[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

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