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