1    | /*	SCCS Id: @(#)minion.c	3.3	2000/06/05	*/
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(ptr)		/* ptr summons a monster */
11   | register struct permonst *ptr;
12   | {
13   | 	register int dtype = NON_PM, cnt = 0;
14   | 	aligntyp atyp = sgn(ptr->maligntyp);
15   | 
16   | 	if (is_dprince(ptr) || (ptr == &mons[PM_WIZARD_OF_YENDOR])) {
17   | 	    dtype = (!rn2(20)) ? dprince(atyp) :
18   | 				 (!rn2(4)) ? dlord(atyp) : ndemon(atyp);
19   | 	    cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
20   | 	} else if (is_dlord(ptr)) {
21   | 	    dtype = (!rn2(50)) ? dprince(atyp) :
22   | 				 (!rn2(20)) ? dlord(atyp) : ndemon(atyp);
23   | 	    cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1;
24   | 	} else if (is_ndemon(ptr)) {
25   | 	    dtype = (!rn2(20)) ? dlord(atyp) :
26   | 				 (!rn2(6)) ? ndemon(atyp) : monsndx(ptr);
27   | 	    cnt = 1;
28   | 	} else if (is_lminion(ptr)) {
29   | 	    dtype = (is_lord(ptr) && !rn2(20)) ? llord() :
30   | 		     (is_lord(ptr) || !rn2(6)) ? lminion() : monsndx(ptr);
31   | 	    cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1;
32   | 	}
33   | 
34   | 	if (dtype == NON_PM) return;
35   | 
36   | 	/* sanity checks */
37   | 	if (cnt > 1 && (mons[dtype].geno & G_UNIQ)) cnt = 1;
38   | 	/*
39   | 	 * If this daemon is unique and being re-summoned (the only way we
40   | 	 * could get this far with an extinct dtype), try another.
41   | 	 */
42   | 	if (mvitals[dtype].mvflags & G_GONE) {
43   | 	    dtype = ndemon(atyp);
44   | 	    if (dtype == NON_PM) return;
45   | 	}
46   | 
47   | 	while (cnt > 0) {
48   | 	    (void)makemon(&mons[dtype], u.ux, u.uy, NO_MM_FLAGS);
49   | 	    cnt--;
50   | 	}
51   | 	return;
52   | }
53   | 
54   | void
55   | summon_minion(alignment, talk)
56   | aligntyp alignment;
57   | boolean talk;
58   | {
59   |     register struct monst *mon;
60   |     int mnum;
61   | 
62   |     switch ((int)alignment) {
63   | 	case A_LAWFUL:
64   | 	    mnum = lminion();
65   | 	    break;
66   | 	case A_NEUTRAL:
67   | 	    mnum = PM_AIR_ELEMENTAL + rn2(4);
68   | 	    break;
69   | 	case A_CHAOTIC:
70   | 	case A_NONE:
71   | 	    mnum = ndemon(alignment);
72   | 	    break;
73   | 	default:
74   | 	    impossible("unaligned player?");
75   | 	    mnum = ndemon(A_NONE);
76   | 	    break;
77   |     }
78   |     if (mnum == NON_PM) {
79   | 	mon = 0;
80   |     } else if (mons[mnum].pxlth == 0) {
81   | 	struct permonst *pm = &mons[mnum];
82   | 	mon = makemon(pm, u.ux, u.uy, MM_EMIN);
83   | 	if (mon) {
84   | 	    mon->isminion = TRUE;
85   | 	    EMIN(mon)->min_align = alignment;
86   | 	}
87   |     } else if (mnum == PM_ANGEL) {
88   | 	mon = makemon(&mons[mnum], u.ux, u.uy, NO_MM_FLAGS);
89   | 	if (mon) {
90   | 	    mon->isminion = TRUE;
91   | 	    EPRI(mon)->shralign = alignment;	/* always A_LAWFUL here */
92   | 	}
93   |     } else
94   | 	mon = makemon(&mons[mnum], u.ux, u.uy, NO_MM_FLAGS);
95   |     if (mon) {
96   | 	if (talk) {
97   | 	    pline_The("voice of %s booms:", align_gname(alignment));
98   | 	    verbalize("Thou shalt pay for thy indiscretion!");
99   | 	    if (!Blind)
100  | 		pline("%s appears before you.", Amonnam(mon));
101  | 	}
102  | 	mon->mpeaceful = FALSE;
103  | 	/* don't call set_malign(); player was naughty */
104  |     }
105  | }
106  | 
107  | #define Athome	(Inhell && !mtmp->cham)
108  | 
109  | int
110  | demon_talk(mtmp)		/* returns 1 if it won't attack. */
111  | register struct monst *mtmp;
112  | {
113  | 	long	demand, offer;
114  | 
115  | 	if (uwep && uwep->oartifact == ART_EXCALIBUR) {
116  | 	    pline("%s looks very angry.", Amonnam(mtmp));
117  | 	    mtmp->mpeaceful = mtmp->mtame = 0;
118  | 	    newsym(mtmp->mx, mtmp->my);
119  | 	    return 0;
120  | 	}
121  | 
122  | 	/* Slight advantage given. */
123  | 	if (is_dprince(mtmp->data) && mtmp->minvis) {
124  | 	    mtmp->minvis = mtmp->perminvis = 0;
125  | 	    if (!Blind) pline("%s appears before you.", Amonnam(mtmp));
126  | 	    newsym(mtmp->mx,mtmp->my);
127  | 	}
128  | 	if (youmonst.data->mlet == S_DEMON) {	/* Won't blackmail their own. */
129  | 	    pline("%s says, \"Good hunting, %s.\"",
130  | 		  Amonnam(mtmp), flags.female ? "Sister" : "Brother");
131  | 	    if (!tele_restrict(mtmp)) rloc(mtmp);
132  | 	    return(1);
133  | 	}
134  | 	demand = (u.ugold * (rnd(80) + 20 * Athome)) /
135  | 		 100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp)));
136  | 	if (!demand)		/* you have no gold */
137  | 	    return mtmp->mpeaceful = 0;
138  | 	else {
139  | 	    pline("%s demands %ld zorkmid%s for safe passage.",
140  | 		  Amonnam(mtmp), demand, plur(demand));
141  | 
142  | 	    if ((offer = bribe(mtmp)) >= demand) {
143  | 		pline("%s vanishes, laughing about cowardly mortals.",
144  | 		      Amonnam(mtmp));
145  | 	    } else {
146  | 		if ((long)rnd(40) > (demand - offer)) {
147  | 		    pline("%s scowls at you menacingly, then vanishes.",
148  | 			  Amonnam(mtmp));
149  | 		} else {
150  | 		    pline("%s gets angry...", Amonnam(mtmp));
151  | 		    return mtmp->mpeaceful = 0;
152  | 		}
153  | 	    }
154  | 	}
155  | 	mongone(mtmp);
156  | 	return(1);
157  | }
158  | 
159  | long
160  | bribe(mtmp)
161  | struct monst *mtmp;
162  | {
163  | 	char buf[BUFSZ];
164  | 	long offer;
165  | 
166  | 	getlin("How much will you offer?", buf);
167  | 	(void) sscanf(buf, "%ld", &offer);
168  | 
169  | 	/*Michael Paddon -- fix for negative offer to monster*/
170  | 	/*JAR880815 - */
171  | 	if (offer < 0L) {
172  | 		You("try to shortchange %s, but fumble.",
173  | 			mon_nam(mtmp));
174  | 		offer = 0L;
175  | 	} else if (offer == 0L) {
176  | 		You("refuse.");
177  | 	} else if (offer >= u.ugold) {
178  | 		You("give %s all your gold.", mon_nam(mtmp));
179  | 		offer = u.ugold;
180  | 	} else You("give %s %ld zorkmid%s.", mon_nam(mtmp), offer,
181  | 		   plur(offer));
182  | 
183  | 	u.ugold -= offer;
184  | 	mtmp->mgold += offer;
185  | 	flags.botl = 1;
186  | 	return(offer);
187  | }
188  | 
189  | int
190  | dprince(atyp)
191  | aligntyp atyp;
192  | {
193  | 	int tryct, pm;
194  | 
195  | 	for (tryct = 0; tryct < 20; tryct++) {
196  | 	    pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS);
197  | 	    if (!(mvitals[pm].mvflags & G_GONE) &&
198  | 		    (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
199  | 		return(pm);
200  | 	}
201  | 	return(dlord(atyp));	/* approximate */
202  | }
203  | 
204  | int
205  | dlord(atyp)
206  | aligntyp atyp;
207  | {
208  | 	int tryct, pm;
209  | 
210  | 	for (tryct = 0; tryct < 20; tryct++) {
211  | 	    pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX);
212  | 	    if (!(mvitals[pm].mvflags & G_GONE) &&
213  | 		    (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
214  | 		return(pm);
215  | 	}
216  | 	return(ndemon(atyp));	/* approximate */
217  | }
218  | 
219  | /* create lawful (good) lord */
220  | int
221  | llord()
222  | {
223  | 	if (!(mvitals[PM_ARCHON].mvflags & G_GONE))
224  | 		return(PM_ARCHON);
225  | 
226  | 	return(lminion());	/* approximate */
227  | }
228  | 
229  | int
230  | lminion()
231  | {
232  | 	int	tryct;
233  | 	struct	permonst *ptr;
234  | 
235  | 	for (tryct = 0; tryct < 20; tryct++) {
236  | 	    ptr = mkclass(S_ANGEL,0);
237  | 	    if (ptr && !is_lord(ptr))
238  | 		return(monsndx(ptr));
239  | 	}
240  | 
241  | 	return NON_PM;
242  | }
243  | 
244  | int
245  | ndemon(atyp)
246  | aligntyp atyp;
247  | {
248  | 	int	tryct;
249  | 	struct	permonst *ptr;
250  | 
251  | 	for (tryct = 0; tryct < 20; tryct++) {
252  | 	    ptr = mkclass(S_DEMON, 0);
253  | 	    if (ptr && is_ndemon(ptr) &&
254  | 		    (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp)))
255  | 		return(monsndx(ptr));
256  | 	}
257  | 
258  | 	return NON_PM;
259  | }
260  | 
261  | /*minion.c*/