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