Ejemplo n.º 1
0
struct monst *
mk_roamer(const struct permonst *ptr, aligntyp alignment, struct level *lev,
          xchar x, xchar y, boolean peaceful, int mm_flags)
{
    struct monst *roamer;
    boolean coaligned = (u.ualign.type == alignment);

    if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
        return NULL;

    if (MON_AT(lev, x, y))
        rloc(m_at(lev, x, y), FALSE);   /* insurance */

    if (!(roamer = makemon(ptr, lev, x, y, mm_flags)))
        return NULL;

    EPRI(roamer)->shralign = alignment;
    if (coaligned && !peaceful)
        EPRI(roamer)->renegade = TRUE;
    /* roamer->ispriest == FALSE naturally */
    roamer->isminion = TRUE;    /* borrowing this bit */
    roamer->mtrapseen = ~0;     /* traps are known */
    msethostility(roamer, !peaceful, TRUE); /* TODO: handle in_mklev */
    roamer->msleeping = 0;

    /* MORE TO COME */
    return roamer;
}
Ejemplo n.º 2
0
void
angry_priest(void)
{
    struct monst *priest;
    struct rm *loc;

    if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
        wakeup(priest, FALSE);
        /* 
         * If the altar has been destroyed or converted, let the
         * priest run loose.
         * (When it's just a conversion and there happens to be
         *  a fresh corpse nearby, the priest ought to have an
         *  opportunity to try converting it back; maybe someday...)
         */
        loc = &level->locations
            [CONST_EPRI(priest)->shrpos.x][CONST_EPRI(priest)->shrpos.y];
        if (!IS_ALTAR(loc->typ) ||
            ((aligntyp) Amask2align(loc->altarmask & AM_MASK) !=
             CONST_EPRI(priest)->shralign)) {
            priest->ispriest = 0;       /* now a roamer */
            priest->isminion = 1;       /* but still aligned */
            /* this overloads the `shroom' field, which is now clobbered */
            EPRI(priest)->renegade = 0;
        }
    }
}
Ejemplo n.º 3
0
/* munge priest-specific structure when restoring -dlc */
void
restpriest(struct monst *mtmp, boolean ghostly)
{
    if (u.uz.dlevel) {
        if (ghostly)
            assign_level(&(EPRI(mtmp)->shrlevel), &u.uz);
    }
}
Ejemplo n.º 4
0
/* check whether monster can arrive at location <x,y> via Tport (or fall) */
static boolean
rloc_pos_ok(int x, int y,       /* coordinates of candidate location */
            struct monst *mtmp)
{
    int xx, yy;

    if (!goodpos(level, x, y, mtmp, 0))
        return FALSE;
    /*
     * Check for restricted areas present in some special levels.
     *
     * `xx' is current column; if 0, then `yy' will contain flag bits
     * rather than row:  bit #0 set => moving upwards; bit #1 set =>
     * inside the Wizard's tower.
     */
    xx = mtmp->mx;
    yy = mtmp->my;
    if (!xx) {
        /* no current location (migrating monster arrival) */
        if (level->dndest.nlx && On_W_tower_level(&u.uz))
            return ((yy & 2) != 0) ^    /* inside xor not within */
                !within_bounded_area(x, y, level->dndest.nlx, level->dndest.nly,
                                     level->dndest.nhx, level->dndest.nhy);
        if (level->updest.lx && (yy & 1) != COLNO)  /* moving up */
            return (within_bounded_area
                    (x, y, level->updest.lx, level->updest.ly,
                     level->updest.hx, level->updest.hy) &&
                    (!level->updest.nlx ||
                     !within_bounded_area(
                       x, y, level->updest.nlx, level->updest.nly,
                       level->updest.nhx, level->updest.nhy)));
        if (level->dndest.lx && (yy & 1) == COLNO)  /* moving down */
            return (within_bounded_area
                    (x, y, level->dndest.lx, level->dndest.ly,
                     level->dndest.hx, level->dndest.hy) &&
                    (!level->dndest.nlx ||
                     !within_bounded_area(
                         x, y, level->dndest.nlx, level->dndest.nly,
                         level->dndest.nhx, level->dndest.nhy)));
    } else { /* [try to] prevent a shopkeeper or temple priest from being
                sent out of his room (caller might resort to goodpos() if
                we report failure here, so this isn't full prevention) */
        if (mtmp->isshk && inhishop(mtmp)) {
            if (level->locations[x][y].roomno != ESHK(mtmp)->shoproom)
                return FALSE;
        } else if (mtmp->ispriest && inhistemple(mtmp)) {
            if (level->locations[x][y].roomno != EPRI(mtmp)->shroom)
                return FALSE;
        }
        /* current location is <xx,yy> */
        if (!tele_jump_ok(xx, yy, x, y))
            return FALSE;
    }
    /* <x,y> is ok */
    return TRUE;
}
Ejemplo n.º 5
0
void
reset_hostility(struct monst *roamer)
{
    if (! (roamer->isminion &&
           (roamer->data == &mons[PM_ALIGNED_PRIEST] ||
            roamer->data == &mons[PM_ANGEL])))
        return;

    if (EPRI(roamer)->shralign != u.ualign.type)
        msethostility(roamer, TRUE, TRUE);
}
Ejemplo n.º 6
0
void
summon_minion(aligntyp alignment, boolean talk)
{
    struct monst *mon;
    int mnum;

    switch ((int)alignment) {
    case A_LAWFUL:
        mnum = lminion();
        break;
    case A_NEUTRAL:
        mnum = PM_AIR_ELEMENTAL + rn2(4);
        break;
    case A_CHAOTIC:
    case A_NONE:
        mnum = ndemon(&u.uz, alignment);
        break;
    default:
        impossible("unaligned player?");
        mnum = ndemon(&u.uz, A_NONE);
        break;
    }
    if (mnum == NON_PM) {
        mon = 0;
    } else if (mons[mnum].pxtyp == MX_NONE) {
        const struct permonst *pm = &mons[mnum];

        mon = makemon(pm, level, u.ux, u.uy, MM_EMIN);
        if (mon) {
            mon->isminion = TRUE;
            EMIN(mon)->min_align = alignment;
        }
    } else if (roamer_type(&mons[mnum])) {
        mon = makemon(&mons[mnum], level, u.ux, u.uy, NO_MM_FLAGS);
        if (mon) {
            mon->isminion = TRUE;
            EPRI(mon)->shralign = alignment;
        }
    } else
        mon = makemon(&mons[mnum], level, u.ux, u.uy, NO_MM_FLAGS);
    if (mon) {
        if (talk) {
            pline("The voice of %s booms:", align_gname(alignment));
            verbalize("Thou shalt pay for thy indiscretion!");
            if (!Blind)
                pline("%s appears before you.", Amonnam(mon));
        }
        mon->mpeaceful = FALSE;
        /* don't call set_malign(); player was naughty */
    }
}
Ejemplo n.º 7
0
/* mon summons a monster */
void
msummon(struct monst *mon)
{
    const struct permonst *ptr;
    int dtype = NON_PM, cnt = 0;
    aligntyp atyp;
    struct monst *mtmp;
    struct d_level *dlev;

    if (mon) {
        ptr = mon->data;
        dlev = &mon->dlevel->z;
        atyp = (ptr->maligntyp == A_NONE) ? A_NONE : sgn(ptr->maligntyp);
        if (mon->ispriest || roamer_type(mon->data))
            atyp = EPRI(mon)->shralign;
    } else {
        ptr = &mons[PM_WIZARD_OF_YENDOR];
        atyp = (ptr->maligntyp == A_NONE) ? A_NONE : sgn(ptr->maligntyp);
        dlev = &u.uz;
    }

    if (is_dprince(ptr) || (ptr == &mons[PM_WIZARD_OF_YENDOR])) {
        dtype = (!rn2(20)) ? dprince(atyp) :
                (!rn2(4)) ? dlord(atyp) : ndemon(dlev, atyp);
        cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
    } else if (is_dlord(ptr)) {
        dtype = (!rn2(50)) ? dprince(atyp) :
                (!rn2(20)) ? dlord(atyp) : ndemon(dlev, atyp);
        cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
    } else if (is_ndemon(ptr)) {
        dtype = (!rn2(20)) ? dlord(atyp) :
                (!rn2(6)) ? ndemon(dlev, atyp) : monsndx(ptr);
        cnt = 1;
    } else if (mon && is_lminion(mon)) {
        dtype = (is_lord(ptr) && !rn2(20)) ? llord() :
                (is_lord(ptr) || !rn2(6)) ? lminion() : monsndx(ptr);
        cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1;
    } else if (ptr == &mons[PM_ANGEL]) {
        /* non-lawful angels can also summon */
        if (!rn2(6)) {
            switch (atyp) {     /* see summon_minion */
            case A_NEUTRAL:
                dtype = PM_AIR_ELEMENTAL + rn2(4);
                break;
            case A_CHAOTIC:
            case A_NONE:
                dtype = ndemon(dlev, atyp);
                break;
            }
        } else {
            dtype = PM_ANGEL;
        }
        cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1;
    }

    if (dtype == NON_PM)
        return;

    /* sanity checks */
    if (cnt > 1 && (mons[dtype].geno & G_UNIQ))
        cnt = 1;
    /* 
     * If this daemon is unique and being re-summoned (the only way we
     * could get this far with an extinct dtype), try another.
     */
    if (mvitals[dtype].mvflags & G_GONE) {
        dtype = ndemon(dlev, atyp);
        if (dtype == NON_PM)
            return;
    }

    while (cnt > 0) {
        mtmp = makemon(&mons[dtype], level, u.ux, u.uy, NO_MM_FLAGS);
        if (mtmp && roamer_type(&mons[dtype])) {
            /* alignment should match the summoner */
            EPRI(mtmp)->shralign = atyp;
        }
        cnt--;
    }
}
Ejemplo n.º 8
0
/* exclusively for mktemple(); uses level creation RNG */
void
priestini(struct level *lev, struct mkroom *sroom, int sx, int sy,
          boolean sanctum)
{       /* is it the seat of the high priest? */
    struct monst *priest = NULL;
    struct obj *otmp;
    int cnt;

    coord *priest_pos, pos_array[] = {
        { sx + 1, sy },
        { sx - 1, sy },
        { sx, sy + 1 },
        { sx, sy - 1 },
        { sx, sy },
        { COLNO, ROWNO },
    };

    /* Search for a good position for the priest. The -1 in the array bound is
     * to ensure that we stop on the { COLNO, ROWNO } entry which is not ok. Do
     * not pass a monster to goodpos(), because we will move any monster later.
     */
    for (priest_pos = pos_array;
         !goodpos(lev, priest_pos->x, priest_pos->y, NULL, 0) &&
         (priest_pos < pos_array + ARRAY_SIZE(pos_array) - 1);
         ++priest_pos)
         {}
    
    if (!isok(priest_pos->x, priest_pos->y)) {
        impossible("Unable to find location for priest in shrine");
    } else {
        if (MON_AT(lev, priest_pos->x, priest_pos->y))
            rloc(m_at(lev, priest_pos->x, priest_pos->y), FALSE);

        priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST],
                         lev, priest_pos->x, priest_pos->y, MM_ALLLEVRNG);
    }

    if (priest) {
        EPRI(priest)->shroom = (sroom - lev->rooms) + ROOMOFFSET;
        EPRI(priest)->shralign = Amask2align(lev->locations[sx][sy].altarmask);
        EPRI(priest)->shrpos.x = sx;
        EPRI(priest)->shrpos.y = sy;
        assign_level(&(EPRI(priest)->shrlevel), &lev->z);
        priest->mtrapseen = ~0; /* traps are known */
        priest->mpeaceful = 1;
        priest->ispriest = 1;
        priest->msleeping = 0;
        set_malign(priest);     /* mpeaceful may have changed */

        /* now his/her goodies... */
        if (sanctum && CONST_EPRI(priest)->shralign == A_NONE &&
            on_level(&sanctum_level, &lev->z)) {
            mongets(priest, AMULET_OF_YENDOR, rng_for_level(&lev->z));
        }
        /* 2 to 4 spellbooks */
        for (cnt = rn1(3, 2); cnt > 0; --cnt) {
            mpickobj(priest, mkobj(level, SPBOOK_CLASS, FALSE,
                                   rng_for_level(&lev->z)));
        }
        /* robe [via makemon()] */
        if (mklev_rn2(2, lev) && (otmp = which_armor(priest, os_armc)) != 0) {
            if (p_coaligned(priest))
                uncurse(otmp);
            else
                curse(otmp);
        }
    }
}