Annotation of early-roguelike/xrogue/move.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: move.c - Hero movement commands
! 3:
! 4: XRogue: Expeditions into the Dungeons of Doom
! 5: Copyright (C) 1991 Robert Pietkivitch
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 10: All rights reserved.
! 11:
! 12: Based on "Rogue: Exploring the Dungeons of Doom"
! 13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 14: All rights reserved.
! 15:
! 16: See the file LICENSE.TXT for full copyright and licensing information.
! 17: */
! 18:
! 19: #include <curses.h>
! 20: #include <ctype.h>
! 21: #include <string.h>
! 22: #include "rogue.h"
! 23:
! 24: /*
! 25: * Used to hold the new hero position
! 26: */
! 27:
! 28: coord move_nh;
! 29:
! 30: static char Moves[3][3] = {
! 31: { 'y', 'k', 'u' },
! 32: { 'h', '.', 'l' },
! 33: { 'b', 'j', 'n' }
! 34: };
! 35:
! 36: /*
! 37: * be_trapped:
! 38: * The guy stepped on a trap.... Make him pay.
! 39: */
! 40:
! 41: char
! 42: be_trapped(struct thing *th, coord *tc)
! 43: {
! 44: register struct trap *tp;
! 45: register char ch, *mname = NULL;
! 46: register bool is_player = (th == &player),
! 47: can_see;
! 48: register struct linked_list *mitem = NULL;
! 49: register struct thing *mp;
! 50:
! 51:
! 52: /* Can the player see the creature? */
! 53: can_see = cansee(tc->y, tc->x);
! 54: can_see &= (is_player || !invisible(th));
! 55:
! 56: tp = trap_at(tc->y, tc->x);
! 57: /*
! 58: * if he's wearing boots of elvenkind, he won't set off the trap
! 59: * unless its a magic pool (they're not really traps)
! 60: */
! 61: if (is_player &&
! 62: cur_misc[WEAR_BOOTS] != NULL &&
! 63: cur_misc[WEAR_BOOTS]->o_which == MM_ELF_BOOTS &&
! 64: tp->tr_type != POOL)
! 65: return '\0';
! 66:
! 67: /*
! 68: * if the creature is flying then it won't set off the trap
! 69: */
! 70: if (on(*th, ISFLY))
! 71: return '\0';
! 72:
! 73: tp->tr_flags |= ISFOUND;
! 74:
! 75: if (!is_player) {
! 76: mitem = find_mons(th->t_pos.y, th->t_pos.x);
! 77: mname = monster_name(th);
! 78: }
! 79: else {
! 80: count = running = FALSE;
! 81: mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
! 82: }
! 83: switch (ch = tp->tr_type) {
! 84: case TRAPDOOR:
! 85: if (is_player) {
! 86: level++;
! 87: pstats.s_hpt -= roll(1, 10);
! 88: if (pstats.s_hpt < 1) {
! 89: pstats.s_hpt = -1;
! 90: death(D_FALL);
! 91: }
! 92: wclear(cw);
! 93: wclear(mw);
! 94: new_level(NORMLEV);
! 95: msg("You fell through a trap! ");
! 96: }
! 97: else {
! 98: if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
! 99:
! 100: /*
! 101: * See if the fall killed the monster
! 102: * don't let a UNIQUE die since it might have an artifact
! 103: * that we need
! 104: */
! 105: if (off(*th,ISUNIQUE) && (th->t_stats.s_hpt-=roll(1,10)) <= 0){
! 106: killed(mitem, FALSE, FALSE, FALSE);
! 107: }
! 108: else { /* Just move monster to next level */
! 109: check_residue(th);
! 110:
! 111: /* Erase the monster from the old position */
! 112: if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
! 113: mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
! 114: mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
! 115:
! 116: /* let him summon on next lvl */
! 117: if (on (*th, HASSUMMONED)) {
! 118: turn_off(*th, HASSUMMONED);
! 119: turn_on(*th, CANSUMMON);
! 120: }
! 121: turn_on(*th,ISELSEWHERE);
! 122: detach(mlist, mitem);
! 123: attach(tlist, mitem); /* remember him next level */
! 124:
! 125: /* Make sure that no one is still chasing us */
! 126: for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
! 127: mp = THINGPTR(mitem);
! 128: if (mp->t_dest == &th->t_pos) {
! 129: mp->t_dest = &hero;
! 130: mp->t_wasshot = FALSE;
! 131: turn_off(*mp, ISFLEE); /* Don't run away! */
! 132: }
! 133: }
! 134:
! 135: /* Make sure we were not chasing a monster here */
! 136: th->t_dest = &hero;
! 137: if (on(*th, ISFRIENDLY)) turn_off(*th, ISFLEE);
! 138: }
! 139: }
! 140: /* worm hole trap to OUTSIDE */
! 141: when WORMHOLE:
! 142: if (is_player) {
! 143: prev_max = 1000; /* flag used in n_level.c */
! 144: level++;
! 145: pstats.s_hpt -= roll(1, 10);
! 146: if (pstats.s_hpt < 1) {
! 147: pstats.s_hpt = -1;
! 148: death(D_FALL);
! 149: }
! 150: new_level(OUTSIDE);
! 151: msg("You suddenly find yourself in strange surroundings! ");
! 152: return(ch);
! 153: }
! 154: else {
! 155: if (can_see) msg("%s fell into the worm hole! ", prname(mname, TRUE));
! 156:
! 157: /*
! 158: * See if the fall killed the monster
! 159: * don't let a UNIQUE die since it might have an artifact
! 160: * that we need
! 161: */
! 162: if (off(*th,ISUNIQUE) && (th->t_stats.s_hpt-=roll(1,10)) <= 0){
! 163: killed(mitem, FALSE, FALSE, FALSE);
! 164: }
! 165: else { /* Just move monster to next level */
! 166: check_residue(th);
! 167:
! 168: /* Erase the monster from the old position */
! 169: if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
! 170: mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
! 171: mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
! 172:
! 173: /* let him summon on next lvl */
! 174: if (on (*th, HASSUMMONED)) {
! 175: turn_off(*th, HASSUMMONED);
! 176: turn_on(*th, CANSUMMON);
! 177: }
! 178:
! 179: turn_on(*th,ISELSEWHERE);
! 180: detach(mlist, mitem);
! 181: attach(tlist, mitem); /* remember him next level */
! 182:
! 183: /* Make sure that no one is still chasing us */
! 184: for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
! 185: mp = THINGPTR(mitem);
! 186: if (mp->t_dest == &th->t_pos) {
! 187: mp->t_dest = &hero;
! 188: mp->t_wasshot = FALSE;
! 189: turn_off(*mp, ISFLEE); /* Don't run away! */
! 190: }
! 191: }
! 192:
! 193: /* Make sure we were not chasing a monster here */
! 194: th->t_dest = &hero;
! 195: if (on(*th, ISFRIENDLY)) turn_off(*th, ISFLEE);
! 196: }
! 197: }
! 198: when BEARTRAP:
! 199: if (is_stealth(th)) {
! 200: if (is_player) msg("You pass a bear trap.");
! 201: else if (can_see) msg("%s passes a bear trap.",
! 202: prname(mname, TRUE));
! 203: }
! 204: else {
! 205: th->t_no_move += movement(&player) * BEARTIME;
! 206: th->t_action = A_FREEZE;
! 207: if (is_player) msg("You are caught in a bear trap.");
! 208: else if (can_see) msg("%s is caught in a bear trap.",
! 209: prname(mname, TRUE));
! 210: }
! 211: when SLEEPTRAP:
! 212: if (is_player) {
! 213: if (!ISWEARING(R_ALERT)) {
! 214: msg("A strange white mist envelops you. You fall asleep. ");
! 215: player.t_no_move += movement(&player) * SLEEPTIME;
! 216: player.t_action = A_FREEZE;
! 217: }
! 218: else {
! 219: msg("The white mist invigorates you. ");
! 220: }
! 221: }
! 222: else {
! 223: if (can_see)
! 224: msg("A strange white mist envelops %s. ",
! 225: prname(mname, FALSE));
! 226: if (on(*th, ISUNDEAD)) {
! 227: if (can_see)
! 228: msg("The mist doesn't seem to affect %s.",
! 229: prname(mname, FALSE));
! 230: }
! 231: else {
! 232: th->t_no_move += movement(th) * SLEEPTIME;
! 233: th->t_action = A_FREEZE;
! 234: }
! 235: }
! 236: when ARROWTRAP:
! 237: if (swing(th->t_ctype, th->t_stats.s_lvl-1, th->t_stats.s_arm, 1))
! 238: {
! 239: if (is_player) {
! 240: msg("Oh no! An arrow shot you.");
! 241: if ((pstats.s_hpt -= roll(1, 8)) < 1) {
! 242: pstats.s_hpt = -1;
! 243: msg("The arrow killed you. --More--");
! 244: wait_for(' ');
! 245: death(D_ARROW);
! 246: }
! 247: }
! 248: else {
! 249: if (can_see)
! 250: msg("An arrow shot %s.", prname(mname, FALSE));
! 251: if ((th->t_stats.s_hpt -= roll(1, 8)) < 1) {
! 252: if (can_see)
! 253: msg("The arrow killed %s.", prname(mname, FALSE));
! 254: killed(mitem, FALSE, FALSE, TRUE);
! 255: }
! 256: }
! 257: }
! 258: else
! 259: {
! 260: register struct linked_list *item;
! 261: register struct object *arrow;
! 262:
! 263: if (is_player) msg("An arrow shoots past you.");
! 264: else if (can_see)
! 265: msg("An arrow shoots by %s.", prname(mname, FALSE));
! 266: item = new_item(sizeof *arrow);
! 267: arrow = OBJPTR(item);
! 268: arrow->o_type = WEAPON;
! 269: arrow->contents = NULL;
! 270: arrow->o_which = ARROW;
! 271: arrow->o_hplus = rnd(7) - 1;
! 272: arrow->o_dplus = rnd(7) - 1;
! 273: init_weapon(arrow, ARROW);
! 274: arrow->o_count = 1;
! 275: arrow->o_pos = *tc;
! 276: arrow->o_mark[0] = '\0';
! 277: fall(item, FALSE);
! 278: }
! 279: when TELTRAP:
! 280: if (is_player) teleport();
! 281: else {
! 282: register int rm;
! 283: struct room *old_room; /* old room of monster */
! 284:
! 285: /*
! 286: * Erase the monster from the old position
! 287: */
! 288: if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
! 289: mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
! 290: mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
! 291: /*
! 292: * check to see if room should go dark
! 293: */
! 294: if (on(*th, HASFIRE)) {
! 295: old_room=roomin(&th->t_pos);
! 296: if (old_room != NULL) {
! 297: register struct linked_list *fire_item;
! 298:
! 299: for (fire_item = old_room->r_fires; fire_item != NULL;
! 300: fire_item = next(fire_item)) {
! 301: if (THINGPTR(fire_item) == th) {
! 302: detach(old_room->r_fires, fire_item);
! 303: destroy_item(fire_item);
! 304:
! 305: if (old_room->r_fires == NULL) {
! 306: old_room->r_flags &= ~HASFIRE;
! 307: if (can_see) light(&hero);
! 308: }
! 309: }
! 310: }
! 311: }
! 312: }
! 313:
! 314: /* Get a new position */
! 315: do {
! 316: rm = rnd_room();
! 317: rnd_pos(&rooms[rm], &th->t_pos);
! 318: } until(winat(th->t_pos.y, th->t_pos.x) == FLOOR);
! 319:
! 320: /* Put it there */
! 321: mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
! 322: th->t_oldch = mvwinch(cw, th->t_pos.y, th->t_pos.x);
! 323: /*
! 324: * check to see if room that creature appears in should
! 325: * light up
! 326: */
! 327: if (on(*th, HASFIRE)) {
! 328: register struct linked_list *fire_item;
! 329:
! 330: fire_item = creat_item();
! 331: ldata(fire_item) = (char *) th;
! 332: attach(rooms[rm].r_fires, fire_item);
! 333:
! 334: rooms[rm].r_flags |= HASFIRE;
! 335: if(cansee(th->t_pos.y, th->t_pos.x) &&
! 336: next(rooms[rm].r_fires) == NULL)
! 337: light(&hero);
! 338: }
! 339: if (can_see)
! 340: msg("%s seems to have disappeared!", prname(mname, TRUE));
! 341: }
! 342: when DARTTRAP:
! 343: if (swing(th->t_ctype, th->t_stats.s_lvl+1, th->t_stats.s_arm, 1)) {
! 344: if (is_player) {
! 345: msg("A small dart just hit you. ");
! 346: if ((pstats.s_hpt -= roll(1, 8)) < 1) {
! 347: pstats.s_hpt = -1;
! 348: msg("The dart killed you.");
! 349: wait_for(' ');
! 350: death(D_DART);
! 351: }
! 352:
! 353: /* Now the poison */
! 354: if (!save(VS_POISON, &player, 0)) {
! 355: /* 75% chance it will do point damage - else strength */
! 356: if (rnd(100) < 75) {
! 357: pstats.s_hpt /= 2;
! 358: if (pstats.s_hpt < 1) {
! 359: pstats.s_hpt = -1;
! 360: death(D_POISON);
! 361: }
! 362: }
! 363: else if (!ISWEARING(R_SUSABILITY))
! 364: chg_str(-1);
! 365: }
! 366: }
! 367: else {
! 368: if (can_see)
! 369: msg("A small dart stabs the %s. ",
! 370: prname(mname, FALSE));
! 371: if ((th->t_stats.s_hpt -= roll(1,8)) < 1) {
! 372: if (can_see)
! 373: msg("The dart killed %s.", prname(mname, FALSE));
! 374: killed(mitem, FALSE, FALSE, TRUE);
! 375: }
! 376: if (!save(VS_POISON, th, 0)) {
! 377: th->t_stats.s_hpt /= 2 + level;
! 378: if (th->t_stats.s_hpt < 1) {
! 379: if (can_see)
! 380: msg("The dart killed %s.", prname(mname,FALSE));
! 381: killed(mitem, FALSE, FALSE, TRUE);
! 382: }
! 383: }
! 384: }
! 385: }
! 386: else {
! 387: if (is_player)
! 388: msg("A small dart whizzes by your ear and vanishes.");
! 389: else if (can_see)
! 390: msg("A small dart whizzes by %s's ear and vanishes.",
! 391: prname(mname, FALSE));
! 392: }
! 393: when POOL: {
! 394: register int i;
! 395:
! 396: i = rnd(100);
! 397: if (is_player) {
! 398: if ((tp->tr_flags & ISGONE)) {
! 399: if (i < 56) {
! 400: teleport(); /* teleport away */
! 401: pool_teleport = TRUE;
! 402: }
! 403: else if((i < 72) && level > 4) {
! 404: level -= rnd(4) + 1;
! 405: cur_max = level;
! 406: new_level(NORMLEV);
! 407: pool_teleport = TRUE;
! 408: msg("You here a faint groan from below.");
! 409: }
! 410: else if(i < 85) {
! 411: level += rnd(4) + 1;
! 412: new_level(NORMLEV);
! 413: pool_teleport = TRUE;
! 414: msg("You find yourself in strange surroundings.");
! 415: }
! 416: else if(i > 96) {
! 417: msg("Oh no!!! You drown in the pool!!! --More--");
! 418: wait_for(' ');
! 419: pstats.s_hpt = -1;
! 420: death(D_DROWN);
! 421: }
! 422: else {
! 423: new_level(NORMLEV);
! 424: pool_teleport = TRUE;
! 425: msg("You are whisked away to another region.");
! 426: }
! 427: }
! 428: }
! 429: else {
! 430: if (i < 60) {
! 431: if (can_see) {
! 432: /* Drowns */
! 433: if (i < 50)
! 434: msg("%s drowned in the pool!", prname(mname, TRUE));
! 435:
! 436: /* Teleported to another level */
! 437: else msg("%s disappeared!", prname(mname, TRUE));
! 438: }
! 439: killed(mitem, FALSE, FALSE, TRUE);
! 440: }
! 441: }
! 442: }
! 443: when MAZETRAP:
! 444: if (is_player) {
! 445: pstats.s_hpt -= roll(1, 10);
! 446: level++;
! 447: if (pstats.s_hpt < 1) {
! 448: pstats.s_hpt = -1;
! 449: death(D_FALL);
! 450: }
! 451: wclear(cw);
! 452: wclear(mw);
! 453: new_level(MAZELEV);
! 454: msg("You are surrounded by twisty passages! ");
! 455: }
! 456: else {
! 457: if (can_see) msg("%s fell into a maze trap!", prname(mname, TRUE));
! 458: if (on(*th, ISUNIQUE)) {
! 459: check_residue(th);
! 460:
! 461: /* Erase the monster from the old position */
! 462: if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
! 463: mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
! 464: mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
! 465:
! 466: /* let him summon on next lvl */
! 467: if (on (*th, HASSUMMONED)) {
! 468: turn_off(*th, HASSUMMONED);
! 469: turn_on(*th, CANSUMMON);
! 470: }
! 471: turn_on(*th,ISELSEWHERE);
! 472: detach(mlist, mitem);
! 473: attach(tlist, mitem); /* remember him next level */
! 474:
! 475: /* Make sure that no one is still chasing us */
! 476: for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
! 477: mp = THINGPTR(mitem);
! 478: if (mp->t_dest == &th->t_pos) {
! 479: mp->t_dest = &hero;
! 480: mp->t_wasshot = FALSE;
! 481: turn_off(*mp, ISFLEE); /* Don't run away! */
! 482: }
! 483: }
! 484:
! 485: /* Make sure we were not chasing a monster here */
! 486: th->t_dest = &hero;
! 487: if (on(*th, ISFRIENDLY)) turn_off(*th, ISFLEE);
! 488: }
! 489: else
! 490: killed(mitem, FALSE, FALSE, FALSE);
! 491: }
! 492: }
! 493:
! 494: /* Move the cursor back onto the hero */
! 495: wmove(cw, hero.y, hero.x);
! 496:
! 497: flushinp();
! 498: return(ch);
! 499: }
! 500:
! 501: /*
! 502: * blue_light:
! 503: * magically light up a room (or level or make it dark)
! 504: */
! 505:
! 506: bool
! 507: blue_light(bool blessed, bool cursed)
! 508: {
! 509: register struct room *rp;
! 510: bool ret_val=FALSE; /* Whether or not affect is known */
! 511:
! 512: rp = roomin(&hero); /* What room is hero in? */
! 513:
! 514: /* Darken the room if the magic is cursed */
! 515: if (cursed) {
! 516: if ((rp == NULL) || !lit_room(rp)) msg(nothing);
! 517: else {
! 518: rp->r_flags |= ISDARK;
! 519: if (!lit_room(rp) && (levtype != OUTSIDE || !daytime) &&
! 520: !ISWEARING(R_LIGHT))
! 521: msg("The %s suddenly goes dark.",
! 522: levtype == OUTSIDE ? "area" : "room");
! 523: else msg(nothing);
! 524: ret_val = TRUE;
! 525: }
! 526: }
! 527: else {
! 528: ret_val = TRUE;
! 529: if (rp && !lit_room(rp) &&
! 530: (levtype != OUTSIDE || !daytime)) {
! 531: addmsg("The %s is lit", levtype == OUTSIDE ? "area" : "room");
! 532: addmsg(" by a %s blue light.", blessed ? "bright" : "shimmering");
! 533: endmsg();
! 534: }
! 535: else if (winat(hero.y, hero.x) == PASSAGE)
! 536: msg("The corridor glows %sand then fades",
! 537: blessed ? "brightly " : "");
! 538: else {
! 539: ret_val = FALSE;
! 540: msg(nothing);
! 541: }
! 542: if (blessed) {
! 543: register int i; /* Index through rooms */
! 544:
! 545: for (i=0; i<MAXROOMS; i++)
! 546: rooms[i].r_flags &= ~ISDARK;
! 547: }
! 548: else if (rp) rp->r_flags &= ~ISDARK;
! 549: }
! 550:
! 551: /*
! 552: * Light the room and put the player back up
! 553: */
! 554: light(&hero);
! 555: mvwaddch(cw, hero.y, hero.x, PLAYER);
! 556: return(ret_val);
! 557: }
! 558:
! 559: /*
! 560: * corr_move:
! 561: * Check to see that a move is legal. If so, return correct character.
! 562: * If not, if player came from a legal place, then try to turn him.
! 563: */
! 564:
! 565: void
! 566: corr_move(int dy, int dx)
! 567: {
! 568: int legal=0; /* Number of legal alternatives */
! 569: register int y, x, /* Indexes though possible positions */
! 570: locy = 0, locx = 0; /* Hold delta of chosen location */
! 571:
! 572: /* New position */
! 573: move_nh.y = hero.y + dy;
! 574: move_nh.x = hero.x + dx;
! 575:
! 576: /* If it is a legal move, just return */
! 577: if (move_nh.x >= 0 && move_nh.x < cols && move_nh.y > 0 && move_nh.y < lines - 2) {
! 578:
! 579: switch (winat(move_nh.y, move_nh.x)) {
! 580: case WALL:
! 581: case VERTWALL:
! 582: case HORZWALL:
! 583: break;
! 584: default:
! 585: if (diag_ok(&hero, &move_nh, &player))
! 586: return;
! 587: }
! 588: }
! 589:
! 590: /* Check legal places surrounding the player -- ignore previous position */
! 591: for (y = hero.y - 1; y <= hero.y + 1; y++) {
! 592: if (y < 1 || y > lines - 3)
! 593: continue;
! 594: for (x = hero.x - 1; x <= hero.x + 1; x++) {
! 595: /* Ignore borders of the screen */
! 596: if (x < 0 || x > cols - 1)
! 597: continue;
! 598:
! 599: /*
! 600: * Ignore where we came from, where we are, and where we couldn't go
! 601: */
! 602: if ((x == hero.x - dx && y == hero.y - dy) ||
! 603: (x == hero.x + dx && y == hero.y + dy) ||
! 604: (x == hero.x && y == hero.y))
! 605: continue;
! 606:
! 607: switch (winat(y, x)) {
! 608: case WALL:
! 609: case VERTWALL:
! 610: case HORZWALL:
! 611: break;
! 612: default:
! 613: move_nh.y = y;
! 614: move_nh.x = x;
! 615: if (diag_ok(&hero, &move_nh, &player)) {
! 616: legal++;
! 617: locy = y - (hero.y - 1);
! 618: locx = x - (hero.x - 1);
! 619: }
! 620: }
! 621: }
! 622: }
! 623:
! 624: /* If we have 2 or more legal moves, make no change */
! 625: if (legal != 1) {
! 626: return;
! 627: }
! 628:
! 629: runch = Moves[locy][locx];
! 630:
! 631: /*
! 632: * For mazes, pretend like it is the beginning of a new run at each turn
! 633: * in order to get the lighting correct.
! 634: */
! 635: if (levtype == MAZELEV) firstmove = TRUE;
! 636: return;
! 637: }
! 638:
! 639: /*
! 640: * dip_it:
! 641: * Dip an object into a magic pool
! 642: */
! 643:
! 644: void
! 645: dip_it(void)
! 646: {
! 647: reg struct linked_list *what;
! 648: reg struct object *ob;
! 649: reg struct trap *tp;
! 650: reg int wh, i;
! 651:
! 652: tp = trap_at(hero.y,hero.x);
! 653: if (tp == NULL || tp->tr_type != POOL) {
! 654: msg("I see no shimmering pool here");
! 655: return;
! 656: }
! 657: if (tp->tr_flags & ISGONE) {
! 658: msg("This shimmering pool appears to have been used once already.");
! 659: return;
! 660: }
! 661:
! 662: /* It takes 3 movement periods to dip something */
! 663: if (player.t_action != C_DIP) {
! 664: if ((what = get_item(pack, "dip", ALL, FALSE, FALSE)) == NULL) {
! 665: msg("");
! 666: after = FALSE;
! 667: return;
! 668: }
! 669:
! 670: ob = OBJPTR(what);
! 671: if (ob == cur_armor ||
! 672: ob == cur_misc[WEAR_BOOTS] ||
! 673: ob == cur_misc[WEAR_JEWEL] ||
! 674: ob == cur_misc[WEAR_GAUNTLET] ||
! 675: ob == cur_misc[WEAR_CLOAK] ||
! 676: ob == cur_misc[WEAR_BRACERS] ||
! 677: ob == cur_misc[WEAR_NECKLACE] ||
! 678: ob == cur_ring[LEFT_1] || ob == cur_ring[LEFT_2] ||
! 679: ob == cur_ring[LEFT_3] || ob == cur_ring[LEFT_4] ||
! 680: ob == cur_ring[RIGHT_1] || ob == cur_ring[RIGHT_2] ||
! 681: ob == cur_ring[RIGHT_3] || ob == cur_ring[RIGHT_4]) {
! 682: mpos = 0;
! 683: msg("You'll have to take it off first.");
! 684: return;
! 685: }
! 686:
! 687: player.t_using = what; /* Remember what it is */
! 688: player.t_action = C_DIP; /* We are dipping */
! 689: player.t_no_move = 3 * movement(&player);
! 690: return;
! 691: }
! 692:
! 693: /* We have waited our time, let's dip it */
! 694: what = player.t_using;
! 695: player.t_using = NULL;
! 696: player.t_action = A_NIL;
! 697:
! 698: ob = OBJPTR(what);
! 699:
! 700: tp->tr_flags |= ISGONE;
! 701: if (ob != NULL) {
! 702: wh = ob->o_which;
! 703: ob->o_flags |= ISKNOW;
! 704: i = rnd(100);
! 705: if (ob->o_group != 0)
! 706: ob->o_group = newgrp(); /* change the group */
! 707: switch(ob->o_type) {
! 708: case WEAPON:
! 709: if(i < 60) { /* enchant weapon here */
! 710: if ((ob->o_flags & ISCURSED) == 0) {
! 711: ob->o_hplus += 1;
! 712: ob->o_dplus += 1;
! 713: }
! 714: else { /* weapon was prev cursed here */
! 715: ob->o_hplus = rnd(2);
! 716: ob->o_dplus = rnd(2);
! 717: }
! 718: ob->o_flags &= ~ISCURSED;
! 719: msg("The %s glows blue for a moment.",weaps[wh].w_name);
! 720: }
! 721: else if(i < 75) { /* curse weapon here */
! 722: if ((ob->o_flags & ISCURSED) == 0) {
! 723: ob->o_hplus = -(rnd(2)+1);
! 724: ob->o_dplus = -(rnd(2)+1);
! 725: }
! 726: else { /* if already cursed */
! 727: ob->o_hplus--;
! 728: ob->o_dplus--;
! 729: }
! 730: ob->o_flags |= ISCURSED;
! 731: msg("The %s glows red for a moment.",weaps[wh].w_name);
! 732: }
! 733: else
! 734: msg(nothing);
! 735: when ARMOR:
! 736: if (i < 60) { /* enchant armor */
! 737: if((ob->o_flags & ISCURSED) == 0)
! 738: ob->o_ac -= rnd(2) + 1;
! 739: else
! 740: ob->o_ac = -rnd(3)+ armors[wh].a_class;
! 741: ob->o_flags &= ~ISCURSED;
! 742: msg("The %s glows blue for a moment",armors[wh].a_name);
! 743: }
! 744: else if(i < 75){ /* curse armor */
! 745: if ((ob->o_flags & ISCURSED) == 0)
! 746: ob->o_ac = rnd(3)+ armors[wh].a_class;
! 747: else
! 748: ob->o_ac += rnd(2) + 1;
! 749: ob->o_flags |= ISCURSED;
! 750: msg("The %s glows red for a moment.",armors[wh].a_name);
! 751: }
! 752: else
! 753: msg(nothing);
! 754: when STICK: {
! 755: int j;
! 756: j = rnd(14) + 1;
! 757: if(i < 60) { /* add charges */
! 758: ob->o_charges += j;
! 759: ws_know[wh] = TRUE;
! 760: if (ob->o_flags & ISCURSED)
! 761: ob->o_flags &= ~ISCURSED;
! 762: msg("The %s %s glows blue for a moment.",
! 763: ws_made[wh],ws_type[wh]);
! 764: }
! 765: else if(i < 75) { /* remove charges */
! 766: if ((ob->o_charges -= i) < 0)
! 767: ob->o_charges = 0;
! 768: ws_know[wh] = TRUE;
! 769: if (ob->o_flags & ISBLESSED)
! 770: ob->o_flags &= ~ISBLESSED;
! 771: else
! 772: ob->o_flags |= ISCURSED;
! 773: msg("The %s %s glows red for a moment.",
! 774: ws_made[wh],ws_type[wh]);
! 775: }
! 776: else
! 777: msg(nothing);
! 778: }
! 779: when SCROLL:
! 780: s_know[wh] = TRUE;
! 781: msg("The '%s' scroll unfurls.",s_names[wh]);
! 782: when POTION:
! 783: p_know[wh] = TRUE;
! 784: msg("The %s potion bubbles for a moment.. ",p_colors[wh]);
! 785: when RING:
! 786: if(i < 60) { /* enchant ring */
! 787: if ((ob->o_flags & ISCURSED) == 0)
! 788: ob->o_ac += rnd(2) + 1;
! 789: else
! 790: ob->o_ac = rnd(2) + 1;
! 791: ob->o_flags &= ~ISCURSED;
! 792: }
! 793: else if(i < 75) { /* curse ring */
! 794: if ((ob->o_flags & ISCURSED) == 0)
! 795: ob->o_ac = -(rnd(2) + 1);
! 796: else
! 797: ob->o_ac -= (rnd(2) + 1);
! 798: ob->o_flags |= ISCURSED;
! 799: }
! 800: r_know[wh] = TRUE;
! 801: msg("The %s ring vibrates for a moment.",r_stones[wh]);
! 802: when MM:
! 803: m_know[wh] = TRUE;
! 804: switch (ob->o_which) {
! 805: case MM_BRACERS:
! 806: case MM_PROTECT:
! 807: if(i < 60) { /* enchant item */
! 808: if ((ob->o_flags & ISCURSED) == 0)
! 809: ob->o_ac += rnd(2) + 1;
! 810: else
! 811: ob->o_ac = rnd(2) + 1;
! 812: ob->o_flags &= ~ISCURSED;
! 813: }
! 814: else if(i < 75) { /* curse item */
! 815: if ((ob->o_flags & ISCURSED) == 0)
! 816: ob->o_ac = -(rnd(2) + 1);
! 817: else
! 818: ob->o_ac -= (rnd(2) + 1);
! 819: ob->o_flags |= ISCURSED;
! 820: }
! 821: msg("The item vibrates for a moment.");
! 822: when MM_CHOKE:
! 823: case MM_DISAPPEAR:
! 824: ob->o_ac = 0;
! 825: msg ("The dust dissolves in the pool!");
! 826: }
! 827: otherwise:
! 828: msg("The pool bubbles up for a moment.. ");
! 829: }
! 830: updpack(FALSE, &player);
! 831: }
! 832: else
! 833: msg(nothing);
! 834: }
! 835:
! 836: /*
! 837: * do_move:
! 838: * Check to see that a move is legal. If it is handle the
! 839: * consequences (fighting, picking up, etc.)
! 840: */
! 841:
! 842: void
! 843: do_move(int dy, int dx)
! 844: {
! 845: register struct room *rp, *orp;
! 846: register unsigned char ch;
! 847: struct linked_list *item;
! 848: register struct thing *tp = NULL;
! 849: coord old_hero;
! 850: register int wasfirstmove, moved, num_hits;
! 851: bool changed=FALSE; /* Did we switch places with a friendly monster? */
! 852:
! 853: wasfirstmove = firstmove;
! 854: firstmove = FALSE;
! 855: curprice = -1; /* if in trading post, we've moved off obj */
! 856:
! 857: /*
! 858: * Do a confused move (maybe)
! 859: */
! 860: if (player.t_action == A_NIL &&
! 861: ((on(player, ISHUH) && rnd(100) < 80) ||
! 862: (on(player, ISDANCE) && rnd(100) < 90) ||
! 863: (ISWEARING(R_DELUSION) && rnd(100) < 70)))
! 864: {
! 865: /* Get a random move */
! 866: move_nh = rndmove(&player);
! 867: dy = move_nh.y - hero.y;
! 868: dx = move_nh.x - hero.x;
! 869: }
! 870: else {
! 871: move_nh.y = hero.y + dy;
! 872: move_nh.x = hero.x + dx;
! 873: }
! 874:
! 875: /*
! 876: * Check if he tried to move off the screen or make an illegal
! 877: * diagonal move, and stop him if he did.
! 878: */
! 879: if (move_nh.x < 0 || move_nh.x > cols-1 || move_nh.y < 1 || move_nh.y >= lines - 2
! 880: || !diag_ok(&hero, &move_nh, &player))
! 881: {
! 882: after = running = FALSE;
! 883: player.t_action = A_NIL;
! 884: return;
! 885: }
! 886: if (running && ce(hero, move_nh))
! 887: after = running = FALSE;
! 888: ch = winat(move_nh.y, move_nh.x);
! 889:
! 890: /* Take care of hero trying to move close to something frightening */
! 891: if (on(player, ISFLEE)) {
! 892: if (rnd(100) < 12) {
! 893: turn_off(player, ISFLEE);
! 894: msg("You regain your composure.");
! 895: }
! 896: else if (DISTANCE(move_nh.y, move_nh.x, player.t_dest->y, player.t_dest->x) <
! 897: DISTANCE(hero.y, hero.x, player.t_dest->y, player.t_dest->x)) {
! 898: running = FALSE;
! 899: msg("You are too terrified to move that way");
! 900: player.t_action = A_NIL;
! 901: player.t_no_move = movement(&player);
! 902: return;
! 903: }
! 904: }
! 905:
! 906: /* If we want to move to a monster, see what it is */
! 907: if (isalpha(ch)) {
! 908: item = find_mons(move_nh.y, move_nh.x);
! 909: if (item == NULL) {
! 910: debug("Cannot find monster in move.");
! 911: player.t_action = A_NIL;
! 912: return;
! 913: }
! 914: tp = THINGPTR(item);
! 915: }
! 916:
! 917: /*
! 918: * Take care of hero being held. If the player is being held, he
! 919: * can't move unless he is either attacking a non-friendly monster
! 920: * or attacking a friendly monster that can't move.
! 921: */
! 922: if (on(player, ISHELD) &&
! 923: (!isalpha(ch) || (on(*tp, ISFRIENDLY) && off(*tp, ISHELD)))) {
! 924: msg("You are being held.");
! 925: player.t_action = A_NIL;
! 926: return;
! 927: }
! 928:
! 929: /* See if we have to wait for our movement rate */
! 930: if (player.t_action == A_NIL) {
! 931: after = FALSE;
! 932: firstmove = wasfirstmove; /* Remember if this is first move */
! 933: player.t_no_move = movement(&player);
! 934: if (player.t_ctype == C_MONK)
! 935: player.t_no_move -= pstats.s_lvl/6;
! 936: if (on(player, ISFLY))
! 937: player.t_no_move /= 2; /* If flying, speed him up */
! 938:
! 939: if (player.t_no_move < 1) player.t_no_move = 1;
! 940:
! 941: /* Remember our action */
! 942: player.t_action = Moves[dy+1][dx+1];
! 943: return;
! 944: }
! 945:
! 946: /* Now let's forget the old move and just do it */
! 947: player.t_action = A_NIL;
! 948:
! 949: /* If we're moving onto a friendly monster, let's change places. */
! 950: if (isalpha(ch) && on(*tp, ISFRIENDLY) && off(*tp, ISHELD)) {
! 951: coord tpos, /* Where monster may have been going */
! 952: current; /* Current hero position */
! 953: int action; /* The monster's action */
! 954:
! 955: current = hero;
! 956: tpos = tp->t_newpos;
! 957: action = tp->t_action;
! 958:
! 959: /* Disrupt whatever our friend was doing */
! 960: tp->t_action = A_NIL;
! 961:
! 962: /* Tentatively move us to where he is */
! 963: hero = tp->t_pos;
! 964:
! 965: /* See if we can move him to where we were */
! 966: tp->t_newpos = current;
! 967: do_chase(tp);
! 968:
! 969: /* Did we succeed? */
! 970: if (ce(tp->t_pos, current)) {
! 971: /* Reset our idea of what ch is */
! 972: ch = winat(move_nh.y, move_nh.x);
! 973:
! 974: /* Let it be known that we made the switch */
! 975: changed = TRUE;
! 976: old_hero = current;
! 977:
! 978: /* Make the monster think it didn't move */
! 979: tp->t_oldpos = current;
! 980: tp->t_doorgoal.x = tp->t_doorgoal.y = -1;
! 981:
! 982: /* Let the player know something funny happened. */
! 983: msg("What a sidestep!");
! 984: }
! 985: else {
! 986: /* Restore things -- we couldn't move */
! 987: hero = current;
! 988: tp->t_newpos = tpos;
! 989: tp->t_action = action;
! 990: }
! 991: }
! 992:
! 993: /* assume he's not in a wall */
! 994: if (!isalpha(ch)) turn_off(player, ISINWALL);
! 995:
! 996: switch (ch) {
! 997: case VERTWALL:
! 998: case HORZWALL:
! 999: if (levtype == OUTSIDE) {
! 1000: hero = move_nh;
! 1001: new_level(OUTSIDE);
! 1002: return;
! 1003: }
! 1004: case WALL:
! 1005: case SECRETDOOR:
! 1006: if (off(player, CANINWALL) || running) {
! 1007: after = running = FALSE;
! 1008:
! 1009: /* Light if finishing run */
! 1010: if (levtype == MAZELEV && lit_room(&rooms[0]))
! 1011: look(FALSE, TRUE);
! 1012:
! 1013: after = running = FALSE;
! 1014:
! 1015: return;
! 1016: }
! 1017: turn_on(player, ISINWALL);
! 1018: break;
! 1019: case POOL:
! 1020: if (levtype == OUTSIDE) {
! 1021: /* lake_check(&move_nh); */ /* not implemented yet */
! 1022: running = FALSE;
! 1023: break;
! 1024: }
! 1025: case MAZETRAP:
! 1026: if (levtype == OUTSIDE) {
! 1027: running = FALSE;
! 1028: break;
! 1029: }
! 1030: case TRAPDOOR:
! 1031: case TELTRAP:
! 1032: case BEARTRAP:
! 1033: case SLEEPTRAP:
! 1034: case ARROWTRAP:
! 1035: case DARTTRAP:
! 1036: case WORMHOLE:
! 1037: ch = be_trapped(&player, &move_nh);
! 1038: if (ch == TRAPDOOR || ch == TELTRAP ||
! 1039: pool_teleport || ch == MAZETRAP) {
! 1040: pool_teleport = FALSE;
! 1041: return;
! 1042: }
! 1043: break;
! 1044: case GOLD:
! 1045: case POTION:
! 1046: case SCROLL:
! 1047: case FOOD:
! 1048: case WEAPON:
! 1049: case ARMOR:
! 1050: case RING:
! 1051: case MM:
! 1052: case RELIC:
! 1053: case STICK:
! 1054: running = FALSE;
! 1055: take = ch;
! 1056: break;
! 1057: case DOOR:
! 1058: case STAIRS:
! 1059: case POST:
! 1060: running = FALSE;
! 1061: break;
! 1062: default:
! 1063: break;
! 1064: }
! 1065:
! 1066: if (isalpha(ch)) { /* if its a monster then fight it */
! 1067: /*
! 1068: * If we were running down a corridor and didn't start right
! 1069: * next to the critter, don't do anything.
! 1070: */
! 1071: if (running && wasfirstmove == FALSE && roomin(&hero) == NULL) {
! 1072: struct linked_list *item;
! 1073:
! 1074: item = find_mons(move_nh.y, move_nh.x);
! 1075: if (item != NULL && !invisible(THINGPTR(item))) {
! 1076: after = running = FALSE;
! 1077: return;
! 1078: }
! 1079: }
! 1080:
! 1081: /* We have to add time because we're attacking */
! 1082: player.t_no_move = FIGHTBASE;
! 1083: player.t_no_move += weap_move(&player, cur_weapon);
! 1084: if (on(player, ISHASTE))
! 1085: player.t_no_move /= 2;
! 1086: else if (on(player, ISSLOW))
! 1087: player.t_no_move *= 2;
! 1088:
! 1089: /* We may attack faster if we're high enough level
! 1090: * and the right class
! 1091: */
! 1092: switch(player.t_ctype) {
! 1093: case C_FIGHTER: num_hits = player.t_stats.s_lvl/25 + 1;
! 1094: when C_PALADIN: num_hits = player.t_stats.s_lvl/35 + 1;
! 1095: when C_RANGER: num_hits = player.t_stats.s_lvl/35 + 1;
! 1096: when C_MONK: if(cur_weapon) num_hits = player.t_stats.s_lvl/40 + 1;
! 1097: else num_hits = player.t_stats.s_lvl/30 + 1;
! 1098: otherwise: num_hits = player.t_stats.s_lvl/60 + 1;
! 1099: }
! 1100:
! 1101: /*
! 1102: * The player has already moved the initial movement period.
! 1103: * Let's add that in, do our division, and then subtract it
! 1104: * out so that the total time is divided, not just the
! 1105: * additional attack time.
! 1106: */
! 1107: moved = movement(&player),
! 1108: player.t_no_move += moved;
! 1109: player.t_no_move /= num_hits;
! 1110: player.t_no_move -= moved;
! 1111: running = FALSE;
! 1112:
! 1113: /* Mark that we are attacking and save the attack coordinate */
! 1114: player.t_action = A_ATTACK;
! 1115: player.t_newpos = move_nh;
! 1116: runch = Moves[dy+1][dx+1]; /* Remember the direction */
! 1117:
! 1118: if (player.t_no_move <= 0) after = FALSE;
! 1119: return;
! 1120: }
! 1121:
! 1122: /*
! 1123: * if not fighting then move the hero
! 1124: */
! 1125: if (changed == FALSE) {
! 1126: old_hero = hero; /* Save hero's old position */
! 1127: hero = move_nh; /* Move the hero */
! 1128: }
! 1129: rp = roomin(&hero);
! 1130: orp = roomin(&old_hero);
! 1131:
! 1132: /* Unlight any possible cross-corridor */
! 1133: if (levtype == MAZELEV) {
! 1134: register bool call_light = FALSE;
! 1135: register unsigned char wall_check;
! 1136:
! 1137: if (wasfirstmove && lit_room(&rooms[0])) {
! 1138: /* Are we moving out of a corridor? */
! 1139: switch (runch) {
! 1140: case 'h':
! 1141: case 'l':
! 1142: if (old_hero.y + 1 < lines - 2) {
! 1143: wall_check = winat(old_hero.y + 1, old_hero.x);
! 1144: if (!isrock(wall_check)) call_light = TRUE;
! 1145: }
! 1146: if (old_hero.y - 1 > 0) {
! 1147: wall_check = winat(old_hero.y - 1, old_hero.x);
! 1148: if (!isrock(wall_check)) call_light = TRUE;
! 1149: }
! 1150: break;
! 1151: case 'j':
! 1152: case 'k':
! 1153: if (old_hero.x + 1 < cols) {
! 1154: wall_check = winat(old_hero.y, old_hero.x + 1);
! 1155: if (!isrock(wall_check)) call_light = TRUE;
! 1156: }
! 1157: if (old_hero.x - 1 >= 0) {
! 1158: wall_check = winat(old_hero.y, old_hero.x - 1);
! 1159: if (!isrock(wall_check)) call_light = TRUE;
! 1160: }
! 1161: break;
! 1162: default:
! 1163: call_light = TRUE;
! 1164: }
! 1165: player.t_oldpos = old_hero;
! 1166: if (call_light) light(&old_hero);
! 1167: }
! 1168: }
! 1169:
! 1170: else if (orp != NULL && rp == NULL) { /* Leaving a room -- darken it */
! 1171: orp->r_flags |= FORCEDARK; /* Fake darkness */
! 1172: light(&old_hero);
! 1173: orp->r_flags &= ~FORCEDARK; /* Restore light state */
! 1174: }
! 1175: else if (rp != NULL && orp == NULL){/* Entering a room */
! 1176: light(&hero);
! 1177: if (rp->r_flags & ISTREAS)
! 1178: wake_room(rp);
! 1179: }
! 1180: ch = winat(old_hero.y, old_hero.x);
! 1181: wmove(cw, unc(old_hero));
! 1182: waddch(cw, ch);
! 1183: wmove(cw, unc(hero));
! 1184: waddch(cw, PLAYER);
! 1185: }
! 1186:
! 1187: /*
! 1188: * do_run:
! 1189: * Start the hero running
! 1190: */
! 1191:
! 1192: void
! 1193: do_run(char ch)
! 1194: {
! 1195: firstmove = TRUE;
! 1196: running = TRUE;
! 1197: after = FALSE;
! 1198: runch = ch;
! 1199: }
! 1200:
! 1201: /*
! 1202: * getdelta:
! 1203: * Takes a movement character (eg. h, j, k, l) and returns the
! 1204: * y and x delta corresponding to it in the remaining arguments.
! 1205: * Returns TRUE if it could find it, FALSE otherwise.
! 1206: */
! 1207:
! 1208: bool
! 1209: getdelta(char match, int *dy, int *dx)
! 1210: {
! 1211: register int y, x;
! 1212:
! 1213: for (y = 0; y < 3; y++)
! 1214: for (x = 0; x < 3; x++)
! 1215: if (Moves[y][x] == match) {
! 1216: *dy = y - 1;
! 1217: *dx = x - 1;
! 1218: return(TRUE);
! 1219: }
! 1220:
! 1221: return(FALSE);
! 1222: }
! 1223:
! 1224: /*
! 1225: * isatrap:
! 1226: * Returns TRUE if this character is some kind of trap
! 1227: */
! 1228:
! 1229: bool
! 1230: isatrap(char ch)
! 1231: {
! 1232: switch(ch) {
! 1233: case WORMHOLE:
! 1234: case DARTTRAP:
! 1235: case TELTRAP:
! 1236: case TRAPDOOR:
! 1237: case ARROWTRAP:
! 1238: case SLEEPTRAP:
! 1239: case BEARTRAP: return(TRUE);
! 1240: case MAZETRAP:
! 1241: case POOL: return(levtype != OUTSIDE);
! 1242: default: return(FALSE);
! 1243: }
! 1244: }
! 1245:
! 1246: /*
! 1247: * Called to illuminate a room.
! 1248: * If it is dark, remove anything that might move.
! 1249: */
! 1250:
! 1251: void
! 1252: light(coord *cp)
! 1253: {
! 1254: register struct room *rp;
! 1255: register int j, k, x, y;
! 1256: register unsigned char ch, rch, sch;
! 1257: register struct linked_list *item;
! 1258: int jlow, jhigh, klow, khigh; /* Boundaries of lit area */
! 1259:
! 1260: if ((rp = roomin(cp)) != NULL) {
! 1261: /*
! 1262: * is he wearing ring of illumination?
! 1263: */
! 1264: if (&hero == cp && ISWEARING(R_LIGHT)) /* Must be hero's room */
! 1265: rp->r_flags &= ~ISDARK;
! 1266:
! 1267: /* If we are in a maze, don't look at the whole room (level) */
! 1268: if (levtype == MAZELEV) {
! 1269: int see_radius;
! 1270:
! 1271: see_radius = 1;
! 1272:
! 1273: /* If we are looking at the hero in a rock, broaden our sights */
! 1274: if (&hero == cp || &player.t_oldpos == cp) {
! 1275: ch = winat(hero.y, hero.x);
! 1276: if (isrock(ch)) see_radius = 2;
! 1277: ch = winat(player.t_oldpos.y, player.t_oldpos.x);
! 1278: if (isrock(ch)) see_radius = 2;
! 1279: }
! 1280:
! 1281: jlow = max(0, cp->y - see_radius - rp->r_pos.y);
! 1282: jhigh = min(rp->r_max.y, cp->y + see_radius + 1 - rp->r_pos.y);
! 1283: klow = max(0, cp->x - see_radius - rp->r_pos.x);
! 1284: khigh = min(rp->r_max.x, cp->x + see_radius + 1 - rp->r_pos.x);
! 1285: }
! 1286: else {
! 1287: jlow = klow = 0;
! 1288: jhigh = rp->r_max.y;
! 1289: khigh = rp->r_max.x;
! 1290: }
! 1291: for (j = 0; j < rp->r_max.y; j++)
! 1292: {
! 1293: for (k = 0; k < rp->r_max.x; k++)
! 1294: {
! 1295: bool see_here = 0, see_before = 0;
! 1296:
! 1297: /* Is this in the give area -- needed for maze */
! 1298: if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh))
! 1299: continue;
! 1300:
! 1301: y = rp->r_pos.y + j;
! 1302: x = rp->r_pos.x + k;
! 1303:
! 1304: /*
! 1305: * If we are in a maze do not look at this area unless
! 1306: * we can see it from where we are or where we last were
! 1307: * (for erasing purposes).
! 1308: */
! 1309: if (levtype == MAZELEV) {
! 1310: /* If we can't see it from here, could we see it before? */
! 1311: if ((see_here = maze_view(y, x)) == FALSE) {
! 1312: coord savhero;
! 1313:
! 1314: /* Could we see it from where we were? */
! 1315: savhero = hero;
! 1316: hero = player.t_oldpos;
! 1317: see_before = maze_view(y, x);
! 1318: hero = savhero;
! 1319:
! 1320: if (!see_before) continue;
! 1321: }
! 1322: }
! 1323:
! 1324: ch = show(y, x);
! 1325: wmove(cw, y, x);
! 1326: /*
! 1327: * Figure out how to display a secret door
! 1328: */
! 1329: if (ch == SECRETDOOR) {
! 1330: if (j == 0 || j == rp->r_max.y - 1)
! 1331: ch = HORZWALL;
! 1332: else
! 1333: ch = VERTWALL;
! 1334: }
! 1335: /* For monsters, if they were previously not seen and
! 1336: * now can be seen, or vice-versa, make sure that will
! 1337: * happen. This is for dark rooms as opposed to invisibility.
! 1338: *
! 1339: * Call winat() in the test because ch will not reveal
! 1340: * invisible monsters.
! 1341: */
! 1342: if (isalpha(winat(y, x))) {
! 1343: struct thing *tp; /* The monster */
! 1344:
! 1345: item = wake_monster(y, x);
! 1346: tp = THINGPTR(item);
! 1347:
! 1348: /* Previously not seen -- now can see it */
! 1349: if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x))
! 1350: tp->t_oldch = mvinch(y, x);
! 1351:
! 1352: /* Previously seen -- now can't see it */
! 1353: else if (!cansee(tp->t_pos.y, tp->t_pos.x) &&
! 1354: roomin(&tp->t_pos) != NULL)
! 1355: switch (tp->t_oldch) {
! 1356: /*
! 1357: * Only blank it out if it is in a room and not
! 1358: * the border (or other wall) of the room.
! 1359: */
! 1360: case DOOR:
! 1361: case SECRETDOOR:
! 1362: case HORZWALL:
! 1363: case VERTWALL:
! 1364: break;
! 1365:
! 1366: otherwise:
! 1367: tp->t_oldch = ' ';
! 1368: }
! 1369: }
! 1370:
! 1371: /*
! 1372: * If the room is a dark room, we might want to remove
! 1373: * monsters and the like from it (since they might
! 1374: * move).
! 1375: * A dark room.
! 1376: */
! 1377: if ((!lit_room(rp) && (levtype != OUTSIDE)) ||
! 1378: (levtype == OUTSIDE && !daytime) ||
! 1379: on(player, ISBLIND) ||
! 1380: (rp->r_flags & FORCEDARK) ||
! 1381: (levtype == MAZELEV && !see_here && see_before)) {
! 1382: sch = mvwinch(cw, y, x); /* What's seen */
! 1383: rch = mvinch(y, x); /* What's really there */
! 1384: switch (rch) {
! 1385: case DOOR:
! 1386: case SECRETDOOR:
! 1387: case STAIRS:
! 1388: case TRAPDOOR:
! 1389: case WORMHOLE:
! 1390: case TELTRAP:
! 1391: case BEARTRAP:
! 1392: case SLEEPTRAP:
! 1393: case ARROWTRAP:
! 1394: case DARTTRAP:
! 1395: case MAZETRAP:
! 1396: case POOL:
! 1397: case POST:
! 1398: case VERTWALL:
! 1399: case HORZWALL:
! 1400: case WALL:
! 1401: if (isalpha(sch)) ch = rch;
! 1402: else if (sch != FLOOR) ch = sch;
! 1403: else ch = ' '; /* Hide undiscoverd things */
! 1404: when FLOOR:
! 1405: ch = ' ';
! 1406: otherwise:
! 1407: ch = ' ';
! 1408: }
! 1409: /* Take care of our magic bookkeeping. */
! 1410: switch (sch) {
! 1411: case MAGIC:
! 1412: case BMAGIC:
! 1413: case CMAGIC:
! 1414: ch = sch;
! 1415: }
! 1416: }
! 1417: mvwaddch(cw, y, x, ch);
! 1418: }
! 1419: }
! 1420: }
! 1421: }
! 1422:
! 1423: /*
! 1424: * lit_room:
! 1425: * Called to see if the specified room is lit up or not.
! 1426: */
! 1427:
! 1428: bool
! 1429: lit_room(struct room *rp)
! 1430: {
! 1431: register struct linked_list *fire_item;
! 1432: register struct thing *fire_creature;
! 1433:
! 1434: if (!(rp->r_flags & ISDARK)) return(TRUE); /* A definitely lit room */
! 1435:
! 1436: /* Is it lit by fire light? */
! 1437: if (rp->r_flags & HASFIRE) {
! 1438: switch ((int)levtype) {
! 1439: case MAZELEV:
! 1440: /* See if a fire creature is in line of sight */
! 1441: for (fire_item = rp->r_fires; fire_item != NULL;
! 1442: fire_item = next(fire_item)) {
! 1443: fire_creature = THINGPTR(fire_item);
! 1444: if (maze_view(fire_creature->t_pos.y,
! 1445: fire_creature->t_pos.x)) return(TRUE);
! 1446: }
! 1447:
! 1448: /* Couldn't find any in line-of-sight */
! 1449: return(FALSE);
! 1450:
! 1451: /* We should probably do something special for the outside */
! 1452: otherwise:
! 1453: return TRUE;
! 1454: }
! 1455: }
! 1456: return(FALSE);
! 1457: }
! 1458:
! 1459: /*
! 1460: * movement:
! 1461: * Given a pointer to a player/monster structure, calculate the
! 1462: * movement rate for that character.
! 1463: */
! 1464:
! 1465: short
! 1466: movement(struct thing *tp)
! 1467: {
! 1468: register int result;
! 1469: register int carry; /* Percentage carried */
! 1470:
! 1471: result = 0;
! 1472:
! 1473: /* Adjust for armor (player only) */
! 1474: if (tp == &player && cur_armor) {
! 1475: int diff; /* Now armor class differs from normal one of same type */
! 1476:
! 1477: /* Blessed armor adds less */
! 1478: diff = cur_armor->o_ac - armors[cur_armor->o_which].a_class;
! 1479: switch (cur_armor->o_which) {
! 1480: case LEATHER:
! 1481: case RING_MAIL:
! 1482: case CHAIN_MAIL:
! 1483: case SCALE_MAIL:
! 1484: case PADDED_ARMOR:
! 1485: diff += 1;
! 1486: when STUDDED_LEATHER:
! 1487: case SPLINT_MAIL:
! 1488: case BANDED_MAIL:
! 1489: case PLATE_MAIL:
! 1490: diff += 2;
! 1491: when PLATE_ARMOR:
! 1492: diff += 3;
! 1493: otherwise:
! 1494: debug("forgot an armor in movement()");
! 1495: }
! 1496: if (diff < 0) diff = 0;
! 1497: result += diff;
! 1498:
! 1499: }
! 1500:
! 1501: /* Adjust for the pack */
! 1502: carry = 100 * tp->t_stats.s_pack / tp->t_stats.s_carry;
! 1503: if (carry > 75) result++;
! 1504:
! 1505: /* Get a bonus for dexterity */
! 1506: result -= dext_plus(tp == &player ? dex_compute() : tp->t_stats.s_dext);
! 1507:
! 1508: /* only allow adjust for the minus's */
! 1509: if (result < 0) result = 0;
! 1510: result += tp->t_movement; /* now add in movement rate */
! 1511:
! 1512: /* Is the character slowed? */
! 1513: if (on(*tp, ISSLOW) || on(*tp, ISDANCE)) result *= 2;
! 1514:
! 1515: /* Is the character hasted? */
! 1516: if (on(*tp, ISHASTE)) result /= 2;
! 1517:
! 1518: /* We have a minimum of 1 */
! 1519: if (result < 1) result = 1;
! 1520:
! 1521: return(result);
! 1522: }
! 1523:
! 1524: /*
! 1525: * rndmove:
! 1526: * move in a random direction if the monster/person is confused
! 1527: */
! 1528:
! 1529: coord
! 1530: rndmove(struct thing *who)
! 1531: {
! 1532: register int x, y;
! 1533: register int ex, ey, nopen = 0;
! 1534: coord ret; /* what we will be returning */
! 1535: coord dest;
! 1536:
! 1537: ret = who->t_pos;
! 1538: /*
! 1539: * Now go through the spaces surrounding the player and
! 1540: * set that place in the array to true if the space can be
! 1541: * moved into
! 1542: */
! 1543: ey = ret.y + 1;
! 1544: ex = ret.x + 1;
! 1545: for (y = who->t_pos.y - 1; y <= ey; y++)
! 1546: if (y > 0 && y < lines - 2)
! 1547: for (x = who->t_pos.x - 1; x <= ex; x++)
! 1548: {
! 1549: if (x < 0 || x >= cols)
! 1550: continue;
! 1551: if (step_ok(y, x, NOMONST, who) == TRUE)
! 1552: {
! 1553: dest.y = y;
! 1554: dest.x = x;
! 1555: if (!diag_ok(&who->t_pos, &dest, who))
! 1556: continue;
! 1557: if (rnd(++nopen) == 0)
! 1558: ret = dest;
! 1559: }
! 1560: }
! 1561: return ret;
! 1562: }
! 1563:
! 1564: #define TRAPTYPES 9 /* 9 total trap types that can be set */
! 1565: #define WIZARDTRAPS 3 /* Only wizards can set the last 3 */
! 1566: /* CTRL(C) to level 400 for POST level */
! 1567: static const char *trap_types[TRAPTYPES] = {
! 1568: "Trap Door",
! 1569: "Bear Trap",
! 1570: "Sleep Trap",
! 1571: "Arrow Trap",
! 1572: "Teleport Trap",
! 1573: "Dart Trap",
! 1574: "Magic pool",
! 1575: "Maze Trap",
! 1576: "Worm Hole"
! 1577: };
! 1578:
! 1579: /*
! 1580: * set_trap:
! 1581: * set a trap at (y, x) on screen.
! 1582: */
! 1583:
! 1584: void
! 1585: set_trap(struct thing *tp, int y, int x)
! 1586: {
! 1587: register bool is_player = (tp == &player);
! 1588: register int selection = rnd(TRAPTYPES-WIZARDTRAPS) + '1';
! 1589: register int i, num_traps;
! 1590: register unsigned char ch = 0, och;
! 1591: int thief_bonus = 0;
! 1592: int s_dext;
! 1593:
! 1594: /* let wizard in on this too */
! 1595: if (wizard) goto can_traps;
! 1596: if (is_player && player.t_ctype != C_THIEF && player.t_ctype !=C_ASSASSIN) {
! 1597: msg("Only thieves and assassins can set traps. ");
! 1598: return;
! 1599: }
! 1600: can_traps:
! 1601: switch (och = mvinch(y, x)) {
! 1602: case WALL:
! 1603: case FLOOR:
! 1604: case PASSAGE:
! 1605: break;
! 1606: default:
! 1607: if (is_player) msg("The trap failed!");
! 1608: return;
! 1609: }
! 1610:
! 1611: if (is_player) {
! 1612: int state = 0, /* 0 -> current screen, 1 -> prompt screen, 2 -> done */
! 1613: units; /* Number of movement units for the given trap */
! 1614:
! 1615: if (player.t_action == C_SETTRAP) {
! 1616: selection = player.t_selection;
! 1617: player.t_selection = 0;
! 1618: player.t_action = A_NIL;
! 1619: }
! 1620: else {
! 1621: msg("Which kind of trap do you wish to set? (* for a list): ");
! 1622: num_traps = TRAPTYPES - (wizard ? 0 : WIZARDTRAPS);
! 1623: do {
! 1624: selection = wgetch(cw);
! 1625: switch (selection) {
! 1626: case '*':
! 1627: if (state != 1) {
! 1628: wclear(hw);
! 1629: touchwin(hw);
! 1630: for (i=0; i<num_traps; i++) {
! 1631: wmove(hw, i+2, 0);
! 1632: wprintw(hw, "[%d] %s", i+1, trap_types[i]);
! 1633: }
! 1634: mvwaddstr(hw, 0, 0,
! 1635: "Which kind of trap do you wish to set? ");
! 1636:
! 1637: if (menu_overlay)
! 1638: /*
! 1639: * Put out the selection. The longest line is
! 1640: * the prompt line (39 characters long).
! 1641: */
! 1642: over_win(cw, hw, num_traps + 3, 41, 0, 39, '\0');
! 1643: else
! 1644: draw(hw);
! 1645: state = 1; /* Now in prompt window */
! 1646: }
! 1647: break;
! 1648:
! 1649: case ESC:
! 1650: if (state == 1) {
! 1651: clearok(cw, FALSE);
! 1652: touchwin(cw);
! 1653: }
! 1654: msg("");
! 1655:
! 1656: trap_tries--; /* Don't count this one */
! 1657: after = FALSE;
! 1658: return;
! 1659:
! 1660: case '1':
! 1661: case '2':
! 1662: case '3':
! 1663: case '4':
! 1664: case '5':
! 1665: case '6':
! 1666: case '7':
! 1667: case '8':
! 1668: case '9':
! 1669: if (selection < '7' || wizard) {
! 1670: if (state == 1) { /* In prompt window */
! 1671: clearok(cw, FALSE); /* Set up for redraw */
! 1672: touchwin(cw);
! 1673: }
! 1674:
! 1675: msg("");
! 1676:
! 1677: /*
! 1678: * Make sure there is a floor below us for trap
! 1679: * doors.
! 1680: */
! 1681: if (selection == '1' && level >= nfloors) {
! 1682: if (state == 1) draw(cw);
! 1683: msg("There is no level below this one.");
! 1684: return;
! 1685: }
! 1686: state = 2; /* Finished */
! 1687: break;
! 1688: }
! 1689:
! 1690: /* Fall through for non-wizard, unusual trap case */
! 1691: default:
! 1692: if (state == 1) { /* In the prompt window */
! 1693: wmove(hw, 0, 0);
! 1694: wprintw(hw,
! 1695: "Please enter a selection between 1 and %d: ",
! 1696: num_traps);
! 1697: if (menu_overlay)
! 1698: /*
! 1699: * Put out the selection. The longest line is
! 1700: * the prompt line (43 characters long).
! 1701: */
! 1702: over_win(cw, hw, num_traps+3, 45, 0, 43, '\0');
! 1703: else
! 1704: draw(hw);
! 1705: }
! 1706: else { /* Normal window */
! 1707: mpos = 0;
! 1708: msg("Please enter a selection between 1 and %d: ",
! 1709: num_traps);
! 1710: }
! 1711: }
! 1712: } while (state != 2);
! 1713:
! 1714: player.t_selection = selection;
! 1715:
! 1716: switch (selection) {
! 1717: case '1': units = 10; /* Trap door */
! 1718: when '2': units = 5; /* Bear trap */
! 1719: when '3': units = 7; /* Sleeping gas trap */
! 1720: when '4': units = 5; /* Arrow trap */
! 1721: when '5': units = 10; /* Teleport trap */
! 1722: when '6': units = 7; /* Dart trap */
! 1723: otherwise: units = 5; /* Unknown trap */
! 1724: }
! 1725: player.t_no_move = units * movement(&player);
! 1726: player.t_action = C_SETTRAP;
! 1727: return;
! 1728: }
! 1729: }
! 1730:
! 1731: if (is_player && player.t_ctype == C_THIEF) thief_bonus = 20;
! 1732: if (is_player && player.t_ctype == C_ASSASSIN) thief_bonus = 15;
! 1733: if (is_player && player.t_ctype == C_FIGHTER) thief_bonus = 10;
! 1734:
! 1735: s_dext = (tp == &player) ? dex_compute() : tp->t_stats.s_dext;
! 1736:
! 1737: if (ntraps >= MAXTRAPS || ++trap_tries >= MAXTRPTRY ||
! 1738: levtype == POSTLEV || levtype == OUTSIDE ||
! 1739: rnd(80) >= (s_dext + tp->t_stats.s_lvl/2 + thief_bonus)) {
! 1740: if (is_player) msg("The trap failed!");
! 1741: return;
! 1742: }
! 1743:
! 1744: switch (selection) {
! 1745: case '1': ch = TRAPDOOR;
! 1746: when '2': ch = BEARTRAP;
! 1747: when '3': ch = SLEEPTRAP;
! 1748: when '4': ch = ARROWTRAP;
! 1749: when '5': ch = TELTRAP;
! 1750: when '6': ch = DARTTRAP;
! 1751: when '7': ch = POOL;
! 1752: when '8': ch = MAZETRAP;
! 1753: when '9': ch = WORMHOLE;
! 1754: }
! 1755:
! 1756: mvaddch(y, x, ch);
! 1757: traps[ntraps].tr_show = och;
! 1758: traps[ntraps].tr_type = ch;
! 1759: traps[ntraps].tr_pos.y = y;
! 1760: traps[ntraps].tr_pos.x = x;
! 1761: if (is_player)
! 1762: traps[ntraps].tr_flags = ISTHIEFSET;
! 1763: if (ch == POOL || ch == POST) {
! 1764: traps[ntraps].tr_flags |= ISFOUND;
! 1765: }
! 1766:
! 1767: ntraps++;
! 1768: }
! 1769:
! 1770: /*
! 1771: * show:
! 1772: * returns what a certain thing will display as to the un-initiated
! 1773: */
! 1774:
! 1775: char
! 1776: show(int y, int x)
! 1777: {
! 1778: register unsigned char ch = winat(y, x);
! 1779: register struct linked_list *it;
! 1780: register struct thing *tp;
! 1781:
! 1782: if (isatrap(ch)) {
! 1783: register struct trap *trp = trap_at(y, x);
! 1784:
! 1785: return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
! 1786: }
! 1787: else if (isalpha(ch)) {
! 1788: if ((it = find_mons(y, x)) == NULL) {
! 1789: msg("Show: Can't find monster in show (%d, %d)", y, x);
! 1790: return(mvwinch(stdscr, y, x));
! 1791: }
! 1792: tp = THINGPTR(it);
! 1793:
! 1794: if (on(*tp, ISDISGUISE)) ch = tp->t_disguise; /* As a mimic */
! 1795:
! 1796: /* Hide invisible creatures */
! 1797: else if (invisible(tp)) {
! 1798: /* We can't see surprise-type creatures through "see invisible" */
! 1799: if (off(player,CANSEE) || on(*tp,CANSURPRISE))
! 1800: ch = mvwinch(stdscr, y, x); /* Invisible */
! 1801: }
! 1802: else if (on(*tp, CANINWALL)) {
! 1803: if (isrock(mvwinch(stdscr, y, x))) ch = winch(stdscr); /* As Xorn */
! 1804: }
! 1805: }
! 1806: return ch;
! 1807: }
! 1808:
! 1809:
! 1810: /*
! 1811: * trap_at:
! 1812: * find the trap at (y,x) on screen.
! 1813: */
! 1814:
! 1815: struct trap *
! 1816: trap_at(int y, int x)
! 1817: {
! 1818: register struct trap *tp, *ep;
! 1819:
! 1820: ep = &traps[ntraps];
! 1821: for (tp = traps; tp < ep; tp++)
! 1822: if (tp->tr_pos.y == y && tp->tr_pos.x == x)
! 1823: break;
! 1824: if (tp == ep)
! 1825: debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
! 1826: return tp;
! 1827: }
! 1828:
! 1829: /*
! 1830: * weap_move:
! 1831: * Calculate how many segments it will take to swing the given
! 1832: * weapon (note that the weapon may actually be a stick or
! 1833: * even something else).
! 1834: * wielder: Who's wielding the weapon
! 1835: * weap: The weapon
! 1836: */
! 1837:
! 1838: int
! 1839: weap_move(struct thing *wielder, struct object *weap)
! 1840: {
! 1841: register int weap_rate;
! 1842: int dexterity;
! 1843: int strength;
! 1844:
! 1845: if (weap == NULL) return(1); /* hand, claw, bite attacks are quick */
! 1846:
! 1847: switch (weap->o_type) {
! 1848: case STICK:
! 1849: if (EQUAL(ws_type[weap->o_which], "staff"))
! 1850: weap_rate = 2;
! 1851: else weap_rate = 1; /* A wand */
! 1852:
! 1853: when WEAPON:
! 1854: weap_rate = weaps[weap->o_which].w_rate;
! 1855:
! 1856: /* Adjust for blessed or cursed weapon */
! 1857: if (weap->o_hplus < 0) /* Cursed */
! 1858: weap_rate -= (weap->o_hplus - 2) / 3;
! 1859: else if (weap_rate > 0) /* Blessed */
! 1860: weap_rate -= (2*weap->o_hplus + weap_rate - 1) / weap_rate;
! 1861:
! 1862: when RELIC:
! 1863: switch (weap->o_which) {
! 1864: case MUSTY_DAGGER:
! 1865: case HRUGGEK_MSTAR:
! 1866: case AXE_AKLAD:
! 1867: case YEENOGHU_FLAIL:
! 1868: case MING_STAFF:
! 1869: case ORCUS_WAND:
! 1870: case ASMO_ROD:
! 1871: /* These operate in the blink of an eye */
! 1872: weap_rate = 1;
! 1873: otherwise:
! 1874: /* What is it? */
! 1875: weap_rate = 10;
! 1876: debug("unknown weapon in weap_move()");
! 1877: }
! 1878: otherwise:
! 1879: /* What is it? */
! 1880: weap_rate = 10;
! 1881: debug("unknown weapon in weap_move()");
! 1882: }
! 1883:
! 1884: /* Put in a dexterity bonus */
! 1885: if (wielder == &player) dexterity = dex_compute();
! 1886: else dexterity = wielder->t_stats.s_dext;
! 1887: weap_rate -= dext_plus(dexterity) / 2;
! 1888:
! 1889: /* Put in a strength bonus */
! 1890: if (wielder == &player) strength = str_compute();
! 1891: else strength = wielder->t_stats.s_str;
! 1892: weap_rate -= str_plus(strength) / 2;
! 1893:
! 1894: /* It can't speed you up and it must take SOME time */
! 1895: if (weap_rate <= 0) weap_rate = 1;
! 1896:
! 1897: /* Do we need to adjust for fast/slow movement? */
! 1898: if (on(*wielder, ISSLOW) || on(*wielder, ISDANCE)) weap_rate *= 2;
! 1899: if (on(*wielder, ISHASTE)) weap_rate /= 2;
! 1900:
! 1901: /* Return the result */
! 1902: return(weap_rate);
! 1903: }
! 1904:
CVSweb