[BACK]Return to sticks.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / urogue

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