Annotation of early-roguelike/xrogue/sticks.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: sticks.c - Functions to implement the various sticks one might find
! 3:
! 4: XRogue: Expeditions into the Dungeons of Doom
! 5: Copyright (C) 1991 Robert Pietkivitch
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 10: All rights reserved.
! 11:
! 12: Based on "Rogue: Exploring the Dungeons of Doom"
! 13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 14: All rights reserved.
! 15:
! 16: See the file LICENSE.TXT for full copyright and licensing information.
! 17: */
! 18:
! 19: #include <curses.h>
! 20: #include <ctype.h>
! 21: #include <string.h>
! 22: #include "rogue.h"
! 23:
! 24: void drain(int ymin, int ymax, int xmin, int xmax);
! 25:
! 26: /*
! 27: * zap a stick and see what happens
! 28: */
! 29:
! 30: void
! 31: do_zap(struct thing *zapper, struct object *obj, coord *direction, int which,
! 32: int flags)
! 33: {
! 34: register struct linked_list *item = NULL;
! 35: register struct thing *tp;
! 36: register int y = 0, x = 0, bonus;
! 37: struct linked_list *nitem;
! 38: struct object *nobj;
! 39: bool cursed, blessed, is_player = FALSE;
! 40: char *mname = NULL;
! 41:
! 42: cursed = flags & ISCURSED;
! 43: blessed = flags & ISBLESSED;
! 44:
! 45: if (obj && obj->o_type != RELIC) { /* all relics are chargeless */
! 46: if (obj->o_charges < 1) {
! 47: msg(nothing);
! 48: return;
! 49: }
! 50: obj->o_charges--;
! 51: }
! 52: if (which == WS_WONDER) {
! 53: switch (rnd(19)) {
! 54: case 0: which = WS_ELECT;
! 55: when 1: which = WS_FIRE;
! 56: when 2: which = WS_COLD;
! 57: when 3: which = WS_POLYMORPH;
! 58: when 4: which = WS_MISSILE;
! 59: when 5: which = WS_SLOW_M;
! 60: when 6: which = WS_TELMON;
! 61: when 7: which = WS_CANCEL;
! 62: when 8: which = WS_CONFMON;
! 63: when 9: which = WS_DISINTEGRATE;
! 64: when 10: which = WS_PETRIFY;
! 65: when 11: which = WS_PARALYZE;
! 66: when 12: which = WS_MDEG;
! 67: when 13: which = WS_FEAR;
! 68: when 14: which = WS_CURING;
! 69: when 15: which = WS_LIGHT;
! 70: when 16: which = WS_HIT;
! 71: when 17: which = WS_DRAIN;
! 72: when 18: which = WS_CHARGE;
! 73: }
! 74: if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){
! 75: cursed = TRUE;
! 76: blessed = FALSE;
! 77: }
! 78: }
! 79:
! 80: tp = NULL;
! 81: switch (which) {
! 82: case WS_POLYMORPH:
! 83: case WS_SLOW_M:
! 84: case WS_TELMON:
! 85: case WS_CANCEL:
! 86: case WS_CONFMON:
! 87: case WS_DISINTEGRATE:
! 88: case WS_PETRIFY:
! 89: case WS_PARALYZE:
! 90: case WS_MDEG:
! 91: case WS_FEAR:
! 92: y = zapper->t_pos.y;
! 93: x = zapper->t_pos.x;
! 94:
! 95: do {
! 96: y += direction->y;
! 97: x += direction->x;
! 98: }
! 99: while (shoot_ok(winat(y, x)) && !(y == hero.y && x == hero.x));
! 100:
! 101: if (y == hero.y && x == hero.x)
! 102: is_player = TRUE;
! 103: else if (isalpha(mvwinch(mw, y, x))) {
! 104: item = find_mons(y, x);
! 105: tp = THINGPTR(item);
! 106: runto(tp, &hero);
! 107: turn_off(*tp, CANSURPRISE);
! 108: mname = monster_name(tp);
! 109: is_player = FALSE;
! 110:
! 111: /* The monster may not like being shot at */
! 112: if ((zapper == &player) &&
! 113: on(*tp, ISCHARMED) &&
! 114: save(VS_MAGIC, tp, 0)) {
! 115: msg("The eyes of %s turn clear.", prname(mname, FALSE));
! 116: turn_off(*tp, ISCHARMED);
! 117: mname = monster_name(tp);
! 118: }
! 119: }
! 120: else {
! 121: /*
! 122: * if monster misses player because the player dodged then lessen
! 123: * the chances he will use the wand again since the player appears
! 124: * to be rather dextrous
! 125: */
! 126: if (zapper != &player)
! 127: zapper->t_wand = zapper->t_wand * 3 / 5;
! 128: }
! 129: }
! 130: switch (which) {
! 131: case WS_LIGHT:
! 132: /*
! 133: * Reddy Kilowat wand. Light up the room
! 134: */
! 135: blue_light(blessed, cursed);
! 136: when WS_DRAIN:
! 137: /*
! 138: * Take away 1/2 of hero's hit points, then take it away
! 139: * evenly from the monsters in the room or next to hero
! 140: * if he is in a passage (but leave the monsters alone
! 141: * if the stick is cursed)
! 142: */
! 143: if (pstats.s_hpt < 2) {
! 144: msg("You are too weak to use it.");
! 145: }
! 146: else if (cursed)
! 147: pstats.s_hpt /= 2;
! 148: if (pstats.s_hpt <= 0) {
! 149: pstats.s_hpt = -1;
! 150: msg("You drain your own life away. --More--");
! 151: death(D_STRENGTH);
! 152: }
! 153: else
! 154: drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
! 155:
! 156: when WS_POLYMORPH:
! 157: {
! 158: register char oldch;
! 159: register struct room *rp;
! 160: register struct linked_list *pitem;
! 161: coord delta;
! 162:
! 163: if (tp == NULL)
! 164: break;
! 165: if (save(VS_MAGIC, tp, 0)) {
! 166: msg(nothing);
! 167: break;
! 168: }
! 169: rp = roomin(&tp->t_pos);
! 170: check_residue(tp);
! 171: delta.x = x;
! 172: delta.y = y;
! 173: detach(mlist, item);
! 174: oldch = tp->t_oldch;
! 175: pitem = tp->t_pack; /* save his pack */
! 176: tp->t_pack = NULL;
! 177:
! 178: if (levtype == OUTSIDE)
! 179: new_monster(item,rnd(NUMDINOS)+NUMMONST-NUMDINOS,&delta,FALSE);
! 180: else
! 181: new_monster(item,rnd(NUMMONST-NUMUNIQUE-NUMDINOS-1)+1,&delta,FALSE);
! 182:
! 183: if (tp->t_pack != NULL)
! 184: o_free_list (tp->t_pack);
! 185: tp->t_pack = pitem;
! 186: if (isalpha(mvwinch(cw, y, x)))
! 187: mvwaddch(cw, y, x, tp->t_type);
! 188: tp->t_oldch = oldch;
! 189: /*
! 190: * should the room light up?
! 191: */
! 192: if (on(*tp, HASFIRE)) {
! 193: if (rp) {
! 194: register struct linked_list *fire_item;
! 195:
! 196: fire_item = creat_item();
! 197: ldata(fire_item) = (char *) tp;
! 198: attach(rp->r_fires, fire_item);
! 199: rp->r_flags |= HASFIRE;
! 200: if (cansee(tp->t_pos.y,tp->t_pos.x) &&
! 201: next(rp->r_fires) == NULL) light(&hero);
! 202: }
! 203: }
! 204: runto(tp, &hero);
! 205: msg(terse ? "A new %s!"
! 206: : "You have created a new %s!",
! 207: monster_name(tp));
! 208: }
! 209:
! 210: when WS_PETRIFY:
! 211: if (tp == NULL)
! 212: break;
! 213: if (save(VS_MAGIC, tp, 0)) {
! 214: msg(nothing);
! 215: break;
! 216: }
! 217: check_residue(tp);
! 218: turn_on(*tp, ISSTONE);
! 219: turn_on(*tp, NOSTONE);
! 220: turn_off(*tp, ISRUN);
! 221: turn_off(*tp, ISINVIS);
! 222: turn_off(*tp, CANSURPRISE);
! 223: turn_off(*tp, ISDISGUISE);
! 224: tp->t_action = A_NIL;
! 225: tp->t_no_move = 0;
! 226: msg("%s is turned to stone!",prname(mname, TRUE));
! 227:
! 228: when WS_TELMON:
! 229: {
! 230: register int rm;
! 231: register struct room *rp;
! 232:
! 233: if (tp == NULL)
! 234: break;
! 235: if (save(VS_MAGIC, tp, 0)) {
! 236: msg(nothing);
! 237: break;
! 238: }
! 239: rp = NULL;
! 240: check_residue(tp);
! 241: tp->t_action = A_FREEZE; /* creature is disoriented */
! 242: tp->t_no_move = 2;
! 243: if (cursed) { /* Teleport monster to player */
! 244: if ((y == (hero.y + direction->y)) &&
! 245: (x == (hero.x + direction->x)))
! 246: msg(nothing);
! 247: else {
! 248: tp->t_pos.y = hero.y + direction->y;
! 249: tp->t_pos.x = hero.x + direction->x;
! 250: }
! 251: }
! 252: else if (blessed) { /* Get rid of monster */
! 253: killed(item, FALSE, TRUE, TRUE);
! 254: return;
! 255: }
! 256: else {
! 257: register int i=0;
! 258:
! 259: do { /* Move monster to another room */
! 260: rm = rnd_room();
! 261: rnd_pos(&rooms[rm], &tp->t_pos);
! 262: }until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500);
! 263: rp = &rooms[rm];
! 264: }
! 265:
! 266: /* Now move the monster */
! 267: if (isalpha(mvwinch(cw, y, x)))
! 268: mvwaddch(cw, y, x, tp->t_oldch);
! 269: mvwaddch(mw, y, x, ' ');
! 270: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
! 271: if (tp->t_pos.y != y || tp->t_pos.x != x)
! 272: tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
! 273: /*
! 274: * check to see if room that creature appears in should
! 275: * light up
! 276: */
! 277: if (on(*tp, HASFIRE)) {
! 278: if (rp) {
! 279: register struct linked_list *fire_item;
! 280:
! 281: fire_item = creat_item();
! 282: ldata(fire_item) = (char *) tp;
! 283: attach(rp->r_fires, fire_item);
! 284: rp->r_flags |= HASFIRE;
! 285: if(cansee(tp->t_pos.y, tp->t_pos.x) &&
! 286: next(rp->r_fires) == NULL)
! 287: light(&hero);
! 288: }
! 289: }
! 290: }
! 291: when WS_CANCEL:
! 292: if (tp == NULL)
! 293: break;
! 294: if (save(VS_MAGIC, tp, 0)) {
! 295: msg(nothing);
! 296: break;
! 297: }
! 298: check_residue(tp);
! 299: tp->t_flags[0] &= CANC0MASK;
! 300: tp->t_flags[1] &= CANC1MASK;
! 301: tp->t_flags[2] &= CANC2MASK;
! 302: tp->t_flags[3] &= CANC3MASK;
! 303: tp->t_flags[4] &= CANC4MASK;
! 304: tp->t_flags[5] &= CANC5MASK;
! 305: tp->t_flags[6] &= CANC6MASK;
! 306: tp->t_flags[7] &= CANC7MASK;
! 307: tp->t_flags[8] &= CANC8MASK;
! 308: tp->t_flags[9] &= CANC9MASK;
! 309: tp->t_flags[10] &= CANCAMASK;
! 310: tp->t_flags[11] &= CANCBMASK;
! 311: tp->t_flags[12] &= CANCCMASK;
! 312: tp->t_flags[13] &= CANCDMASK;
! 313: tp->t_flags[14] &= CANCEMASK;
! 314: tp->t_flags[15] &= CANCFMASK;
! 315:
! 316: when WS_MISSILE:
! 317: {
! 318: int dice;
! 319: static struct object bolt =
! 320: {
! 321: MISSILE , {0, 0}, 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1
! 322: };
! 323:
! 324: if (!obj)
! 325: dice = zapper->t_stats.s_lvl;
! 326: if (obj->o_type == RELIC)
! 327: dice = 15;
! 328: else if (EQUAL(ws_type[which], "staff"))
! 329: dice = 10;
! 330: else
! 331: dice = 6;
! 332: sprintf(bolt.o_hurldmg, "%dd4", dice);
! 333: do_motion(&bolt, direction->y, direction->x, zapper);
! 334: if (!hit_monster(unc(bolt.o_pos), &bolt, zapper))
! 335: msg("The missile vanishes with a puff of smoke");
! 336: }
! 337: when WS_HIT:
! 338: {
! 339: register unsigned char ch;
! 340: struct object strike; /* don't want to change sticks attributes */
! 341:
! 342: direction->y += hero.y;
! 343: direction->x += hero.x;
! 344: ch = winat(direction->y, direction->x);
! 345: if (isalpha(ch))
! 346: {
! 347: strike = *obj;
! 348: strike.o_hplus = 7;
! 349: if (EQUAL(ws_type[which], "staff"))
! 350: strcpy(strike.o_damage,"3d8");
! 351: else
! 352: strcpy(strike.o_damage,"2d8");
! 353: fight(direction, &strike, FALSE);
! 354: }
! 355: }
! 356: when WS_SLOW_M:
! 357: if (is_player) {
! 358: add_slow();
! 359: break;
! 360: }
! 361: if (tp == NULL)
! 362: break;
! 363: if (cursed) {
! 364: if (on(*tp, ISSLOW))
! 365: turn_off(*tp, ISSLOW);
! 366: else
! 367: turn_on(*tp, ISHASTE);
! 368: break;
! 369: }
! 370: if ((on(*tp,ISUNIQUE) && save(VS_MAGIC,tp,0)) || on(*tp,NOSLOW)) {
! 371: msg(nothing);
! 372: break;
! 373: }
! 374: else if (blessed) {
! 375: turn_off(*tp, ISRUN);
! 376: turn_on(*tp, ISHELD);
! 377: }
! 378: /*
! 379: * always slow in case he breaks free of HOLD
! 380: */
! 381: if (on(*tp, ISHASTE))
! 382: turn_off(*tp, ISHASTE);
! 383: else
! 384: turn_on(*tp, ISSLOW);
! 385:
! 386: when WS_CHARGE:
! 387: if (ws_know[WS_CHARGE] != TRUE && obj)
! 388: msg("This is a wand of charging.");
! 389: nitem = get_item(pack, "charge", STICK, FALSE, FALSE);
! 390: if (nitem != NULL) {
! 391: nobj = OBJPTR(nitem);
! 392: if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT))
! 393: fix_stick(nobj);
! 394: if (blessed) ++(nobj->o_charges);
! 395: if (EQUAL(ws_type[nobj->o_which], "staff")) {
! 396: if (nobj->o_charges > 200)
! 397: nobj->o_charges = 200;
! 398: }
! 399: else {
! 400: if (nobj->o_charges > 200)
! 401: nobj->o_charges = 200;
! 402: }
! 403: }
! 404: when WS_ELECT:
! 405: shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
! 406: "lightning bolt", roll(zapper->t_stats.s_lvl,6));
! 407:
! 408: when WS_FIRE:
! 409: shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
! 410: "flame", roll(zapper->t_stats.s_lvl,6));
! 411:
! 412: when WS_COLD:
! 413: shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
! 414: "ice", roll(zapper->t_stats.s_lvl,6));
! 415:
! 416: when WS_CONFMON:
! 417: if (cursed || is_player) {
! 418: if (!save(VS_WAND, &player, 0)) {
! 419: dsrpt_player();
! 420: confus_player();
! 421: }
! 422: else {
! 423: if (zapper != &player) zapper->t_wand /= 2;
! 424: msg(nothing);
! 425: }
! 426: }
! 427: else {
! 428: if (tp == NULL)
! 429: break;
! 430: if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR))
! 431: msg(nothing);
! 432: else
! 433: turn_on (*tp, ISHUH);
! 434: }
! 435: when WS_PARALYZE:
! 436: if (is_player || cursed) {
! 437: if ((obj && obj->o_type==RELIC) || !save(VS_WAND, &player, 0)){
! 438: player.t_no_move += 2 * movement(&player) * FREEZETIME;
! 439: player.t_action = A_FREEZE;
! 440: msg("You can't move.");
! 441: }
! 442: else {
! 443: if (zapper != &player) zapper->t_wand /= 2;
! 444: msg(nothing);
! 445: }
! 446: }
! 447: else {
! 448: if (tp == NULL)
! 449: break;
! 450: bonus = 0;
! 451: if (blessed) bonus = -3;
! 452: if (((obj && obj->o_type==RELIC) || !save(VS_WAND,tp,bonus)) &&
! 453: off(*tp, NOPARALYZE)) {
! 454: tp->t_no_move += 2 * movement(tp) * FREEZETIME;
! 455: tp->t_action = A_FREEZE;
! 456: }
! 457: else {
! 458: msg(nothing);
! 459: }
! 460: }
! 461: when WS_FEAR:
! 462: if (is_player) {
! 463: if (!on(player, ISFLEE) ||
! 464: ISWEARING(R_HEROISM) ||
! 465: save(VS_WAND, &player, 0)) {
! 466: msg(nothing);
! 467: zapper->t_wand /= 2;
! 468: }
! 469: else {
! 470: turn_on(player, ISFLEE);
! 471: player.t_dest = &zapper->t_pos;
! 472: msg("The sight of %s terrifies you.", prname(mname, FALSE));
! 473: }
! 474: break;
! 475: }
! 476: if (tp == NULL)
! 477: break;
! 478: bonus = 0;
! 479: if (blessed) bonus = -3;
! 480: if(save(VS_WAND, tp,bonus) || on(*tp,ISUNDEAD) || on(*tp,NOFEAR)){
! 481: msg(nothing);
! 482: break;
! 483: }
! 484: turn_on(*tp, ISFLEE);
! 485: turn_on(*tp, WASTURNED);
! 486:
! 487: /* Stop it from attacking us */
! 488: dsrpt_monster(tp, TRUE, cansee(tp->t_pos.y, tp->t_pos.x));
! 489:
! 490: /* If monster was suffocating, stop it */
! 491: if (on(*tp, DIDSUFFOCATE)) {
! 492: turn_off(*tp, DIDSUFFOCATE);
! 493: extinguish(suffocate);
! 494: }
! 495:
! 496: /* If monster held us, stop it */
! 497: if (on(*tp, DIDHOLD) && (--hold_count == 0))
! 498: turn_off(player, ISHELD);
! 499: turn_off(*tp, DIDHOLD);
! 500:
! 501: /* It is okay to turn tail */
! 502: tp->t_oldpos = tp->t_pos;
! 503:
! 504: when WS_MDEG:
! 505: if (is_player) {
! 506: if (save(VS_WAND, &player, 0)) {
! 507: msg (nothing);
! 508: zapper->t_wand /= 2;
! 509: break;
! 510: }
! 511: pstats.s_hpt /= 2;
! 512: if (pstats.s_hpt <= 0) {
! 513: pstats.s_hpt = -1;
! 514: msg("Your life has been sucked out from you! --More--");
! 515: wait_for(' ');
! 516: death(zapper->t_index);
! 517: }
! 518: else
! 519: msg("You feel a great drain on your system.");
! 520: }
! 521: if (tp == NULL)
! 522: break;
! 523: if (cursed) {
! 524: tp->t_stats.s_hpt *= 2;
! 525: msg("%s appears to be stronger now!", prname(mname, TRUE));
! 526: }
! 527: else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0))
! 528: msg (nothing);
! 529: else {
! 530: tp->t_stats.s_hpt /= 2;
! 531: msg("%s appears to be weaker now", prname(mname, TRUE));
! 532: }
! 533: if (tp->t_stats.s_hpt < 1)
! 534: killed(item, TRUE, TRUE, TRUE);
! 535: when WS_DISINTEGRATE:
! 536: if (tp == NULL)
! 537: break;
! 538: if (cursed) {
! 539: register int m1, m2;
! 540: coord mp;
! 541: struct linked_list *titem;
! 542: char ch;
! 543: struct thing *th;
! 544:
! 545: if (on(*tp, ISUNIQUE) || on(*tp, CANSELL)) {
! 546: msg (nothing);
! 547: break;
! 548: }
! 549: for (m1=tp->t_pos.x-1 ; m1 <= tp->t_pos.x+1 ; m1++) {
! 550: for(m2=tp->t_pos.y-1 ; m2<=tp->t_pos.y+1 ; m2++) {
! 551: if (m1 == hero.x && m2 == hero.y)
! 552: continue;
! 553: ch = winat(m2,m1);
! 554: if (shoot_ok(ch)) {
! 555: mp.x = m1; /* create it */
! 556: mp.y = m2;
! 557: titem = new_item(sizeof(struct thing));
! 558: new_monster(titem,(short)tp->t_index,&mp,FALSE);
! 559: th = THINGPTR(titem);
! 560: turn_on (*th, ISMEAN);
! 561: runto(th,&hero);
! 562: if (on(*th, HASFIRE)) {
! 563: register struct room *rp;
! 564:
! 565: rp = roomin(&th->t_pos);
! 566: if (rp) {
! 567: register struct linked_list *fire_item;
! 568:
! 569: fire_item = creat_item();
! 570: ldata(fire_item) = (char *) th;
! 571: attach(rp->r_fires, fire_item);
! 572: rp->r_flags |= HASFIRE;
! 573: if (cansee(th->t_pos.y, th->t_pos.x) &&
! 574: next(rp->r_fires) == NULL)
! 575: light(&hero);
! 576: }
! 577: }
! 578: }
! 579: }
! 580: }
! 581: }
! 582: else { /* if its a UNIQUE it might still live */
! 583: if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0)) {
! 584: tp->t_stats.s_hpt /= 2;
! 585: if (tp->t_stats.s_hpt < 1) {
! 586: killed(item, FALSE, TRUE, TRUE);
! 587: msg("You have disintegrated %s", prname(mname, FALSE));
! 588: }
! 589: else {
! 590: msg("%s appears wounded", prname(mname, TRUE));
! 591: }
! 592: }
! 593: else {
! 594: msg("You have disintegrated %s", prname(mname, FALSE));
! 595: killed (item, FALSE, TRUE, TRUE);
! 596: }
! 597: }
! 598: when WS_CURING:
! 599: if (cursed) {
! 600: bool sick = FALSE;
! 601: if (!save(VS_POISON, &player, 0)) {
! 602: msg("You feel extremely sick. ");
! 603: sick = TRUE;
! 604: pstats.s_hpt -= (pstats.s_hpt/3)+1;
! 605: if (pstats.s_hpt == 0) {
! 606: pstats.s_hpt = -1;
! 607: msg("You die! --More--");
! 608: wait_for(' ');
! 609: death (D_POISON);
! 610: }
! 611: }
! 612: if (!save(VS_WAND, &player, 0) && !ISWEARING(R_HEALTH)) {
! 613: turn_on(player, HASDISEASE);
! 614: turn_on(player, HASINFEST);
! 615: turn_on(player, DOROT);
! 616: fuse(cure_disease, NULL, roll(HEALTIME,SICKTIME), AFTER);
! 617: infest_dam++;
! 618: }
! 619: else if (sick == FALSE) msg("You feel momentarily sick");
! 620: }
! 621: else {
! 622: if (on(player, HASDISEASE) || on(player, HASINFEST)) {
! 623: extinguish(cure_disease);
! 624: turn_off(player, HASINFEST);
! 625: infest_dam = 0;
! 626: cure_disease(); /* this prints message */
! 627: }
! 628: if (on(player, DOROT)) {
! 629: msg("You feel your skin returning to normal.");
! 630: turn_off(player, DOROT);
! 631: }
! 632: pstats.s_hpt += roll(pstats.s_lvl, blessed ? 9 : 6);
! 633: if (pstats.s_hpt > max_stats.s_hpt)
! 634: pstats.s_hpt = max_stats.s_hpt;
! 635: msg("You begin to feel %sbetter.", blessed ? "much " : "");
! 636:
! 637: }
! 638: otherwise:
! 639: msg("What a bizarre schtick!");
! 640: }
! 641: }
! 642:
! 643:
! 644: /*
! 645: * drain:
! 646: * Do drain hit points from player shtick
! 647: */
! 648:
! 649: void
! 650: drain(int ymin, int ymax, int xmin, int xmax)
! 651: {
! 652: register int i, j, count;
! 653: register struct thing *ick;
! 654: register struct linked_list *item;
! 655:
! 656: /*
! 657: * First count how many things we need to spread the hit points among
! 658: */
! 659: count = 0;
! 660: for (i = ymin; i <= ymax; i++) {
! 661: if (i < 1 || i > lines - 3)
! 662: continue;
! 663: for (j = xmin; j <= xmax; j++) {
! 664: if (j < 0 || j > cols - 1)
! 665: continue;
! 666: if (isalpha(mvwinch(mw, i, j)))
! 667: count++;
! 668: }
! 669: }
! 670: if (count == 0)
! 671: {
! 672: msg("You have a tingling feeling.");
! 673: return;
! 674: }
! 675: count = pstats.s_hpt / count;
! 676: pstats.s_hpt /= 2;
! 677: if (pstats.s_hpt <= 0) {
! 678: pstats.s_hpt = -1;
! 679: msg("Aarrgghhh!! --More--");
! 680: wait_for(' ');
! 681: death(D_STRENGTH);
! 682: }
! 683: /*
! 684: * Now zot all of the monsters
! 685: */
! 686: for (i = ymin; i <= ymax; i++) {
! 687: if (i < 1 || i > lines - 3)
! 688: continue;
! 689: for (j = xmin; j <= xmax; j++) {
! 690: if (j < 0 || j > cols - 1)
! 691: continue;
! 692: if (isalpha(mvwinch(mw, i, j)) &&
! 693: ((item = find_mons(i, j)) != NULL)) {
! 694: ick = THINGPTR(item);
! 695: if (on(*ick, ISUNIQUE) && save(VS_MAGIC, ick, 0))
! 696: ick->t_stats.s_hpt -= count / 2;
! 697: else
! 698: ick->t_stats.s_hpt -= count;
! 699: if (ick->t_stats.s_hpt < 1)
! 700: killed(item,
! 701: cansee(i,j)&&(!on(*ick,ISINVIS)||on(player,CANSEE)),
! 702: TRUE, TRUE);
! 703: else {
! 704: runto(ick, &hero);
! 705:
! 706: /*
! 707: * The monster may not like being shot at. Since the
! 708: * shot is not aimed directly at the monster, we will
! 709: * give him a poorer save.
! 710: */
! 711: if (on(*ick, ISCHARMED) && save(VS_MAGIC, ick, -2)) {
! 712: msg("The eyes of %s turn clear.",
! 713: prname(monster_name(ick), FALSE));
! 714: turn_off(*ick, ISCHARMED);
! 715: }
! 716: if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE)))
! 717: msg("%s appears wounded",
! 718: prname(monster_name(ick), TRUE));
! 719: }
! 720: }
! 721: }
! 722: }
! 723: }
! 724:
! 725: /*
! 726: * initialize a stick
! 727: */
! 728:
! 729: void
! 730: fix_stick(struct object *cur)
! 731: {
! 732: if (EQUAL(ws_type[cur->o_which], "staff")) {
! 733: cur->o_weight = 100;
! 734: cur->o_charges = 5 + rnd(11);
! 735: strcpy(cur->o_damage,"3d4");
! 736: cur->o_hplus = 1;
! 737: cur->o_dplus = 0;
! 738: switch (cur->o_which) {
! 739: case WS_HIT:
! 740: cur->o_hplus = 3;
! 741: cur->o_dplus = 3;
! 742: strcpy(cur->o_damage,"2d8");
! 743: when WS_LIGHT:
! 744: cur->o_charges = 15 + rnd(11);
! 745: }
! 746: }
! 747: else {
! 748: strcpy(cur->o_damage,"2d3");
! 749: cur->o_weight = 75;
! 750: cur->o_hplus = 1;
! 751: cur->o_dplus = 0;
! 752: cur->o_charges = 5 + rnd(11);
! 753: switch (cur->o_which) {
! 754: case WS_HIT:
! 755: cur->o_hplus = 3;
! 756: cur->o_dplus = 3;
! 757: strcpy(cur->o_damage,"2d8");
! 758: when WS_LIGHT:
! 759: cur->o_charges = 15 + rnd(11);
! 760: }
! 761: }
! 762: strcpy(cur->o_hurldmg,"3d3");
! 763:
! 764: }
! 765:
! 766: /*
! 767: * Use the wand that our monster is wielding.
! 768: */
! 769:
! 770: void
! 771: m_use_wand(struct thing *monster)
! 772: {
! 773: register struct object *obj;
! 774:
! 775: /* Make sure we really have it */
! 776: if (monster->t_using)
! 777: obj = OBJPTR(monster->t_using);
! 778: else {
! 779: debug("Stick not set!");
! 780: monster->t_action = A_NIL;
! 781: return;
! 782: }
! 783:
! 784: if (obj->o_type != STICK) {
! 785: debug("Stick not selected!");
! 786: monster->t_action = A_NIL;
! 787: return;
! 788: }
! 789: /*
! 790: * shoot the stick!
! 791: * assume all blessed sticks are normal for now.
! 792: * Note that we don't get here if the wand is cursed.
! 793: */
! 794: msg("%s points a %s at you!", prname(monster_name(monster), TRUE),
! 795: ws_type[obj->o_which]);
! 796: do_zap(monster, obj, &monster->t_newpos, obj->o_which, 0);
! 797: monster->t_wand /= 2; /* chance lowers with each use */
! 798: }
! 799:
! 800: /*
! 801: * type: type of item, NULL means stick
! 802: * which: which item
! 803: */
! 804: bool
! 805: need_dir(int type, int which)
! 806: {
! 807: if (type == STICK || type == 0) {
! 808: switch (which) {
! 809: case WS_LIGHT:
! 810: case WS_DRAIN:
! 811: case WS_CHARGE:
! 812: case WS_CURING:
! 813: return(FALSE);
! 814: default:
! 815: return(TRUE);
! 816: }
! 817: }
! 818: else if (type == RELIC) {
! 819: switch (which) {
! 820: case MING_STAFF:
! 821: case ASMO_ROD:
! 822: case EMORI_CLOAK:
! 823: return(TRUE);
! 824: default:
! 825: return(FALSE);
! 826: }
! 827: }
! 828: return (FALSE); /* hope we don't get here */
! 829: }
! 830:
! 831: /*
! 832: * let the player zap a stick and see what happens
! 833: */
! 834:
! 835: bool
! 836: player_zap(int which, int flag)
! 837: {
! 838: register struct linked_list *item;
! 839: register struct object *obj;
! 840:
! 841: obj = NULL;
! 842: if (which == 0) {
! 843: /* This is a stick. It takes 2 movement periods to zap it */
! 844: if (player.t_action != C_ZAP) {
! 845: if ((item = get_item(pack,"zap with",ZAPPABLE,FALSE,FALSE)) == NULL)
! 846: return(FALSE);
! 847:
! 848: obj = OBJPTR(item);
! 849:
! 850: if (need_dir(obj->o_type, obj->o_which)) {
! 851: if (!get_dir(&player.t_newpos))
! 852: return(FALSE);
! 853: }
! 854: player.t_using = item; /* Remember what it is */
! 855: player.t_action = C_ZAP; /* We are quaffing */
! 856: player.t_no_move = 2 * movement(&player);
! 857: return(TRUE);
! 858: }
! 859:
! 860: item = player.t_using;
! 861: /* We've waited our time, let's shoot 'em up! */
! 862: player.t_using = NULL;
! 863: player.t_action = A_NIL;
! 864:
! 865: obj = OBJPTR(item);
! 866:
! 867: /* Handle relics specially here */
! 868: if (obj->o_type == RELIC) {
! 869: switch (obj->o_which) {
! 870: case ORCUS_WAND:
! 871: /* msg(nothing); */
! 872: read_scroll(S_PETRIFY, 0, FALSE);
! 873: return(TRUE);
! 874: when MING_STAFF:
! 875: which = WS_MISSILE;
! 876: when EMORI_CLOAK:
! 877: which = WS_PARALYZE;
! 878: obj->o_charges = 0; /* one zap/day (whatever that is) */
! 879: fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
! 880: when ASMO_ROD:
! 881: switch (rnd(3)) {
! 882: case 0: which = WS_ELECT;
! 883: when 1: which = WS_COLD;
! 884: otherwise: which = WS_FIRE;
! 885: }
! 886: }
! 887: }
! 888: else {
! 889: which = obj->o_which;
! 890: ws_know[which] = TRUE;
! 891: flag = obj->o_flags;
! 892: }
! 893: }
! 894: do_zap(&player, obj, &player.t_newpos, which, flag);
! 895: return(TRUE);
! 896: }
! 897:
CVSweb