OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / src / minion.c
1 /* NetHack 3.6  minion.c        $NHDT-Date: 1432512773 2015/05/25 00:12:53 $  $NHDT-Branch: master $:$NHDT-Revision: 1.33 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 void
8 newemin(mtmp)
9 struct monst *mtmp;
10 {
11     if (!mtmp->mextra)
12         mtmp->mextra = newmextra();
13     if (!EMIN(mtmp)) {
14         EMIN(mtmp) = (struct emin *) alloc(sizeof(struct emin));
15         (void) memset((genericptr_t) EMIN(mtmp), 0, sizeof(struct emin));
16     }
17 }
18
19 void
20 free_emin(mtmp)
21 struct monst *mtmp;
22 {
23     if (mtmp->mextra && EMIN(mtmp)) {
24         free((genericptr_t) EMIN(mtmp));
25         EMIN(mtmp) = (struct emin *) 0;
26     }
27     mtmp->isminion = 0;
28 }
29
30 /* count the number of monsters on the level */
31 int
32 monster_census(spotted)
33 boolean spotted; /* seen|sensed vs all */
34 {
35     struct monst *mtmp;
36     int count = 0;
37
38     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
39         if (DEADMONSTER(mtmp))
40             continue;
41         if (spotted && !canspotmon(mtmp))
42             continue;
43         ++count;
44     }
45     return count;
46 }
47
48 /* mon summons a monster */
49 int
50 msummon(mon)
51 struct monst *mon;
52 {
53     struct permonst *ptr;
54     int dtype = NON_PM, cnt = 0, result = 0, census;
55     aligntyp atyp;
56     struct monst *mtmp;
57
58     if (mon) {
59         ptr = mon->data;
60         atyp = mon->ispriest ? EPRI(mon)->shralign
61                              : mon->isminion ? EMIN(mon)->min_align
62                                              : (ptr->maligntyp == A_NONE)
63                                                    ? A_NONE
64                                                    : sgn(ptr->maligntyp);
65     } else {
66         ptr = &mons[PM_WIZARD_OF_YENDOR];
67         atyp = (ptr->maligntyp == A_NONE) ? A_NONE : sgn(ptr->maligntyp);
68     }
69
70     if (is_dprince(ptr) || (ptr == &mons[PM_WIZARD_OF_YENDOR])) {
71         dtype = (!rn2(20)) ? dprince(atyp) : (!rn2(4)) ? dlord(atyp)
72                                                        : ndemon(atyp);
73         cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
74     } else if (is_dlord(ptr)) {
75         dtype = (!rn2(50)) ? dprince(atyp) : (!rn2(20)) ? dlord(atyp)
76                                                         : ndemon(atyp);
77         cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
78     } else if (is_ndemon(ptr)) {
79         dtype = (!rn2(20)) ? dlord(atyp) : (!rn2(6)) ? ndemon(atyp)
80                                                      : monsndx(ptr);
81         cnt = 1;
82     } else if (is_lminion(mon)) {
83         dtype = (is_lord(ptr) && !rn2(20))
84                     ? llord()
85                     : (is_lord(ptr) || !rn2(6)) ? lminion() : monsndx(ptr);
86         cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1;
87     } else if (ptr == &mons[PM_ANGEL]) {
88         /* non-lawful angels can also summon */
89         if (!rn2(6)) {
90             switch (atyp) { /* see summon_minion */
91             case A_NEUTRAL:
92                 dtype = PM_AIR_ELEMENTAL + rn2(4);
93                 break;
94             case A_CHAOTIC:
95             case A_NONE:
96                 dtype = ndemon(atyp);
97                 break;
98             }
99         } else {
100             dtype = PM_ANGEL;
101         }
102         cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1;
103     }
104
105     if (dtype == NON_PM)
106         return 0;
107
108     /* sanity checks */
109     if (cnt > 1 && (mons[dtype].geno & G_UNIQ))
110         cnt = 1;
111     /*
112      * If this daemon is unique and being re-summoned (the only way we
113      * could get this far with an extinct dtype), try another.
114      */
115     if (mvitals[dtype].mvflags & G_GONE) {
116         dtype = ndemon(atyp);
117         if (dtype == NON_PM)
118             return 0;
119     }
120
121     /* some candidates can generate a group of monsters, so simple
122        count of non-null makemon() result is not sufficient */
123     census = monster_census(FALSE);
124
125     while (cnt > 0) {
126         mtmp = makemon(&mons[dtype], u.ux, u.uy, MM_EMIN);
127         if (mtmp) {
128             result++;
129             /* an angel's alignment should match the summoner */
130             if (dtype == PM_ANGEL) {
131                 mtmp->isminion = 1;
132                 EMIN(mtmp)->min_align = atyp;
133                 /* renegade if same alignment but not peaceful
134                    or peaceful but different alignment */
135                 EMIN(mtmp)->renegade =
136                     (atyp != u.ualign.type) ^ !mtmp->mpeaceful;
137             }
138         }
139         cnt--;
140     }
141
142     /* how many monsters exist now compared to before? */
143     if (result)
144         result = monster_census(FALSE) - census;
145
146     return result;
147 }
148
149 void
150 summon_minion(alignment, talk)
151 aligntyp alignment;
152 boolean talk;
153 {
154     register struct monst *mon;
155     int mnum;
156
157     switch ((int) alignment) {
158     case A_LAWFUL:
159         mnum = lminion();
160         break;
161     case A_NEUTRAL:
162         mnum = PM_AIR_ELEMENTAL + rn2(4);
163         break;
164     case A_CHAOTIC:
165     case A_NONE:
166         mnum = ndemon(alignment);
167         break;
168     default:
169         impossible("unaligned player?");
170         mnum = ndemon(A_NONE);
171         break;
172     }
173     if (mnum == NON_PM) {
174         mon = 0;
175     } else if (mnum == PM_ANGEL) {
176         mon = makemon(&mons[mnum], u.ux, u.uy, MM_EMIN);
177         if (mon) {
178             mon->isminion = 1;
179             EMIN(mon)->min_align = alignment;
180             EMIN(mon)->renegade = FALSE;
181         }
182     } else if (mnum != PM_SHOPKEEPER && mnum != PM_GUARD
183                && mnum != PM_ALIGNED_PRIEST && mnum != PM_HIGH_PRIEST) {
184         /* This was mons[mnum].pxlth == 0 but is this restriction
185            appropriate or necessary now that the structures are separate? */
186         mon = makemon(&mons[mnum], u.ux, u.uy, MM_EMIN);
187         if (mon) {
188             mon->isminion = 1;
189             EMIN(mon)->min_align = alignment;
190             EMIN(mon)->renegade = FALSE;
191         }
192     } else {
193         mon = makemon(&mons[mnum], u.ux, u.uy, NO_MM_FLAGS);
194     }
195     if (mon) {
196         if (talk) {
197             pline_The("voice of %s booms:", align_gname(alignment));
198             verbalize("Thou shalt pay for thine indiscretion!");
199             if (!Blind)
200                 pline("%s appears before you.", Amonnam(mon));
201             mon->mstrategy &= ~STRAT_APPEARMSG;
202         }
203         mon->mpeaceful = FALSE;
204         /* don't call set_malign(); player was naughty */
205     }
206 }
207
208 #define Athome (Inhell && (mtmp->cham == NON_PM))
209
210 /* returns 1 if it won't attack. */
211 int
212 demon_talk(mtmp)
213 register struct monst *mtmp;
214 {
215     long cash, demand, offer;
216
217     if (uwep && uwep->oartifact == ART_EXCALIBUR) {
218         pline("%s looks very angry.", Amonnam(mtmp));
219         mtmp->mpeaceful = mtmp->mtame = 0;
220         set_malign(mtmp);
221         newsym(mtmp->mx, mtmp->my);
222         return 0;
223     }
224
225     if (is_fainted()) {
226         reset_faint(); /* if fainted - wake up */
227     } else {
228         stop_occupation();
229         if (multi > 0) {
230             nomul(0);
231             unmul((char *) 0);
232         }
233     }
234
235     /* Slight advantage given. */
236     if (is_dprince(mtmp->data) && mtmp->minvis) {
237         boolean wasunseen = !canspotmon(mtmp);
238
239         mtmp->minvis = mtmp->perminvis = 0;
240         if (wasunseen && canspotmon(mtmp)) {
241             pline("%s appears before you.", Amonnam(mtmp));
242             mtmp->mstrategy &= ~STRAT_APPEARMSG;
243         }
244         newsym(mtmp->mx, mtmp->my);
245     }
246     if (youmonst.data->mlet == S_DEMON) { /* Won't blackmail their own. */
247         pline("%s says, \"Good hunting, %s.\"", Amonnam(mtmp),
248               flags.female ? "Sister" : "Brother");
249         if (!tele_restrict(mtmp))
250             (void) rloc(mtmp, TRUE);
251         return (1);
252     }
253     cash = money_cnt(invent);
254     demand =
255         (cash * (rnd(80) + 20 * Athome))
256         / (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))));
257
258     if (!demand || multi < 0) { /* you have no gold or can't move */
259         mtmp->mpeaceful = 0;
260         set_malign(mtmp);
261         return 0;
262     } else {
263         /* make sure that the demand is unmeetable if the monster
264            has the Amulet, preventing monster from being satisfied
265            and removed from the game (along with said Amulet...) */
266         if (mon_has_amulet(mtmp))
267             demand = cash + (long) rn1(1000, 40);
268
269         pline("%s demands %ld %s for safe passage.", Amonnam(mtmp), demand,
270               currency(demand));
271
272         if ((offer = bribe(mtmp)) >= demand) {
273             pline("%s vanishes, laughing about cowardly mortals.",
274                   Amonnam(mtmp));
275         } else if (offer > 0L && (long) rnd(40) > (demand - offer)) {
276             pline("%s scowls at you menacingly, then vanishes.",
277                   Amonnam(mtmp));
278         } else {
279             pline("%s gets angry...", Amonnam(mtmp));
280             mtmp->mpeaceful = 0;
281             set_malign(mtmp);
282             return 0;
283         }
284     }
285     mongone(mtmp);
286     return (1);
287 }
288
289 long
290 bribe(mtmp)
291 struct monst *mtmp;
292 {
293     char buf[BUFSZ];
294     long offer;
295     long umoney = money_cnt(invent);
296
297     getlin("How much will you offer?", buf);
298     if (sscanf(buf, "%ld", &offer) != 1)
299         offer = 0L;
300
301     /*Michael Paddon -- fix for negative offer to monster*/
302     /*JAR880815 - */
303     if (offer < 0L) {
304         You("try to shortchange %s, but fumble.", mon_nam(mtmp));
305         return 0L;
306     } else if (offer == 0L) {
307         You("refuse.");
308         return 0L;
309     } else if (offer >= umoney) {
310         You("give %s all your gold.", mon_nam(mtmp));
311         offer = umoney;
312     } else {
313         You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer));
314     }
315     (void) money2mon(mtmp, offer);
316     context.botl = 1;
317     return (offer);
318 }
319
320 int
321 dprince(atyp)
322 aligntyp atyp;
323 {
324     int tryct, pm;
325
326     for (tryct = !In_endgame(&u.uz) ? 20 : 0; tryct > 0; --tryct) {
327         pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS);
328         if (!(mvitals[pm].mvflags & G_GONE)
329             && (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
330             return (pm);
331     }
332     return (dlord(atyp)); /* approximate */
333 }
334
335 int
336 dlord(atyp)
337 aligntyp atyp;
338 {
339     int tryct, pm;
340
341     for (tryct = !In_endgame(&u.uz) ? 20 : 0; tryct > 0; --tryct) {
342         pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX);
343         if (!(mvitals[pm].mvflags & G_GONE)
344             && (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
345             return (pm);
346     }
347     return (ndemon(atyp)); /* approximate */
348 }
349
350 /* create lawful (good) lord */
351 int
352 llord()
353 {
354     if (!(mvitals[PM_ARCHON].mvflags & G_GONE))
355         return (PM_ARCHON);
356
357     return (lminion()); /* approximate */
358 }
359
360 int
361 lminion()
362 {
363     int tryct;
364     struct permonst *ptr;
365
366     for (tryct = 0; tryct < 20; tryct++) {
367         ptr = mkclass(S_ANGEL, 0);
368         if (ptr && !is_lord(ptr))
369             return (monsndx(ptr));
370     }
371
372     return NON_PM;
373 }
374
375 int
376 ndemon(atyp)
377 aligntyp atyp;
378 {
379     int tryct;
380     struct permonst *ptr;
381
382     for (tryct = 0; tryct < 20; tryct++) {
383         ptr = mkclass(S_DEMON, 0);
384         if (ptr && is_ndemon(ptr)
385             && (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp)))
386             return (monsndx(ptr));
387     }
388
389     return NON_PM;
390 }
391
392 /* guardian angel has been affected by conflict so is abandoning hero */
393 void
394 lose_guardian_angel(mon)
395 struct monst *mon; /* if null, angel hasn't been created yet */
396 {
397     coord mm;
398     int i;
399
400     if (mon) {
401         if (canspotmon(mon)) {
402             if (!Deaf) {
403                 pline("%s rebukes you, saying:", Monnam(mon));
404                 verbalize("Since you desire conflict, have some more!");
405             } else {
406                 pline("%s vanishes!", Monnam(mon));
407             }
408         }
409         mongone(mon);
410     }
411     /* create 2 to 4 hostile angels to replace the lost guardian */
412     for (i = rn1(3, 2); i > 0; --i) {
413         mm.x = u.ux;
414         mm.y = u.uy;
415         if (enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL]))
416             (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type, mm.x, mm.y,
417                              FALSE);
418     }
419 }
420
421 /* just entered the Astral Plane; receive tame guardian angel if worthy */
422 void
423 gain_guardian_angel()
424 {
425     struct monst *mtmp;
426     struct obj *otmp;
427     coord mm;
428
429     Hear_again(); /* attempt to cure any deafness now (divine
430                      message will be heard even if that fails) */
431     if (Conflict) {
432         pline("A voice booms:");
433         verbalize("Thy desire for conflict shall be fulfilled!");
434         /* send in some hostile angels instead */
435         lose_guardian_angel((struct monst *) 0);
436     } else if (u.ualign.record > 8) { /* fervent */
437         pline("A voice whispers:");
438         verbalize("Thou hast been worthy of me!");
439         mm.x = u.ux;
440         mm.y = u.uy;
441         if (enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])
442             && (mtmp = mk_roamer(&mons[PM_ANGEL], u.ualign.type, mm.x, mm.y,
443                                  TRUE)) != 0) {
444             mtmp->mstrategy &= ~STRAT_APPEARMSG;
445             if (!Blind)
446                 pline("An angel appears near you.");
447             else
448                 You_feel("the presence of a friendly angel near you.");
449             /* guardian angel -- the one case mtame doesn't
450              * imply an edog structure, so we don't want to
451              * call tamedog().
452              */
453             mtmp->mtame = 10;
454             /* make him strong enough vs. endgame foes */
455             mtmp->m_lev = rn1(8, 15);
456             mtmp->mhp = mtmp->mhpmax =
457                 d((int) mtmp->m_lev, 10) + 30 + rnd(30);
458             if ((otmp = select_hwep(mtmp)) == 0) {
459                 otmp = mksobj(SILVER_SABER, FALSE, FALSE);
460                 if (mpickobj(mtmp, otmp))
461                     panic("merged weapon?");
462             }
463             bless(otmp);
464             if (otmp->spe < 4)
465                 otmp->spe += rnd(4);
466             if ((otmp = which_armor(mtmp, W_ARMS)) == 0
467                 || otmp->otyp != SHIELD_OF_REFLECTION) {
468                 (void) mongets(mtmp, AMULET_OF_REFLECTION);
469                 m_dowear(mtmp, TRUE);
470             }
471         }
472     }
473 }
474
475 /*minion.c*/