comparison xrogue/maze.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children f54901b9c39b
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
1 /*
2 maze.c - functions for dealing with mazes
3
4 XRogue: Expeditions into the Dungeons of Doom
5 Copyright (C) 1991 Robert Pietkivitch
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
10 All rights reserved.
11
12 See the file LICENSE.TXT for full copyright and licensing information.
13 */
14
15 #include <stdlib.h>
16 #include <curses.h>
17 #include "rogue.h"
18
19 struct cell {
20 char y_pos;
21 char x_pos;
22 };
23 struct b_cellscells {
24 char num_pos; /* number of frontier cells next to you */
25 struct cell conn[4]; /* the y,x position of above cell */
26 } b_cells;
27
28 static char *maze_frontier, *maze_bits;
29 static int maze_lines, maze_cols;
30 static char *moffset(), *foffset();
31 static int rmwall(),findcells(),crankout(),draw_maze();
32
33 /*
34 * crankout:
35 * Does actual drawing of maze to window
36 */
37
38 static
39 crankout()
40 {
41 reg int x, y;
42
43 for (y = 0; y < lines - 3; y++) {
44 move(y + 1, 0);
45 for (x = 0; x < cols - 1; x++) {
46 if (*moffset(y, x)) { /* here is a wall */
47 if(y==0 || y==lines-4) /* top or bottom line */
48 addch(HORZWALL);
49 else if(x==0 || x==cols-2) /* left | right side */
50 addch(VERTWALL);
51 else if (y % 2 == 0 && x % 2 == 0) {
52 if(*moffset(y, x-1) || *moffset(y, x+1))
53 addch(HORZWALL);
54 else
55 addch(VERTWALL);
56 }
57 else if (y % 2 == 0)
58 addch(HORZWALL);
59 else
60 addch(VERTWALL);
61 }
62 else
63 addch(FLOOR);
64 }
65 }
66 }
67
68 /*
69 * domaze:
70 * Draw the maze on this level.
71 */
72
73 do_maze()
74 {
75 reg int least;
76 reg struct room *rp;
77 reg struct linked_list *item;
78 reg struct object *obj;
79 int cnt;
80 bool treas;
81 coord tp;
82
83 for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
84 rp->r_flags = ISGONE; /* kill all rooms */
85 rp->r_fires = NULL; /* no fires */
86 }
87 rp = &rooms[0]; /* point to only room */
88 rp->r_flags = ISDARK; /* mazes always dark */
89 rp->r_pos.x = 0; /* room fills whole screen */
90 rp->r_pos.y = 1;
91 rp->r_max.x = cols - 1;
92 rp->r_max.y = lines - 3;
93 draw_maze(); /* put maze into window */
94 /*
95 * add some gold to make it worth looking for
96 */
97 item = spec_item(GOLD, NULL, NULL, NULL);
98 obj = OBJPTR(item);
99 obj->o_count *= (rnd(50) + 50); /* add in one large hunk */
100 attach(lvl_obj, item);
101 cnt = 0;
102 do {
103 rnd_pos(rp, &tp);
104 } until (mvinch(tp.y, tp.x) == FLOOR || cnt++ > 2500);
105 mvaddch(tp.y, tp.x, GOLD);
106 obj->o_pos = tp;
107 /*
108 * add in some food to make sure he has enough
109 */
110 item = spec_item(FOOD, NULL, NULL, NULL);
111 obj = OBJPTR(item);
112 attach(lvl_obj, item);
113 do {
114 rnd_pos(rp, &tp);
115 } until (mvinch(tp.y, tp.x) == FLOOR || cnt++ > 2500);
116 mvaddch(tp.y, tp.x, FOOD);
117 obj->o_pos = tp;
118
119 /* it doesn't mater if it's a treasure maze or a normal maze,
120 * more than enough monsters will be genned.
121 */
122 least = rnd(11)+5;
123 if (least < 6) {
124 least = 7;
125 treas = FALSE;
126 }
127 else treas = TRUE;
128 genmonsters(least, treas);
129
130 /* sometimes they're real angry */
131 if (rnd(100) < 65) {
132 /* protect the good charactors */
133 if (player.t_ctype == C_PALADIN ||
134 player.t_ctype == C_RANGER || player.t_ctype == C_MONK) {
135 aggravate(TRUE, FALSE);
136 }
137 else {
138 aggravate(TRUE, TRUE);
139 }
140 }
141 }
142
143 /*
144 * draw_maze:
145 * Generate and draw the maze on the screen
146 */
147
148 static
149 draw_maze()
150 {
151 reg int i, j, more;
152 reg char *ptr;
153
154 maze_lines = (lines - 3) / 2;
155 maze_cols = (cols - 1) / 2;
156 maze_bits = ALLOC((lines - 3) * (cols - 1));
157 maze_frontier = ALLOC(maze_lines * maze_cols);
158 ptr = maze_frontier;
159 while (ptr < (maze_frontier + (maze_lines * maze_cols)))
160 *ptr++ = TRUE;
161 for (i = 0; i < lines - 3; i++) {
162 for (j = 0; j < cols - 1; j++) {
163 if (i % 2 == 1 && j % 2 == 1)
164 *moffset(i, j) = FALSE; /* floor */
165 else
166 *moffset(i, j) = TRUE; /* wall */
167 }
168 }
169 for (i = 0; i < maze_lines; i++) {
170 for (j = 0; j < maze_cols; j++) {
171 do
172 more = findcells(i,j);
173 while(more != 0);
174 }
175 }
176 crankout();
177 FREE(maze_frontier);
178 FREE(maze_bits);
179 }
180
181 /*
182 * findcells:
183 * Figure out cells to open up
184 */
185
186 static findcells(y,x)
187 reg int x, y;
188 {
189 reg int rtpos, i;
190
191 *foffset(y, x) = FALSE;
192 b_cells.num_pos = 0;
193 if (y < maze_lines - 1) { /* look below */
194 if (*foffset(y + 1, x)) {
195 b_cells.conn[b_cells.num_pos].y_pos = y + 1;
196 b_cells.conn[b_cells.num_pos].x_pos = x;
197 b_cells.num_pos += 1;
198 }
199 }
200 if (y > 0) { /* look above */
201 if (*foffset(y - 1, x)) {
202 b_cells.conn[b_cells.num_pos].y_pos = y - 1;
203 b_cells.conn[b_cells.num_pos].x_pos = x;
204 b_cells.num_pos += 1;
205
206 }
207 }
208 if (x < maze_cols - 1) { /* look right */
209 if (*foffset(y, x + 1)) {
210 b_cells.conn[b_cells.num_pos].y_pos = y;
211 b_cells.conn[b_cells.num_pos].x_pos = x + 1;
212 b_cells.num_pos += 1;
213 }
214 }
215 if (x > 0) { /* look left */
216 if (*foffset(y, x - 1)) {
217 b_cells.conn[b_cells.num_pos].y_pos = y;
218 b_cells.conn[b_cells.num_pos].x_pos = x - 1;
219 b_cells.num_pos += 1;
220
221 }
222 }
223 if (b_cells.num_pos == 0) /* no neighbors available */
224 return 0;
225 else {
226 i = rnd(b_cells.num_pos);
227 rtpos = b_cells.num_pos - 1;
228 rmwall(b_cells.conn[i].y_pos, b_cells.conn[i].x_pos, y, x);
229 return rtpos;
230 }
231 }
232
233 /*
234 * foffset:
235 * Calculate memory address for frontier
236 */
237
238 static char *
239 foffset(y, x)
240 int y, x;
241 {
242
243 return (maze_frontier + (y * maze_cols) + x);
244 }
245
246
247 /*
248 * Maze_view:
249 * Returns true if the player can see the specified location within
250 * the confines of a maze (within one column or row)
251 */
252
253 bool
254 maze_view(y, x)
255 int y, x;
256 {
257 register int start, goal, delta, ycheck = 0, xcheck = 0, absy, absx, see_radius;
258 register bool row;
259
260 /* Get the absolute value of y and x differences */
261 absy = hero.y - y;
262 absx = hero.x - x;
263 if (absy < 0) absy = -absy;
264 if (absx < 0) absx = -absx;
265
266 /* If we are standing in a wall, we can see a bit more */
267 switch (winat(hero.y, hero.x)) {
268 case VERTWALL:
269 case HORZWALL:
270 case WALL:
271 case SECRETDOOR:
272 case DOOR:
273 see_radius = 2;
274 otherwise:
275 see_radius = 1;
276 }
277
278 /* Must be within one or two rows or columns */
279 if (absy > see_radius && absx > see_radius) return(FALSE);
280
281 if (absx > see_radius) { /* Go along row */
282 start = hero.x;
283 goal = x;
284 ycheck = hero.y;
285 row = TRUE;
286 }
287 else { /* Go along column */
288 start = hero.y;
289 goal = y;
290 xcheck = hero.x;
291 row = FALSE;
292 }
293
294 if (start <= goal) delta = 1;
295 else delta = -1;
296
297 /* Start one past where we are standing */
298 if (start != goal) start += delta;
299
300 /* If we are in a wall, we want to look in the area outside the wall */
301 if (see_radius > 1) {
302 if (row) {
303 /* See if above us it okay first */
304 switch (winat(ycheck, start)) {
305 case VERTWALL:
306 case HORZWALL:
307 case WALL:
308 case DOOR:
309 case SECRETDOOR:
310 /* No good, try one up */
311 if (y > hero.y) ycheck++;
312 else ycheck--;
313 otherwise:
314 see_radius = 1; /* Just look straight over the row */
315 }
316 }
317 else {
318 /* See if above us it okay first */
319 switch (winat(start, xcheck)) {
320 case VERTWALL:
321 case HORZWALL:
322 case WALL:
323 case DOOR:
324 case SECRETDOOR:
325 /* No good, try one over */
326 if (x > hero.x) xcheck++;
327 else xcheck--;
328 otherwise:
329 see_radius = 1; /* Just look straight up the column */
330 }
331 }
332 }
333
334 /* Check boundary again */
335 if (absy > see_radius && absx > see_radius) return(FALSE);
336
337 while (start != goal) {
338 if (row) xcheck = start;
339 else ycheck = start;
340
341 if (xcheck < 0 || ycheck < 0)
342 return FALSE;
343 switch (winat(ycheck, xcheck)) {
344 case VERTWALL:
345 case HORZWALL:
346 case WALL:
347 case DOOR:
348 case SECRETDOOR:
349 return(FALSE);
350 }
351 start += delta;
352 }
353 return(TRUE);
354 }
355
356
357 /*
358 * moffset:
359 * Calculate memory address for bits
360 */
361
362 static char *
363 moffset(y, x)
364 int y, x;
365 {
366 return (maze_bits + (y * (cols - 1)) + x);
367 }
368
369 /*
370 * rmwall:
371 * Removes appropriate walls from the maze
372 */
373 static
374 rmwall(newy, newx, oldy, oldx)
375 int newy, newx, oldy, oldx;
376 {
377 reg int xdif,ydif;
378
379 xdif = newx - oldx;
380 ydif = newy - oldy;
381
382 *moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
383 findcells(newy, newx);
384 }
385