Annotation of early-roguelike/arogue7/maze.c, Revision 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