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