OSDN Git Service

shrink mine
[nethackexpress/trunk.git] / src / wizard.c
1 /*      SCCS Id: @(#)wizard.c   3.4     2003/02/18      */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
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) */
9
10 #include "hack.h"
11 #include "qtext.h"
12 #include "epri.h"
13
14 extern const int monstr[];
15
16 #ifdef OVLB
17
18 STATIC_DCL short FDECL(which_arti, (int));
19 STATIC_DCL boolean FDECL(mon_has_arti, (struct monst *,SHORT_P));
20 STATIC_DCL struct monst *FDECL(other_mon_has_arti, (struct monst *,SHORT_P));
21 STATIC_DCL struct obj *FDECL(on_ground, (SHORT_P));
22 STATIC_DCL boolean FDECL(you_have, (int));
23 STATIC_DCL long FDECL(target_on, (int,struct monst *));
24 STATIC_DCL long FDECL(strategy, (struct monst *));
25
26 static NEARDATA const int nasties[] = {
27         PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR, PM_RED_DRAGON,
28         PM_BLACK_DRAGON, PM_GREEN_DRAGON, PM_OWLBEAR, PM_PURPLE_WORM,
29         PM_ROCK_TROLL, PM_XAN, PM_GREMLIN, PM_UMBER_HULK, PM_VAMPIRE_LORD,
30         PM_XORN, PM_ZRUTY, PM_ELF_LORD, PM_ELVENKING, PM_YELLOW_DRAGON,
31         PM_LEOCROTTA, PM_BALUCHITHERIUM, PM_CARNIVOROUS_APE, PM_FIRE_GIANT,
32         PM_COUATL, PM_CAPTAIN, PM_WINGED_GARGOYLE, PM_MASTER_MIND_FLAYER,
33         PM_FIRE_ELEMENTAL, PM_JABBERWOCK, PM_ARCH_LICH, PM_OGRE_KING,
34         PM_OLOG_HAI, PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME,
35         PM_DISENCHANTER
36         };
37
38 static NEARDATA const unsigned wizapp[] = {
39         PM_HUMAN, PM_WATER_DEMON, PM_VAMPIRE,
40         PM_RED_DRAGON, PM_TROLL, PM_UMBER_HULK,
41         PM_XORN, PM_XAN, PM_COCKATRICE,
42         PM_FLOATING_EYE,
43         PM_GUARDIAN_NAGA,
44         PM_TRAPPER
45 };
46
47 #endif /* OVLB */
48 #ifdef OVL0
49
50 /* If you've found the Amulet, make the Wizard appear after some time */
51 /* Also, give hints about portal locations, if amulet is worn/wielded -dlc */
52 void
53 amulet()
54 {
55         struct monst *mtmp;
56         struct trap *ttmp;
57         struct obj *amu;
58
59 #if 0           /* caller takes care of this check */
60         if (!u.uhave.amulet)
61                 return;
62 #endif
63         if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR) ||
64              ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR))
65             && !rn2(15)) {
66             for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
67                 if(ttmp->ttyp == MAGIC_PORTAL) {
68                     int du = distu(ttmp->tx, ttmp->ty);
69                     if (du <= 9)
70                         pline("%s hot!", Tobjnam(amu, "feel"));
71                     else if (du <= 64)
72                         pline("%s very warm.", Tobjnam(amu, "feel"));
73                     else if (du <= 144)
74                         pline("%s warm.", Tobjnam(amu, "feel"));
75                     /* else, the amulet feels normal */
76                     break;
77                 }
78             }
79         }
80
81         if (!flags.no_of_wizards)
82                 return;
83         /* find Wizard, and wake him if necessary */
84         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
85             if (!DEADMONSTER(mtmp) && mtmp->iswiz && mtmp->msleeping && !rn2(40)) {
86                 mtmp->msleeping = 0;
87                 if (distu(mtmp->mx,mtmp->my) > 2)
88                     You(
89     "get the creepy feeling that somebody noticed your taking the Amulet."
90                     );
91                 return;
92             }
93 }
94
95 #endif /* OVL0 */
96 #ifdef OVLB
97
98 int
99 mon_has_amulet(mtmp)
100 register struct monst *mtmp;
101 {
102         register struct obj *otmp;
103
104         for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
105                 if(otmp->otyp == AMULET_OF_YENDOR) return(1);
106         return(0);
107 }
108
109 int
110 mon_has_special(mtmp)
111 register struct monst *mtmp;
112 {
113         register struct obj *otmp;
114
115         for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
116                 if(otmp->otyp == AMULET_OF_YENDOR ||
117                         is_quest_artifact(otmp) ||
118                         otmp->otyp == BELL_OF_OPENING ||
119                         otmp->otyp == CANDELABRUM_OF_INVOCATION ||
120                         otmp->otyp == SPE_BOOK_OF_THE_DEAD) return(1);
121         return(0);
122 }
123
124 /*
125  *      New for 3.1  Strategy / Tactics for the wiz, as well as other
126  *      monsters that are "after" something (defined via mflag3).
127  *
128  *      The strategy section decides *what* the monster is going
129  *      to attempt, the tactics section implements the decision.
130  */
131 #define STRAT(w, x, y, typ) (w | ((long)(x)<<16) | ((long)(y)<<8) | (long)typ)
132
133 #define M_Wants(mask)   (mtmp->data->mflags3 & (mask))
134
135 STATIC_OVL short
136 which_arti(mask)
137         register int mask;
138 {
139         switch(mask) {
140             case M3_WANTSAMUL:  return(AMULET_OF_YENDOR);
141             case M3_WANTSBELL:  return(BELL_OF_OPENING);
142             case M3_WANTSCAND:  return(CANDELABRUM_OF_INVOCATION);
143             case M3_WANTSBOOK:  return(SPE_BOOK_OF_THE_DEAD);
144             default:            break;  /* 0 signifies quest artifact */
145         }
146         return(0);
147 }
148
149 /*
150  *      If "otyp" is zero, it triggers a check for the quest_artifact,
151  *      since bell, book, candle, and amulet are all objects, not really
152  *      artifacts right now.    [MRS]
153  */
154 STATIC_OVL boolean
155 mon_has_arti(mtmp, otyp)
156         register struct monst *mtmp;
157         register short  otyp;
158 {
159         register struct obj *otmp;
160
161         for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
162             if(otyp) {
163                 if(otmp->otyp == otyp)
164                         return(1);
165             }
166              else if(is_quest_artifact(otmp)) return(1);
167         }
168         return(0);
169
170 }
171
172 STATIC_OVL struct monst *
173 other_mon_has_arti(mtmp, otyp)
174         register struct monst *mtmp;
175         register short  otyp;
176 {
177         register struct monst *mtmp2;
178
179         for(mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon)
180             /* no need for !DEADMONSTER check here since they have no inventory */
181             if(mtmp2 != mtmp)
182                 if(mon_has_arti(mtmp2, otyp)) return(mtmp2);
183
184         return((struct monst *)0);
185 }
186
187 STATIC_OVL struct obj *
188 on_ground(otyp)
189         register short  otyp;
190 {
191         register struct obj *otmp;
192
193         for (otmp = fobj; otmp; otmp = otmp->nobj)
194             if (otyp) {
195                 if (otmp->otyp == otyp)
196                     return(otmp);
197             } else if (is_quest_artifact(otmp))
198                 return(otmp);
199         return((struct obj *)0);
200 }
201
202 STATIC_OVL boolean
203 you_have(mask)
204         register int mask;
205 {
206         switch(mask) {
207             case M3_WANTSAMUL:  return(boolean)(u.uhave.amulet);
208             case M3_WANTSBELL:  return(boolean)(u.uhave.bell);
209             case M3_WANTSCAND:  return(boolean)(u.uhave.menorah);
210             case M3_WANTSBOOK:  return(boolean)(u.uhave.book);
211             case M3_WANTSARTI:  return(boolean)(u.uhave.questart);
212             default:            break;
213         }
214         return(0);
215 }
216
217 STATIC_OVL long
218 target_on(mask, mtmp)
219         register int mask;
220         register struct monst *mtmp;
221 {
222         register short  otyp;
223         register struct obj *otmp;
224         register struct monst *mtmp2;
225
226         if(!M_Wants(mask))      return(STRAT_NONE);
227
228         otyp = which_arti(mask);
229         if(!mon_has_arti(mtmp, otyp)) {
230             if(you_have(mask))
231                 return(STRAT(STRAT_PLAYER, u.ux, u.uy, mask));
232             else if((otmp = on_ground(otyp)))
233                 return(STRAT(STRAT_GROUND, otmp->ox, otmp->oy, mask));
234             else if((mtmp2 = other_mon_has_arti(mtmp, otyp)))
235                 return(STRAT(STRAT_MONSTR, mtmp2->mx, mtmp2->my, mask));
236         }
237         return(STRAT_NONE);
238 }
239
240 STATIC_OVL long
241 strategy(mtmp)
242         register struct monst *mtmp;
243 {
244         long strat, dstrat;
245
246         if (!is_covetous(mtmp->data) ||
247                 /* perhaps a shopkeeper has been polymorphed into a master
248                    lich; we don't want it teleporting to the stairs to heal
249                    because that will leave its shop untended */
250                 (mtmp->isshk && inhishop(mtmp)))
251             return STRAT_NONE;
252
253         switch((mtmp->mhp*3)/mtmp->mhpmax) {    /* 0-3 */
254
255            default:
256             case 0:     /* panic time - mtmp is almost snuffed */
257                         return(STRAT_HEAL);
258
259             case 1:     /* the wiz is less cautious */
260                         if(mtmp->data != &mons[PM_WIZARD_OF_YENDOR])
261                             return(STRAT_HEAL);
262                         /* else fall through */
263
264             case 2:     dstrat = STRAT_HEAL;
265                         break;
266
267             case 3:     dstrat = STRAT_NONE;
268                         break;
269         }
270
271         if(flags.made_amulet)
272             if((strat = target_on(M3_WANTSAMUL, mtmp)) != STRAT_NONE)
273                 return(strat);
274
275         if(u.uevent.invoked) {          /* priorities change once gate opened */
276
277             if((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
278                 return(strat);
279             if((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
280                 return(strat);
281             if((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
282                 return(strat);
283             if((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
284                 return(strat);
285         } else {
286
287             if((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
288                 return(strat);
289             if((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
290                 return(strat);
291             if((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
292                 return(strat);
293             if((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
294                 return(strat);
295         }
296         return(dstrat);
297 }
298
299 int
300 tactics(mtmp)
301         register struct monst *mtmp;
302 {
303         long strat = strategy(mtmp);
304
305         mtmp->mstrategy = (mtmp->mstrategy & STRAT_WAITMASK) | strat;
306
307         switch (strat) {
308             case STRAT_HEAL:    /* hide and recover */
309                 /* if wounded, hole up on or near the stairs (to block them) */
310                 /* unless, of course, there are no stairs (e.g. endlevel) */
311                 mtmp->mavenge = 1; /* covetous monsters attack while fleeing */
312                 if (In_W_tower(mtmp->mx, mtmp->my, &u.uz) ||
313                         (mtmp->iswiz && !xupstair && !mon_has_amulet(mtmp))) {
314                     if (!rn2(3 + mtmp->mhp/10)) (void) rloc(mtmp, FALSE);
315                 } else if (xupstair &&
316                          (mtmp->mx != xupstair || mtmp->my != yupstair)) {
317                     (void) mnearto(mtmp, xupstair, yupstair, TRUE);
318                 }
319                 /* if you're not around, cast healing spells */
320                 if (distu(mtmp->mx,mtmp->my) > (BOLT_LIM * BOLT_LIM))
321                     if(mtmp->mhp <= mtmp->mhpmax - 8) {
322                         mtmp->mhp += rnd(8);
323                         return(1);
324                     }
325                 /* fall through :-) */
326
327             case STRAT_NONE:    /* harrass */
328                 if (!rn2(!mtmp->mflee ? 5 : 33)) mnexto(mtmp);
329                 return(0);
330
331             default:            /* kill, maim, pillage! */
332             {
333                 long  where = (strat & STRAT_STRATMASK);
334                 xchar tx = STRAT_GOALX(strat),
335                       ty = STRAT_GOALY(strat);
336                 int   targ = strat & STRAT_GOAL;
337                 struct obj *otmp;
338
339                 if(!targ) { /* simply wants you to close */
340                     return(0);
341                 }
342                 if((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) {
343                     /* player is standing on it (or has it) */
344                     mnexto(mtmp);
345                     return(0);
346                 }
347                 if(where == STRAT_GROUND) {
348                     if(!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) {
349                         /* teleport to it and pick it up */
350                         rloc_to(mtmp, tx, ty);  /* clean old pos */
351
352                         if ((otmp = on_ground(which_arti(targ))) != 0) {
353                             if (cansee(mtmp->mx, mtmp->my))
354                                 pline("%s picks up %s.",
355                                     Monnam(mtmp),
356                                     (distu(mtmp->mx, mtmp->my) <= 5) ?
357                                      doname(otmp) : distant_name(otmp, doname));
358                             obj_extract_self(otmp);
359                             (void) mpickobj(mtmp, otmp);
360                             return(1);
361                         } else return(0);
362                     } else {
363                         /* a monster is standing on it - cause some trouble */
364                         if (!rn2(5)) mnexto(mtmp);
365                         return(0);
366                     }
367                 } else { /* a monster has it - 'port beside it. */
368                     (void) mnearto(mtmp, tx, ty, FALSE);
369                     return(0);
370                 }
371             }
372         }
373         /*NOTREACHED*/
374         return(0);
375 }
376
377 void
378 aggravate()
379 {
380         register struct monst *mtmp;
381
382         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
383             if (!DEADMONSTER(mtmp)) {
384                 mtmp->msleeping = 0;
385                 if(!mtmp->mcanmove && !rn2(5)) {
386                         mtmp->mfrozen = 0;
387                         mtmp->mcanmove = 1;
388                 }
389             }
390 }
391
392 void
393 clonewiz()
394 {
395         register struct monst *mtmp2;
396
397         if ((mtmp2 = makemon(&mons[PM_WIZARD_OF_YENDOR],
398                                 u.ux, u.uy, NO_MM_FLAGS)) != 0) {
399             mtmp2->msleeping = mtmp2->mtame = mtmp2->mpeaceful = 0;
400             if (!u.uhave.amulet && rn2(2)) {  /* give clone a fake */
401                 (void) add_to_minv(mtmp2, mksobj(FAKE_AMULET_OF_YENDOR,
402                                         TRUE, FALSE));
403             }
404             mtmp2->m_ap_type = M_AP_MONSTER;
405             mtmp2->mappearance = wizapp[rn2(SIZE(wizapp))];
406             newsym(mtmp2->mx,mtmp2->my);
407         }
408 }
409
410 /* also used by newcham() */
411 int
412 pick_nasty()
413 {
414     /* To do?  Possibly should filter for appropriate forms when
415        in the elemental planes or surrounded by water or lava. */
416     return nasties[rn2(SIZE(nasties))];
417 }
418
419 /* create some nasty monsters, aligned or neutral with the caster */
420 /* a null caster defaults to a chaotic caster (e.g. the wizard) */
421 int
422 nasty(mcast)
423         struct monst *mcast;
424 {
425     register struct monst       *mtmp;
426     register int        i, j, tmp;
427     int castalign = (mcast ? mcast->data->maligntyp : -1);
428     coord bypos;
429     int count=0;
430
431     if(!rn2(10) && Inhell) {
432         msummon((struct monst *) 0);    /* summons like WoY */
433         count++;
434     } else {
435         tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */
436         /* if we don't have a casting monster, the nasties appear around you */
437         bypos.x = u.ux;
438         bypos.y = u.uy;
439         for(i = rnd(tmp); i > 0; --i)
440             for(j=0; j<20; j++) {
441                 int makeindex;
442
443                 /* Don't create more spellcasters of the monsters' level or
444                  * higher--avoids chain summoners filling up the level.
445                  */
446                 do {
447                     makeindex = pick_nasty();
448                 } while(mcast && attacktype(&mons[makeindex], AT_MAGC) &&
449                         monstr[makeindex] >= monstr[mcast->mnum]);
450                 /* do this after picking the monster to place */
451                 if (mcast &&
452                     !enexto(&bypos, mcast->mux, mcast->muy, &mons[makeindex]))
453                     continue;
454                 if ((mtmp = makemon(&mons[makeindex],
455                                     bypos.x, bypos.y, NO_MM_FLAGS)) != 0) {
456                     mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
457                     set_malign(mtmp);
458                 } else /* GENOD? */
459                     mtmp = makemon((struct permonst *)0,
460                                         bypos.x, bypos.y, NO_MM_FLAGS);
461                 if(mtmp && (mtmp->data->maligntyp == 0 ||
462                             sgn(mtmp->data->maligntyp) == sgn(castalign)) ) {
463                     count++;
464                     break;
465                 }
466             }
467     }
468     return count;
469 }
470
471 /*      Let's resurrect the wizard, for some unexpected fun.    */
472 void
473 resurrect()
474 {
475         struct monst *mtmp, **mmtmp;
476         long elapsed;
477         const char *verb;
478
479         if (!flags.no_of_wizards) {
480             /* make a new Wizard */
481             verb = "kill";
482             mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy, MM_NOWAIT);
483         } else {
484             /* look for a migrating Wizard */
485             verb = "elude";
486             mmtmp = &migrating_mons;
487             while ((mtmp = *mmtmp) != 0) {
488                 if (mtmp->iswiz &&
489                         /* if he has the Amulet, he won't bring it to you */
490                         !mon_has_amulet(mtmp) &&
491                         (elapsed = monstermoves - mtmp->mlstmv) > 0L) {
492                     mon_catchup_elapsed_time(mtmp, elapsed);
493                     if (elapsed >= LARGEST_INT) elapsed = LARGEST_INT - 1;
494                     elapsed /= 50L;
495                     if (mtmp->msleeping && rn2((int)elapsed + 1))
496                         mtmp->msleeping = 0;
497                     if (mtmp->mfrozen == 1) /* would unfreeze on next move */
498                         mtmp->mfrozen = 0,  mtmp->mcanmove = 1;
499                     if (mtmp->mcanmove && !mtmp->msleeping) {
500                         *mmtmp = mtmp->nmon;
501                         mon_arrive(mtmp, TRUE);
502                         /* note: there might be a second Wizard; if so,
503                            he'll have to wait til the next resurrection */
504                         break;
505                     }
506                 }
507                 mmtmp = &mtmp->nmon;
508             }
509         }
510
511         if (mtmp) {
512                 mtmp->msleeping = mtmp->mtame = mtmp->mpeaceful = 0;
513                 set_malign(mtmp);
514                 pline("A voice booms out...");
515                 verbalize("So thou thought thou couldst %s me, fool.", verb);
516         }
517
518 }
519
520 /*      Here, we make trouble for the poor shmuck who actually  */
521 /*      managed to do in the Wizard.                            */
522 void
523 intervene()
524 {
525         int which = Is_astralevel(&u.uz) ? rnd(4) : rn2(6);
526         /* cases 0 and 5 don't apply on the Astral level */
527         switch (which) {
528             case 0:
529             case 1:     You_feel("vaguely nervous.");
530                         break;
531             case 2:     if (!Blind)
532                             You("notice a %s glow surrounding you.",
533                                   hcolor(NH_BLACK));
534                         rndcurse();
535                         break;
536             case 3:     aggravate();
537                         break;
538             case 4:     (void)nasty((struct monst *)0);
539                         break;
540             case 5:     resurrect();
541                         break;
542         }
543 }
544
545 void
546 wizdead()
547 {
548         flags.no_of_wizards--;
549         if (!u.uevent.udemigod) {
550                 u.uevent.udemigod = TRUE;
551                 u.udg_cnt = rn1(250, 50);
552         }
553 }
554
555 const char * const random_insult[] = {
556         "antic",
557         "blackguard",
558         "caitiff",
559         "chucklehead",
560         "coistrel",
561         "craven",
562         "cretin",
563         "cur",
564         "dastard",
565         "demon fodder",
566         "dimwit",
567         "dolt",
568         "fool",
569         "footpad",
570         "imbecile",
571         "knave",
572         "maledict",
573         "miscreant",
574         "niddering",
575         "poltroon",
576         "rattlepate",
577         "reprobate",
578         "scapegrace",
579         "varlet",
580         "villein",      /* (sic.) */
581         "wittol",
582         "worm",
583         "wretch",
584 };
585
586 const char * const random_malediction[] = {
587         "Hell shall soon claim thy remains,",
588         "I chortle at thee, thou pathetic",
589         "Prepare to die, thou",
590         "Resistance is useless,",
591         "Surrender or die, thou",
592         "There shall be no mercy, thou",
593         "Thou shalt repent of thy cunning,",
594         "Thou art as a flea to me,",
595         "Thou art doomed,",
596         "Thy fate is sealed,",
597         "Verily, thou shalt be one dead"
598 };
599
600 /* Insult or intimidate the player */
601 void
602 cuss(mtmp)
603 register struct monst   *mtmp;
604 {
605         if (mtmp->iswiz) {
606             if (!rn2(5))  /* typical bad guy action */
607                 pline("%s laughs fiendishly.", Monnam(mtmp));
608             else
609                 if (u.uhave.amulet && !rn2(SIZE(random_insult)))
610                     verbalize("Relinquish the amulet, %s!",
611                           random_insult[rn2(SIZE(random_insult))]);
612                 else if (u.uhp < 5 && !rn2(2))  /* Panic */
613                     verbalize(rn2(2) ?
614                           "Even now thy life force ebbs, %s!" :
615                           "Savor thy breath, %s, it be thy last!",
616                           random_insult[rn2(SIZE(random_insult))]);
617                 else if (mtmp->mhp < 5 && !rn2(2))      /* Parthian shot */
618                     verbalize(rn2(2) ?
619                               "I shall return." :
620                               "I'll be back.");
621                 else
622                     verbalize("%s %s!",
623                           random_malediction[rn2(SIZE(random_malediction))],
624                           random_insult[rn2(SIZE(random_insult))]);
625         } else if(is_lminion(mtmp)) {
626                 com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0)) +
627                               QT_ANGELIC);
628         } else {
629             if (!rn2(5))
630                 pline("%s casts aspersions on your ancestry.", Monnam(mtmp));
631             else
632                 com_pager(rn2(QTN_DEMONIC) + QT_DEMONIC);
633         }
634 }
635
636 #endif /* OVLB */
637
638 /*wizard.c*/