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
9void
10msummon(mon)		/* mon summons a monster */
11struct 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
86void
87summon_minion(alignment, talk)
88aligntyp alignment;
89boolean 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
141int
142demon_talk(mtmp)		/* returns 1 if it won't attack. */
143register 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
206long
207bribe(mtmp)
208struct 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
250int
251dprince(atyp)
252aligntyp 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
265int
266dlord(atyp)
267aligntyp 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 */
281int
282llord()
283{
284	if (!(mvitals[PM_ARCHON].mvflags & G_GONE))
285		return(PM_ARCHON);
286
287	return(lminion());	/* approximate */
288}
289
290int
291lminion()
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
305int
306ndemon(atyp)
307aligntyp 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*/
323