1 1.10 dholland /* $NetBSD: level.c,v 1.10 2008/01/14 03:50:01 dholland Exp $ */ 2 1.3 cgd 3 1.1 cgd /* 4 1.3 cgd * Copyright (c) 1988, 1993 5 1.3 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * This code is derived from software contributed to Berkeley by 8 1.1 cgd * Timothy C. Stoehr. 9 1.1 cgd * 10 1.1 cgd * Redistribution and use in source and binary forms, with or without 11 1.1 cgd * modification, are permitted provided that the following conditions 12 1.1 cgd * are met: 13 1.1 cgd * 1. Redistributions of source code must retain the above copyright 14 1.1 cgd * notice, this list of conditions and the following disclaimer. 15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 cgd * notice, this list of conditions and the following disclaimer in the 17 1.1 cgd * documentation and/or other materials provided with the distribution. 18 1.7 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 cgd * may be used to endorse or promote products derived from this software 20 1.1 cgd * without specific prior written permission. 21 1.1 cgd * 22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 cgd * SUCH DAMAGE. 33 1.1 cgd */ 34 1.1 cgd 35 1.4 lukem #include <sys/cdefs.h> 36 1.1 cgd #ifndef lint 37 1.3 cgd #if 0 38 1.3 cgd static char sccsid[] = "@(#)level.c 8.1 (Berkeley) 5/31/93"; 39 1.3 cgd #else 40 1.10 dholland __RCSID("$NetBSD: level.c,v 1.10 2008/01/14 03:50:01 dholland Exp $"); 41 1.3 cgd #endif 42 1.1 cgd #endif /* not lint */ 43 1.1 cgd 44 1.1 cgd /* 45 1.1 cgd * level.c 46 1.1 cgd * 47 1.1 cgd * This source herein may be modified and/or distributed by anybody who 48 1.1 cgd * so desires, with the following restrictions: 49 1.1 cgd * 1.) No portion of this notice shall be removed. 50 1.1 cgd * 2.) Credit shall not be taken for the creation of this source. 51 1.1 cgd * 3.) This code is not to be traded, sold, or used for personal 52 1.1 cgd * gain or profit. 53 1.1 cgd * 54 1.1 cgd */ 55 1.1 cgd 56 1.1 cgd #include "rogue.h" 57 1.1 cgd 58 1.10 dholland #define SWAP(x,y) (t = (x), (x) = (y), (y) = t) 59 1.10 dholland 60 1.10 dholland static void add_mazes(void); 61 1.10 dholland static int connect_rooms(short, short); 62 1.10 dholland static void draw_simple_passage(short, short, short, short, short); 63 1.10 dholland static void fill_it(int, boolean); 64 1.10 dholland static void fill_out_level(void); 65 1.10 dholland static int get_exp_level(long); 66 1.10 dholland static void hide_boxed_passage(short, short, short, short, short); 67 1.10 dholland static void make_maze(short, short, short, short, short, short); 68 1.10 dholland static void make_room(short, short, short, short); 69 1.10 dholland static boolean mask_room(short, short *, short *, unsigned short); 70 1.10 dholland static void mix_random_rooms(void); 71 1.10 dholland static void put_door(room *, short, short *, short *); 72 1.10 dholland static void recursive_deadend(short, const short *, short, short); 73 1.10 dholland static int same_col(int, int); 74 1.10 dholland static int same_row(int, int); 75 1.1 cgd 76 1.1 cgd short cur_level = 0; 77 1.1 cgd short max_level = 1; 78 1.1 cgd short cur_room; 79 1.10 dholland const char *new_level_message = NULL; 80 1.1 cgd short party_room = NO_ROOM; 81 1.10 dholland 82 1.10 dholland static short r_de; 83 1.1 cgd 84 1.5 hubertf const long level_points[MAX_EXP_LEVEL] = { 85 1.1 cgd 10L, 86 1.1 cgd 20L, 87 1.1 cgd 40L, 88 1.1 cgd 80L, 89 1.1 cgd 160L, 90 1.1 cgd 320L, 91 1.1 cgd 640L, 92 1.1 cgd 1300L, 93 1.1 cgd 2600L, 94 1.1 cgd 5200L, 95 1.1 cgd 10000L, 96 1.1 cgd 20000L, 97 1.1 cgd 40000L, 98 1.1 cgd 80000L, 99 1.1 cgd 160000L, 100 1.1 cgd 320000L, 101 1.1 cgd 1000000L, 102 1.1 cgd 3333333L, 103 1.1 cgd 6666666L, 104 1.1 cgd MAX_EXP, 105 1.1 cgd 99900000L 106 1.1 cgd }; 107 1.1 cgd 108 1.10 dholland static short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8}; 109 1.1 cgd 110 1.4 lukem void 111 1.10 dholland make_level(void) 112 1.1 cgd { 113 1.1 cgd short i, j; 114 1.1 cgd short must_1, must_2, must_3; 115 1.1 cgd boolean big_room; 116 1.1 cgd 117 1.4 lukem must_2 = must_3 = 0; 118 1.1 cgd if (cur_level < LAST_DUNGEON) { 119 1.1 cgd cur_level++; 120 1.1 cgd } 121 1.1 cgd if (cur_level > max_level) { 122 1.1 cgd max_level = cur_level; 123 1.1 cgd } 124 1.1 cgd must_1 = get_rand(0, 5); 125 1.1 cgd 126 1.1 cgd switch(must_1) { 127 1.1 cgd case 0: 128 1.1 cgd must_1 = 0; 129 1.1 cgd must_2 = 1; 130 1.1 cgd must_3 = 2; 131 1.1 cgd break; 132 1.1 cgd case 1: 133 1.1 cgd must_1 = 3; 134 1.1 cgd must_2 = 4; 135 1.1 cgd must_3 = 5; 136 1.1 cgd break; 137 1.1 cgd case 2: 138 1.1 cgd must_1 = 6; 139 1.1 cgd must_2 = 7; 140 1.1 cgd must_3 = 8; 141 1.1 cgd break; 142 1.1 cgd case 3: 143 1.1 cgd must_1 = 0; 144 1.1 cgd must_2 = 3; 145 1.1 cgd must_3 = 6; 146 1.1 cgd break; 147 1.1 cgd case 4: 148 1.1 cgd must_1 = 1; 149 1.1 cgd must_2 = 4; 150 1.1 cgd must_3 = 7; 151 1.1 cgd break; 152 1.1 cgd case 5: 153 1.1 cgd must_1 = 2; 154 1.1 cgd must_2 = 5; 155 1.1 cgd must_3 = 8; 156 1.1 cgd break; 157 1.1 cgd } 158 1.1 cgd if (rand_percent(8)) { 159 1.1 cgd party_room = 0; 160 1.1 cgd } 161 1.1 cgd big_room = ((party_room != NO_ROOM) && rand_percent(1)); 162 1.1 cgd if (big_room) { 163 1.1 cgd make_room(BIG_ROOM, 0, 0, 0); 164 1.1 cgd } else { 165 1.1 cgd for (i = 0; i < MAXROOMS; i++) { 166 1.1 cgd make_room(i, must_1, must_2, must_3); 167 1.1 cgd } 168 1.1 cgd } 169 1.1 cgd if (!big_room) { 170 1.1 cgd add_mazes(); 171 1.1 cgd 172 1.1 cgd mix_random_rooms(); 173 1.1 cgd 174 1.1 cgd for (j = 0; j < MAXROOMS; j++) { 175 1.1 cgd 176 1.1 cgd i = random_rooms[j]; 177 1.1 cgd 178 1.1 cgd if (i < (MAXROOMS-1)) { 179 1.9 dholland (void)connect_rooms(i, i+1); 180 1.1 cgd } 181 1.1 cgd if (i < (MAXROOMS-3)) { 182 1.9 dholland (void)connect_rooms(i, i+3); 183 1.1 cgd } 184 1.1 cgd if (i < (MAXROOMS-2)) { 185 1.1 cgd if (rooms[i+1].is_room & R_NOTHING) { 186 1.1 cgd if (connect_rooms(i, i+2)) { 187 1.1 cgd rooms[i+1].is_room = R_CROSS; 188 1.1 cgd } 189 1.1 cgd } 190 1.1 cgd } 191 1.1 cgd if (i < (MAXROOMS-6)) { 192 1.1 cgd if (rooms[i+3].is_room & R_NOTHING) { 193 1.1 cgd if (connect_rooms(i, i+6)) { 194 1.1 cgd rooms[i+3].is_room = R_CROSS; 195 1.1 cgd } 196 1.1 cgd } 197 1.1 cgd } 198 1.1 cgd if (is_all_connected()) { 199 1.1 cgd break; 200 1.1 cgd } 201 1.1 cgd } 202 1.1 cgd fill_out_level(); 203 1.1 cgd } 204 1.1 cgd if (!has_amulet() && (cur_level >= AMULET_LEVEL)) { 205 1.1 cgd put_amulet(); 206 1.1 cgd } 207 1.1 cgd } 208 1.1 cgd 209 1.10 dholland static void 210 1.10 dholland make_room(short rn, short r1, short r2, short r3) 211 1.1 cgd { 212 1.1 cgd short left_col, right_col, top_row, bottom_row; 213 1.1 cgd short width, height; 214 1.1 cgd short row_offset, col_offset; 215 1.1 cgd short i, j, ch; 216 1.1 cgd 217 1.4 lukem left_col = right_col = top_row = bottom_row = 0; 218 1.1 cgd switch(rn) { 219 1.1 cgd case 0: 220 1.1 cgd left_col = 0; 221 1.1 cgd right_col = COL1-1; 222 1.1 cgd top_row = MIN_ROW; 223 1.1 cgd bottom_row = ROW1-1; 224 1.1 cgd break; 225 1.1 cgd case 1: 226 1.1 cgd left_col = COL1+1; 227 1.1 cgd right_col = COL2-1; 228 1.1 cgd top_row = MIN_ROW; 229 1.1 cgd bottom_row = ROW1-1; 230 1.1 cgd break; 231 1.1 cgd case 2: 232 1.1 cgd left_col = COL2+1; 233 1.1 cgd right_col = DCOLS-1; 234 1.1 cgd top_row = MIN_ROW; 235 1.1 cgd bottom_row = ROW1-1; 236 1.1 cgd break; 237 1.1 cgd case 3: 238 1.1 cgd left_col = 0; 239 1.1 cgd right_col = COL1-1; 240 1.1 cgd top_row = ROW1+1; 241 1.1 cgd bottom_row = ROW2-1; 242 1.1 cgd break; 243 1.1 cgd case 4: 244 1.1 cgd left_col = COL1+1; 245 1.1 cgd right_col = COL2-1; 246 1.1 cgd top_row = ROW1+1; 247 1.1 cgd bottom_row = ROW2-1; 248 1.1 cgd break; 249 1.1 cgd case 5: 250 1.1 cgd left_col = COL2+1; 251 1.1 cgd right_col = DCOLS-1; 252 1.1 cgd top_row = ROW1+1; 253 1.1 cgd bottom_row = ROW2-1; 254 1.1 cgd break; 255 1.1 cgd case 6: 256 1.1 cgd left_col = 0; 257 1.1 cgd right_col = COL1-1; 258 1.1 cgd top_row = ROW2+1; 259 1.1 cgd bottom_row = DROWS - 2; 260 1.1 cgd break; 261 1.1 cgd case 7: 262 1.1 cgd left_col = COL1+1; 263 1.1 cgd right_col = COL2-1; 264 1.1 cgd top_row = ROW2+1; 265 1.1 cgd bottom_row = DROWS - 2; 266 1.1 cgd break; 267 1.1 cgd case 8: 268 1.1 cgd left_col = COL2+1; 269 1.1 cgd right_col = DCOLS-1; 270 1.1 cgd top_row = ROW2+1; 271 1.1 cgd bottom_row = DROWS - 2; 272 1.1 cgd break; 273 1.1 cgd case BIG_ROOM: 274 1.1 cgd top_row = get_rand(MIN_ROW, MIN_ROW+5); 275 1.1 cgd bottom_row = get_rand(DROWS-7, DROWS-2); 276 1.6 simonb left_col = get_rand(0, 10); 277 1.1 cgd right_col = get_rand(DCOLS-11, DCOLS-1); 278 1.1 cgd rn = 0; 279 1.1 cgd goto B; 280 1.1 cgd } 281 1.1 cgd height = get_rand(4, (bottom_row - top_row + 1)); 282 1.1 cgd width = get_rand(7, (right_col - left_col - 2)); 283 1.1 cgd 284 1.1 cgd row_offset = get_rand(0, ((bottom_row - top_row) - height + 1)); 285 1.1 cgd col_offset = get_rand(0, ((right_col - left_col) - width + 1)); 286 1.1 cgd 287 1.1 cgd top_row += row_offset; 288 1.1 cgd bottom_row = top_row + height - 1; 289 1.1 cgd 290 1.1 cgd left_col += col_offset; 291 1.1 cgd right_col = left_col + width - 1; 292 1.1 cgd 293 1.1 cgd if ((rn != r1) && (rn != r2) && (rn != r3) && rand_percent(40)) { 294 1.1 cgd goto END; 295 1.1 cgd } 296 1.1 cgd B: 297 1.1 cgd rooms[rn].is_room = R_ROOM; 298 1.1 cgd 299 1.1 cgd for (i = top_row; i <= bottom_row; i++) { 300 1.1 cgd for (j = left_col; j <= right_col; j++) { 301 1.1 cgd if ((i == top_row) || (i == bottom_row)) { 302 1.1 cgd ch = HORWALL; 303 1.1 cgd } else if ( ((i != top_row) && (i != bottom_row)) && 304 1.1 cgd ((j == left_col) || (j == right_col))) { 305 1.1 cgd ch = VERTWALL; 306 1.1 cgd } else { 307 1.1 cgd ch = FLOOR; 308 1.1 cgd } 309 1.1 cgd dungeon[i][j] = ch; 310 1.1 cgd } 311 1.1 cgd } 312 1.1 cgd END: 313 1.1 cgd rooms[rn].top_row = top_row; 314 1.1 cgd rooms[rn].bottom_row = bottom_row; 315 1.1 cgd rooms[rn].left_col = left_col; 316 1.1 cgd rooms[rn].right_col = right_col; 317 1.1 cgd } 318 1.1 cgd 319 1.10 dholland static int 320 1.10 dholland connect_rooms(short room1, short room2) 321 1.1 cgd { 322 1.1 cgd short row1, col1, row2, col2, dir; 323 1.1 cgd 324 1.1 cgd if ((!(rooms[room1].is_room & (R_ROOM | R_MAZE))) || 325 1.1 cgd (!(rooms[room2].is_room & (R_ROOM | R_MAZE)))) { 326 1.1 cgd return(0); 327 1.1 cgd } 328 1.1 cgd if (same_row(room1, room2) && 329 1.1 cgd (rooms[room1].left_col > rooms[room2].right_col)) { 330 1.1 cgd put_door(&rooms[room1], LEFT, &row1, &col1); 331 1.1 cgd put_door(&rooms[room2], RIGHT, &row2, &col2); 332 1.1 cgd dir = LEFT; 333 1.1 cgd } else if (same_row(room1, room2) && 334 1.1 cgd (rooms[room2].left_col > rooms[room1].right_col)) { 335 1.1 cgd put_door(&rooms[room1], RIGHT, &row1, &col1); 336 1.1 cgd put_door(&rooms[room2], LEFT, &row2, &col2); 337 1.1 cgd dir = RIGHT; 338 1.1 cgd } else if (same_col(room1, room2) && 339 1.1 cgd (rooms[room1].top_row > rooms[room2].bottom_row)) { 340 1.1 cgd put_door(&rooms[room1], UPWARD, &row1, &col1); 341 1.1 cgd put_door(&rooms[room2], DOWN, &row2, &col2); 342 1.1 cgd dir = UPWARD; 343 1.1 cgd } else if (same_col(room1, room2) && 344 1.1 cgd (rooms[room2].top_row > rooms[room1].bottom_row)) { 345 1.1 cgd put_door(&rooms[room1], DOWN, &row1, &col1); 346 1.1 cgd put_door(&rooms[room2], UPWARD, &row2, &col2); 347 1.1 cgd dir = DOWN; 348 1.1 cgd } else { 349 1.1 cgd return(0); 350 1.1 cgd } 351 1.1 cgd 352 1.1 cgd do { 353 1.1 cgd draw_simple_passage(row1, col1, row2, col2, dir); 354 1.1 cgd } while (rand_percent(4)); 355 1.1 cgd 356 1.1 cgd rooms[room1].doors[dir/2].oth_room = room2; 357 1.1 cgd rooms[room1].doors[dir/2].oth_row = row2; 358 1.1 cgd rooms[room1].doors[dir/2].oth_col = col2; 359 1.1 cgd 360 1.1 cgd rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_room = room1; 361 1.1 cgd rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_row = row1; 362 1.1 cgd rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_col = col1; 363 1.1 cgd return(1); 364 1.1 cgd } 365 1.1 cgd 366 1.4 lukem void 367 1.10 dholland clear_level(void) 368 1.1 cgd { 369 1.1 cgd short i, j; 370 1.1 cgd 371 1.1 cgd for (i = 0; i < MAXROOMS; i++) { 372 1.1 cgd rooms[i].is_room = R_NOTHING; 373 1.1 cgd for (j = 0; j < 4; j++) { 374 1.1 cgd rooms[i].doors[j].oth_room = NO_ROOM; 375 1.1 cgd } 376 1.1 cgd } 377 1.1 cgd 378 1.1 cgd for (i = 0; i < MAX_TRAPS; i++) { 379 1.1 cgd traps[i].trap_type = NO_TRAP; 380 1.1 cgd } 381 1.1 cgd for (i = 0; i < DROWS; i++) { 382 1.1 cgd for (j = 0; j < DCOLS; j++) { 383 1.1 cgd dungeon[i][j] = NOTHING; 384 1.1 cgd } 385 1.1 cgd } 386 1.1 cgd detect_monster = see_invisible = 0; 387 1.1 cgd being_held = bear_trap = 0; 388 1.1 cgd party_room = NO_ROOM; 389 1.1 cgd rogue.row = rogue.col = -1; 390 1.1 cgd clear(); 391 1.1 cgd } 392 1.1 cgd 393 1.10 dholland static void 394 1.10 dholland put_door(room *rm, short dir, short *row, short *col) 395 1.1 cgd { 396 1.1 cgd short wall_width; 397 1.1 cgd 398 1.1 cgd wall_width = (rm->is_room & R_MAZE) ? 0 : 1; 399 1.1 cgd 400 1.1 cgd switch(dir) { 401 1.1 cgd case UPWARD: 402 1.1 cgd case DOWN: 403 1.1 cgd *row = ((dir == UPWARD) ? rm->top_row : rm->bottom_row); 404 1.1 cgd do { 405 1.1 cgd *col = get_rand(rm->left_col+wall_width, 406 1.1 cgd rm->right_col-wall_width); 407 1.1 cgd } while (!(dungeon[*row][*col] & (HORWALL | TUNNEL))); 408 1.1 cgd break; 409 1.1 cgd case RIGHT: 410 1.1 cgd case LEFT: 411 1.1 cgd *col = (dir == LEFT) ? rm->left_col : rm->right_col; 412 1.1 cgd do { 413 1.1 cgd *row = get_rand(rm->top_row+wall_width, 414 1.1 cgd rm->bottom_row-wall_width); 415 1.1 cgd } while (!(dungeon[*row][*col] & (VERTWALL | TUNNEL))); 416 1.1 cgd break; 417 1.1 cgd } 418 1.1 cgd if (rm->is_room & R_ROOM) { 419 1.1 cgd dungeon[*row][*col] = DOOR; 420 1.1 cgd } 421 1.1 cgd if ((cur_level > 2) && rand_percent(HIDE_PERCENT)) { 422 1.1 cgd dungeon[*row][*col] |= HIDDEN; 423 1.1 cgd } 424 1.1 cgd rm->doors[dir/2].door_row = *row; 425 1.1 cgd rm->doors[dir/2].door_col = *col; 426 1.1 cgd } 427 1.1 cgd 428 1.10 dholland static void 429 1.10 dholland draw_simple_passage(short row1, short col1, short row2, short col2, short dir) 430 1.1 cgd { 431 1.1 cgd short i, middle, t; 432 1.1 cgd 433 1.1 cgd if ((dir == LEFT) || (dir == RIGHT)) { 434 1.1 cgd if (col1 > col2) { 435 1.10 dholland SWAP(row1, row2); 436 1.10 dholland SWAP(col1, col2); 437 1.1 cgd } 438 1.1 cgd middle = get_rand(col1+1, col2-1); 439 1.1 cgd for (i = col1+1; i != middle; i++) { 440 1.1 cgd dungeon[row1][i] = TUNNEL; 441 1.1 cgd } 442 1.1 cgd for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) { 443 1.1 cgd dungeon[i][middle] = TUNNEL; 444 1.1 cgd } 445 1.1 cgd for (i = middle; i != col2; i++) { 446 1.1 cgd dungeon[row2][i] = TUNNEL; 447 1.1 cgd } 448 1.1 cgd } else { 449 1.1 cgd if (row1 > row2) { 450 1.10 dholland SWAP(row1, row2); 451 1.10 dholland SWAP(col1, col2); 452 1.1 cgd } 453 1.1 cgd middle = get_rand(row1+1, row2-1); 454 1.1 cgd for (i = row1+1; i != middle; i++) { 455 1.1 cgd dungeon[i][col1] = TUNNEL; 456 1.1 cgd } 457 1.1 cgd for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) { 458 1.1 cgd dungeon[middle][i] = TUNNEL; 459 1.1 cgd } 460 1.1 cgd for (i = middle; i != row2; i++) { 461 1.1 cgd dungeon[i][col2] = TUNNEL; 462 1.1 cgd } 463 1.1 cgd } 464 1.1 cgd if (rand_percent(HIDE_PERCENT)) { 465 1.1 cgd hide_boxed_passage(row1, col1, row2, col2, 1); 466 1.1 cgd } 467 1.1 cgd } 468 1.1 cgd 469 1.10 dholland static int 470 1.10 dholland same_row(int room1, int room2) 471 1.1 cgd { 472 1.1 cgd return((room1 / 3) == (room2 / 3)); 473 1.1 cgd } 474 1.1 cgd 475 1.10 dholland static int 476 1.10 dholland same_col(int room1, int room2) 477 1.1 cgd { 478 1.1 cgd return((room1 % 3) == (room2 % 3)); 479 1.1 cgd } 480 1.1 cgd 481 1.10 dholland static void 482 1.10 dholland add_mazes(void) 483 1.1 cgd { 484 1.1 cgd short i, j; 485 1.1 cgd short start; 486 1.1 cgd short maze_percent; 487 1.1 cgd 488 1.1 cgd if (cur_level > 1) { 489 1.1 cgd start = get_rand(0, (MAXROOMS-1)); 490 1.1 cgd maze_percent = (cur_level * 5) / 4; 491 1.1 cgd 492 1.1 cgd if (cur_level > 15) { 493 1.1 cgd maze_percent += cur_level; 494 1.1 cgd } 495 1.1 cgd for (i = 0; i < MAXROOMS; i++) { 496 1.1 cgd j = ((start + i) % MAXROOMS); 497 1.1 cgd if (rooms[j].is_room & R_NOTHING) { 498 1.1 cgd if (rand_percent(maze_percent)) { 499 1.1 cgd rooms[j].is_room = R_MAZE; 500 1.1 cgd make_maze(get_rand(rooms[j].top_row+1, rooms[j].bottom_row-1), 501 1.1 cgd get_rand(rooms[j].left_col+1, rooms[j].right_col-1), 502 1.1 cgd rooms[j].top_row, rooms[j].bottom_row, 503 1.1 cgd rooms[j].left_col, rooms[j].right_col); 504 1.1 cgd hide_boxed_passage(rooms[j].top_row, rooms[j].left_col, 505 1.1 cgd rooms[j].bottom_row, rooms[j].right_col, 506 1.1 cgd get_rand(0, 2)); 507 1.1 cgd } 508 1.1 cgd } 509 1.1 cgd } 510 1.1 cgd } 511 1.1 cgd } 512 1.1 cgd 513 1.10 dholland static void 514 1.10 dholland fill_out_level(void) 515 1.1 cgd { 516 1.1 cgd short i, rn; 517 1.1 cgd 518 1.1 cgd mix_random_rooms(); 519 1.1 cgd 520 1.1 cgd r_de = NO_ROOM; 521 1.1 cgd 522 1.1 cgd for (i = 0; i < MAXROOMS; i++) { 523 1.1 cgd rn = random_rooms[i]; 524 1.1 cgd if ((rooms[rn].is_room & R_NOTHING) || 525 1.1 cgd ((rooms[rn].is_room & R_CROSS) && coin_toss())) { 526 1.1 cgd fill_it(rn, 1); 527 1.1 cgd } 528 1.1 cgd } 529 1.1 cgd if (r_de != NO_ROOM) { 530 1.1 cgd fill_it(r_de, 0); 531 1.1 cgd } 532 1.1 cgd } 533 1.1 cgd 534 1.10 dholland static void 535 1.10 dholland fill_it(int rn, boolean do_rec_de) 536 1.1 cgd { 537 1.1 cgd short i, tunnel_dir, door_dir, drow, dcol; 538 1.1 cgd short target_room, rooms_found = 0; 539 1.1 cgd short srow, scol, t; 540 1.1 cgd static short offsets[4] = {-1, 1, 3, -3}; 541 1.1 cgd boolean did_this = 0; 542 1.1 cgd 543 1.1 cgd for (i = 0; i < 10; i++) { 544 1.1 cgd srow = get_rand(0, 3); 545 1.1 cgd scol = get_rand(0, 3); 546 1.1 cgd t = offsets[srow]; 547 1.1 cgd offsets[srow] = offsets[scol]; 548 1.1 cgd offsets[scol] = t; 549 1.1 cgd } 550 1.1 cgd for (i = 0; i < 4; i++) { 551 1.1 cgd 552 1.1 cgd target_room = rn + offsets[i]; 553 1.1 cgd 554 1.1 cgd if (((target_room < 0) || (target_room >= MAXROOMS)) || 555 1.1 cgd (!(same_row(rn,target_room) || same_col(rn,target_room))) || 556 1.1 cgd (!(rooms[target_room].is_room & (R_ROOM | R_MAZE)))) { 557 1.1 cgd continue; 558 1.1 cgd } 559 1.1 cgd if (same_row(rn, target_room)) { 560 1.1 cgd tunnel_dir = (rooms[rn].left_col < rooms[target_room].left_col) ? 561 1.1 cgd RIGHT : LEFT; 562 1.1 cgd } else { 563 1.1 cgd tunnel_dir = (rooms[rn].top_row < rooms[target_room].top_row) ? 564 1.1 cgd DOWN : UPWARD; 565 1.1 cgd } 566 1.1 cgd door_dir = ((tunnel_dir + 4) % DIRS); 567 1.1 cgd if (rooms[target_room].doors[door_dir/2].oth_room != NO_ROOM) { 568 1.1 cgd continue; 569 1.1 cgd } 570 1.1 cgd if (((!do_rec_de) || did_this) || 571 1.1 cgd (!mask_room(rn, &srow, &scol, TUNNEL))) { 572 1.1 cgd srow = (rooms[rn].top_row + rooms[rn].bottom_row) / 2; 573 1.1 cgd scol = (rooms[rn].left_col + rooms[rn].right_col) / 2; 574 1.1 cgd } 575 1.1 cgd put_door(&rooms[target_room], door_dir, &drow, &dcol); 576 1.1 cgd rooms_found++; 577 1.1 cgd draw_simple_passage(srow, scol, drow, dcol, tunnel_dir); 578 1.1 cgd rooms[rn].is_room = R_DEADEND; 579 1.1 cgd dungeon[srow][scol] = TUNNEL; 580 1.1 cgd 581 1.1 cgd if ((i < 3) && (!did_this)) { 582 1.1 cgd did_this = 1; 583 1.1 cgd if (coin_toss()) { 584 1.1 cgd continue; 585 1.1 cgd } 586 1.1 cgd } 587 1.1 cgd if ((rooms_found < 2) && do_rec_de) { 588 1.1 cgd recursive_deadend(rn, offsets, srow, scol); 589 1.1 cgd } 590 1.1 cgd break; 591 1.1 cgd } 592 1.1 cgd } 593 1.1 cgd 594 1.10 dholland static void 595 1.10 dholland recursive_deadend(short rn, const short *offsets, short srow, short scol) 596 1.1 cgd { 597 1.1 cgd short i, de; 598 1.1 cgd short drow, dcol, tunnel_dir; 599 1.1 cgd 600 1.1 cgd rooms[rn].is_room = R_DEADEND; 601 1.1 cgd dungeon[srow][scol] = TUNNEL; 602 1.1 cgd 603 1.1 cgd for (i = 0; i < 4; i++) { 604 1.1 cgd de = rn + offsets[i]; 605 1.1 cgd if (((de < 0) || (de >= MAXROOMS)) || 606 1.1 cgd (!(same_row(rn, de) || same_col(rn, de)))) { 607 1.1 cgd continue; 608 1.1 cgd } 609 1.1 cgd if (!(rooms[de].is_room & R_NOTHING)) { 610 1.1 cgd continue; 611 1.1 cgd } 612 1.1 cgd drow = (rooms[de].top_row + rooms[de].bottom_row) / 2; 613 1.1 cgd dcol = (rooms[de].left_col + rooms[de].right_col) / 2; 614 1.1 cgd if (same_row(rn, de)) { 615 1.1 cgd tunnel_dir = (rooms[rn].left_col < rooms[de].left_col) ? 616 1.1 cgd RIGHT : LEFT; 617 1.1 cgd } else { 618 1.1 cgd tunnel_dir = (rooms[rn].top_row < rooms[de].top_row) ? 619 1.1 cgd DOWN : UPWARD; 620 1.1 cgd } 621 1.1 cgd draw_simple_passage(srow, scol, drow, dcol, tunnel_dir); 622 1.1 cgd r_de = de; 623 1.1 cgd recursive_deadend(de, offsets, drow, dcol); 624 1.1 cgd } 625 1.1 cgd } 626 1.1 cgd 627 1.10 dholland static boolean 628 1.10 dholland mask_room(short rn, short *row, short *col, unsigned short mask) 629 1.1 cgd { 630 1.1 cgd short i, j; 631 1.1 cgd 632 1.1 cgd for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) { 633 1.1 cgd for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) { 634 1.1 cgd if (dungeon[i][j] & mask) { 635 1.1 cgd *row = i; 636 1.1 cgd *col = j; 637 1.1 cgd return(1); 638 1.1 cgd } 639 1.1 cgd } 640 1.1 cgd } 641 1.1 cgd return(0); 642 1.1 cgd } 643 1.1 cgd 644 1.10 dholland static void 645 1.10 dholland make_maze(short r, short c, short tr, short br, short lc, short rc) 646 1.1 cgd { 647 1.1 cgd char dirs[4]; 648 1.1 cgd short i, t; 649 1.1 cgd 650 1.1 cgd dirs[0] = UPWARD; 651 1.1 cgd dirs[1] = DOWN; 652 1.1 cgd dirs[2] = LEFT; 653 1.1 cgd dirs[3] = RIGHT; 654 1.1 cgd 655 1.1 cgd dungeon[r][c] = TUNNEL; 656 1.1 cgd 657 1.1 cgd if (rand_percent(20)) { 658 1.1 cgd for (i = 0; i < 10; i++) { 659 1.1 cgd short t1, t2; 660 1.1 cgd 661 1.1 cgd t1 = get_rand(0, 3); 662 1.1 cgd t2 = get_rand(0, 3); 663 1.1 cgd 664 1.10 dholland SWAP(dirs[t1], dirs[t2]); 665 1.1 cgd } 666 1.1 cgd } 667 1.1 cgd for (i = 0; i < 4; i++) { 668 1.1 cgd switch(dirs[i]) { 669 1.1 cgd case UPWARD: 670 1.1 cgd if (((r-1) >= tr) && 671 1.1 cgd (dungeon[r-1][c] != TUNNEL) && 672 1.1 cgd (dungeon[r-1][c-1] != TUNNEL) && 673 1.1 cgd (dungeon[r-1][c+1] != TUNNEL) && 674 1.1 cgd (dungeon[r-2][c] != TUNNEL)) { 675 1.1 cgd make_maze((r-1), c, tr, br, lc, rc); 676 1.1 cgd } 677 1.1 cgd break; 678 1.1 cgd case DOWN: 679 1.1 cgd if (((r+1) <= br) && 680 1.1 cgd (dungeon[r+1][c] != TUNNEL) && 681 1.1 cgd (dungeon[r+1][c-1] != TUNNEL) && 682 1.1 cgd (dungeon[r+1][c+1] != TUNNEL) && 683 1.1 cgd (dungeon[r+2][c] != TUNNEL)) { 684 1.1 cgd make_maze((r+1), c, tr, br, lc, rc); 685 1.1 cgd } 686 1.1 cgd break; 687 1.1 cgd case LEFT: 688 1.1 cgd if (((c-1) >= lc) && 689 1.1 cgd (dungeon[r][c-1] != TUNNEL) && 690 1.1 cgd (dungeon[r-1][c-1] != TUNNEL) && 691 1.1 cgd (dungeon[r+1][c-1] != TUNNEL) && 692 1.1 cgd (dungeon[r][c-2] != TUNNEL)) { 693 1.1 cgd make_maze(r, (c-1), tr, br, lc, rc); 694 1.1 cgd } 695 1.1 cgd break; 696 1.1 cgd case RIGHT: 697 1.1 cgd if (((c+1) <= rc) && 698 1.1 cgd (dungeon[r][c+1] != TUNNEL) && 699 1.1 cgd (dungeon[r-1][c+1] != TUNNEL) && 700 1.1 cgd (dungeon[r+1][c+1] != TUNNEL) && 701 1.1 cgd (dungeon[r][c+2] != TUNNEL)) { 702 1.1 cgd make_maze(r, (c+1), tr, br, lc, rc); 703 1.1 cgd } 704 1.1 cgd break; 705 1.1 cgd } 706 1.1 cgd } 707 1.1 cgd } 708 1.1 cgd 709 1.10 dholland static void 710 1.10 dholland hide_boxed_passage(short row1, short col1, short row2, short col2, short n) 711 1.1 cgd { 712 1.1 cgd short i, j, t; 713 1.1 cgd short row, col, row_cut, col_cut; 714 1.1 cgd short h, w; 715 1.1 cgd 716 1.1 cgd if (cur_level > 2) { 717 1.1 cgd if (row1 > row2) { 718 1.10 dholland SWAP(row1, row2); 719 1.1 cgd } 720 1.1 cgd if (col1 > col2) { 721 1.10 dholland SWAP(col1, col2); 722 1.1 cgd } 723 1.1 cgd h = row2 - row1; 724 1.1 cgd w = col2 - col1; 725 1.1 cgd 726 1.1 cgd if ((w >= 5) || (h >= 5)) { 727 1.1 cgd row_cut = ((h >= 2) ? 1 : 0); 728 1.1 cgd col_cut = ((w >= 2) ? 1 : 0); 729 1.1 cgd 730 1.1 cgd for (i = 0; i < n; i++) { 731 1.1 cgd for (j = 0; j < 10; j++) { 732 1.1 cgd row = get_rand(row1 + row_cut, row2 - row_cut); 733 1.1 cgd col = get_rand(col1 + col_cut, col2 - col_cut); 734 1.1 cgd if (dungeon[row][col] == TUNNEL) { 735 1.1 cgd dungeon[row][col] |= HIDDEN; 736 1.1 cgd break; 737 1.1 cgd } 738 1.1 cgd } 739 1.1 cgd } 740 1.1 cgd } 741 1.1 cgd } 742 1.1 cgd } 743 1.1 cgd 744 1.10 dholland /* 745 1.10 dholland * try not to put in room NR 746 1.10 dholland */ 747 1.4 lukem void 748 1.10 dholland put_player(short nr) 749 1.1 cgd { 750 1.1 cgd short rn = nr, misses; 751 1.1 cgd short row, col; 752 1.1 cgd 753 1.1 cgd for (misses = 0; ((misses < 2) && (rn == nr)); misses++) { 754 1.1 cgd gr_row_col(&row, &col, (FLOOR | TUNNEL | OBJECT | STAIRS)); 755 1.1 cgd rn = get_room_number(row, col); 756 1.1 cgd } 757 1.1 cgd rogue.row = row; 758 1.1 cgd rogue.col = col; 759 1.1 cgd 760 1.1 cgd if (dungeon[rogue.row][rogue.col] & TUNNEL) { 761 1.1 cgd cur_room = PASSAGE; 762 1.1 cgd } else { 763 1.1 cgd cur_room = rn; 764 1.1 cgd } 765 1.1 cgd if (cur_room != PASSAGE) { 766 1.1 cgd light_up_room(cur_room); 767 1.1 cgd } else { 768 1.1 cgd light_passage(rogue.row, rogue.col); 769 1.1 cgd } 770 1.1 cgd rn = get_room_number(rogue.row, rogue.col); 771 1.1 cgd wake_room(rn, 1, rogue.row, rogue.col); 772 1.1 cgd if (new_level_message) { 773 1.8 dholland messagef(0, "%s", new_level_message); 774 1.8 dholland new_level_message = NULL; 775 1.1 cgd } 776 1.1 cgd mvaddch(rogue.row, rogue.col, rogue.fchar); 777 1.1 cgd } 778 1.1 cgd 779 1.4 lukem int 780 1.10 dholland drop_check(void) 781 1.1 cgd { 782 1.1 cgd if (wizard) { 783 1.1 cgd return(1); 784 1.1 cgd } 785 1.1 cgd if (dungeon[rogue.row][rogue.col] & STAIRS) { 786 1.1 cgd if (levitate) { 787 1.8 dholland messagef(0, "you're floating in the air!"); 788 1.1 cgd return(0); 789 1.1 cgd } 790 1.1 cgd return(1); 791 1.1 cgd } 792 1.8 dholland messagef(0, "I see no way down"); 793 1.1 cgd return(0); 794 1.1 cgd } 795 1.1 cgd 796 1.4 lukem int 797 1.10 dholland check_up(void) 798 1.1 cgd { 799 1.1 cgd if (!wizard) { 800 1.1 cgd if (!(dungeon[rogue.row][rogue.col] & STAIRS)) { 801 1.8 dholland messagef(0, "I see no way up"); 802 1.1 cgd return(0); 803 1.1 cgd } 804 1.1 cgd if (!has_amulet()) { 805 1.8 dholland messagef(0, "your way is magically blocked"); 806 1.1 cgd return(0); 807 1.1 cgd } 808 1.1 cgd } 809 1.1 cgd new_level_message = "you feel a wrenching sensation in your gut"; 810 1.1 cgd if (cur_level == 1) { 811 1.1 cgd win(); 812 1.1 cgd } else { 813 1.1 cgd cur_level -= 2; 814 1.1 cgd return(1); 815 1.1 cgd } 816 1.1 cgd return(0); 817 1.1 cgd } 818 1.1 cgd 819 1.4 lukem void 820 1.10 dholland add_exp(int e, boolean promotion) 821 1.1 cgd { 822 1.1 cgd short new_exp; 823 1.1 cgd short i, hp; 824 1.1 cgd 825 1.1 cgd rogue.exp_points += e; 826 1.1 cgd 827 1.1 cgd if (rogue.exp_points >= level_points[rogue.exp-1]) { 828 1.1 cgd new_exp = get_exp_level(rogue.exp_points); 829 1.1 cgd if (rogue.exp_points > MAX_EXP) { 830 1.1 cgd rogue.exp_points = MAX_EXP + 1; 831 1.1 cgd } 832 1.1 cgd for (i = rogue.exp+1; i <= new_exp; i++) { 833 1.8 dholland messagef(0, "welcome to level %d", i); 834 1.1 cgd if (promotion) { 835 1.1 cgd hp = hp_raise(); 836 1.1 cgd rogue.hp_current += hp; 837 1.1 cgd rogue.hp_max += hp; 838 1.1 cgd } 839 1.1 cgd rogue.exp = i; 840 1.1 cgd print_stats(STAT_HP | STAT_EXP); 841 1.1 cgd } 842 1.1 cgd } else { 843 1.1 cgd print_stats(STAT_EXP); 844 1.1 cgd } 845 1.1 cgd } 846 1.1 cgd 847 1.10 dholland static int 848 1.10 dholland get_exp_level(long e) 849 1.1 cgd { 850 1.1 cgd short i; 851 1.1 cgd 852 1.1 cgd for (i = 0; i < (MAX_EXP_LEVEL - 1); i++) { 853 1.1 cgd if (level_points[i] > e) { 854 1.1 cgd break; 855 1.1 cgd } 856 1.1 cgd } 857 1.1 cgd return(i+1); 858 1.1 cgd } 859 1.1 cgd 860 1.4 lukem int 861 1.10 dholland hp_raise(void) 862 1.1 cgd { 863 1.1 cgd int hp; 864 1.1 cgd 865 1.1 cgd hp = (wizard ? 10 : get_rand(3, 10)); 866 1.1 cgd return(hp); 867 1.1 cgd } 868 1.1 cgd 869 1.4 lukem void 870 1.10 dholland show_average_hp(void) 871 1.1 cgd { 872 1.1 cgd float real_average; 873 1.1 cgd float effective_average; 874 1.1 cgd 875 1.1 cgd if (rogue.exp == 1) { 876 1.1 cgd real_average = effective_average = 0.00; 877 1.1 cgd } else { 878 1.1 cgd real_average = (float) 879 1.1 cgd ((rogue.hp_max - extra_hp - INIT_HP) + less_hp) / (rogue.exp - 1); 880 1.9 dholland effective_average = (float)(rogue.hp_max - INIT_HP) / (rogue.exp - 1); 881 1.1 cgd 882 1.1 cgd } 883 1.8 dholland messagef(0, "R-Hp: %.2f, E-Hp: %.2f (!: %d, V: %d)", real_average, 884 1.1 cgd effective_average, extra_hp, less_hp); 885 1.1 cgd } 886 1.1 cgd 887 1.10 dholland static void 888 1.10 dholland mix_random_rooms(void) 889 1.1 cgd { 890 1.1 cgd short i, t; 891 1.1 cgd short x, y; 892 1.1 cgd 893 1.1 cgd for (i = 0; i < (3 * MAXROOMS); i++) { 894 1.1 cgd do { 895 1.1 cgd x = get_rand(0, (MAXROOMS-1)); 896 1.1 cgd y = get_rand(0, (MAXROOMS-1)); 897 1.1 cgd } while (x == y); 898 1.10 dholland SWAP(random_rooms[x], random_rooms[y]); 899 1.1 cgd } 900 1.1 cgd } 901