Annotation of early-roguelike/urogue/sticks.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: sticks.c - Functions to implement the various sticks one might find
! 3:
! 4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
! 5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
! 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 <limits.h>
! 20: #include <string.h>
! 21: #include <ctype.h>
! 22: #include "rogue.h"
! 23:
! 24: /* for WS_HIT, WS_WEB, etc */
! 25:
! 26: static struct object null_stick =
! 27: {
! 28: {0,0},NULL,NULL,"",0,"0d0",0,0,'X',0,0,0,0,0,0,0,0,0,{0}
! 29: };
! 30:
! 31: /*
! 32: * Mask for cancelling special abilities The flags listed here will be the
! 33: * ones left on after the cancellation takes place
! 34: */
! 35:
! 36: #define CANC0MASK ( ISBLIND | ISINWALL | ISRUN | \
! 37: ISFLEE | ISMEAN | ISGREED | \
! 38: CANSHOOT | ISHELD | ISHUH | \
! 39: ISSLOW | ISHASTE | ISCLEAR | \
! 40: ISUNIQUE)
! 41:
! 42: #define CANC1MASK ( HASDISEASE | DIDSUFFOCATE | CARRYGOLD | \
! 43: HASITCH | CANSELL | CANBBURN | \
! 44: CANSPEAK | CANFLY | ISFRIENDLY)
! 45:
! 46: #define CANC2MASK ( HASINFEST | NOMOVE | ISSCAVENGE | \
! 47: DOROT | HASSTINK | DIDHOLD)
! 48:
! 49: #define CANC3MASK ( ISUNDEAD | CANBREATHE | CANCAST | \
! 50: HASOXYGEN)
! 51:
! 52: #define CANC4MASK ( CANTRAMPLE | CANSWIM | CANWIELD | \
! 53: ISFAST | CANBARGAIN | CANSPORE | \
! 54: ISLARGE | ISSMALL | ISFLOCK | \
! 55: ISSWARM | CANSTICK | CANTANGLE | \
! 56: SHOOTNEEDLE | CANZAP | HASARMOR | \
! 57: CANTELEPORT | ISBERSERK | ISFAMILIAR | \
! 58: HASFAMILIAR | SUMMONING)
! 59:
! 60: #define CANC5MASK ( CANREFLECT | MAGICATTRACT | HASSHIELD | HASMSHIELD)
! 61:
! 62: #define CANC6MASK ( 0 )
! 63: #define CANC7MASK ( 0 )
! 64: #define CANC8MASK ( 0 )
! 65: #define CANC9MASK ( 0 )
! 66: #define CANCAMASK ( 0 )
! 67: #define CANCBMASK ( 0 )
! 68: #define CANCCMASK ( 0 )
! 69: #define CANCDMASK ( 0 )
! 70: #define CANCEMASK ( 0 )
! 71: #define CANCFMASK ( 0 )
! 72:
! 73: void
! 74: fix_stick(struct object *cur)
! 75: {
! 76: if (strcmp(ws_type[cur->o_which], "staff") == 0)
! 77: {
! 78: cur->o_weight = 100;
! 79: cur->o_charges = 5 + rnd(10);
! 80: cur->o_damage = "2d3";
! 81:
! 82: switch (cur->o_which)
! 83: {
! 84: case WS_HIT:
! 85: cur->o_hplus = 3;
! 86: cur->o_dplus = 3;
! 87: cur->o_damage = "2d8";
! 88: break;
! 89:
! 90: case WS_LIGHT:
! 91: cur->o_charges = 20 + rnd(10);
! 92: break;
! 93: }
! 94: }
! 95: else /* A wand */
! 96: {
! 97: cur->o_damage = "1d3";
! 98: cur->o_weight = 60;
! 99: cur->o_charges = 3 + rnd(5);
! 100:
! 101: switch (cur->o_which)
! 102: {
! 103: case WS_HIT:
! 104: cur->o_hplus = 3;
! 105: cur->o_dplus = 3;
! 106: cur->o_damage = "1d8";
! 107: break;
! 108:
! 109: case WS_LIGHT:
! 110: cur->o_charges = 10 + rnd(10);
! 111: break;
! 112: }
! 113: }
! 114:
! 115: cur->o_hurldmg = "1d1";
! 116: }
! 117:
! 118: /*
! 119: do_zap()
! 120: zap a stick (or effect a stick-like spell)
! 121: zapper: who does it
! 122: got_dir: need to ask for direction?
! 123: which: which WS_STICK (-1 means ask from pack)
! 124: flags: ISBLESSED, ISCURSED
! 125: */
! 126:
! 127: void
! 128: do_zap(struct thing *zapper, int which, unsigned long flags)
! 129: {
! 130: struct linked_list *item = NULL, *nitem;
! 131: struct object *obj, *nobj;
! 132: struct room *rp;
! 133: struct thing *tp = NULL;
! 134: char *mname = NULL;
! 135: int y, x;
! 136: int blessed = flags & ISBLESSED;
! 137: int cursed = flags & ISCURSED;
! 138: int is_stick = (which < 0 ? TRUE : FALSE);
! 139: int got_one = TRUE;
! 140:
! 141: if (zapper != &player)
! 142: {
! 143: monster_do_zap(zapper, which, flags);
! 144: return;
! 145: }
! 146:
! 147: if (is_stick)
! 148: {
! 149: if ((obj = get_object(pack, "zap with", 0, bff_zappable)) == NULL)
! 150: return;
! 151:
! 152: if (obj->o_type != STICK && !(obj->o_flags & ISZAPPED))
! 153: {
! 154: msg("You can't zap with that!");
! 155: return;
! 156: }
! 157:
! 158: if (obj->o_type != STICK) /* an electrified weapon */
! 159: which = WS_ELECT;
! 160: else
! 161: which = obj->o_which;
! 162:
! 163: if (obj->o_charges < 1)
! 164: {
! 165: nothing_message(flags);
! 166: return;
! 167: }
! 168:
! 169: obj->o_charges--;
! 170:
! 171: if (delta.y == 0 && delta.x == 0)
! 172: do
! 173: {
! 174: delta.y = rnd(3) - 1;
! 175: delta.x = rnd(3) - 1;
! 176: }
! 177: while (delta.y == 0 && delta.x == 0);
! 178:
! 179: flags = obj->o_flags;
! 180: cursed = obj->o_flags & ISCURSED;
! 181: blessed = obj->o_flags & ISBLESSED;
! 182: }
! 183: else
! 184: obj = &null_stick;
! 185:
! 186: /* Find out who the target is */
! 187:
! 188: y = hero.y;
! 189: x = hero.x;
! 190:
! 191: while(shoot_ok(CCHAR(winat(y, x))))
! 192: {
! 193: y += delta.y;
! 194: x += delta.x;
! 195: }
! 196:
! 197: if (x >= 0 && x < COLS && y >= 1 && y < LINES - 2 &&
! 198: isalpha(mvwinch(mw, y, x)))
! 199: {
! 200: item = find_mons(y, x);
! 201: tp = THINGPTR(item);
! 202: mname = on(player, ISBLIND) ? "monster" :
! 203: monsters[tp->t_index].m_name;
! 204:
! 205: if (on(*tp, CANSELL))
! 206: {
! 207: luck++;
! 208: aggravate();
! 209: }
! 210: }
! 211: else
! 212: got_one = FALSE;
! 213:
! 214: debug("Zapping with %d", which);
! 215:
! 216: switch(which)
! 217: {
! 218: case WS_LIGHT:
! 219: /* Reddy Kilowat wand. Light up the room */
! 220: if (blue_light(flags) && is_stick)
! 221: if (is_stick)
! 222: know_items[TYP_STICK][WS_LIGHT] = TRUE;
! 223: break;
! 224:
! 225: case WS_DRAIN:
! 226:
! 227: /*
! 228: * Take away 1/2 of hero's hit points, then take it away
! 229: * evenly from the monsters in the room or next to hero if he
! 230: * is in a passage. Leave the monsters alone if the stick is
! 231: * cursed. Drain 1/3rd of hero's hit points if blessed.
! 232: */
! 233:
! 234: if (pstats.s_hpt < 2)
! 235: {
! 236: death(D_DRAINLIFE);
! 237: return;
! 238: }
! 239:
! 240: if (cursed)
! 241: pstats.s_hpt /= 2;
! 242: else if ((rp = roomin(hero)) == NULL)
! 243: drain(hero.y - 1, hero.y + 1, hero.x - 1, hero.x + 1);
! 244: else
! 245: drain(rp->r_pos.y, rp->r_pos.y + rp->r_max.y,
! 246: rp->r_pos.x, rp->r_pos.x + rp->r_max.x);
! 247:
! 248: if (blessed)
! 249: pstats.s_hpt = (int) (pstats.s_hpt * 2.0 / 3.0);
! 250:
! 251: break;
! 252:
! 253: case WS_POLYMORPH:
! 254: case WS_MONSTELEP:
! 255: case WS_CANCEL:
! 256: {
! 257: char oldch;
! 258: int rm;
! 259: int save_adj = 0;
! 260:
! 261: if (got_one)
! 262: {
! 263: /* if the monster gets the saving throw, leave the case */
! 264:
! 265: if (blessed)
! 266: save_adj = -5;
! 267:
! 268: if (cursed)
! 269: if (which == WS_POLYMORPH)
! 270: save_adj = -5; /* not save vs becoming tougher */
! 271: else
! 272: save_adj = 5;
! 273:
! 274: if (save_throw(VS_MAGIC - save_adj, tp))
! 275: {
! 276: nothing_message(flags);
! 277: break;
! 278: }
! 279: else if (is_stick)
! 280: know_items[TYP_STICK][which] = TRUE;
! 281:
! 282: /* Unhold player */
! 283:
! 284: if (on(*tp, DIDHOLD))
! 285: {
! 286: turn_off(*tp, DIDHOLD);
! 287:
! 288: if (--hold_count == 0)
! 289: turn_off(player, ISHELD);
! 290: }
! 291:
! 292: /* unsuffocate player */
! 293:
! 294: if (on(*tp, DIDSUFFOCATE))
! 295: {
! 296: turn_off(*tp, DIDSUFFOCATE);
! 297: extinguish_fuse(FUSE_SUFFOCATE);
! 298: }
! 299:
! 300: if (which == WS_POLYMORPH)
! 301: {
! 302: int which_new;
! 303: int charmed;
! 304:
! 305: detach(mlist, item);
! 306: charmed = on(*tp, ISCHARMED);
! 307: oldch = tp->t_oldch;
! 308: delta.y = y;
! 309: delta.x = x;
! 310:
! 311: if (!blessed && !cursed)
! 312: which_new = randmonster(WANDER, GRAB);
! 313: else
! 314: {
! 315: /* duplicate randmonster() for now */
! 316: /* Eventually fix to take level */
! 317:
! 318: int cur_level = 0, range, i;
! 319:
! 320: if (blessed)
! 321: cur_level = level / 2;
! 322:
! 323: if (cursed)
! 324: cur_level = level * 2;
! 325:
! 326: range = 4 * NLEVMONS;
! 327: i = 0;
! 328:
! 329: do
! 330: {
! 331: if (i++ > range * 10) /* just in case all have */
! 332: { /* been genocided */
! 333: i = 0;
! 334:
! 335: if (--cur_level <= 0)
! 336: fatal("Rogue could not find a monster to make");
! 337: }
! 338:
! 339: which_new = NLEVMONS * (cur_level - 1) + (rnd(range) - (range - 1 - NLEVMONS));
! 340:
! 341: if (which_new < 1)
! 342: which_new = rnd(NLEVMONS) + 1;
! 343:
! 344: if (which_new > nummonst - NUMSUMMON - 1)
! 345: {
! 346: if (blessed)
! 347: which_new = rnd(range) + (nummonst - NUMSUMMON - 1) - (range - 1);
! 348: else if (which_new > nummonst - 1)
! 349: which_new = rnd(range + NUMSUMMON) + (nummonst - 1) - (range + NUMSUMMON - 1);
! 350: }
! 351: }
! 352: while (!monsters[which_new].m_normal);
! 353: }
! 354:
! 355: new_monster(item, which_new, &delta, NOMAXSTATS);
! 356: mname = on(player, ISBLIND) ? "monster" : monsters[tp->t_index].m_name;
! 357:
! 358: if (!cursed && charmed)
! 359: turn_on(*tp, ISCHARMED);
! 360:
! 361: if (off(*tp, ISRUN))
! 362: chase_it(&delta, &player);
! 363:
! 364: if (isalpha(mvwinch(cw, y, x)))
! 365: mvwaddch(cw, y, x, tp->t_type);
! 366:
! 367: tp->t_oldch = oldch;
! 368: seemsg("You have created a new %s!", mname);
! 369: }
! 370: else if (which == WS_CANCEL)
! 371: {
! 372: tp->t_flags[0] &= CANC0MASK;
! 373: tp->t_flags[1] &= CANC1MASK;
! 374: tp->t_flags[2] &= CANC2MASK;
! 375: tp->t_flags[3] &= CANC3MASK;
! 376: tp->t_flags[4] &= CANC4MASK;
! 377: tp->t_flags[5] &= CANC5MASK;
! 378: tp->t_flags[6] &= CANC5MASK;
! 379: tp->t_flags[7] &= CANC7MASK;
! 380: tp->t_flags[8] &= CANC8MASK;
! 381: tp->t_flags[9] &= CANC9MASK;
! 382: tp->t_flags[10] &= CANCAMASK;
! 383: tp->t_flags[11] &= CANCBMASK;
! 384: tp->t_flags[12] &= CANCCMASK;
! 385: tp->t_flags[13] &= CANCDMASK;
! 386: tp->t_flags[14] &= CANCEMASK;
! 387: tp->t_flags[15] &= CANCFMASK;
! 388: }
! 389: else /* A teleport stick */
! 390: {
! 391: if (cursed) /* Teleport monster to */
! 392: { /* player */
! 393: if ((y == (hero.y + delta.y)) &&
! 394: (x == (hero.x + delta.x)))
! 395: nothing_message(flags);
! 396: else
! 397: {
! 398: tp->t_pos.y = hero.y + delta.y;
! 399: tp->t_pos.x = hero.x + delta.x;
! 400: }
! 401: }
! 402: else if (blessed) /* Get rid of monster */
! 403: {
! 404: killed(NULL, item, NOMESSAGE, NOPOINTS);
! 405: return;
! 406: }
! 407: else
! 408: {
! 409: int i = 0;
! 410:
! 411: do /* Move monster to */
! 412: { /* another room */
! 413: rm = rnd_room();
! 414: rnd_pos(&rooms[rm], &tp->t_pos);
! 415: }
! 416: while (winat(tp->t_pos.y, tp->t_pos.x) !=
! 417: FLOOR && i++ < 500);
! 418: }
! 419:
! 420: /* Now move the monster */
! 421:
! 422: if (isalpha(mvwinch(cw, y, x)))
! 423: mvwaddch(cw, y, x, tp->t_oldch);
! 424:
! 425: chase_it(&tp->t_pos, &player);
! 426: mvwaddch(mw, y, x, ' ');
! 427: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
! 428:
! 429: if (tp->t_pos.y != y || tp->t_pos.x != x)
! 430: tp->t_oldch = CCHAR(mvwinch(cw, tp->t_pos.y, tp->t_pos.x));
! 431: }
! 432: }
! 433: }
! 434: break;
! 435:
! 436: case WS_MISSILE:
! 437: {
! 438: int damage;
! 439: int nsides = 4;
! 440: int ch;
! 441: coord pos;
! 442:
! 443: if (is_stick)
! 444: know_items[TYP_STICK][which] = TRUE;
! 445:
! 446: /* Magic Missiles *always* hit, no saving throw */
! 447:
! 448: pos = do_motion('*', delta.y, delta.x, &player);
! 449: ch = winat(pos.y, pos.x);
! 450:
! 451: if (cursed)
! 452: nsides /= 2;
! 453: else if (blessed)
! 454: nsides *= 2;
! 455:
! 456: damage = roll(pstats.s_lvl, nsides);
! 457:
! 458: if (isalpha(ch))
! 459: {
! 460: debug("Missiled %s for %d (%d)",
! 461: mname, damage, tp->t_stats.s_hpt - damage);
! 462:
! 463: if ((tp->t_stats.s_hpt -= damage) <= 0)
! 464: {
! 465: seemsg("The missile kills the %s.", mname);
! 466: killed(&player, item, NOMESSAGE, POINTS);
! 467: }
! 468: else
! 469: {
! 470: seemsg("The missile hits the %s", mname);
! 471: chase_it(&pos, &player);
! 472: summon_help(tp, NOFORCE);
! 473: }
! 474: }
! 475:
! 476: if (pos.y >= 0 && pos.x >= 0 &&
! 477: pos.y < LINES && pos.x < COLS)
! 478: mvwaddch(cw, pos.y, pos.x, show(pos.y, pos.x));
! 479: }
! 480: break;
! 481:
! 482: case WS_HIT:
! 483: {
! 484: coord pos;
! 485: int ch;
! 486: struct object strike; /* don't want to change sticks attributes */
! 487:
! 488: if (is_stick)
! 489: know_items[TYP_STICK][which] = TRUE;
! 490:
! 491: pos = do_motion('@', delta.y, delta.x, &player);
! 492: ch = winat(pos.y, pos.x);
! 493:
! 494: if (isalpha(ch))
! 495: {
! 496: static char buf[20];
! 497: int nsides, ndice;
! 498:
! 499: strike = *obj;
! 500:
! 501: if (blessed)
! 502: strike.o_hplus = 12;
! 503: else if (cursed)
! 504: strike.o_hplus = 3;
! 505: else
! 506: strike.o_hplus = 6;
! 507:
! 508: if (!is_stick || strcmp(ws_type[which], "staff") == 0)
! 509: ndice = 3;
! 510: else
! 511: ndice = 2;
! 512:
! 513: if (blessed)
! 514: nsides = 16;
! 515: else if (cursed)
! 516: nsides = 4;
! 517: else
! 518: nsides = 8;
! 519:
! 520: sprintf(buf, "%dd%d", ndice, nsides);
! 521:
! 522: strike.o_damage = buf;
! 523: fight(&tp->t_pos, &strike, NOTHROWN);
! 524: }
! 525: }
! 526: break;
! 527:
! 528: case WS_SLOW_M:
! 529: if (got_one)
! 530: {
! 531: if (cursed)
! 532: {
! 533: if (off(*tp, ISSLOW))
! 534: turn_on(*tp, ISHASTE);
! 535: else
! 536: turn_off(*tp, ISSLOW);
! 537: }
! 538: else if (blessed)
! 539: {
! 540: if (is_stick)
! 541: know_items[TYP_STICK][which] = TRUE;
! 542:
! 543: turn_off(*tp, ISRUN);
! 544: turn_on(*tp, ISHELD);
! 545: return;
! 546: }
! 547: else
! 548: {
! 549: if (is_stick)
! 550: know_items[TYP_STICK][which] = TRUE;
! 551:
! 552: if (off(*tp, ISHASTE))
! 553: turn_on(*tp, ISSLOW);
! 554: else
! 555: turn_off(*tp, ISHASTE);
! 556:
! 557: tp->t_turn = TRUE;
! 558: }
! 559:
! 560: delta.y = y;
! 561: delta.x = x;
! 562: chase_it(&delta, &player);
! 563: }
! 564: break;
! 565:
! 566: case WS_CHARGE:
! 567: if (know_items[TYP_STICK][which] != TRUE && is_stick)
! 568: {
! 569: msg("This is a wand of charging.");
! 570: know_items[TYP_STICK][which] = TRUE;
! 571: }
! 572:
! 573: if ((nitem = get_item("charge", STICK)) != NULL)
! 574: {
! 575: nobj = OBJPTR(nitem);
! 576:
! 577: if ((nobj->o_charges == 0) && (nobj->o_which != WS_CHARGE))
! 578: {
! 579: fix_stick(nobj);
! 580:
! 581: if (blessed)
! 582: nobj->o_charges *= 2;
! 583: else if (cursed)
! 584: nobj->o_charges /= 2;
! 585: }
! 586: else
! 587: {
! 588: if (blessed)
! 589: nobj->o_charges += 2;
! 590: else if (cursed)
! 591: nobj->o_charges -= 1;
! 592: else
! 593: nobj->o_charges += 1;
! 594: }
! 595: }
! 596: break;
! 597:
! 598: case WS_ELECT:
! 599: case WS_FIRE:
! 600: case WS_COLD:
! 601: {
! 602: char *name = NULL;
! 603: int damage;
! 604: int ndice = 3 + pstats.s_lvl;
! 605: int nsides;
! 606:
! 607: if (is_stick)
! 608: {
! 609: know_items[TYP_STICK][which] = TRUE;
! 610:
! 611: if (strcmp(ws_type[which], "staff") == 0)
! 612: nsides = 8;
! 613: else
! 614: nsides = 4;
! 615: }
! 616: else
! 617: nsides = 6;
! 618:
! 619: if (cursed)
! 620: nsides /= 2;
! 621: else if (blessed)
! 622: nsides *= 2;
! 623:
! 624: switch (which)
! 625: {
! 626: case WS_ELECT:
! 627: name = "lightning bolt";
! 628:
! 629: if (rnd(2))
! 630: ndice += rnd(obj->o_charges / 10);
! 631: else
! 632: nsides += rnd(obj->o_charges / 10);
! 633:
! 634: break;
! 635:
! 636: case WS_FIRE:
! 637: name = "flame";
! 638: break;
! 639:
! 640: case WS_COLD:
! 641: name = "ice";
! 642: break;
! 643: }
! 644:
! 645: damage = roll(ndice, nsides);
! 646: shoot_bolt(&player, hero, delta, POINTS, D_BOLT, name, damage);
! 647: }
! 648: break;
! 649:
! 650: case WS_ANTIMATTER:
! 651: {
! 652: int m1, m2, x1, y1;
! 653: char ch;
! 654: struct linked_list *ll;
! 655: struct thing *lt;
! 656:
! 657: if (is_stick)
! 658: know_items[TYP_STICK][which] = TRUE;
! 659:
! 660: y1 = hero.y;
! 661: x1 = hero.x;
! 662:
! 663: do
! 664: {
! 665: y1 += delta.y;
! 666: x1 += delta.x;
! 667: ch = winat(y1, x1);
! 668: }
! 669: while (ch == PASSAGE || ch == FLOOR);
! 670:
! 671: for (m1 = x1 - 1; m1 <= x1 + 1; m1++)
! 672: {
! 673: for (m2 = y1 - 1; m2 <= y1 + 1; m2++)
! 674: {
! 675: ch = winat(m2, m1);
! 676:
! 677: if (m1 == hero.x && m2 == hero.y)
! 678: continue;
! 679:
! 680: if (ch != ' ')
! 681: {
! 682: ll = find_obj(m2, m1);
! 683:
! 684: while (ll != NULL)
! 685: {
! 686: rem_obj(ll, TRUE);
! 687: ll = find_obj(m2, m1);
! 688: }
! 689:
! 690: ll = find_mons(m2, m1);
! 691:
! 692: if (ll != NULL)
! 693: {
! 694: lt = THINGPTR(ll);
! 695: if (on(*lt, CANSELL))
! 696: {
! 697: luck++;
! 698: aggravate();
! 699: }
! 700:
! 701: if (off(*lt, CANINWALL))
! 702: {
! 703: check_residue(lt);
! 704: detach(mlist, ll);
! 705: discard(ll);
! 706: mvwaddch(mw, m2, m1, ' ');
! 707: }
! 708: }
! 709:
! 710: mvaddch(m2, m1, ' ');
! 711: mvwaddch(cw, m2, m1, ' ');
! 712: }
! 713: }
! 714: }
! 715:
! 716: touchwin(cw);
! 717: touchwin(mw);
! 718: }
! 719: break;
! 720:
! 721: case WS_CONFMON:
! 722: case WS_PARALYZE:
! 723: if (got_one)
! 724: {
! 725: if (save_throw(VS_MAGIC - (blessed ? 5 : (cursed ? -5 : 0)), tp))
! 726: nothing_message(flags);
! 727: else
! 728: {
! 729: if (is_stick)
! 730: know_items[TYP_STICK][which] = TRUE;
! 731:
! 732: switch(which)
! 733: {
! 734: case WS_CONFMON:
! 735: seemsg("The %s looks bewildered.", mname);
! 736: turn_on(*tp, ISHUH);
! 737: break;
! 738:
! 739: case WS_PARALYZE:
! 740: seemsg("The %s looks stunned.", mname);
! 741: tp->t_no_move = FREEZETIME;
! 742: break;
! 743: }
! 744: }
! 745:
! 746: delta.y = y;
! 747: delta.x = x;
! 748: chase_it(&delta, &player);
! 749: }
! 750: else
! 751: nothing_message(flags);
! 752:
! 753: break;
! 754:
! 755: case WS_XENOHEALING:
! 756: {
! 757: int hpt_gain = roll(zapper->t_stats.s_lvl, (blessed ? 8 : 4));
! 758: int mons_hpt = tp->t_stats.s_hpt;
! 759:
! 760: if (got_one)
! 761: {
! 762: if (cursed)
! 763: {
! 764: if (!save_throw(VS_MAGIC, tp))
! 765: {
! 766: if ((mons_hpt -= hpt_gain) <= 0) {
! 767: seemsg("The %s shrivels up and dies!", mname);
! 768: killed(&player, item, NOMESSAGE, POINTS);
! 769: }
! 770: else
! 771: seemsg("Wounds appear all over the %s.", mname);
! 772: }
! 773: else
! 774: nothing_message(flags);
! 775:
! 776: delta.y = y;
! 777: delta.x = x;
! 778: chase_it(&delta, &player);
! 779: }
! 780: else
! 781: {
! 782: if (is_stick)
! 783: know_items[TYP_STICK][which] = TRUE;
! 784:
! 785: mons_hpt = min(mons_hpt + hpt_gain, tp->maxstats.s_hpt);
! 786: seemsg("The %s appears less wounded!", mname);
! 787: }
! 788: }
! 789: else
! 790: nothing_message(flags);
! 791: }
! 792: break;
! 793:
! 794: case WS_DISINTEGRATE:
! 795: if (got_one)
! 796: {
! 797: if (cursed)
! 798: {
! 799: if (on(*tp, ISUNIQUE))
! 800: {
! 801: if (on(*tp, CANSUMMON))
! 802: summon_help(tp, FORCE);
! 803: else
! 804: msg("The %s is very upset.", mname);
! 805:
! 806: turn_on(*tp, ISHASTE);
! 807: }
! 808: else
! 809: {
! 810: int m1, m2;
! 811: coord mp;
! 812: struct linked_list *titem;
! 813: int ch;
! 814: struct thing *th;
! 815:
! 816: for (m1 = tp->t_pos.x - 1; m1 <= tp->t_pos.x + 1; m1++)
! 817: {
! 818: for (m2 = tp->t_pos.y - 1; m2 <= tp->t_pos.y + 1; m2++)
! 819: {
! 820: ch = winat(m2, m1);
! 821:
! 822: if (shoot_ok(ch) && ch != PLAYER)
! 823: {
! 824: mp.x = m1; /* create it */
! 825: mp.y = m2;
! 826: titem = new_item(sizeof(struct thing));
! 827: new_monster(titem, (short) tp->t_index, &mp, NOMAXSTATS);
! 828: th = THINGPTR(titem);
! 829: turn_on(*th, ISMEAN);
! 830: chase_it(&mp, &player);
! 831: }
! 832: }
! 833: }
! 834: }
! 835:
! 836: delta.y = y;
! 837: delta.x = x;
! 838: turn_on(*tp, ISMEAN);
! 839: chase_it(&delta, &player);
! 840: }
! 841: else /* if its a UNIQUE it might still live */
! 842: {
! 843: if (is_stick)
! 844: know_items[TYP_STICK][which] = TRUE;
! 845:
! 846: if (on(*tp, ISUNIQUE) &&
! 847: save_throw(VS_MAGIC - (blessed ? -5 : 0), tp))
! 848: {
! 849: tp->t_stats.s_hpt = tp->t_stats.s_hpt / 2 - 1;
! 850:
! 851: if (tp->t_stats.s_hpt < 1)
! 852: {
! 853: killed(&player, item, NOMESSAGE, POINTS);
! 854: seemsg("The %s fades away.", mname);
! 855: }
! 856: else
! 857: {
! 858: delta.y = y;
! 859: delta.x = x;
! 860:
! 861: chase_it(&delta, &player);
! 862:
! 863: if (on(*tp, CANSUMMON))
! 864: summon_help(tp, FORCE);
! 865: else
! 866: seemsg("The %s is very upset.", mname);
! 867: }
! 868: }
! 869: else
! 870: {
! 871: if (on(*tp, CANSELL))
! 872: {
! 873: luck++;
! 874: aggravate();
! 875: }
! 876: seemsg("The %s turns to dust and blows away.", mname);
! 877: killed(&player, item, NOMESSAGE, POINTS);
! 878: }
! 879: }
! 880: }
! 881: break;
! 882:
! 883: case WS_NOTHING:
! 884: nothing_message(flags);
! 885: break;
! 886:
! 887: case WS_INVIS:
! 888: {
! 889: if (cursed)
! 890: {
! 891: int x1, y1, x2, y2;
! 892: int zapped = FALSE;
! 893:
! 894: if ((rp = roomin(hero)) == NULL)
! 895: {
! 896: x1 = max(hero.x - 1, 0);
! 897: y1 = max(hero.y - 1, 0);
! 898: x2 = min(hero.x + 1, COLS - 1);
! 899: y2 = min(hero.y + 1, LINES - 3);
! 900: }
! 901: else
! 902: {
! 903: x1 = rp->r_pos.x;
! 904: y1 = rp->r_pos.y;
! 905: x2 = rp->r_pos.x + rp->r_max.x;
! 906: y2 = rp->r_pos.y + rp->r_max.y;
! 907: }
! 908:
! 909: for (item = mlist; item != NULL; item = next(item))
! 910: {
! 911: tp = THINGPTR(item);
! 912:
! 913: if (tp->t_pos.x >= x1 && tp->t_pos.x <= x2 &&
! 914: tp->t_pos.y >= y1 && tp->t_pos.y <= y2)
! 915: {
! 916: turn_on(*tp, ISINVIS);
! 917: turn_on(*tp, ISRUN);
! 918: turn_off(*tp, ISDISGUISE);
! 919: chase_it(&tp->t_pos, &player);
! 920: zapped = TRUE;
! 921: }
! 922: }
! 923:
! 924: if (zapped)
! 925: seemsg("The monsters seem to have all disappeared.");
! 926: else
! 927: nothing_message(flags);
! 928: }
! 929: else
! 930: {
! 931: if (got_one)
! 932: {
! 933: if (is_stick)
! 934: know_items[TYP_STICK][which] = TRUE;
! 935:
! 936: if (blessed)
! 937: {
! 938: turn_off(*tp, ISINVIS);
! 939: turn_off(*tp, ISSHADOW);
! 940: seemsg("The %s appears.", mname);
! 941: }
! 942: else
! 943: {
! 944: turn_on(*tp, ISINVIS);
! 945: seemsg("The %s disappears.", mname);
! 946: }
! 947: }
! 948: else
! 949: nothing_message(flags);
! 950: }
! 951: light(&hero);
! 952: }
! 953: break;
! 954:
! 955: case WS_BLAST:
! 956: {
! 957: int ch;
! 958: struct linked_list *itm, *ip;
! 959: struct object *ob;
! 960: struct trap *trp;
! 961:
! 962: if (is_stick)
! 963: know_items[TYP_STICK][which] = TRUE;
! 964:
! 965: itm = spec_item(WEAPON, GRENADE, 0, 0);
! 966: ob = OBJPTR(itm);
! 967: ob->o_count = 1;
! 968: ob->o_flags |= ISKNOW;
! 969: hearmsg("BOOOM!");
! 970: aggravate();
! 971: ob->o_pos.x = hero.x;
! 972: ob->o_pos.y = hero.y;
! 973:
! 974: for (;;)
! 975: {
! 976: ob->o_pos.y += delta.y;
! 977: ob->o_pos.x += delta.x;
! 978:
! 979: if (!ce(ob->o_pos, hero) &&
! 980: cansee(ob->o_pos.y, ob->o_pos.x) &&
! 981: mvwinch(cw, ob->o_pos.y, ob->o_pos.x) != ' ')
! 982: {
! 983: mvwaddch(cw, ob->o_pos.y, ob->o_pos.x,
! 984: show(ob->o_pos.y, ob->o_pos.x));
! 985: }
! 986:
! 987: if (shoot_ok(ch = winat(ob->o_pos.y, ob->o_pos.x))
! 988: && ch != DOOR && !ce(ob->o_pos, hero))
! 989: {
! 990: if (cansee(ob->o_pos.y, ob->o_pos.x) &&
! 991: ntraps + 1 < 2 * MAXTRAPS &&
! 992: mvwinch(cw, ob->o_pos.y, ob->o_pos.x) != ' ')
! 993: {
! 994: mvwaddch(cw, ob->o_pos.y, ob->o_pos.x,TRAPDOOR);
! 995: wrefresh(cw);
! 996: }
! 997:
! 998: if (isatrap(ch))
! 999: {
! 1000: trp = trap_at(ob->o_pos.y, ob->o_pos.x);
! 1001:
! 1002: if (trp != NULL)
! 1003: {
! 1004: trp->tr_type = TRAPDOOR;
! 1005: trp->tr_flags |= ISFOUND;
! 1006: trp->tr_show = TRAPDOOR;
! 1007: }
! 1008: }
! 1009: else if (isalpha(ch))
! 1010: hit_monster(ob->o_pos.y, ob->o_pos.x, ob, &player);
! 1011: else if ((ch == FLOOR || ch == PASSAGE)
! 1012: && ntraps + 1 < 2 * MAXTRAPS)
! 1013: {
! 1014: mvaddch(ob->o_pos.y, ob->o_pos.x, TRAPDOOR);
! 1015: traps[ntraps].tr_type = TRAPDOOR;
! 1016: traps[ntraps].tr_flags = ISFOUND;
! 1017: traps[ntraps].tr_show = TRAPDOOR;
! 1018: traps[ntraps].tr_pos.y = ob->o_pos.y;
! 1019: traps[ntraps++].tr_pos.x = ob->o_pos.x;
! 1020: }
! 1021: else if (ch == POTION || ch == SCROLL || ch == FOOD
! 1022: || ch == WEAPON || ch == RING || ch == ARMOR
! 1023: || ch == STICK || ch == ARTIFACT || ch == GOLD)
! 1024: {
! 1025: ip = find_obj(ob->o_pos.y, ob->o_pos.x);
! 1026:
! 1027: while (ip) /* BOOM destroys all stacked objects */
! 1028: {
! 1029: rem_obj(ip, TRUE);
! 1030: ip = find_obj(ob->o_pos.y, ob->o_pos.x);
! 1031: }
! 1032:
! 1033: mvaddch(ob->o_pos.y, ob->o_pos.x,
! 1034: (roomin(ob->o_pos) == NULL ? PASSAGE : FLOOR) );
! 1035: }
! 1036: continue;
! 1037: }
! 1038: break;
! 1039: }
! 1040: discard(itm);
! 1041: }
! 1042: break;
! 1043:
! 1044: case WS_WEB:
! 1045: {
! 1046: int ch;
! 1047: coord pos;
! 1048:
! 1049: if (is_stick)
! 1050: know_items[TYP_STICK][which] = TRUE;
! 1051:
! 1052: pos = do_motion('#', delta.y, delta.x, &player);
! 1053: ch = winat(pos.y, pos.x);
! 1054:
! 1055: if (isalpha(ch))
! 1056: {
! 1057: if (save_throw(VS_MAGIC, tp))
! 1058: seemsg("The %s evades your web.", mname);
! 1059: else
! 1060: {
! 1061: seemsg("The %s is webbed.", mname);
! 1062: turn_off(*tp, ISRUN);
! 1063: turn_on(*tp, ISHELD);
! 1064: }
! 1065: }
! 1066:
! 1067: if (pos.y >= 0 && pos.x >= 0 &&
! 1068: pos.y < LINES && pos.x < COLS)
! 1069: mvwaddch(cw, pos.y, pos.x, show(pos.y, pos.x));
! 1070: }
! 1071: break;
! 1072:
! 1073: case WS_KNOCK:
! 1074: case WS_CLOSE:
! 1075: if (blessed) /* Do all doors in room */
! 1076: {
! 1077: char new_door = (which == WS_KNOCK ? DOOR : SECRETDOOR);
! 1078: struct room *rmp = roomin(hero);
! 1079:
! 1080: if (rmp != NULL)
! 1081: for (x = 0; x < rmp->r_nexits; x++)
! 1082: {
! 1083: move(rmp->r_exit[x].y, rmp->r_exit[x].x);
! 1084: addch(new_door);
! 1085: }
! 1086: else /* Do all adjacent doors */
! 1087: for (x = hero.x - 1; x <= hero.x + 1; x++)
! 1088: for (y = hero.y - 1; y <= hero.y + 1; y++)
! 1089: switch(CCHAR( winat(y, x) ))
! 1090: {
! 1091: case DOOR:
! 1092: case SECRETDOOR:
! 1093: addch(new_door);
! 1094: break;
! 1095: }
! 1096: light(&hero);
! 1097: }
! 1098: else if (cursed)/* do opposite spell */
! 1099: do_zap(zapper, (which == WS_KNOCK ? WS_CLOSE : WS_KNOCK), ISBLESSED);
! 1100: else
! 1101: {
! 1102: coord zap_loc;
! 1103: char loc;
! 1104:
! 1105: zap_loc.y = hero.y + delta.y;
! 1106: zap_loc.x = hero.x + delta.x;
! 1107: loc = winat(zap_loc.y, zap_loc.x);
! 1108:
! 1109: switch (loc)
! 1110: {
! 1111: case SECRETDOOR:
! 1112: if (which == WS_KNOCK)
! 1113: {
! 1114: mvaddch(zap_loc.y, zap_loc.x, DOOR);
! 1115: seemsg("A secret door stands revealed before you!");
! 1116:
! 1117: if (is_stick)
! 1118: know_items[TYP_STICK][which] = TRUE;
! 1119: }
! 1120: else
! 1121: nothing_message(flags);
! 1122: break;
! 1123:
! 1124: case DOOR:
! 1125:
! 1126: if (which == WS_CLOSE)
! 1127: {
! 1128: mvaddch(zap_loc.y, zap_loc.x, SECRETDOOR);
! 1129: msg("You sucessfully block off the door.")
! 1130: ;
! 1131: if (is_stick)
! 1132: know_items[TYP_STICK][which] = TRUE;
! 1133: }
! 1134: else
! 1135: nothing_message(flags);
! 1136:
! 1137: break;
! 1138:
! 1139: default:
! 1140: nothing_message(flags);
! 1141: }
! 1142: }
! 1143:
! 1144: break;
! 1145: default:
! 1146: msg("What a bizarre schtick!");
! 1147: }
! 1148: }
! 1149:
! 1150: /*
! 1151: drain()
! 1152: Do drain hit points from player shtick
! 1153: */
! 1154:
! 1155: void
! 1156: drain(int ymin, int ymax, int xmin, int xmax)
! 1157: {
! 1158: int i, j, cnt;
! 1159: struct thing *ick;
! 1160: struct linked_list *item;
! 1161:
! 1162: /* First count how many things we need to spread the hit points among */
! 1163:
! 1164: for (cnt = 0, i = ymin; i <= ymax; i++)
! 1165: for (j = xmin; j <= xmax; j++)
! 1166: if (isalpha(mvwinch(mw, i, j)))
! 1167: cnt++;
! 1168:
! 1169: if (cnt == 0)
! 1170: {
! 1171: msg("You have a tingling feeling.");
! 1172: return;
! 1173: }
! 1174: else
! 1175: msg("You feel weaker.");
! 1176:
! 1177: cnt = pstats.s_hpt / cnt;
! 1178: pstats.s_hpt /= 2;
! 1179:
! 1180: /* Now zot all of the monsters */
! 1181:
! 1182: for (i = ymin; i <= ymax; i++)
! 1183: for (j = xmin; j <= xmax; j++)
! 1184: if (isalpha(mvwinch(mw, i, j)) && ((item = find_mons(i, j)) != NULL))
! 1185: {
! 1186: ick = THINGPTR(item);
! 1187:
! 1188: if (on(*ick, CANSELL))
! 1189: {
! 1190: luck++;
! 1191: aggravate();
! 1192: }
! 1193:
! 1194: if ((ick->t_stats.s_hpt -= cnt) < 1)
! 1195: killed(&player, item,
! 1196: cansee(i, j) && !on(*ick, ISINVIS), POINTS);
! 1197: }
! 1198: }
! 1199:
! 1200: /*
! 1201: charge_str()
! 1202: charge a wand for wizards.
! 1203: */
! 1204:
! 1205: char *
! 1206: charge_str(struct object *obj, char *buf)
! 1207: {
! 1208: if (buf == NULL)
! 1209: return( "[UltraRogue Bug #103]" );
! 1210:
! 1211: if (!(obj->o_flags & ISKNOW))
! 1212: buf[0] = '\0';
! 1213: else if (obj->o_charges == 1)
! 1214: sprintf(buf, " [%d charge]", obj->o_charges);
! 1215: else
! 1216: sprintf(buf, " [%d charges]", obj->o_charges);
! 1217:
! 1218: return(buf);
! 1219: }
! 1220:
! 1221:
! 1222: /*
! 1223: shoot_bolt()
! 1224: fires a bolt from the given starting point in the given direction
! 1225: struct thing *shooter;
! 1226: coord start, dir;
! 1227: int get_points; should player get exp points?
! 1228: short reason; reason for dying
! 1229: char *name; fire, nerve, cold, etc
! 1230: int damage; make zapee suffer
! 1231: */
! 1232:
! 1233: void
! 1234: shoot_bolt(struct thing *shooter, coord start, coord dir, int get_points, int reason, char *name, int damage)
! 1235: {
! 1236: int ch;
! 1237: char dirch;
! 1238: int change;
! 1239: short y, x;
! 1240: coord pos;
! 1241: coord spotpos[BOLT_LENGTH + 1];
! 1242: int ret_val = FALSE;/* True if breathing monster gets killed */
! 1243: struct linked_list *item;
! 1244: struct thing *tp;
! 1245: char *mname;
! 1246: int bounced; /* where along BOLT_LENGTH it hit a wall */
! 1247: int player_damage; /* damage if player saved */
! 1248: int no_effect; /* zap does not effect zappee */
! 1249: int take_that[BOLT_LENGTH + 1]; /* damage to each monster */
! 1250:
! 1251: /* last spot for player */
! 1252:
! 1253: debug("%s does %d damage", name, damage);
! 1254:
! 1255: switch (dir.y + dir.x)
! 1256: {
! 1257: case 0:
! 1258: dirch = '/';
! 1259: break;
! 1260:
! 1261: case 1:
! 1262: case -1:
! 1263: dirch = (dir.y == 0 ? '-' : '|');
! 1264: break;
! 1265:
! 1266: case 2:
! 1267: case -2:
! 1268: dirch = '\\';
! 1269: break;
! 1270: }
! 1271:
! 1272: pos.y = start.y + dir.y;
! 1273: pos.x = start.x + dir.x;
! 1274: change = FALSE;
! 1275:
! 1276: for (y = 0; y < BOLT_LENGTH + 1; y++)
! 1277: take_that[y] = 0;
! 1278:
! 1279: bounced = 0;
! 1280:
! 1281: for (y = 0; y < BOLT_LENGTH; y++)
! 1282: {
! 1283: no_effect = FALSE;
! 1284: ch = winat(pos.y, pos.x);
! 1285: spotpos[y] = pos;
! 1286:
! 1287: /* Bolt damage dimishes over space */
! 1288:
! 1289: damage = max(1, damage - (y / 3));
! 1290:
! 1291: /* Are we at hero? */
! 1292:
! 1293: if (ce(pos, hero))
! 1294: goto at_hero;
! 1295:
! 1296: switch(ch)
! 1297: {
! 1298: case SECRETDOOR:
! 1299: case '|':
! 1300: case '-':
! 1301: case ' ':
! 1302: bounced = y;
! 1303: if (dirch == '-' || dirch == '|')
! 1304: {
! 1305: dir.y = -dir.y;
! 1306: dir.x = -dir.x;
! 1307: }
! 1308: else
! 1309: switch (ch)
! 1310: {
! 1311: case '|':
! 1312: case '-':
! 1313: case SECRETDOOR:
! 1314: {
! 1315: struct room *rp;
! 1316:
! 1317: rp = roomin(pos);
! 1318:
! 1319: if (pos.y == rp->r_pos.y ||
! 1320: pos.y == rp->r_pos.y + rp->r_max.y - 1)
! 1321: {
! 1322: dir.y = -dir.y;
! 1323: change ^= TRUE;
! 1324: }
! 1325:
! 1326: if (pos.x == rp->r_pos.x ||
! 1327: pos.x == rp->r_pos.x + rp->r_max.x - 1)
! 1328: {
! 1329: dir.x = -dir.x;
! 1330: change ^= TRUE;
! 1331: }
! 1332: }
! 1333: default: /* A wall */
! 1334: {
! 1335: char chy = CCHAR( mvinch(pos.y - dir.y, pos.x + dir.x)), chx = CCHAR( mvinch(pos.y + dir.y, pos.x - dir.x) );
! 1336:
! 1337: if (chy != WALL && chy != SECRETDOOR &&
! 1338: chy != '-' && chy != '|')
! 1339: {
! 1340: dir.y = -dir.y;
! 1341: change = TRUE;
! 1342: }
! 1343: else if (chx != WALL && chx != SECRETDOOR &&
! 1344: chx != '-' && chx != '|')
! 1345: {
! 1346: dir.x = -dir.x;
! 1347: change = TRUE;
! 1348: }
! 1349: else
! 1350: {
! 1351: dir.y = -dir.y;
! 1352: dir.x = -dir.x;
! 1353: }
! 1354: }
! 1355: }
! 1356:
! 1357: /* Do we change how the bolt looks? */
! 1358:
! 1359: if (change)
! 1360: {
! 1361: change = FALSE;
! 1362:
! 1363: if (dirch == '\\')
! 1364: dirch = '/';
! 1365: else if (dirch == '/')
! 1366: dirch = '\\';
! 1367: }
! 1368:
! 1369: break;
! 1370:
! 1371: default:
! 1372: if (isalpha(ch)) /* hit a monster */
! 1373: {
! 1374: item = find_mons(pos.y, pos.x);
! 1375:
! 1376: if (item == NULL)
! 1377: {
! 1378: debug("Can't find monster %c @ %d %d.",
! 1379: ch, pos.y, pos.x);
! 1380:
! 1381: continue;
! 1382: }
! 1383:
! 1384: tp = THINGPTR(item);
! 1385: mname = on(player, ISBLIND) ? "monster" : monsters[tp->t_index].m_name;
! 1386:
! 1387: /* Disguised monsters stay hidden if they save */
! 1388:
! 1389: if (on(*tp, ISDISGUISE) && save_throw(VS_MAGIC, tp) &&
! 1390: (tp->t_type != tp->t_disguise) && off(player, ISBLIND))
! 1391: {
! 1392: msg("Wait! That's a %s!", mname);
! 1393: turn_off(*tp, ISDISGUISE);
! 1394: }
! 1395:
! 1396: tp->t_wasshot = TRUE;
! 1397:
! 1398: if (on(*tp, CANSELL))
! 1399: {
! 1400: luck++;
! 1401: aggravate();
! 1402: }
! 1403:
! 1404: /* Hit the monster -- does it do damage? */
! 1405:
! 1406: if (strcmp(name, "ice") == 0)
! 1407: {
! 1408: if (on(*tp, NOCOLD) || on(*tp, ISUNDEAD))
! 1409: no_effect = TRUE;
! 1410: }
! 1411: else if (strcmp(name, "flame") == 0)
! 1412: {
! 1413: if (on(*tp, NOFIRE))
! 1414: no_effect = TRUE;
! 1415:
! 1416: if (on(*tp, CANBBURN))
! 1417: {
! 1418: seemsg("The %s is burned to death by the flame.",
! 1419: mname);
! 1420:
! 1421: take_that[y] += tp->t_stats.s_hpt + 1;
! 1422: ret_val = TRUE;
! 1423: }
! 1424: }
! 1425: else if (strcmp(name, "lightning bolt") == 0)
! 1426: {
! 1427: if (on(*tp, NOBOLT))
! 1428: no_effect = TRUE;
! 1429:
! 1430: if (on(*tp, BOLTDIVIDE))
! 1431: {
! 1432: no_effect = TRUE;
! 1433:
! 1434: if (creat_mons(tp, tp->t_index, NOMESSAGE))
! 1435: seemsg("The %s divides the %s.", name, mname);
! 1436: }
! 1437: }
! 1438:
! 1439: if (no_effect == TRUE)
! 1440: {
! 1441: msg("The %s has no effect on the %s.", name,
! 1442: on(player, ISBLIND) ? "monster" : mname);
! 1443: }
! 1444: else
! 1445: {
! 1446: take_that[(bounced ? bounced-- : y)] +=
! 1447: save_throw(VS_MAGIC, tp) ? damage / 2 : damage;
! 1448: }
! 1449: }
! 1450: else if (pos.y == hero.y && pos.x == hero.x)
! 1451: {
! 1452: at_hero:
! 1453: player_damage = damage;
! 1454: running = fighting = FALSE;
! 1455: bounced = 0;
! 1456:
! 1457: if (cur_armor != NULL &&
! 1458: cur_armor->o_which == CRYSTAL_ARMOR &&
! 1459: (strcmp(name, "acid") == 0))
! 1460: {
! 1461: player_damage = 0;
! 1462: msg("The acid splashes harmlessly against your armor!");
! 1463: }
! 1464: else if (((cur_armor != NULL &&
! 1465: cur_armor->o_which == CRYSTAL_ARMOR) ||
! 1466: (on(player, ISELECTRIC)) ||
! 1467: is_wearing(R_ELECTRESIST)) &&
! 1468: (strcmp(name, "lightning bolt") == 0))
! 1469: {
! 1470: player_damage = 0;
! 1471:
! 1472: if (rnd(100) < 75
! 1473: && cur_weapon != NULL
! 1474: && shooter != &player)
! 1475: {
! 1476: cur_weapon->o_flags |= ISZAPPED;
! 1477: cur_weapon->o_charges += (10 + rnd(15));
! 1478: }
! 1479:
! 1480: if (cur_weapon != NULL && cur_armor != NULL)
! 1481: msg("Your armor and %s are covered with dancing blue lights!", weaps[cur_weapon->o_which].w_name);
! 1482: else if (cur_armor != NULL)
! 1483: msg("Your armor is covered with dancing blue lights!");
! 1484: else if (cur_weapon != NULL)
! 1485: msg("Your %s is covered with dancing blue lights!", weaps[cur_weapon->o_which].w_name);
! 1486: else
! 1487: msg("You are momentarily covered with dancing blue lights.");
! 1488: }
! 1489: else if ((is_wearing(R_FIRERESIST) || on(player, NOFIRE)) &&
! 1490: (strcmp(name, "flame") == 0))
! 1491: {
! 1492: player_damage = 0;
! 1493: msg("The flame bathes you harmlessly.");
! 1494: }
! 1495: else if ((is_wearing(R_COLDRESIST) || on(player, NOCOLD)) &&
! 1496: (strcmp(name, "ice") == 0))
! 1497: {
! 1498: player_damage = 0;
! 1499: msg("The ice cracks and quickly melts around you.");
! 1500: }
! 1501: else if (save(VS_MAGIC))
! 1502: {
! 1503: take_that[BOLT_LENGTH] += player_damage / 2;
! 1504: debug("Player dodges %s for %d.", name, player_damage / 2);
! 1505: }
! 1506: else
! 1507: {
! 1508: debug("Player zapped by %s for %d.", name, player_damage);
! 1509: take_that[BOLT_LENGTH] += player_damage;
! 1510: }
! 1511:
! 1512: /* Check for gas with special effects */
! 1513:
! 1514: if (off(player, HASOXYGEN) && !is_wearing(R_BREATHE) && !save(VS_BREATH))
! 1515: {
! 1516: if (strcmp(name, "nerve gas") == 0)
! 1517: {
! 1518: if (no_command == 0)
! 1519: {
! 1520: msg("The nerve gas paralyzes you.");
! 1521: no_command = FREEZETIME;
! 1522: }
! 1523: }
! 1524: else if (strcmp(name, "sleeping gas") == 0)
! 1525: {
! 1526: if (no_command == 0)
! 1527: {
! 1528: msg("The sleeping gas puts you to sleep.");
! 1529: no_command = SLEEPTIME;
! 1530: }
! 1531: }
! 1532: else if (strcmp(name, "slow gas") == 0
! 1533: && !is_wearing(R_FREEDOM))
! 1534: {
! 1535: msg("You feel yourself moving %sslower.",
! 1536: on(player, ISSLOW) ? "even " : "");
! 1537:
! 1538: if (on(player, ISSLOW))
! 1539: lengthen_fuse(FUSE_NOSLOW, rnd(10) + 4);
! 1540: else
! 1541: {
! 1542: turn_on(player, ISSLOW);
! 1543: player.t_turn = TRUE;
! 1544: light_fuse(FUSE_NOSLOW, 0, rnd(10) + 4, AFTER);
! 1545: }
! 1546: }
! 1547: else if (strcmp(name, "fear gas") == 0)
! 1548: {
! 1549: if (!(on(player, ISFLEE) &&
! 1550: (player.t_chasee==shooter)) &&
! 1551: (shooter != &player))
! 1552: {
! 1553: if (off(player, SUPERHERO)
! 1554: && player.t_ctype != C_PALADIN)
! 1555: {
! 1556: turn_on(player, ISFLEE);
! 1557: player.t_chasee = shooter;
! 1558: player.t_ischasing = FALSE;
! 1559: msg("The fear gas terrifies you.");
! 1560: }
! 1561: else
! 1562: msg("The fear gas has no effect.");
! 1563: }
! 1564: }
! 1565: }
! 1566: }
! 1567: mvwaddch(cw, pos.y, pos.x, dirch);
! 1568: wrefresh(cw);
! 1569: }
! 1570: pos.y += dir.y;
! 1571: pos.x += dir.x;
! 1572: }
! 1573:
! 1574: /*
! 1575: * Now that we have determined the damage for the length of the bolt,
! 1576: * apply it to each monster (and then the player) in turn
! 1577: */
! 1578:
! 1579: for (x = 0; x < BOLT_LENGTH; x++)
! 1580: {
! 1581: ch = winat(spotpos[x].y, spotpos[x].x);
! 1582:
! 1583: if (take_that[x] != 0 && isalpha(ch))
! 1584: {
! 1585: if ((item = find_mons(spotpos[x].y, spotpos[x].x)) == NULL)
! 1586: {
! 1587: debug("Can't find monster %c @ %d %d.",
! 1588: ch, spotpos[x].y, spotpos[x].x);
! 1589:
! 1590: continue;
! 1591: }
! 1592: else
! 1593: tp = THINGPTR(item);
! 1594:
! 1595: mname = on(player, ISBLIND) ? "monster" : monsters[tp->t_index].m_name;
! 1596:
! 1597: debug("Zapped %s for %d (%d)",
! 1598: mname, take_that[x], tp->t_stats.s_hpt - take_that[x]);
! 1599:
! 1600: if ((tp->t_stats.s_hpt -= take_that[x]) <= 0)
! 1601: {
! 1602: if (cansee(tp->t_pos.y, tp->t_pos.x))
! 1603: msg("The %s kills the %s.", name,
! 1604: on(player, ISBLIND) ? "monster" : mname);
! 1605:
! 1606: killed(shooter, item, NOMESSAGE, get_points);
! 1607: ret_val = TRUE;
! 1608: }
! 1609: else if (get_points)
! 1610: {
! 1611: chase_it(&spotpos[x], &player);
! 1612: summon_help(tp, NOFORCE);
! 1613: }
! 1614: }
! 1615:
! 1616: if (spotpos[x].y >= 0 && spotpos[x].x >= 0 &&
! 1617: spotpos[x].y < LINES && spotpos[x].x < COLS)
! 1618: mvwaddch(cw, spotpos[x].y, spotpos[x].x,
! 1619: show(spotpos[x].y, spotpos[x].x));
! 1620: }
! 1621:
! 1622: if (take_that[BOLT_LENGTH] != 0)
! 1623: {
! 1624: if (tp != THINGPTR(fam_ptr))
! 1625: {
! 1626: msg("You are hit by the %s.", name);
! 1627:
! 1628: if ((pstats.s_hpt -= take_that[BOLT_LENGTH]) <= 0)
! 1629: {
! 1630: death(reason);
! 1631: return;
! 1632: }
! 1633: }
! 1634: }
! 1635:
! 1636: return;
! 1637: }
! 1638:
! 1639: /*
! 1640: monster_do_zap()
! 1641: monster gets the effect
! 1642: */
! 1643:
! 1644: void
! 1645: monster_do_zap(struct thing *zapper, int which, int flags)
! 1646: {
! 1647: struct stats *curp = &(zapper->t_stats);
! 1648: int blessed = flags & ISBLESSED;
! 1649: int cursed = flags & ISCURSED;
! 1650: int shoot = FALSE;
! 1651: int damage;
! 1652: int ndice, nsides;
! 1653: int ch;
! 1654: char *bolt_name = NULL;
! 1655: coord pos;
! 1656:
! 1657: switch(which)
! 1658: {
! 1659: case WS_MISSILE:
! 1660: bolt_name = "magic missile";
! 1661: pos = do_motion('*', delta.y, delta.x, zapper);
! 1662: ch = winat(pos.y, pos.x);
! 1663: ndice = curp->s_lvl;
! 1664: nsides = 4;
! 1665:
! 1666: if (cursed)
! 1667: nsides /= 2;
! 1668: else if (blessed)
! 1669: nsides *= 2;
! 1670:
! 1671: damage = roll(ndice, nsides);
! 1672:
! 1673: if (ch == PLAYER)
! 1674: {
! 1675: if (save(VS_MAGIC)) /* help the player */
! 1676: msg("You evade the %s.", bolt_name);
! 1677: else
! 1678: {
! 1679: msg("You are hit by the %s.", bolt_name);
! 1680:
! 1681: if ((pstats.s_hpt -= damage) <= 0)
! 1682: death(D_BOLT);
! 1683: }
! 1684: }
! 1685: else if (isalpha(ch))
! 1686: {
! 1687: struct linked_list *item = find_mons(pos.y, pos.x);
! 1688:
! 1689: if (item != NULL)
! 1690: {
! 1691: struct thing *tp = THINGPTR(item);
! 1692: int see_it = cansee(pos.y, pos.x);
! 1693:
! 1694: if ((tp->t_stats.s_hpt -= damage) <= 0)
! 1695: killed(zapper, item, see_it, (zapper == THINGPTR(fam_ptr)));
! 1696: else if (see_it)
! 1697: msg("The %s hits the monster.", bolt_name);
! 1698: }
! 1699: }
! 1700:
! 1701: if (pos.y >= 0 && pos.x >= 0 &&
! 1702: pos.y < LINES && pos.x < COLS)
! 1703: mvwaddch(cw, pos.y, pos.x, show(pos.y, pos.x));
! 1704:
! 1705: break;
! 1706:
! 1707: case WS_CANCEL:
! 1708: cancel_player(off(*zapper, ISUNIQUE));
! 1709: break;
! 1710:
! 1711: case WS_COLD:
! 1712: shoot = TRUE;
! 1713: bolt_name = "cold";
! 1714: break;
! 1715:
! 1716: case WS_FIRE:
! 1717: shoot = TRUE;
! 1718: bolt_name = "fire";
! 1719: break;
! 1720:
! 1721: case WS_ELECT:
! 1722: shoot = TRUE;
! 1723: bolt_name = "lightning";
! 1724: break;
! 1725:
! 1726: default:
! 1727: debug("'%s' is a strange stick for a monster to zap!",
! 1728: ws_magic[which].mi_name);
! 1729: break;
! 1730: }
! 1731:
! 1732: if (shoot)
! 1733: {
! 1734: ndice = curp->s_lvl / 2 + 1;
! 1735: nsides = 6;
! 1736:
! 1737: if (cursed)
! 1738: nsides /= 2;
! 1739: else if (blessed)
! 1740: nsides *= 2;
! 1741:
! 1742: damage = roll(ndice, nsides);
! 1743: shoot_bolt(zapper, zapper->t_pos, delta,
! 1744: (zapper == THINGPTR(fam_ptr)), D_BOLT, bolt_name, damage);
! 1745: }
! 1746: }
! 1747:
! 1748: struct powers
! 1749: {
! 1750: unsigned long p_flag;
! 1751: int fuse_id;
! 1752: };
! 1753:
! 1754: /* Order in which powers will attempt to be cancelled */
! 1755:
! 1756: struct powers player_powers[] =
! 1757: {
! 1758: { ISHASTE, FUSE_NOHASTE },
! 1759: { ISELECTRIC, FUSE_UNELECTRIFY },
! 1760: { CANINWALL, FUSE_UNPHASE },
! 1761: { CANFLY, FUSE_UNFLY },
! 1762: { ISINVIS, FUSE_APPEAR },
! 1763: { CANREFLECT, FUSE_UNGAZE },
! 1764: { ISDISGUISE, FUSE_UNDISGUISE },
! 1765: { HASMSHIELD, FUSE_UNMSHIELD },
! 1766: { ISREGEN, FUSE_UNREGEN },
! 1767: { CANSEE, FUSE_UNSEE },
! 1768: { NOCOLD, FUSE_UNCOLD },
! 1769: { NOFIRE, FUSE_UNHOT },
! 1770: { HASOXYGEN, FUSE_UNBREATHE },
! 1771: { HASSHIELD, FUSE_UNSHIELD },
! 1772: { ULONG_MAX, FUSE_NULL }
! 1773: };
! 1774:
! 1775: void
! 1776: cancel_player(int not_unique)
! 1777: {
! 1778: struct powers *pp;
! 1779: int no_effect = TRUE;
! 1780:
! 1781: for(pp = player_powers; pp->p_flag != ULONG_MAX; pp++)
! 1782: {
! 1783: if (on(player, pp->p_flag) && !save(VS_MAGIC))
! 1784: {
! 1785: fuses[pp->fuse_id].func(NULL);
! 1786: extinguish_fuse(pp->fuse_id);
! 1787: no_effect = FALSE;
! 1788:
! 1789: if (not_unique) /* Gods might cancel everything */
! 1790: break;
! 1791: }
! 1792: }
! 1793:
! 1794: if (no_effect)
! 1795: nothing_message(ISNORMAL);
! 1796: }
CVSweb