Mercurial > hg > early-roguelike
comparison arogue7/maze.c @ 125:adfa37e67084
Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Fri, 08 May 2015 15:24:40 -0400 |
| parents | |
| children | f9ef86cf22b2 |
comparison
equal
deleted
inserted
replaced
| 124:d10fc4a065ac | 125:adfa37e67084 |
|---|---|
| 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 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 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(5) + 5); /* 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) < 40) { /* treasure type maze */ | |
| 120 treas = TRUE; | |
| 121 least = 10; | |
| 122 debug("treasure maze"); | |
| 123 } | |
| 124 else { /* normal maze level */ | |
| 125 least = 5; | |
| 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, xcheck, absy, absx, see_radius; | |
| 243 register bool row; | |
| 244 | |
| 245 /* Get the absolute value of y and x differences */ | |
| 246 absy = hero.y - y; | |
| 247 absx = hero.x - x; | |
| 248 if (absy < 0) absy = -absy; | |
| 249 if (absx < 0) absx = -absx; | |
| 250 | |
| 251 /* If we are standing in a wall, we can see a bit more */ | |
| 252 switch (winat(hero.y, hero.x)) { | |
| 253 case '|': | |
| 254 case '-': | |
| 255 case WALL: | |
| 256 case SECRETDOOR: | |
| 257 case DOOR: | |
| 258 see_radius = 2; | |
| 259 otherwise: | |
| 260 see_radius = 1; | |
| 261 } | |
| 262 | |
| 263 /* Must be within one or two rows or columns */ | |
| 264 if (absy > see_radius && absx > see_radius) return(FALSE); | |
| 265 | |
| 266 if (absx > see_radius) { /* Go along row */ | |
| 267 start = hero.x; | |
| 268 goal = x; | |
| 269 ycheck = hero.y; | |
| 270 row = TRUE; | |
| 271 } | |
| 272 else { /* Go along column */ | |
| 273 start = hero.y; | |
| 274 goal = y; | |
| 275 xcheck = hero.x; | |
| 276 row = FALSE; | |
| 277 } | |
| 278 | |
| 279 if (start <= goal) delta = 1; | |
| 280 else delta = -1; | |
| 281 | |
| 282 /* Start one past where we are standing */ | |
| 283 if (start != goal) start += delta; | |
| 284 | |
| 285 /* If we are in a wall, we want to look in the area outside the wall */ | |
| 286 if (see_radius > 1) { | |
| 287 if (row) { | |
| 288 /* See if above us it okay first */ | |
| 289 switch (winat(ycheck, start)) { | |
| 290 case '|': | |
| 291 case '-': | |
| 292 case WALL: | |
| 293 case DOOR: | |
| 294 case SECRETDOOR: | |
| 295 /* No good, try one up */ | |
| 296 if (y > hero.y) ycheck++; | |
| 297 else ycheck--; | |
| 298 otherwise: | |
| 299 see_radius = 1; /* Just look straight over the row */ | |
| 300 } | |
| 301 } | |
| 302 else { | |
| 303 /* See if above us it okay first */ | |
| 304 switch (winat(start, xcheck)) { | |
| 305 case '|': | |
| 306 case '-': | |
| 307 case WALL: | |
| 308 case DOOR: | |
| 309 case SECRETDOOR: | |
| 310 /* No good, try one over */ | |
| 311 if (x > hero.x) xcheck++; | |
| 312 else xcheck--; | |
| 313 otherwise: | |
| 314 see_radius = 1; /* Just look straight up the column */ | |
| 315 } | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 /* Check boundary again */ | |
| 320 if (absy > see_radius && absx > see_radius) return(FALSE); | |
| 321 | |
| 322 while (start != goal) { | |
| 323 if (row) xcheck = start; | |
| 324 else ycheck = start; | |
| 325 switch (winat(ycheck, xcheck)) { | |
| 326 case '|': | |
| 327 case '-': | |
| 328 case WALL: | |
| 329 case DOOR: | |
| 330 case SECRETDOOR: | |
| 331 return(FALSE); | |
| 332 } | |
| 333 start += delta; | |
| 334 } | |
| 335 return(TRUE); | |
| 336 } | |
| 337 | |
| 338 | |
| 339 /* | |
| 340 * moffset: | |
| 341 * Calculate memory address for bits | |
| 342 */ | |
| 343 char * | |
| 344 moffset(y, x) | |
| 345 int y, x; | |
| 346 { | |
| 347 | |
| 348 return (bits + (y * (cols - 1)) + x); | |
| 349 } | |
| 350 | |
| 351 | |
| 352 | |
| 353 | |
| 354 /* | |
| 355 * rmwall: | |
| 356 * Removes appropriate walls from the maze | |
| 357 */ | |
| 358 rmwall(newy, newx, oldy, oldx) | |
| 359 int newy, newx, oldy, oldx; | |
| 360 { | |
| 361 reg int xdif,ydif; | |
| 362 | |
| 363 xdif = newx - oldx; | |
| 364 ydif = newy - oldy; | |
| 365 | |
| 366 *moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE; | |
| 367 findcells(newy, newx); | |
| 368 } |
