Annotation of early-roguelike/arogue5/sticks.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Functions to implement the various sticks one might find
! 3: * while wandering around the dungeon.
! 4: *
! 5: * Advanced Rogue
! 6: * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 7: * All rights reserved.
! 8: *
! 9: * Based on "Rogue: Exploring the Dungeons of Doom"
! 10: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 11: * All rights reserved.
! 12: *
! 13: * See the file LICENSE.TXT for full copyright and licensing information.
! 14: */
! 15:
! 16: #include "curses.h"
! 17: #include <ctype.h>
! 18: #include <string.h>
! 19: #include "rogue.h"
! 20:
! 21: void drain(int ymin, int ymax, int xmin, int xmax);
! 22:
! 23: /*
! 24: * zap a stick and see what happens
! 25: */
! 26: bool
! 27: do_zap(bool gotdir, int which, int flag)
! 28: {
! 29: register struct linked_list *item;
! 30: register struct object *obj = NULL;
! 31: register struct thing *tp;
! 32: register int y, x;
! 33: struct linked_list *nitem;
! 34: struct object *nobj;
! 35: bool cursed, blessed, is_stick;
! 36:
! 37: blessed = FALSE;
! 38: cursed = FALSE;
! 39: is_stick = FALSE;
! 40:
! 41: if (which == 0) {
! 42: if ((item = get_item(pack, "zap with", ZAPPABLE)) == NULL)
! 43: return(FALSE);
! 44: obj = OBJPTR(item);
! 45:
! 46: /* Handle relics specially here */
! 47: if (obj->o_type == RELIC) {
! 48: switch (obj->o_which) {
! 49: case ORCUS_WAND:
! 50: msg(nothing);
! 51: return(TRUE);
! 52: when MING_STAFF:
! 53: which = WS_MISSILE;
! 54: when ASMO_ROD:
! 55: switch (rnd(3)) {
! 56: case 0:
! 57: which = WS_ELECT;
! 58: when 1:
! 59: which = WS_COLD;
! 60: otherwise:
! 61: which = WS_FIRE;
! 62: }
! 63: }
! 64: cursed = FALSE;
! 65: blessed = FALSE;
! 66: }
! 67: else {
! 68: which = obj->o_which;
! 69: ws_know[which] = TRUE;
! 70: cursed = (obj->o_flags & ISCURSED) != 0;
! 71: blessed = (obj->o_flags & ISBLESSED) != 0;
! 72: is_stick = TRUE;
! 73: }
! 74: }
! 75: else {
! 76: cursed = flag & ISCURSED;
! 77: blessed = flag & ISBLESSED;
! 78: }
! 79: switch (which) { /* no direction for these */
! 80: case WS_LIGHT:
! 81: case WS_DRAIN:
! 82: case WS_CHARGE:
! 83: case WS_CURING:
! 84: break;
! 85:
! 86: default:
! 87: if (!get_dir())
! 88: return(FALSE);
! 89: if (!gotdir) {
! 90: do {
! 91: delta.y = rnd(3) - 1;
! 92: delta.x = rnd(3) - 1;
! 93: } while (delta.y == 0 && delta.x == 0);
! 94: }
! 95: }
! 96:
! 97: if (is_stick) {
! 98: if (obj->o_charges < 1) {
! 99: msg(nothing);
! 100: return(TRUE);
! 101: }
! 102: obj->o_charges--;
! 103: }
! 104: if (which == WS_WONDER) {
! 105: switch (rnd(14)) {
! 106: case 0: which = WS_ELECT;
! 107: when 1: which = WS_FIRE;
! 108: when 2: which = WS_COLD;
! 109: when 3: which = WS_POLYMORPH;
! 110: when 4: which = WS_MISSILE;
! 111: when 5: which = WS_SLOW_M;
! 112: when 6: which = WS_TELMON;
! 113: when 7: which = WS_CANCEL;
! 114: when 8: which = WS_CONFMON;
! 115: when 9: which = WS_DISINTEGRATE;
! 116: when 10: which = WS_PETRIFY;
! 117: when 11: which = WS_PARALYZE;
! 118: when 12: which = WS_MDEG;
! 119: when 13: which = WS_FEAR;
! 120: }
! 121: if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){
! 122: cursed = TRUE;
! 123: blessed = FALSE;
! 124: }
! 125: }
! 126:
! 127: switch (which) {
! 128: case WS_LIGHT:
! 129: /*
! 130: * Reddy Kilowat wand. Light up the room
! 131: */
! 132: blue_light(blessed, cursed);
! 133: when WS_DRAIN:
! 134: /*
! 135: * Take away 1/2 of hero's hit points, then take it away
! 136: * evenly from the monsters in the room or next to hero
! 137: * if he is in a passage (but leave the monsters alone
! 138: * if the stick is cursed)
! 139: */
! 140: if (pstats.s_hpt < 2) {
! 141: msg("You are too weak to use it.");
! 142: return(TRUE);
! 143: }
! 144: if (cursed)
! 145: pstats.s_hpt /= 2;
! 146: else
! 147: drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
! 148: when WS_POLYMORPH:
! 149: case WS_TELMON:
! 150: case WS_CANCEL:
! 151: {
! 152: register char monster, oldch;
! 153: register int rm;
! 154:
! 155: y = hero.y;
! 156: x = hero.x;
! 157: while (shoot_ok(winat(y, x))) {
! 158: y += delta.y;
! 159: x += delta.x;
! 160: }
! 161: if (isalpha(monster = CCHAR( mvwinch(mw, y, x) ))) {
! 162: register struct room *rp;
! 163:
! 164: item = find_mons(y, x);
! 165: tp = THINGPTR(item);
! 166: /* if the monster gets the saving throw, leave the case */
! 167: if (save(VS_MAGIC, tp, 0)) {
! 168: msg(nothing);
! 169: break;
! 170: }
! 171:
! 172: /* Unhold player */
! 173: if (on(*tp, DIDHOLD)) {
! 174: turn_off(*tp, DIDHOLD);
! 175: if (--hold_count == 0) turn_off(player, ISHELD);
! 176: }
! 177: /* unsuffocate player */
! 178: if (on(*tp, DIDSUFFOCATE)) {
! 179: turn_off(*tp, DIDSUFFOCATE);
! 180: extinguish(suffocate);
! 181: }
! 182: rp = roomin(&tp->t_pos);
! 183: /*
! 184: * check to see if room should go dark
! 185: */
! 186: if (on(*tp, HASFIRE)) {
! 187: if (rp != NULL) {
! 188: register struct linked_list *fire_item;
! 189:
! 190: for (fire_item = rp->r_fires; fire_item != NULL;
! 191: fire_item = next(fire_item)) {
! 192: if (THINGPTR(fire_item) == tp) {
! 193: detach(rp->r_fires, fire_item);
! 194: destroy_item(fire_item);
! 195: if (rp->r_fires == NULL) {
! 196: rp->r_flags &= ~HASFIRE;
! 197: if(cansee(tp->t_pos.y,tp->t_pos.x))
! 198: light(&hero);
! 199: }
! 200: break;
! 201: }
! 202: }
! 203: }
! 204: }
! 205:
! 206: if (which == WS_POLYMORPH) {
! 207: register struct linked_list *pitem;
! 208:
! 209: delta.x = x;
! 210: delta.y = y;
! 211: detach(mlist, item);
! 212: oldch = tp->t_oldch;
! 213: pitem = tp->t_pack; /* save his pack */
! 214: tp->t_pack = NULL;
! 215: new_monster(item,rnd(NUMMONST-NUMUNIQUE-1)+1,&delta,FALSE);
! 216: if (tp->t_pack != NULL)
! 217: o_free_list (tp->t_pack);
! 218: tp->t_pack = pitem;
! 219: monster = tp->t_type;
! 220: if (isalpha(mvwinch(cw, y, x)))
! 221: mvwaddch(cw, y, x, monster);
! 222: tp->t_oldch = oldch;
! 223: /*
! 224: * should the room light up?
! 225: */
! 226: if (on(*tp, HASFIRE)) {
! 227: if (rp) {
! 228: register struct linked_list *fire_item;
! 229:
! 230: fire_item = creat_item();
! 231: ldata(fire_item) = (char *) tp;
! 232: attach(rp->r_fires, fire_item);
! 233: rp->r_flags |= HASFIRE;
! 234: if (cansee(tp->t_pos.y,tp->t_pos.x) &&
! 235: next(rp->r_fires) == NULL) light(&hero);
! 236: }
! 237: }
! 238: msg(terse ? "A new %s!" : "You have created a new %s!",
! 239: monsters[tp->t_index].m_name);
! 240: }
! 241: else if (which == WS_CANCEL) {
! 242: tp->t_flags[0] &= CANC0MASK;
! 243: tp->t_flags[1] &= CANC1MASK;
! 244: tp->t_flags[2] &= CANC2MASK;
! 245: tp->t_flags[3] &= CANC3MASK;
! 246: tp->t_flags[4] &= CANC4MASK;
! 247: tp->t_flags[4] &= CANC5MASK;
! 248: }
! 249: else { /* A teleport stick */
! 250: if (cursed) { /* Teleport monster to player */
! 251: if ((y == (hero.y + delta.y)) &&
! 252: (x == (hero.x + delta.x)))
! 253: msg(nothing);
! 254: else {
! 255: tp->t_pos.y = hero.y + delta.y;
! 256: tp->t_pos.x = hero.x + delta.x;
! 257: }
! 258: }
! 259: else if (blessed) { /* Get rid of monster */
! 260: killed(item, FALSE, TRUE);
! 261: return(TRUE);
! 262: }
! 263: else {
! 264: register int i=0;
! 265:
! 266: do { /* Move monster to another room */
! 267: rm = rnd_room();
! 268: rnd_pos(&rooms[rm], &tp->t_pos);
! 269: }until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500);
! 270: rp = &rooms[rm];
! 271: }
! 272:
! 273: /* Now move the monster */
! 274: if (isalpha(mvwinch(cw, y, x)))
! 275: mvwaddch(cw, y, x, tp->t_oldch);
! 276: turn_off(*tp, ISDISGUISE);
! 277: mvwaddch(mw, y, x, ' ');
! 278: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
! 279: if (tp->t_pos.y != y || tp->t_pos.x != x)
! 280: tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
! 281: /*
! 282: * check to see if room that creature appears in should
! 283: * light up
! 284: */
! 285: if (on(*tp, HASFIRE)) {
! 286: register struct linked_list *fire_item;
! 287:
! 288: fire_item = creat_item();
! 289: ldata(fire_item) = (char *) tp;
! 290: attach(rp->r_fires, fire_item);
! 291: rp->r_flags |= HASFIRE;
! 292: if(cansee(tp->t_pos.y, tp->t_pos.x) &&
! 293: next(rp->r_fires) == NULL)
! 294: light(&hero);
! 295: }
! 296: }
! 297: runto(tp, &hero);
! 298: }
! 299: }
! 300: when WS_MISSILE:
! 301: {
! 302: static struct object bolt =
! 303: {
! 304: MISSILE , {0, 0}, "", 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1
! 305: };
! 306:
! 307: sprintf(bolt.o_hurldmg, "%dd4", pstats.s_lvl);
! 308: do_motion(&bolt, delta.y, delta.x, &player);
! 309: if (!hit_monster(unc(bolt.o_pos), &bolt, &player))
! 310: msg("The missile vanishes with a puff of smoke");
! 311: }
! 312: when WS_HIT:
! 313: {
! 314: register char ch;
! 315: struct object strike; /* don't want to change sticks attributes */
! 316:
! 317: delta.y += hero.y;
! 318: delta.x += hero.x;
! 319: ch = CCHAR( winat(delta.y, delta.x) );
! 320: if (isalpha(ch))
! 321: {
! 322: strike = *obj;
! 323: strike.o_hplus = 6;
! 324: if (EQUAL(ws_type[which], "staff"))
! 325: strcpy(strike.o_damage,"3d8");
! 326: else
! 327: strcpy(strike.o_damage,"2d8");
! 328: fight(&delta, &strike, FALSE);
! 329: }
! 330: }
! 331: case WS_SLOW_M:
! 332: y = hero.y;
! 333: x = hero.x;
! 334: while (shoot_ok(winat(y, x))) {
! 335: y += delta.y;
! 336: x += delta.x;
! 337: }
! 338: if (isalpha(mvwinch(mw, y, x))) {
! 339: item = find_mons(y, x);
! 340: tp = THINGPTR(item);
! 341: runto(tp, &hero);
! 342: if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0))
! 343: msg(nothing);
! 344: else if (on(*tp, NOSLOW))
! 345: msg(nothing);
! 346: else if (cursed) {
! 347: if (on(*tp, ISSLOW))
! 348: turn_off(*tp, ISSLOW);
! 349: else
! 350: turn_on(*tp, ISHASTE);
! 351: }
! 352: else if (blessed) {
! 353: turn_off(*tp, ISRUN);
! 354: turn_on(*tp, ISHELD);
! 355: return(TRUE);
! 356: }
! 357: else {
! 358: if (on(*tp, ISHASTE))
! 359: turn_off(*tp, ISHASTE);
! 360: else
! 361: turn_on(*tp, ISSLOW);
! 362: tp->t_turn = TRUE;
! 363: }
! 364: }
! 365: when WS_CHARGE:
! 366: if (ws_know[WS_CHARGE] != TRUE && is_stick)
! 367: msg("This is a wand of charging.");
! 368: if ((nitem = get_item(pack, "charge", STICK)) != NULL) {
! 369: nobj = OBJPTR(nitem);
! 370: if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT))
! 371: fix_stick(nobj);
! 372: if (EQUAL(ws_type[nobj->o_which], "staff")) {
! 373: if (nobj->o_charges > 100)
! 374: nobj->o_charges = 100;
! 375: }
! 376: else {
! 377: if (nobj->o_charges > 50)
! 378: nobj->o_charges = 50;
! 379: }
! 380: }
! 381: when WS_ELECT:
! 382: case WS_FIRE:
! 383: case WS_COLD:
! 384: {
! 385: char *name;
! 386:
! 387: if (which == WS_ELECT)
! 388: name = "lightning bolt";
! 389: else if (which == WS_FIRE)
! 390: name = "flame";
! 391: else
! 392: name = "ice";
! 393:
! 394: shoot_bolt( &player, hero,
! 395: delta, TRUE, D_BOLT,
! 396: name, roll(pstats.s_lvl,6));
! 397: }
! 398: when WS_PETRIFY: {
! 399: reg int m1, m2, x1, y1;
! 400: reg char ch;
! 401: reg struct linked_list *ll;
! 402: reg struct thing *lt;
! 403:
! 404: y1 = hero.y;
! 405: x1 = hero.x;
! 406: do {
! 407: y1 += delta.y;
! 408: x1 += delta.x;
! 409: ch = CCHAR( winat(y1,x1) );
! 410: } while (ch == PASSAGE || ch == FLOOR);
! 411: for (m1 = x1 - 1 ; m1 <= x1 + 1 ; m1++) {
! 412: for(m2 = y1 - 1 ; m2 <= y1 + 1 ; m2++) {
! 413: ch = CCHAR( winat(m2,m1) );
! 414: if (m1 == hero.x && m2 == hero.y)
! 415: continue;
! 416: if (ch != ' ') {
! 417: ll = find_obj(m2,m1);
! 418: if (ll != NULL) {
! 419: detach(lvl_obj,ll);
! 420: o_discard(ll);
! 421: }
! 422: ll = find_mons(m2,m1);
! 423: if (ll != NULL) {
! 424: lt = THINGPTR(ll);
! 425: if (on(*lt, ISUNIQUE))
! 426: monsters[lt->t_index].m_normal = TRUE;
! 427: check_residue(lt);
! 428: detach(mlist,ll);
! 429: t_discard(ll);
! 430: mvwaddch(mw,m2,m1,' ');
! 431: }
! 432: mvaddch(m2,m1,' ');
! 433: mvwaddch(cw,m2,m1,' ');
! 434: }
! 435: }
! 436: }
! 437: touchwin(cw);
! 438: touchwin(mw);
! 439: }
! 440: when WS_CONFMON:
! 441: if (cursed) {
! 442: if (off(player, ISCLEAR)) {
! 443: if (on(player, ISHUH))
! 444: lengthen(unconfuse, rnd(20)+HUHDURATION);
! 445: else {
! 446: turn_on(player, ISHUH);
! 447: fuse(unconfuse,0,rnd(20)+HUHDURATION,AFTER);
! 448: msg("Wait, what's going on here. Huh? What? Who?");
! 449: }
! 450: }
! 451: else msg("You feel dizzy for a moment, but it quickly passes.");
! 452: }
! 453: else {
! 454: y = hero.y;
! 455: x = hero.x;
! 456: while (shoot_ok(winat(y, x)))
! 457: {
! 458: y += delta.y;
! 459: x += delta.x;
! 460: }
! 461: if (isalpha(mvwinch(mw, y, x)))
! 462: {
! 463: item = find_mons(y, x);
! 464: tp = THINGPTR(item);
! 465: if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR))
! 466: msg(nothing);
! 467: else
! 468: turn_on (*tp, ISHUH);
! 469: runto(tp, &hero);
! 470: }
! 471: }
! 472: when WS_PARALYZE:
! 473: if (cursed) {
! 474: no_command += FREEZETIME;
! 475: msg("You can't move.");
! 476: }
! 477: else {
! 478: y = hero.y;
! 479: x = hero.x;
! 480: while (shoot_ok(winat(y, x)))
! 481: {
! 482: y += delta.y;
! 483: x += delta.x;
! 484: }
! 485: if (isalpha(mvwinch(mw, y, x)))
! 486: {
! 487: item = find_mons(y, x);
! 488: tp = THINGPTR(item);
! 489: if (save(VS_WAND, tp, 0) || on(*tp, NOPARALYZE))
! 490: msg(nothing);
! 491: else {
! 492: tp->t_no_move = FREEZETIME;
! 493: }
! 494: runto(tp, &hero);
! 495: }
! 496: }
! 497: when WS_FEAR:
! 498: y = hero.y;
! 499: x = hero.x;
! 500: while (shoot_ok(winat(y, x)))
! 501: {
! 502: y += delta.y;
! 503: x += delta.x;
! 504: }
! 505: if (isalpha(mvwinch(mw, y, x)))
! 506: {
! 507: item = find_mons(y, x);
! 508: tp = THINGPTR(item);
! 509: runto(tp, &hero);
! 510: if (save(VS_WAND, tp, 0) ||
! 511: on(*tp, ISUNDEAD) ||
! 512: on(*tp, NOFEAR))
! 513: msg(nothing);
! 514: else {
! 515: turn_on(*tp, ISFLEE);
! 516: turn_on(*tp, WASTURNED);
! 517:
! 518: /* If monster was suffocating, stop it */
! 519: if (on(*tp, DIDSUFFOCATE)) {
! 520: turn_off(*tp, DIDSUFFOCATE);
! 521: extinguish(suffocate);
! 522: }
! 523:
! 524: /* If monster held us, stop it */
! 525: if (on(*tp, DIDHOLD) && (--hold_count == 0))
! 526: turn_off(player, ISHELD);
! 527: turn_off(*tp, DIDHOLD);
! 528: }
! 529: }
! 530: when WS_MDEG:
! 531: y = hero.y;
! 532: x = hero.x;
! 533: while (shoot_ok(winat(y, x)))
! 534: {
! 535: y += delta.y;
! 536: x += delta.x;
! 537: }
! 538: if (isalpha(mvwinch(mw, y, x)))
! 539: {
! 540: item = find_mons(y, x);
! 541: tp = THINGPTR(item);
! 542: if (cursed) {
! 543: tp->t_stats.s_hpt *= 2;
! 544: msg("The %s appears to be stronger now!",
! 545: monsters[tp->t_index].m_name);
! 546: }
! 547: else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0))
! 548: msg (nothing);
! 549: else {
! 550: tp->t_stats.s_hpt /= 2;
! 551: msg("The %s appears to be weaker now",
! 552: monsters[tp->t_index].m_name);
! 553: }
! 554: runto(tp, &hero);
! 555: if (tp->t_stats.s_hpt < 1)
! 556: killed(item, TRUE, TRUE);
! 557: }
! 558: when WS_DISINTEGRATE:
! 559: y = hero.y;
! 560: x = hero.x;
! 561: while (shoot_ok(winat(y, x))) {
! 562: y += delta.y;
! 563: x += delta.x;
! 564: }
! 565: if (isalpha(mvwinch(mw, y, x))) {
! 566: item = find_mons(y, x);
! 567: tp = THINGPTR(item);
! 568: turn_on (*tp, ISMEAN);
! 569: runto(tp, &hero);
! 570: if (cursed) {
! 571: register int m1, m2;
! 572: coord mp;
! 573: struct linked_list *titem;
! 574: char ch;
! 575: struct thing *th;
! 576:
! 577: if (on(*tp, ISUNIQUE)) {
! 578: msg (nothing);
! 579: break;
! 580: }
! 581: for (m1=tp->t_pos.x-1 ; m1 <= tp->t_pos.x+1 ; m1++) {
! 582: for(m2=tp->t_pos.y-1 ; m2<=tp->t_pos.y+1 ; m2++) {
! 583: ch = CCHAR( winat(m2,m1) );
! 584: if (shoot_ok(ch) && ch != PLAYER) {
! 585: mp.x = m1; /* create it */
! 586: mp.y = m2;
! 587: titem = new_item(sizeof(struct thing));
! 588: new_monster(titem,(short)tp->t_index,&mp,FALSE);
! 589: th = THINGPTR(titem);
! 590: turn_on (*th, ISMEAN);
! 591: runto(th,&hero);
! 592: if (on(*th, HASFIRE)) {
! 593: register struct room *rp;
! 594:
! 595: rp = roomin(&th->t_pos);
! 596: if (rp) {
! 597: register struct linked_list *fire_item;
! 598:
! 599: fire_item = creat_item();
! 600: ldata(fire_item) = (char *) th;
! 601: attach(rp->r_fires, fire_item);
! 602: rp->r_flags |= HASFIRE;
! 603: if (cansee(th->t_pos.y, th->t_pos.x) &&
! 604: next(rp->r_fires) == NULL)
! 605: light(&hero);
! 606: }
! 607: }
! 608: }
! 609: }
! 610: }
! 611: }
! 612: else { /* if its a UNIQUE it might still live */
! 613: tp = THINGPTR(item);
! 614: if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0)) {
! 615: tp->t_stats.s_hpt /= 2;
! 616: if (tp->t_stats.s_hpt < 1) {
! 617: killed(item, FALSE, TRUE);
! 618: msg("You have disintegrated the %s",
! 619: monsters[tp->t_index].m_name);
! 620: }
! 621: else {
! 622: msg("The %s appears wounded",
! 623: monsters[tp->t_index].m_name);
! 624: }
! 625: }
! 626: else {
! 627: msg("You have disintegrated the %s",
! 628: monsters[tp->t_index].m_name);
! 629: killed (item, FALSE, TRUE);
! 630: }
! 631: }
! 632: }
! 633: when WS_CURING:
! 634: ws_know[WS_CURING] = TRUE;
! 635: if (cursed) {
! 636: if (!save(VS_POISON, &player, 0)) {
! 637: msg("You feel extremely sick now");
! 638: pstats.s_hpt /=2;
! 639: if (pstats.s_hpt == 0) death (D_POISON);
! 640: }
! 641: if (!save(VS_WAND, &player, 0) && !ISWEARING(R_HEALTH)) {
! 642: turn_on(player, HASDISEASE);
! 643: turn_on(player, HASINFEST);
! 644: turn_on(player, DOROT);
! 645: fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER);
! 646: infest_dam++;
! 647: }
! 648: else msg("You fell momentarily sick");
! 649: }
! 650: else {
! 651: if (on(player, HASDISEASE)) {
! 652: extinguish(cure_disease);
! 653: cure_disease();
! 654: msg(terse ? "You feel yourself improving."
! 655: : "You begin to feel yourself improving again.");
! 656: }
! 657: if (on(player, HASINFEST)) {
! 658: turn_off(player, HASINFEST);
! 659: infest_dam = 0;
! 660: msg(terse ? "You feel yourself improving."
! 661: : "You begin to feel yourself improving again.");
! 662: }
! 663: if (on(player, DOROT)) {
! 664: msg("You feel your skin returning to normal.");
! 665: turn_off(player, DOROT);
! 666: }
! 667: pstats.s_hpt += roll(pstats.s_lvl, blessed ? 6 : 4);
! 668: if (pstats.s_hpt > max_stats.s_hpt)
! 669: pstats.s_hpt = max_stats.s_hpt;
! 670: msg("You begin to feel %sbetter.", blessed ? "much " : "");
! 671:
! 672: }
! 673: otherwise:
! 674: msg("What a bizarre schtick!");
! 675: }
! 676: return(TRUE);
! 677: }
! 678:
! 679:
! 680: /*
! 681: * drain:
! 682: * Do drain hit points from player shtick
! 683: */
! 684:
! 685: void
! 686: drain(int ymin, int ymax, int xmin, int xmax)
! 687: {
! 688: register int i, j, count;
! 689: register struct thing *ick;
! 690: register struct linked_list *item;
! 691:
! 692: /*
! 693: * First count how many things we need to spread the hit points among
! 694: */
! 695: count = 0;
! 696: for (i = ymin; i <= ymax; i++) {
! 697: if (i < 1 || i > LINES - 3)
! 698: continue;
! 699: for (j = xmin; j <= xmax; j++) {
! 700: if (j < 0 || j > COLS - 1)
! 701: continue;
! 702: if (isalpha(mvwinch(mw, i, j)))
! 703: count++;
! 704: }
! 705: }
! 706: if (count == 0)
! 707: {
! 708: msg("You have a tingling feeling");
! 709: return;
! 710: }
! 711: count = pstats.s_hpt / count;
! 712: pstats.s_hpt /= 2;
! 713: /*
! 714: * Now zot all of the monsters
! 715: */
! 716: for (i = ymin; i <= ymax; i++) {
! 717: if (i < 1 || i > LINES - 3)
! 718: continue;
! 719: for (j = xmin; j <= xmax; j++) {
! 720: if (j < 0 || j > COLS - 1)
! 721: continue;
! 722: if (isalpha(mvwinch(mw, i, j)) &&
! 723: ((item = find_mons(i, j)) != NULL)) {
! 724: ick = THINGPTR(item);
! 725: if (on(*ick, ISUNIQUE) && save(VS_MAGIC, ick, 0))
! 726: ick->t_stats.s_hpt -= count / 2;
! 727: else
! 728: ick->t_stats.s_hpt -= count;
! 729: if (ick->t_stats.s_hpt < 1)
! 730: killed(item,
! 731: cansee(i,j)&&(!on(*ick,ISINVIS)||on(player,CANSEE)),
! 732: TRUE);
! 733: else {
! 734: runto(ick, &hero);
! 735: if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE)))
! 736: msg("The %s appears wounded",
! 737: monsters[ick->t_index].m_name);
! 738: }
! 739: }
! 740: }
! 741: }
! 742: }
! 743:
! 744: /*
! 745: * initialize a stick
! 746: */
! 747: void
! 748: fix_stick(struct object *cur)
! 749: {
! 750: if (EQUAL(ws_type[cur->o_which], "staff")) {
! 751: cur->o_weight = 100;
! 752: cur->o_charges = 5 + rnd(10);
! 753: strcpy(cur->o_damage,"2d3");
! 754: cur->o_hplus = 1;
! 755: cur->o_dplus = 0;
! 756: switch (cur->o_which) {
! 757: case WS_HIT:
! 758: cur->o_hplus = 3;
! 759: cur->o_dplus = 3;
! 760: strcpy(cur->o_damage,"2d8");
! 761: when WS_LIGHT:
! 762: cur->o_charges = 20 + rnd(10);
! 763: }
! 764: }
! 765: else {
! 766: strcpy(cur->o_damage,"1d3");
! 767: cur->o_weight = 60;
! 768: cur->o_hplus = 1;
! 769: cur->o_dplus = 0;
! 770: cur->o_charges = 3 + rnd(5);
! 771: switch (cur->o_which) {
! 772: case WS_HIT:
! 773: cur->o_hplus = 3;
! 774: cur->o_dplus = 3;
! 775: strcpy(cur->o_damage,"1d8");
! 776: when WS_LIGHT:
! 777: cur->o_charges = 10 + rnd(10);
! 778: }
! 779: }
! 780: strcpy(cur->o_hurldmg,"1d1");
! 781:
! 782: }
! 783:
! 784: /*
! 785: * shoot_bolt fires a bolt from the given starting point in the
! 786: * given direction
! 787: */
! 788:
! 789: bool
! 790: shoot_bolt(struct thing *shooter, coord start, coord dir, bool get_points,
! 791: short reason, char *name, int damage)
! 792: {
! 793: register char dirch = 0, ch;
! 794: register bool used, change;
! 795: register short y, x, bounces;
! 796: bool mdead = FALSE;
! 797: coord pos;
! 798: struct {
! 799: coord place;
! 800: char oldch;
! 801: } spotpos[BOLT_LENGTH];
! 802:
! 803: switch (dir.y + dir.x) {
! 804: case 0: dirch = '/';
! 805: when 1: case -1: dirch = (dir.y == 0 ? '-' : '|');
! 806: when 2: case -2: dirch = '\\';
! 807: }
! 808: pos.y = start.y + dir.y;
! 809: pos.x = start.x + dir.x;
! 810: used = FALSE;
! 811: change = FALSE;
! 812:
! 813: bounces = 0; /* No bounces yet */
! 814: for (y = 0; y < BOLT_LENGTH && !used; y++)
! 815: {
! 816: ch = CCHAR( winat(pos.y, pos.x) );
! 817: spotpos[y].place = pos;
! 818: spotpos[y].oldch = CCHAR( mvwinch(cw, pos.y, pos.x) );
! 819:
! 820: /* Are we at hero? */
! 821: if (ce(pos, hero)) goto at_hero;
! 822:
! 823: switch (ch)
! 824: {
! 825: case SECRETDOOR:
! 826: case '|':
! 827: case '-':
! 828: case ' ':
! 829: if (dirch == '-' || dirch == '|') {
! 830: dir.y = -dir.y;
! 831: dir.x = -dir.x;
! 832: }
! 833: else {
! 834: char chx = CCHAR( mvinch(pos.y-dir.y, pos.x) ),
! 835: chy = CCHAR( mvinch(pos.y, pos.x-dir.x) );
! 836: bool anychange = FALSE; /* Did we change anthing */
! 837:
! 838: if (chy == WALL || chy == SECRETDOOR ||
! 839: chy == '-' || chy == '|') {
! 840: dir.y = -dir.y;
! 841: change ^= TRUE; /* Change at least one direction */
! 842: anychange = TRUE;
! 843: }
! 844: if (chx == WALL || chx == SECRETDOOR ||
! 845: chx == '-' || chx == '|') {
! 846: dir.x = -dir.x;
! 847: change ^= TRUE; /* Change at least one direction */
! 848: anychange = TRUE;
! 849: }
! 850:
! 851: /* If we didn't make any change, make both changes */
! 852: if (!anychange) {
! 853: dir.x = -dir.x;
! 854: dir.y = -dir.y;
! 855: }
! 856: }
! 857:
! 858: /* Do we change how the bolt looks? */
! 859: if (change) {
! 860: change = FALSE;
! 861: if (dirch == '\\') dirch = '/';
! 862: else if (dirch == '/') dirch = '\\';
! 863: }
! 864:
! 865: y--; /* The bounce doesn't count as using up the bolt */
! 866:
! 867: /* Make sure we aren't in an infinite bounce */
! 868: if (++bounces > BOLT_LENGTH) used = TRUE;
! 869: msg("The %s bounces", name);
! 870: break;
! 871: default:
! 872: if (isalpha(ch)) {
! 873: register struct linked_list *item;
! 874: register struct thing *tp;
! 875: register const char *mname;
! 876: bool see_monster = cansee(pos.y, pos.x);
! 877:
! 878: item = find_mons(unc(pos));
! 879: tp = THINGPTR(item);
! 880: mname = monsters[tp->t_index].m_name;
! 881:
! 882: if (!save(VS_BREATH, tp, -(shooter->t_stats.s_lvl/10))) {
! 883: if (see_monster) {
! 884: if (on(*tp, ISDISGUISE) &&
! 885: (tp->t_type != tp->t_disguise)) {
! 886: msg("Wait! That's a %s!", mname);
! 887: turn_off(*tp, ISDISGUISE);
! 888: }
! 889:
! 890: sprintf(outstring,"The %s hits the %s", name, mname);
! 891: msg(outstring);
! 892: }
! 893:
! 894: tp->t_wasshot = TRUE;
! 895: runto(tp, &hero);
! 896: used = TRUE;
! 897:
! 898: /* Hit the monster -- does it do anything? */
! 899: if ((EQUAL(name,"ice") &&
! 900: (on(*tp, NOCOLD) || on(*tp, ISUNDEAD))) ||
! 901: (EQUAL(name,"flame") && on(*tp, NOFIRE)) ||
! 902: (EQUAL(name,"acid") && on(*tp, NOACID)) ||
! 903: (EQUAL(name,"lightning bolt")&& on(*tp,NOBOLT)) ||
! 904: (EQUAL(name,"nerve gas") &&on(*tp,NOPARALYZE))||
! 905: (EQUAL(name,"sleeping gas") &&
! 906: (on(*tp, NOSLEEP) || on(*tp, ISUNDEAD))) ||
! 907: (EQUAL(name,"slow gas") && on(*tp,NOSLOW)) ||
! 908: (EQUAL(name,"fear gas") && on(*tp,NOFEAR)) ||
! 909: (EQUAL(name,"confusion gas") && on(*tp,ISCLEAR)) ||
! 910: (EQUAL(name,"chlorine gas") && on(*tp,NOGAS))) {
! 911: if (see_monster){
! 912: sprintf(outstring,"The %s has no effect on the %s.",
! 913: name, mname);
! 914: msg(outstring);
! 915: }
! 916: }
! 917:
! 918: /*
! 919: * Check for gas with special effects
! 920: */
! 921: else if (EQUAL(name, "nerve gas")) {
! 922: tp->t_no_move = FREEZETIME;
! 923: }
! 924: else if (EQUAL(name, "sleeping gas")) {
! 925: tp->t_no_move = SLEEPTIME;
! 926: }
! 927: else if (EQUAL(name, "slow gas")) {
! 928: if (on(*tp, ISHASTE))
! 929: turn_off(*tp, ISHASTE);
! 930: else
! 931: turn_on(*tp, ISSLOW);
! 932: tp->t_turn = TRUE;
! 933: }
! 934: else if (EQUAL(name, "fear gas")) {
! 935: turn_on(*tp, ISFLEE);
! 936: tp->t_dest = &hero;
! 937: }
! 938: else if (EQUAL(name, "confusion gas")) {
! 939: turn_on(*tp, ISHUH);
! 940: tp->t_dest = &hero;
! 941: }
! 942: else if ((EQUAL(name, "lightning bolt")) &&
! 943: on(*tp, BOLTDIVIDE)) {
! 944: if (creat_mons(tp, tp->t_index, FALSE)) {
! 945: if (see_monster){
! 946: sprintf(outstring,"The %s divides the %s.",name,mname);
! 947: msg(outstring);
! 948: }
! 949: light(&hero);
! 950: }
! 951: else if (see_monster){
! 952: sprintf(outstring,"The %s has no effect on the %s.",
! 953: name, mname);
! 954: msg(outstring);
! 955: }
! 956: }
! 957: else {
! 958: if(save(VS_BREATH,tp, -(shooter->t_stats.s_lvl/10)))
! 959: damage /= 2;
! 960:
! 961: /* The poor fellow got killed! */
! 962: if ((tp->t_stats.s_hpt -= damage) <= 0) {
! 963: if (see_monster){
! 964: sprintf(outstring,"The %s kills the %s", name, mname);
! 965: msg(outstring);
! 966: }
! 967: else
! 968: msg("You hear a faint groan in the distance");
! 969: killed(item, FALSE, get_points);
! 970:
! 971: /* Replace the screen character */
! 972: spotpos[y].oldch = CCHAR( mvwinch(cw, pos.y, pos.x) );
! 973:
! 974: mdead = TRUE;
! 975: }
! 976: else { /* Not dead, so just scream */
! 977: if (!see_monster)
! 978: msg("You hear a scream in the distance");
! 979: }
! 980: }
! 981: }
! 982: else if (isalpha(show(pos.y, pos.x))) {
! 983: if (see_monster) {
! 984: if (terse)
! 985: msg("%s misses", name);
! 986: else {
! 987: sprintf(outstring,"The %s whizzes past the %s", name, mname);
! 988: msg(outstring);
! 989: }
! 990: }
! 991: if (get_points) runto(tp, &hero);
! 992: }
! 993: }
! 994: else if (pos.y == hero.y && pos.x == hero.x) {
! 995: at_hero: if (!save(VS_BREATH, &player,
! 996: -(shooter->t_stats.s_lvl/10))){
! 997: if (terse)
! 998: msg("The %s hits you", name);
! 999: else
! 1000: msg("You are hit by the %s", name);
! 1001: used = TRUE;
! 1002:
! 1003: /*
! 1004: * The Amulet of Yendor protects against all "breath"
! 1005: *
! 1006: * The following two if statements could be combined
! 1007: * into one, but it makes the compiler barf, so split
! 1008: * it up
! 1009: */
! 1010: if (cur_relic[YENDOR_AMULET] ||
! 1011: (EQUAL(name,"chlorine gas")&&on(player, NOGAS)) ||
! 1012: (EQUAL(name,"sleeping gas")&&ISWEARING(R_ALERT))){
! 1013: msg("The %s has no affect", name);
! 1014: }
! 1015: else if((EQUAL(name, "flame") && on(player, NOFIRE)) ||
! 1016: (EQUAL(name, "ice") && on(player, NOCOLD)) ||
! 1017: (EQUAL(name,"fear gas")&&ISWEARING(R_HEROISM))){
! 1018: msg("The %s has no affect", name);
! 1019: }
! 1020: /*
! 1021: * Check for gas with special effects
! 1022: */
! 1023: else if (EQUAL(name, "nerve gas")) {
! 1024: msg("The nerve gas paralyzes you.");
! 1025: no_command += FREEZETIME;
! 1026: }
! 1027: else if (EQUAL(name, "sleeping gas")) {
! 1028: msg("The sleeping gas puts you to sleep.");
! 1029: no_command += SLEEPTIME;
! 1030: }
! 1031: else if (EQUAL(name, "confusion gas")) {
! 1032: if (off(player, ISCLEAR)) {
! 1033: if (on(player, ISHUH))
! 1034: lengthen(unconfuse, rnd(20)+HUHDURATION);
! 1035: else {
! 1036: turn_on(player, ISHUH);
! 1037: fuse(unconfuse,0,rnd(20)+HUHDURATION,AFTER);
! 1038: msg("The confusion gas has confused you.");
! 1039: }
! 1040: }
! 1041: else msg("You feel dizzy for a moment, but it quickly passes.");
! 1042: }
! 1043: else if (EQUAL(name, "slow gas")) {
! 1044: add_slow();
! 1045: }
! 1046: else if (EQUAL(name, "fear gas")) {
! 1047: turn_on(player, ISFLEE);
! 1048: player.t_dest = &shooter->t_pos;
! 1049: msg("The fear gas terrifies you.");
! 1050: }
! 1051: else {
! 1052: if(save(VS_BREATH,&player, -(shooter->t_stats.s_lvl/10)))
! 1053: damage /= 2;
! 1054: if ((pstats.s_hpt -= damage) <= 0)
! 1055: death(reason);
! 1056: }
! 1057: }
! 1058: else
! 1059: msg("The %s whizzes by you", name);
! 1060: }
! 1061:
! 1062: mvwaddch(cw, pos.y, pos.x, dirch);
! 1063: draw(cw);
! 1064: }
! 1065:
! 1066: pos.y += dir.y;
! 1067: pos.x += dir.x;
! 1068: }
! 1069: for (x = y - 1; x >= 0; x--)
! 1070: mvwaddch(cw, spotpos[x].place.y, spotpos[x].place.x, spotpos[x].oldch);
! 1071: return(mdead);
! 1072: }
CVSweb