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

Annotation of early-roguelike/xrogue/actions.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:     actions.c  -  functions for dealing with monster actions
        !             3:
        !             4:     XRogue: Expeditions into the Dungeons of Doom
        !             5:     Copyright (C) 1991 Robert Pietkivitch
        !             6:     All rights reserved.
        !             7:
        !             8:     Based on "Advanced Rogue"
        !             9:     Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
        !            10:     All rights reserved.
        !            11:
        !            12:     Based on "Rogue: Exploring the Dungeons of Doom"
        !            13:     Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
        !            14:     All rights reserved.
        !            15:
        !            16:     See the file LICENSE.TXT for full copyright and licensing information.
        !            17: */
        !            18:
        !            19: #include <ctype.h>
        !            20: #include <curses.h>
        !            21: #include <limits.h>
        !            22: #include "rogue.h"
        !            23:
        !            24: int mf_count = 0;       /* move_free counter - see actions.c(m_act()) */
        !            25: int mf_jmpcnt = 0;      /* move_free counter for # of jumps           */
        !            26:
        !            27: void m_breathe(struct thing *tp);
        !            28: void m_select(struct thing *th, bool flee);
        !            29: void m_sonic(struct thing *tp);
        !            30: void m_spell(struct thing *tp);
        !            31: void m_summon(struct thing *tp);
        !            32: bool m_use_it(struct thing *tp, bool flee, struct room *rer, struct room *ree);
        !            33: bool m_use_pack(struct thing *monster, coord *defend_pos, int dist,
        !            34:                 coord *shoot_dir);
        !            35:
        !            36: /*
        !            37:  * Did we disrupt a spell?
        !            38:  */
        !            39: void
        !            40: dsrpt_monster(struct thing *tp, bool always, bool see_him)
        !            41: {
        !            42:     switch (tp->t_action) {
        !            43:     case A_SUMMON:
        !            44:     case A_MISSILE:
        !            45:     case A_SLOW:
        !            46:         tp->t_action = A_NIL;   /* Just make the old fellow start over again */
        !            47:         tp->t_no_move = movement(tp);
        !            48:         tp->t_using = NULL; /* Just to be on the safe side */
        !            49:         turn_on(*tp, WASDISRUPTED);
        !            50:         if (see_him)
        !            51:             msg("%s's spell has been disrupted.",prname(monster_name(tp),TRUE));
        !            52:         /*
        !            53:          * maybe choose something else to do next time since player
        !            54:          * is disrupting us
        !            55:          */
        !            56:         tp->t_summon *= 2;
        !            57:         tp->t_cast /= 2;
        !            58:         return;
        !            59:     }
        !            60:
        !            61:     /* We may want to disrupt other actions, too */
        !            62:     if (always) {
        !            63:         tp->t_action = A_NIL; /* Just make the old fellow start over again */
        !            64:         tp->t_no_move = movement(tp);
        !            65:         tp->t_using = NULL;/* Just to be on the safe side */
        !            66:     }
        !            67: }
        !            68:
        !            69: void
        !            70: dsrpt_player(void)
        !            71: {
        !            72:     int which, action;
        !            73:     struct linked_list *item;
        !            74:     struct object *obj;
        !            75:
        !            76:     action = player.t_action;
        !            77:     which = player.t_selection;
        !            78:
        !            79:     switch (action) {
        !            80:     case C_CAST: /* Did we disrupt a spell? */
        !            81:     case C_PRAY:
        !            82:     case C_CHANT:
        !            83:     {
        !            84:         msg("Your %s was disrupted!", action == C_CAST ? "spell" : "prayer");
        !            85:
        !            86:         /* Charge him 1/4 anyway */
        !            87:         if (action == C_CAST)
        !            88:             spell_power += magic_spells[which].s_cost / 4;
        !            89:         else if (action == C_PRAY)
        !            90:             pray_time += cleric_spells[which].s_cost / 4;
        !            91:         else if (action == C_CHANT)
        !            92:             chant_time += druid_spells[which].s_cost / 4;
        !            93:     }
        !            94:     when C_COUNT: /* counting of gold? */
        !            95:     {
        !            96:         if (purse > 0) {
        !            97:             msg("Your gold goes flying everywhere!");
        !            98:             do {
        !            99:                 item = spec_item(GOLD, 0, 0, 0);
        !           100:                 obj = OBJPTR(item);
        !           101:                 obj->o_count = min(purse, rnd(20)+1);
        !           102:                 purse -= obj->o_count;
        !           103:                 obj->o_pos = hero;
        !           104:                 fall(item, FALSE);
        !           105:             } while (purse > 0 && rnd(25) != 1);
        !           106:         }
        !           107:     }
        !           108:     when C_EAT:
        !           109:         msg("Ack!  You gag on your food for a moment. ");
        !           110:         del_pack(player.t_using);
        !           111:
        !           112:     when A_PICKUP:
        !           113:         msg("You drop what you are picking up! ");
        !           114:
        !           115:     when C_SEARCH:      /* searching for traps and secret doors... */
        !           116:         msg("Ouch!  You decide to stop searching. ");
        !           117:         count = 0;      /* don't search again */
        !           118:
        !           119:     when C_SETTRAP:
        !           120:         msg("Ouch!  You can't set a trap right now. ");
        !           121:
        !           122:     when A_NIL:
        !           123:     default:
        !           124:         return;
        !           125:     }
        !           126:     player.t_no_move = movement(&player); /* disoriented for a while */
        !           127:     player.t_action = A_NIL;
        !           128:     player.t_selection = 0;
        !           129: }
        !           130:
        !           131: /*
        !           132:  * m_act:
        !           133:  *      If the critter isn't doing anything, choose an action for it.
        !           134:  *      Otherwise, let it perform its chosen action.
        !           135:  */
        !           136:
        !           137: void
        !           138: m_act(struct thing *tp)
        !           139: {
        !           140:     struct object *obj;
        !           141:     bool flee;          /* Are we scared? */
        !           142:
        !           143:     /* What are we planning to do? */
        !           144:     switch (tp->t_action) {
        !           145:         default:
        !           146:             /* An unknown action! */
        !           147:             msg("Unknown monster action (%d)", tp->t_action);
        !           148:
        !           149:             /* Fall through */
        !           150:
        !           151:         case A_NIL:
        !           152:             /* If the monster is fairly intelligent and about to die, it
        !           153:              * may turn tail and run.  But if we are a FRIENDLY creature
        !           154:              * in the hero's service, don't run.
        !           155:              */
        !           156:             if (off(*tp, ISFLEE)                                        &&
        !           157:                 tp->t_stats.s_hpt < tp->maxstats.s_hpt                  &&
        !           158:                 tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/6)       &&
        !           159:                 (off(*tp, ISFRIENDLY) || tp->t_dest != &hero)           &&
        !           160:                 rnd(25) < tp->t_stats.s_intel) {
        !           161:                     turn_on(*tp, ISFLEE);
        !           162:
        !           163:                     /* It is okay to turn tail */
        !           164:                     tp->t_oldpos = tp->t_pos;
        !           165:                 }
        !           166:
        !           167:             /* Should the monster run away? */
        !           168:             flee = on(*tp, ISFLEE) ||
        !           169:                 ((tp->t_dest == &hero) && on(player, ISINWALL) &&
        !           170:                  off(*tp, CANINWALL));
        !           171:
        !           172:             m_select(tp, flee); /* Select an action */
        !           173:             return;
        !           174:
        !           175:         when A_ATTACK:
        !           176:             /*
        !           177:              * We're trying to attack the player or monster at t_newpos
        !           178:              * if the prey moved, do nothing
        !           179:              */
        !           180:             obj = tp->t_using ? OBJPTR(tp->t_using) : NULL;
        !           181:             if (ce(tp->t_newpos, hero)) {
        !           182:                 attack(tp, obj, FALSE);
        !           183:             }
        !           184:             else if (mvwinch(mw, tp->t_newpos.y, tp->t_newpos.x) &&
        !           185:                      step_ok(tp->t_newpos.y, tp->t_newpos.x, FIGHTOK, tp)) {
        !           186:                 skirmish(tp, &tp->t_newpos, obj, FALSE);
        !           187:             }
        !           188:
        !           189:         when A_SELL:
        !           190:                 /* Is the quartermaster still next to us? */
        !           191:             if (ce(tp->t_newpos, hero)) sell(tp);
        !           192:
        !           193:                 /* The quartermaster moved away */
        !           194:             else if (off(player, ISBLIND) && cansee(unc(tp->t_pos)) &&
        !           195:                 (off(*tp, ISINVIS)     || on(player, CANSEE)) &&
        !           196:                 (off(*tp, ISSHADOW)    || on(player, CANSEE)) &&
        !           197:                 (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT)) &&
        !           198:         (rnd(12) < 4))
        !           199:                 msg("%s grunts with frustration",prname(monster_name(tp),TRUE));
        !           200:
        !           201:         when A_MOVE:
        !           202:             /* Let's try to move */
        !           203:             do_chase(tp);
        !           204:
        !           205:             /* If t_no_move > 0, we found that we have to fight! */
        !           206:             if (tp->t_no_move > 0) return;
        !           207:
        !           208:         when A_BREATHE:
        !           209:             /* Breathe on the critter */
        !           210:             m_breathe(tp);
        !           211:
        !           212:         when A_SLOW:
        !           213:             /* make him move slower */
        !           214:             add_slow();
        !           215:             turn_off(*tp, CANSLOW);
        !           216:
        !           217:         when A_MISSILE:
        !           218:             /* Start up a magic missile spell */
        !           219:             m_spell(tp);
        !           220:
        !           221:         when A_SONIC:
        !           222:             /* Let out a sonic blast! */
        !           223:             m_sonic(tp);
        !           224:
        !           225:         when A_THROW:
        !           226:             /* We're throwing something (like an arrow) */
        !           227:             missile(tp->t_newpos.y, tp->t_newpos.x, tp->t_using, tp);
        !           228:
        !           229:         when A_SUMMON:
        !           230:             /* We're summoning help */
        !           231:             m_summon(tp);
        !           232:
        !           233:         when A_USERELIC:
        !           234:             /* Use our relic */
        !           235:             m_use_relic(tp);
        !           236:
        !           237:         when A_USEWAND:
        !           238:             /* use the wand we have */
        !           239:             m_use_wand(tp);
        !           240:     }
        !           241:
        !           242:     /* Can we in fact move?  (we might have solidified in solid rock) */
        !           243:     if (!step_ok(hero.y, hero.x, NOMONST, &player)) {
        !           244:
        !           245:          if (move_free > 1) goto jump_over;   /* avoid messages */
        !           246:          if (mf_count > 2)  goto jump_over;   /* limit messages */
        !           247:
        !           248:          if (pstats.s_hpt < 1) {
        !           249:          pstats.s_hpt = -1;
        !           250:              msg("You have merged into the surroundings!  --More--");
        !           251:              wait_for(' ');
        !           252:              death(D_PETRIFY);
        !           253:          }
        !           254:          else {
        !           255:              mf_count += 1;  /* count number of times we are here */
        !           256:              pstats.s_hpt -= rnd(2)+1;
        !           257:              if (pstats.s_hpt < 1) {
        !           258:           pstats.s_hpt = -1;
        !           259:                   msg("You have merged into the surroundings!  --More--");
        !           260:                   wait_for(' ');
        !           261:                   death(D_PETRIFY);
        !           262:              }
        !           263:          }
        !           264:          switch (rnd(51)) {
        !           265:              case 0: msg("Arrrggghhhhh!! ");
        !           266:              when 5: msg("You can't move! ");
        !           267:              when 10: msg("You motion angrily! ");
        !           268:              when 15: msg("You feel so weird! ");
        !           269:              when 20: msg("If only you could phase. ");
        !           270:              when 25: msg("The rock maggots are closing in! ");
        !           271:              when 30: msg("You wrench and wrench and wrench... ");
        !           272:              when 35: msg("You wish you could teleport out of here! ");
        !           273:              when 40: msg("Your feel your life force ebbing away... ");
        !           274:              when 45: msg("You partially regain your senses. ");
        !           275:              when 50: msg("The rock maggots have found you!!! ");
        !           276:              otherwise: pstats.s_hpt -= rnd(4)+1;
        !           277:          }
        !           278:          if (pstats.s_hpt < 1) {
        !           279:           pstats.s_hpt = -1;
        !           280:               msg("You lose the urge to live...  --More--");
        !           281:               wait_for(' ');
        !           282:               death(D_PETRIFY);
        !           283:      }
        !           284:         jump_over:
        !           285:         mf_jmpcnt++;          /* count this jump */
        !           286:         if (mf_jmpcnt > 9) {  /* take a few turns, then reset it */
        !           287:             mf_jmpcnt = 0;
        !           288:             mf_count  = 0;
        !           289:         }
        !           290:     }
        !           291:
        !           292:     /* No action now */
        !           293:     tp->t_action = A_NIL;
        !           294:     tp->t_using = NULL;
        !           295: }
        !           296:
        !           297: /*
        !           298:  * m_breathe:
        !           299:  *      Breathe in the chosen direction.
        !           300:  */
        !           301:
        !           302: void
        !           303: m_breathe(struct thing *tp)
        !           304: {
        !           305:     register int damage;
        !           306:     register char *breath = NULL;
        !           307:
        !           308:     damage = tp->t_stats.s_hpt;
        !           309:     turn_off(*tp, CANSURPRISE);
        !           310:
        !           311:     /* Will it breathe at random */
        !           312:     if (on(*tp, CANBRANDOM)) {
        !           313:         /* Turn off random breath */
        !           314:         turn_off(*tp, CANBRANDOM);
        !           315:
        !           316:         /* Select type of breath */
        !           317:         switch (rnd(10)) {
        !           318:             case 0: breath = "acid";
        !           319:                     turn_on(*tp, NOACID);
        !           320:             when 1: breath = "flame";
        !           321:                     turn_on(*tp, NOFIRE);
        !           322:             when 2: breath = "lightning bolt";
        !           323:                     turn_on(*tp, NOBOLT);
        !           324:             when 3: breath = "chlorine gas";
        !           325:                     turn_on(*tp, NOGAS);
        !           326:             when 4: breath = "ice";
        !           327:                     turn_on(*tp, NOCOLD);
        !           328:             when 5: breath = "nerve gas";
        !           329:                     turn_on(*tp, NOPARALYZE);
        !           330:             when 6: breath = "sleeping gas";
        !           331:                     turn_on(*tp, NOSLEEP);
        !           332:             when 7: breath = "slow gas";
        !           333:                     turn_on(*tp, NOSLOW);
        !           334:             when 8: breath = "confusion gas";
        !           335:                     turn_on(*tp, ISCLEAR);
        !           336:             when 9: breath = "fear gas";
        !           337:                     turn_on(*tp, NOFEAR);
        !           338:         }
        !           339:     }
        !           340:
        !           341:     /* Or can it breathe acid? */
        !           342:     else if (on(*tp, CANBACID)) {
        !           343:         turn_off(*tp, CANBACID);
        !           344:         breath = "acid";
        !           345:     }
        !           346:
        !           347:     /* Or can it breathe fire */
        !           348:     else if (on(*tp, CANBFIRE)) {
        !           349:         turn_off(*tp, CANBFIRE);
        !           350:         breath = "flame";
        !           351:     }
        !           352:
        !           353:     /* Or can it breathe electricity? */
        !           354:     else if (on(*tp, CANBBOLT)) {
        !           355:         turn_off(*tp, CANBBOLT);
        !           356:         breath = "lightning bolt";
        !           357:     }
        !           358:
        !           359:     /* Or can it breathe gas? */
        !           360:     else if (on(*tp, CANBGAS)) {
        !           361:         turn_off(*tp, CANBGAS);
        !           362:         breath = "chlorine gas";
        !           363:     }
        !           364:
        !           365:     /* Or can it breathe ice? */
        !           366:     else if (on(*tp, CANBICE)) {
        !           367:         turn_off(*tp, CANBICE);
        !           368:         breath = "ice";
        !           369:     }
        !           370:
        !           371:     else if (on(*tp, CANBPGAS)) {
        !           372:         turn_off(*tp, CANBPGAS);
        !           373:         breath = "nerve gas";
        !           374:     }
        !           375:
        !           376:     /* can it breathe sleeping gas */
        !           377:     else if (on(*tp, CANBSGAS)) {
        !           378:         turn_off(*tp, CANBSGAS);
        !           379:         breath = "sleeping gas";
        !           380:     }
        !           381:
        !           382:     /* can it breathe slow gas */
        !           383:     else if (on(*tp, CANBSLGAS)) {
        !           384:         turn_off(*tp, CANBSLGAS);
        !           385:         breath = "slow gas";
        !           386:     }
        !           387:
        !           388:     /* can it breathe confusion gas */
        !           389:     else if (on(*tp, CANBCGAS)) {
        !           390:         turn_off(*tp, CANBCGAS);
        !           391:         breath = "confusion gas";
        !           392:     }
        !           393:
        !           394:     /* can it breathe fear gas */
        !           395:     else {
        !           396:         turn_off(*tp, CANBFGAS);
        !           397:         breath = "fear gas";
        !           398:     }
        !           399:
        !           400:     /* Now breathe */
        !           401:     shoot_bolt(tp, tp->t_pos, tp->t_newpos, FALSE,
        !           402:                     tp->t_index, breath, damage);
        !           403:
        !           404:     running = FALSE;
        !           405:     if (fight_flush) flushinp();
        !           406: }
        !           407:
        !           408: /*
        !           409:  * m_select:
        !           410:  *      Select an action for the monster.
        !           411:  * flee: True if running away or player is inaccessible in wall
        !           412:  */
        !           413:
        !           414: void
        !           415: m_select(struct thing *th, bool flee)
        !           416: {
        !           417:     register struct room *rer, *ree;    /* room of chaser, room of chasee */
        !           418:     int dist = INT_MIN;
        !           419:     int mindist = INT_MAX, maxdist = INT_MIN;
        !           420:     bool rundoor;                       /* TRUE means run to a door */
        !           421:     char sch;
        !           422:     coord *last_door=0,                 /* Door we just came from */
        !           423:            this;                        /* Temporary destination for chaser */
        !           424:
        !           425:     rer = roomin(&th->t_pos);   /* Find room of chaser */
        !           426:     ree = roomin(th->t_dest);   /* Find room of chasee */
        !           427:
        !           428:     /* First see if we want to use an ability or weapon */
        !           429:     if (m_use_it(th, flee, rer, ree)) return;
        !           430:
        !           431:     /*
        !           432:      * We don't count monsters on doors as inside rooms here because when
        !           433:      * a monster is in a room and the player is not in that room, the
        !           434:      * monster looks for the best door out.  If we counted doors as part
        !           435:      * of the room, the monster would already be on the best door out;
        !           436:      * so he would never move.
        !           437:      */
        !           438:     if ((sch = mvwinch(stdscr, th->t_pos.y, th->t_pos.x)) == DOOR ||
        !           439:         sch == SECRETDOOR || sch == PASSAGE) {
        !           440:         rer = NULL;
        !           441:     }
        !           442:     this = *th->t_dest;
        !           443:
        !           444:     /*
        !           445:      * If we are in a room heading for the player and the player is not
        !           446:      * in the room with us, we run to the "best" door.
        !           447:      * If we are in a room fleeing from the player, then we run to the
        !           448:      * "best" door if he IS in the same room.
        !           449:      *
        !           450:      * Note:  We don't bother with doors in mazes or if we can walk
        !           451:      * through walls.
        !           452:      */
        !           453:     if (rer != NULL && levtype != MAZELEV && off(*th, CANINWALL)) {
        !           454:         if (flee) rundoor = (rer == ree);
        !           455:         else rundoor = (rer != ree);
        !           456:     }
        !           457:     else rundoor = FALSE;
        !           458:
        !           459:     if (rundoor) {
        !           460:         register struct linked_list *exitptr;   /* For looping through exits */
        !           461:         coord *exit,                            /* A particular door */
        !           462:               *entrance;                        /* Place just inside doorway */
        !           463:         int exity, exitx;                       /* Door's coordinates */
        !           464:         char dch='\0';                          /* Door character */
        !           465:
        !           466:         if ((th->t_doorgoal.x != -1) && (th->t_doorgoal.y != -1))
        !           467:             dch = mvwinch(stdscr, th->t_doorgoal.y, th->t_doorgoal.x);
        !           468:
        !           469:         /* Do we have a valid goal? */
        !           470:         if ((dch == PASSAGE || dch == DOOR) &&  /* A real door */
        !           471:             (!flee || !ce(th->t_doorgoal, *th->t_dest))) { /* Prey should not
        !           472:                                                              * be at door if
        !           473:                                                              * we are running
        !           474:                                                              * away
        !           475:                                                              */
        !           476:             /* Make sure the player is not in the doorway, either */
        !           477:             entrance = doorway(rer, &th->t_doorgoal);
        !           478:             if (!flee || entrance == NULL || !ce(*entrance, *th->t_dest)) {
        !           479:                 this = th->t_doorgoal;
        !           480:                 dist = 0;       /* Indicate that we have our door */
        !           481:             }
        !           482:         }
        !           483:
        !           484:         /* Go through all the doors */
        !           485:         else for (exitptr = rer->r_exit; exitptr; exitptr = next(exitptr)) {
        !           486:             exit = DOORPTR(exitptr);
        !           487:             exity = exit->y;
        !           488:             exitx = exit->x;
        !           489:
        !           490:             /* Make sure it is a real door */
        !           491:             dch = mvwinch(stdscr, exity, exitx);
        !           492:             if (dch == PASSAGE || dch == DOOR) {
        !           493:                 /* Don't count a door if we are fleeing from someone and
        !           494:                  * he is standing on it.  Also, don't count it if he is
        !           495:                  * standing in the doorway.
        !           496:                  */
        !           497:                 if (flee) {
        !           498:                     if (ce(*exit, *th->t_dest)) continue;
        !           499:
        !           500:                     entrance = doorway(rer, exit);
        !           501:                     if (entrance != NULL && ce(*entrance, *th->t_dest))
        !           502:                         continue;
        !           503:                 }
        !           504:
        !           505:                 /* Were we just on this door? */
        !           506:                 if (ce(*exit, th->t_oldpos)) last_door = exit;
        !           507:
        !           508:                 else {
        !           509:                     dist = DISTANCE(th->t_dest->y, th->t_dest->x, exity, exitx);
        !           510:
        !           511:                     /* If fleeing, we want to maximize distance from door to
        !           512:                      * what we flee, and minimize distance from door to us.
        !           513:                      */
        !           514:                     if (flee)
        !           515:                        dist -= DISTANCE(th->t_pos.y, th->t_pos.x, exity, exitx);
        !           516:
        !           517:                     /* Maximize distance if fleeing, otherwise minimize it */
        !           518:                     if ((flee && (dist > maxdist)) ||
        !           519:                         (!flee && (dist < mindist))) {
        !           520:                         th->t_doorgoal = *exit;  /* Use this door */
        !           521:                         this = *exit;
        !           522:                         mindist = maxdist = dist;
        !           523:                     }
        !           524:                 }
        !           525:             }
        !           526:         }
        !           527:
        !           528:         /* Could we not find a door? */
        !           529:         if (dist == INT_MIN) {
        !           530:             /* If we were on a door, go ahead and use it */
        !           531:             if (last_door) {
        !           532:                 th->t_doorgoal = *last_door;
        !           533:                 this = th->t_oldpos;
        !           534:                 dist = 0;       /* Indicate that we found a door */
        !           535:             }
        !           536:             else th->t_doorgoal.x = th->t_doorgoal.y = -1; /* No more door goal */
        !           537:         }
        !           538:
        !           539:         /* Indicate that we do not want to flee from the door */
        !           540:         if (dist != INT_MIN) flee = FALSE;
        !           541:     }
        !           542:     else th->t_doorgoal.x = th->t_doorgoal.y = -1;    /* Not going to any door */
        !           543:
        !           544:     /* Now select someplace to go and start the action */
        !           545:     chase(th, &this, rer, ree, flee);
        !           546: }
        !           547:
        !           548: /*
        !           549:  * m_sonic:
        !           550:  *      The monster is sounding a sonic blast.
        !           551:  */
        !           552:
        !           553: void
        !           554: m_sonic(struct thing *tp)
        !           555: {
        !           556:     register int damage;
        !           557:     struct object blast =
        !           558:     {
        !           559:         MISSILE, {0, 0}, 0, "", "150" , NULL, 0, 0, 0, 0
        !           560:     };
        !           561:
        !           562:     turn_off(*tp, CANSONIC);
        !           563:     turn_off(*tp, CANSURPRISE);
        !           564:     do_motion(&blast, tp->t_newpos.y, tp->t_newpos.x, tp);
        !           565:     damage = rnd(61)+40;
        !           566:     if (save(VS_BREATH, &player, -3))
        !           567:         damage /= 2;
        !           568:     msg ("%s's ultra-sonic blast hits you", prname(monster_name(tp), TRUE));
        !           569:     if ((pstats.s_hpt -= damage) <= 0) {
        !           570:     pstats.s_hpt = -1;
        !           571:         death(tp->t_index);
        !           572:     }
        !           573:     running = FALSE;
        !           574:     if (fight_flush) flushinp();
        !           575:     dsrpt_player();
        !           576: }
        !           577:
        !           578: /*
        !           579:  * m_spell:
        !           580:  *      The monster casts a spell.  Currently this is limited to
        !           581:  *      magic missile.
        !           582:  */
        !           583: void
        !           584: m_spell(struct thing *tp)
        !           585: {
        !           586:     struct object missile =
        !           587:     {
        !           588:         MISSILE, {0, 0}, 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
        !           589:     };
        !           590:
        !           591:     sprintf(missile.o_hurldmg, "%dd4", tp->t_stats.s_lvl);
        !           592:     do_motion(&missile, tp->t_newpos.y, tp->t_newpos.x, tp);
        !           593:     hit_monster(unc(missile.o_pos), &missile, tp);
        !           594:     turn_off(*tp, CANMISSILE);
        !           595:     turn_off(*tp, CANSURPRISE);
        !           596:
        !           597:     running = FALSE;
        !           598:     if (fight_flush) flushinp();
        !           599: }
        !           600:
        !           601: /*
        !           602:  * m_summon:
        !           603:  *      Summon aid.
        !           604:  */
        !           605:
        !           606: void
        !           607: m_summon(struct thing *tp)
        !           608: {
        !           609:     register char *helpname, *mname;
        !           610:     int fail, numsum;
        !           611:     register int which, i;
        !           612:
        !           613:     /* Let's make sure our prey is still here */
        !           614:     if (!cansee(unc(tp->t_pos)) || fallpos(&hero, FALSE, 2) == NULL) return;
        !           615:
        !           616:     /*
        !           617:      * Non-uniques can only summon once.  Uniques get fewer
        !           618:      * creatures with each successive summoning. Also, the
        !           619:      * probability of summoning goes down
        !           620:      */
        !           621:     if (off(*tp, ISUNIQUE))
        !           622:             turn_off(*tp, CANSUMMON);
        !           623:
        !           624:     turn_off(*tp, CANSURPRISE);
        !           625:     mname = monster_name(tp);
        !           626:     helpname = monsters[tp->t_index].m_typesum;
        !           627:     which = findmindex(helpname);
        !           628:
        !           629:     if ((off(*tp, ISINVIS)     || on(player, CANSEE)) &&
        !           630:         (off(*tp, ISSHADOW)    || on(player, CANSEE)) &&
        !           631:         (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
        !           632:         if (monsters[which].m_normal == FALSE) { /* genocided? */
        !           633:             msg("%s appears dismayed", prname(mname, TRUE));
        !           634:             monsters[tp->t_index].m_numsum = 0;
        !           635:         }
        !           636:         else {
        !           637:             msg("%s summons %ss for help", prname(mname, TRUE), helpname);
        !           638:         }
        !           639:     }
        !           640:     else {
        !           641:         if (monsters[which].m_normal == FALSE) /* genocided? */
        !           642:             monsters[tp->t_index].m_numsum = 0;
        !           643:         else {
        !           644:             msg("%ss seem to appear from nowhere!", helpname);
        !           645:         }
        !           646:     }
        !           647:     numsum = monsters[tp->t_index].m_numsum;
        !           648:     if (numsum && on(*tp, ISUNIQUE)) {   /* UNIQUEs summon less each time */
        !           649:         monsters[tp->t_index].m_numsum--;
        !           650:         tp->t_summon *= 2; /* cut probability in half */
        !           651:     }
        !           652:
        !           653:     /*
        !           654:      * try to make all the creatures around player but remember
        !           655:      * if unsuccessful
        !           656:      */
        !           657:     for (i=0, fail=0; i<numsum; i++) {
        !           658:          if (!creat_mons(&player, which, FALSE))
        !           659:              fail++;    /* remember the failures */
        !           660:     }
        !           661:
        !           662:     /*
        !           663:      * try once again to make the buggers
        !           664:      */
        !           665:     for (i=0; i<fail; i++)
        !           666:          creat_mons(tp, which, FALSE);
        !           667:
        !           668:     /* Now let the poor fellow see all the trouble */
        !           669:     light(&hero);
        !           670:     turn_on(*tp, HASSUMMONED);
        !           671: }
        !           672:
        !           673: /*
        !           674:  * m_use_it:
        !           675:  *      See if the monster (tp) has anything useful it can do
        !           676:  *      (ie. an ability or a weapon) other than just move.
        !           677:  */
        !           678:
        !           679: bool
        !           680: m_use_it(struct thing *tp, bool flee, struct room *rer, struct room *ree)
        !           681: {
        !           682:     int dist;
        !           683:     register coord *ee = tp->t_dest, *er = &tp->t_pos;
        !           684:     coord *shoot_dir = NULL;
        !           685:     coord straight_dir;
        !           686:     int   straight_shot = FALSE;
        !           687:     struct thing *prey;
        !           688:     bool dest_player;   /* Are we after the player? */
        !           689:
        !           690:     /*
        !           691:      * If we are fleeing, there's a chance, depending on our
        !           692:      * intelligence, that we'll just run in terror.
        !           693:      */
        !           694:     if (flee && rnd(25) >= tp->t_stats.s_intel) return(FALSE);
        !           695:
        !           696:     /*
        !           697:      * Make sure that we have a living destination, and record whether
        !           698:      * it is the player.
        !           699:      */
        !           700:     if (ee != NULL) {
        !           701:         if (ce(*ee, hero)) {
        !           702:             dest_player = TRUE;
        !           703:             prey = &player;
        !           704:         }
        !           705:         else {
        !           706:             struct linked_list *item;
        !           707:
        !           708:             dest_player = FALSE;
        !           709:
        !           710:             /* What is the monster we're chasing? */
        !           711:             item = find_mons(ee->y, ee->x);
        !           712:             if (item != NULL) prey = THINGPTR(item);
        !           713:             else return(FALSE);
        !           714:         }
        !           715:     }
        !           716:     else return(FALSE);
        !           717:
        !           718:     /*
        !           719:      * If we are friendly to the hero, we don't do anything.
        !           720:      */
        !           721:     if (on(*tp, ISFRIENDLY) && dest_player) return(FALSE);
        !           722:
        !           723:     /*
        !           724:      * Also, for now, if our prey is in a wall, we won't do
        !           725:      * anything.  The prey must be in the same room as we are OR
        !           726:      * we must have a straight shot at him.  Note that
        !           727:      * shoot_dir must get set before rer is checked so
        !           728:      * that we get a valid value.
        !           729:      */
        !           730:
        !           731:     if (can_shoot(er, ee, &straight_dir) == 0)
        !           732:         shoot_dir = &straight_dir;
        !           733:     else
        !           734:         shoot_dir = NULL;
        !           735:
        !           736:     if (on(*prey, ISINWALL) ||
        !           737:         ( (shoot_dir == NULL) && (rer == NULL || rer != ree)))
        !           738:         return(FALSE);
        !           739:
        !           740:     /*
        !           741:      * If we can't see the prey then forget it
        !           742:      */
        !           743:     if (on(*prey, ISINVIS) && off(*tp, CANSEE))
        !           744:         return(FALSE);
        !           745:
        !           746:     /* How far are we from our prey? */
        !           747:     dist = DISTANCE(er->y, er->x, ee->y, ee->x);
        !           748:
        !           749:     /*
        !           750:      * Shall we summon aid so we don't have to get our hands dirty?
        !           751:      * For now, we will only summon aid against the player.
        !           752:      * We'll wait until he's within 2 dots of a missile length.
        !           753:      */
        !           754:     if (on(*tp, CANSUMMON) && dest_player                       &&
        !           755:         dist < (BOLT_LENGTH+2)*(BOLT_LENGTH+2)                  &&
        !           756:         rnd(tp->t_summon) < tp->t_stats.s_lvl                   &&
        !           757:         monsters[tp->t_index].m_numsum > 0                      &&
        !           758:         fallpos(&hero, FALSE, 2) != NULL) {
        !           759:         tp->t_action = A_SUMMON;        /* We're going to summon help */
        !           760:         tp->t_no_move = movement(tp); /* It takes time! */
        !           761:         return(TRUE);
        !           762:     }
        !           763:
        !           764:     /*
        !           765:      * If the creature can cast a slow spell and if the prey is within
        !           766:      * 2 dots of a missile fire, then see whether we will cast it.
        !           767:      * if next to player, lessen chance because we don't like being
        !           768:      * disrupted
        !           769:      */
        !           770:     if (on(*tp, CANSLOW) && dest_player                 &&
        !           771:         dist < (BOLT_LENGTH+5)*(BOLT_LENGTH+5)          &&
        !           772:         rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)) {
        !           773:             tp->t_action = A_SLOW;              /* We're going to slow him */
        !           774:             tp->t_no_move = 3 * movement(tp);   /* Takes time! */
        !           775:             debug("casting slow spell!");
        !           776:             return(TRUE);
        !           777:     }
        !           778:
        !           779:     /*
        !           780:      * If we have a special magic item, we might use it.  We will restrict
        !           781:      * this options to uniques with relics and creatures with wands for now.
        !           782:      * Also check for the quartermaster. Don't want him shooting wands....
        !           783:      */
        !           784:     if ((on(*tp, ISUNIQUE) || on(*tp, CARRYSTICK)) &&
        !           785:         off(*tp, CANSELL) && dest_player           &&
        !           786:         m_use_pack(tp, ee, dist, shoot_dir)) {
        !           787:             return(TRUE);
        !           788:     }
        !           789:
        !           790:     /* From now on, we must have a direct shot at the prey */
        !           791:     if (!straight_shot) return(FALSE);
        !           792:
        !           793:     /* We may use a sonic blast if we can, only on the player */
        !           794:     if (on(*tp, CANSONIC)               &&
        !           795:         dest_player                     &&
        !           796:         (dist < BOLT_LENGTH*2)          &&
        !           797:         (rnd(100) < tp->t_breathe)) {
        !           798:         tp->t_newpos = *shoot_dir;      /* Save the direction */
        !           799:         tp->t_action = A_SONIC; /* We're going to sonic blast */
        !           800:         tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
        !           801:     }
        !           802:
        !           803:     /* If we can breathe, we may do so */
        !           804:     else if (on(*tp, CANBREATHE)                &&
        !           805:          (dist < BOLT_LENGTH*BOLT_LENGTH)       &&
        !           806:          (rnd(100) < tp->t_breathe)) {
        !           807:             tp->t_newpos = *shoot_dir;  /* Save the direction */
        !           808:             tp->t_action = A_BREATHE;   /* We're going to breathe */
        !           809:             tp->t_no_move = movement(tp); /* It takes 1 movement period */
        !           810:     }
        !           811:
        !           812:     /*
        !           813:      * We may shoot missiles if we can
        !           814:      * if next to player, lessen chance so we don't get disrupted as often
        !           815:      */
        !           816:     else if (on(*tp,CANMISSILE) &&
        !           817:              rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)){
        !           818:             tp->t_newpos = *shoot_dir;  /* Save the direction */
        !           819:             tp->t_action = A_MISSILE;   /* We're going to shoot MM's */
        !           820:             tp->t_no_move = 3 * movement(tp); /* Takes time! */
        !           821:     }
        !           822:
        !           823:     /*
        !           824:      * If we can shoot or throw something, we might do so.
        !           825:      * If next to player, then forget it
        !           826:      */
        !           827:     else if ((on(*tp,CANSHOOT)          || on(*tp,CARRYWEAPON) ||
        !           828:               on(*tp,CARRYDAGGER)       || on(*tp, CARRYAXE))           &&
        !           829:               dist > 3                                                  &&
        !           830:               off(*tp, CANSELL)                                         &&
        !           831:              (get_hurl(tp) != NULL)) {
        !           832:             tp->t_newpos = *shoot_dir;  /* Save the direction */
        !           833:             tp->t_action = A_THROW;     /* We're going to throw something */
        !           834:             tp->t_using = get_hurl(tp);       /* Save our weapon */
        !           835:             tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
        !           836:     }
        !           837:
        !           838:     /* We couldn't find anything to do */
        !           839:     else return(FALSE);
        !           840:
        !           841:     return(TRUE);
        !           842:
        !           843: }
        !           844:
        !           845: void
        !           846: reap(void)
        !           847: {
        !           848:     _t_free_list(&rlist);
        !           849: }
        !           850:
        !           851: /*
        !           852:  * runners:
        !           853:  *      Make all the awake monsters try to do something.
        !           854:  * segments: Number of segments since last called
        !           855:  */
        !           856:
        !           857: int
        !           858: runners(int segments)
        !           859: {
        !           860:     register struct linked_list *item;
        !           861:     register struct thing *tp = NULL;
        !           862:     register int min_time = 20;     /* Minimum time until a monster can act */
        !           863:
        !           864:     /*
        !           865:      * loop thru the list of running (wandering) monsters and see what
        !           866:      * each one will do this time.
        !           867:      *
        !           868:      * Note: the special case that one of this buggers kills another.
        !           869:      *       if this happens than we have to see if the monster killed
        !           870:      *       himself or someone else. In case its himself we have to get next
        !           871:      *       one immediately. If it wasn't we have to get next one at very
        !           872:      *       end in case he killed the next one.
        !           873:      */
        !           874:     for (item = mlist; item != NULL; item = item->l_next)
        !           875:     {
        !           876:         tp = THINGPTR(item);
        !           877:         turn_on(*tp, NEEDSTOACT);
        !           878:     }
        !           879:
        !           880:     for(;;)
        !           881:     {
        !           882:         for (item = mlist; item != NULL; item = item->l_next)
        !           883:         {
        !           884:             tp = THINGPTR(item);
        !           885:
        !           886:             if (on(*tp, NEEDSTOACT))
        !           887:                 break;
        !           888:         }
        !           889:
        !           890:         if (item == NULL)
        !           891:             break;
        !           892:
        !           893:         turn_off(*tp, NEEDSTOACT);
        !           894:
        !           895:         /* If we are not awake, just skip us */
        !           896:
        !           897:         if (off(*tp, ISRUN) && off(*tp, ISHELD))
        !           898:             continue;
        !           899:
        !           900:         /* See if it's our turn */
        !           901:
        !           902:         tp->t_no_move -= segments;
        !           903:
        !           904:         if (tp->t_no_move > 0)
        !           905:         {
        !           906:             if (tp->t_no_move < min_time) min_time = tp->t_no_move;
        !           907:                 continue;
        !           908:         }
        !           909:
        !           910:         /* If we were frozen, we're moving now */
        !           911:
        !           912:         if (tp->t_action == A_FREEZE)
        !           913:             tp->t_action = A_NIL;
        !           914:
        !           915:         if (on(*tp, ISHELD))
        !           916:         {
        !           917:             /* Make sure the action and using are nil */
        !           918:
        !           919:             tp->t_action = A_NIL;
        !           920:             tp->t_using = NULL;
        !           921:
        !           922:             /* Can we break free? */
        !           923:
        !           924:             if (rnd(tp->t_stats.s_lvl) > 11)
        !           925:             {
        !           926:                 turn_off(*tp, ISHELD);
        !           927:
        !           928:                 runto(tp, &hero);
        !           929:
        !           930:                 if (cansee(tp->t_pos.y, tp->t_pos.x))
        !           931:                     msg("%s breaks free from the hold spell",
        !           932:                         prname(monster_name(tp), TRUE));
        !           933:             }
        !           934:             else /* Too bad -- try again later */
        !           935:                 tp->t_no_move = movement(tp);
        !           936:         }
        !           937:
        !           938:         /* Heal the creature if it's not in the middle of some action */
        !           939:
        !           940:         if (tp->t_action == A_NIL)
        !           941:            doctor(tp);
        !           942:
        !           943:         while (off(*tp, ISELSEWHERE) &&
        !           944:                off(*tp, ISDEAD) &&
        !           945:                tp->t_no_move <= 0 &&
        !           946:                off(*tp, ISHELD) &&
        !           947:                on(*tp, ISRUN)       )
        !           948:         {
        !           949:             /* Let's act (or choose an action if t_action = A_NIL) */
        !           950:
        !           951:             m_act(tp);
        !           952:         }
        !           953:
        !           954:         if ( off(*tp,ISELSEWHERE) && off(*tp,ISDEAD) )
        !           955:         {
        !           956:             if (tp->t_no_move < min_time)
        !           957:                min_time = tp->t_no_move;
        !           958:
        !           959:             if (tp->t_quiet < 0)
        !           960:                tp->t_quiet = 0;
        !           961:         }
        !           962:     }
        !           963:
        !           964:     return(min_time);
        !           965: }
        !           966:
        !           967: /*
        !           968:  * See if a monster has some magic it can use.  Return TRUE if so.
        !           969:  * Only care about relics and wands for now.
        !           970:  */
        !           971: bool
        !           972: m_use_pack(struct thing *monster, coord *defend_pos, int dist, coord *shoot_dir)
        !           973: {
        !           974:     register struct object *obj;
        !           975:     register struct linked_list *pitem, *relic, *stick;
        !           976:     register int units = -1;
        !           977:
        !           978:     relic = stick = NULL;
        !           979:
        !           980:     for (pitem=monster->t_pack; pitem; pitem=next(pitem)) {
        !           981:         obj = OBJPTR(pitem);
        !           982:         if (obj->o_flags & ISCURSED) continue;
        !           983:         if (obj->o_type == RELIC) {
        !           984:             switch (obj->o_which) {
        !           985:                 case MING_STAFF:
        !           986:                     if (shoot_dir != NULL) {
        !           987:                         units = 2;      /* Use 2 time units */
        !           988:                         relic = pitem;
        !           989:                     }
        !           990:
        !           991:                 when EMORI_CLOAK:
        !           992:                     if (obj->o_charges != 0     &&
        !           993:                         shoot_dir != NULL) {
        !           994:                             units = 2;  /* Use 2 time units */
        !           995:                             relic = pitem;
        !           996:                     }
        !           997:
        !           998:                 when ASMO_ROD:
        !           999:                     /* The bolt must be able to reach the defendant */
        !          1000:                     if (shoot_dir != NULL                       &&
        !          1001:                         dist < BOLT_LENGTH * BOLT_LENGTH) {
        !          1002:                         units = 2;      /* Use 2 time units */
        !          1003:                         relic = pitem;
        !          1004:                     }
        !          1005:
        !          1006:                 when BRIAN_MANDOLIN:
        !          1007:                     /* The defendant must be the player and within 4 spaces */
        !          1008:                     if (ce(*defend_pos, hero)           &&
        !          1009:                         dist < 25                       &&
        !          1010:                         player.t_action != A_FREEZE) {
        !          1011:                         units = 4;
        !          1012:                         relic = pitem;
        !          1013:                     }
        !          1014:
        !          1015:                 when GERYON_HORN:
        !          1016:                     /* The defendant must be the player and within 5 spaces */
        !          1017:                     if (ce(*defend_pos, hero)                                &&
        !          1018:                         dist < 25                                            &&
        !          1019:                         (off(player,ISFLEE)|| player.t_dest!=&monster->t_pos)) {
        !          1020:                         units = 3;
        !          1021:                         relic = pitem;
        !          1022:                     }
        !          1023:             }
        !          1024:         }
        !          1025:         if (obj->o_type == STICK) {
        !          1026:             if (obj->o_charges < 1) continue;
        !          1027:             switch(obj->o_which) {
        !          1028:                 case WS_ELECT:
        !          1029:                 case WS_FIRE:
        !          1030:                 case WS_COLD:
        !          1031:                     /* The bolt must be able to reach the defendant */
        !          1032:                     if (shoot_dir != NULL                       &&
        !          1033:                         dist < BOLT_LENGTH * BOLT_LENGTH) {
        !          1034:                             units = 3;
        !          1035:                             stick = pitem;
        !          1036:                     }
        !          1037:
        !          1038:                 when WS_MISSILE:
        !          1039:                 case WS_SLOW_M:
        !          1040:                 case WS_CONFMON:
        !          1041:                 case WS_PARALYZE:
        !          1042:                 case WS_MDEG:
        !          1043:                 case WS_FEAR:
        !          1044:                     if (shoot_dir != NULL) {
        !          1045:                         units = 3;
        !          1046:                         stick = pitem;
        !          1047:                     }
        !          1048:
        !          1049:                 otherwise:
        !          1050:                     break;
        !          1051:             }
        !          1052:         }
        !          1053:     }
        !          1054:
        !          1055:     /* use relics in preference to all others */
        !          1056:     if (relic) debug("chance to use relic = %d%%", monster->t_artifact);
        !          1057:     if (stick) debug("chance to use stick = %d%%", monster->t_wand);
        !          1058:     if (relic && rnd(100) < monster->t_artifact)  {
        !          1059:         monster->t_action = A_USERELIC;
        !          1060:         pitem = relic;
        !          1061:     }
        !          1062:     else if (stick && rnd(100) < monster->t_wand) {
        !          1063:         /*
        !          1064:          * see if the monster will use the wand
        !          1065:          */
        !          1066:         pitem = stick;
        !          1067:         monster->t_action = A_USEWAND;
        !          1068:     }
        !          1069:     else {
        !          1070:         return(FALSE);
        !          1071:     }
        !          1072:
        !          1073:     monster->t_no_move = units * movement(monster);
        !          1074:     monster->t_using = pitem;
        !          1075:     monster->t_newpos = *shoot_dir;
        !          1076:     return(TRUE);
        !          1077: }
        !          1078:

CVSweb