OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / src / minion.c
1 /*      SCCS Id: @(#)minion.c   3.4     2003/01/09      */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6 #include "emin.h"
7 #include "epri.h"
8
9 void
10 msummon(mon)            /* mon summons a monster */
11 struct monst *mon;
12 {
13         register struct permonst *ptr;
14         register int dtype = NON_PM, cnt = 0;
15         aligntyp atyp;
16         struct monst *mtmp;
17
18         if (mon) {
19             ptr = mon->data;
20             atyp = (ptr->maligntyp==A_NONE) ? A_NONE : sgn(ptr->maligntyp);
21             if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST]
22                 || mon->data == &mons[PM_ANGEL])
23                 atyp = EPRI(mon)->shralign;
24         } else {
25             ptr = &mons[PM_WIZARD_OF_YENDOR];
26             atyp = (ptr->maligntyp==A_NONE) ? A_NONE : sgn(ptr->maligntyp);
27         }
28             
29         if (is_dprince(ptr) || (ptr == &mons[PM_WIZARD_OF_YENDOR])) {
30             dtype = (!rn2(20)) ? dprince(atyp) :
31                                  (!rn2(4)) ? dlord(atyp) : ndemon(atyp);
32             cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
33         } else if (is_dlord(ptr)) {
34             dtype = (!rn2(50)) ? dprince(atyp) :
35                                  (!rn2(20)) ? dlord(atyp) : ndemon(atyp);
36             cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
37         } else if (is_ndemon(ptr)) {
38             dtype = (!rn2(20)) ? dlord(atyp) :
39                                  (!rn2(6)) ? ndemon(atyp) : monsndx(ptr);
40             cnt = 1;
41         } else if (is_lminion(mon)) {
42             dtype = (is_lord(ptr) && !rn2(20)) ? llord() :
43                      (is_lord(ptr) || !rn2(6)) ? lminion() : monsndx(ptr);
44             cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1;
45         } else if (ptr == &mons[PM_ANGEL]) {
46             /* non-lawful angels can also summon */
47             if (!rn2(6)) {
48                 switch (atyp) { /* see summon_minion */
49                 case A_NEUTRAL:
50                     dtype = PM_AIR_ELEMENTAL + rn2(4);
51                     break;
52                 case A_CHAOTIC:
53                 case A_NONE:
54                     dtype = ndemon(atyp);
55                     break;
56                 }
57             } else {
58                 dtype = PM_ANGEL;
59             }
60             cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1;
61         }
62
63         if (dtype == NON_PM) return;
64
65         /* sanity checks */
66         if (cnt > 1 && (mons[dtype].geno & G_UNIQ)) cnt = 1;
67         /*
68          * If this daemon is unique and being re-summoned (the only way we
69          * could get this far with an extinct dtype), try another.
70          */
71         if (mvitals[dtype].mvflags & G_GONE) {
72             dtype = ndemon(atyp);
73             if (dtype == NON_PM) return;
74         }
75
76         while (cnt > 0) {
77             mtmp = makemon(&mons[dtype], u.ux, u.uy, NO_MM_FLAGS);
78             if (mtmp && (dtype == PM_ANGEL)) {
79                 /* alignment should match the summoner */
80                 EPRI(mtmp)->shralign = atyp;
81             }
82             cnt--;
83         }
84 }
85
86 void
87 summon_minion(alignment, talk)
88 aligntyp alignment;
89 boolean talk;
90 {
91     register struct monst *mon;
92     int mnum;
93
94     switch ((int)alignment) {
95         case A_LAWFUL:
96             mnum = lminion();
97             break;
98         case A_NEUTRAL:
99             mnum = PM_AIR_ELEMENTAL + rn2(4);
100             break;
101         case A_CHAOTIC:
102         case A_NONE:
103             mnum = ndemon(alignment);
104             break;
105         default:
106             impossible("unaligned player?");
107             mnum = ndemon(A_NONE);
108             break;
109     }
110     if (mnum == NON_PM) {
111         mon = 0;
112     } else if (mons[mnum].pxlth == 0) {
113         struct permonst *pm = &mons[mnum];
114         mon = makemon(pm, u.ux, u.uy, MM_EMIN);
115         if (mon) {
116             mon->isminion = TRUE;
117             EMIN(mon)->min_align = alignment;
118         }
119     } else if (mnum == PM_ANGEL) {
120         mon = makemon(&mons[mnum], u.ux, u.uy, NO_MM_FLAGS);
121         if (mon) {
122             mon->isminion = TRUE;
123             EPRI(mon)->shralign = alignment;    /* always A_LAWFUL here */
124         }
125     } else
126         mon = makemon(&mons[mnum], u.ux, u.uy, NO_MM_FLAGS);
127     if (mon) {
128         if (talk) {
129             pline_The("voice of %s booms:", align_gname(alignment));
130             verbalize("Thou shalt pay for thy indiscretion!");
131             if (!Blind)
132                 pline("%s appears before you.", Amonnam(mon));
133         }
134         mon->mpeaceful = FALSE;
135         /* don't call set_malign(); player was naughty */
136     }
137 }
138
139 #define Athome  (Inhell && !mtmp->cham)
140
141 int
142 demon_talk(mtmp)                /* returns 1 if it won't attack. */
143 register struct monst *mtmp;
144 {
145         long cash, demand, offer;
146
147         if (uwep && uwep->oartifact == ART_EXCALIBUR) {
148             pline("%s looks very angry.", Amonnam(mtmp));
149             mtmp->mpeaceful = mtmp->mtame = 0;
150             set_malign(mtmp);
151             newsym(mtmp->mx, mtmp->my);
152             return 0;
153         }
154
155         /* Slight advantage given. */
156         if (is_dprince(mtmp->data) && mtmp->minvis) {
157             mtmp->minvis = mtmp->perminvis = 0;
158             if (!Blind) pline("%s appears before you.", Amonnam(mtmp));
159             newsym(mtmp->mx,mtmp->my);
160         }
161         if (youmonst.data->mlet == S_DEMON) {   /* Won't blackmail their own. */
162             pline("%s says, \"Good hunting, %s.\"",
163                   Amonnam(mtmp), flags.female ? "Sister" : "Brother");
164             if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
165             return(1);
166         }
167 #ifndef GOLDOBJ
168         cash = u.ugold;
169 #else
170         cash = money_cnt(invent);
171 #endif
172         demand = (cash * (rnd(80) + 20 * Athome)) /
173             (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))));
174
175         if (!demand) {          /* you have no gold */
176             mtmp->mpeaceful = 0;
177             set_malign(mtmp);
178             return 0;
179         } else {
180             /* make sure that the demand is unmeetable if the monster
181                has the Amulet, preventing monster from being satisified
182                and removed from the game (along with said Amulet...) */
183             if (mon_has_amulet(mtmp))
184                 demand = cash + (long)rn1(1000,40);
185
186             pline("%s demands %ld %s for safe passage.",
187                   Amonnam(mtmp), demand, currency(demand));
188
189             if ((offer = bribe(mtmp)) >= demand) {
190                 pline("%s vanishes, laughing about cowardly mortals.",
191                       Amonnam(mtmp));
192             } else if (offer > 0L && (long)rnd(40) > (demand - offer)) {
193                 pline("%s scowls at you menacingly, then vanishes.",
194                       Amonnam(mtmp));
195             } else {
196                 pline("%s gets angry...", Amonnam(mtmp));
197                 mtmp->mpeaceful = 0;
198                 set_malign(mtmp);
199                 return 0;
200             }
201         }
202         mongone(mtmp);
203         return(1);
204 }
205
206 long
207 bribe(mtmp)
208 struct monst *mtmp;
209 {
210         char buf[BUFSZ];
211         long offer;
212 #ifdef GOLDOBJ
213         long umoney = money_cnt(invent);
214 #endif
215
216         getlin("How much will you offer?", buf);
217         if (sscanf(buf, "%ld", &offer) != 1) offer = 0L;
218
219         /*Michael Paddon -- fix for negative offer to monster*/
220         /*JAR880815 - */
221         if (offer < 0L) {
222                 You("try to shortchange %s, but fumble.",
223                         mon_nam(mtmp));
224                 return 0L;
225         } else if (offer == 0L) {
226                 You("refuse.");
227                 return 0L;
228 #ifndef GOLDOBJ
229         } else if (offer >= u.ugold) {
230                 You("give %s all your gold.", mon_nam(mtmp));
231                 offer = u.ugold;
232         } else {
233                 You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer));
234         }
235         u.ugold -= offer;
236         mtmp->mgold += offer;
237 #else
238         } else if (offer >= umoney) {
239                 You("give %s all your gold.", mon_nam(mtmp));
240                 offer = umoney;
241         } else {
242                 You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer));
243         }
244         (void) money2mon(mtmp, offer);
245 #endif
246         flags.botl = 1;
247         return(offer);
248 }
249
250 int
251 dprince(atyp)
252 aligntyp atyp;
253 {
254         int tryct, pm;
255
256         for (tryct = 0; tryct < 20; tryct++) {
257             pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS);
258             if (!(mvitals[pm].mvflags & G_GONE) &&
259                     (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
260                 return(pm);
261         }
262         return(dlord(atyp));    /* approximate */
263 }
264
265 int
266 dlord(atyp)
267 aligntyp atyp;
268 {
269         int tryct, pm;
270
271         for (tryct = 0; tryct < 20; tryct++) {
272             pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX);
273             if (!(mvitals[pm].mvflags & G_GONE) &&
274                     (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
275                 return(pm);
276         }
277         return(ndemon(atyp));   /* approximate */
278 }
279
280 /* create lawful (good) lord */
281 int
282 llord()
283 {
284         if (!(mvitals[PM_ARCHON].mvflags & G_GONE))
285                 return(PM_ARCHON);
286
287         return(lminion());      /* approximate */
288 }
289
290 int
291 lminion()
292 {
293         int     tryct;
294         struct  permonst *ptr;
295
296         for (tryct = 0; tryct < 20; tryct++) {
297             ptr = mkclass(S_ANGEL,0);
298             if (ptr && !is_lord(ptr))
299                 return(monsndx(ptr));
300         }
301
302         return NON_PM;
303 }
304
305 int
306 ndemon(atyp)
307 aligntyp atyp;
308 {
309         int     tryct;
310         struct  permonst *ptr;
311
312         for (tryct = 0; tryct < 20; tryct++) {
313             ptr = mkclass(S_DEMON, 0);
314             if (ptr && is_ndemon(ptr) &&
315                     (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp)))
316                 return(monsndx(ptr));
317         }
318
319         return NON_PM;
320 }
321
322 /*minion.c*/