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 * $DragonFly: src/games/rogue/level.c,v 1.4 2006/09/02 19:31:07 pavalos Exp $ 35 */ 36 37 /* 38 * level.c 39 * 40 * This source herein may be modified and/or distributed by anybody who 41 * so desires, with the following restrictions: 42 * 1.) No portion of this notice shall be removed. 43 * 2.) Credit shall not be taken for the creation of this source. 44 * 3.) This code is not to be traded, sold, or used for personal 45 * gain or profit. 46 * 47 */ 48 49 #include "rogue.h" 50 51 #define swap(x,y) {t = x; x = y; y = t;} 52 53 static void add_mazes(void); 54 static boolean connect_rooms(short, short); 55 static void draw_simple_passage(short, short, short, short, short); 56 static void fill_it(int, boolean); 57 static void fill_out_level(void); 58 static short get_exp_level(long); 59 static void hide_boxed_passage(short, short, short, short, short); 60 static void make_maze(short, short, short, short, short, short); 61 static void make_room(short, short, short, short); 62 static boolean mask_room(short, short *, short *, unsigned short); 63 static void mix_random_rooms(void); 64 static void put_door(room *, short, short *, short *); 65 static void recursive_deadend(short, const short *, short, short); 66 static boolean same_col(short, short); 67 static boolean same_row(short, short); 68 69 short cur_level = 0; 70 short max_level = 1; 71 short cur_room; 72 const char *new_level_message = NULL; 73 short party_room = NO_ROOM; 74 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 short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8}; 101 102 extern boolean being_held, wizard, detect_monster; 103 extern boolean see_invisible; 104 extern short bear_trap, levitate, extra_hp, less_hp; 105 106 void 107 make_level(void) 108 { 109 short i, j; 110 short must_1, must_2 = 0, must_3 = 0; 111 boolean big_room; 112 113 if (cur_level < LAST_DUNGEON) { 114 cur_level++; 115 } 116 if (cur_level > max_level) { 117 max_level = cur_level; 118 } 119 must_1 = get_rand(0, 5); 120 121 switch(must_1) { 122 case 0: 123 must_1 = 0; 124 must_2 = 1; 125 must_3 = 2; 126 break; 127 case 1: 128 must_1 = 3; 129 must_2 = 4; 130 must_3 = 5; 131 break; 132 case 2: 133 must_1 = 6; 134 must_2 = 7; 135 must_3 = 8; 136 break; 137 case 3: 138 must_1 = 0; 139 must_2 = 3; 140 must_3 = 6; 141 break; 142 case 4: 143 must_1 = 1; 144 must_2 = 4; 145 must_3 = 7; 146 break; 147 case 5: 148 must_1 = 2; 149 must_2 = 5; 150 must_3 = 8; 151 break; 152 } 153 if (rand_percent(8)) { 154 party_room = 0; 155 } 156 big_room = ((party_room != NO_ROOM) && rand_percent(1)); 157 if (big_room) { 158 make_room(BIG_ROOM, 0, 0, 0); 159 } else { 160 for (i = 0; i < MAXROOMS; i++) { 161 make_room(i, must_1, must_2, must_3); 162 } 163 } 164 if (!big_room) { 165 add_mazes(); 166 167 mix_random_rooms(); 168 169 for (j = 0; j < MAXROOMS; j++) { 170 171 i = random_rooms[j]; 172 173 if (i < (MAXROOMS-1)) { 174 connect_rooms(i, i+1); 175 } 176 if (i < (MAXROOMS-3)) { 177 connect_rooms(i, i+3); 178 } 179 if (i < (MAXROOMS-2)) { 180 if (rooms[i+1].is_room & R_NOTHING) { 181 if (connect_rooms(i, i+2)) { 182 rooms[i+1].is_room = R_CROSS; 183 } 184 } 185 } 186 if (i < (MAXROOMS-6)) { 187 if (rooms[i+3].is_room & R_NOTHING) { 188 if (connect_rooms(i, i+6)) { 189 rooms[i+3].is_room = R_CROSS; 190 } 191 } 192 } 193 if (is_all_connected()) { 194 break; 195 } 196 } 197 fill_out_level(); 198 } 199 if (!has_amulet() && (cur_level >= AMULET_LEVEL)) { 200 put_amulet(); 201 } 202 } 203 204 static void 205 make_room(short rn, short r1, short r2, short r3) 206 { 207 short left_col, right_col, top_row, bottom_row; 208 short width, height; 209 short row_offset, col_offset; 210 short i, j, ch; 211 212 left_col = right_col = top_row = bottom_row = 0; 213 214 switch(rn) { 215 case 0: 216 left_col = 0; 217 right_col = COL1-1; 218 top_row = MIN_ROW; 219 bottom_row = ROW1-1; 220 break; 221 case 1: 222 left_col = COL1+1; 223 right_col = COL2-1; 224 top_row = MIN_ROW; 225 bottom_row = ROW1-1; 226 break; 227 case 2: 228 left_col = COL2+1; 229 right_col = DCOLS-1; 230 top_row = MIN_ROW; 231 bottom_row = ROW1-1; 232 break; 233 case 3: 234 left_col = 0; 235 right_col = COL1-1; 236 top_row = ROW1+1; 237 bottom_row = ROW2-1; 238 break; 239 case 4: 240 left_col = COL1+1; 241 right_col = COL2-1; 242 top_row = ROW1+1; 243 bottom_row = ROW2-1; 244 break; 245 case 5: 246 left_col = COL2+1; 247 right_col = DCOLS-1; 248 top_row = ROW1+1; 249 bottom_row = ROW2-1; 250 break; 251 case 6: 252 left_col = 0; 253 right_col = COL1-1; 254 top_row = ROW2+1; 255 bottom_row = DROWS - 2; 256 break; 257 case 7: 258 left_col = COL1+1; 259 right_col = COL2-1; 260 top_row = ROW2+1; 261 bottom_row = DROWS - 2; 262 break; 263 case 8: 264 left_col = COL2+1; 265 right_col = DCOLS-1; 266 top_row = ROW2+1; 267 bottom_row = DROWS - 2; 268 break; 269 case BIG_ROOM: 270 top_row = get_rand(MIN_ROW, MIN_ROW+5); 271 bottom_row = get_rand(DROWS-7, DROWS-2); 272 left_col = get_rand(0, 10); 273 right_col = get_rand(DCOLS-11, DCOLS-1); 274 rn = 0; 275 goto B; 276 } 277 height = get_rand(4, (bottom_row - top_row + 1)); 278 width = get_rand(7, (right_col - left_col - 2)); 279 280 row_offset = get_rand(0, ((bottom_row - top_row) - height + 1)); 281 col_offset = get_rand(0, ((right_col - left_col) - width + 1)); 282 283 top_row += row_offset; 284 bottom_row = top_row + height - 1; 285 286 left_col += col_offset; 287 right_col = left_col + width - 1; 288 289 if ((rn != r1) && (rn != r2) && (rn != r3) && rand_percent(40)) { 290 goto END; 291 } 292 B: 293 rooms[rn].is_room = R_ROOM; 294 295 for (i = top_row; i <= bottom_row; i++) { 296 for (j = left_col; j <= right_col; j++) { 297 if ((i == top_row) || (i == bottom_row)) { 298 ch = HORWALL; 299 } else if ( ((i != top_row) && (i != bottom_row)) && 300 ((j == left_col) || (j == right_col))) { 301 ch = VERTWALL; 302 } else { 303 ch = FLOOR; 304 } 305 dungeon[i][j] = ch; 306 } 307 } 308 END: 309 rooms[rn].top_row = top_row; 310 rooms[rn].bottom_row = bottom_row; 311 rooms[rn].left_col = left_col; 312 rooms[rn].right_col = right_col; 313 } 314 315 static boolean 316 connect_rooms(short room1, short room2) 317 { 318 short row1, col1, row2, col2, dir; 319 320 if ((!(rooms[room1].is_room & (R_ROOM | R_MAZE))) || 321 (!(rooms[room2].is_room & (R_ROOM | R_MAZE)))) { 322 return(0); 323 } 324 if (same_row(room1, room2) && 325 (rooms[room1].left_col > rooms[room2].right_col)) { 326 put_door(&rooms[room1], LEFT, &row1, &col1); 327 put_door(&rooms[room2], RIGHT, &row2, &col2); 328 dir = LEFT; 329 } else if (same_row(room1, room2) && 330 (rooms[room2].left_col > rooms[room1].right_col)) { 331 put_door(&rooms[room1], RIGHT, &row1, &col1); 332 put_door(&rooms[room2], LEFT, &row2, &col2); 333 dir = RIGHT; 334 } else if (same_col(room1, room2) && 335 (rooms[room1].top_row > rooms[room2].bottom_row)) { 336 put_door(&rooms[room1], UPWARD, &row1, &col1); 337 put_door(&rooms[room2], DOWN, &row2, &col2); 338 dir = UPWARD; 339 } else if (same_col(room1, room2) && 340 (rooms[room2].top_row > rooms[room1].bottom_row)) { 341 put_door(&rooms[room1], DOWN, &row1, &col1); 342 put_door(&rooms[room2], UPWARD, &row2, &col2); 343 dir = DOWN; 344 } else { 345 return(0); 346 } 347 348 do { 349 draw_simple_passage(row1, col1, row2, col2, dir); 350 } while (rand_percent(4)); 351 352 rooms[room1].doors[dir/2].oth_room = room2; 353 rooms[room1].doors[dir/2].oth_row = row2; 354 rooms[room1].doors[dir/2].oth_col = col2; 355 356 rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_room = room1; 357 rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_row = row1; 358 rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_col = col1; 359 return(1); 360 } 361 362 void 363 clear_level(void) 364 { 365 short i, j; 366 367 for (i = 0; i < MAXROOMS; i++) { 368 rooms[i].is_room = R_NOTHING; 369 for (j = 0; j < 4; j++) { 370 rooms[i].doors[j].oth_room = NO_ROOM; 371 } 372 } 373 374 for (i = 0; i < MAX_TRAPS; i++) { 375 traps[i].trap_type = NO_TRAP; 376 } 377 for (i = 0; i < DROWS; i++) { 378 for (j = 0; j < DCOLS; j++) { 379 dungeon[i][j] = NOTHING; 380 } 381 } 382 detect_monster = see_invisible = 0; 383 bear_trap = being_held = 0; 384 party_room = NO_ROOM; 385 rogue.row = rogue.col = -1; 386 clear(); 387 } 388 389 static void 390 put_door(room *rm, short dir, short *row, short *col) 391 { 392 short wall_width; 393 394 wall_width = (rm->is_room & R_MAZE) ? 0 : 1; 395 396 switch(dir) { 397 case UPWARD: 398 case DOWN: 399 *row = ((dir == UPWARD) ? rm->top_row : rm->bottom_row); 400 do { 401 *col = get_rand(rm->left_col+wall_width, 402 rm->right_col-wall_width); 403 } while (!(dungeon[*row][*col] & (HORWALL | TUNNEL))); 404 break; 405 case RIGHT: 406 case LEFT: 407 *col = (dir == LEFT) ? rm->left_col : rm->right_col; 408 do { 409 *row = get_rand(rm->top_row+wall_width, 410 rm->bottom_row-wall_width); 411 } while (!(dungeon[*row][*col] & (VERTWALL | TUNNEL))); 412 break; 413 } 414 if (rm->is_room & R_ROOM) { 415 dungeon[*row][*col] = DOOR; 416 } 417 if ((cur_level > 2) && rand_percent(HIDE_PERCENT)) { 418 dungeon[*row][*col] |= HIDDEN; 419 } 420 rm->doors[dir/2].door_row = *row; 421 rm->doors[dir/2].door_col = *col; 422 } 423 424 static void 425 draw_simple_passage(short row1, short col1, short row2, short col2, short dir) 426 { 427 short i, middle, t; 428 429 if ((dir == LEFT) || (dir == RIGHT)) { 430 if (col1 > col2) { 431 swap(row1, row2); 432 swap(col1, col2); 433 } 434 middle = get_rand(col1+1, col2-1); 435 for (i = col1+1; i != middle; i++) { 436 dungeon[row1][i] = TUNNEL; 437 } 438 for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) { 439 dungeon[i][middle] = TUNNEL; 440 } 441 for (i = middle; i != col2; i++) { 442 dungeon[row2][i] = TUNNEL; 443 } 444 } else { 445 if (row1 > row2) { 446 swap(row1, row2); 447 swap(col1, col2); 448 } 449 middle = get_rand(row1+1, row2-1); 450 for (i = row1+1; i != middle; i++) { 451 dungeon[i][col1] = TUNNEL; 452 } 453 for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) { 454 dungeon[middle][i] = TUNNEL; 455 } 456 for (i = middle; i != row2; i++) { 457 dungeon[i][col2] = TUNNEL; 458 } 459 } 460 if (rand_percent(HIDE_PERCENT)) { 461 hide_boxed_passage(row1, col1, row2, col2, 1); 462 } 463 } 464 465 static boolean 466 same_row(short room1, short room2) 467 { 468 return((room1 / 3) == (room2 / 3)); 469 } 470 471 static boolean 472 same_col(short room1, short room2) 473 { 474 return((room1 % 3) == (room2 % 3)); 475 } 476 477 static void 478 add_mazes(void) 479 { 480 short i, j; 481 short start; 482 short maze_percent; 483 484 if (cur_level > 1) { 485 start = get_rand(0, (MAXROOMS-1)); 486 maze_percent = (cur_level * 5) / 4; 487 488 if (cur_level > 15) { 489 maze_percent += cur_level; 490 } 491 for (i = 0; i < MAXROOMS; i++) { 492 j = ((start + i) % MAXROOMS); 493 if (rooms[j].is_room & R_NOTHING) { 494 if (rand_percent(maze_percent)) { 495 rooms[j].is_room = R_MAZE; 496 make_maze(get_rand(rooms[j].top_row+1, rooms[j].bottom_row-1), 497 get_rand(rooms[j].left_col+1, rooms[j].right_col-1), 498 rooms[j].top_row, rooms[j].bottom_row, 499 rooms[j].left_col, rooms[j].right_col); 500 hide_boxed_passage(rooms[j].top_row, rooms[j].left_col, 501 rooms[j].bottom_row, rooms[j].right_col, 502 get_rand(0, 2)); 503 } 504 } 505 } 506 } 507 } 508 509 static void 510 fill_out_level(void) 511 { 512 short i, rn; 513 514 mix_random_rooms(); 515 516 r_de = NO_ROOM; 517 518 for (i = 0; i < MAXROOMS; i++) { 519 rn = random_rooms[i]; 520 if ((rooms[rn].is_room & R_NOTHING) || 521 ((rooms[rn].is_room & R_CROSS) && coin_toss())) { 522 fill_it(rn, 1); 523 } 524 } 525 if (r_de != NO_ROOM) { 526 fill_it(r_de, 0); 527 } 528 } 529 530 static void 531 fill_it(int rn, boolean do_rec_de) 532 { 533 short i, tunnel_dir, door_dir, drow, dcol; 534 short target_room, rooms_found = 0; 535 short srow, scol, t; 536 static short offsets[4] = {-1, 1, 3, -3}; 537 boolean did_this = 0; 538 539 for (i = 0; i < 10; i++) { 540 srow = get_rand(0, 3); 541 scol = get_rand(0, 3); 542 t = offsets[srow]; 543 offsets[srow] = offsets[scol]; 544 offsets[scol] = t; 545 } 546 for (i = 0; i < 4; i++) { 547 548 target_room = rn + offsets[i]; 549 550 if (((target_room < 0) || (target_room >= MAXROOMS)) || 551 (!(same_row(rn,target_room) || same_col(rn,target_room))) || 552 (!(rooms[target_room].is_room & (R_ROOM | R_MAZE)))) { 553 continue; 554 } 555 if (same_row(rn, target_room)) { 556 tunnel_dir = (rooms[rn].left_col < rooms[target_room].left_col) ? 557 RIGHT : LEFT; 558 } else { 559 tunnel_dir = (rooms[rn].top_row < rooms[target_room].top_row) ? 560 DOWN : UPWARD; 561 } 562 door_dir = ((tunnel_dir + 4) % DIRS); 563 if (rooms[target_room].doors[door_dir/2].oth_room != NO_ROOM) { 564 continue; 565 } 566 if (((!do_rec_de) || did_this) || 567 (!mask_room(rn, &srow, &scol, TUNNEL))) { 568 srow = (rooms[rn].top_row + rooms[rn].bottom_row) / 2; 569 scol = (rooms[rn].left_col + rooms[rn].right_col) / 2; 570 } 571 put_door(&rooms[target_room], door_dir, &drow, &dcol); 572 rooms_found++; 573 draw_simple_passage(srow, scol, drow, dcol, tunnel_dir); 574 rooms[rn].is_room = R_DEADEND; 575 dungeon[srow][scol] = TUNNEL; 576 577 if ((i < 3) && (!did_this)) { 578 did_this = 1; 579 if (coin_toss()) { 580 continue; 581 } 582 } 583 if ((rooms_found < 2) && do_rec_de) { 584 recursive_deadend(rn, offsets, srow, scol); 585 } 586 break; 587 } 588 } 589 590 static void 591 recursive_deadend(short rn, const short *offsets, short srow, short scol) 592 { 593 short i, de; 594 short drow, dcol, tunnel_dir; 595 596 rooms[rn].is_room = R_DEADEND; 597 dungeon[srow][scol] = TUNNEL; 598 599 for (i = 0; i < 4; i++) { 600 de = rn + offsets[i]; 601 if (((de < 0) || (de >= MAXROOMS)) || 602 (!(same_row(rn, de) || same_col(rn, de)))) { 603 continue; 604 } 605 if (!(rooms[de].is_room & R_NOTHING)) { 606 continue; 607 } 608 drow = (rooms[de].top_row + rooms[de].bottom_row) / 2; 609 dcol = (rooms[de].left_col + rooms[de].right_col) / 2; 610 if (same_row(rn, de)) { 611 tunnel_dir = (rooms[rn].left_col < rooms[de].left_col) ? 612 RIGHT : LEFT; 613 } else { 614 tunnel_dir = (rooms[rn].top_row < rooms[de].top_row) ? 615 DOWN : UPWARD; 616 } 617 draw_simple_passage(srow, scol, drow, dcol, tunnel_dir); 618 r_de = de; 619 recursive_deadend(de, offsets, drow, dcol); 620 } 621 } 622 623 static boolean 624 mask_room(short rn, short *row, short *col, unsigned short mask) 625 { 626 short i, j; 627 628 for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) { 629 for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) { 630 if (dungeon[i][j] & mask) { 631 *row = i; 632 *col = j; 633 return(1); 634 } 635 } 636 } 637 return(0); 638 } 639 640 static void 641 make_maze(short r, short c, short tr, short br, short lc, short rc) 642 { 643 char dirs[4]; 644 short i, t; 645 646 dirs[0] = UPWARD; 647 dirs[1] = DOWN; 648 dirs[2] = LEFT; 649 dirs[3] = RIGHT; 650 651 dungeon[r][c] = TUNNEL; 652 653 if (rand_percent(20)) { 654 for (i = 0; i < 10; i++) { 655 short t1, t2; 656 657 t1 = get_rand(0, 3); 658 t2 = get_rand(0, 3); 659 660 swap(dirs[t1], dirs[t2]); 661 } 662 } 663 for (i = 0; i < 4; i++) { 664 switch(dirs[i]) { 665 case UPWARD: 666 if (((r-1) >= tr) && 667 (dungeon[r-1][c] != TUNNEL) && 668 (dungeon[r-1][c-1] != TUNNEL) && 669 (dungeon[r-1][c+1] != TUNNEL) && 670 (dungeon[r-2][c] != TUNNEL)) { 671 make_maze((r-1), c, tr, br, lc, rc); 672 } 673 break; 674 case DOWN: 675 if (((r+1) <= br) && 676 (dungeon[r+1][c] != TUNNEL) && 677 (dungeon[r+1][c-1] != TUNNEL) && 678 (dungeon[r+1][c+1] != TUNNEL) && 679 (dungeon[r+2][c] != TUNNEL)) { 680 make_maze((r+1), c, tr, br, lc, rc); 681 } 682 break; 683 case LEFT: 684 if (((c-1) >= lc) && 685 (dungeon[r][c-1] != TUNNEL) && 686 (dungeon[r-1][c-1] != TUNNEL) && 687 (dungeon[r+1][c-1] != TUNNEL) && 688 (dungeon[r][c-2] != TUNNEL)) { 689 make_maze(r, (c-1), tr, br, lc, rc); 690 } 691 break; 692 case RIGHT: 693 if (((c+1) <= rc) && 694 (dungeon[r][c+1] != TUNNEL) && 695 (dungeon[r-1][c+1] != TUNNEL) && 696 (dungeon[r+1][c+1] != TUNNEL) && 697 (dungeon[r][c+2] != TUNNEL)) { 698 make_maze(r, (c+1), tr, br, lc, rc); 699 } 700 break; 701 } 702 } 703 } 704 705 static void 706 hide_boxed_passage(short row1, short col1, short row2, short col2, short n) 707 { 708 short i, j, t; 709 short row, col, row_cut, col_cut; 710 short h, w; 711 712 if (cur_level > 2) { 713 if (row1 > row2) { 714 swap(row1, row2); 715 } 716 if (col1 > col2) { 717 swap(col1, col2); 718 } 719 h = row2 - row1; 720 w = col2 - col1; 721 722 if ((w >= 5) || (h >= 5)) { 723 row_cut = ((h >= 2) ? 1 : 0); 724 col_cut = ((w >= 2) ? 1 : 0); 725 726 for (i = 0; i < n; i++) { 727 for (j = 0; j < 10; j++) { 728 row = get_rand(row1 + row_cut, row2 - row_cut); 729 col = get_rand(col1 + col_cut, col2 - col_cut); 730 if (dungeon[row][col] == TUNNEL) { 731 dungeon[row][col] |= HIDDEN; 732 break; 733 } 734 } 735 } 736 } 737 } 738 } 739 740 void 741 put_player(short nr) /* try not to put in this room */ 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