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