Mercurial > hg > early-roguelike
comparison arogue5/maze.c @ 63:0ed67132cf10
Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Thu, 09 Aug 2012 22:58:48 +0000 |
parents | |
children | 56e748983fa8 |
comparison
equal
deleted
inserted
replaced
62:0ef99244acb8 | 63:0ed67132cf10 |
---|---|
1 /* | |
2 * maze | |
3 * | |
4 * Advanced Rogue | |
5 * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T | |
6 * All rights reserved. | |
7 * | |
8 * Based on "Super-Rogue" | |
9 * Copyright (C) 1984 Robert D. Kindelberger | |
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 | |
24 struct bordercells { | |
25 char num_pos; /* number of frontier cells next to you */ | |
26 struct cell conn[4]; /* the y,x position of above cell */ | |
27 } border_cells; | |
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(10) + 1); /* 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) < 10) { /* 10% for treasure maze */ | |
120 treas = TRUE; | |
121 least = 6; | |
122 debug("treasure maze"); | |
123 } | |
124 else { /* normal maze level */ | |
125 least = 1; | |
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 = 0, xcheck = 0, absy, absx, see_radius; | |
243 register bool row; | |
244 char ch; /* What we are standing on (or near) */ | |
245 | |
246 /* Get the absolute value of y and x differences */ | |
247 absy = hero.y - y; | |
248 absx = hero.x - x; | |
249 if (absy < 0) absy = -absy; | |
250 if (absx < 0) absx = -absx; | |
251 | |
252 /* If we are standing in a wall, we can see a bit more */ | |
253 switch (ch = CCHAR( winat(hero.y, hero.x) )) { | |
254 case '|': | |
255 case '-': | |
256 case WALL: | |
257 case SECRETDOOR: | |
258 case DOOR: | |
259 see_radius = 2; | |
260 otherwise: | |
261 see_radius = 1; | |
262 } | |
263 | |
264 /* Must be within one or two rows or columns */ | |
265 if (absy > see_radius && absx > see_radius) return(FALSE); | |
266 | |
267 if (absx > see_radius) { /* Go along row */ | |
268 start = hero.x; | |
269 goal = x; | |
270 ycheck = hero.y; | |
271 row = TRUE; | |
272 } | |
273 else { /* Go along column */ | |
274 start = hero.y; | |
275 goal = y; | |
276 xcheck = hero.x; | |
277 row = FALSE; | |
278 } | |
279 | |
280 if (start <= goal) delta = 1; | |
281 else delta = -1; | |
282 | |
283 /* Start one past where we are standing */ | |
284 if (start != goal) start += delta; | |
285 | |
286 /* If we are in a wall, we want to look in the area outside the wall */ | |
287 if (see_radius > 1) { | |
288 if (row) { | |
289 /* See if above us it okay first */ | |
290 switch (winat(ycheck, start)) { | |
291 case '|': | |
292 case '-': | |
293 case WALL: | |
294 case DOOR: | |
295 case SECRETDOOR: | |
296 /* No good, try one up */ | |
297 if (y > hero.y) ycheck++; | |
298 else ycheck--; | |
299 otherwise: | |
300 see_radius = 1; /* Just look straight over the row */ | |
301 } | |
302 } | |
303 else { | |
304 /* See if above us it okay first */ | |
305 switch (winat(start, xcheck)) { | |
306 case '|': | |
307 case '-': | |
308 case WALL: | |
309 case DOOR: | |
310 case SECRETDOOR: | |
311 /* No good, try one over */ | |
312 if (x > hero.x) xcheck++; | |
313 else xcheck--; | |
314 otherwise: | |
315 see_radius = 1; /* Just look straight up the column */ | |
316 } | |
317 } | |
318 } | |
319 | |
320 /* Check boundary again */ | |
321 if (absy > see_radius && absx > see_radius) return(FALSE); | |
322 | |
323 while (start != goal) { | |
324 if (row) xcheck = start; | |
325 else ycheck = start; | |
326 switch (winat(ycheck, xcheck)) { | |
327 case '|': | |
328 case '-': | |
329 case WALL: | |
330 case DOOR: | |
331 case SECRETDOOR: | |
332 return(FALSE); | |
333 } | |
334 start += delta; | |
335 } | |
336 return(TRUE); | |
337 } | |
338 | |
339 | |
340 /* | |
341 * moffset: | |
342 * Calculate memory address for bits | |
343 */ | |
344 char * | |
345 moffset(y, x) | |
346 int y, x; | |
347 { | |
348 | |
349 return (bits + (y * (COLS - 1)) + x); | |
350 } | |
351 | |
352 | |
353 | |
354 | |
355 /* | |
356 * rmwall: | |
357 * Removes appropriate walls from the maze | |
358 */ | |
359 rmwall(newy, newx, oldy, oldx) | |
360 int newy, newx, oldy, oldx; | |
361 { | |
362 reg int xdif,ydif; | |
363 | |
364 xdif = newx - oldx; | |
365 ydif = newy - oldy; | |
366 | |
367 *moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE; | |
368 findcells(newy, newx); | |
369 } |