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
msummon(mon)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
summon_minion(alignment,talk)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 #define Athome (Inhell && !mtmp->cham)
139
140 int
demon_talk(mtmp)141 demon_talk(mtmp) /* returns 1 if it won't attack. */
142 register struct monst *mtmp;
143 {
144 long cash, demand, offer;
145
146 if (uwep && uwep->oartifact == ART_EXCALIBUR) {
147 pline("%s looks very angry.", Amonnam(mtmp));
148 mtmp->mpeaceful = mtmp->mtame = 0;
149 set_malign(mtmp);
150 newsym(mtmp->mx, mtmp->my);
151 return 0;
152 }
153
154 /* Slight advantage given. */
155 if (is_dprince(mtmp->data) && mtmp->minvis) {
156 mtmp->minvis = mtmp->perminvis = 0;
157 if (!Blind) pline("%s appears before you.", Amonnam(mtmp));
158 newsym(mtmp->mx,mtmp->my);
159 }
160 if (youmonst.data->mlet == S_DEMON) { /* Won't blackmail their own. */
161 pline("%s says, \"Good hunting, %s.\"",
162 Amonnam(mtmp), flags.female ? "Sister" : "Brother");
163 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
164 return(1);
165 }
166 #ifndef GOLDOBJ
167 cash = u.ugold;
168 #else
169 cash = money_cnt(invent);
170 #endif
171 demand = (cash * (rnd(80) + 20 * Athome)) /
172 (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))));
173
174 if (!demand) { /* you have no gold */
175 mtmp->mpeaceful = 0;
176 set_malign(mtmp);
177 return 0;
178 } else {
179 /* make sure that the demand is unmeetable if the monster
180 has the Amulet, preventing monster from being satisified
181 and removed from the game (along with said Amulet...) */
182 if (mon_has_amulet(mtmp))
183 demand = cash + (long)rn1(1000,40);
184
185 pline("%s demands %ld %s for safe passage.",
186 Amonnam(mtmp), demand, currency(demand));
187
188 if ((offer = bribe(mtmp)) >= demand) {
189 pline("%s vanishes, laughing about cowardly mortals.",
190 Amonnam(mtmp));
191 } else if (offer > 0L && (long)rnd(40) > (demand - offer)) {
192 pline("%s scowls at you menacingly, then vanishes.",
193 Amonnam(mtmp));
194 } else {
195 pline("%s gets angry...", Amonnam(mtmp));
196 mtmp->mpeaceful = 0;
197 set_malign(mtmp);
198 return 0;
199 }
200 }
201 mongone(mtmp);
202 return(1);
203 }
204
lawful_minion(int difficulty)205 int lawful_minion(int difficulty)
206 /* this routine returns the # of an appropriate minion,
207 given a difficulty rating from 1 to 30 */
208 {
209 difficulty = difficulty + rn2(5) - 2;
210 if (difficulty < 0) difficulty = 0;
211 if (difficulty > 30) difficulty = 30;
212 difficulty /= 3;
213 switch (difficulty) {
214 case 0: return PM_TENGU;
215 case 1: return PM_COUATL;
216 case 2: return PM_WHITE_UNICORN;
217 case 3: return PM_MOVANIC_DEVA;
218 case 4: return PM_MONADIC_DEVA;
219 case 5: return PM_KI_RIN;
220 case 6: return PM_ASTRAL_DEVA;
221 case 7: return PM_ARCHON;
222 case 8: return PM_PLANETAR;
223 case 9: return PM_SOLAR;
224 case 10: return PM_SOLAR;
225
226 default: return PM_TENGU;
227 }
228 }
229
neutral_minion(int difficulty)230 int neutral_minion(int difficulty)
231 /* this routine returns the # of an appropriate minion,
232 given a difficulty rating from 1 to 30 */
233 {
234 difficulty = difficulty + rn2(9) - 4;
235 if (difficulty < 0) difficulty = 0;
236 if (difficulty > 30) difficulty = 30;
237 if (difficulty < 6) return PM_GRAY_UNICORN;
238 if (difficulty < 15) return (PM_AIR_ELEMENTAL+rn2(4));
239 return (PM_DJINNI /* +rn2(4) */);
240 }
241
chaotic_minion(int difficulty)242 int chaotic_minion(int difficulty)
243 /* this routine returns the # of an appropriate minion,
244 given a difficulty rating from 1 to 30 */
245 {
246 difficulty = difficulty + rn2(5) - 2;
247 if (difficulty < 0) difficulty = 0;
248 if (difficulty > 30) difficulty = 30;
249 /* KMH, balance patch -- avoid using floating-point (not supported by all ports) */
250 /* difficulty = (int)((float)difficulty / 1.5);*/
251 difficulty = (difficulty * 2) / 3;
252 switch (difficulty) {
253 case 0: return PM_GREMLIN;
254 case 1:
255 case 2: return (PM_DRETCH+rn2(5));
256 case 3: return PM_BLACK_UNICORN;
257 case 4: return PM_BLOOD_IMP;
258 case 5: return PM_SPINED_DEVIL;
259 case 6: return PM_SHADOW_WOLF;
260 case 7: return PM_HELL_HOUND;
261 case 8: return PM_HORNED_DEVIL;
262 case 9: return PM_BEARDED_DEVIL;
263 case 10: return PM_BAR_LGURA;
264 case 11: return PM_CHASME;
265 case 12: return PM_BARBED_DEVIL;
266 case 13: return PM_VROCK;
267 case 14: return PM_BABAU;
268 case 15: return PM_NALFESHNEE;
269 case 16: return PM_MARILITH;
270 case 17: return PM_NABASSU;
271 case 18: return PM_BONE_DEVIL;
272 case 19: return PM_ICE_DEVIL;
273 case 20: return PM_PIT_FIEND;
274 }
275 return PM_GREMLIN;
276 }
277
278 long
bribe(mtmp)279 bribe(mtmp)
280 struct monst *mtmp;
281 {
282 char buf[BUFSZ];
283 long offer;
284 #ifdef GOLDOBJ
285 long umoney = money_cnt(invent);
286 #endif
287
288 getlin("How much will you offer?", buf);
289 if (sscanf(buf, "%ld", &offer) != 1) offer = 0L;
290
291 /*Michael Paddon -- fix for negative offer to monster*/
292 /*JAR880815 - */
293 if (offer < 0L) {
294 You("try to shortchange %s, but fumble.",
295 mon_nam(mtmp));
296 return 0L;
297 } else if (offer == 0L) {
298 You("refuse.");
299 return 0L;
300 #ifndef GOLDOBJ
301 } else if (offer >= u.ugold) {
302 You("give %s all your gold.", mon_nam(mtmp));
303 offer = u.ugold;
304 } else {
305 You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer));
306 }
307 u.ugold -= offer;
308 mtmp->mgold += offer;
309 #else
310 } else if (offer >= umoney) {
311 You("give %s all your money.", mon_nam(mtmp));
312 offer = umoney;
313 } else {
314 You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer));
315 }
316 (void) money2mon(mtmp, offer);
317 #endif
318 flags.botl = 1;
319 return(offer);
320 }
321
322 int
dprince(atyp)323 dprince(atyp)
324 aligntyp atyp;
325 {
326 int tryct, pm;
327
328 for (tryct = 0; tryct < 20; tryct++) {
329 pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS);
330 if (!(mvitals[pm].mvflags & G_GONE) &&
331 (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
332 return(pm);
333 }
334 return(dlord(atyp)); /* approximate */
335 }
336
337 int
dlord(atyp)338 dlord(atyp)
339 aligntyp atyp;
340 {
341 int tryct, pm;
342
343 for (tryct = 0; tryct < 20; tryct++) {
344 pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX);
345 if (!(mvitals[pm].mvflags & G_GONE) &&
346 (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
347 return(pm);
348 }
349 return(ndemon(atyp)); /* approximate */
350 }
351
352 /* create lawful (good) lord */
353 int
llord()354 llord()
355 {
356 if (!(mvitals[PM_ARCHON].mvflags & G_GONE))
357 return(PM_ARCHON);
358
359 return(lminion()); /* approximate */
360 }
361
362 int
lminion()363 lminion()
364 {
365 int tryct;
366 struct permonst *ptr;
367
368 for (tryct = 0; tryct < 20; tryct++) {
369 ptr = mkclass(S_ANGEL,0);
370 if (ptr && !is_lord(ptr))
371 return(monsndx(ptr));
372 }
373
374 return NON_PM;
375 }
376
377 int
ndemon(atyp)378 ndemon(atyp)
379 aligntyp atyp;
380 {
381 int tryct;
382 struct permonst *ptr;
383
384 for (tryct = 0; tryct < 20; tryct++) {
385 ptr = mkclass(S_DEMON, 0);
386 if (ptr && is_ndemon(ptr) &&
387 (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp)))
388 return(monsndx(ptr));
389 }
390
391 return NON_PM;
392 }
393
394 /*minion.c*/
395