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