1/*	SCCS Id: @(#)mplayer.c	3.4	1997/02/04	*/
2/*	Copyright (c) Izchak Miller, 1992.			  */
3/* NetHack may be freely redistributed.  See license for details. */
4
5#include "hack.h"
6
7STATIC_DCL const char *NDECL(dev_name);
8STATIC_DCL void FDECL(get_mplname, (struct monst *, char *));
9STATIC_DCL void FDECL(mk_mplayer_armor, (struct monst *, SHORT_P));
10
11/* These are the names of those who
12 * contributed to the development of NetHack 3.2/3.3/3.4.
13 *
14 * Keep in alphabetical order within teams.
15 * Same first name is entered once within each team.
16 */
17static const char *developers[] = {
18	/* devteam */
19	"Dave", "Dean", "Eric", "Izchak", "Janet", "Jessie",
20	"Ken", "Kevin", "Michael", "Mike", "Pat", "Paul", "Steve", "Timo",
21	"Warwick",
22	/* PC team */
23	"Bill", "Eric", "Keizo", "Ken", "Kevin", "Michael", "Mike", "Paul",
24	"Stephen", "Steve", "Timo", "Yitzhak",
25	/* Amiga team */
26	"Andy", "Gregg", "Janne", "Keni", "Mike", "Olaf", "Richard",
27	/* Mac team */
28	"Andy", "Chris", "Dean", "Jon", "Jonathan", "Kevin", "Wang",
29	/* Atari team */
30	"Eric", "Marvin", "Warwick",
31	/* NT team */
32	"Alex", "Dion", "Michael",
33	/* OS/2 team */
34	"Helge", "Ron", "Timo",
35	/* VMS team */
36	"Joshua", "Pat",
37	""};
38
39
40/* return a randomly chosen developer name */
41STATIC_OVL const char *
42dev_name()
43{
44	register int i, m = 0, n = SIZE(developers);
45	register struct monst *mtmp;
46	register boolean match;
47
48	do {
49	    match = FALSE;
50	    i = rn2(n);
51	    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
52		if(!is_mplayer(mtmp->data)) continue;
53		if(!strncmp(developers[i], NAME(mtmp),
54			               strlen(developers[i]))) {
55		    match = TRUE;
56		    break;
57	        }
58	    }
59	    m++;
60	} while (match && m < 100); /* m for insurance */
61
62	if (match) return (const char *)0;
63	return(developers[i]);
64}
65
66STATIC_OVL void
67get_mplname(mtmp, nam)
68register struct monst *mtmp;
69char *nam;
70{
71	boolean fmlkind = is_female(mtmp->data);
72	const char *devnam;
73
74	devnam = dev_name();
75	if (!devnam)
76	    Strcpy(nam, fmlkind ? "Eve" : "Adam");
77	else if (fmlkind && !!strcmp(devnam, "Janet"))
78	    Strcpy(nam, rn2(2) ? "Maud" : "Eve");
79	else Strcpy(nam, devnam);
80
81	if (fmlkind || !strcmp(nam, "Janet"))
82	    mtmp->female = 1;
83	else
84	    mtmp->female = 0;
85	Strcat(nam, " the ");
86	Strcat(nam, rank_of((int)mtmp->m_lev,
87			    monsndx(mtmp->data),
88			    (boolean)mtmp->female));
89}
90
91STATIC_OVL void
92mk_mplayer_armor(mon, typ)
93struct monst *mon;
94short typ;
95{
96	struct obj *obj;
97
98	if (typ == STRANGE_OBJECT) return;
99	obj = mksobj(typ, FALSE, FALSE);
100	if (!rn2(3)) obj->oerodeproof = 1;
101	if (!rn2(3)) curse(obj);
102	if (!rn2(3)) bless(obj);
103	/* Most players who get to the endgame who have cursed equipment
104	 * have it because the wizard or other monsters cursed it, so its
105	 * chances of having plusses is the same as usual....
106	 */
107	obj->spe = rn2(10) ? (rn2(3) ? rn2(5) : rn1(4,4)) : -rnd(3);
108	(void) mpickobj(mon, obj);
109}
110
111struct monst *
112mk_mplayer(ptr, x, y, special)
113register struct permonst *ptr;
114xchar x, y;
115register boolean special;
116{
117	register struct monst *mtmp;
118	char nam[PL_NSIZ];
119
120	if(!is_mplayer(ptr))
121		return((struct monst *)0);
122
123	if(MON_AT(x, y))
124		(void) rloc(m_at(x, y), FALSE); /* insurance */
125
126	if(!In_endgame(&u.uz)) special = FALSE;
127
128	if ((mtmp = makemon(ptr, x, y, NO_MM_FLAGS)) != 0) {
129	    short weapon = rn2(2) ? LONG_SWORD : rnd_class(SPEAR, BULLWHIP);
130	    short armor = rnd_class(GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL);
131	    short cloak = !rn2(8) ? STRANGE_OBJECT :
132	    		rnd_class(OILSKIN_CLOAK, CLOAK_OF_DISPLACEMENT);
133	    short helm = !rn2(8) ? STRANGE_OBJECT :
134	    		rnd_class(ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY);
135	    short shield = !rn2(8) ? STRANGE_OBJECT :
136	    		rnd_class(ELVEN_SHIELD, SHIELD_OF_REFLECTION);
137	    int quan;
138	    struct obj *otmp;
139
140	    mtmp->m_lev = (special ? rn1(16,15) : rnd(16));
141	    mtmp->mhp = mtmp->mhpmax = d((int)mtmp->m_lev,10) +
142					(special ? (30 + rnd(30)) : 30);
143	    if(special) {
144	        get_mplname(mtmp, nam);
145	        mtmp = christen_monst(mtmp, nam);
146		/* that's why they are "stuck" in the endgame :-) */
147		(void)mongets(mtmp, FAKE_AMULET_OF_YENDOR);
148	    }
149	    mtmp->mpeaceful = 0;
150	    set_malign(mtmp); /* peaceful may have changed again */
151
152	    switch(monsndx(ptr)) {
153		case PM_ARCHEOLOGIST:
154		    if (rn2(2)) weapon = BULLWHIP;
155		    break;
156		case PM_BARBARIAN:
157		    if (rn2(2)) {
158		    	weapon = rn2(2) ? TWO_HANDED_SWORD : BATTLE_AXE;
159		    	shield = STRANGE_OBJECT;
160		    }
161		    if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL);
162		    if (helm == HELM_OF_BRILLIANCE) helm = STRANGE_OBJECT;
163		    break;
164		case PM_CAVEMAN:
165		case PM_CAVEWOMAN:
166		    if (rn2(4)) weapon = MACE;
167		    else if (rn2(2)) weapon = CLUB;
168		    if (helm == HELM_OF_BRILLIANCE) helm = STRANGE_OBJECT;
169		    break;
170		case PM_HEALER:
171		    if (rn2(4)) weapon = QUARTERSTAFF;
172		    else if (rn2(2)) weapon = rn2(2) ? UNICORN_HORN : SCALPEL;
173		    if (rn2(4)) helm = rn2(2) ? HELM_OF_BRILLIANCE : HELM_OF_TELEPATHY;
174		    if (rn2(2)) shield = STRANGE_OBJECT;
175		    break;
176		case PM_KNIGHT:
177		    if (rn2(4)) weapon = LONG_SWORD;
178		    if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL);
179		    break;
180		case PM_MONK:
181		    weapon = STRANGE_OBJECT;
182		    armor = STRANGE_OBJECT;
183		    cloak = ROBE;
184		    if (rn2(2)) shield = STRANGE_OBJECT;
185		    break;
186		case PM_PRIEST:
187		case PM_PRIESTESS:
188		    if (rn2(2)) weapon = MACE;
189		    if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL);
190		    if (rn2(4)) cloak = ROBE;
191		    if (rn2(4)) helm = rn2(2) ? HELM_OF_BRILLIANCE : HELM_OF_TELEPATHY;
192		    if (rn2(2)) shield = STRANGE_OBJECT;
193		    break;
194		case PM_RANGER:
195		    if (rn2(2)) weapon = ELVEN_DAGGER;
196		    break;
197		case PM_ROGUE:
198		    if (rn2(2)) weapon = SHORT_SWORD;
199		    break;
200		case PM_SAMURAI:
201		    if (rn2(2)) weapon = KATANA;
202		    break;
203#ifdef TOURIST
204		case PM_TOURIST:
205		    /* Defaults are just fine */
206		    break;
207#endif
208		case PM_VALKYRIE:
209		    if (rn2(2)) weapon = WAR_HAMMER;
210		    if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL);
211		    break;
212		case PM_WIZARD:
213		    if (rn2(4)) weapon = rn2(2) ? QUARTERSTAFF : ATHAME;
214		    if (rn2(2)) {
215		    	armor = rn2(2) ? BLACK_DRAGON_SCALE_MAIL :
216		    			SILVER_DRAGON_SCALE_MAIL;
217		    	cloak = CLOAK_OF_MAGIC_RESISTANCE;
218		    }
219		    if (rn2(4)) helm = HELM_OF_BRILLIANCE;
220		    shield = STRANGE_OBJECT;
221		    break;
222		default: impossible("bad mplayer monster");
223		    weapon = 0;
224		    break;
225	    }
226
227	    if (weapon != STRANGE_OBJECT) {
228		otmp = mksobj(weapon, TRUE, FALSE);
229		otmp->spe = (special ? rn1(5,4) : rn2(4));
230		if (!rn2(3)) otmp->oerodeproof = 1;
231		else if (!rn2(2)) otmp->greased = 1;
232		if (special && rn2(2))
233		    otmp = mk_artifact(otmp, A_NONE);
234		/* mplayers knew better than to overenchant Magicbane */
235		if (otmp->oartifact == ART_MAGICBANE)
236		    otmp->spe = rnd(4);
237		(void) mpickobj(mtmp, otmp);
238	    }
239
240	    if(special) {
241		if (!rn2(10))
242		    (void) mongets(mtmp, rn2(3) ? LUCKSTONE : LOADSTONE);
243		mk_mplayer_armor(mtmp, armor);
244		mk_mplayer_armor(mtmp, cloak);
245		mk_mplayer_armor(mtmp, helm);
246		mk_mplayer_armor(mtmp, shield);
247		if (rn2(8))
248		    mk_mplayer_armor(mtmp, rnd_class(LEATHER_GLOVES,
249					       GAUNTLETS_OF_DEXTERITY));
250		if (rn2(8))
251		    mk_mplayer_armor(mtmp, rnd_class(LOW_BOOTS, LEVITATION_BOOTS));
252		m_dowear(mtmp, TRUE);
253
254		quan = rn2(3) ? rn2(3) : rn2(16);
255		while(quan--)
256		    (void)mongets(mtmp, rnd_class(DILITHIUM_CRYSTAL, JADE));
257		/* To get the gold "right" would mean a player can double his */
258		/* gold supply by killing one mplayer.  Not good. */
259#ifndef GOLDOBJ
260		mtmp->mgold = rn2(1000);
261#else
262		mkmonmoney(mtmp, rn2(1000));
263#endif
264		quan = rn2(10);
265		while(quan--)
266		    (void) mpickobj(mtmp, mkobj(RANDOM_CLASS, FALSE));
267	    }
268	    quan = rnd(3);
269	    while(quan--)
270		(void)mongets(mtmp, rnd_offensive_item(mtmp));
271	    quan = rnd(3);
272	    while(quan--)
273		(void)mongets(mtmp, rnd_defensive_item(mtmp));
274	    quan = rnd(3);
275	    while(quan--)
276		(void)mongets(mtmp, rnd_misc_item(mtmp));
277	}
278
279	return(mtmp);
280}
281
282/* create the indicated number (num) of monster-players,
283 * randomly chosen, and in randomly chosen (free) locations
284 * on the level.  If "special", the size of num should not
285 * be bigger than the number of _non-repeated_ names in the
286 * developers array, otherwise a bunch of Adams and Eves will
287 * fill up the overflow.
288 */
289void
290create_mplayers(num, special)
291register int num;
292boolean special;
293{
294	int pm, x, y;
295	struct monst fakemon;
296
297	while(num) {
298		int tryct = 0;
299
300		/* roll for character class */
301		pm = PM_ARCHEOLOGIST + rn2(PM_WIZARD - PM_ARCHEOLOGIST + 1);
302		fakemon.data = &mons[pm];
303
304		/* roll for an available location */
305		do {
306		    x = rn1(COLNO-4, 2);
307		    y = rnd(ROWNO-2);
308		} while(!goodpos(x, y, &fakemon, 0) && tryct++ <= 50);
309
310		/* if pos not found in 50 tries, don't bother to continue */
311		if(tryct > 50) return;
312
313		(void) mk_mplayer(&mons[pm], (xchar)x, (xchar)y, special);
314		num--;
315	}
316}
317
318void
319mplayer_talk(mtmp)
320register struct monst *mtmp;
321{
322	static const char *same_class_msg[3] = {
323		"I can't win, and neither will you!",
324		"You don't deserve to win!",
325		"Mine should be the honor, not yours!",
326	},		  *other_class_msg[3] = {
327		"The low-life wants to talk, eh?",
328		"Fight, scum!",
329		"Here is what I have to say!",
330	};
331
332	if(mtmp->mpeaceful) return; /* will drop to humanoid talk */
333
334	pline("Talk? -- %s",
335		(mtmp->data == &mons[urole.malenum] ||
336		mtmp->data == &mons[urole.femalenum]) ?
337		same_class_msg[rn2(3)] : other_class_msg[rn2(3)]);
338}
339
340/*mplayer.c*/
341