ftp.nice.ch/pub/next/games/strategic/NetHack.s.tar.gz#/NetHackSource/src/polyself.c

This is polyself.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)polyself.c 3.0	89/11/21
/* Polymorph self routine.  Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
/* NetHack may be freely redistributed.  See license for details. */

#include "hack.h"

#ifdef POLYSELF
static void NDECL(break_armor);
static void FDECL(drop_weapon,(int));
static void NDECL(skinback);
static void NDECL(uunstick);
#ifdef OVLB
static boolean sticky;
#endif /* OVLB */
#endif

#ifdef OVLB

void
newman()
{
	int tmp, tmp2;
	char buf[BUFSZ];

	if (!rn2(10)) {
		flags.female = !flags.female;
		max_rank_sz();
		if (pl_character[0] == 'P')
			Strcpy(pl_character+6, flags.female ? "ess" : "");
		if (pl_character[0] == 'C')
			Strcpy(pl_character+5, flags.female ? "woman" : "man");
	}
#ifdef POLYSELF
	if (u.umonnum != -1) {
		u.acurr = u.macurr;	/* restore old attribs */
		u.amax = u.mamax;
	}
	u.usym = S_HUMAN;
	u.umonnum = -1;
	if (u.uundetected) u.uundetected = 0;
	prme();
	u.mtimedone = u.mh = u.mhmax = 0;
#endif
	tmp = u.uhpmax;
	tmp2 = u.ulevel;
	u.ulevel = u.ulevel-2+rn2(5);
	if (u.ulevel > 127 || u.ulevel == 0) u.ulevel = 1;
	if (u.ulevel > MAXULEV) u.ulevel = MAXULEV;

	adjabil(tmp2, (int)u.ulevel);
	tmp = u.uhpmax;

	/* random experience points for the new experience level */
	u.uexp = rndexp();
#ifndef LINT
	u.uhpmax = (u.uhpmax-10)*(long)u.ulevel/tmp2 + 19 - rn2(19);
#endif
/* If it was u.uhpmax*u.ulevel/tmp+9-rn2(19), then a 1st level character
   with 16 hp who polymorphed into a 3rd level one would have an average
   of 48 hp.  */
#ifdef LINT
	u.uhp = u.uhp + tmp;
#else
	u.uhp = u.uhp * (long)u.uhpmax/tmp;
#endif
#ifdef SPELLS
	tmp = u.uenmax;
#  ifndef LINT
	u.uenmax = u.uenmax * (long)u.ulevel/tmp2 + 9 - rn2(19);
#  endif
	if (u.uenmax < 0) u.uenmax = 0;
#  ifndef LINT
	u.uen = (tmp ? u.uen * (long)u.uenmax / tmp : u.uenmax);
#  endif
#endif
	redist_attr();
	u.uhunger = rn1(500,500);
	Sick = 0;
	Stoned = 0;
	if (u.uhp <= 0 || u.uhpmax <= 0) {
#ifdef POLYSELF
		if(Polymorph_control) {
		    if (u.uhp <= 0) u.uhp = 1;
		    if (u.uhpmax <= 0) u.uhpmax = 1;
		} else {
#endif
		    Your("new form doesn't seem healthy enough to survive.");
		    killer_format = KILLED_BY_AN;
		    killer="unsuccessful polymorph";
		    done(DIED);
#ifdef POLYSELF
		}
#endif
	}
#ifdef POLYSELF
	set_uasmon();
#endif
	You("feel like a new %sman!", flags.female ? "wo" : "");
#ifdef WIZARD
	if(!wizard) {
#endif
newname:	more();
		do {
		    pline("What is your new name? ");
		    getlin(buf);
		} while (buf[0]=='\033' || buf[0]==0);
		if (!strcmp(plname,buf)) {
		    pline("That is the same as your old name!");
		    goto newname;
		}
		(void)strncpy(plname, buf, sizeof(plname)-1);
#ifdef VMS
		Sprintf(SAVEF, "[.save]%d%s", getuid(), plname);
		regularize(SAVEF+7);
		Strcat(SAVEF, ";1");
#else
# ifdef MSDOS
		(void)strcpy(SAVEF, SAVEP);
		{
			int i = strlen(SAVEF);
			(void)strncat(SAVEF, plname, 8);
			regularize(SAVEF+i);
		}
		(void)strcat(SAVEF, ".sav");
# else
		Sprintf(SAVEF, "save/%d%s", getuid(), plname);
		regularize(SAVEF+5);		/* avoid . or / in name */
# endif
#endif
#ifdef WIZARD
	}
#endif
	flags.botl = 1;
#ifdef POLYSELF
	skinback();
	find_ac();
	if (sticky) uunstick();
#endif
}

#ifdef POLYSELF
void
polyself()
{
	char buf[BUFSZ];
	int mntmp = -1;
	int tries=0;
	boolean draconian = (uarm && uarm->otyp==DRAGON_SCALE_MAIL &&
		uarm->corpsenm >= PM_GRAY_DRAGON &&
		uarm->corpsenm <= PM_YELLOW_DRAGON);
	boolean iswere = (u.ulycn > -1 || is_were(uasmon));
	boolean isvamp = (u.usym == S_VAMPIRE || u.umonnum == PM_VAMPIRE_BAT);
	/* We have to calculate sticky in multiple places since we might go
	 * through any one of them without going through the others.
	 */
	sticky = sticks(uasmon) && u.ustuck && !u.uswallow;

	if(!Polymorph_control && !draconian && !iswere && !isvamp) {
	    if (rn2(20) > ACURR(A_CON)) {
		You("shudder for a moment.");
		losehp(rn2(30),"system shock", KILLED_BY_AN);
		return;
	    }
	}

	if (Polymorph_control) {
		do {
			pline("Become what kind of monster? [type the name] ");
			getlin(buf);
			mntmp = name_to_mon(buf);
			if (mntmp < 0)
				pline("I've never heard of such monsters.");
			else if (!polyok(&mons[mntmp]))
				You("cannot polymorph into that.");
			else break;
		} while(++tries < 5);
		if (tries==5) pline(thats_enough_tries);
	} else if (draconian || iswere || isvamp) {
		/* special changes that don't require polyok() */
		if (draconian) {
			mntmp = uarm->corpsenm;
			if (!(mons[mntmp].geno & G_GENOD)) {
				You("merge with your scaly armor.");
				uskin = uarm;
				uarm = (struct obj *)0;
			}
		} else if (iswere) {
			if (is_were(uasmon))
				mntmp = PM_HUMAN; /* Illegal; force newman() */
			else
				mntmp = u.ulycn;
		} else {
			if (u.usym == S_VAMPIRE)
				mntmp = PM_VAMPIRE_BAT;
			else
				mntmp = PM_VAMPIRE;
		}
		if (polymon(mntmp))
			return;
	}

	if (mntmp < 0) {
		tries = 0;
		do {
			mntmp = rn2(PM_ARCHEOLOGIST);
			/* All valid monsters are from 0 to PM_ARCHEOLOGIST-1 */
		} while(!polyok(&mons[mntmp]) && tries++ < 200);
	}

	/* The below polyok() fails either if everything is genocided, or if
	 * we deliberately chose something illegal to force newman().
	 */
	if (!polyok(&mons[mntmp]) || !rn2(5))
		newman();
	else if(!polymon(mntmp)) return;

	if (!uarmg) selftouch("No longer petrify-resistant, you");
	if (Inhell && !Fire_resistance) {
	    You("burn to a crisp.");
	    killer_format = KILLED_BY;
	    killer = "losing fire resistance after polymorphing";
	    while(1) {
		done(BURNING);
		You("continue burning.");
	    }
	}
}

int
polymon(mntmp)	/* returns 1 if polymorph successful */
	int	mntmp;
{
	int	tmp;
	sticky = sticks(uasmon) && u.ustuck && !u.uswallow;

	if (mons[mntmp].geno & G_GENOD) {
		You("feel rather %s-ish.",mons[mntmp].mname);
		return(0);
	}

	if (u.umonnum == -1) {
		/* Human to monster; save human stats */
		u.macurr = u.acurr;
		u.mamax = u.amax;
	} else {
		/* Monster to monster; restore human stats, to be
		 * immediately changed to provide stats for the new monster
		 */
		u.acurr = u.macurr;
		u.amax = u.mamax;
	}
	tmp = u.umonnum;
	u.umonnum = mntmp;
	set_uasmon();
	u.usym = mons[mntmp].mlet;

	if (tmp != mntmp)
		You("turn into %s!", an(mons[mntmp].mname));
	else
		You("feel like a new %s!", mons[mntmp].mname);

	/* New stats for monster, to last only as long as polymorphed.
	 * Currently only strength gets changed.
	 */
	if(strongmonst(&mons[mntmp])) ABASE(A_STR) = AMAX(A_STR) = 118;

	if (resists_ston(uasmon) && Stoned) { /* parnes@eniac.seas.upenn.edu */
		Stoned = 0;
		You("no longer seem to be petrifying.");
	}
	if (u.usym == S_FUNGUS && Sick) {
		Sick = 0;
		You("no longer feel sick.");
	}
	if (u.usym == S_DRAGON && mntmp >= PM_GRAY_DRAGON) u.mhmax = 80;
#ifdef GOLEMS
	else if (is_golem(uasmon)) u.mhmax = golemhp(mntmp);
#endif /* GOLEMS */
	else {

		/*
		tmp = adj_lev(&mons[mntmp]);
		 * We can't do this, since there's no such thing as an
		 * "experience level of you as a monster" for a polymorphed
		 * character.
		 */
		tmp = mons[mntmp].mlevel;
		if (!tmp) u.mhmax = rnd(4);
		else u.mhmax = d(tmp, 8);
	}
	u.mh = u.mhmax;
	if (uskin && mntmp != uskin->corpsenm)
		skinback();
	break_armor();
	drop_weapon(1);
	if (u.uundetected && !hides_under(uasmon)) u.uundetected = 0;
	else if (hides_under(uasmon) && (OBJ_AT(u.ux, u.uy) ||
			levl[u.ux][u.uy].gmask))
		u.uundetected = 1;
	prme();
	if (!sticky && !u.uswallow && u.ustuck && sticks(uasmon)) u.ustuck = 0;
	else if (sticky && !sticks(uasmon)) uunstick();
	u.mtimedone = 500 + rn2(500);
	if (u.ulevel < mons[mntmp].mlevel)
	/* Low level characters can't become high level monsters for long */
		u.mtimedone = u.mtimedone * u.ulevel / mons[mntmp].mlevel;
	flags.botl = 1;
	if (flags.verbose) {
	    if (can_breathe(uasmon))
		pline("Use the command #monster to use your breath weapon.");
	    if (attacktype(uasmon, AT_SPIT))
		pline("Use the command #monster to spit venom.");
	    if (u.usym == S_NYMPH)
		pline("Use the command #monster to remove an iron ball.");
	    if (u.usym == S_UMBER)
		pline("Use the command #monster to confuse monsters.");
	    if (is_hider(uasmon))
		pline("Use the command #monster to hide.");
	    if (is_were(uasmon))
		pline("Use the command #monster to summon help.");
	    if (webmaker(uasmon))
		pline("Use the command #monster to spin a web.");
	    if (u.usym == S_UNICORN)
		pline("Use the command #monster to use your horn.");
	    if (lays_eggs(uasmon) || u.umonnum == PM_QUEEN_BEE)
		pline("Use the command #sit to lay an egg.");
	}
	find_ac();
	return(1);
}

static void
break_armor() {
     struct obj *otmp;

     if (breakarm(uasmon)) {
	if (otmp = uarm) {
		if (donning(otmp)) cancel_don();
		You("break out of your armor!");
		(void) Armor_gone();
		useup(otmp);
	}
	if (otmp = uarmc) {
		Your("cloak tears apart!");
		(void) Cloak_off();
		useup(otmp);
	}
#ifdef SHIRT
	if (uarmu) {
		Your("shirt rips to shreds!");
		useup(uarmu);
	}
#endif
     } else if (sliparm(uasmon)) {
	if (otmp = uarm) {
		if (donning(otmp)) cancel_don();
		Your("armor falls around you!");
		(void) Armor_gone();
		dropx(otmp);
	}
	if (otmp = uarmc) {
		You("shrink out of your cloak!");
		(void) Cloak_off();
		dropx(otmp);
	}
#ifdef SHIRT
	if (otmp = uarmu) {
		You("become much too small for your shirt!");
		setworn((struct obj *)0, otmp->owornmask & W_ARMU);
		dropx(otmp);
	}
#endif
     }
     if (nohands(uasmon) || verysmall(uasmon)) {
	  if (otmp = uarmg) {
	       if (donning(otmp)) cancel_don();
	       /* Drop weapon along with gloves */
	       You("drop your gloves%s!", uwep ? " and weapon" : "");
	       drop_weapon(0);
	       (void) Gloves_off();
	       dropx(otmp);
	  }
	  if (otmp = uarms) {
	       You("can no longer hold your shield!");
	       (void) Shield_off();
	       dropx(otmp);
	  }
	  if (otmp = uarmh) {
	       if (donning(otmp)) cancel_don();
	       Your("helmet falls to the floor!");
	       (void) Helmet_off();
	       dropx(otmp);
	  }
	  if (otmp = uarmf) {
	       if (donning(otmp)) cancel_don();
	       Your("boots %s off your feet!",
			verysmall(uasmon) ? "slide" : "are pushed");
	       (void) Boots_off();
	       dropx(otmp);
	  }
     }
}

static void
drop_weapon(alone)
int alone;
{
     struct obj *otmp;
     if (otmp = uwep) {
	  /* !alone check below is currently superfluous but in the
	   * future it might not be so if there are monsters which cannot
	   * wear gloves but can wield weapons
	   */
	  if (!alone || cantwield(uasmon)) {
	       if (alone) You("find you must drop your weapon!");
	       uwepgone();
	       dropx(otmp);
	  }
     }
}

void
rehumanize()
{
	sticky = sticks(uasmon) && u.ustuck && !u.uswallow;

	u.mh = u.mhmax = u.mtimedone = 0;
 	u.acurr = u.macurr;		/* restore old strength */
 	u.amax = u.mamax;
	u.usym = S_HUMAN;
	u.umonnum = -1;
	skinback();
	set_uasmon();
	You("return to %sn form!", (pl_character[0] == 'E')? "elve" : "huma");

	if (u.uhp < 1)	done(DIED);
	if (!Fire_resistance && Inhell) {
	    You("burn to a crisp.");
	    killer_format = KILLED_BY;
	    killer = "losing fire resistance after rehumanization";
	    while(1) {
		done(BURNING);
		You("continue burning.");
	    }
	}
	if (!uarmg) selftouch("No longer petrify-resistant, you");
	if (sticky) uunstick();
	nomul(0);
	if (u.uundetected) u.uundetected = 0;
	prme();
	flags.botl = 1;
	find_ac();
}

int
dobreathe() {
	if(!getdir(1)) return(0);
	if (rn2(4))
	    You("produce a loud and noxious belch.");
	else {
	    register struct attack *mattk;
	    register int i;

	    for(i = 0; i < NATTK; i++) {
		mattk = &(uasmon->mattk[i]);
		if(mattk->aatyp == AT_BREA) break;
	    }
	    buzz((int) (20 + mattk->adtyp-1), (int)mattk->damn,
		u.ux, u.uy, u.dx, u.dy);
	}
	return(1);
}

int
dospit() {
	struct obj *otmp;

	if (!getdir(1)) return(0);
	otmp = mksobj(u.umonnum==PM_COBRA ? BLINDING_VENOM : ACID_VENOM, FALSE);
	otmp->spe = 1; /* to indicate it's yours */
	(void) throwit(otmp);
	return(1);
}

int
doremove() {
     if (!Punished) {
	  You("are not chained to anything!");
	  return(0);
     }
     unpunish();
     return(1);
}

int
dospinweb() {
	register struct trap *ttmp = t_at(u.ux,u.uy);

	if (Levitation) {
		You("must be on the ground to spin a web.");
		return(0);
	}
	if (u.uswallow) {
		You("release web fluid inside %s.", mon_nam(u.ustuck));
		if (is_animal(u.ustuck->data)) {
			expels(u.ustuck, u.ustuck->data, TRUE);
			return(0);
		}
		if (is_whirly(u.ustuck->data)) {
			int i;

			for (i = 0; i < NATTK; i++)
				if (u.ustuck->data->mattk[i].aatyp == AT_ENGL)
					break;
			if (i == NATTK)
			       impossible("Swallower has no engulfing attack?");
			else {
				char sweep[30];

				sweep[0] = '\0';
				switch(u.ustuck->data->mattk[i].adtyp) {
					case AD_FIRE:
						Strcpy(sweep, "ignites and ");
						break;
					case AD_ELEC:
						Strcpy(sweep, "fries and ");
						break;
					case AD_COLD:
						Strcpy(sweep,
						      "freezes, shatters and ");
						break;
				}
				pline("The web %sis swept away!", sweep);
			}
			return(0);
		}		     /* default: a nasty jelly-like creature */ 
		pline("The web dissolves into %s.", mon_nam(u.ustuck));
		return(0);
	}
	if (u.utrap) {
		You("cannot spin webs while stuck in a trap.");
		return(0);
	}
	if (ttmp) switch (ttmp->ttyp) {
		case SPIKED_PIT:
		case PIT: You("spin a web, covering up the pit.");
			deltrap(ttmp);
			if (Invisible) newsym(u.ux, u.uy);
			return(1);
		case WEB: You("make the web thicker.");
			return(1);
		case SQBRD: pline("The squeaky board is muffled.");
			deltrap(ttmp);
			if (Invisible) newsym(u.ux, u.uy);
			return(1);
		case TELEP_TRAP:
		case LEVEL_TELEP:
			Your("webbing vanishes!");
			return(0);
		case TRAPDOOR: if (!is_maze_lev) {
				You("web over the trap door.");
				deltrap(ttmp);
				if (Invisible) newsym(u.ux, u.uy);
				return 1;
			}
			/* Fall through */
		case MGTRP:
		case POLY_TRAP:
		case DART_TRAP:
		case ARROW_TRAP:
#ifdef SPELLS
		case ANTI_MAGIC:
#endif
		case LANDMINE:
		case SLP_GAS_TRAP:
		case BEAR_TRAP:
		case RUST_TRAP:
			You("have triggered a trap!");
			dotrap(ttmp);
			return(1);
		default:
			impossible("Webbing over trap type %d?", ttmp->ttyp);
			return(0);
	}
	ttmp = maketrap(u.ux, u.uy, WEB);
	ttmp->tseen = 1;
	if (Invisible) newsym(u.ux, u.uy);
	return(1);
}

int
dosummon()
{
	You("call upon your brethren for help!");
	if (!were_summon(uasmon,TRUE))
		pline("But none arrive.");
	return(1);
}

int
doconfuse()
{
	register struct monst *mtmp;
	int looked = 0;

	if (Blind) {
		You("can't see anything to gaze at.");
		return 0;
	}
	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
	    if (canseemon(mtmp)) {
		looked = 1;
		if (Invis && !perceives(mtmp->data))
		    pline("%s seems not to notice your gaze.", Monnam(mtmp));
		else if (mtmp->minvis && !See_invisible)
		    You("can't see where to gaze at %s.", Monnam(mtmp));
		else if (mtmp->mimic)
		    continue;
		else if (flags.safe_dog && !Confusion && !Hallucination
		  && mtmp->mtame) {
		    if (mtmp->mnamelth)
			You("avoid gazing at %s.", NAME(mtmp));
		    else
			You("avoid gazing at your %s.",
						mtmp->data->mname);
		} else {
		    if (flags.confirm && mtmp->mpeaceful && !Confusion
							&& !Hallucination) {
#ifdef MACOS
			char mac_tbuf[80];
			if(!flags.silent) SysBeep(1);
			sprintf(mac_tbuf, "Really confuse %s?", mon_nam(mtmp));
			if(UseMacAlertText(128, mac_tbuf) != 1) continue;
#else
			pline("Really confuse %s? ", mon_nam(mtmp));
			(void) fflush(stdout);
			if (yn() != 'y') continue;
#endif
			setmangry(mtmp);
		    }
		    if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleep ||
							!mtmp->mcansee)
			continue;
		    if (!mtmp->mconf)
			Your("gaze confuses %s!", mon_nam(mtmp));
		    else
			pline("%s is getting more and more confused.",
							Monnam(mtmp));
		    mtmp->mconf = 1;
		    if ((mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
			You("are frozen by %s's gaze!", mon_nam(mtmp));
			nomul((u.ulevel > 6 || rn2(4)) ? 
				-d((int)mtmp->m_lev+1,
					(int)mtmp->data->mattk[0].damd)
				: -200);
			return 1;
		    }
#ifdef MEDUSA
		    if ((mtmp->data==&mons[PM_MEDUSA]) && !mtmp->mcan) {
			pline("Gazing at the awake Medusa is not a very good idea.");
			/* as if gazing at a sleeping anything is fruitful... */
			You("turn to stone...");
			done(STONING);
		    }
#endif
		}
	    }
	}
	if (!looked) You("gaze at no place in particular.");
	return 1;
}

int
dohide()
{
	if (u.uundetected || u.usym == S_MIMIC_DEF) {
		You("are already hiding.");
		return(0);
	}
	if (u.usym == S_MIMIC) {
		u.usym = S_MIMIC_DEF;
		prme();
	} else {
		newsym(u.ux,u.uy);
		u.uundetected = 1;
	}
	return(1);
}

static void
uunstick()
{
	kludge("%s is no longer in your clutches.", Monnam(u.ustuck));
	u.ustuck = 0;
}

static void
skinback()
{
	if (uskin) {
		Your("skin returns to its original form.");
		uarm = uskin;
		uskin = (struct obj *)0;
	}	
}
#endif

const char *
body_part(part)
int part;
{
	/* Note: it is assumed these will never be >22 characters long,
	 * plus the trailing null, after pluralizing (since sometimes a
	 * buffer is made a fixed size and must be able to hold it)
	 */
	static const char *humanoid_parts[] = { "arm", "eye", "face", "finger",
		"fingertip", "foot", "hand", "handed", "head", "leg",
                "light headed", "neck", "spine", "toe" };
#ifdef POLYSELF
	static const char *jelly_parts[] = { "pseudopod", "dark spot", "front",
		"pseudopod extension", "pseudopod extremity",
		"pseudopod root", "grasp", "grasped", "cerebral area",
		"lower pseudopod", "viscous", "middle", "surface",
		"pseudopod extremity" },
	*animal_parts[] = { "forelimb", "eye", "face", "foreclaw", "claw tip",
		"rear claw", "foreclaw", "clawed", "head", "rear limb",
		"light headed", "neck", "spine", "rear claw tip" },
	*horse_parts[] = { "forelimb", "eye", "face", "forehoof", "hoof tip",
		"rear hoof", "foreclaw", "hooved", "head", "rear limb",
		"light headed", "neck", "backbone", "rear hoof tip" },
	*sphere_parts[] = { "appendage", "optic nerve", "body", "tentacle",
		"tentacle tip", "lower appendage", "tentacle", "tentacled",
		"body", "lower tentacle", "rotational", "equator", "body",
		"lower tentacle tip" },
	*fungus_parts[] = { "mycelium", "visual area", "front", "hypha",
		"hypha", "root", "strand", "stranded", "cap area",
		"rhizome", "sporulated", "stalk", "root", "rhizome tip" },
	*vortex_parts[] = { "region", "eye", "front", "minor current",
		"minor current", "lower current", "swirl", "swirled",
		"central core", "lower current", "addled", "center",
		"currents", "edge" },
	*snake_parts[] = { "vestigial limb", "eye", "face", "large scale",
		"large scale tip", "rear region", "scale gap", "scale gapped",
		"head", "rear region", "light headed", "neck", "length",
		"rear scale" };
	
	if (humanoid(uasmon) || (u.usym==S_CENTAUR && 
		(part==ARM || part==FINGER || part==FINGERTIP
		|| part==HAND || part==HANDED))) return humanoid_parts[part];
	if (u.usym==S_CENTAUR || u.usym==S_UNICORN) return horse_parts[part];
	if (u.usym==S_SNAKE || u.usym==S_NAGA || u.usym==S_WORM)
		return snake_parts[part];
	if (u.usym==S_EYE) return sphere_parts[part];
	if (u.usym==S_JELLY || u.usym==S_PUDDING || u.usym==S_BLOB)
		return jelly_parts[part];
	if (u.usym==S_VORTEX || u.usym==S_ELEMENTAL) return vortex_parts[part];
	if (u.usym==S_FUNGUS) return fungus_parts[part];
	return animal_parts[part];
#else
	return humanoid_parts[part];
#endif
}

#endif /* OVLB */
#ifdef OVL0

int
poly_gender()
{
/* Returns gender of polymorphed player; 0/1=same meaning as flags.female,
 * 2=none.
 * Used in:
 *	- Seduction by succubus/incubus
 *	- Talking to nymphs (sounds.c)
 * Not used in:
 *	- Messages given by nymphs stealing armor (they can't steal from
 *	  incubi/succubi/nymphs, and nonhumanoids can't wear armor).
 *	- Amulet of change (must refer to real gender no matter what
 *	  polymorphed into).
 *	- Priest/Priestess, Caveman/Cavewoman (ditto)
 *	- Polymorph self (only happens when human)
 *	- Shopkeeper messages (since referred to as "creature" and not "sir"
 *	  or "lady" when polymorphed)
 */
#ifdef POLYSELF
	if (uasmon->mflags2 & M2_FEM) return 1;
# ifdef INFERNO
	if (u.umonnum == PM_INCUBUS) return 0;
# endif
	if (!humanoid(uasmon)) return 2;
#endif
	return flags.female;
}

#endif /* OVL0 */
#ifdef OVLB

#if defined(POLYSELF) && defined(GOLEMS)
void
ugolemeffects(damtype, dam)
int damtype, dam;
{
	int heal = 0;
	/* We won't bother with "slow"/"haste" since players do not
	 * have a monster-specific slow/haste so there is no way to
	 * restore the old velocity once they are back to human.
	 */
	if (u.umonnum != PM_FLESH_GOLEM && u.umonnum != PM_IRON_GOLEM)
		return;
	switch (damtype) {
		case AD_ELEC: if (u.umonnum == PM_IRON_GOLEM)
				heal = dam / 6; /* Approx 1 per die */
			break;
		case AD_FIRE: if (u.umonnum == PM_IRON_GOLEM)
				heal = dam;
			break;
	}
	if (heal && (u.mh < u.mhmax)) {
		u.mh += heal;
		if (u.mh > u.mhmax) u.mh = u.mhmax;
		flags.botl = 1;
		pline("Strangely, you feel better than before.");
	}
}
#endif /* POLYSELF && GOLEMS */

#endif /* OVLB */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.