static struct permonst * morguemon (void) { int i = rn2(100), hd = rn2(level_difficulty()); if(hd > 10 && i < 10) return((Inhell || In_endgame(&u.uz)) ? mkclass(S_DEMON,0) : &mons[ndemon(A_NONE)]); if(hd > 8 && i > 85) return(mkclass(S_VAMPIRE,0)); return((i < 20) ? &mons[PM_GHOST] : (i < 40) ? &mons[PM_WRAITH] : mkclass(S_ZOMBIE,0)); }
struct permonst * qt_montype (void) { int qpm; if (rn2(5)) { qpm = urole.enemy1num; if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD)) return (&mons[qpm]); return (mkclass(urole.enemy1sym, 0)); } qpm = urole.enemy2num; if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD)) return (&mons[qpm]); return (mkclass(urole.enemy2sym, 0)); }
static const struct permonst * morguemon(const d_level * dlev) { int i = rn2(100), hd = rn2(level_difficulty(dlev)); if (hd > 10 && i < 10) return (In_hell(dlev) || In_endgame(dlev)) ? mkclass(dlev, S_DEMON, 0) : &mons[ndemon(dlev, A_NONE)]; if (hd > 8 && i > 85) return mkclass(dlev, S_VAMPIRE, 0); return (i < 20) ? &mons[PM_GHOST] : (i < 40) ? &mons[PM_WRAITH] : mkclass(dlev, S_ZOMBIE, 0); }
/* Note: this now only returns a suggestion; it no longer takes genocide into account, so that the caller can handle the RNG implications */ const struct permonst * qt_montype(const d_level *dlev, enum rng rng) { int qpm; if (rn2_on_rng(5, rng)) { qpm = urole.enemy1num; if (qpm != NON_PM && rn2_on_rng(5, rng)) return &mons[qpm]; return mkclass(dlev, urole.enemy1sym, 0, rng); } qpm = urole.enemy2num; if (qpm != NON_PM && rn2_on_rng(5, rng)) return &mons[qpm]; return mkclass(dlev, urole.enemy2sym, 0, rng); }
static void mkswamp(struct level *lev) { struct mkroom *sroom; int sx, sy, i, eelct = 0; for (i = 0; i < 5; i++) { /* turn up to 5 rooms swampy */ sroom = &lev->rooms[rn2(lev->nroom)]; if (sroom->hx < 0 || sroom->rtype != OROOM || has_upstairs(lev, sroom) || has_dnstairs(lev, sroom)) continue; /* satisfied; make a swamp */ sroom->rtype = SWAMP; for (sx = sroom->lx; sx <= sroom->hx; sx++) for (sy = sroom->ly; sy <= sroom->hy; sy++) if (!OBJ_AT_LEV(lev, sx, sy) && !MON_AT(lev, sx, sy) && !t_at(lev, sx, sy) && !nexttodoor(lev, sx, sy)) { if ((sx + sy) % 2) { lev->locations[sx][sy].typ = POOL; if (!eelct || !rn2(4)) { /* mkclass() won't do, as we might get kraken */ makemon(rn2(5) ? &mons[PM_GIANT_EEL] : rn2(2) ? &mons[PM_PIRANHA] : &mons[PM_ELECTRIC_EEL], lev, sx, sy, NO_MM_FLAGS); eelct++; } } else if (!rn2(4)) /* swamps tend to be moldy */ makemon(mkclass(&lev->z, S_FUNGUS, 0), lev, sx, sy, NO_MM_FLAGS); } lev->flags.has_swamp = 1; } }
static const struct permonst * morguemon(const d_level *dlev, enum rng rng) { int i = rn2_on_rng(100, rng); int hd = rn2_on_rng(level_difficulty(dlev), rng); if (hd > 10 && i < 10) { if (In_hell(dlev) || In_endgame(dlev)) return mkclass(dlev, S_DEMON, 0, rng); else { int mnum = ndemon(dlev, A_NONE); if (mnum != NON_PM) return &mons[mnum]; /* otherwise fall through */ } } else if (hd > 8 && i > 85) return mkclass(dlev, S_VAMPIRE, 0, rng); return (i < 20) ? &mons[PM_GHOST] : (i < 40) ? &mons[PM_WRAITH] : mkclass(dlev, S_ZOMBIE, 0, rng); }
int lminion(void) { int tryct; const struct permonst *ptr; for (tryct = 0; tryct < 20; tryct++) { ptr = mkclass(&u.uz, S_ANGEL, 0); if (ptr && !is_lord(ptr)) return monsndx(ptr); } return NON_PM; }
int ndemon(const d_level * dlev, aligntyp atyp) { int tryct; const struct permonst *ptr; for (tryct = 0; tryct < 20; tryct++) { ptr = mkclass(dlev, S_DEMON, 0); if (ptr && is_ndemon(ptr) && (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp))) return monsndx(ptr); } return NON_PM; }
struct permonst * courtmon (void) { int i = rn2(60) + rn2(3*level_difficulty()); if (i > 100) return(mkclass(S_DRAGON,0)); else if (i > 95) return(mkclass(S_GIANT,0)); else if (i > 85) return(mkclass(S_TROLL,0)); else if (i > 75) return(mkclass(S_CENTAUR,0)); else if (i > 60) return(mkclass(S_ORC,0)); else if (i > 45) return(&mons[PM_BUGBEAR]); else if (i > 30) return(&mons[PM_HOBGOBLIN]); else if (i > 15) return(mkclass(S_GNOME,0)); else return(mkclass(S_KOBOLD,0)); }
/* make an object of the appropriate type for a shop square */ static void mkshobj_at ( const struct shclass *shp, int sx, int sy) { struct monst *mtmp; int atype; struct permonst *ptr; if (rn2(100) < depth(&u.uz) && !MON_AT(sx, sy) && (ptr = mkclass(S_MIMIC,0)) && (mtmp = makemon(ptr,sx,sy,NO_MM_FLAGS)) != 0) { /* note: makemon will set the mimic symbol to a shop item */ if (rn2(10) >= depth(&u.uz)) { mtmp->m_ap_type = M_AP_OBJECT; mtmp->mappearance = STRANGE_OBJECT; } } else { atype = get_shop_item(shp - shtypes); if (atype < 0) (void) mksobj_at(-atype, sx, sy, true, true); else (void) mkobj_at(atype, sx, sy, true); } }
/* Make an object of the appropriate type for a shop square. Uses the level generation RNG. */ static void mkshobj_at(const struct shclass *shp, struct level *lev, int sx, int sy) { struct monst *mtmp; int atype; const struct permonst *ptr; enum rng rng = rng_for_level(&lev->z); if (rn2_on_rng(100, rng) < depth(&lev->z) && !MON_AT(lev, sx, sy) && (ptr = mkclass(&lev->z, S_MIMIC, 0, rng)) && (mtmp = makemon(ptr, lev, sx, sy, MM_ALLLEVRNG)) != 0) { /* note: makemon will set the mimic symbol to a shop item */ if (rn2_on_rng(10, rng) >= depth(&lev->z)) { mtmp->m_ap_type = M_AP_OBJECT; mtmp->mappearance = STRANGE_OBJECT; } } else { atype = get_shop_item(shp - shtypes, rng); if (atype < 0) mksobj_at(-atype, lev, sx, sy, TRUE, TRUE, rng); else mkobj_at(atype, lev, sx, sy, TRUE, rng); } }
const struct permonst * courtmon(const d_level *dlev, enum rng rng) { int i = rn2_on_rng(60, rng) + rn2_on_rng(3 * level_difficulty(dlev), rng); if (i > 100) return mkclass(dlev, S_DRAGON, 0, rng); else if (i > 95) return mkclass(dlev, S_GIANT, 0, rng); else if (i > 85) return mkclass(dlev, S_TROLL, 0, rng); else if (i > 75) return mkclass(dlev, S_CENTAUR, 0, rng); else if (i > 60) return mkclass(dlev, S_ORC, 0, rng); else if (i > 45) return &mons[PM_BUGBEAR]; else if (i > 30) return &mons[PM_HOBGOBLIN]; else if (i > 15) return mkclass(dlev, S_GNOME, 0, rng); else return mkclass(dlev, S_KOBOLD, 0, rng); }
/* Record the breaking of a roleplay-conduct. */ void violated(int cdt) { switch (cdt) { case CONDUCT_PACIFISM: u.uconduct.killer++; if (u.roleplay.pacifist) { pline("你感到狂暴!"); if (yn("你确定要退出吗?") == 'y') { killer_format = NO_KILLER_PREFIX; killer = "在一阵狂暴之后退出"; done(QUIT); } if (u.uconduct.killer >= 10) u.roleplay.pacifist = FALSE; } break; case CONDUCT_NUDISM: u.uconduct.armoruses++; if (u.roleplay.nudist) { pline("你意识到你光着身子。"); makemon(&mons[PM_COBRA], level, u.ux, u.uy, NO_MM_FLAGS); mksobj_at(APPLE, level, u.ux, u.uy, FALSE, FALSE); u.roleplay.nudist = FALSE; } break; case CONDUCT_BLINDFOLDED: u.uconduct.unblinded++; if (u.roleplay.blindfolded) { pline("禅之精神,离开你的身体。"); makemon(mkclass(&level->z, S_ZOMBIE, 0), level, u.ux, u.uy, NO_MM_FLAGS); /* Z */ makemon(mkclass(&level->z, S_EYE, 0), level, u.ux, u.uy, NO_MM_FLAGS); /* e */ makemon(mkclass(&level->z, S_NYMPH, 0), level, u.ux, u.uy, NO_MM_FLAGS); /* n */ u.roleplay.blindfolded = FALSE; } break; case CONDUCT_VEGETARIAN: /* replaces violated_vegetarian() */ if (u.roleplay.vegetarian) pline("你感到内疚。"); if (Role_if(PM_MONK)) adjalign(-1); u.uconduct.unvegetarian++; u.uconduct.unvegan++; u.uconduct.food++; if (u.uconduct.unvegetarian >= 30) u.roleplay.vegetarian = FALSE; if (u.uconduct.unvegan >= 20) u.roleplay.vegan = FALSE; if (u.uconduct.food >= 10) u.roleplay.ascet = FALSE; break; case CONDUCT_VEGAN: if (u.roleplay.vegan) pline("你感到有点内疚。"); u.uconduct.unvegan++; u.uconduct.food++; if (u.uconduct.unvegan >= 20) u.roleplay.vegan = FALSE; if (u.uconduct.food >= 10) u.roleplay.ascet = FALSE; break; case CONDUCT_FOODLESS: if (u.roleplay.ascet) pline("你略微感到内疚。"); u.uconduct.food++; if (u.uconduct.food >= 10) u.roleplay.ascet = FALSE; break; case CONDUCT_ILLITERACY: u.uconduct.literate++; if (u.roleplay.illiterate) { /* should be impossible */ pline("Literatally literature for literate illiterates!"); exercise(A_WIS, TRUE); } break; case CONDUCT_THIEVERY: u.uconduct.robbed++; if (Role_if(PM_ROGUE)) pline("你感觉自己像一个强盗。"); break; default: impossible("violated: unknown conduct"); } }
static void cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) { if (dmg == 0 && !is_undirected_spell(AD_CLRC, spellnum)) { impossible("cast directed cleric spell (%d) with dmg=0?", spellnum); return; } switch (spellnum) { case CLC_GEYSER: /* this is physical damage, not magical damage */ pline("A sudden geyser slams into you from nowhere!"); dmg = dice(8, 6); if (Half_physical_damage) dmg = (dmg + 1) / 2; break; case CLC_FIRE_PILLAR: pline("A pillar of fire strikes all around you!"); if (Fire_resistance) { shieldeff(u.ux, u.uy); dmg = 0; } else dmg = dice(8, 6); if (Half_spell_damage) dmg = (dmg + 1) / 2; burn_away_slime(); burnarmor(&youmonst); destroy_item(SCROLL_CLASS, AD_FIRE); destroy_item(POTION_CLASS, AD_FIRE); destroy_item(SPBOOK_CLASS, AD_FIRE); burn_floor_paper(u.ux, u.uy, TRUE, FALSE); break; case CLC_LIGHTNING: { boolean reflects; pline("A bolt of lightning strikes down at you from above!"); reflects = ureflects("It bounces off your %s%s.", ""); if (reflects || Shock_resistance) { shieldeff(u.ux, u.uy); dmg = 0; if (reflects) break; } else dmg = dice(8, 6); if (Half_spell_damage) dmg = (dmg + 1) / 2; destroy_item(WAND_CLASS, AD_ELEC); destroy_item(RING_CLASS, AD_ELEC); break; } case CLC_CURSE_ITEMS: pline("You feel as if you need some help."); rndcurse(); dmg = 0; break; case CLC_INSECTS: { /* Try for insects, and if there are none left, go for (sticks to) snakes. -3. */ const struct permonst *pm = mkclass(&u.uz, S_ANT,0); struct monst *mtmp2 = NULL; char let = (pm ? S_ANT : S_SNAKE); boolean success; int i; coord bypos; int quan; quan = (mtmp->m_lev < 2) ? 1 : rnd((int)mtmp->m_lev / 2); if (quan < 3) quan = 3; success = pm ? TRUE : FALSE; for (i = 0; i <= quan; i++) { if (!enexto(&bypos, level, mtmp->mux, mtmp->muy, mtmp->data)) break; if ((pm = mkclass(&u.uz, let,0)) != 0 && (mtmp2 = makemon(pm, level, bypos.x, bypos.y, NO_MM_FLAGS)) != 0) { success = TRUE; mtmp2->msleeping = mtmp2->mpeaceful = mtmp2->mtame = 0; set_malign(mtmp2); } } /* Not quite right: * -- message doesn't always make sense for unseen caster (particularly * the first message) * -- message assumes plural monsters summoned (non-plural should be * very rare, unlike in nasty()) * -- message assumes plural monsters seen */ if (!success) pline("%s casts at a clump of sticks, but nothing happens.", Monnam(mtmp)); else if (let == S_SNAKE) pline("%s transforms a clump of sticks into snakes!", Monnam(mtmp)); else if (Invisible && !perceives(mtmp->data) && (mtmp->mux != u.ux || mtmp->muy != u.uy)) pline("%s summons insects around a spot near you!", Monnam(mtmp)); else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy)) pline("%s summons insects around your displaced image!", Monnam(mtmp)); else pline("%s summons insects!", Monnam(mtmp)); dmg = 0; break; } case CLC_BLIND_YOU: /* note: resists_blnd() doesn't apply here */ if (!Blinded) { int num_eyes = eyecount(youmonst.data); pline("Scales cover your %s!", (num_eyes == 1) ? body_part(EYE) : makeplural(body_part(EYE))); make_blinded(Half_spell_damage ? 100L : 200L, FALSE); if (!Blind) pline("Your vision quickly clears."); dmg = 0; } else impossible("no reason for monster to cast blindness spell?"); break; case CLC_PARALYZE: if (Antimagic || Free_action) { shieldeff(u.ux, u.uy); if (multi >= 0) pline("You stiffen briefly."); nomul(-1, "paralyzed by a monster"); } else { if (multi >= 0) pline("You are frozen in place!"); dmg = 4 + (int)mtmp->m_lev; if (Half_spell_damage) dmg = (dmg + 1) / 2; nomul(-dmg, "paralyzed by a monster"); } dmg = 0; break; case CLC_CONFUSE_YOU: if (Antimagic) { shieldeff(u.ux, u.uy); pline("You feel momentarily dizzy."); } else { boolean oldprop = !!Confusion; dmg = (int)mtmp->m_lev; if (Half_spell_damage) dmg = (dmg + 1) / 2; make_confused(HConfusion + dmg, TRUE); if (Hallucination) pline("You feel %s!", oldprop ? "trippier" : "trippy"); else pline("You feel %sconfused!", oldprop ? "more " : ""); } dmg = 0; break; case CLC_CURE_SELF: if (mtmp->mhp < mtmp->mhpmax) { if (canseemon(mtmp)) pline("%s looks better.", Monnam(mtmp)); /* note: player healing does 6d4; this used to do 1d8 */ if ((mtmp->mhp += dice(3,6)) > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax; dmg = 0; } break; case CLC_OPEN_WOUNDS: if (Antimagic) { shieldeff(u.ux, u.uy); dmg = (dmg + 1) / 2; } if (dmg <= 5) pline("Your skin itches badly for a moment."); else if (dmg <= 10) pline("Wounds appear on your body!"); else if (dmg <= 20) pline("Severe wounds appear on your body!"); else pline("Your body is covered with painful wounds!"); break; default: impossible("mcastu: invalid clerical spell (%d)", spellnum); dmg = 0; break; } if (dmg) mdamageu(mtmp, dmg); }