1 /* NetHack 3.6 wizard.c $NHDT-Date: 1446078768 2015/10/29 00:32:48 $ $NHDT-Branch: master $:$NHDT-Revision: 1.42 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
6 /* - heavily modified to give the wiz balls. (genat!mike) */
7 /* - dewimped and given some maledictions. -3. */
8 /* - generalized for 3.1 (mike@bullns.on01.bull.ca) */
13 extern const int monstr[];
15 STATIC_DCL short FDECL(which_arti, (int));
16 STATIC_DCL boolean FDECL(mon_has_arti, (struct monst *, SHORT_P));
17 STATIC_DCL struct monst *FDECL(other_mon_has_arti, (struct monst *, SHORT_P));
18 STATIC_DCL struct obj *FDECL(on_ground, (SHORT_P));
19 STATIC_DCL boolean FDECL(you_have, (int));
20 STATIC_DCL unsigned long FDECL(target_on, (int, struct monst *));
21 STATIC_DCL unsigned long FDECL(strategy, (struct monst *));
23 static NEARDATA const int nasties[] = {
24 PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR, PM_RED_DRAGON,
25 PM_BLACK_DRAGON, PM_GREEN_DRAGON, PM_OWLBEAR, PM_PURPLE_WORM,
26 PM_ROCK_TROLL, PM_XAN, PM_GREMLIN, PM_UMBER_HULK, PM_VAMPIRE_LORD,
27 PM_XORN, PM_ZRUTY, PM_ELF_LORD, PM_ELVENKING, PM_YELLOW_DRAGON,
28 PM_LEOCROTTA, PM_BALUCHITHERIUM, PM_CARNIVOROUS_APE, PM_FIRE_GIANT,
29 PM_COUATL, PM_CAPTAIN, PM_WINGED_GARGOYLE, PM_MASTER_MIND_FLAYER,
30 PM_FIRE_ELEMENTAL, PM_JABBERWOCK, PM_ARCH_LICH, PM_OGRE_KING, PM_OLOG_HAI,
31 PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME, PM_DISENCHANTER
34 static NEARDATA const unsigned wizapp[] = {
35 PM_HUMAN, PM_WATER_DEMON, PM_VAMPIRE, PM_RED_DRAGON,
36 PM_TROLL, PM_UMBER_HULK, PM_XORN, PM_XAN,
37 PM_COCKATRICE, PM_FLOATING_EYE, PM_GUARDIAN_NAGA, PM_TRAPPER
40 /* If you've found the Amulet, make the Wizard appear after some time */
41 /* Also, give hints about portal locations, if amulet is worn/wielded -dlc */
49 #if 0 /* caller takes care of this check */
53 if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR)
54 || ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR))
56 for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
57 if (ttmp->ttyp == MAGIC_PORTAL) {
58 int du = distu(ttmp->tx, ttmp->ty);
60 pline("%s hot!", Tobjnam(amu, "feel"));
62 pline("%s very warm.", Tobjnam(amu, "feel"));
64 pline("%s warm.", Tobjnam(amu, "feel"));
65 /* else, the amulet feels normal */
71 if (!context.no_of_wizards)
73 /* find Wizard, and wake him if necessary */
74 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
75 if (DEADMONSTER(mtmp))
77 if (mtmp->iswiz && mtmp->msleeping && !rn2(40)) {
79 if (distu(mtmp->mx, mtmp->my) > 2)
81 "get the creepy feeling that somebody noticed your taking the Amulet.");
89 register struct monst *mtmp;
91 register struct obj *otmp;
93 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
94 if (otmp->otyp == AMULET_OF_YENDOR)
100 mon_has_special(mtmp)
101 register struct monst *mtmp;
103 register struct obj *otmp;
105 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
106 if (otmp->otyp == AMULET_OF_YENDOR || is_quest_artifact(otmp)
107 || otmp->otyp == BELL_OF_OPENING
108 || otmp->otyp == CANDELABRUM_OF_INVOCATION
109 || otmp->otyp == SPE_BOOK_OF_THE_DEAD)
115 * New for 3.1 Strategy / Tactics for the wiz, as well as other
116 * monsters that are "after" something (defined via mflag3).
118 * The strategy section decides *what* the monster is going
119 * to attempt, the tactics section implements the decision.
121 #define STRAT(w, x, y, typ) \
122 ((unsigned long) (w) | ((unsigned long) (x) << 16) \
123 | ((unsigned long) (y) << 8) | (unsigned long) (typ))
125 #define M_Wants(mask) (mtmp->data->mflags3 & (mask))
133 return AMULET_OF_YENDOR;
135 return BELL_OF_OPENING;
137 return CANDELABRUM_OF_INVOCATION;
139 return SPE_BOOK_OF_THE_DEAD;
141 break; /* 0 signifies quest artifact */
147 * If "otyp" is zero, it triggers a check for the quest_artifact,
148 * since bell, book, candle, and amulet are all objects, not really
149 * artifacts right now. [MRS]
152 mon_has_arti(mtmp, otyp)
153 register struct monst *mtmp;
156 register struct obj *otmp;
158 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
160 if (otmp->otyp == otyp)
162 } else if (is_quest_artifact(otmp))
168 STATIC_OVL struct monst *
169 other_mon_has_arti(mtmp, otyp)
170 register struct monst *mtmp;
173 register struct monst *mtmp2;
175 for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon)
176 /* no need for !DEADMONSTER check here since they have no inventory */
178 if (mon_has_arti(mtmp2, otyp))
181 return (struct monst *) 0;
184 STATIC_OVL struct obj *
188 register struct obj *otmp;
190 for (otmp = fobj; otmp; otmp = otmp->nobj)
192 if (otmp->otyp == otyp)
194 } else if (is_quest_artifact(otmp))
196 return (struct obj *) 0;
205 return (boolean) u.uhave.amulet;
207 return (boolean) u.uhave.bell;
209 return (boolean) u.uhave.menorah;
211 return (boolean) u.uhave.book;
213 return (boolean) u.uhave.questart;
220 STATIC_OVL unsigned long
221 target_on(mask, mtmp)
223 register struct monst *mtmp;
226 register struct obj *otmp;
227 register struct monst *mtmp2;
230 return (unsigned long) STRAT_NONE;
232 otyp = which_arti(mask);
233 if (!mon_has_arti(mtmp, otyp)) {
235 return STRAT(STRAT_PLAYER, u.ux, u.uy, mask);
236 else if ((otmp = on_ground(otyp)))
237 return STRAT(STRAT_GROUND, otmp->ox, otmp->oy, mask);
238 else if ((mtmp2 = other_mon_has_arti(mtmp, otyp)) != 0
239 /* when seeking the Amulet, avoid targetting the Wizard
240 or temple priests (to protect Moloch's high priest) */
241 && (otyp != AMULET_OF_YENDOR
242 || (!mtmp2->iswiz && !inhistemple(mtmp2))))
243 return STRAT(STRAT_MONSTR, mtmp2->mx, mtmp2->my, mask);
245 return (unsigned long) STRAT_NONE;
248 STATIC_OVL unsigned long
250 register struct monst *mtmp;
252 unsigned long strat, dstrat;
254 if (!is_covetous(mtmp->data)
255 /* perhaps a shopkeeper has been polymorphed into a master
256 lich; we don't want it teleporting to the stairs to heal
257 because that will leave its shop untended */
258 || (mtmp->isshk && inhishop(mtmp))
259 /* likewise for temple priests */
260 || (mtmp->ispriest && inhistemple(mtmp)))
261 return (unsigned long) STRAT_NONE;
263 switch ((mtmp->mhp * 3) / mtmp->mhpmax) { /* 0-3 */
266 case 0: /* panic time - mtmp is almost snuffed */
267 return (unsigned long) STRAT_HEAL;
269 case 1: /* the wiz is less cautious */
270 if (mtmp->data != &mons[PM_WIZARD_OF_YENDOR])
271 return (unsigned long) STRAT_HEAL;
272 /* else fall through */
283 if (context.made_amulet)
284 if ((strat = target_on(M3_WANTSAMUL, mtmp)) != STRAT_NONE)
287 if (u.uevent.invoked) { /* priorities change once gate opened */
288 if ((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
290 if ((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
292 if ((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
294 if ((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
297 if ((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
299 if ((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
301 if ((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
303 if ((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
311 register struct monst *mtmp;
313 unsigned long strat = strategy(mtmp);
316 (mtmp->mstrategy & (STRAT_WAITMASK | STRAT_APPEARMSG)) | strat;
319 case STRAT_HEAL: /* hide and recover */
320 /* if wounded, hole up on or near the stairs (to block them) */
321 /* unless, of course, there are no stairs (e.g. endlevel) */
322 mtmp->mavenge = 1; /* covetous monsters attack while fleeing */
323 if (In_W_tower(mtmp->mx, mtmp->my, &u.uz)
324 || (mtmp->iswiz && !xupstair && !mon_has_amulet(mtmp))) {
325 if (!rn2(3 + mtmp->mhp / 10))
326 (void) rloc(mtmp, TRUE);
328 && (mtmp->mx != xupstair || mtmp->my != yupstair)) {
329 (void) mnearto(mtmp, xupstair, yupstair, TRUE);
331 /* if you're not around, cast healing spells */
332 if (distu(mtmp->mx, mtmp->my) > (BOLT_LIM * BOLT_LIM))
333 if (mtmp->mhp <= mtmp->mhpmax - 8) {
337 /* fall through :-) */
339 case STRAT_NONE: /* harass */
340 if (!rn2(!mtmp->mflee ? 5 : 33))
344 default: /* kill, maim, pillage! */
346 long where = (strat & STRAT_STRATMASK);
347 xchar tx = STRAT_GOALX(strat), ty = STRAT_GOALY(strat);
348 int targ = (int) (strat & STRAT_GOAL);
351 if (!targ) { /* simply wants you to close */
354 if ((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) {
355 /* player is standing on it (or has it) */
359 if (where == STRAT_GROUND) {
360 if (!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) {
361 /* teleport to it and pick it up */
362 rloc_to(mtmp, tx, ty); /* clean old pos */
364 if ((otmp = on_ground(which_arti(targ))) != 0) {
365 if (cansee(mtmp->mx, mtmp->my))
366 pline("%s picks up %s.", Monnam(mtmp),
367 (distu(mtmp->mx, mtmp->my) <= 5)
369 : distant_name(otmp, doname));
370 obj_extract_self(otmp);
371 (void) mpickobj(mtmp, otmp);
376 /* a monster is standing on it - cause some trouble */
381 } else { /* a monster has it - 'port beside it. */
382 (void) mnearto(mtmp, tx, ty, FALSE);
394 register struct monst *mtmp;
396 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
397 if (DEADMONSTER(mtmp))
399 mtmp->mstrategy &= ~(STRAT_WAITFORU | STRAT_APPEARMSG);
401 if (!mtmp->mcanmove && !rn2(5)) {
411 register struct monst *mtmp2;
413 if ((mtmp2 = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy, NO_MM_FLAGS))
415 mtmp2->msleeping = mtmp2->mtame = mtmp2->mpeaceful = 0;
416 if (!u.uhave.amulet && rn2(2)) { /* give clone a fake */
417 (void) add_to_minv(mtmp2,
418 mksobj(FAKE_AMULET_OF_YENDOR, TRUE, FALSE));
420 mtmp2->m_ap_type = M_AP_MONSTER;
421 mtmp2->mappearance = wizapp[rn2(SIZE(wizapp))];
422 newsym(mtmp2->mx, mtmp2->my);
426 /* also used by newcham() */
430 int res = nasties[rn2(SIZE(nasties))];
432 /* To do? Possibly should filter for appropriate forms when
433 * in the elemental planes or surrounded by water or lava.
435 * We want monsters represented by uppercase on rogue level,
436 * but we don't try very hard.
438 if (Is_rogue_level(&u.uz)
439 && !('A' <= mons[res].mlet && mons[res].mlet <= 'Z'))
440 res = nasties[rn2(SIZE(nasties))];
445 /* create some nasty monsters, aligned or neutral with the caster */
446 /* a null caster defaults to a chaotic caster (e.g. the wizard) */
451 register struct monst *mtmp;
452 register int i, j, tmp;
453 int castalign = (mcast ? sgn(mcast->data->maligntyp) : -1);
457 /* some candidates may be created in groups, so simple count
458 of non-null makemon() return is inadequate */
459 census = monster_census(FALSE);
461 if (!rn2(10) && Inhell) {
462 count = msummon((struct monst *) 0); /* summons like WoY */
465 tmp = (u.ulevel > 3) ? u.ulevel / 3 : 1; /* just in case -- rph */
466 /* if we don't have a casting monster, the nasties appear around you
470 for (i = rnd(tmp); i > 0; --i)
471 for (j = 0; j < 20; j++) {
474 /* Don't create more spellcasters of the monsters' level or
475 * higher--avoids chain summoners filling up the level.
478 makeindex = pick_nasty();
479 } while (mcast && attacktype(&mons[makeindex], AT_MAGC)
480 && monstr[makeindex] >= monstr[mcast->mnum]);
481 /* do this after picking the monster to place */
483 && !enexto(&bypos, mcast->mux, mcast->muy,
486 if ((mtmp = makemon(&mons[makeindex], bypos.x, bypos.y,
487 NO_MM_FLAGS)) != 0) {
488 mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
491 mtmp = makemon((struct permonst *) 0, bypos.x, bypos.y,
495 if (mtmp->data->maligntyp == 0
496 || sgn(mtmp->data->maligntyp) == castalign)
503 count = monster_census(FALSE) - census;
507 /* Let's resurrect the wizard, for some unexpected fun. */
511 struct monst *mtmp, **mmtmp;
515 if (!context.no_of_wizards) {
516 /* make a new Wizard */
518 mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy, MM_NOWAIT);
519 /* affects experience; he's not coming back from a corpse
520 but is subject to repeated killing like a revived corpse */
521 if (mtmp) mtmp->mrevived = 1;
523 /* look for a migrating Wizard */
525 mmtmp = &migrating_mons;
526 while ((mtmp = *mmtmp) != 0) {
528 /* if he has the Amulet, he won't bring it to you */
529 && !mon_has_amulet(mtmp)
530 && (elapsed = monstermoves - mtmp->mlstmv) > 0L) {
531 mon_catchup_elapsed_time(mtmp, elapsed);
532 if (elapsed >= LARGEST_INT)
533 elapsed = LARGEST_INT - 1;
535 if (mtmp->msleeping && rn2((int) elapsed + 1))
537 if (mtmp->mfrozen == 1) /* would unfreeze on next move */
538 mtmp->mfrozen = 0, mtmp->mcanmove = 1;
539 if (mtmp->mcanmove && !mtmp->msleeping) {
541 mon_arrive(mtmp, TRUE);
542 /* note: there might be a second Wizard; if so,
543 he'll have to wait til the next resurrection */
552 mtmp->mtame = mtmp->mpeaceful = 0; /* paranoia */
555 pline("A voice booms out...");
556 verbalize("So thou thought thou couldst %s me, fool.", verb);
561 /* Here, we make trouble for the poor shmuck who actually
562 managed to do in the Wizard. */
566 int which = Is_astralevel(&u.uz) ? rnd(4) : rn2(6);
567 /* cases 0 and 5 don't apply on the Astral level */
571 You_feel("vaguely nervous.");
575 You("notice a %s glow surrounding you.", hcolor(NH_BLACK));
582 (void) nasty((struct monst *) 0);
593 context.no_of_wizards--;
594 if (!u.uevent.udemigod) {
595 u.uevent.udemigod = TRUE;
596 u.udg_cnt = rn1(250, 50);
600 const char *const random_insult[] = {
601 "antic", "blackguard", "caitiff", "chucklehead",
602 "coistrel", "craven", "cretin", "cur",
603 "dastard", "demon fodder", "dimwit", "dolt",
604 "fool", "footpad", "imbecile", "knave",
605 "maledict", "miscreant", "niddering", "poltroon",
606 "rattlepate", "reprobate", "scapegrace", "varlet",
607 "villein", /* (sic.) */
608 "wittol", "worm", "wretch",
611 const char *const random_malediction[] = {
612 "Hell shall soon claim thy remains,", "I chortle at thee, thou pathetic",
613 "Prepare to die, thou", "Resistance is useless,",
614 "Surrender or die, thou", "There shall be no mercy, thou",
615 "Thou shalt repent of thy cunning,", "Thou art as a flea to me,",
616 "Thou art doomed,", "Thy fate is sealed,",
617 "Verily, thou shalt be one dead"
620 /* Insult or intimidate the player */
623 register struct monst *mtmp;
628 if (!rn2(5)) /* typical bad guy action */
629 pline("%s laughs fiendishly.", Monnam(mtmp));
630 else if (u.uhave.amulet && !rn2(SIZE(random_insult)))
631 verbalize("Relinquish the amulet, %s!",
632 random_insult[rn2(SIZE(random_insult))]);
633 else if (u.uhp < 5 && !rn2(2)) /* Panic */
634 verbalize(rn2(2) ? "Even now thy life force ebbs, %s!"
635 : "Savor thy breath, %s, it be thy last!",
636 random_insult[rn2(SIZE(random_insult))]);
637 else if (mtmp->mhp < 5 && !rn2(2)) /* Parthian shot */
638 verbalize(rn2(2) ? "I shall return." : "I'll be back.");
641 random_malediction[rn2(SIZE(random_malediction))],
642 random_insult[rn2(SIZE(random_insult))]);
643 } else if (is_lminion(mtmp)) {
644 com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0))
648 pline("%s casts aspersions on your ancestry.", Monnam(mtmp));
650 com_pager(rn2(QTN_DEMONIC) + QT_DEMONIC);