Mercurial > hg > early-roguelike
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 } |
