1 /* NetHack 3.6	wizard.c	$NHDT-Date: 1561336025 2019/06/24 00:27:05 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.56 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2016. */
4 /* NetHack may be freely redistributed.  See license for details. */
5 
6 /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
7 /*             - heavily modified to give the wiz balls.  (genat!mike)   */
8 /*             - dewimped and given some maledictions. -3. */
9 /*             - generalized for 3.1 (mike@bullns.on01.bull.ca) */
10 
11 #include "hack.h"
12 #include "qtext.h"
13 
14 STATIC_DCL short FDECL(which_arti, (int));
15 STATIC_DCL boolean FDECL(mon_has_arti, (struct monst *, SHORT_P));
16 STATIC_DCL struct monst *FDECL(other_mon_has_arti, (struct monst *, SHORT_P));
17 STATIC_DCL struct obj *FDECL(on_ground, (SHORT_P));
18 STATIC_DCL boolean FDECL(you_have, (int));
19 STATIC_DCL unsigned long FDECL(target_on, (int, struct monst *));
20 STATIC_DCL unsigned long FDECL(strategy, (struct monst *));
21 
22 /* adding more neutral creatures will tend to reduce the number of monsters
23    summoned by nasty(); adding more lawful creatures will reduce the number
24    of monsters summoned by lawfuls; adding more chaotic creatures will reduce
25    the number of monsters summoned by chaotics; prior to 3.6.1, there were
26    only four lawful candidates, so lawful summoners tended to summon more
27    (trying to get lawful or neutral but obtaining chaotic instead) than
28    their chaotic counterparts */
29 static NEARDATA const int nasties[] = {
30     /* neutral */
31     PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR,
32     PM_OWLBEAR, PM_PURPLE_WORM, PM_XAN, PM_UMBER_HULK,
33     PM_XORN, PM_ZRUTY, PM_LEOCROTTA, PM_BALUCHITHERIUM,
34     PM_CARNIVOROUS_APE, PM_FIRE_ELEMENTAL, PM_JABBERWOCK,
35     PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME,
36     /* chaotic */
37     PM_BLACK_DRAGON, PM_RED_DRAGON, PM_ARCH_LICH, PM_VAMPIRE_LORD,
38     PM_MASTER_MIND_FLAYER, PM_DISENCHANTER, PM_WINGED_GARGOYLE,
39     PM_STORM_GIANT, PM_OLOG_HAI, PM_ELF_LORD, PM_ELVENKING,
40     PM_OGRE_KING, PM_CAPTAIN, PM_GREMLIN,
41     /* lawful */
42     PM_SILVER_DRAGON, PM_ORANGE_DRAGON, PM_GREEN_DRAGON,
43     PM_YELLOW_DRAGON, PM_GUARDIAN_NAGA, PM_FIRE_GIANT,
44     PM_ALEAX, PM_COUATL, PM_HORNED_DEVIL, PM_BARBED_DEVIL,
45     /* (titans, ki-rin, and golden nagas are suitably nasty, but
46        they're summoners so would aggravate excessive summoning) */
47 };
48 
49 static NEARDATA const unsigned wizapp[] = {
50     PM_HUMAN,      PM_WATER_DEMON,  PM_VAMPIRE,       PM_RED_DRAGON,
51     PM_TROLL,      PM_UMBER_HULK,   PM_XORN,          PM_XAN,
52     PM_COCKATRICE, PM_FLOATING_EYE, PM_GUARDIAN_NAGA, PM_TRAPPER,
53 };
54 
55 /* If you've found the Amulet, make the Wizard appear after some time */
56 /* Also, give hints about portal locations, if amulet is worn/wielded -dlc */
57 void
amulet()58 amulet()
59 {
60     struct monst *mtmp;
61     struct trap *ttmp;
62     struct obj *amu;
63 
64 #if 0 /* caller takes care of this check */
65     if (!u.uhave.amulet)
66         return;
67 #endif
68     if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR)
69          || ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR))
70         && !rn2(15)) {
71         for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
72             if (ttmp->ttyp == MAGIC_PORTAL) {
73                 int du = distu(ttmp->tx, ttmp->ty);
74                 if (du <= 9)
75                     pline("%s hot!", Tobjnam(amu, "feel"));
76                 else if (du <= 64)
77                     pline("%s very warm.", Tobjnam(amu, "feel"));
78                 else if (du <= 144)
79                     pline("%s warm.", Tobjnam(amu, "feel"));
80                 /* else, the amulet feels normal */
81                 break;
82             }
83         }
84     }
85 
86     if (!context.no_of_wizards)
87         return;
88     /* find Wizard, and wake him if necessary */
89     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
90         if (DEADMONSTER(mtmp))
91             continue;
92         if (mtmp->iswiz && mtmp->msleeping && !rn2(40)) {
93             mtmp->msleeping = 0;
94             if (distu(mtmp->mx, mtmp->my) > 2)
95                 You(
96       "get the creepy feeling that somebody noticed your taking the Amulet.");
97             return;
98         }
99     }
100 }
101 
102 int
mon_has_amulet(mtmp)103 mon_has_amulet(mtmp)
104 register struct monst *mtmp;
105 {
106     register struct obj *otmp;
107 
108     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
109         if (otmp->otyp == AMULET_OF_YENDOR)
110             return 1;
111     return 0;
112 }
113 
114 int
mon_has_special(mtmp)115 mon_has_special(mtmp)
116 register struct monst *mtmp;
117 {
118     register struct obj *otmp;
119 
120     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
121         if (otmp->otyp == AMULET_OF_YENDOR
122             || any_quest_artifact(otmp)
123             || otmp->otyp == BELL_OF_OPENING
124             || otmp->otyp == CANDELABRUM_OF_INVOCATION
125             || otmp->otyp == SPE_BOOK_OF_THE_DEAD)
126             return 1;
127     return 0;
128 }
129 
130 /*
131  *      New for 3.1  Strategy / Tactics for the wiz, as well as other
132  *      monsters that are "after" something (defined via mflag3).
133  *
134  *      The strategy section decides *what* the monster is going
135  *      to attempt, the tactics section implements the decision.
136  */
137 #define STRAT(w, x, y, typ)                            \
138     ((unsigned long) (w) | ((unsigned long) (x) << 16) \
139      | ((unsigned long) (y) << 8) | (unsigned long) (typ))
140 
141 #define M_Wants(mask) (mtmp->data->mflags3 & (mask))
142 
143 STATIC_OVL short
which_arti(mask)144 which_arti(mask)
145 register int mask;
146 {
147     switch (mask) {
148     case M3_WANTSAMUL:
149         return AMULET_OF_YENDOR;
150     case M3_WANTSBELL:
151         return BELL_OF_OPENING;
152     case M3_WANTSCAND:
153         return CANDELABRUM_OF_INVOCATION;
154     case M3_WANTSBOOK:
155         return SPE_BOOK_OF_THE_DEAD;
156     default:
157         break; /* 0 signifies quest artifact */
158     }
159     return 0;
160 }
161 
162 /*
163  *      If "otyp" is zero, it triggers a check for the quest_artifact,
164  *      since bell, book, candle, and amulet are all objects, not really
165  *      artifacts right now.  [MRS]
166  */
167 STATIC_OVL boolean
mon_has_arti(mtmp,otyp)168 mon_has_arti(mtmp, otyp)
169 register struct monst *mtmp;
170 register short otyp;
171 {
172     register struct obj *otmp;
173 
174     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
175         if (otyp) {
176             if (otmp->otyp == otyp)
177                 return 1;
178         } else if (any_quest_artifact(otmp))
179             return 1;
180     }
181     return 0;
182 }
183 
184 STATIC_OVL struct monst *
other_mon_has_arti(mtmp,otyp)185 other_mon_has_arti(mtmp, otyp)
186 register struct monst *mtmp;
187 register short otyp;
188 {
189     register struct monst *mtmp2;
190 
191     for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon)
192         /* no need for !DEADMONSTER check here since they have no inventory */
193         if (mtmp2 != mtmp)
194             if (mon_has_arti(mtmp2, otyp))
195                 return mtmp2;
196 
197     return (struct monst *) 0;
198 }
199 
200 STATIC_OVL struct obj *
on_ground(otyp)201 on_ground(otyp)
202 register short otyp;
203 {
204     register struct obj *otmp;
205 
206     for (otmp = fobj; otmp; otmp = otmp->nobj)
207         if (otyp) {
208             if (otmp->otyp == otyp)
209                 return otmp;
210         } else if (any_quest_artifact(otmp))
211             return otmp;
212     return (struct obj *) 0;
213 }
214 
215 STATIC_OVL boolean
you_have(mask)216 you_have(mask)
217 register int mask;
218 {
219     switch (mask) {
220     case M3_WANTSAMUL:
221         return (boolean) u.uhave.amulet;
222     case M3_WANTSBELL:
223         return (boolean) u.uhave.bell;
224     case M3_WANTSCAND:
225         return (boolean) u.uhave.menorah;
226     case M3_WANTSBOOK:
227         return (boolean) u.uhave.book;
228     case M3_WANTSARTI:
229         return (boolean) u.uhave.questart;
230     default:
231         break;
232     }
233     return 0;
234 }
235 
236 STATIC_OVL unsigned long
target_on(mask,mtmp)237 target_on(mask, mtmp)
238 register int mask;
239 register struct monst *mtmp;
240 {
241     register short otyp;
242     register struct obj *otmp;
243     register struct monst *mtmp2;
244 
245     if (!M_Wants(mask))
246         return (unsigned long) STRAT_NONE;
247 
248     otyp = which_arti(mask);
249     if (!mon_has_arti(mtmp, otyp)) {
250         if (you_have(mask))
251             return STRAT(STRAT_PLAYER, u.ux, u.uy, mask);
252         else if ((otmp = on_ground(otyp)))
253             return STRAT(STRAT_GROUND, otmp->ox, otmp->oy, mask);
254         else if ((mtmp2 = other_mon_has_arti(mtmp, otyp)) != 0
255                  /* when seeking the Amulet, avoid targetting the Wizard
256                     or temple priests (to protect Moloch's high priest) */
257                  && (otyp != AMULET_OF_YENDOR
258                      || (!mtmp2->iswiz && !inhistemple(mtmp2))))
259             return STRAT(STRAT_MONSTR, mtmp2->mx, mtmp2->my, mask);
260     }
261     return (unsigned long) STRAT_NONE;
262 }
263 
264 STATIC_OVL unsigned long
strategy(mtmp)265 strategy(mtmp)
266 register struct monst *mtmp;
267 {
268     unsigned long strat, dstrat;
269 
270     if (!is_covetous(mtmp->data)
271         /* perhaps a shopkeeper has been polymorphed into a master
272            lich; we don't want it teleporting to the stairs to heal
273            because that will leave its shop untended */
274         || (mtmp->isshk && inhishop(mtmp))
275         /* likewise for temple priests */
276         || (mtmp->ispriest && inhistemple(mtmp)))
277         return (unsigned long) STRAT_NONE;
278 
279     switch ((mtmp->mhp * 3) / mtmp->mhpmax) { /* 0-3 */
280 
281     default:
282     case 0: /* panic time - mtmp is almost snuffed */
283         return (unsigned long) STRAT_HEAL;
284 
285     case 1: /* the wiz is less cautious */
286         if (mtmp->data != &mons[PM_WIZARD_OF_YENDOR])
287             return (unsigned long) STRAT_HEAL;
288     /* else fall through */
289 
290     case 2:
291         dstrat = STRAT_HEAL;
292         break;
293 
294     case 3:
295         dstrat = STRAT_NONE;
296         break;
297     }
298 
299     if (context.made_amulet)
300         if ((strat = target_on(M3_WANTSAMUL, mtmp)) != STRAT_NONE)
301             return strat;
302 
303     if (u.uevent.invoked) { /* priorities change once gate opened */
304         if ((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
305             return strat;
306         if ((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
307             return strat;
308         if ((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
309             return strat;
310         if ((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
311             return strat;
312     } else {
313         if ((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
314             return strat;
315         if ((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
316             return strat;
317         if ((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
318             return strat;
319         if ((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
320             return strat;
321     }
322     return dstrat;
323 }
324 
325 void
choose_stairs(sx,sy)326 choose_stairs(sx, sy)
327 xchar *sx;
328 xchar *sy;
329 {
330     xchar x = 0, y = 0;
331 
332     if (builds_up(&u.uz)) {
333         if (xdnstair) {
334             x = xdnstair;
335             y = ydnstair;
336         } else if (xdnladder) {
337             x = xdnladder;
338             y = ydnladder;
339         }
340     } else {
341         if (xupstair) {
342             x = xupstair;
343             y = yupstair;
344         } else if (xupladder) {
345             x = xupladder;
346             y = yupladder;
347         }
348     }
349 
350     if (!x && sstairs.sx) {
351         x = sstairs.sx;
352         y = sstairs.sy;
353     }
354 
355     if (x && y) {
356         *sx = x;
357         *sy = y;
358     }
359 }
360 
361 int
tactics(mtmp)362 tactics(mtmp)
363 register struct monst *mtmp;
364 {
365     unsigned long strat = strategy(mtmp);
366     xchar sx = 0, sy = 0, mx, my;
367 
368     mtmp->mstrategy =
369         (mtmp->mstrategy & (STRAT_WAITMASK | STRAT_APPEARMSG)) | strat;
370 
371     switch (strat) {
372     case STRAT_HEAL: /* hide and recover */
373         mx = mtmp->mx, my = mtmp->my;
374         /* if wounded, hole up on or near the stairs (to block them) */
375         choose_stairs(&sx, &sy);
376         mtmp->mavenge = 1; /* covetous monsters attack while fleeing */
377         if (In_W_tower(mx, my, &u.uz)
378             || (mtmp->iswiz && !sx && !mon_has_amulet(mtmp))) {
379             if (!rn2(3 + mtmp->mhp / 10))
380                 (void) rloc(mtmp, TRUE);
381         } else if (sx && (mx != sx || my != sy)) {
382             if (!mnearto(mtmp, sx, sy, TRUE)) {
383                 /* couldn't move to the target spot for some reason,
384                    so stay where we are (don't actually need rloc_to()
385                    because mtmp is still on the map at <mx,my>... */
386                 rloc_to(mtmp, mx, my);
387                 return 0;
388             }
389             mx = mtmp->mx, my = mtmp->my; /* update cached location */
390         }
391         /* if you're not around, cast healing spells */
392         if (distu(mx, my) > (BOLT_LIM * BOLT_LIM))
393             if (mtmp->mhp <= mtmp->mhpmax - 8) {
394                 mtmp->mhp += rnd(8);
395                 return 1;
396             }
397         /*FALLTHRU*/
398 
399     case STRAT_NONE: /* harass */
400         if (!rn2(!mtmp->mflee ? 5 : 33))
401             mnexto(mtmp);
402         return 0;
403 
404     default: /* kill, maim, pillage! */
405     {
406         long where = (strat & STRAT_STRATMASK);
407         xchar tx = STRAT_GOALX(strat), ty = STRAT_GOALY(strat);
408         int targ = (int) (strat & STRAT_GOAL);
409         struct obj *otmp;
410 
411         if (!targ) { /* simply wants you to close */
412             return 0;
413         }
414         if ((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) {
415             /* player is standing on it (or has it) */
416             mnexto(mtmp);
417             return 0;
418         }
419         if (where == STRAT_GROUND) {
420             if (!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) {
421                 /* teleport to it and pick it up */
422                 rloc_to(mtmp, tx, ty); /* clean old pos */
423 
424                 if ((otmp = on_ground(which_arti(targ))) != 0) {
425                     if (cansee(mtmp->mx, mtmp->my))
426                         pline("%s picks up %s.", Monnam(mtmp),
427                               (distu(mtmp->mx, mtmp->my) <= 5)
428                                   ? doname(otmp)
429                                   : distant_name(otmp, doname));
430                     obj_extract_self(otmp);
431                     (void) mpickobj(mtmp, otmp);
432                     return 1;
433                 } else
434                     return 0;
435             } else {
436                 /* a monster is standing on it - cause some trouble */
437                 if (!rn2(5))
438                     mnexto(mtmp);
439                 return 0;
440             }
441         } else { /* a monster has it - 'port beside it. */
442             mx = mtmp->mx, my = mtmp->my;
443             if (!mnearto(mtmp, tx, ty, FALSE))
444                 rloc_to(mtmp, mx, my); /* no room? stay put */
445             return 0;
446         }
447     } /* default case */
448     } /* switch */
449     /*NOTREACHED*/
450     return 0;
451 }
452 
453 /* are there any monsters mon could aggravate? */
454 boolean
has_aggravatables(mon)455 has_aggravatables(mon)
456 struct monst *mon;
457 {
458     struct monst *mtmp;
459     boolean in_w_tower = In_W_tower(mon->mx, mon->my, &u.uz);
460 
461     if (in_w_tower != In_W_tower(u.ux, u.uy, &u.uz))
462         return FALSE;
463 
464     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
465         if (DEADMONSTER(mtmp))
466             continue;
467         if (in_w_tower != In_W_tower(mtmp->mx, mtmp->my, &u.uz))
468             continue;
469         if ((mtmp->mstrategy & STRAT_WAITFORU) != 0
470             || mtmp->msleeping || !mtmp->mcanmove)
471             return TRUE;
472     }
473     return FALSE;
474 }
475 
476 void
aggravate()477 aggravate()
478 {
479     register struct monst *mtmp;
480     boolean in_w_tower = In_W_tower(u.ux, u.uy, &u.uz);
481 
482     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
483         if (DEADMONSTER(mtmp))
484             continue;
485         if (in_w_tower != In_W_tower(mtmp->mx, mtmp->my, &u.uz))
486             continue;
487         mtmp->mstrategy &= ~(STRAT_WAITFORU | STRAT_APPEARMSG);
488         mtmp->msleeping = 0;
489         if (!mtmp->mcanmove && !rn2(5)) {
490             mtmp->mfrozen = 0;
491             mtmp->mcanmove = 1;
492         }
493     }
494 }
495 
496 void
clonewiz()497 clonewiz()
498 {
499     register struct monst *mtmp2;
500 
501     if ((mtmp2 = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy, NO_MM_FLAGS))
502         != 0) {
503         mtmp2->msleeping = mtmp2->mtame = mtmp2->mpeaceful = 0;
504         if (!u.uhave.amulet && rn2(2)) { /* give clone a fake */
505             (void) add_to_minv(mtmp2,
506                                mksobj(FAKE_AMULET_OF_YENDOR, TRUE, FALSE));
507         }
508         mtmp2->m_ap_type = M_AP_MONSTER;
509         mtmp2->mappearance = wizapp[rn2(SIZE(wizapp))];
510         newsym(mtmp2->mx, mtmp2->my);
511     }
512 }
513 
514 /* also used by newcham() */
515 int
pick_nasty()516 pick_nasty()
517 {
518     int res = nasties[rn2(SIZE(nasties))];
519 
520     /* To do?  Possibly should filter for appropriate forms when
521      * in the elemental planes or surrounded by water or lava.
522      *
523      * We want monsters represented by uppercase on rogue level,
524      * but we don't try very hard.
525      */
526     if (Is_rogue_level(&u.uz)
527         && !('A' <= mons[res].mlet && mons[res].mlet <= 'Z'))
528         res = nasties[rn2(SIZE(nasties))];
529 
530     return res;
531 }
532 
533 /* create some nasty monsters, aligned with the caster or neutral; chaotic
534    and unaligned are treated as equivalent; if summoner is Null, this is
535    for late-game harassment (after the Wizard has been killed at least once
536    or the invocation ritual has been performed), in which case we treat
537    'summoner' as neutral, since that will produce the greatest number of
538    creatures on average (in 3.6.0 and earlier, Null was treated as chaotic);
539    returns the number of monsters created */
540 int
nasty(summoner)541 nasty(summoner)
542 struct monst *summoner;
543 {
544     register struct monst *mtmp;
545     register int i, j;
546     int castalign = (summoner ? sgn(summoner->data->maligntyp) : 0);
547     coord bypos;
548     int count, census, tmp, makeindex, s_cls, m_cls;
549 
550 #define MAXNASTIES 10 /* more than this can be created */
551 
552     /* some candidates may be created in groups, so simple count
553        of non-null makemon() return is inadequate */
554     census = monster_census(FALSE);
555 
556     if (!rn2(10) && Inhell) {
557         /* this might summon a demon prince or lord */
558         count = msummon((struct monst *) 0); /* summons like WoY */
559     } else {
560         count = 0;
561         s_cls = summoner ? summoner->data->mlet : 0;
562         tmp = (u.ulevel > 3) ? u.ulevel / 3 : 1;
563         /* if we don't have a casting monster, nasties appear around hero,
564            otherwise they'll appear around spot summoner thinks she's at */
565         bypos.x = u.ux;
566         bypos.y = u.uy;
567         for (i = rnd(tmp); i > 0 && count < MAXNASTIES; --i)
568             /* Of the 42 nasties[], 10 are lawful, 14 are chaotic,
569              * and 18 are neutral.
570              *
571              * Neutral caster, used for late-game harrassment,
572              * has 18/42 chance to stop the inner loop on each
573              * critter, 24/42 chance for another iteration.
574              * Lawful caster has 28/42 chance to stop unless the
575              * summoner is an angel or demon, in which case the
576              * chance is 26/42.
577              * Chaotic or unaligned caster has 32/42 chance to
578              * stop, so will summon fewer creatures on average.
579              *
580              * The outer loop potentially gives chaotic/unaligned
581              * a chance to even things up since others will hit
582              * MAXNASTIES sooner, but its number of iterations is
583              * randomized so it won't always do so.
584              */
585             for (j = 0; j < 20; j++) {
586                 /* Don't create more spellcasters of the monsters' level or
587                  * higher--avoids chain summoners filling up the level.
588                  */
589                 do {
590                     makeindex = pick_nasty();
591                     m_cls = mons[makeindex].mlet;
592                 } while (summoner
593                          && ((attacktype(&mons[makeindex], AT_MAGC)
594                               && mons[makeindex].difficulty
595                                  >= mons[summoner->mnum].difficulty)
596                              || (s_cls == S_DEMON && m_cls == S_ANGEL)
597                              || (s_cls == S_ANGEL && m_cls == S_DEMON)));
598                 /* do this after picking the monster to place */
599                 if (summoner && !enexto(&bypos, summoner->mux, summoner->muy,
600                                         &mons[makeindex]))
601                     continue;
602                 /* this honors genocide but overrides extinction; it ignores
603                    inside-hell-only (G_HELL) & outside-hell-only (G_NOHELL) */
604                 if ((mtmp = makemon(&mons[makeindex], bypos.x, bypos.y,
605                                     NO_MM_FLAGS)) != 0) {
606                     mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
607                     set_malign(mtmp);
608                 } else /* random monster to substitute for geno'd selection */
609                     mtmp = makemon((struct permonst *) 0, bypos.x, bypos.y,
610                                    NO_MM_FLAGS);
611                 if (mtmp) {
612                     /* delay first use of spell or breath attack */
613                     mtmp->mspec_used = rnd(4);
614                     if (++count >= MAXNASTIES
615                         || mtmp->data->maligntyp == 0
616                         || sgn(mtmp->data->maligntyp) == castalign)
617                         break;
618                 }
619             }
620     }
621 
622     if (count)
623         count = monster_census(FALSE) - census;
624     return count;
625 }
626 
627 /* Let's resurrect the wizard, for some unexpected fun. */
628 void
resurrect()629 resurrect()
630 {
631     struct monst *mtmp, **mmtmp;
632     long elapsed;
633     const char *verb;
634 
635     if (!context.no_of_wizards) {
636         /* make a new Wizard */
637         verb = "kill";
638         mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy, MM_NOWAIT);
639         /* affects experience; he's not coming back from a corpse
640            but is subject to repeated killing like a revived corpse */
641         if (mtmp) mtmp->mrevived = 1;
642     } else {
643         /* look for a migrating Wizard */
644         verb = "elude";
645         mmtmp = &migrating_mons;
646         while ((mtmp = *mmtmp) != 0) {
647             if (mtmp->iswiz
648                 /* if he has the Amulet, he won't bring it to you */
649                 && !mon_has_amulet(mtmp)
650                 && (elapsed = monstermoves - mtmp->mlstmv) > 0L) {
651                 mon_catchup_elapsed_time(mtmp, elapsed);
652                 if (elapsed >= LARGEST_INT)
653                     elapsed = LARGEST_INT - 1;
654                 elapsed /= 50L;
655                 if (mtmp->msleeping && rn2((int) elapsed + 1))
656                     mtmp->msleeping = 0;
657                 if (mtmp->mfrozen == 1) /* would unfreeze on next move */
658                     mtmp->mfrozen = 0, mtmp->mcanmove = 1;
659                 if (mtmp->mcanmove && !mtmp->msleeping) {
660                     *mmtmp = mtmp->nmon;
661                     mon_arrive(mtmp, TRUE);
662                     /* note: there might be a second Wizard; if so,
663                        he'll have to wait til the next resurrection */
664                     break;
665                 }
666             }
667             mmtmp = &mtmp->nmon;
668         }
669     }
670 
671     if (mtmp) {
672         mtmp->mtame = mtmp->mpeaceful = 0; /* paranoia */
673         set_malign(mtmp);
674         if (!Deaf) {
675             pline("A voice booms out...");
676             verbalize("So thou thought thou couldst %s me, fool.", verb);
677         }
678     }
679 }
680 
681 /* Here, we make trouble for the poor shmuck who actually
682    managed to do in the Wizard. */
683 void
intervene()684 intervene()
685 {
686     int which = Is_astralevel(&u.uz) ? rnd(4) : rn2(6);
687     /* cases 0 and 5 don't apply on the Astral level */
688     switch (which) {
689     case 0:
690     case 1:
691         You_feel("vaguely nervous.");
692         break;
693     case 2:
694         if (!Blind)
695             You("notice a %s glow surrounding you.", hcolor(NH_BLACK));
696         rndcurse();
697         break;
698     case 3:
699         aggravate();
700         break;
701     case 4:
702         (void) nasty((struct monst *) 0);
703         break;
704     case 5:
705         resurrect();
706         break;
707     }
708 }
709 
710 void
wizdead()711 wizdead()
712 {
713     context.no_of_wizards--;
714     if (!u.uevent.udemigod) {
715         u.uevent.udemigod = TRUE;
716         u.udg_cnt = rn1(250, 50);
717     }
718 }
719 
720 const char *const random_insult[] = {
721     "antic",      "blackguard",   "caitiff",    "chucklehead",
722     "coistrel",   "craven",       "cretin",     "cur",
723     "dastard",    "demon fodder", "dimwit",     "dolt",
724     "fool",       "footpad",      "imbecile",   "knave",
725     "maledict",   "miscreant",    "niddering",  "poltroon",
726     "rattlepate", "reprobate",    "scapegrace", "varlet",
727     "villein", /* (sic.) */
728     "wittol",     "worm",         "wretch",
729 };
730 
731 const char *const random_malediction[] = {
732     "Hell shall soon claim thy remains,", "I chortle at thee, thou pathetic",
733     "Prepare to die, thou", "Resistance is useless,",
734     "Surrender or die, thou", "There shall be no mercy, thou",
735     "Thou shalt repent of thy cunning,", "Thou art as a flea to me,",
736     "Thou art doomed,", "Thy fate is sealed,",
737     "Verily, thou shalt be one dead"
738 };
739 
740 /* Insult or intimidate the player */
741 void
cuss(mtmp)742 cuss(mtmp)
743 register struct monst *mtmp;
744 {
745     if (Deaf)
746         return;
747     if (mtmp->iswiz) {
748         if (!rn2(5)) /* typical bad guy action */
749             pline("%s laughs fiendishly.", Monnam(mtmp));
750         else if (u.uhave.amulet && !rn2(SIZE(random_insult)))
751             verbalize("Relinquish the amulet, %s!",
752                       random_insult[rn2(SIZE(random_insult))]);
753         else if (u.uhp < 5 && !rn2(2)) /* Panic */
754             verbalize(rn2(2) ? "Even now thy life force ebbs, %s!"
755                              : "Savor thy breath, %s, it be thy last!",
756                       random_insult[rn2(SIZE(random_insult))]);
757         else if (mtmp->mhp < 5 && !rn2(2)) /* Parthian shot */
758             verbalize(rn2(2) ? "I shall return." : "I'll be back.");
759         else
760             verbalize("%s %s!",
761                       random_malediction[rn2(SIZE(random_malediction))],
762                       random_insult[rn2(SIZE(random_insult))]);
763     } else if (is_lminion(mtmp)
764                && !(mtmp->isminion && EMIN(mtmp)->renegade)) {
765         com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0))
766                   + QT_ANGELIC);
767     } else {
768         if (!rn2(is_minion(mtmp->data) ? 100 : 5))
769             pline("%s casts aspersions on your ancestry.", Monnam(mtmp));
770         else
771             com_pager(rn2(QTN_DEMONIC) + QT_DEMONIC);
772     }
773 }
774 
775 /*wizard.c*/
776