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