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

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

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

CVSweb