Exemple #1
0
/* Returns 1 if otmp is free'd, 0 otherwise. */
int mpickobj (struct monst *mtmp, struct obj *otmp) {
    int freed_otmp;

    if (otmp->oclass == COIN_CLASS) {
        mtmp->mgold += otmp->quan;
        obfree(otmp, (struct obj *)0);
        freed_otmp = 1;
    } else {
        bool snuff_otmp = false;
        /* don't want hidden light source inside the monster; assumes that
           engulfers won't have external inventories; whirly monsters cause
           the light to be extinguished rather than letting it shine thru */
        if (otmp->lamplit &&  /* hack to avoid function calls for most objs */
                obj_sheds_light(otmp) &&
                attacktype(mtmp->data, AT_ENGL)) {
            /* this is probably a burning object that you dropped or threw */
            if (u.uswallow && mtmp == u.ustuck && !Blind()) {
                message_object(MSG_O_GO_OUT, otmp);
            }
            snuff_otmp = true;
        }
        /* Must do carrying effects on object prior to add_to_minv() */
        carry_obj_effects(otmp);
        /* add_to_minv() might free otmp [if merged with something else],
           so we have to call it after doing the object checks */
        freed_otmp = add_to_minv(mtmp, otmp);
        /* and we had to defer this until object is in mtmp's inventory */
        if (snuff_otmp) snuff_light_source(mtmp->mx, mtmp->my);
    }
    return freed_otmp;
}
Exemple #2
0
static void
convert_arg (char c)
{
        const char *str;

        switch (c) {

            case 'p':   str = plname;
                        break;
            case 'c':   str = (flags.female && urole.name.f) ?
                                urole.name.f : urole.name.m;
                        break;
            case 'r':   str = rank_of(u.ulevel, Role_switch, flags.female);
                        break;
            case 'R':   str = rank_of(MIN_QUEST_LEVEL, Role_switch,
                                flags.female);
                        break;
            case 's':   str = (flags.female) ? "sister" : "brother";
                        break;
            case 'S':   str = (flags.female) ? "daughter" : "son";
                        break;
            case 'l':   str = ldrname();
                        break;
            case 'i':   str = intermed();
                        break;
            case 'o':   str = the(artiname(urole.questarti));
                        break;
            case 'n':   str = neminame();
                        break;
            case 'g':   str = guardname();
                        break;
            case 'G':   str = align_gtitle(u.ualignbase[A_ORIGINAL]);
                        break;
            case 'H':   str = homebase();
                        break;
            case 'a':   str = align_str(u.ualignbase[A_ORIGINAL]);
                        break;
            case 'A':   str = align_str(u.ualign.type);
                        break;
            case 'd':   str = align_gname(u.ualignbase[A_ORIGINAL]);
                        break;
            case 'D':   str = align_gname(A_LAWFUL);
                        break;
            case 'C':   str = "chaotic";
                        break;
            case 'N':   str = "neutral";
                        break;
            case 'L':   str = "lawful";
                        break;
            case 'x':   str = Blind() ? "sense" : "see";
                        break;
            case 'Z':   str = dungeons[0].dname;
                        break;
            case '%':   str = "%";
                        break;
             default:   str = "";
                        break;
        }
        strcpy(cvt_buf, str);
}
#include "channel.h"
#include "blind.h"
#include "shutter.h"
#include <sblib/eib.h>
#include <sblib/digital_pin.h>
#include <sblib/io_pin_names.h>

#ifdef HAND_ACTUATION
#include "hand_actuation.h"
#endif

//#define MEM_TEST

Channel * channels[NO_OF_CHANNELS];
#ifdef MEM_TEST
Blind b0 = Blind(0, 0);
Blind b1 = Blind(1, 1);
Blind b2 = Blind(2, 2);
Shutter b3 = Shutter(3, 3);
#endif

void objectUpdated(int objno)
{
    if (objno >= 13)
    {   // handle the com objects specific to one channel
        unsigned int channel = (objno - 13) / 20;
        Channel * chn = channels [channel];
        if (chn)
            chn->objectUpdate(objno);
    }
    else
Exemple #4
0
/* Returns 1 when something was stolen (or at least, when N should flee now)
 * Returns -1 if the monster died in the attempt
 * Avoid stealing the object stealoid
 */
int steal (struct monst *mtmp, char *objnambuf) {
    struct obj *otmp;
    int tmp, could_petrify, named = 0, armordelay;
    bool monkey_business; /* true iff an animal is doing the thievery */

    if (objnambuf) *objnambuf = '\0';
    /* the following is true if successful on first of two attacks. */
    if(!monnear(mtmp, u.ux, u.uy)) return(0);

    /* food being eaten might already be used up but will not have
       been removed from inventory yet; we don't want to steal that,
       so this will cause it to be removed now */
    if (occupation) (void) maybe_finished_meal(false);

    if (!invent || (inv_cnt() == 1 && uskin)) {
nothing_to_steal:
        /* Not even a thousand men in armor can strip a naked man. */
        if (Blind()) {
            pline("Somebody tries to rob you, but finds nothing to steal.");
        } else {
            message_monster(MSG_M_TRIES_TO_ROB_BUT_YOURE_NAKED, mtmp);
        }
        return 1;  /* let her flee */
    }

    monkey_business = is_animal(mtmp->data);
    if (monkey_business) {
        ;   /* skip ring special cases */
    } else if (Adornment & LEFT_RING) {
        otmp = uleft;
        goto gotobj;
    } else if (Adornment & RIGHT_RING) {
        otmp = uright;
        goto gotobj;
    }

    tmp = 0;
    for(otmp = invent; otmp; otmp = otmp->nobj)
        if ((!uarm || otmp != uarmc) && otmp != uskin
           )
            tmp += ((otmp->owornmask &
                        (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1);
    if (!tmp) goto nothing_to_steal;
    tmp = rn2(tmp);
    for(otmp = invent; otmp; otmp = otmp->nobj)
        if ((!uarm || otmp != uarmc) && otmp != uskin
           )
            if((tmp -= ((otmp->owornmask &
                                (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) < 0)
                break;
    if(!otmp) {
        impossible("Steal fails!");
        return(0);
    }
    /* can't steal gloves while wielding - so steal the wielded item. */
    if (otmp == uarmg && uwep)
        otmp = uwep;
    /* can't steal armor while wearing cloak - so steal the cloak. */
    else if(otmp == uarm && uarmc) otmp = uarmc;
    else if(otmp == uarmu && uarmc) otmp = uarmc;
    else if(otmp == uarmu && uarm) otmp = uarm;
gotobj:
    if(otmp->o_id == stealoid) return(0);

    /* animals can't overcome curse stickiness nor unlock chains */
    if (monkey_business) {
        bool ostuck;
        /* is the player prevented from voluntarily giving up this item?
           (ignores loadstones; the !can_carry() check will catch those) */
        if (otmp == uball)
            ostuck = true;  /* effectively worn; curse is implicit */
        else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap))
            ostuck = false; /* not really worn; curse doesn't matter */
        else
            ostuck = (otmp->cursed && otmp->owornmask);

        if (ostuck || !can_carry(mtmp, otmp)) {
            static const char * const how[] = { "steal","snatch","grab","take" };
cant_take:
            message_monster_object_string(MSG_M_TRIES_TO_STEAL_YOUR_O_BUT_GIVES_UP, mtmp, otmp,
                    how[rn2(SIZE(how))]);
            /* the fewer items you have, the less likely the thief
               is going to stick around to try again (0) instead of
               running away (1) */
            return !rn2(inv_cnt() / 5 + 2);
        }
    }

    if (otmp->otyp == LEASH && otmp->leashmon) {
        if (monkey_business && otmp->cursed) goto cant_take;
        o_unleash(otmp);
    }

    /* you're going to notice the theft... */
    stop_occupation();

    if((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){
        switch(otmp->oclass) {
            case TOOL_CLASS:
            case AMULET_CLASS:
            case RING_CLASS:
            case FOOD_CLASS: /* meat ring */
                remove_worn_item(otmp, true);
                break;
            case ARMOR_CLASS:
                armordelay = objects[otmp->otyp].oc_delay;
                /* Stop putting on armor which has been stolen. */
                if (donning(otmp)) {
                    remove_worn_item(otmp, true);
                    break;
                } else if (monkey_business) {
                    /* animals usually don't have enough patience
                       to take off items which require extra time */
                    if (armordelay >= 1 && rn2(10)) goto cant_take;
                    remove_worn_item(otmp, true);
                    break;
                } else {
                    int curssv = otmp->cursed;
                    int slowly;
                    bool seen = canspotmon(mtmp);

                    otmp->cursed = 0;
                    /* can't charm you without first waking you */
                    if (multi < 0 && is_fainted()) unmul((char *)0);
                    slowly = (armordelay >= 1 || multi < 0);
                    if (flags.female) {
                        pline("%s charms you.  You gladly %s your %s.",
                                !seen ? "She" : "TODO: Monnam(mtmp)",
                                curssv ? "let her take" :
                                slowly ? "start removing" : "hand over",
                                equipname(otmp));
                    } else {
                        pline("%s seduces you and %s off your %s.",
                                !seen ? "She" : "TODO: Adjmonnam(mtmp, \"beautiful\")",
                                curssv ? "helps you to take" :
                                slowly ? "you start taking" : "you take",
                                equipname(otmp));
                    }
                    named++;
                    /* the following is to set multi for later on */
                    nomul(-armordelay);
                    remove_worn_item(otmp, true);
                    otmp->cursed = curssv;
                    if(multi < 0){
                        /*
                           multi = 0;
                           nomovemsg = 0;
                           afternmv = 0;
                           */
                        stealoid = otmp->o_id;
                        stealmid = mtmp->m_id;
                        afternmv = stealarm;
                        return(0);
                    }
                }
                break;
            default:
                impossible("Tried to steal a strange worn thing. [%d]",
                        otmp->oclass);
        }
    }
    else if (otmp->owornmask)
        remove_worn_item(otmp, true);

    /* do this before removing it from inventory */
    if (objnambuf) strcpy(objnambuf, yname(otmp));
    /* set mavenge bit so knights won't suffer an
     * alignment penalty during retaliation;
     */
    mtmp->mavenge = 1;

    freeinv(otmp);
    message_monster_object(MSG_M_STOLE_O, mtmp, otmp);
    could_petrify = (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]));
    mpickobj(mtmp,otmp);     /* may free otmp */
    if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) {
        minstapetrify(mtmp, true);
        return -1;
    }
    return((multi < 0) ? 0 : 1);
}
Exemple #5
0
int dogaze(void) {
        struct monst *mtmp;
        int looked = 0;
        char qbuf[QBUFSZ];
        int i;
        unsigned char adtyp = 0;

        for (i = 0; i < NATTK; i++) {
            if(youmonst.data->mattk[i].aatyp == AT_GAZE) {
                adtyp = youmonst.data->mattk[i].adtyp;
                break;
            }
        }
        if (adtyp != AD_CONF && adtyp != AD_FIRE) {
            impossible("gaze attack %d?", adtyp);
            return 0;
        }


        if (Blind()) {
            You_cant("see anything to gaze at.");
            return 0;
        }
        if (u.uen < 15) {
            You("lack the energy to use your special gaze!");
            return(0);
        }
        u.uen -= 15;

        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp)) continue;
            if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
                looked++;
                if (Invis && !perceives(mtmp->data)) {
                    message_monster(MSG_M_SEEMS_NOT_NOTICE_GAZE, mtmp);
                } else if (mtmp->minvis && !See_invisible()) {
                    message_monster(MSG_YOU_CANT_SEE_WHERE_GAZE_M, mtmp);
                } else if (mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT) {
                    looked--;
                    continue;
                } else if (flags.safe_dog && !Confusion() && !Hallucination() && mtmp->mtame) {
                    message_monster(MSG_YOU_AVOID_GAZING_AT_M, mtmp);
                } else {
                    if (flags.confirm && mtmp->mpeaceful && !Confusion()
                                                        && !Hallucination()) {
                        sprintf(qbuf, "Really %s %s?",
                            (adtyp == AD_CONF) ? "confuse" : "attack", "TODO: mon_nam(mtmp)");
                        if (yn(qbuf) != 'y') continue;
                        setmangry(mtmp);
                    }
                    if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping ||
                                    !mtmp->mcansee || !haseyes(mtmp->data))
                    {
                        looked--;
                        continue;
                    }
                    /* No reflection check for consistency with when a monster
                     * gazes at *you*--only medusa gaze gets reflected then.
                     */
                    if (adtyp == AD_CONF) {
                        if (!mtmp->mconf) {
                            message_monster(MSG_GAZE_CONFUSES_M, mtmp);
                        } else {
                            message_monster(MSG_M_GETTING_MORE_CONFUSED, mtmp);
                        }
                        mtmp->mconf = 1;
                    } else if (adtyp == AD_FIRE) {
                        int dmg = d(2,6);
                        message_monster(MSG_ATTACK_M_WITH_FIERY_GAZE, mtmp);
                        if (resists_fire(mtmp)) {
                            message_monster(MSG_FIRE_DOES_NOT_BURN_M, mtmp);
                            dmg = 0;
                        }
                        if((int) u.ulevel > rn2(20))
                            (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
                        if((int) u.ulevel > rn2(20))
                            (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
                        if((int) u.ulevel > rn2(25))
                            (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
                        if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg;
                        if (mtmp->mhp <= 0) killed(mtmp);
                    }
                    /* For consistency with passive() in uhitm.c, this only
                     * affects you if the monster is still alive.
                     */
                    if (!DEADMONSTER(mtmp) &&
                          (mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
                        if (!Free_action) {
                            message_monster(MSG_YOU_ARE_FROZEN_BY_M_GAZE, mtmp);
                            nomul((u.ulevel > 6 || rn2(4)) ?
                                    -d((int)mtmp->m_lev+1,
                                            (int)mtmp->data->mattk[0].damd)
                                    : -200);
                            return 1;
                        } else {
                            message_monster(MSG_STIFFEN_MOMENTARILY_UNDER_M_GAZE, mtmp);
                        }
                    }
                    /* Technically this one shouldn't affect you at all because
                     * the Medusa gaze is an active monster attack that only
                     * works on the monster's turn, but for it to *not* have an
                     * effect would be too weird.
                     */
                    if (!DEADMONSTER(mtmp) && (mtmp->data == &mons[PM_MEDUSA]) && !mtmp->mcan) {
                        message_monster(MSG_GAZING_AT_AWAKE_MEDUSA_BAD_IDEA, mtmp);
                        /* as if gazing at a sleeping anything is fruitful... */
                        You("turn to stone...");
                        killer = killed_by_const(KM_DELIBERATELY_MEETING_MEDUSA_GAZE);
                        done(KM_STONING);
                    }
                }
            }
        }
        if (!looked) You("gaze at no place in particular.");
        return 1;
}
Exemple #6
0
/* make a (new) human out of the player */
static void
polyman (const char *fmt, const char *arg)
{
        bool sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow,
                was_mimicking = (youmonst.m_ap_type == M_AP_OBJECT);
        bool could_pass_walls = Passes_walls;
        bool was_blind = !!Blind();

        if (Upolyd) {
                u.acurr = u.macurr;     /* restore old attribs */
                u.amax = u.mamax;
                u.umonnum = u.umonster;
                flags.female = u.mfemale;
        }
        set_uasmon();

        u.mh = u.mhmax = 0;
        u.mtimedone = 0;
        skinback(false);
        u.uundetected = 0;

        if (sticky) uunstick();
        find_ac();
        if (was_mimicking) {
            if (multi < 0) unmul("");
            youmonst.m_ap_type = M_AP_NOTHING;
        }

        newsym(u.ux,u.uy);

        You(fmt, arg);
        /* check whether player foolishly genocided self while poly'd */
        if ((mvitals[urole.malenum].mvflags & G_GENOD) ||
                        (urole.femalenum != NON_PM &&
                        (mvitals[urole.femalenum].mvflags & G_GENOD)) ||
                        (mvitals[urace.malenum].mvflags & G_GENOD) ||
                        (urace.femalenum != NON_PM &&
                        (mvitals[urace.femalenum].mvflags & G_GENOD))) {
            /* intervening activity might have clobbered genocide info */
            killer = delayed_killer;
            if (killer.method == KM_DIED || killer.method == KM_GENOCIDED) {
                killer.method = KM_SELF_GENOCIDE;
            }
            done(KM_GENOCIDED);
        }

        if (u.twoweap && !could_twoweap(youmonst.data))
            untwoweapon();

        if (u.utraptype == TT_PIT) {
            if (could_pass_walls) {     /* player forms cannot pass walls */
                u.utrap = rn1(6,2);
            }
        }
        if (was_blind && !Blind()) {      /* reverting from eyeless */
            Blinded = 1L;
            make_blinded(0L, true);     /* remove blindness */
        }

        if(!Levitation && !u.ustuck &&
           (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy)))
                spoteffects(true);

        see_monsters();
}
Exemple #7
0
/* (try to) make a mntmp monster out of the player */
int
polymon (       /* returns 1 if polymorph successful */
    int mntmp
)
{
        bool sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow,
                was_blind = !!Blind(), dochange = false;
        bool could_pass_walls = Passes_walls;
        int mlvl;

        if (mvitals[mntmp].mvflags & G_GENOD) { /* allow G_EXTINCT */
                You_feel("rather %s-ish.",mons[mntmp].mname);
                exercise(A_WIS, true);
                return(0);
        }

        /* KMH, conduct */
        u.uconduct.polyselfs++;

        if (!Upolyd) {
                /* Human to monster; save human stats */
                u.macurr = u.acurr;
                u.mamax = u.amax;
                u.mfemale = flags.female;
        } else {
                /* Monster to monster; restore human stats, to be
                 * immediately changed to provide stats for the new monster
                 */
                u.acurr = u.macurr;
                u.amax = u.mamax;
                flags.female = u.mfemale;
        }

        if (youmonst.m_ap_type) {
            /* stop mimicking immediately */
            if (multi < 0) unmul("");
        } else if (mons[mntmp].mlet != S_MIMIC) {
            /* as in polyman() */
            youmonst.m_ap_type = M_AP_NOTHING;
        }
        if (is_male(&mons[mntmp])) {
                if(flags.female) dochange = true;
        } else if (is_female(&mons[mntmp])) {
                if(!flags.female) dochange = true;
        } else if (!is_neuter(&mons[mntmp]) && mntmp != u.ulycn) {
                if(!rn2(10)) dochange = true;
        }
        if (dochange) {
                flags.female = !flags.female;
                You("%s %s%s!",
                    (u.umonnum != mntmp) ? "turn into a" : "feel like a new",
                    (is_male(&mons[mntmp]) || is_female(&mons[mntmp])) ? "" :
                        flags.female ? "female " : "male ",
                    mons[mntmp].mname);
        } else {
                if (u.umonnum != mntmp)
                        You("turn into %s!", an(mons[mntmp].mname));
                else
                        You_feel("like a new %s!", mons[mntmp].mname);
        }
        if (Stoned && poly_when_stoned(&mons[mntmp])) {
                /* poly_when_stoned already checked stone golem genocide */
                You("turn to stone!");
                mntmp = PM_STONE_GOLEM;
                Stoned = 0;
                delayed_killer.method = KM_DIED;
        }

        u.mtimedone = rn1(500, 500);
        u.umonnum = mntmp;
        set_uasmon();

        /* New stats for monster, to last only as long as polymorphed.
         * Currently only strength gets changed.
         */
        if(strongmonst(&mons[mntmp])) ABASE(A_STR) = AMAX(A_STR) = STR18(100);

        if (Stone_resistance() && Stoned) { /* [email protected] */
                Stoned = 0;
                delayed_killer.method = KM_DIED;
                You("no longer seem to be petrifying.");
        }
        if (Sick_resistance() && Sick) {
                make_sick(0L, NULL, false, SICK_ALL);
                You("no longer feel sick.");
        }
        if (Slimed) {
            if (flaming(youmonst.data)) {
                pline_The("slime burns away!");
                Slimed = 0L;
            } else if (mntmp == PM_GREEN_SLIME) {
                /* do it silently */
                Slimed = 0L;
            }
        }
        if (nohands(youmonst.data)) Glib = 0;

        /*
        mlvl = adj_lev(&mons[mntmp]);
         * We can't do the above, since there's no such thing as an
         * "experience level of you as a monster" for a polymorphed character.
         */
        mlvl = (int)mons[mntmp].mlevel;
        if (youmonst.data->mlet == S_DRAGON && mntmp >= PM_GRAY_DRAGON) {
                u.mhmax = In_endgame(&u.uz) ? (8*mlvl) : (4*mlvl + d(mlvl,4));
        } else if (is_golem(youmonst.data)) {
                u.mhmax = golemhp(mntmp);
        } else {
                if (!mlvl) u.mhmax = rnd(4);
                else u.mhmax = d(mlvl, 8);
                if (is_home_elemental(&mons[mntmp])) u.mhmax *= 3;
        }
        u.mh = u.mhmax;

        if (u.ulevel < mlvl) {
                u.mtimedone = u.mtimedone * u.ulevel / mlvl;
        }

        if (uskin && mntmp != armor_to_dragon(uskin->otyp))
                skinback(false);
        break_armor();
        drop_weapon(1);
        if (hides_under(youmonst.data))
                u.uundetected = OBJ_AT(u.ux, u.uy);
        else if (youmonst.data->mlet == S_EEL)
                u.uundetected = is_pool(u.ux, u.uy);
        else
                u.uundetected = 0;

        if (u.utraptype == TT_PIT) {
            if (could_pass_walls && !Passes_walls) {
                u.utrap = rn1(6,2);
            } else if (!could_pass_walls && Passes_walls) {
                u.utrap = 0;
            }
        }
        if (was_blind && !Blind()) {      /* previous form was eyeless */
            Blinded = 1L;
            make_blinded(0L, true);     /* remove blindness */
        }
        newsym(u.ux,u.uy);              /* Change symbol */

        if (!sticky && !u.uswallow && u.ustuck && sticks(youmonst.data)) u.ustuck = 0;
        else if (sticky && !sticks(youmonst.data)) uunstick();
        if (u.usteed) {
            if (touch_petrifies(u.usteed->data) && !Stone_resistance() && rnl(3)) {
                char buf[BUFSZ];

                message_monster(MSG_TOUCH_PETRIFYING_STEED, u.usteed);
                sprintf(buf, "riding %s", an(u.usteed->data->mname));
                instapetrify(buf);
            }
            if (!can_ride(u.usteed)) dismount_steed(DISMOUNT_POLY);
        }

        if (flags.verbose) {
            static const char use_thec[] = "Use the command #%s to %s.";
            static const char monsterc[] = "monster";
            if (can_breathe(youmonst.data))
                pline(use_thec,monsterc,"use your breath weapon");
            if (attacktype(youmonst.data, AT_SPIT))
                pline(use_thec,monsterc,"spit venom");
            if (youmonst.data->mlet == S_NYMPH)
                pline(use_thec,monsterc,"remove an iron ball");
            if (attacktype(youmonst.data, AT_GAZE))
                pline(use_thec,monsterc,"gaze at monsters");
            if (is_hider(youmonst.data))
                pline(use_thec,monsterc,"hide");
            if (is_were(youmonst.data))
                pline(use_thec,monsterc,"summon help");
            if (webmaker(youmonst.data))
                pline(use_thec,monsterc,"spin a web");
            if (u.umonnum == PM_GREMLIN)
                pline(use_thec,monsterc,"multiply in a fountain");
            if (is_unicorn(youmonst.data))
                pline(use_thec,monsterc,"use your horn");
            if (is_mind_flayer(youmonst.data))
                pline(use_thec,monsterc,"emit a mental blast");
            if (youmonst.data->msound == MS_SHRIEK) /* worthless, actually */
                pline(use_thec,monsterc,"shriek");
            if (lays_eggs(youmonst.data) && flags.female)
                pline(use_thec,"sit","lay an egg");
        }
        /* you now know what an egg of your type looks like */
        if (lays_eggs(youmonst.data)) {
            learn_egg_type(u.umonnum);
            /* make queen bees recognize killer bee eggs */
            learn_egg_type(egg_type_from_parent(u.umonnum, true));
        }
        find_ac();
        if((!Levitation && !u.ustuck && !Flying &&
            (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy))) ||
           (Underwater && !Swimming))
            spoteffects(true);
        if (Passes_walls && u.utrap && u.utraptype == TT_INFLOOR) {
            u.utrap = 0;
            pline_The("rock seems to no longer trap you.");
        } else if (likes_lava(youmonst.data) && u.utrap && u.utraptype == TT_LAVA) {
            u.utrap = 0;
            pline_The("lava now feels soothing.");
        }
        if (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) {
            if (Punished) {
                You("slip out of the iron chain.");
                unpunish();
            }
        }
        if (u.utrap && (u.utraptype == TT_WEB || u.utraptype == TT_BEARTRAP) &&
                (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data) ||
                  (youmonst.data->msize <= MZ_SMALL && u.utraptype == TT_BEARTRAP))) {
            You("are no longer stuck in the %s.",
                    u.utraptype == TT_WEB ? "web" : "bear trap");
            /* probably should burn webs too if PM_FIRE_ELEMENTAL */
            u.utrap = 0;
        }
        if (webmaker(youmonst.data) && u.utrap && u.utraptype == TT_WEB) {
            You("orient yourself on the web.");
            u.utrap = 0;
        }
        vision_full_recalc = 1;
        see_monsters();
        exercise(A_CON, false);
        exercise(A_WIS, true);
        (void) encumber_msg();
        return(1);
}