Annotation of early-roguelike/arogue5/maze.c, Revision 1.1.1.1
1.1 rubenllo 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: unsigned 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:
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(10) + 1); /* 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) < 10) { /* 10% for treasure maze */
126: treas = TRUE;
127: least = 6;
128: debug("treasure maze");
129: }
130: else { /* normal maze level */
131: least = 1;
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 = 0, xcheck = 0, absy, absx, see_radius;
248: register bool row;
249: char ch; /* What we are standing on (or near) */
250:
251: /* Get the absolute value of y and x differences */
252: absy = hero.y - y;
253: absx = hero.x - x;
254: if (absy < 0) absy = -absy;
255: if (absx < 0) absx = -absx;
256:
257: /* If we are standing in a wall, we can see a bit more */
258: switch (ch = CCHAR( winat(hero.y, hero.x) )) {
259: case '|':
260: case '-':
261: case WALL:
262: case SECRETDOOR:
263: case DOOR:
264: see_radius = 2;
265: otherwise:
266: see_radius = 1;
267: }
268:
269: /* Must be within one or two rows or columns */
270: if (absy > see_radius && absx > see_radius) return(FALSE);
271:
272: if (absx > see_radius) { /* Go along row */
273: start = hero.x;
274: goal = x;
275: ycheck = hero.y;
276: row = TRUE;
277: }
278: else { /* Go along column */
279: start = hero.y;
280: goal = y;
281: xcheck = hero.x;
282: row = FALSE;
283: }
284:
285: if (start <= goal) delta = 1;
286: else delta = -1;
287:
288: /* Start one past where we are standing */
289: if (start != goal) start += delta;
290:
291: /* If we are in a wall, we want to look in the area outside the wall */
292: if (see_radius > 1) {
293: if (row) {
294: /* See if above us it okay first */
295: switch (winat(ycheck, start)) {
296: case '|':
297: case '-':
298: case WALL:
299: case DOOR:
300: case SECRETDOOR:
301: /* No good, try one up */
302: if (y > hero.y) ycheck++;
303: else ycheck--;
304: otherwise:
305: see_radius = 1; /* Just look straight over the row */
306: }
307: }
308: else {
309: /* See if above us it okay first */
310: switch (winat(start, xcheck)) {
311: case '|':
312: case '-':
313: case WALL:
314: case DOOR:
315: case SECRETDOOR:
316: /* No good, try one over */
317: if (x > hero.x) xcheck++;
318: else xcheck--;
319: otherwise:
320: see_radius = 1; /* Just look straight up the column */
321: }
322: }
323: }
324:
325: /* Check boundary again */
326: if (absy > see_radius && absx > see_radius) return(FALSE);
327:
328: while (start != goal) {
329: if (row) xcheck = start;
330: else ycheck = start;
331: switch (winat(ycheck, xcheck)) {
332: case '|':
333: case '-':
334: case WALL:
335: case DOOR:
336: case SECRETDOOR:
337: return(FALSE);
338: }
339: start += delta;
340: }
341: return(TRUE);
342: }
343:
344:
345: /*
346: * moffset:
347: * Calculate memory address for bits
348: */
349: char *
350: moffset(int y, int x)
351: {
352:
353: return (bits + (y * (COLS - 1)) + x);
354: }
355:
356:
357:
358:
359: /*
360: * rmwall:
361: * Removes appropriate walls from the maze
362: */
363: void
364: rmwall(int newy, int newx, int oldy, int oldx)
365: {
366: reg int xdif,ydif;
367:
368: xdif = newx - oldx;
369: ydif = newy - oldy;
370:
371: *moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
372: findcells(newy, newx);
373: }
CVSweb