Source:SLASH'EM 0.0.7E7F2/polyself.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to polyself.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/polyself.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)polyself.c	3.4	2003/01/08	*/
2.    /*	Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /*
6.     * Polymorph self routine.
7.     *
8.     * Note:  the light source handling code assumes that both youmonst.m_id
9.     * and youmonst.mx will always remain 0 when it handles the case of the
10.    * player polymorphed into a light-emitting monster.
11.    */
12.   
13.   #include "hack.h"
14.   
15.   #ifdef OVLB
16.   STATIC_DCL void FDECL(polyman, (const char *,const char *));
17.   STATIC_DCL void NDECL(break_armor);
18.   STATIC_DCL void FDECL(drop_weapon,(int));
19.   STATIC_DCL void NDECL(uunstick);
20.   STATIC_DCL int FDECL(armor_to_dragon,(int));
21.   STATIC_DCL void NDECL(newman);
22.   STATIC_DCL void NDECL(merge_with_armor);
23.   
24.   /*  Not Used 
25.   static void NDECL(special_poly);
26.   */
27.   
28.   /* Assumes u.umonster is set up already */
29.   /* Use u.umonster since we might be restoring and you may be polymorphed */
30.   void
31.   init_uasmon()
32.   {
33.   	int i;
34.   
35.   	upermonst = mons[u.umonster];
36.   
37.   	/* Fix up the flags */
38.   	/* Default flags assume human,  so replace with your race's flags */
39.   
40.   	upermonst.mflags1 &= ~(mons[PM_HUMAN].mflags1);
41.   	upermonst.mflags1 |= (mons[urace.malenum].mflags1);
42.   
43.   	upermonst.mflags2 &= ~(mons[PM_HUMAN].mflags2);
44.   	upermonst.mflags2 |= (mons[urace.malenum].mflags2);
45.   
46.   	upermonst.mflags3 &= ~(mons[PM_HUMAN].mflags3);
47.   	upermonst.mflags3 |= (mons[urace.malenum].mflags3);
48.   	
49.   	/* Fix up the attacks */
50.   	for(i = 0; i < NATTK; i++) {
51.   	    upermonst.mattk[i] = mons[urace.malenum].mattk[i];
52.   	}
53.   	
54.   	set_uasmon();
55.   }
56.   
57.   /* update the youmonst.data structure pointer */
58.   void
59.   set_uasmon()
60.   {
61.   	set_mon_data(&youmonst, ((u.umonnum == u.umonster) ? 
62.   					&upermonst : &mons[u.umonnum]), 0);
63.   	bot_reconfig();
64.   }
65.   
66.   /* make a (new) human out of the player */
67.   STATIC_OVL void
68.   polyman(fmt, arg)
69.   const char *fmt, *arg;
70.   {
71.   	boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow,
72.   		was_mimicking = (youmonst.m_ap_type == M_AP_OBJECT);
73.   	boolean could_pass_walls = Passes_walls;
74.   	boolean was_blind = !!Blind;
75.   
76.   	if (Upolyd) {
77.   		u.acurr = u.macurr;	/* restore old attribs */
78.   		u.amax = u.mamax;
79.   		u.umonnum = u.umonster;
80.   		flags.female = u.mfemale;
81.   	}
82.   
83.   	set_uasmon();
84.   
85.   	u.mh = u.mhmax = 0;
86.   	u.mtimedone = 0;
87.   	skinback(FALSE);
88.   	u.uundetected = 0;
89.   	newsym(u.ux,u.uy);
90.   
91.   	if (sticky) uunstick();
92.   	find_ac();
93.   	if (was_mimicking) {
94.   	    if (multi < 0) unmul("");
95.   	    youmonst.m_ap_type = M_AP_NOTHING;
96.   	}
97.   
98.   	newsym(u.ux,u.uy);
99.   
100.  	
101.  	You(fmt, arg);
102.  	/* check whether player foolishly genocided self while poly'd */
103.  	if ((mvitals[urole.malenum].mvflags & G_GENOD) ||
104.  			(urole.femalenum != NON_PM &&
105.  			(mvitals[urole.femalenum].mvflags & G_GENOD)) ||
106.  			(mvitals[urace.malenum].mvflags & G_GENOD) ||
107.  			(urace.femalenum != NON_PM &&
108.  			(mvitals[urace.femalenum].mvflags & G_GENOD))) {
109.  	    /* intervening activity might have clobbered genocide info */
110.  	    killer = delayed_killer;
111.  	    if (!killer || !strstri(killer, "genocid")) {
112.  		killer_format = KILLED_BY;
113.  		killer = "self-genocide";
114.  	    }
115.  	    done(GENOCIDED);
116.  	}
117.  
118.  	if (u.twoweap && !could_twoweap(youmonst.data))
119.  	    untwoweapon();
120.  
121.  	if (u.utraptype == TT_PIT) {
122.  	    if (could_pass_walls) {	/* player forms cannot pass walls */
123.  		u.utrap = rn1(6,2);
124.  	    }
125.  	}
126.  	if (was_blind && !Blind) {	/* reverting from eyeless */
127.  	    Blinded = 1L;
128.  	    make_blinded(0L, TRUE);	/* remove blindness */
129.  	}
130.  
131.  	if(!Levitation && !u.ustuck &&
132.  	   (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy)))
133.  		spoteffects(TRUE);
134.  
135.  	see_monsters();
136.  }
137.  
138.  void
139.  change_sex()
140.  {
141.  	/* setting u.umonster for caveman/cavewoman or priest/priestess
142.  	   swap unintentionally makes `Upolyd' appear to be true */
143.  	boolean already_polyd = (boolean) Upolyd;
144.  
145.  	/* Some monsters are always of one sex and their sex can't be changed */
146.  	/* succubi/incubi can change, but are handled below */
147.  	/* !already_polyd check necessary because is_male() and is_female()
148.             are true if the player is a priest/priestess */
149.  	if (!already_polyd || (!is_male(youmonst.data) && !is_female(youmonst.data) && !is_neuter(youmonst.data)))
150.  	    flags.female = !flags.female;
151.  	if (already_polyd)	/* poly'd: also change saved sex */
152.  	    u.mfemale = !u.mfemale;
153.  	max_rank_sz();		/* [this appears to be superfluous] */
154.  	if ((already_polyd ? u.mfemale : flags.female) && urole.name.f)
155.  	    Strcpy(pl_character, urole.name.f);
156.  	else
157.  	    Strcpy(pl_character, urole.name.m);
158.  	u.umonster = ((already_polyd ? u.mfemale : flags.female) && urole.femalenum != NON_PM) ?
159.  			urole.femalenum : urole.malenum;
160.  
161.  	if (!already_polyd) {
162.  	    u.umonnum = u.umonster;
163.  	} else if (u.umonnum == PM_SUCCUBUS || u.umonnum == PM_INCUBUS) {
164.  	    flags.female = !flags.female;
165.  	    /* change monster type to match new sex */
166.  	    u.umonnum = (u.umonnum == PM_SUCCUBUS) ? PM_INCUBUS : PM_SUCCUBUS;
167.  	}
168.  	set_uasmon();
169.  }
170.  
171.  STATIC_OVL void
172.  newman()
173.  {
174.  	int tmp, oldlvl;
175.  
176.  	if (Race_if(PM_DOPPELGANGER)) {
177.  	    if (!rn2(10)) change_sex();
178.  	} else {
179.  	tmp = u.uhpmax;
180.  	oldlvl = u.ulevel;
181.  	u.ulevel = u.ulevel + rn1(5, -2);
182.  	if (u.ulevel > 127 || u.ulevel < 1) { /* level went below 0? */
183.  	    u.ulevel = oldlvl; /* restore old level in case they lifesave */
184.  	    goto dead;
185.  	}
186.  	if (u.ulevel > MAXULEV) u.ulevel = MAXULEV;
187.  	/* If your level goes down, your peak level goes down by
188.  	   the same amount so that you can't simply use blessed
189.  	   full healing to undo the decrease.  But if your level
190.  	   goes up, your peak level does *not* undergo the same
191.  	   adjustment; you might end up losing out on the chance
192.  	   to regain some levels previously lost to other causes. */
193.  	if (u.ulevel < oldlvl) u.ulevelmax -= (oldlvl - u.ulevel);
194.  	if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel;
195.  
196.  	if (!rn2(10)) change_sex();
197.  
198.  	adjabil(oldlvl, (int)u.ulevel);
199.  	reset_rndmonst(NON_PM);	/* new monster generation criteria */
200.  
201.  	/* random experience points for the new experience level */
202.  	u.uexp = rndexp(FALSE);
203.  
204.  	/* u.uhpmax * u.ulevel / oldlvl: proportionate hit points to new level
205.  	 * -10 and +10: don't apply proportionate HP to 10 of a starting
206.  	 *   character's hit points (since a starting character's hit points
207.  	 *   are not on the same scale with hit points obtained through level
208.  	 *   gain)
209.  	 * 9 - rn2(19): random change of -9 to +9 hit points
210.  	 */
211.  #ifndef LINT
212.  	u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / oldlvl + 10) +
213.  		(9 - rn2(19));
214.  #endif
215.  
216.  #ifdef LINT
217.  	u.uhp = u.uhp + tmp;
218.  #else
219.  	u.uhp = u.uhp * (long)u.uhpmax/tmp;
220.  #endif
221.  
222.  	tmp = u.uenmax;
223.  #ifndef LINT
224.  	u.uenmax = u.uenmax * (long)u.ulevel / oldlvl + 9 - rn2(19);
225.  #endif
226.  	if (u.uenmax < 0) u.uenmax = 0;
227.  #ifndef LINT
228.  	u.uen = (tmp ? u.uen * (long)u.uenmax / tmp : u.uenmax);
229.  #endif
230.  	}
231.  
232.  	redist_attr();
233.  	u.uhunger = rn1(500,500);
234.  	if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL);
235.  	Sick = 0;
236.  	Stoned = 0;
237.  	delayed_killer = 0;
238.  	if (Race_if(PM_DOPPELGANGER)) {        
239.  		if (u.uhp <= 10) u.uhp = 10;
240.  		if (u.uhpmax <= 10) u.uhpmax = 10;
241.  		if (u.uen <= u.ulevel) u.uen = u.ulevel;
242.  		if (u.uenmax <= u.ulevel) u.uenmax = u.ulevel;
243.  	}
244.  	if (u.uhp <= 0 || u.uhpmax <= 0) {
245.  		if (Polymorph_control) {
246.  		    if (u.uhp <= 0) u.uhp = 1;
247.  		    if (u.uhpmax <= 0) u.uhpmax = 1;
248.  		} else {
249.  dead: /* we come directly here if their experience level went to 0 or less */
250.  		    Your("new form doesn't seem healthy enough to survive.");
251.  		    killer_format = KILLED_BY_AN;
252.  		    killer="unsuccessful polymorph";
253.  		    done(DIED);
254.  		    newuhs(FALSE);
255.  		    return; /* lifesaved */
256.  		}
257.  	}
258.  	newuhs(FALSE);
259.  	polyman("feel like a new %s!",
260.  		(flags.female && urace.individual.f) ? urace.individual.f :
261.  		(urace.individual.m) ? urace.individual.m : urace.noun);
262.  	if (Slimed) {
263.  		Your("body transforms, but there is still slime on you.");
264.  		Slimed = 10L;
265.  	}
266.  	flags.botl = 1;
267.  	vision_full_recalc = 1;
268.  	(void) encumber_msg();
269.  	see_monsters();
270.  }
271.  
272.  void
273.  polyself(forcecontrol)
274.  boolean forcecontrol;     
275.  {
276.  	char buf[BUFSZ];
277.  	int old_light, new_light;
278.  	int mntmp = NON_PM;
279.  	int tries=0;
280.  	boolean draconian = (uarm &&
281.  				uarm->otyp >= GRAY_DRAGON_SCALE_MAIL &&
282.  				uarm->otyp <= YELLOW_DRAGON_SCALES);
283.  	boolean iswere = (u.ulycn >= LOW_PM || is_were(youmonst.data));
284.  	boolean isvamp = (is_vampire(youmonst.data));
285.  	boolean was_floating = (Levitation || Flying);
286.  
287.  	/* [Tom] I made the chance of dying from Con check only possible for
288.  		 really weak people (it was out of 20) */
289.  
290.  	if(!Polymorph_control && !forcecontrol && !draconian && !iswere &&
291.  			!isvamp && !Race_if(PM_DOPPELGANGER)) {
292.  		if (rn2(12) > ACURR(A_CON)) {
293.  		You(shudder_for_moment);
294.  		losehp(rnd(30), "system shock", KILLED_BY_AN);
295.  		exercise(A_CON, FALSE);
296.  		return;
297.  	    }
298.  	}
299.  	old_light = Upolyd ? emits_light(youmonst.data) : 0;
300.  
301.  	if (Polymorph_control || forcecontrol) {
302.  		do {
303.  			getlin("Become what kind of monster? [type the name]",
304.  				buf);
305.  			mntmp = name_to_mon(buf);
306.  			if (mntmp < LOW_PM)
307.  				pline("I've never heard of such monsters.");
308.  			/* Note:  humans are illegal as monsters, but an
309.  			 * illegal monster forces newman(), which is what we
310.  			 * want if they specified a human.... */
311.  			else if (!polyok(&mons[mntmp]) && !your_race(&mons[mntmp]))
312.  				You("cannot polymorph into that.");
313.  			else break;
314.  		} while(++tries < 5);
315.  		if (tries==5) pline(thats_enough_tries);
316.  		/* allow skin merging, even when polymorph is controlled */
317.  		if (draconian &&
318.  		    (mntmp == armor_to_dragon(uarm->otyp) || tries == 5))
319.  		    goto do_merge;
320.  	} else if (Race_if(PM_DOPPELGANGER)) {
321.  		/* Not an experienced Doppelganger yet */
322.  		do {
323.  			/* Slightly different wording */
324.  			getlin("Attempt to become what kind of monster? [type the name]",
325.  				buf);
326.  			mntmp = name_to_mon(buf);
327.  			if (mntmp < LOW_PM)
328.  				pline("I've never heard of such monsters.");
329.  			/* Note:  humans are illegal as monsters, but an
330.  			 * illegal monster forces newman(), which is what we
331.  			 * want if they specified a human.... */
332.  			else if (!polyok(&mons[mntmp]) && !your_race(&mons[mntmp]))
333.  				You("cannot polymorph into that.");
334.  #ifdef EATEN_MEMORY
335.  			else if (!mvitals[mntmp].eaten) {
336.  				You("attempt an unfamiliar polymorph.");
337.  				if ((rn2(5) + u.ulevel) < mons[mntmp].mlevel)
338.  				    mntmp = LOW_PM - 1; /* Didn't work for sure */
339.  				/* Either way, give it a shot */
340.  				break;
341.  			}
342.  #else
343.  			else if (rn2((u.ulevel + 25)) < 20) {
344.  				mntmp = LOW_PM - 1;
345.  				break;
346.  			}
347.  #endif
348.  
349.  			else break;
350.  		} while(++tries < 5);
351.  		if (tries==5) pline(thats_enough_tries);
352.  		/* allow skin merging, even when polymorph is controlled */
353.  		if (draconian &&
354.  		    (mntmp == armor_to_dragon(uarm->otyp) || tries == 5))
355.  		    goto do_merge;
356.  	} else if (draconian || iswere || isvamp) {
357.  		/* special changes that don't require polyok() */
358.  		if (draconian) {
359.  		    do_merge:
360.  			mntmp = armor_to_dragon(uarm->otyp);
361.  
362.  			if (!(mvitals[mntmp].mvflags & G_GENOD)) {
363.  				/* Code that was here is now in merge_with_armor */
364.  				merge_with_armor();
365.  			}
366.  		} else if (iswere) {
367.  			if (is_were(youmonst.data))
368.  				mntmp = PM_HUMAN; /* Illegal; force newman() */
369.  			else
370.  				mntmp = u.ulycn;
371.  		} else if (isvamp) {
372.  			if (u.umonnum != PM_VAMPIRE_BAT)
373.  				mntmp = PM_VAMPIRE_BAT;
374.  			else
375.  				mntmp = PM_HUMAN; /* newman() */
376.  		}
377.  		/* if polymon fails, "you feel" message has been given
378.  		   so don't follow up with another polymon or newman */
379.  		if (mntmp == PM_HUMAN) newman();	/* werecritter */
380.  		else (void) polymon(mntmp);
381.  		goto made_change;    /* maybe not, but this is right anyway */
382.  	}
383.  	if (mntmp < LOW_PM) {
384.  		tries = 0;
385.  		do {
386.  			/* randomly pick an "ordinary" monster */
387.  			mntmp = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
388.  		} while((!polyok(&mons[mntmp]) || is_placeholder(&mons[mntmp]))
389.  				&& tries++ < 200);
390.  	}
391.  
392.  	/* The below polyok() fails either if everything is genocided, or if
393.  	 * we deliberately chose something illegal to force newman().
394.  	 */
395.          /* WAC Doppelgangers go through a 1/20 check rather than 1/5 */
396.          if (!polyok(&mons[mntmp]) ||
397.          		(Race_if(PM_DOPPELGANGER) ? (
398.          			((u.ulevel < mons[mntmp].mlevel)
399.  #ifdef EATEN_MEMORY
400.          			 || !mvitals[mntmp].eaten
401.  #endif
402.          			 ) && !rn2(20)) : 
403.  				   !rn2(5)) || your_race(&mons[mntmp]))
404.  		newman();
405.  	else if(!polymon(mntmp)) return;
406.  
407.  	if (!uarmg) selftouch("No longer petrify-resistant, you");
408.  
409.   made_change:
410.  	new_light = Upolyd ? emits_light(youmonst.data) : 0;
411.  	if (old_light != new_light) {
412.  	    if (old_light)
413.  		del_light_source(LS_MONSTER, (genericptr_t)&youmonst);
414.  	    if (new_light == 1) ++new_light;  /* otherwise it's undetectable */
415.  	    if (new_light)
416.  		new_light_source(u.ux, u.uy, new_light,
417.  				 LS_MONSTER, (genericptr_t)&youmonst);
418.  	}
419.  	if (is_pool(u.ux,u.uy) && was_floating && !(Levitation || Flying) &&
420.  		!breathless(youmonst.data) && !amphibious(youmonst.data) &&
421.  		!Swimming) drown();
422.  }
423.  
424.  /* (try to) make a mntmp monster out of the player */
425.  int
426.  polymon(mntmp)	/* returns 1 if polymorph successful */
427.  int	mntmp;
428.  {
429.  	boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow,
430.  		was_blind = !!Blind, dochange = FALSE;
431.  	boolean could_pass_walls = Passes_walls;
432.  	int mlvl;
433.  
434.  	if (mvitals[mntmp].mvflags & G_GENOD) {	/* allow G_EXTINCT */
435.  		You_feel("rather %s-ish.",mons[mntmp].mname);
436.  		exercise(A_WIS, TRUE);
437.  		return(0);
438.  	}
439.  
440.  	/* STEPHEN WHITE'S NEW CODE */        
441.    
442.  	/* If your an Undead Slayer, you can't become undead! */
443.    
444.  	if (is_undead(&mons[mntmp]) && Role_if(PM_UNDEAD_SLAYER)) {
445.  		if (Polymorph_control) { 
446.  			You("hear a voice boom out: \"How dare you take such a form!\"");
447.  			u.ualign.record -= 5;
448.  #ifdef NOARTIFACTWISH
449.  			u.usacrifice = 0;
450.  #endif
451.  			exercise(A_WIS, FALSE);
452.  		 } else {
453.  			You("start to change into %s, but a voice booms out:", an(mons[mntmp].mname));
454.  			pline("\"No, I will not allow such a change!\"");
455.  		 }
456.  		 return(0);
457.  	}
458.  
459.  	/* KMH, conduct */
460.  	u.uconduct.polyselfs++;
461.  
462.  	if (!Upolyd) {
463.  		/* Human to monster; save human stats */
464.  		u.macurr = u.acurr;
465.  		u.mamax = u.amax;
466.  		u.mfemale = flags.female;
467.  	} else {
468.  		/* Monster to monster; restore human stats, to be
469.  		 * immediately changed to provide stats for the new monster
470.  		 */
471.  		u.acurr = u.macurr;
472.  		u.amax = u.mamax;
473.  		flags.female = u.mfemale;
474.  	}
475.  
476.  	if (youmonst.m_ap_type) {
477.  	    /* stop mimicking immediately */
478.  	    if (multi < 0) unmul("");
479.  	} else if (mons[mntmp].mlet != S_MIMIC) {
480.  	    /* as in polyman() */
481.  	    youmonst.m_ap_type = M_AP_NOTHING;
482.  	}
483.  	if (is_male(&mons[mntmp])) {
484.  		if(flags.female) dochange = TRUE;
485.  	} else if (is_female(&mons[mntmp])) {
486.  		if(!flags.female) dochange = TRUE;
487.  	} else if (!is_neuter(&mons[mntmp]) && mntmp != u.ulycn) {
488.  		if(!rn2(10)) dochange = TRUE;
489.  	}
490.  	if (dochange) {
491.  		flags.female = !flags.female;
492.  		You("%s %s%s!",
493.  		    (u.umonnum != mntmp) ? "turn into a" : "feel like a new",
494.  		    (is_male(&mons[mntmp]) || is_female(&mons[mntmp])) ? "" :
495.  			flags.female ? "female " : "male ",
496.  		    mons[mntmp].mname);
497.  	} else {
498.  		if (u.umonnum != mntmp)
499.  			You("turn into %s!", an(mons[mntmp].mname));
500.  		else
501.  			You_feel("like a new %s!", mons[mntmp].mname);
502.  	}
503.  	if (Stoned && poly_when_stoned(&mons[mntmp])) {
504.  		/* poly_when_stoned already checked stone golem genocide */
505.  		You("turn to stone!");
506.  		mntmp = PM_STONE_GOLEM;
507.  		Stoned = 0;
508.  		delayed_killer = 0;
509.  	}
510.  
511.  	u.mtimedone = rn1(500, 500);
512.  	u.umonnum = mntmp;
513.  	set_uasmon();
514.  
515.  	/* New stats for monster, to last only as long as polymorphed.
516.  	 * Currently only strength gets changed.
517.  	 */
518.  	if(strongmonst(&mons[mntmp])) ABASE(A_STR) = AMAX(A_STR) = STR18(100);
519.  
520.  	if (Stone_resistance && Stoned) { /* parnes@eniac.seas.upenn.edu */
521.  		Stoned = 0;
522.  		delayed_killer = 0;
523.  		You("no longer seem to be petrifying.");
524.  	}
525.  	if (Sick_resistance && Sick) {
526.  		make_sick(0L, (char *) 0, FALSE, SICK_ALL);
527.  		You("no longer feel sick.");
528.  	}
529.  	if (Slimed) {
530.  	    if (flaming(youmonst.data)) {
531.  		pline_The("slime burns away!");
532.  		Slimed = 0L;
533.  		flags.botl = 1;
534.  	    } else if (mntmp == PM_GREEN_SLIME) {
535.  		/* do it silently */
536.  		Slimed = 0L;
537.  		flags.botl = 1;
538.  	    }
539.  	}
540.  	if (nohands(youmonst.data)) Glib = 0;
541.  
542.  	/*
543.  	mlvl = adj_lev(&mons[mntmp]);
544.  	 * We can't do the above, since there's no such thing as an
545.  	 * "experience level of you as a monster" for a polymorphed character.
546.  	 */
547.  	mlvl = ((mntmp == u.ulycn) ? u.ulevel : (int)mons[mntmp].mlevel);
548.  	if (youmonst.data->mlet == S_DRAGON && mntmp >= PM_GRAY_DRAGON) {
549.  		u.mhmax = In_endgame(&u.uz) ? (8*mlvl) : (4*mlvl + d(mlvl,4));
550.  	} else if (is_golem(youmonst.data)) {
551.  		u.mhmax = golemhp(mntmp);
552.  	} else {
553.  		if (!mlvl) u.mhmax = rnd(4);
554.  		else u.mhmax = d(mlvl, 8);
555.  		if (is_home_elemental(&mons[mntmp])) u.mhmax *= 3;
556.  	}
557.  	u.mh = u.mhmax;
558.  
559.  	if (u.ulevel < mlvl) {
560.  	/* Low level characters can't become high level monsters for long */
561.  #ifdef DUMB
562.  		/* DRS/NS 2.2.6 messes up -- Peter Kendell */
563.  		int mtd = u.mtimedone, ulv = u.ulevel;
564.  
565.  		u.mtimedone = mtd * ulv / mlvl;
566.  #else
567.  		u.mtimedone = u.mtimedone * u.ulevel / mlvl;
568.  #endif
569.  	}
570.  
571.  #ifdef EATEN_MEMORY
572.  	/* WAC Doppelgangers can stay much longer in a form they know well */
573.  	if (Race_if(PM_DOPPELGANGER) && mvitals[mntmp].eaten) {
574.  		u.mtimedone *= 2;
575.  		u.mtimedone += mvitals[mntmp].eaten;
576.  	}
577.  #endif
578.  
579.  	if (uskin && mntmp != armor_to_dragon(uskin->otyp))
580.  		skinback(FALSE);
581.  	break_armor();
582.  	drop_weapon(1);
583.  	if (hides_under(youmonst.data))
584.  		u.uundetected = OBJ_AT(u.ux, u.uy);
585.  	else if (youmonst.data->mlet == S_EEL)
586.  		u.uundetected = is_pool(u.ux, u.uy);
587.  	else
588.  		u.uundetected = 0;
589.  
590.  	if (u.utraptype == TT_PIT) {
591.  	    if (could_pass_walls && !Passes_walls) {
592.  		u.utrap = rn1(6,2);
593.  	    } else if (!could_pass_walls && Passes_walls) {
594.  		u.utrap = 0;
595.  	    }
596.  	}
597.  	if (was_blind && !Blind) {	/* previous form was eyeless */
598.  	    Blinded = 1L;
599.  	    make_blinded(0L, TRUE);	/* remove blindness */
600.  	}
601.  	newsym(u.ux,u.uy);		/* Change symbol */
602.  
603.  	if (!sticky && !u.uswallow && u.ustuck && sticks(youmonst.data)) setustuck(0);
604.  	else if (sticky && !sticks(youmonst.data)) uunstick();
605.  #ifdef STEED
606.  	if (u.usteed) {
607.  	    if (touch_petrifies(u.usteed->data) &&
608.  	    		!Stone_resistance && rnl(3)) {
609.  	    	char buf[BUFSZ];
610.  
611.  	    	pline("No longer petrifying-resistant, you touch %s.",
612.  	    			mon_nam(u.usteed));
613.  	    	Sprintf(buf, "riding %s", an(u.usteed->data->mname));
614.  	    	instapetrify(buf);
615.   	    }
616.  	    if (!can_ride(u.usteed)) dismount_steed(DISMOUNT_POLY);
617.  	}
618.  #endif
619.  
620.  	if (flags.verbose) {
621.  	    static const char use_thec[] = "Use the command #%s to %s.";
622.  	    static const char monsterc[] = "monster";
623.  	    if (can_breathe(youmonst.data))
624.  		pline(use_thec,monsterc,"use your breath weapon");
625.  	    if (attacktype(youmonst.data, AT_SPIT))
626.  		pline(use_thec,monsterc,"spit venom");
627.  	    if (youmonst.data->mlet == S_NYMPH)
628.  		pline(use_thec,monsterc,"remove an iron ball");
629.  	    if (attacktype(youmonst.data, AT_GAZE))
630.  		pline(use_thec,monsterc,"gaze at monsters");
631.  	    if (is_hider(youmonst.data))
632.  		pline(use_thec,monsterc,"hide");
633.  	    if (is_were(youmonst.data))
634.  		pline(use_thec,monsterc,"summon help");
635.  	    if (webmaker(youmonst.data))
636.  		pline(use_thec,monsterc,"spin a web");
637.  	    if (u.umonnum == PM_GREMLIN)
638.  		pline(use_thec,monsterc,"multiply in a fountain");
639.  	    if (is_unicorn(youmonst.data))
640.  		pline(use_thec,monsterc,"use your horn");
641.  	    if (is_mind_flayer(youmonst.data))
642.  		pline(use_thec,monsterc,"emit a mental blast");
643.  	    if (youmonst.data->msound == MS_SHRIEK) /* worthless, actually */
644.  		pline(use_thec,monsterc,"shriek");
645.  	    if (lays_eggs(youmonst.data) && flags.female)
646.  		pline(use_thec,"sit","lay an egg");
647.  	}
648.  	/* you now know what an egg of your type looks like */
649.  	if (lays_eggs(youmonst.data)) {
650.  	    /* make queen bees recognize killer bee eggs */
651.  	    learn_egg_type(egg_type_from_parent(u.umonnum, TRUE));
652.  	}
653.  	find_ac();
654.  	if((!Levitation && !u.ustuck && !Flying &&
655.  	    (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy))) ||
656.  	   (Underwater && !Swimming))
657.  	    spoteffects(TRUE);
658.  	if (Passes_walls && u.utrap && u.utraptype == TT_INFLOOR) {
659.  	    u.utrap = 0;
660.  	    pline_The("rock seems to no longer trap you.");
661.  	} else if (likes_lava(youmonst.data) && u.utrap && u.utraptype == TT_LAVA) {
662.  	    u.utrap = 0;
663.  	    pline_The("lava now feels soothing.");
664.  	}
665.  	if (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) {
666.  	    if (Punished) {
667.  		You("slip out of the iron chain.");
668.  		unpunish();
669.  	    }
670.  	}
671.  	if (u.utrap && (u.utraptype == TT_WEB || u.utraptype == TT_BEARTRAP) &&
672.  		(amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data) ||
673.  		  (youmonst.data->msize <= MZ_SMALL && u.utraptype == TT_BEARTRAP))) {
674.  	    You("are no longer stuck in the %s.",
675.  		    u.utraptype == TT_WEB ? "web" : "bear trap");
676.  	    /* probably should burn webs too if PM_FIRE_ELEMENTAL */
677.  	    u.utrap = 0;
678.  	}
679.  	if (webmaker(youmonst.data) && u.utrap && u.utraptype == TT_WEB) {
680.  	    You("orient yourself on the web.");
681.  	    u.utrap = 0;
682.  	}
683.  	flags.botl = 1;
684.  	vision_full_recalc = 1;
685.  	see_monsters();
686.  	exercise(A_CON, FALSE);
687.  	exercise(A_WIS, TRUE);
688.  	(void) encumber_msg();
689.  	return(1);
690.  }
691.  
692.  STATIC_OVL void
693.  break_armor()
694.  {
695.      register struct obj *otmp;
696.      boolean controlled_change = (Race_if(PM_DOPPELGANGER) || 
697.      		(Race_if(PM_HUMAN_WEREWOLF) && u.umonnum == PM_WEREWOLF));
698.  
699.      if (breakarm(youmonst.data)) {
700.  	if ((otmp = uarm) != 0) {
701.  	    if(otmp->oartifact) {
702.  		if (donning(otmp)) cancel_don();
703.  		Your("armor falls off!");
704.  		(void) Armor_gone();
705.  		dropx(otmp); /*WAC Drop instead of destroy*/
706.  	    } else if (controlled_change && !otmp->cursed) {
707.  		if (donning(otmp)) cancel_don();
708.  		You("quickly remove your armor as you start to change.");
709.  		(void) Armor_gone();
710.  		dropx(otmp); /*WAC Drop instead of destroy*/
711.  	    } else {
712.  		if (donning(otmp)) cancel_don();
713.  		You("break out of your armor!");
714.  		exercise(A_STR, FALSE);
715.  		(void) Armor_gone();
716.  		useup(otmp);
717.  	}
718.  	}
719.  	if ((otmp = uarmc) != 0) {
720.  	    if(otmp->oartifact) {
721.  		Your("%s falls off!", cloak_simple_name(otmp));
722.  		(void) Cloak_off();
723.  		dropx(otmp);
724.  	    } else if (controlled_change && !otmp->cursed) {
725.  		You("remove your %s before you transform.",
726.  			cloak_simple_name(otmp));
727.  		(void) Cloak_off();
728.  		dropx(otmp);
729.  	    } else {
730.  		Your("%s tears apart!", cloak_simple_name(otmp));
731.  		(void) Cloak_off();
732.  		useup(otmp);
733.  	    }
734.  	}
735.  #ifdef TOURIST
736.  	if ((otmp = uarmu) != 0) {
737.  	    if (controlled_change && !otmp->cursed && !uskin) {
738.  		You("take off your shirt just before it starts to rip.");
739.  		setworn((struct obj *)0, otmp->owornmask & W_ARMU);
740.  		dropx(otmp);
741.  	    } else {                
742.  		Your("shirt rips to shreds!");
743.  		useup(uarmu);
744.  	    }
745.  	}
746.  #endif
747.      } else if (sliparm(youmonst.data)) {
748.  	if (((otmp = uarm) != 0) && (racial_exception(&youmonst, otmp) < 1)) {
749.  		if (donning(otmp)) cancel_don();
750.  		Your("armor falls around you!");
751.  		(void) Armor_gone();
752.  		dropx(otmp);
753.  	}
754.  	if ((otmp = uarmc) != 0) {
755.  		if (is_whirly(youmonst.data))
756.  			Your("%s falls, unsupported!", cloak_simple_name(otmp));
757.  		else You("shrink out of your %s!", cloak_simple_name(otmp));
758.  		(void) Cloak_off();
759.  		dropx(otmp);
760.  	}
761.  #ifdef TOURIST
762.  	if ((otmp = uarmu) != 0) {
763.  		if (is_whirly(youmonst.data))
764.  			You("seep right through your shirt!");
765.  		else You("become much too small for your shirt!");
766.  		setworn((struct obj *)0, otmp->owornmask & W_ARMU);
767.  		dropx(otmp);
768.  	}
769.  #endif
770.      }
771.      if (has_horns(youmonst.data)) {
772.  	if ((otmp = uarmh) != 0) {
773.  	    if (is_flimsy(otmp) && !donning(otmp)) {
774.  		char hornbuf[BUFSZ], yourbuf[BUFSZ];
775.  
776.  		/* Future possiblities: This could damage/destroy helmet */
777.  		Sprintf(hornbuf, "horn%s", plur(num_horns(youmonst.data)));
778.  		Your("%s %s through %s %s.", hornbuf, vtense(hornbuf, "pierce"),
779.  		     shk_your(yourbuf, otmp), xname(otmp));
780.  	    } else {
781.  		if (donning(otmp)) cancel_don();
782.  		Your("helmet falls to the %s!", surface(u.ux, u.uy));
783.  		(void) Helmet_off();
784.  		dropx(otmp);
785.  	    }
786.  	}
787.      }
788.      if (nohands(youmonst.data) || verysmall(youmonst.data)) {
789.  	if ((otmp = uarmg) != 0) {
790.  	    if (donning(otmp)) cancel_don();
791.  	    /* Drop weapon along with gloves */
792.  	    You("drop your gloves%s!", uwep ? " and weapon" : "");
793.  	    drop_weapon(0);
794.  	    (void) Gloves_off();
795.  	    dropx(otmp);
796.  	}
797.  	if ((otmp = uarms) != 0) {
798.  	    You("can no longer hold your shield!");
799.  	    (void) Shield_off();
800.  	    dropx(otmp);
801.  	}
802.  	if ((otmp = uarmh) != 0) {
803.  	    if (donning(otmp)) cancel_don();
804.  	    Your("helmet falls to the %s!", surface(u.ux, u.uy));
805.  	    (void) Helmet_off();
806.  	    dropx(otmp);
807.  	}
808.      }
809.      if (nohands(youmonst.data) || verysmall(youmonst.data) ||
810.  		slithy(youmonst.data) || youmonst.data->mlet == S_CENTAUR) {
811.  	if ((otmp = uarmf) != 0) {
812.  	    if (donning(otmp)) cancel_don();
813.  	    if (is_whirly(youmonst.data))
814.  		Your("boots fall away!");
815.  	    else Your("boots %s off your feet!",
816.  			verysmall(youmonst.data) ? "slide" : "are pushed");
817.  	    (void) Boots_off();
818.  	    dropx(otmp);
819.  	}
820.      }
821.  }
822.  
823.  STATIC_OVL void
824.  drop_weapon(alone)
825.  int alone;
826.  {
827.      struct obj *otmp;
828.      struct obj *otmp2;
829.  
830.      if ((otmp = uwep) != 0) {
831.  	/* !alone check below is currently superfluous but in the
832.  	 * future it might not be so if there are monsters which cannot
833.  	 * wear gloves but can wield weapons
834.  	 */
835.  	if (!alone || cantwield(youmonst.data)) {
836.  	    struct obj *wep = uwep;
837.  
838.  	    if (alone) You("find you must drop your weapon%s!",
839.  			   	u.twoweap ? "s" : "");
840.  	    otmp2 = u.twoweap ? uswapwep : 0;
841.  	    uwepgone();
842.  	    if (!wep->cursed || wep->otyp != LOADSTONE)
843.  		dropx(otmp);
844.  	    if (otmp2 != 0) {
845.  		uswapwepgone();
846.  		if (!otmp2->cursed || otmp2->otyp != LOADSTONE)
847.  		    dropx(otmp2);
848.  	    }
849.  	    untwoweapon();
850.  	} else if (!could_twoweap(youmonst.data)) {
851.  	    untwoweapon();
852.  	}
853.      } else if (cantwield(youmonst.data))
854.  	untwoweapon();
855.  }
856.  
857.  void
858.  rehumanize()
859.  {
860.  	boolean forced = (u.mh < 1);
861.  	
862.  	/* KMH, balance patch -- you can't revert back while unchanging */
863.  	if (Unchanging && forced) {
864.  		killer_format = NO_KILLER_PREFIX;
865.  		killer = "killed while stuck in creature form";
866.  		done(DIED);
867.  	}
868.  
869.  	if (emits_light(youmonst.data))
870.  	    del_light_source(LS_MONSTER, (genericptr_t)&youmonst);
871.  	polyman("return to %s form!", urace.adj);
872.  
873.  	if (u.uhp < 1) {
874.  	    char kbuf[256];
875.  
876.  	    Sprintf(kbuf, "reverting to unhealthy %s form", urace.adj);
877.  	    killer_format = KILLED_BY;
878.  	    killer = kbuf;
879.  	    done(DIED);
880.  	}
881.  	
882.  	if (forced || (!Race_if(PM_DOPPELGANGER) && (rn2(20) > ACURR(A_CON)))) { 
883.  	/* Exhaustion for "forced" rehumaization & must pass con chack for 
884.      	 * non-doppelgangers 
885.      	 * Don't penalize doppelgangers/polymorph running out */
886.      	 
887.     	/* WAC Polymorph Exhaustion 1/2 HP to prevent abuse */
888.  	    u.uhp = (u.uhp/2) + 1;
889.  	}
890.  
891.  	if (!uarmg) selftouch("No longer petrify-resistant, you");
892.  	nomul(0);
893.  
894.  	flags.botl = 1;
895.  	vision_full_recalc = 1;
896.  	(void) encumber_msg();
897.  }
898.  
899.  
900.  /* WAC -- MUHAHAHAAHA - Gaze attacks! 
901.   * Note - you can only gaze at one monster at a time, to keep this 
902.   * from getting out of hand ;B  Also costs 20 energy.
903.   */
904.  int
905.  dogaze()
906.  {
907.  	coord cc;
908.  	struct monst *mtmp;
909.  
910.  	if (Blind) {
911.  		You("can't see a thing!");
912.  		return(0);
913.  	}
914.  	if (u.uen < 20) {
915.  		You("lack the energy to use your special gaze!");
916.  		return(0);
917.  	}
918.  	pline("Where do you wish to look?");
919.  	cc.x = u.ux;
920.  	cc.y = u.uy;
921.  	getpos(&cc, TRUE, "the spot to look");
922.  
923.  	if (cc.x == -10) return (0); /* user pressed esc */
924.  
925.  	mtmp = m_at(cc.x, cc.y);
926.  
927.  	if (!mtmp || !canseemon(mtmp)) {
928.  		You("don't see a monster there!");
929.  		return (0);
930.  	}
931.  
932.  
933.  	if ((flags.safe_dog && !Confusion && !Hallucination
934.  		  && mtmp->mtame) || (flags.confirm && mtmp->mpeaceful 
935.  		  && !Confusion && !Hallucination)) {
936.  		  	char qbuf[QBUFSZ];
937.  		  	
938.  			Sprintf(qbuf, "Really gaze at %s?", mon_nam(mtmp));
939.  			if (yn(qbuf) != 'y') return (0);
940.  			if (mtmp->mpeaceful) setmangry(mtmp);
941.  	}
942.  
943.  	u.uen -= 20;
944.  
945.  	You("gaze at %s...", mon_nam(mtmp));
946.  
947.  	if ((mtmp->data==&mons[PM_MEDUSA]) && !mtmp->mcan) {
948.  		pline("Gazing at the awake Medusa is not a very good idea.");
949.  		/* as if gazing at a sleeping anything is fruitful... */
950.  		You("turn to stone...");
951.  		killer_format = KILLED_BY;
952.  		killer = "deliberately gazing at Medusa's hideous countenance";
953.  		done(STONING);
954.  	} else if (!mtmp->mcansee || mtmp->msleeping) {
955.  	    pline("But nothing happens.");
956.  	    return (1);
957.  	} else if (Invis && !perceives(mtmp->data)) {
958.  	    pline("%s seems not to notice your gaze.", Monnam(mtmp));
959.  	    return (1);
960.  	} else {
961.  	    register struct attack *mattk;
962.  	    register int i;
963.  
964.  	    for(i = 0; i < NATTK; i++) {
965.  		mattk = &(youmonst.data->mattk[i]);
966.  		if (mattk->aatyp == AT_GAZE) {
967.  		    damageum(mtmp, mattk);
968.  		    break;
969.  		}
970.  	    }
971.  	}
972.  	return(1);
973.  }
974.  
975.  int
976.  dobreathe()
977.  {
978.  	struct attack *mattk;
979.  	int energy = 0;
980.  
981.  	if (Strangled) {
982.  	    You_cant("breathe.  Sorry.");
983.  	    return(0);
984.  	}
985.  
986.  	/* WAC -- no more belching.  Use up energy instead */
987.  	if (Race_if(PM_DOPPELGANGER)
988.  		|| (Role_if(PM_FLAME_MAGE) && u.umonnum == PM_RED_DRAGON)
989.  		|| (Role_if(PM_ICE_MAGE) && u.umonnum == PM_WHITE_DRAGON))
990.  	    energy = 10;
991.  	else
992.  	    energy = 15;
993.  
994.  	if (u.uen < energy) {
995.  	    You("don't have enough energy to breathe!");
996.  	    return(0);
997.  	}
998.  
999.  	if (!getdir((char *)0)) return(0);
1000. 
1001. 	u.uen -= energy;
1002. 	flags.botl = 1;
1003. 
1004. 	mattk = attacktype_fordmg(youmonst.data, AT_BREA, AD_ANY);
1005. 	if (!mattk)
1006. 	    impossible("bad breath attack?");   /* mouthwash needed... */
1007. 	else {
1008. 	    /* Extra handling for AD_RBRE - player might poly into a crystal
1009. 	     * golem. */
1010. 	    uchar adtyp;
1011. 	    adtyp = mattk->adtyp == AD_RBRE ? rnd(AD_ACID) : mattk->adtyp;
1012. 	    buzz((int) (20 + adtyp - 1), (int)mattk->damn,
1013. 		u.ux, u.uy, u.dx, u.dy);
1014. 	}
1015. 	return(1);
1016. }
1017. 
1018. int
1019. dospit()
1020. {
1021. 	struct obj *otmp;
1022. 	struct attack *mattk;
1023. 
1024. 	if (!getdir((char *)0)) return(0);
1025. 	mattk = attacktype_fordmg(youmonst.data, AT_SPIT, AD_ANY);
1026. 	if (!mattk)
1027. 	    impossible("bad spit attack?");
1028. 	else {
1029. 	    switch (mattk->adtyp) {
1030. 		case AD_BLND:
1031. 		case AD_DRST:
1032. 		    otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
1033. 		    break;
1034. 		default:
1035. 		    impossible("bad attack type in do_spit");
1036. 		    /* fall through */
1037. 		case AD_ACID:
1038. 		    otmp = mksobj(ACID_VENOM, TRUE, FALSE);
1039. 		    break;
1040. 	    }
1041. 	    otmp->spe = 1; /* to indicate it's yours */
1042. 	    throwit(otmp, 0L, FALSE, 0);
1043. 	}
1044. 	return(1);
1045. }
1046. 
1047. int
1048. doremove()
1049. {
1050. 	if (!Punished) {
1051. 		You("are not chained to anything!");
1052. 		return(0);
1053. 	}
1054. 	unpunish();
1055. 	return(1);
1056. }
1057. 
1058. int
1059. dospinweb()
1060. {
1061. 	register struct trap *ttmp = t_at(u.ux,u.uy);
1062. 
1063. 	if (Levitation || Is_airlevel(&u.uz)
1064. 	    || Underwater || Is_waterlevel(&u.uz)) {
1065. 		You("must be on the ground to spin a web.");
1066. 		return(0);
1067. 	}
1068. 	if (u.uswallow) {
1069. 		You("release web fluid inside %s.", mon_nam(u.ustuck));
1070. 		if (is_animal(u.ustuck->data)) {
1071. 			expels(u.ustuck, u.ustuck->data, TRUE);
1072. 			return(0);
1073. 		}
1074. 		if (is_whirly(u.ustuck->data)) {
1075. 			int i;
1076. 
1077. 			for (i = 0; i < NATTK; i++)
1078. 				if (u.ustuck->data->mattk[i].aatyp == AT_ENGL)
1079. 					break;
1080. 			if (i == NATTK)
1081. 			       impossible("Swallower has no engulfing attack?");
1082. 			else {
1083. 				char sweep[30];
1084. 
1085. 				sweep[0] = '\0';
1086. 				switch(u.ustuck->data->mattk[i].adtyp) {
1087. 					case AD_FIRE:
1088. 						Strcpy(sweep, "ignites and ");
1089. 						break;
1090. 					case AD_ELEC:
1091. 						Strcpy(sweep, "fries and ");
1092. 						break;
1093. 					case AD_COLD:
1094. 						Strcpy(sweep,
1095. 						      "freezes, shatters and ");
1096. 						break;
1097. 				}
1098. 				pline_The("web %sis swept away!", sweep);
1099. 			}
1100. 			return(0);
1101. 		}		     /* default: a nasty jelly-like creature */
1102. 		pline_The("web dissolves into %s.", mon_nam(u.ustuck));
1103. 		return(0);
1104. 	}
1105. 	if (u.utrap) {
1106. 		You("cannot spin webs while stuck in a trap.");
1107. 		return(0);
1108. 	}
1109. 	exercise(A_DEX, TRUE);
1110. 	if (ttmp) switch (ttmp->ttyp) {
1111. 		case PIT:
1112. 		case SPIKED_PIT: You("spin a web, covering up the pit.");
1113. 			deltrap(ttmp);
1114. 			bury_objs(u.ux, u.uy);
1115. 			newsym(u.ux, u.uy);
1116. 			return(1);
1117. 		case SQKY_BOARD: pline_The("squeaky board is muffled.");
1118. 			deltrap(ttmp);
1119. 			newsym(u.ux, u.uy);
1120. 			return(1);
1121. 		case TELEP_TRAP:
1122. 		case LEVEL_TELEP:
1123. 		case MAGIC_PORTAL:
1124. 			Your("webbing vanishes!");
1125. 			return(0);
1126. 		case WEB: You("make the web thicker.");
1127. 			return(1);
1128. 		case HOLE:
1129. 		case TRAPDOOR:
1130. 			You("web over the %s.",
1131. 			    (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole");
1132. 			deltrap(ttmp);
1133. 			newsym(u.ux, u.uy);
1134. 			return 1;
1135. 		case ROLLING_BOULDER_TRAP:
1136. 			You("spin a web, jamming the trigger.");
1137. 			deltrap(ttmp);
1138. 			newsym(u.ux, u.uy);
1139. 			return(1);
1140. 		case ARROW_TRAP:
1141. 		case DART_TRAP:
1142. 		case BEAR_TRAP:
1143. 		case ROCKTRAP:
1144. 		case FIRE_TRAP:
1145. 		case LANDMINE:
1146. 		case SLP_GAS_TRAP:
1147. 		case RUST_TRAP:
1148. 		case MAGIC_TRAP:
1149. 		case ANTI_MAGIC:
1150. 		case POLY_TRAP:
1151. 			You("have triggered a trap!");
1152. 			dotrap(ttmp, 0);
1153. 			return(1);
1154. 		default:
1155. 			impossible("Webbing over trap type %d?", ttmp->ttyp);
1156. 			return(0);
1157. 		}
1158. 	else if (On_stairs(u.ux, u.uy)) {
1159. 	    /* cop out: don't let them hide the stairs */
1160. 	    Your("web fails to impede access to the %s.",
1161. 		 (levl[u.ux][u.uy].typ == STAIRS) ? "stairs" : "ladder");
1162. 	    return(1);
1163. 		 
1164. 	}
1165. 	ttmp = maketrap(u.ux, u.uy, WEB);
1166. 	if (ttmp) {
1167. 		ttmp->tseen = 1;
1168. 		ttmp->madeby_u = 1;
1169. 	}
1170. 	newsym(u.ux, u.uy);
1171. 	return(1);
1172. }
1173. 
1174. int
1175. dosummon()
1176. {
1177. 	int placeholder;
1178. 	if (u.uen < 10) {
1179. 	    You("lack the energy to send forth a call for help!");
1180. 	    return(0);
1181. 	}
1182. 	u.uen -= 10;
1183. 	flags.botl = 1;
1184. 
1185. 	You("call upon your brethren for help!");
1186. 	exercise(A_WIS, TRUE);
1187. 	if (!were_summon(youmonst.data, TRUE, &placeholder, (char *)0))
1188. 		pline("But none arrive.");
1189. 	return(1);
1190. }
1191. 
1192. 
1193. #if 0
1194. /* WAC supplanted by dogaze (). */
1195. int
1196. dogaze()
1197. {
1198. 	register struct monst *mtmp;
1199. 	int looked = 0;
1200. 	char qbuf[QBUFSZ];
1201. 	int i;
1202. 	uchar adtyp = 0;
1203. 
1204. 	for (i = 0; i < NATTK; i++) {
1205. 	    if(youmonst.data->mattk[i].aatyp == AT_GAZE) {
1206. 		adtyp = youmonst.data->mattk[i].adtyp;
1207. 		break;
1208. 	    }
1209. 	}
1210. 	if (adtyp != AD_CONF && adtyp != AD_FIRE) {
1211. 	    impossible("gaze attack %d?", adtyp);
1212. 	    return 0;
1213. 	}
1214. 
1215. 
1216. 	if (Blind) {
1217. 	    You_cant("see anything to gaze at.");
1218. 	    return 0;
1219. 	}
1220. 	if (u.uen < 15) {
1221. 	    You("lack the energy to use your special gaze!");
1222. 	    return(0);
1223. 	}
1224. 	u.uen -= 15;
1225. 	flags.botl = 1;
1226. 
1227. 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1228. 	    if (DEADMONSTER(mtmp)) continue;
1229. 	    if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
1230. 		looked++;
1231. 		if (Invis && !perceives(mtmp->data))
1232. 		    pline("%s seems not to notice your gaze.", Monnam(mtmp));
1233. 		else if (mtmp->minvis && !See_invisible)
1234. 		    You_cant("see where to gaze at %s.", Monnam(mtmp));
1235. 		else if (mtmp->m_ap_type == M_AP_FURNITURE
1236. 			|| mtmp->m_ap_type == M_AP_OBJECT) {
1237. 		    looked--;
1238. 		    continue;
1239. 		} else if (flags.safe_dog && !Confusion && !Hallucination
1240. 		  && mtmp->mtame) {
1241. 		    You("avoid gazing at %s.", y_monnam(mtmp));
1242. 		} else {
1243. 		    if (flags.confirm && mtmp->mpeaceful && !Confusion
1244. 							&& !Hallucination) {
1245. 			Sprintf(qbuf, "Really %s %s?",
1246. 			    (adtyp == AD_CONF) ? "confuse" : "attack",
1247. 			    mon_nam(mtmp));
1248. 			if (yn(qbuf) != 'y') continue;
1249. 			setmangry(mtmp);
1250. 		    }
1251. 		    if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping ||
1252. 				    !mtmp->mcansee || !haseyes(mtmp->data)) {
1253. 			looked--;
1254. 			continue;
1255. 		    }
1256. 		    /* No reflection check for consistency with when a monster
1257. 		     * gazes at *you*--only medusa gaze gets reflected then.
1258. 		     */
1259. 		    if (adtyp == AD_CONF) {
1260. 			if (!mtmp->mconf)
1261. 			    Your("gaze confuses %s!", mon_nam(mtmp));
1262. 			else
1263. 			    pline("%s is getting more and more confused.",
1264. 							Monnam(mtmp));
1265. 			mtmp->mconf = 1;
1266. 		    } else if (adtyp == AD_FIRE) {
1267. 			int dmg = d(2,6);
1268. 			You("attack %s with a fiery gaze!", mon_nam(mtmp));
1269. 			if (resists_fire(mtmp)) {
1270. 			    pline_The("fire doesn't burn %s!", mon_nam(mtmp));
1271. 			    dmg = 0;
1272. 			}
1273. 			if((int) u.ulevel > rn2(20))
1274. 			    (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
1275. 			if((int) u.ulevel > rn2(20))
1276. 			    (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
1277. 			if((int) u.ulevel > rn2(25))
1278. 			    (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
1279. 			if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg;
1280. 			if (mtmp->mhp <= 0) killed(mtmp);
1281. 		    }
1282. 		    /* For consistency with passive() in uhitm.c, this only
1283. 		     * affects you if the monster is still alive.
1284. 		     */
1285. 		    if (!DEADMONSTER(mtmp) &&
1286. 			  (mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
1287. 			if (!Free_action) {
1288. 			    You("are frozen by %s gaze!",
1289. 					     s_suffix(mon_nam(mtmp)));
1290. 			    nomul((u.ulevel > 6 || rn2(4)) ?
1291. 				    -d((int)mtmp->m_lev+1,
1292. 					    (int)mtmp->data->mattk[0].damd)
1293. 				    : -200);
1294. 			    return 1;
1295. 			} else
1296. 			    You("stiffen momentarily under %s gaze.",
1297. 				    s_suffix(mon_nam(mtmp)));
1298. 		    }
1299. 		    /* Technically this one shouldn't affect you at all because
1300. 		     * the Medusa gaze is an active monster attack that only
1301. 		     * works on the monster's turn, but for it to *not* have an
1302. 		     * effect would be too weird.
1303. 		     */
1304. 		    if (!DEADMONSTER(mtmp) &&
1305. 			    (mtmp->data==&mons[PM_MEDUSA]) && !mtmp->mcan) {
1306. 			pline(
1307. 			 "Gazing at the awake %s is not a very good idea.",
1308. 			    l_monnam(mtmp));
1309. 			/* as if gazing at a sleeping anything is fruitful... */
1310. 			You("turn to stone...");
1311. 			killer_format = KILLED_BY;
1312. 			killer = "deliberately meeting Medusa's gaze";
1313. 			done(STONING);
1314. 		    }
1315. 		}
1316. 	    }
1317. 	}
1318. 	if (!looked) You("gaze at no place in particular.");
1319. 	return 1;
1320. }
1321. #endif
1322. 
1323. 
1324. int
1325. dohide()
1326. {
1327. 	boolean ismimic = youmonst.data->mlet == S_MIMIC;
1328. 
1329. 	if (u.uundetected || (ismimic && youmonst.m_ap_type != M_AP_NOTHING)) {
1330. 		You("are already hiding.");
1331. 		return(0);
1332. 	}
1333. 	if (ismimic) {
1334. 		/* should bring up a dialog "what would you like to imitate?" */
1335. 		youmonst.m_ap_type = M_AP_OBJECT;
1336. 		youmonst.mappearance = STRANGE_OBJECT;
1337. 	} else
1338. 		u.uundetected = 1;
1339. 	newsym(u.ux,u.uy);
1340. 	return(1);
1341. }
1342. 
1343. int
1344. domindblast()
1345. {
1346. 	struct monst *mtmp, *nmon;
1347. 
1348. 	if (u.uen < 10) {
1349. 	    You("concentrate but lack the energy to maintain doing so.");
1350. 	    return(0);
1351. 	}
1352. 	u.uen -= 10;
1353. 	flags.botl = 1;
1354. 
1355. 	pline("A wave of psychic energy pours out.");
1356. 	for(mtmp=fmon; mtmp; mtmp = nmon) {
1357. 		int u_sen;
1358. 
1359. 		nmon = mtmp->nmon;
1360. 		if (DEADMONSTER(mtmp))
1361. 			continue;
1362. 		if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM)
1363. 			continue;
1364. 		if(mtmp->mpeaceful)
1365. 			continue;
1366. 		u_sen = telepathic(mtmp->data) && !mtmp->mcansee;
1367. 		if (u_sen || (telepathic(mtmp->data) && rn2(3)) || !rn2(2)) {
1368. 			You("lock in on %s %s.", s_suffix(mon_nam(mtmp)),
1369. 				u_sen ? "telepathy" :
1370. 				telepathic(mtmp->data) ? "latent telepathy" :
1371. 				"mind");
1372. 			mtmp->mhp -= rn1(4,4);
1373. 			if (mtmp->mhp <= 0)
1374. 				killed(mtmp);
1375. 		}
1376. 	}
1377. 	return 1;
1378. }
1379. 
1380. STATIC_OVL void
1381. uunstick()
1382. {
1383. 	pline("%s is no longer in your clutches.", Monnam(u.ustuck));
1384. 	setustuck(0);
1385. }
1386. 
1387. void
1388. skinback(silently)
1389. boolean silently;
1390. {
1391. 	if (uskin) {
1392. 		if (!silently) Your("skin returns to its original form.");
1393. 		uarm = uskin;
1394. 		uskin = (struct obj *)0;
1395. 		/* undo save/restore hack */
1396. 		uarm->owornmask &= ~I_SPECIAL;
1397. 	}
1398. }
1399. 
1400. #endif /* OVLB */
1401. #ifdef OVL1
1402. 
1403. const char *
1404. mbodypart(mon, part)
1405. struct monst *mon;
1406. int part;
1407. {
1408. 	static NEARDATA const char
1409. 	*humanoid_parts[] = { "arm", "eye", "face", "finger",
1410. 		"fingertip", "foot", "hand", "handed", "head", "leg",
1411. 		"light headed", "neck", "spine", "toe", "hair",
1412. 		"blood", "lung", "nose", "stomach"},
1413. 	*jelly_parts[] = { "pseudopod", "dark spot", "front",
1414. 		"pseudopod extension", "pseudopod extremity",
1415. 		"pseudopod root", "grasp", "grasped", "cerebral area",
1416. 		"lower pseudopod", "viscous", "middle", "surface",
1417. 		"pseudopod extremity", "ripples", "juices",
1418. 		"surface", "sensor", "stomach" },
1419. 	*animal_parts[] = { "forelimb", "eye", "face", "foreclaw", "claw tip",
1420. 		"rear claw", "foreclaw", "clawed", "head", "rear limb",
1421. 		"light headed", "neck", "spine", "rear claw tip",
1422. 		"fur", "blood", "lung", "nose", "stomach" },
1423. 	*bird_parts[] = { "wing", "eye", "face", "wing", "wing tip",
1424. 		"foot", "wing", "winged", "head", "leg",
1425. 		"light headed", "neck", "spine", "toe",
1426. 		"feathers", "blood", "lung", "bill", "stomach" },
1427. 	*horse_parts[] = { "foreleg", "eye", "face", "forehoof", "hoof tip",
1428. 		"rear hoof", "foreclaw", "hooved", "head", "rear leg",
1429. 		"light headed", "neck", "backbone", "rear hoof tip",
1430. 		"mane", "blood", "lung", "nose", "stomach"},
1431. 	*sphere_parts[] = { "appendage", "optic nerve", "body", "tentacle",
1432. 		"tentacle tip", "lower appendage", "tentacle", "tentacled",
1433. 		"body", "lower tentacle", "rotational", "equator", "body",
1434. 		"lower tentacle tip", "cilia", "life force", "retina",
1435. 		"olfactory nerve", "interior" },
1436. 	*fungus_parts[] = { "mycelium", "visual area", "front", "hypha",
1437. 		"hypha", "root", "strand", "stranded", "cap area",
1438. 		"rhizome", "sporulated", "stalk", "root", "rhizome tip",
1439. 		"spores", "juices", "gill", "gill", "interior" },
1440. 	*vortex_parts[] = { "region", "eye", "front", "minor current",
1441. 		"minor current", "lower current", "swirl", "swirled",
1442. 		"central core", "lower current", "addled", "center",
1443. 		"currents", "edge", "currents", "life force",
1444. 		"center", "leading edge", "interior" },
1445. 	*snake_parts[] = { "vestigial limb", "eye", "face", "large scale",
1446. 		"large scale tip", "rear region", "scale gap", "scale gapped",
1447. 		"head", "rear region", "light headed", "neck", "length",
1448. 		"rear scale", "scales", "blood", "lung", "forked tongue", "stomach" },
1449. 	*fish_parts[] = { "fin", "eye", "premaxillary", "pelvic axillary",
1450. 		"pelvic fin", "anal fin", "pectoral fin", "finned", "head", "peduncle",
1451. 		"played out", "gills", "dorsal fin", "caudal fin",
1452. 		"scales", "blood", "gill", "nostril", "stomach" };
1453. 	/* claw attacks are overloaded in mons[]; most humanoids with
1454. 	   such attacks should still reference hands rather than claws */
1455. 	static const char not_claws[] = {
1456. 		S_HUMAN, S_MUMMY, S_ZOMBIE, S_ANGEL,
1457. 		S_NYMPH, S_LEPRECHAUN, S_QUANTMECH, S_VAMPIRE,
1458. 		S_ORC, S_GIANT,		/* quest nemeses */
1459. 		'\0'		/* string terminator; assert( S_xxx != 0 ); */
1460. 	};
1461. 	struct permonst *mptr = mon->data;
1462. 
1463. 	if (part == HAND || part == HANDED) {	/* some special cases */
1464. 	    if (mptr->mlet == S_DOG || mptr->mlet == S_FELINE ||
1465. 		    mptr->mlet == S_YETI)
1466. 		return part == HAND ? "paw" : "pawed";
1467. 	    if (humanoid(mptr) && attacktype(mptr, AT_CLAW) &&
1468. 		    !index(not_claws, mptr->mlet) &&
1469. 		    mptr != &mons[PM_STONE_GOLEM] &&
1470. 		    mptr != &mons[PM_INCUBUS] && mptr != &mons[PM_SUCCUBUS])
1471. 		return part == HAND ? "claw" : "clawed";
1472. 	}
1473. 	if ((mptr == &mons[PM_MUMAK] || mptr == &mons[PM_MASTODON]) &&
1474. 		part == NOSE)
1475. 	    return "trunk";
1476. 	if (mptr == &mons[PM_SHARK] && part == HAIR)
1477. 	    return "skin";	/* sharks don't have scales */
1478. 	if (mptr == &mons[PM_JELLYFISH] && (part == ARM || part == FINGER ||
1479. 	    part == HAND || part == FOOT || part == TOE))
1480. 	    return "tentacle";
1481. 	if (mptr == &mons[PM_FLOATING_EYE] && part == EYE)
1482. 	    return "cornea";
1483. 	if (humanoid(mptr) &&
1484. 		(part == ARM || part == FINGER || part == FINGERTIP ||
1485. 		    part == HAND || part == HANDED))
1486. 	    return humanoid_parts[part];
1487. 	if (mptr == &mons[PM_RAVEN])
1488. 	    return bird_parts[part];
1489. 	if (mptr->mlet == S_CENTAUR || mptr->mlet == S_UNICORN ||
1490. 		(mptr == &mons[PM_ROTHE] && part != HAIR))
1491. 	    return horse_parts[part];
1492. 	if (mptr->mlet == S_LIGHT) {
1493. 		if (part == HANDED) return "rayed";
1494. 		else if (part == ARM || part == FINGER ||
1495. 				part == FINGERTIP || part == HAND) return "ray";
1496. 		else return "beam";
1497. 	}
1498. 	if (mptr->mlet == S_EEL && mptr != &mons[PM_JELLYFISH])
1499. 	    return fish_parts[part];
1500. 	if (slithy(mptr) || (mptr->mlet == S_DRAGON && part == HAIR))
1501. 	    return snake_parts[part];
1502. 	if (mptr->mlet == S_EYE)
1503. 	    return sphere_parts[part];
1504. 	if (mptr->mlet == S_JELLY || mptr->mlet == S_PUDDING ||
1505. 		mptr->mlet == S_BLOB || mptr == &mons[PM_JELLYFISH])
1506. 	    return jelly_parts[part];
1507. 	if (mptr->mlet == S_VORTEX || mptr->mlet == S_ELEMENTAL)
1508. 	    return vortex_parts[part];
1509. 	if (mptr->mlet == S_FUNGUS)
1510. 	    return fungus_parts[part];
1511. 	if (humanoid(mptr))
1512. 	    return humanoid_parts[part];
1513. 	return animal_parts[part];
1514. }
1515. 
1516. const char *
1517. body_part(part)
1518. int part;
1519. {
1520. 	return mbodypart(&youmonst, part);
1521. }
1522. 
1523. #endif /* OVL1 */
1524. #ifdef OVL0
1525. 
1526. int
1527. poly_gender()
1528. {
1529. /* Returns gender of polymorphed player; 0/1=same meaning as flags.female,
1530.  * 2=none.
1531.  */
1532. 	if (is_neuter(youmonst.data) || !humanoid(youmonst.data)) return 2;
1533. 	return flags.female;
1534. }
1535. 
1536. #endif /* OVL0 */
1537. #ifdef OVLB
1538. 
1539. void
1540. ugolemeffects(damtype, dam)
1541. int damtype, dam;
1542. {
1543. 	int heal = 0;
1544. 	/* We won't bother with "slow"/"haste" since players do not
1545. 	 * have a monster-specific slow/haste so there is no way to
1546. 	 * restore the old velocity once they are back to human.
1547. 	 */
1548. 	if (u.umonnum != PM_FLESH_GOLEM && u.umonnum != PM_IRON_GOLEM)
1549. 		return;
1550. 	switch (damtype) {
1551. 		case AD_ELEC: if (u.umonnum == PM_FLESH_GOLEM)
1552. 				heal = dam / 6; /* Approx 1 per die */
1553. 			break;
1554. 		case AD_FIRE: if (u.umonnum == PM_IRON_GOLEM)
1555. 				heal = dam;
1556. 			break;
1557. 	}
1558. 	if (heal && (u.mh < u.mhmax)) {
1559. 		u.mh += heal;
1560. 		if (u.mh > u.mhmax) u.mh = u.mhmax;
1561. 		flags.botl = 1;
1562. 		pline("Strangely, you feel better than before.");
1563. 		exercise(A_STR, TRUE);
1564. 	}
1565. }
1566. 
1567. STATIC_OVL int
1568. armor_to_dragon(atyp)
1569. int atyp;
1570. {
1571. 	switch(atyp) {
1572. 	    case GRAY_DRAGON_SCALE_MAIL:
1573. 	    case GRAY_DRAGON_SCALES:
1574. 		return PM_GRAY_DRAGON;
1575. 	    case SILVER_DRAGON_SCALE_MAIL:
1576. 	    case SILVER_DRAGON_SCALES:
1577. 		return PM_SILVER_DRAGON;
1578. 	    case SHIMMERING_DRAGON_SCALE_MAIL:
1579. 	    case SHIMMERING_DRAGON_SCALES:
1580. 		return PM_SHIMMERING_DRAGON;
1581. 	    case DEEP_DRAGON_SCALE_MAIL:
1582. 	    case DEEP_DRAGON_SCALES:
1583. 		return PM_DEEP_DRAGON;
1584. 	    case RED_DRAGON_SCALE_MAIL:
1585. 	    case RED_DRAGON_SCALES:
1586. 		return PM_RED_DRAGON;
1587. 	    case ORANGE_DRAGON_SCALE_MAIL:
1588. 	    case ORANGE_DRAGON_SCALES:
1589. 		return PM_ORANGE_DRAGON;
1590. 	    case WHITE_DRAGON_SCALE_MAIL:
1591. 	    case WHITE_DRAGON_SCALES:
1592. 		return PM_WHITE_DRAGON;
1593. 	    case BLACK_DRAGON_SCALE_MAIL:
1594. 	    case BLACK_DRAGON_SCALES:
1595. 		return PM_BLACK_DRAGON;
1596. 	    case BLUE_DRAGON_SCALE_MAIL:
1597. 	    case BLUE_DRAGON_SCALES:
1598. 		return PM_BLUE_DRAGON;
1599. 	    case GREEN_DRAGON_SCALE_MAIL:
1600. 	    case GREEN_DRAGON_SCALES:
1601. 		return PM_GREEN_DRAGON;
1602. 	    case YELLOW_DRAGON_SCALE_MAIL:
1603. 	    case YELLOW_DRAGON_SCALES:
1604. 		return PM_YELLOW_DRAGON;
1605. 	    default:
1606. 		return -1;
1607. 	}
1608. }
1609. 
1610. static struct {
1611.     int mon;
1612.     int reqtime;
1613.     boolean merge;
1614. } draconic;
1615. 
1616. STATIC_PTR
1617. int
1618. mage_transform()	/* called each move during transformation process */
1619. {
1620.     if (--draconic.reqtime)
1621. 	return 1;
1622.     if (draconic.merge)
1623. 	merge_with_armor();
1624.     polymon(draconic.mon);
1625.     return 0;
1626. }
1627. 
1628. int
1629. polyatwill()      /* Polymorph under conscious control (#youpoly) */
1630. {
1631. #define EN_DOPP 	20 	/* This is the "base cost" for a polymorph
1632. 				 * Actual cost is this base cost + 5 * monster level
1633. 				 * of the final form you actually assume.
1634. 				 * Energy will be taken first, then you will get 
1635. 				 * more hungry if you do not have enough energy.
1636. 				 */
1637. #define EN_WERE 	10
1638. #define EN_BABY_DRAGON 	10
1639. #define EN_ADULT_DRAGON 15
1640. 
1641. 	boolean scales = ((uarm && uarm->otyp == RED_DRAGON_SCALES
1642. 				&& Role_if(PM_FLAME_MAGE)) ||
1643. 			  (uarm && uarm->otyp == WHITE_DRAGON_SCALES
1644. 				&& Role_if(PM_ICE_MAGE)));
1645. 	boolean scale_mail = ((uarm && uarm->otyp == RED_DRAGON_SCALE_MAIL   
1646. 				&& Role_if(PM_FLAME_MAGE)) ||
1647. 			  (uarm && uarm->otyp == WHITE_DRAGON_SCALE_MAIL 
1648. 				&& Role_if(PM_ICE_MAGE)));
1649. 
1650. 	/* Set to TRUE when you can polyatwill but choose not to */
1651. 	boolean can_polyatwill = FALSE; 
1652. 	
1653. 	/* KMH, balance patch -- new intrinsic */
1654. 	if (Unchanging) {
1655. 	    pline("You cannot change your form.");
1656. 	    return 0;
1657. 	}
1658. 
1659. 	/* First, if in correct polymorphed form, rehumanize (for free) 
1660. 	 * Omit Lycanthropes,  who need to spend energy to change back and forth
1661. 	 */
1662. 	if (Upolyd && (Race_if(PM_DOPPELGANGER) ||
1663. 			(Role_if(PM_FLAME_MAGE) && (u.umonnum == PM_RED_DRAGON || 
1664. 				u.umonnum == PM_BABY_RED_DRAGON)) ||
1665. 			(Role_if(PM_ICE_MAGE) && (u.umonnum == PM_WHITE_DRAGON || 
1666. 				u.umonnum == PM_BABY_WHITE_DRAGON)))) {
1667. 	    rehumanize();
1668. 	    return 1;	    
1669. 	}
1670. 
1671. 	if ((Role_if(PM_ICE_MAGE) || Role_if(PM_FLAME_MAGE)) &&
1672. 	    (u.ulevel > 6 || scale_mail)) {
1673. 	    /* [ALI]
1674. 	     * I've rewritten the logic here to fix the failure messages,
1675. 	     * but the requirements for polymorphing into the two dragon
1676. 	     * forms remains the same:
1677. 	     *
1678. 	     * Polymorph into adult dragon form if one of:
1679. 	     *
1680. 	     * - Wearing scale mail (no charge).
1681. 	     * - Wearing scales and experience level 7 and
1682. 	     *   energy level 11 or more (charge is 10).
1683. 	     * - Not wearing scales or scale mail and experience level 14 and
1684. 	     *   energy level 16 or more (charge is 15).
1685. 	     *
1686. 	     * Polymorph into baby dragon form if one of:
1687. 	     *
1688. 	     * - Wearing scales and experience level 7 and
1689. 	     *   energy level 10 or less (no charge).
1690. 	     * - Not wearing scales or scale mail and experience level 14 and
1691. 	     *   energy level 11-15 (charge is 10).
1692. 	     * - Not wearing scales or scale mail and experience level 7-13 and
1693. 	     *   energy level 11 or more (charge is 10).
1694. 	     *
1695. 	     * Fail if one of:
1696. 	     *
1697. 	     * - Not wearing scales or scale mail and experience level 7 and
1698. 	     *   energy level 10 or less (not enough energy).
1699. 	     * - Not wearing scale mail and experience level 6 or less
1700. 	     *   (not experienced enough).
1701. 	     *
1702. 	     * The transformation takes a few turns. If interrupted during this
1703. 	     * period then the ritual must be begun again from the beginning.
1704. 	     * We deliberately don't say what form the ritual takes since it
1705. 	     * is unaffected by blindness, confusion, stun etc. 
1706. 	     */
1707. 	    if (yn("Transform into your draconic form?") == 'n') 
1708. 		can_polyatwill = TRUE;
1709. 	    else if (!scales && !scale_mail && u.uen <= EN_BABY_DRAGON) {
1710. 		You("don't have the energy to polymorph.");
1711. 		return 0;		
1712. 	    } else {
1713. 		/* Check if you can do the adult form */
1714. 		if (u.ulevel > 13 && u.uen > EN_ADULT_DRAGON || 
1715. 			scales && u.uen > EN_BABY_DRAGON || scale_mail) {
1716. 		    /* If you have scales, energy cost is less */
1717. 		    /* If you have scale mail,  there is no cost! */
1718. 		    if (!scale_mail) {
1719. 			if (scales) u.uen -= EN_BABY_DRAGON; 
1720. 			else u.uen -= EN_ADULT_DRAGON;
1721. 		    }
1722. 
1723. 		    draconic.mon = Role_if(PM_FLAME_MAGE) ?
1724. 			    PM_RED_DRAGON : PM_WHITE_DRAGON;
1725. 		    draconic.merge = scales || scale_mail;
1726. 		/* Otherwise use the baby form */
1727. 		} else {
1728. 		    if (!scales) u.uen -= EN_BABY_DRAGON;
1729. 
1730. 		    draconic.mon = Role_if(PM_FLAME_MAGE) ?
1731. 			    PM_BABY_RED_DRAGON : PM_BABY_WHITE_DRAGON;
1732. 		    draconic.merge = scales;
1733. 		}
1734. 		draconic.reqtime = 2;
1735. 		if (mvitals[draconic.mon].mvflags & G_GENOD)
1736. 		    draconic.merge = FALSE;
1737. 		set_occupation(mage_transform,
1738. 			"transforming into your draconic form", 0);
1739. 		You("begin the transformation ritual.");
1740. 		return 1;
1741. 	    }
1742. 	}
1743. 	if (Race_if(PM_DOPPELGANGER)) {
1744. 	    if (yn("Polymorph at will?") == 'n')	    
1745. 	    	can_polyatwill = TRUE;
1746. 	    else if (u.uen < EN_DOPP) {
1747. 		You("don't have the energy to polymorph!");
1748. 		return 0;
1749. 	    } else {
1750. 		u.uen -= EN_DOPP;
1751. 		if (multi >= 0) {
1752. 		    if (occupation) stop_occupation();
1753. 		    else nomul(0);
1754. 		}
1755. 		polyself(FALSE);
1756. 		if (Upolyd) { /* You actually polymorphed */
1757. 		    u.uen -= 5 * mons[u.umonnum].mlevel;
1758. 		    if (u.uen < 0) {
1759. 			morehungry(-u.uen);
1760. 			u.uen = 0;
1761. 		    }
1762. 		}
1763. 		return 1;	
1764. 	    }
1765. 	} else if (Race_if(PM_HUMAN_WEREWOLF) &&
1766. 		(!Upolyd || u.umonnum == u.ulycn)) {
1767. 	    if (yn("Change form?") == 'n')
1768. 	    	can_polyatwill = TRUE;
1769. 	    else if (u.ulycn == NON_PM) {
1770. 	    	/* Very serious */
1771. 	    	You("are no longer a lycanthrope!");
1772. 	    } else if (u.ulevel <= 2) {
1773. 	    	You("can't invoke the change at will yet.");
1774. 		return 0;		
1775. 	    } else if (u.uen < EN_WERE) {
1776. 		You("don't have the energy to change form!");
1777. 		return 0;
1778. 	    } else {
1779. 	    	/* Committed to the change now */
1780. 		u.uen -= EN_WERE;
1781. 		if (!Upolyd) {
1782. 		    if (multi >= 0) {
1783. 			if (occupation) stop_occupation();
1784. 			else nomul(0);
1785. 		    }
1786. 		    you_were();
1787. 		    return 1;
1788. 		} else {
1789. 		    rehumanize();
1790. 		    return 1;
1791. 		}
1792. 	    }
1793. 	} else if (!can_polyatwill) {
1794. 	    pline("You can't polymorph at will%s.", 
1795. 		    ((Role_if(PM_FLAME_MAGE) || Role_if(PM_ICE_MAGE) || 
1796. 		      Race_if(PM_HUMAN_WEREWOLF) || Race_if(PM_DOPPELGANGER)) ?
1797. 		    " yet" : ""));
1798. 	    return 0;
1799. 	}
1800. 
1801. 	flags.botl = 1;
1802. 	return 1;
1803. }
1804. 
1805. static void
1806. merge_with_armor()
1807. {
1808. 	/* This function does hides the armor being worn 
1809. 	 * It currently assumes that you are changing into a dragon
1810. 	 * Should check that monster being morphed into is not genocided
1811. 	 * see do_merge above for correct use
1812. 	 */
1813. 	if (Race_if(PM_DOPPELGANGER) && !uarm->cursed && uarmu &&
1814. 	  !uarmu->cursed) {
1815. 	    struct obj *otmp = uarmu;
1816. 	    You("quickly remove your shirt as you start to change.");
1817. 	    setworn((struct obj *)0, otmp->owornmask & W_ARMU);
1818. 	    dropx(otmp);
1819. 	}
1820. 	You("merge with your scaly armor.");
1821. 	uskin = uarm;
1822. 	uarm = (struct obj *)0;
1823. 	/* save/restore hack */
1824. 	uskin->owornmask |= I_SPECIAL;
1825. 
1826. }
1827. 
1828. #if 0	/* What the f*** is this for? -- KMH */
1829. static void
1830. special_poly()
1831. {
1832. 	char buf[BUFSZ];
1833. 	int old_light, new_light;
1834. 	int mntmp = NON_PM;
1835. 	int tries=0;
1836. 
1837. 	old_light = (u.umonnum >= LOW_PM) ? emits_light(youmonst.data) : 0;
1838. 	do {
1839. 		getlin("Become what kind of monster? [type the name]", buf);
1840. 		mntmp = name_to_mon(buf);
1841. 		if (mntmp < LOW_PM)
1842. 				pline("I've never heard of such monsters.");
1843. 			/* Note:  humans are illegal as monsters, but an
1844. 			 * illegal monster forces newman(), which is what we
1845. 			 * want if they specified a human.... */
1846. 
1847. 			/* [Tom] gnomes are polyok, so this doesn't apply for
1848. 			   player gnomes */
1849. 	                     /* WAC but we want to catch player gnomes and not
1850. 	                        so add an extra check */
1851. 		else if (!polyok(&mons[mntmp]) &&
1852. 				(Role_elven ? !is_elf(&mons[mntmp]) :
1853. #ifdef DWARF
1854. 				Role_if(PM_DWARF) ? !is_gnome(&mons[mntmp]) :
1855. #endif
1856. 				/* WAC
1857. 				 * should always fail (for now) gnome check
1858. 				 * unless gnomes become not polyok.  Then, it'll
1859. 				 * still work ;B
1860. 				 */
1861. 				Role_if(PM_GNOME) ? !is_gnome(&mons[mntmp]) :
1862. 				!is_human(&mons[mntmp])))
1863. 			You("cannot polymorph into that.");
1864. #ifdef EATEN_MEMORY
1865. 		else if (!mvitals[mntmp].eaten && (rn2((u.ulevel + 25)) < 20)) {
1866. 			You("don't have the knowledge to polymorph into that.");
1867. 			return;  /* Nice try */
1868. 		} else {
1869. 			You("attempt an unfamiliar polymorph.");
1870. 			break;
1871. 		}
1872. #endif
1873. 	} while(++tries < 5);
1874. 	if (tries==5) {
1875. 		pline(thats_enough_tries);
1876. 		return;
1877. 	} else if (polymon(mntmp)) {
1878. 		/* same as made_change above */
1879. 		new_light = (u.umonnum >= LOW_PM) ? emits_light(youmonst.data) : 0;
1880. 		if (old_light != new_light) {
1881. 		    if (old_light)
1882. 			del_light_source(LS_MONSTER, (genericptr_t)&youmonst);
1883. 		    if (new_light == 1) ++new_light;  /* otherwise it's undetectable */
1884. 		    if (new_light)
1885. 			new_light_source(u.ux, u.uy, new_light,
1886. 					 LS_MONSTER, (genericptr_t)&youmonst);
1887. 		}
1888. 	}
1889. 	return;
1890. }
1891. #endif
1892. 
1893. 
1894. #endif /* OVLB */
1895. 
1896. /*polyself.c*/