Mercurial > hg > early-roguelike
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: | |