Merge branch 'vendor/BMAKE'
[dragonfly.git] / games / hunt / huntd / makemaze.c
1 /*-
2  * Copyright (c) 1983-2003, Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University of California, San Francisco nor
15  *    the names of its contributors may be used to endorse or promote
16  *    products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $OpenBSD: makemaze.c,v 1.6 2003/06/11 08:45:33 pjanzen Exp $
32  * $NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $
33  * $DragonFly: src/games/hunt/huntd/makemaze.c,v 1.2 2008/09/04 16:12:51 swildner Exp $
34  */
35
36 #include <string.h>
37
38 #include "hunt.h"
39 #include "server.h"
40 #include "conf.h"
41
42 # define        ISCLEAR(y,x)    (Maze[y][x] == SPACE)
43 # define        ODD(n)          ((n) & 01)
44
45 static  void    dig_maze(int, int);
46 static  void    remap(void);
47
48 void
49 makemaze(void)
50 {
51         char    *sp;
52         int     y, x;
53
54         /*
55          * fill maze with walls
56          */
57         sp = &Maze[0][0];
58         while (sp < &Maze[HEIGHT - 1][WIDTH])
59                 *sp++ = DOOR;
60
61         x = rand_num(WIDTH / 2) * 2 + 1;
62         y = rand_num(HEIGHT / 2) * 2 + 1;
63         dig_maze(x, y);
64         remap();
65 }
66
67 # define        NPERM   24
68 # define        NDIR    4
69
70 int     dirs[NPERM][NDIR] = {
71                 {0,1,2,3},      {3,0,1,2},      {0,2,3,1},      {0,3,2,1},
72                 {1,0,2,3},      {2,3,0,1},      {0,2,1,3},      {2,3,1,0},
73                 {1,0,3,2},      {1,2,0,3},      {3,1,2,0},      {2,0,3,1},
74                 {1,3,0,2},      {0,3,1,2},      {1,3,2,0},      {2,0,1,3},
75                 {0,1,3,2},      {3,1,0,2},      {2,1,0,3},      {1,2,3,0},
76                 {2,1,3,0},      {3,0,2,1},      {3,2,0,1},      {3,2,1,0}
77         };
78
79 int     incr[NDIR][2] = {
80                 {0, 1}, {1, 0}, {0, -1}, {-1, 0}
81         };
82
83 static void
84 dig_maze(int x, int y)
85 {
86         int     tx, ty;
87         int     i, j;
88         int     order[4];
89 #define MNORTH  0x1
90 #define MSOUTH  0x2
91 #define MEAST   0x4
92 #define MWEST   0x8
93
94         tx = ty = 0;
95         Maze[y][x] = SPACE;
96         order[0] = MNORTH;
97         for (i = 1; i < 4; i++) {
98                 j = rand_num(i + 1);
99                 order[i] = order[j];
100                 order[j] = 0x1 << i;
101         }
102         for (i = 0; i < 4; i++) {
103                 switch (order[i]) {
104                   case MNORTH:
105                         tx = x;
106                         ty = y - 2;
107                         break;
108                   case MSOUTH:
109                         tx = x;
110                         ty = y + 2;
111                         break;
112                   case MEAST:
113                         tx = x + 2;
114                         ty = y;
115                         break;
116                   case MWEST:
117                         tx = x - 2;
118                         ty = y;
119                         break;
120                 }
121                 if (tx < 0 || ty < 0 || tx >= WIDTH || ty >= HEIGHT)
122                         continue;
123                 if (Maze[ty][tx] == SPACE)
124                         continue;
125                 Maze[(y + ty) / 2][(x + tx) / 2] = SPACE;
126                 dig_maze(tx, ty);
127         }
128 }
129
130 static void
131 remap(void)
132 {
133         int     y, x;
134         char    *sp;
135         int     stat;
136
137         for (y = 0; y < HEIGHT; y++)
138                 for (x = 0; x < WIDTH; x++) {
139                         sp = &Maze[y][x];
140                         if (*sp == SPACE)
141                                 continue;
142                         /* Find occupied adjacent cells. */
143                         stat = 0;
144                         if (y - 1 >= 0 && Maze[y - 1][x] != SPACE)
145                                 stat |= NORTH;
146                         if (y + 1 < HEIGHT && Maze[y + 1][x] != SPACE)
147                                 stat |= SOUTH;
148                         if (x + 1 < WIDTH && Maze[y][x + 1] != SPACE)
149                                 stat |= EAST;
150                         if (x - 1 >= 0 && Maze[y][x - 1] != SPACE)
151                                 stat |= WEST;
152                         switch (stat) {
153                           case WEST | EAST:
154                           case EAST:
155                           case WEST:
156                                 *sp = WALL1;                       /* - */
157                                 break;
158                           case NORTH | SOUTH:
159                           case NORTH:
160                           case SOUTH:
161                                 *sp = WALL2;                       /* | */
162                                 break;
163                           case 0:
164                                 if (conf_random)
165                                         *sp = DOOR;
166                                 if (conf_reflect)
167                                         *sp = rand_num(2) ? WALL4 : WALL5;
168                                 break;
169                           default:
170                                 *sp = WALL3;                       /* + */
171                                 break;
172                         }
173                 }
174         memcpy(Orig_maze, Maze, sizeof Orig_maze);
175 }