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: }