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