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