Source:NetHack 3.2.0/polyself.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to polyself.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/polyself.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see 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.2	95/11/12	*/
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 void FDECL(polyman, (const char *,const char *));
17.   static void NDECL(break_armor);
18.   static void FDECL(drop_weapon,(int));
19.   static void NDECL(skinback);
20.   static void NDECL(uunstick);
21.   static int FDECL(armor_to_dragon,(int));
22.   
23.   /* update the "uasmon" structure */
24.   void
25.   set_uasmon()
26.   {
27.   	if (u.umonnum >= LOW_PM) {
28.   	    uasmon = &mons[u.umonnum];
29.   	} else {
30.   	    uasmon = &playermon;
31.   #if 0
32.   	    /* We do not currently use uasmon or playermon to check the below
33.   	     * attributes of the player, and it is generally pointless to do
34.   	     * so.  Furthermore, we do not call set_uasmon() often enough to
35.   	     * use uasmon or playermon for this purpose; for instance, we do
36.   	     * not call it every time we wear armor.
37.   	     */
38.   	    playermon.mlevel = u.ulevel;
39.   	    playermon.ac = u.uac;
40.   	    playermon.mr = (u.ulevel > 8) ? 5 * (u.ulevel - 7) : u.ulevel;
41.   #endif
42.   	}
43.   	set_mon_data(&youmonst, uasmon, 0);
44.   	return;
45.   }
46.   
47.   /* make a (new) human out of the player */
48.   static void
49.   polyman(fmt, arg)
50.   const char *fmt, *arg;
51.   {
52.   	boolean sticky = sticks(uasmon) && u.ustuck && !u.uswallow;
53.   
54.   	if (u.umonnum != PM_PLAYERMON) {
55.   		u.acurr = u.macurr;	/* restore old attribs */
56.   		u.amax = u.mamax;
57.   		u.umonnum = PM_PLAYERMON;
58.   		flags.female = u.mfemale;
59.   	}
60.   	u.usym = S_HUMAN;
61.   	set_uasmon();
62.   
63.   	u.mh = u.mhmax = 0;
64.   	u.mtimedone = 0;
65.   	skinback();
66.   	u.uundetected = 0;
67.   	newsym(u.ux,u.uy);
68.   
69.   	if (sticky) uunstick();
70.   	find_ac();
71.   
72.   	You(fmt, arg);
73.   	/* check whether player foolishly genocided self while poly'd */
74.   	if (mvitals[u.umonster].mvflags & G_GENOD) done(GENOCIDED);
75.   
76.   	if(!Levitation && !u.ustuck &&
77.   	   (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy)))
78.   		spoteffects();
79.   }
80.   
81.   void
82.   change_sex()
83.   {
84.   	flags.female = !flags.female;
85.   	max_rank_sz();
86.   	if (Role_is('P')) {
87.   		Strcpy(pl_character+6, flags.female ? "ess" : "");
88.   		u.umonster = flags.female ? PM_PRIESTESS : PM_PRIEST;
89.   	} else if (Role_is('C')) {
90.   		Strcpy(pl_character+4, flags.female ? "woman" : "man");
91.   		u.umonster = flags.female ? PM_CAVEWOMAN : PM_CAVEMAN;
92.   	}
93.   }
94.   
95.   void
96.   newman()
97.   {
98.   	int tmp, tmp2;
99.   
100.  	if (!rn2(10)) change_sex();
101.  
102.  	tmp = u.uhpmax;
103.  	tmp2 = u.ulevel;
104.  	u.ulevel = u.ulevel + rn1(5, -2);
105.  	if (u.ulevel > 127 || u.ulevel < 1) u.ulevel = 1;
106.  	if (u.ulevel > MAXULEV) u.ulevel = MAXULEV;
107.  
108.  	adjabil(tmp2, (int)u.ulevel);
109.  	reset_rndmonst(NON_PM);	/* new monster generation criteria */
110.  
111.  	/* random experience points for the new experience level */
112.  	u.uexp = rndexp();
113.  
114.  	/* u.uhpmax * u.ulevel / tmp2: proportionate hit points to new level
115.  	 * -10 and +10: don't apply proportionate HP to 10 of a starting
116.  	 *   character's hit points (since a starting character's hit points
117.  	 *   are not on the same scale with hit points obtained through level
118.  	 *   gain)
119.  	 * 9 - rn2(19): random change of -9 to +9 hit points
120.  	 */
121.  #ifndef LINT
122.  	u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / tmp2 + 10) +
123.  		(9 - rn2(19));
124.  #endif
125.  
126.  #ifdef LINT
127.  	u.uhp = u.uhp + tmp;
128.  #else
129.  	u.uhp = u.uhp * (long)u.uhpmax/tmp;
130.  #endif
131.  
132.  	tmp = u.uenmax;
133.  #ifndef LINT
134.  	u.uenmax = u.uenmax * (long)u.ulevel / tmp2 + 9 - rn2(19);
135.  #endif
136.  	if (u.uenmax < 0) u.uenmax = 0;
137.  #ifndef LINT
138.  	u.uen = (tmp ? u.uen * (long)u.uenmax / tmp : u.uenmax);
139.  #endif
140.  
141.  	redist_attr();
142.  	u.uhunger = rn1(500,500);
143.  	newuhs(FALSE);
144.  	if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL);
145.  	Stoned = 0;
146.  	if (u.uhp <= 0 || u.uhpmax <= 0) {
147.  		if (Polymorph_control) {
148.  		    if (u.uhp <= 0) u.uhp = 1;
149.  		    if (u.uhpmax <= 0) u.uhpmax = 1;
150.  		} else {
151.  		    Your("new form doesn't seem healthy enough to survive.");
152.  		    killer_format = KILLED_BY_AN;
153.  		    killer="unsuccessful polymorph";
154.  		    done(DIED);
155.  		}
156.  	}
157.  	polyman("feel like a new %s!",
158.  		Role_is('E') ? "elf" : flags.female ? "woman" : "man");
159.  	flags.botl = 1;
160.  	(void) encumber_msg();
161.  }
162.  
163.  void
164.  polyself()
165.  {
166.  	char buf[BUFSZ];
167.  	int old_light, new_light;
168.  	int mntmp = NON_PM;
169.  	int tries=0;
170.  	boolean draconian = (uarm &&
171.  				uarm->otyp >= GRAY_DRAGON_SCALE_MAIL &&
172.  				uarm->otyp <= YELLOW_DRAGON_SCALES);
173.  
174.  	boolean iswere = (u.ulycn >= LOW_PM || is_were(uasmon));
175.  	boolean isvamp = (u.usym == S_VAMPIRE || u.umonnum == PM_VAMPIRE_BAT);
176.  
177.  	if(!Polymorph_control && !draconian && !iswere && !isvamp) {
178.  	    if (rn2(20) > ACURR(A_CON)) {
179.  		You(shudder_for_moment);
180.  		losehp(rnd(30), "system shock", KILLED_BY_AN);
181.  		exercise(A_CON, FALSE);
182.  		return;
183.  	    }
184.  	}
185.  	old_light = (u.umonnum >= LOW_PM) ? emits_light(uasmon) : 0;
186.  
187.  	if (Polymorph_control) {
188.  		do {
189.  			getlin("Become what kind of monster? [type the name]",
190.  				buf);
191.  			mntmp = name_to_mon(buf);
192.  			if (mntmp < LOW_PM)
193.  				pline("I've never heard of such monsters.");
194.  			/* Note:  humans are illegal as monsters, but an
195.  			 * illegal monster forces newman(), which is what we
196.  			 * want if they specified a human.... */
197.  			else if (!polyok(&mons[mntmp]) &&
198.  			    (Role_is('E') ? !is_elf(&mons[mntmp])
199.  					  : !is_human(&mons[mntmp])))
200.  				You("cannot polymorph into that.");
201.  			else break;
202.  		} while(++tries < 5);
203.  		if (tries==5) pline(thats_enough_tries);
204.  		/* allow skin merging, even when polymorph is controlled */
205.  		if (draconian &&
206.  		    (mntmp == armor_to_dragon(uarm->otyp) || tries == 5))
207.  		    goto do_merge;
208.  	} else if (draconian || iswere || isvamp) {
209.  		/* special changes that don't require polyok() */
210.  		if (draconian) {
211.  		    do_merge:
212.  			mntmp = armor_to_dragon(uarm->otyp);
213.  			if (!(mvitals[mntmp].mvflags & G_GENOD)) {
214.  				/* allow G_EXTINCT */
215.  				You("merge with your scaly armor.");
216.  				uskin = uarm;
217.  				uarm = (struct obj *)0;
218.  				/* save/restore hack */
219.  				uskin->owornmask |= I_SPECIAL;
220.  			}
221.  		} else if (iswere) {
222.  			if (is_were(uasmon))
223.  				mntmp = PM_HUMAN; /* Illegal; force newman() */
224.  			else
225.  				mntmp = u.ulycn;
226.  		} else {
227.  			if (u.usym == S_VAMPIRE)
228.  				mntmp = PM_VAMPIRE_BAT;
229.  			else
230.  				mntmp = PM_VAMPIRE;
231.  		}
232.  		if (polymon(mntmp))
233.  			goto made_change;
234.  	}
235.  
236.  	if (mntmp < LOW_PM) {
237.  		tries = 0;
238.  		do {
239.  			/* randomly pick an "ordinary" monster */
240.  			mntmp = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
241.  		} while((!polyok(&mons[mntmp]) || is_placeholder(&mons[mntmp]))
242.  				&& tries++ < 200);
243.  	}
244.  
245.  	/* The below polyok() fails either if everything is genocided, or if
246.  	 * we deliberately chose something illegal to force newman().
247.  	 */
248.  	if (!polyok(&mons[mntmp]) || !rn2(5))
249.  		newman();
250.  	else if(!polymon(mntmp)) return;
251.  
252.  	if (!uarmg) selftouch("No longer petrify-resistant, you");
253.  
254.   made_change:
255.  	new_light = (u.umonnum >= LOW_PM) ? emits_light(uasmon) : 0;
256.  	if (old_light != new_light) {
257.  	    if (old_light)
258.  		del_light_source(LS_MONSTER, (genericptr_t)&youmonst);
259.  	    if (new_light == 1) ++new_light;  /* otherwise it's undetectable */
260.  	    if (new_light)
261.  		new_light_source(u.ux, u.uy, new_light,
262.  				 LS_MONSTER, (genericptr_t)&youmonst);
263.  	}
264.  }
265.  
266.  /* (try to) make a mntmp monster out of the player */
267.  int
268.  polymon(mntmp)	/* returns 1 if polymorph successful */
269.  int	mntmp;
270.  {
271.  	boolean sticky = sticks(uasmon) && u.ustuck && !u.uswallow;
272.  	boolean dochange = FALSE;
273.  	int	tmp;
274.  
275.  	if (mvitals[mntmp].mvflags & G_GENOD) {	/* allow G_EXTINCT */
276.  		You_feel("rather %s-ish.",mons[mntmp].mname);
277.  		exercise(A_WIS, TRUE);
278.  		return(0);
279.  	}
280.  
281.  	if (u.umonnum == PM_PLAYERMON) {
282.  		/* Human to monster; save human stats */
283.  		u.macurr = u.acurr;
284.  		u.mamax = u.amax;
285.  		u.mfemale = flags.female;
286.  	} else {
287.  		/* Monster to monster; restore human stats, to be
288.  		 * immediately changed to provide stats for the new monster
289.  		 */
290.  		u.acurr = u.macurr;
291.  		u.amax = u.mamax;
292.  		flags.female = u.mfemale;
293.  	}
294.  
295.  	if (is_male(&mons[mntmp])) {
296.  		if(flags.female) dochange = TRUE;
297.  	} else if (is_female(&mons[mntmp])) {
298.  		if(!flags.female) dochange = TRUE;
299.  	} else if (!is_neuter(&mons[mntmp]) && mntmp != u.ulycn) {
300.  		if(!rn2(10)) dochange = TRUE;
301.  	}
302.  	if (dochange) {
303.  		flags.female = !flags.female;
304.  		You("%s %s %s!",
305.  		    (u.umonnum != mntmp) ? "turn into a" : "feel like a new",
306.  		    flags.female ? "female" : "male",
307.  		    mons[mntmp].mname);
308.  	} else {
309.  		if (u.umonnum != mntmp)
310.  			You("turn into %s!", an(mons[mntmp].mname));
311.  		else
312.  			You_feel("like a new %s!", mons[mntmp].mname);
313.  	}
314.  	if (Stoned && poly_when_stoned(&mons[mntmp])) {
315.  		/* poly_when_stoned already checked stone golem genocide */
316.  		You("turn to stone!");
317.  		mntmp = PM_STONE_GOLEM;
318.  		Stoned = 0;
319.  	}
320.  
321.  	u.umonnum = mntmp;
322.  	u.usym = mons[mntmp].mlet;
323.  	set_uasmon();
324.  
325.  	/* New stats for monster, to last only as long as polymorphed.
326.  	 * Currently only strength gets changed.
327.  	 */
328.  	if(strongmonst(&mons[mntmp])) ABASE(A_STR) = AMAX(A_STR) = 118;
329.  
330.  	if (resists_ston(&youmonst) && Stoned) { /* parnes@eniac.seas.upenn.edu */
331.  		Stoned = 0;
332.  		You("no longer seem to be petrifying.");
333.  	}
334.  	if (u.usym == S_FUNGUS && Sick) {
335.  		make_sick(0L, (char *) 0, FALSE, SICK_ALL);
336.  		You("no longer feel sick.");
337.  	}
338.  	if (nohands(uasmon)) Glib = 0;
339.  
340.  	if (u.usym == S_DRAGON && mntmp >= PM_GRAY_DRAGON)
341.  		u.mhmax = 8 * mons[mntmp].mlevel;
342.  	else if (is_golem(uasmon)) u.mhmax = golemhp(mntmp);
343.  	else {
344.  		/*
345.  		tmp = adj_lev(&mons[mntmp]);
346.  		 * We can't do this, since there's no such thing as an
347.  		 * "experience level of you as a monster" for a polymorphed
348.  		 * character.
349.  		 */
350.  		tmp = mons[mntmp].mlevel;
351.  		if (!tmp) u.mhmax = rnd(4);
352.  		else u.mhmax = d(tmp, 8);
353.  	}
354.  	u.mh = u.mhmax;
355.  
356.  	u.mtimedone = rn1(500, 500);
357.  	if (u.ulevel < mons[mntmp].mlevel)
358.  	/* Low level characters can't become high level monsters for long */
359.  #ifdef DUMB
360.  		{
361.  		/* DRS/NS 2.2.6 messes up -- Peter Kendell */
362.  			int	mtd = u.mtimedone,
363.  				ulv = u.ulevel,
364.  				mlv = mons[mntmp].mlevel;
365.  
366.  			u.mtimedone = mtd * ulv / mlv;
367.  		}
368.  #else
369.  		u.mtimedone = u.mtimedone * u.ulevel / mons[mntmp].mlevel;
370.  #endif
371.  
372.  	if (uskin && mntmp != armor_to_dragon(uskin->otyp))
373.  		skinback();
374.  	break_armor();
375.  	drop_weapon(1);
376.  	if (hides_under(uasmon))
377.  		u.uundetected = OBJ_AT(u.ux, u.uy);
378.  	else if (uasmon->mlet == S_EEL)
379.  		u.uundetected = is_pool(u.ux, u.uy);
380.  	else
381.  		u.uundetected = 0;
382.  	newsym(u.ux,u.uy);		/* Change symbol */
383.  
384.  	if (!sticky && !u.uswallow && u.ustuck && sticks(uasmon)) u.ustuck = 0;
385.  	else if (sticky && !sticks(uasmon)) uunstick();
386.  
387.  	if (flags.verbose) {
388.  	    static const char use_thec[] = "Use the command #%s to %s.";
389.  	    static const char monsterc[] = "monster";
390.  	    if (can_breathe(uasmon))
391.  		pline(use_thec,monsterc,"use your breath weapon");
392.  	    if (attacktype(uasmon, AT_SPIT))
393.  		pline(use_thec,monsterc,"spit venom");
394.  	    if (u.usym == S_NYMPH)
395.  		pline(use_thec,monsterc,"remove an iron ball");
396.  	    if (u.usym == S_UMBER)
397.  		pline(use_thec,monsterc,"confuse monsters");
398.  	    if (is_hider(uasmon))
399.  		pline(use_thec,monsterc,"hide");
400.  	    if (is_were(uasmon))
401.  		pline(use_thec,monsterc,"summon help");
402.  	    if (webmaker(uasmon))
403.  		pline(use_thec,monsterc,"spin a web");
404.  	    if (u.umonnum == PM_GREMLIN)
405.  		pline(use_thec,monsterc,"multiply in a fountain");
406.  	    if (u.usym == S_UNICORN)
407.  		pline(use_thec,monsterc,"use your horn");
408.  	    if (u.umonnum == PM_MIND_FLAYER)
409.  		pline(use_thec,monsterc,"emit a mental blast");
410.  	    if (uasmon->msound == MS_SHRIEK) /* worthless, actually */
411.  		pline(use_thec,monsterc,"shriek");
412.  	    if (lays_eggs(uasmon) && flags.female)
413.  		pline(use_thec,"sit","lay an egg");
414.  	}
415.  	/* you now know what an egg of your type looks like */
416.  	if (lays_eggs(uasmon)) {
417.  	    learn_egg_type(u.umonnum);
418.  	    /* make queen bees recognize killer bee eggs */
419.  	    learn_egg_type(egg_type_from_parent(u.umonnum, TRUE));
420.  	}
421.  	find_ac();
422.  	if((!Levitation && !u.ustuck && !is_flyer(uasmon) &&
423.  	    (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy))) ||
424.  	   (Underwater && !is_swimmer(uasmon)))
425.  	    spoteffects();
426.  	if (passes_walls(uasmon) && u.utrap && u.utraptype == TT_INFLOOR) {
427.  	    u.utrap = 0;
428.  	    pline_The("rock seems to no longer trap you.");
429.  	} else if (likes_lava(uasmon) && u.utrap && u.utraptype == TT_LAVA) {
430.  	    u.utrap = 0;
431.  	    pline_The("lava now feels soothing.");
432.  	}
433.  	if (amorphous(uasmon) || is_whirly(uasmon) || unsolid(uasmon)) {
434.  	    if (Punished) {
435.  		You("slip out of the iron chain.");
436.  		unpunish();
437.  	    }
438.  	}
439.  	if (u.utrap && (u.utraptype == TT_WEB || u.utraptype == TT_BEARTRAP) &&
440.  		(amorphous(uasmon) || is_whirly(uasmon) || unsolid(uasmon) ||
441.  		  (uasmon->msize <= MZ_SMALL && u.utraptype == TT_BEARTRAP))) {
442.  	    You("are no longer stuck in the %s.",
443.  		    u.utraptype == TT_WEB ? "web" : "bear trap");
444.  	    /* probably should burn webs too if PM_FIRE_ELEMENTAL */
445.  	    u.utrap = 0;
446.  	}
447.  	if (uasmon->mlet == S_SPIDER && u.utrap && u.utraptype == TT_WEB) {
448.  	    You("orient yourself on the web.");
449.  	    u.utrap = 0;
450.  	}
451.  	flags.botl = 1;
452.  	vision_full_recalc = 1;
453.  	exercise(A_CON, FALSE);
454.  	exercise(A_WIS, TRUE);
455.  	(void) encumber_msg();
456.  	return(1);
457.  }
458.  
459.  static void
460.  break_armor()
461.  {
462.      register struct obj *otmp;
463.  
464.      if (breakarm(uasmon)) {
465.  	if ((otmp = uarm) != 0) {
466.  		if (donning(otmp)) cancel_don();
467.  		You("break out of your armor!");
468.  		exercise(A_STR, FALSE);
469.  		(void) Armor_gone();
470.  		useup(otmp);
471.  	}
472.  	if ((otmp = uarmc) != 0) {
473.  	    if(otmp->oartifact) {
474.  		Your("cloak falls off!");
475.  		(void) Cloak_off();
476.  		dropx(otmp);
477.  	    } else {
478.  		Your("cloak tears apart!");
479.  		(void) Cloak_off();
480.  		useup(otmp);
481.  	    }
482.  	}
483.  #ifdef TOURIST
484.  	if (uarmu) {
485.  		Your("shirt rips to shreds!");
486.  		useup(uarmu);
487.  	}
488.  #endif
489.      } else if (sliparm(uasmon)) {
490.  	if ((otmp = uarm) != 0) {
491.  		if (donning(otmp)) cancel_don();
492.  		Your("armor falls around you!");
493.  		(void) Armor_gone();
494.  		dropx(otmp);
495.  	}
496.  	if ((otmp = uarmc) != 0) {
497.  		if (is_whirly(uasmon))
498.  			Your("cloak falls, unsupported!");
499.  		else You("shrink out of your cloak!");
500.  		(void) Cloak_off();
501.  		dropx(otmp);
502.  	}
503.  #ifdef TOURIST
504.  	if ((otmp = uarmu) != 0) {
505.  		if (is_whirly(uasmon))
506.  			You("seep right through your shirt!");
507.  		else You("become much too small for your shirt!");
508.  		setworn((struct obj *)0, otmp->owornmask & W_ARMU);
509.  		dropx(otmp);
510.  	}
511.  #endif
512.      }
513.      if (nohands(uasmon) || verysmall(uasmon)) {
514.  	if ((otmp = uarmg) != 0) {
515.  	    if (donning(otmp)) cancel_don();
516.  	    /* Drop weapon along with gloves */
517.  	    You("drop your gloves%s!", uwep ? " and weapon" : "");
518.  	    drop_weapon(0);
519.  	    (void) Gloves_off();
520.  	    dropx(otmp);
521.  	}
522.  	if ((otmp = uarms) != 0) {
523.  	    You("can no longer hold your shield!");
524.  	    (void) Shield_off();
525.  	    dropx(otmp);
526.  	}
527.  	if ((otmp = uarmh) != 0) {
528.  	    if (donning(otmp)) cancel_don();
529.  	    Your("helmet falls to the %s!", surface(u.ux, u.uy));
530.  	    (void) Helmet_off();
531.  	    dropx(otmp);
532.  	}
533.      }
534.      if (nohands(uasmon) || verysmall(uasmon) || slithy(uasmon) ||
535.  		u.usym == S_CENTAUR) {
536.  	if ((otmp = uarmf) != 0) {
537.  	    if (donning(otmp)) cancel_don();
538.  	    if (is_whirly(uasmon))
539.  		Your("boots fall away!");
540.  	    else Your("boots %s off your feet!",
541.  			verysmall(uasmon) ? "slide" : "are pushed");
542.  	    (void) Boots_off();
543.  	    dropx(otmp);
544.  	}
545.      }
546.  }
547.  
548.  static void
549.  drop_weapon(alone)
550.  int alone;
551.  {
552.      struct obj *otmp;
553.      if ((otmp = uwep) != 0) {
554.  	/* !alone check below is currently superfluous but in the
555.  	 * future it might not be so if there are monsters which cannot
556.  	 * wear gloves but can wield weapons
557.  	 */
558.  	if (!alone || cantwield(uasmon)) {
559.  	    struct obj *wep = uwep;
560.  
561.  	    if (alone) You("find you must drop your weapon!");
562.  	    uwepgone();
563.  	    if (!wep->cursed || wep->otyp != LOADSTONE)
564.  		dropx(otmp);
565.  	}
566.      }
567.  }
568.  
569.  void
570.  rehumanize()
571.  {
572.  	if (emits_light(uasmon))
573.  	    del_light_source(LS_MONSTER, (genericptr_t)&youmonst);
574.  	polyman("return to %s form!", Role_is('E') ? "elven" : "human");
575.  
576.  	if (u.uhp < 1)	done(DIED);
577.  	if (!uarmg) selftouch("No longer petrify-resistant, you");
578.  	nomul(0);
579.  
580.  	flags.botl = 1;
581.  	vision_full_recalc = 1;
582.  	(void) encumber_msg();
583.  }
584.  
585.  int
586.  dobreathe() {
587.  	if (Strangled) {
588.  	    You_cant("breathe.  Sorry.");
589.  	    return(0);
590.  	}
591.  	if (!getdir((char *)0)) return(0);
592.  	if (rn2(4))
593.  	    You("produce a loud and noxious belch.");
594.  	else {
595.  	    register struct attack *mattk;
596.  	    register int i;
597.  
598.  	    for(i = 0; i < NATTK; i++) {
599.  		mattk = &(uasmon->mattk[i]);
600.  		if(mattk->aatyp == AT_BREA) break;
601.  	    }
602.  	    buzz((int) (20 + mattk->adtyp-1), (int)mattk->damn,
603.  		u.ux, u.uy, u.dx, u.dy);
604.  	}
605.  	return(1);
606.  }
607.  
608.  int
609.  dospit() {
610.  	struct obj *otmp;
611.  
612.  	if (!getdir((char *)0)) return(0);
613.  	otmp = mksobj(u.umonnum==PM_COBRA ? BLINDING_VENOM : ACID_VENOM,
614.  			TRUE, FALSE);
615.  	otmp->spe = 1; /* to indicate it's yours */
616.  	throwit(otmp);
617.  	return(1);
618.  }
619.  
620.  int
621.  doremove() {
622.  	if (!Punished) {
623.  		You("are not chained to anything!");
624.  		return(0);
625.  	}
626.  	unpunish();
627.  	return(1);
628.  }
629.  
630.  int
631.  dospinweb()
632.  {
633.  	register struct trap *ttmp = t_at(u.ux,u.uy);
634.  
635.  	if (Levitation || Is_airlevel(&u.uz)
636.  	    || Underwater || Is_waterlevel(&u.uz)) {
637.  		You("must be on the ground to spin a web.");
638.  		return(0);
639.  	}
640.  	if (u.uswallow) {
641.  		You("release web fluid inside %s.", mon_nam(u.ustuck));
642.  		if (is_animal(u.ustuck->data)) {
643.  			expels(u.ustuck, u.ustuck->data, TRUE);
644.  			return(0);
645.  		}
646.  		if (is_whirly(u.ustuck->data)) {
647.  			int i;
648.  
649.  			for (i = 0; i < NATTK; i++)
650.  				if (u.ustuck->data->mattk[i].aatyp == AT_ENGL)
651.  					break;
652.  			if (i == NATTK)
653.  			       impossible("Swallower has no engulfing attack?");
654.  			else {
655.  				char sweep[30];
656.  
657.  				sweep[0] = '\0';
658.  				switch(u.ustuck->data->mattk[i].adtyp) {
659.  					case AD_FIRE:
660.  						Strcpy(sweep, "ignites and ");
661.  						break;
662.  					case AD_ELEC:
663.  						Strcpy(sweep, "fries and ");
664.  						break;
665.  					case AD_COLD:
666.  						Strcpy(sweep,
667.  						      "freezes, shatters and ");
668.  						break;
669.  				}
670.  				pline_The("web %sis swept away!", sweep);
671.  			}
672.  			return(0);
673.  		}		     /* default: a nasty jelly-like creature */
674.  		pline_The("web dissolves into %s.", mon_nam(u.ustuck));
675.  		return(0);
676.  	}
677.  	if (u.utrap) {
678.  		You("cannot spin webs while stuck in a trap.");
679.  		return(0);
680.  	}
681.  	exercise(A_DEX, TRUE);
682.  	if (ttmp) switch (ttmp->ttyp) {
683.  		case PIT:
684.  		case SPIKED_PIT: You("spin a web, covering up the pit.");
685.  			deltrap(ttmp);
686.  			bury_objs(u.ux, u.uy);
687.  			if (Invisible) newsym(u.ux, u.uy);
688.  			return(1);
689.  		case SQKY_BOARD: pline_The("squeaky board is muffled.");
690.  			deltrap(ttmp);
691.  			if (Invisible) newsym(u.ux, u.uy);
692.  			return(1);
693.  		case TELEP_TRAP:
694.  		case LEVEL_TELEP:
695.  		case MAGIC_PORTAL:
696.  			Your("webbing vanishes!");
697.  			return(0);
698.  		case WEB: You("make the web thicker.");
699.  			return(1);
700.  		case HOLE:
701.  		case TRAPDOOR:
702.  			You("web over the %s.",
703.  			    (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole");
704.  			deltrap(ttmp);
705.  			if (Invisible) newsym(u.ux, u.uy);
706.  			return 1;
707.  		case ARROW_TRAP:
708.  		case DART_TRAP:
709.  		case BEAR_TRAP:
710.  		case LANDMINE:
711.  		case SLP_GAS_TRAP:
712.  		case RUST_TRAP:
713.  		case MAGIC_TRAP:
714.  		case ANTI_MAGIC:
715.  		case POLY_TRAP:
716.  			You("have triggered a trap!");
717.  			dotrap(ttmp);
718.  			return(1);
719.  		default:
720.  			impossible("Webbing over trap type %d?", ttmp->ttyp);
721.  			return(0);
722.  	}
723.  	ttmp = maketrap(u.ux, u.uy, WEB);
724.  	if (ttmp) {
725.  		ttmp->tseen = 1;
726.  		ttmp->madeby_u = 1;
727.  	}
728.  	if (Invisible) newsym(u.ux, u.uy);
729.  	return(1);
730.  }
731.  
732.  int
733.  dosummon()
734.  {
735.  	You("call upon your brethren for help!");
736.  	exercise(A_WIS, TRUE);
737.  	if (!were_summon(uasmon,TRUE))
738.  		pline("But none arrive.");
739.  	return(1);
740.  }
741.  
742.  int
743.  doconfuse()
744.  {
745.  	register struct monst *mtmp;
746.  	int looked = 0;
747.  	char qbuf[QBUFSZ];
748.  
749.  	if (Blind) {
750.  		You_cant("see anything to gaze at.");
751.  		return 0;
752.  	}
753.  	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
754.  	    if (canseemon(mtmp)) {
755.  		looked++;
756.  		if (Invis && !perceives(mtmp->data))
757.  		    pline("%s seems not to notice your gaze.", Monnam(mtmp));
758.  		else if (mtmp->minvis && !See_invisible)
759.  		    You_cant("see where to gaze at %s.", Monnam(mtmp));
760.  		else if (mtmp->m_ap_type == M_AP_FURNITURE
761.  			|| mtmp->m_ap_type == M_AP_OBJECT) {
762.  		    looked--;
763.  		    continue;
764.  		} else if (flags.safe_dog && !Confusion && !Hallucination
765.  		  && mtmp->mtame) {
766.  		    if (mtmp->mnamelth)
767.  			You("avoid gazing at %s.", NAME(mtmp));
768.  		    else
769.  			You("avoid gazing at your %s.",
770.  						mtmp->data->mname);
771.  		} else {
772.  		    if (flags.confirm && mtmp->mpeaceful && !Confusion
773.  							&& !Hallucination) {
774.  			Sprintf(qbuf, "Really confuse %s?", mon_nam(mtmp));
775.  			if (yn(qbuf) != 'y') continue;
776.  			setmangry(mtmp);
777.  		    }
778.  		    if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleep ||
779.  				    !mtmp->mcansee || !haseyes(mtmp->data)) {
780.  			looked--;
781.  			continue;
782.  		    }
783.  		    if (!mon_reflects(mtmp,"Your gaze is reflected by %s %s.")){
784.  			if (!mtmp->mconf)
785.  			    Your("gaze confuses %s!", mon_nam(mtmp));
786.  			else
787.  			    pline("%s is getting more and more confused.",
788.  							    Monnam(mtmp));
789.  			mtmp->mconf = 1;
790.  		    }
791.  		    if ((mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
792.  			You("are frozen by %s gaze!",
793.  			                 s_suffix(mon_nam(mtmp)));
794.  			nomul((u.ulevel > 6 || rn2(4)) ?
795.  				-d((int)mtmp->m_lev+1,
796.  					(int)mtmp->data->mattk[0].damd)
797.  				: -200);
798.  			return 1;
799.  		    }
800.  		    if ((mtmp->data==&mons[PM_MEDUSA]) && !mtmp->mcan) {
801.  			pline("Gazing at the awake Medusa is not a very good idea.");
802.  			/* as if gazing at a sleeping anything is fruitful... */
803.  			You("turn to stone...");
804.  			done(STONING);
805.  		    }
806.  		}
807.  	    }
808.  	}
809.  	if (!looked) You("gaze at no place in particular.");
810.  	return 1;
811.  }
812.  
813.  int
814.  dohide()
815.  {
816.  	if (u.uundetected || u.usym == S_MIMIC_DEF) {
817.  		You("are already hiding.");
818.  		return(0);
819.  	}
820.  	if (u.usym == S_MIMIC) {
821.  		u.usym = S_MIMIC_DEF;
822.  	} else {
823.  		u.uundetected = 1;
824.  	}
825.  	newsym(u.ux,u.uy);
826.  	return(1);
827.  }
828.  
829.  int
830.  domindblast()
831.  {
832.  	struct monst *mtmp, *nmon;
833.  
834.  	You("concentrate.");
835.  	if (rn2(3)) return 0;
836.  	pline("A wave of psychic energy pours out.");
837.  	for(mtmp=fmon; mtmp; mtmp = nmon) {
838.  		int u_sen;
839.  
840.  		nmon = mtmp->nmon;
841.  		if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM)
842.  			continue;
843.  		if(mtmp->mpeaceful)
844.  			continue;
845.  		u_sen = telepathic(mtmp->data) && !mtmp->mcansee;
846.  		if (u_sen || (telepathic(mtmp->data) && rn2(2)) || !rn2(10)) {
847.  			You("lock in on %s %s.", s_suffix(mon_nam(mtmp)),
848.  				u_sen ? "telepathy" :
849.  				telepathic(mtmp->data) ? "latent telepathy" :
850.  				"mind");
851.  			mtmp->mhp -= rnd(15);
852.  			if (mtmp->mhp <= 0)
853.  				killed(mtmp);
854.  		}
855.  	}
856.  	return 1;
857.  }
858.  
859.  static void
860.  uunstick()
861.  {
862.  	pline("%s is no longer in your clutches.", Monnam(u.ustuck));
863.  	u.ustuck = 0;
864.  }
865.  
866.  static void
867.  skinback()
868.  {
869.  	if (uskin) {
870.  		Your("skin returns to its original form.");
871.  		uarm = uskin;
872.  		uskin = (struct obj *)0;
873.  		/* undo save/restore hack */
874.  		uarm->owornmask &= ~I_SPECIAL;
875.  	}
876.  }
877.  
878.  #endif /* OVLB */
879.  #ifdef OVL1
880.  const char *
881.  body_part(part)
882.  int part;
883.  {
884.  	static NEARDATA const char
885.  	*humanoid_parts[] = { "arm", "eye", "face", "finger",
886.  		"fingertip", "foot", "hand", "handed", "head", "leg",
887.  		"light headed", "neck", "spine", "toe", "hair" },
888.  	*jelly_parts[] = { "pseudopod", "dark spot", "front",
889.  		"pseudopod extension", "pseudopod extremity",
890.  		"pseudopod root", "grasp", "grasped", "cerebral area",
891.  		"lower pseudopod", "viscous", "middle", "surface",
892.  		"pseudopod extremity", "ripples" },
893.  	*animal_parts[] = { "forelimb", "eye", "face", "foreclaw", "claw tip",
894.  		"rear claw", "foreclaw", "clawed", "head", "rear limb",
895.  		"light headed", "neck", "spine", "rear claw tip", "fur" },
896.  	*horse_parts[] = { "forelimb", "eye", "face", "forehoof", "hoof tip",
897.  		"rear hoof", "foreclaw", "hooved", "head", "rear limb",
898.  		"light headed", "neck", "backbone", "rear hoof tip", "mane" },
899.  	*sphere_parts[] = { "appendage", "optic nerve", "body", "tentacle",
900.  		"tentacle tip", "lower appendage", "tentacle", "tentacled",
901.  		"body", "lower tentacle", "rotational", "equator", "body",
902.  		"lower tentacle tip", "cilia" },
903.  	*fungus_parts[] = { "mycelium", "visual area", "front", "hypha",
904.  		"hypha", "root", "strand", "stranded", "cap area",
905.  		"rhizome", "sporulated", "stalk", "root", "rhizome tip",
906.  		"spores" },
907.  	*vortex_parts[] = { "region", "eye", "front", "minor current",
908.  		"minor current", "lower current", "swirl", "swirled",
909.  		"central core", "lower current", "addled", "center",
910.  		"currents", "edge", "currents" },
911.  	*snake_parts[] = { "vestigial limb", "eye", "face", "large scale",
912.  		"large scale tip", "rear region", "scale gap", "scale gapped",
913.  		"head", "rear region", "light headed", "neck", "length",
914.  		"rear scale", "scales" };
915.  	/* claw attacks are overloaded in mons[]; most humanoids with
916.  	   such attacks should still reference hands rather than claws */
917.  	static const char not_claws[] = {
918.  		S_HUMAN, S_MUMMY, S_ZOMBIE, S_ANGEL,
919.  		S_NYMPH, S_LEPRECHAUN, S_QUANTMECH, S_VAMPIRE,
920.  		S_ORC, S_GIANT,		/* quest nemeses */
921.  		'\0'		/* string terminator; assert( S_xxx != 0 ); */
922.  	};
923.  
924.  	if (part == HAND || part == HANDED) {	/* some special cases */
925.  	    if (u.usym == S_DOG || u.usym == S_FELINE || u.usym == S_YETI)
926.  		return part == HAND ? "paw" : "pawed";
927.  	    if (humanoid(uasmon) && attacktype(uasmon, AT_CLAW) &&
928.  		  !index(not_claws, u.usym) && u.umonnum != PM_STONE_GOLEM
929.  		  && u.umonnum != PM_INCUBUS && u.umonnum != PM_SUCCUBUS)
930.  		return part == HAND ? "claw" : "clawed";
931.  	}
932.  	if (humanoid(uasmon) && (part==ARM || part==FINGER || part==FINGERTIP
933.  		|| part==HAND || part==HANDED)) return humanoid_parts[part];
934.  	if (u.usym==S_CENTAUR || u.usym==S_UNICORN) return horse_parts[part];
935.  	if (slithy(uasmon)) return snake_parts[part];
936.  	if (u.usym==S_EYE) return sphere_parts[part];
937.  	if (u.usym==S_JELLY || u.usym==S_PUDDING || u.usym==S_BLOB)
938.  		return jelly_parts[part];
939.  	if (u.usym==S_VORTEX || u.usym==S_ELEMENTAL) return vortex_parts[part];
940.  	if (u.usym==S_FUNGUS) return fungus_parts[part];
941.  	if (humanoid(uasmon)) return humanoid_parts[part];
942.  	return animal_parts[part];
943.  }
944.  
945.  #endif /* OVL1 */
946.  #ifdef OVL0
947.  
948.  int
949.  poly_gender()
950.  {
951.  /* Returns gender of polymorphed player; 0/1=same meaning as flags.female,
952.   * 2=none.
953.   * Used in:
954.   *	- Seduction by succubus/incubus
955.   *	- Talking to nymphs (sounds.c)
956.   * Not used in:
957.   *	- Messages given by nymphs stealing armor (they can't steal from
958.   *	  incubi/succubi/nymphs, and nonhumanoids can't wear armor).
959.   *	- Amulet of change (must refer to real gender no matter what
960.   *	  polymorphed into).
961.   *	- Priest/Priestess, Caveman/Cavewoman (ditto)
962.   *	- Polymorph self (only happens when human)
963.   *	- Shopkeeper messages (since referred to as "creature" and not "sir"
964.   *	  or "lady" when polymorphed)
965.   */
966.  	if (!humanoid(uasmon)) return 2;
967.  	return flags.female;
968.  }
969.  
970.  #endif /* OVL0 */
971.  #ifdef OVLB
972.  
973.  void
974.  ugolemeffects(damtype, dam)
975.  int damtype, dam;
976.  {
977.  	int heal = 0;
978.  	/* We won't bother with "slow"/"haste" since players do not
979.  	 * have a monster-specific slow/haste so there is no way to
980.  	 * restore the old velocity once they are back to human.
981.  	 */
982.  	if (u.umonnum != PM_FLESH_GOLEM && u.umonnum != PM_IRON_GOLEM)
983.  		return;
984.  	switch (damtype) {
985.  		case AD_ELEC: if (u.umonnum == PM_IRON_GOLEM)
986.  				heal = dam / 6; /* Approx 1 per die */
987.  			break;
988.  		case AD_FIRE: if (u.umonnum == PM_IRON_GOLEM)
989.  				heal = dam;
990.  			break;
991.  	}
992.  	if (heal && (u.mh < u.mhmax)) {
993.  		u.mh += heal;
994.  		if (u.mh > u.mhmax) u.mh = u.mhmax;
995.  		flags.botl = 1;
996.  		pline("Strangely, you feel better than before.");
997.  		exercise(A_STR, TRUE);
998.  	}
999.  }
1000. 
1001. static int
1002. armor_to_dragon(atyp)
1003. int atyp;
1004. {
1005. 	switch(atyp) {
1006. 	    case GRAY_DRAGON_SCALE_MAIL:
1007. 	    case GRAY_DRAGON_SCALES:
1008. 		return PM_GRAY_DRAGON;
1009. 	    case RED_DRAGON_SCALE_MAIL:
1010. 	    case RED_DRAGON_SCALES:
1011. 		return PM_RED_DRAGON;
1012. 	    case ORANGE_DRAGON_SCALE_MAIL:
1013. 	    case ORANGE_DRAGON_SCALES:
1014. 		return PM_ORANGE_DRAGON;
1015. 	    case WHITE_DRAGON_SCALE_MAIL:
1016. 	    case WHITE_DRAGON_SCALES:
1017. 		return PM_WHITE_DRAGON;
1018. 	    case BLACK_DRAGON_SCALE_MAIL:
1019. 	    case BLACK_DRAGON_SCALES:
1020. 		return PM_BLACK_DRAGON;
1021. 	    case BLUE_DRAGON_SCALE_MAIL:
1022. 	    case BLUE_DRAGON_SCALES:
1023. 		return PM_BLUE_DRAGON;
1024. 	    case GREEN_DRAGON_SCALE_MAIL:
1025. 	    case GREEN_DRAGON_SCALES:
1026. 		return PM_GREEN_DRAGON;
1027. 	    case YELLOW_DRAGON_SCALE_MAIL:
1028. 	    case YELLOW_DRAGON_SCALES:
1029. 		return PM_YELLOW_DRAGON;
1030. 	    default:
1031. 		return -1;
1032. 	}
1033. }
1034. 
1035. #endif /* OVLB */
1036. 
1037. /*polyself.c*/