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. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)move.c 8.1 (Berkeley) 5/31/93"; 40 #endif 41 static const char rcsid[] = 42 "$FreeBSD: src/games/rogue/move.c,v 1.7 1999/11/30 03:49:24 billf Exp $"; 43 #endif /* not lint */ 44 45 /* 46 * move.c 47 * 48 * This source herein may be modified and/or distributed by anybody who 49 * so desires, with the following restrictions: 50 * 1.) No portion of this notice shall be removed. 51 * 2.) Credit shall not be taken for the creation of this source. 52 * 3.) This code is not to be traded, sold, or used for personal 53 * gain or profit. 54 * 55 */ 56 57 #include "rogue.h" 58 59 short m_moves = 0; 60 boolean jump = 0; 61 const char *you_can_move_again = "you can move again"; 62 63 extern short cur_room, halluc, blind, levitate; 64 extern short cur_level, max_level; 65 extern short bear_trap, haste_self, confused; 66 extern short e_rings, regeneration, auto_search; 67 extern char hunger_str[]; 68 extern boolean being_held, interrupted, r_teleport, passgo; 69 70 one_move_rogue(dirch, pickup) 71 short dirch, pickup; 72 { 73 short row, col; 74 object *obj; 75 char desc[DCOLS]; 76 short n, status, d; 77 78 row = rogue.row; 79 col = rogue.col; 80 81 if (confused) { 82 dirch = gr_dir(); 83 } 84 (void) is_direction(dirch, &d); 85 get_dir_rc(d, &row, &col, 1); 86 87 if (!can_move(rogue.row, rogue.col, row, col)) { 88 return(MOVE_FAILED); 89 } 90 if (being_held || bear_trap) { 91 if (!(dungeon[row][col] & MONSTER)) { 92 if (being_held) { 93 message("you are being held", 1); 94 } else { 95 message("you are still stuck in the bear trap", 0); 96 (void) reg_move(); 97 } 98 return(MOVE_FAILED); 99 } 100 } 101 if (r_teleport) { 102 if (rand_percent(R_TELE_PERCENT)) { 103 tele(); 104 return(STOPPED_ON_SOMETHING); 105 } 106 } 107 if (dungeon[row][col] & MONSTER) { 108 rogue_hit(object_at(&level_monsters, row, col), 0); 109 (void) reg_move(); 110 return(MOVE_FAILED); 111 } 112 if (dungeon[row][col] & DOOR) { 113 if (cur_room == PASSAGE) { 114 cur_room = get_room_number(row, col); 115 light_up_room(cur_room); 116 wake_room(cur_room, 1, row, col); 117 } else { 118 light_passage(row, col); 119 } 120 } else if ((dungeon[rogue.row][rogue.col] & DOOR) && 121 (dungeon[row][col] & TUNNEL)) { 122 light_passage(row, col); 123 wake_room(cur_room, 0, rogue.row, rogue.col); 124 darken_room(cur_room); 125 cur_room = PASSAGE; 126 } else if (dungeon[row][col] & TUNNEL) { 127 light_passage(row, col); 128 } 129 mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col)); 130 mvaddch(row, col, rogue.fchar); 131 132 if (!jump) { 133 refresh(); 134 } 135 rogue.row = row; 136 rogue.col = col; 137 if (dungeon[row][col] & OBJECT) { 138 if (levitate && pickup) { 139 return(STOPPED_ON_SOMETHING); 140 } 141 if (pickup && !levitate) { 142 if (obj = pick_up(row, col, &status)) { 143 get_desc(obj, desc); 144 if (obj->what_is == GOLD) { 145 free_object(obj); 146 goto NOT_IN_PACK; 147 } 148 } else if (!status) { 149 goto MVED; 150 } else { 151 goto MOVE_ON; 152 } 153 } else { 154 MOVE_ON: 155 obj = object_at(&level_objects, row, col); 156 (void) strcpy(desc, "moved onto "); 157 get_desc(obj, desc+11); 158 goto NOT_IN_PACK; 159 } 160 n = strlen(desc); 161 desc[n] = '('; 162 desc[n+1] = obj->ichar; 163 desc[n+2] = ')'; 164 desc[n+3] = 0; 165 NOT_IN_PACK: 166 message(desc, 1); 167 (void) reg_move(); 168 return(STOPPED_ON_SOMETHING); 169 } 170 if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) { 171 if ((!levitate) && (dungeon[row][col] & TRAP)) { 172 trap_player(row, col); 173 } 174 (void) reg_move(); 175 return(STOPPED_ON_SOMETHING); 176 } 177 MVED: if (reg_move()) { /* fainted from hunger */ 178 return(STOPPED_ON_SOMETHING); 179 } 180 return((confused ? STOPPED_ON_SOMETHING : MOVED)); 181 } 182 183 multiple_move_rogue(dirch) 184 short dirch; 185 { 186 short row, col; 187 short m; 188 189 switch(dirch) { 190 case '\010': 191 case '\012': 192 case '\013': 193 case '\014': 194 case '\031': 195 case '\025': 196 case '\016': 197 case '\002': 198 do { 199 row = rogue.row; 200 col = rogue.col; 201 if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) || 202 (m == STOPPED_ON_SOMETHING) || 203 interrupted) { 204 break; 205 } 206 } while (!next_to_something(row, col)); 207 if ( (!interrupted) && passgo && (m == MOVE_FAILED) && 208 (dungeon[rogue.row][rogue.col] & TUNNEL)) { 209 turn_passage(dirch + 96, 0); 210 } 211 break; 212 case 'H': 213 case 'J': 214 case 'K': 215 case 'L': 216 case 'B': 217 case 'Y': 218 case 'U': 219 case 'N': 220 while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) ; 221 222 if ( (!interrupted) && passgo && 223 (dungeon[rogue.row][rogue.col] & TUNNEL)) { 224 turn_passage(dirch + 32, 1); 225 } 226 break; 227 } 228 } 229 230 is_passable(row, col) 231 int row, col; 232 { 233 if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) || 234 (col > (DCOLS-1))) { 235 return(0); 236 } 237 if (dungeon[row][col] & HIDDEN) { 238 return((dungeon[row][col] & TRAP) ? 1 : 0); 239 } 240 return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP)); 241 } 242 243 next_to_something(drow, dcol) 244 int drow, dcol; 245 { 246 short i, j, i_end, j_end, row, col; 247 short pass_count = 0; 248 unsigned short s; 249 250 if (confused) { 251 return(1); 252 } 253 if (blind) { 254 return(0); 255 } 256 i_end = (rogue.row < (DROWS-2)) ? 1 : 0; 257 j_end = (rogue.col < (DCOLS-1)) ? 1 : 0; 258 259 for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) { 260 for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) { 261 if ((i == 0) && (j == 0)) { 262 continue; 263 } 264 if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) { 265 continue; 266 } 267 row = rogue.row + i; 268 col = rogue.col + j; 269 s = dungeon[row][col]; 270 if (s & HIDDEN) { 271 continue; 272 } 273 /* If the rogue used to be right, up, left, down, or right of 274 * row,col, and now isn't, then don't stop */ 275 if (s & (MONSTER | OBJECT | STAIRS)) { 276 if (((row == drow) || (col == dcol)) && 277 (!((row == rogue.row) || (col == rogue.col)))) { 278 continue; 279 } 280 return(1); 281 } 282 if (s & TRAP) { 283 if (!(s & HIDDEN)) { 284 if (((row == drow) || (col == dcol)) && 285 (!((row == rogue.row) || (col == rogue.col)))) { 286 continue; 287 } 288 return(1); 289 } 290 } 291 if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) { 292 if (++pass_count > 1) { 293 return(1); 294 } 295 } 296 if ((s & DOOR) && ((i == 0) || (j == 0))) { 297 return(1); 298 } 299 } 300 } 301 return(0); 302 } 303 304 can_move(row1, col1, row2, col2) 305 { 306 if (!is_passable(row2, col2)) { 307 return(0); 308 } 309 if ((row1 != row2) && (col1 != col2)) { 310 if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) { 311 return(0); 312 } 313 if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) { 314 return(0); 315 } 316 } 317 return(1); 318 } 319 320 move_onto() 321 { 322 short ch, d; 323 boolean first_miss = 1; 324 325 while (!is_direction(ch = rgetchar(), &d)) { 326 sound_bell(); 327 if (first_miss) { 328 message("direction? ", 0); 329 first_miss = 0; 330 } 331 } 332 check_message(); 333 if (ch != CANCEL) { 334 (void) one_move_rogue(ch, 0); 335 } 336 } 337 338 boolean 339 is_direction(c, d) 340 short c; 341 short *d; 342 { 343 switch(c) { 344 case 'h': 345 *d = LEFT; 346 break; 347 case 'j': 348 *d = DOWN; 349 break; 350 case 'k': 351 *d = UPWARD; 352 break; 353 case 'l': 354 *d = RIGHT; 355 break; 356 case 'b': 357 *d = DOWNLEFT; 358 break; 359 case 'y': 360 *d = UPLEFT; 361 break; 362 case 'u': 363 *d = UPRIGHT; 364 break; 365 case 'n': 366 *d = DOWNRIGHT; 367 break; 368 case CANCEL: 369 break; 370 default: 371 return(0); 372 } 373 return(1); 374 } 375 376 boolean 377 check_hunger(msg_only) 378 boolean msg_only; 379 { 380 short i, n; 381 boolean fainted = 0; 382 383 if (rogue.moves_left == HUNGRY) { 384 (void) strcpy(hunger_str, "hungry"); 385 message(hunger_str, 0); 386 print_stats(STAT_HUNGER); 387 } 388 if (rogue.moves_left == WEAK) { 389 (void) strcpy(hunger_str, "weak"); 390 message(hunger_str, 1); 391 print_stats(STAT_HUNGER); 392 } 393 if (rogue.moves_left <= FAINT) { 394 if (rogue.moves_left == FAINT) { 395 (void) strcpy(hunger_str, "faint"); 396 message(hunger_str, 1); 397 print_stats(STAT_HUNGER); 398 } 399 n = get_rand(0, (FAINT - rogue.moves_left)); 400 if (n > 0) { 401 fainted = 1; 402 if (rand_percent(40)) { 403 rogue.moves_left++; 404 } 405 message("you faint", 1); 406 for (i = 0; i < n; i++) { 407 if (coin_toss()) { 408 mv_mons(); 409 } 410 } 411 message(you_can_move_again, 1); 412 } 413 } 414 if (msg_only) { 415 return(fainted); 416 } 417 if (rogue.moves_left <= STARVE) { 418 killed_by((object *) 0, STARVATION); 419 } 420 421 switch(e_rings) { 422 /*case -2: 423 Subtract 0, i.e. do nothing. 424 break;*/ 425 case -1: 426 rogue.moves_left -= (rogue.moves_left % 2); 427 break; 428 case 0: 429 rogue.moves_left--; 430 break; 431 case 1: 432 rogue.moves_left--; 433 (void) check_hunger(1); 434 rogue.moves_left -= (rogue.moves_left % 2); 435 break; 436 case 2: 437 rogue.moves_left--; 438 (void) check_hunger(1); 439 rogue.moves_left--; 440 break; 441 } 442 return(fainted); 443 } 444 445 boolean 446 reg_move() 447 { 448 boolean fainted; 449 450 if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) { 451 fainted = check_hunger(0); 452 } else { 453 fainted = 0; 454 } 455 456 mv_mons(); 457 458 if (++m_moves >= 120) { 459 m_moves = 0; 460 wanderer(); 461 } 462 if (halluc) { 463 if (!(--halluc)) { 464 unhallucinate(); 465 } else { 466 hallucinate(); 467 } 468 } 469 if (blind) { 470 if (!(--blind)) { 471 unblind(); 472 } 473 } 474 if (confused) { 475 if (!(--confused)) { 476 unconfuse(); 477 } 478 } 479 if (bear_trap) { 480 bear_trap--; 481 } 482 if (levitate) { 483 if (!(--levitate)) { 484 message("you float gently to the ground", 1); 485 if (dungeon[rogue.row][rogue.col] & TRAP) { 486 trap_player(rogue.row, rogue.col); 487 } 488 } 489 } 490 if (haste_self) { 491 if (!(--haste_self)) { 492 message("you feel yourself slowing down", 0); 493 } 494 } 495 heal(); 496 if (auto_search > 0) { 497 search(auto_search, auto_search); 498 } 499 return(fainted); 500 } 501 502 rest(count) 503 { 504 int i; 505 506 interrupted = 0; 507 508 for (i = 0; i < count; i++) { 509 if (interrupted) { 510 break; 511 } 512 (void) reg_move(); 513 } 514 } 515 516 gr_dir() 517 { 518 short d; 519 520 d = get_rand(1, 8); 521 522 switch(d) { 523 case 1: 524 d = 'j'; 525 break; 526 case 2: 527 d = 'k'; 528 break; 529 case 3: 530 d = 'l'; 531 break; 532 case 4: 533 d = 'h'; 534 break; 535 case 5: 536 d = 'y'; 537 break; 538 case 6: 539 d = 'u'; 540 break; 541 case 7: 542 d = 'b'; 543 break; 544 case 8: 545 d = 'n'; 546 break; 547 } 548 return(d); 549 } 550 551 heal() 552 { 553 static short heal_exp = -1, n, c = 0; 554 static boolean alt; 555 556 if (rogue.hp_current == rogue.hp_max) { 557 c = 0; 558 return; 559 } 560 if (rogue.exp != heal_exp) { 561 heal_exp = rogue.exp; 562 563 switch(heal_exp) { 564 case 1: 565 n = 20; 566 break; 567 case 2: 568 n = 18; 569 break; 570 case 3: 571 n = 17; 572 break; 573 case 4: 574 n = 14; 575 break; 576 case 5: 577 n = 13; 578 break; 579 case 6: 580 n = 10; 581 break; 582 case 7: 583 n = 9; 584 break; 585 case 8: 586 n = 8; 587 break; 588 case 9: 589 n = 7; 590 break; 591 case 10: 592 n = 4; 593 break; 594 case 11: 595 n = 3; 596 break; 597 case 12: 598 default: 599 n = 2; 600 } 601 } 602 if (++c >= n) { 603 c = 0; 604 rogue.hp_current++; 605 if (alt = !alt) { 606 rogue.hp_current++; 607 } 608 if ((rogue.hp_current += regeneration) > rogue.hp_max) { 609 rogue.hp_current = rogue.hp_max; 610 } 611 print_stats(STAT_HP); 612 } 613 } 614 615 static boolean 616 can_turn(nrow, ncol) 617 short nrow, ncol; 618 { 619 if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) { 620 return(1); 621 } 622 return(0); 623 } 624 625 turn_passage(dir, fast) 626 short dir; 627 boolean fast; 628 { 629 short crow = rogue.row, ccol = rogue.col, turns = 0; 630 short ndir; 631 632 if ((dir != 'h') && can_turn(crow, ccol + 1)) { 633 turns++; 634 ndir = 'l'; 635 } 636 if ((dir != 'l') && can_turn(crow, ccol - 1)) { 637 turns++; 638 ndir = 'h'; 639 } 640 if ((dir != 'k') && can_turn(crow + 1, ccol)) { 641 turns++; 642 ndir = 'j'; 643 } 644 if ((dir != 'j') && can_turn(crow - 1, ccol)) { 645 turns++; 646 ndir = 'k'; 647 } 648 if (turns == 1) { 649 multiple_move_rogue(ndir - (fast ? 32 : 96)); 650 } 651 } 652