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