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