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 }