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 */ } }
/* 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--; } }
void mstatusline(struct monst *mtmp) { aligntyp alignment; const char *info, *monnambuf; if (mtmp->ispriest || (mtmp->isminion && roamer_type(mtmp->data))) alignment = CONST_EPRI(mtmp)->shralign; else if (mtmp->isminion) alignment = EMIN(mtmp)->min_align; else { alignment = mtmp->data->maligntyp; alignment = (alignment > 0) ? A_LAWFUL : (alignment == A_NONE) ? A_NONE : (alignment < 0) ? A_CHAOTIC : A_NEUTRAL; } info = ""; if (mtmp->mtame) { info = msgcat(info, ", tame"); if (wizard) { info = msgprintf("%s (%d", info, mtmp->mtame); if (!mtmp->isminion) info = msgprintf("%s; hungry %u; apport %d", info, EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport); info = msgcat(info, ")"); } } else if (mtmp->mpeaceful) info = msgcat(info, ", peaceful"); if (mtmp->meating) info = msgcat(info, ", eating"); if (mtmp->mcan) info = msgcat(info, ", cancelled"); if (mtmp->mconf) info = msgcat(info, ", confused"); if (mtmp->mblinded || !mtmp->mcansee) info = msgcat(info, ", blind"); if (mtmp->mstun) info = msgcat(info, ", stunned"); if (mtmp->msleeping) info = msgcat(info, ", asleep"); else if (mtmp->mfrozen || !mtmp->mcanmove) info = msgcat(info, ", can't move"); /* [arbitrary reason why it isn't moving] */ else if (mtmp->mstrategy & STRAT_WAITMASK) info = msgcat(info, ", meditating"); else if (mtmp->mflee) info = msgcat(info, ", scared"); if (mtmp->mtrapped) info = msgcat(info, ", trapped"); if (mtmp->mspeed) info = msgcat(info, mtmp->mspeed == MFAST ? ", fast" : mtmp->mspeed == MSLOW ? ", slow" : ", ???? speed"); if (mtmp->mundetected) info = msgcat(info, ", concealed"); if (mtmp->minvis) info = msgcat(info, ", invisible"); if (mtmp == u.ustuck) info = msgcat(info, (sticks(youmonst.data)) ? ", held by you" : Engulfed ? (is_animal(u.ustuck->data) ? ", swallowed you" : ", engulfed you") : ", holding you"); if (mtmp == u.usteed) info = msgcat(info, ", carrying you"); /* avoid "Status of the invisible newt ..., invisible" */ /* and unlike a normal mon_nam, use "saddled" even if it has a name */ monnambuf = x_monnam(mtmp, ARTICLE_THE, NULL, (SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE); pline("Status of %s (%s): Level %d HP %d(%d) Def %d%s.", monnambuf, align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax, 10 - find_mac(mtmp), info); }