[comp.sources.games] v07i073: NetHack3 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/24/89)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 73
Archive-name: NetHack3/Part18



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 18 (of 38)."
# Contents:  src/artifact.c src/makemon.c src/options.c
# Wrapped by billr@saab on Sun Jul 23 21:33:01 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/artifact.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/artifact.c'\"
else
echo shar: Extracting \"'src/artifact.c'\" \(6525 characters\)
sed "s/^X//" >'src/artifact.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)artifact.c	3.0	88/07/27
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X
X#ifdef NAMED_ITEMS
X
X#include "artifact.h"
X
X/* the artifacts (currently weapons only) */
Xstatic const struct artifact artilist[] = {
X
X#define	    NO_ATTK	0, 0, 0, 0
X
X{ LONG_SWORD,	 "Excalibur",	(SPFX_NOGEN | SPFX_SEEK | SPFX_DEFN |
X								SPFX_SEARCH), 0,
X  { 0, AD_PHYS, 5, 10 }, { 0, AD_DRLI, 0, 0} },
X
X{ KATANA,	 "Snickersnee",	SPFX_RESTR, 0,
X  { 0, AD_PHYS, 0, 8 }, NO_ATTK },
X
X/*	Ah, never shall I forget the cry, 
X *		or the shriek that shrieked he,
X *	As I gnashed my teeth, and from my sheath
X *		I drew my Snickersnee!
X *
X *		--Koko, Lord high executioner of Titipu
X *		  (From Sir W.S. Gilbert's "The Mikado")
X */
X
X{ AXE,		 "Cleaver",	SPFX_RESTR, 0,
X  { 0, AD_PHYS, 3, 12 }, NO_ATTK },
X
X/*  Special purpose swords - various types */
X
X{ TWO_HANDED_SWORD, "Orcrist",	SPFX_DCLAS, S_ORC,
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X#ifdef TOLKIEN
X{ ELVEN_DAGGER,	 "Sting",	(SPFX_WARN | SPFX_DCLAS), S_ORC,
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X#else
X{ DAGGER,	 "Sting",	(SPFX_WARN | SPFX_DCLAS), S_ORC,
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X#endif
X
X{ LONG_SWORD,	 "Frost Brand", (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0,
X  { 0, AD_COLD, 5, 0 }, { 0, AD_COLD, 0, 0 } },
X
X{ LONG_SWORD,	 "Fire Brand",	(SPFX_RESTR | SPFX_ATTK | SPFX_DEFN), 0,
X  { 0, AD_FIRE, 5, 0 }, { 0, AD_FIRE, 0, 0 } },
X
X/* Stormbringer only has a 2 because it can drain a level, providing 8 more */
X{ BROADSWORD,	 "Stormbringer", (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN |
X								SPFX_DRLI), 0,
X  { 0, AD_DRLI, 5, 2 }, { 0, AD_DRLI, 0, 0 } },
X
X{ LONG_SWORD,	 "Sunsword",	(SPFX_RESTR | SPFX_DCLAS), 0, /* undead */
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X{ BROADSWORD,	 "Dragonbane",	(SPFX_RESTR | SPFX_DCLAS), S_DRAGON,
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X{ LONG_SWORD,	 "Demonbane",	(SPFX_RESTR | SPFX_DCLAS), 0, /* demons */
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X{ LONG_SWORD,	 "Werebane",	(SPFX_RESTR | SPFX_DCLAS), 0, /* weres */
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X{ LONG_SWORD,	 "Giantslayer", (SPFX_RESTR | SPFX_DCLAS), 0, /* giants */
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X{ LUCERN_HAMMER, "Ogresmasher",	(SPFX_RESTR | SPFX_DCLAS),  S_OGRE,
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X{ LUCERN_HAMMER, "Thunderfist",	(SPFX_RESTR | SPFX_ATTK),  0,
X  { 0, AD_ELEC, 5, 24 }, NO_ATTK },
X
X{ MORNING_STAR,	 "Trollsbane", (SPFX_RESTR | SPFX_DCLAS), S_TROLL,
X  { 0, AD_PHYS, 5, 0 }, NO_ATTK },
X
X/*	ARRAY TERMINATOR	*/
X{ 0,  "", 0, 0, NO_ATTK, NO_ATTK }
X};
X
Xvoid
Xmkartifact(otmp1)
Xstruct obj **otmp1;
X{
X	register struct artifact *artif;
X	register struct obj *otmp = *otmp1;
X	register int n = 0;
X
X	for(artif = artilist; artif->otyp; artif++)
X	    if(otmp->otyp == artif->otyp && !(artif->spfx & SPFX_NOGEN)) n++;
X
X	if (n) {
X		n = rnd(n);
X		for(artif = artilist; artif->otyp && n > 0; ) {
X		    if(otmp->otyp == artif->otyp && !(artif->spfx & SPFX_NOGEN)) n--;
X		    if (n>0) artif++;
X		}
X
X		if(artif->otyp) *otmp1 = oname(otmp, artif->name, 0);
X	}
X}
X
Xstatic struct artifact *
Xget_artifact(otmp)
Xstruct obj *otmp;
X{
X	register struct artifact *artif;
X
X	if(otmp)
X	    if(strlen(ONAME(otmp)))
X		for(artif = artilist; artif->otyp; artif++)
X		    if(artif->otyp == otmp->otyp &&
X		       !strcmp(ONAME(otmp), artif->name)) return(artif);
X	return((struct artifact *)0);
X}
X
Xboolean
Xis_artifact(otmp)
Xstruct obj *otmp;
X{
X	return(get_artifact(otmp) != (struct artifact *)0);
X}
X
Xboolean
Xspec_ability(otmp, abil)
Xstruct obj *otmp;
Xunsigned abil;
X{
X	struct artifact *arti = get_artifact(otmp);
X	
X	return(arti && (arti->spfx & abil));
X}
X
Xint
Xrestr_name(otmp, name)	/* returns 1 if name is restricted for otmp->otyp */
Xregister struct obj *otmp;
Xregister char	*name;
X{
X	register struct artifact *artif;
X
X	if(!strlen(name)) return(0);
X
X	for(artif = artilist; artif->otyp; artif++)
X	    if(artif->otyp == otmp->otyp)
X		if(artif->spfx & (SPFX_NOGEN | SPFX_RESTR))
X		    if(!strcmp(artif->name, name)) return(1);
X
X	return(0);
X}
X
X# if defined(THEOLOGY) && defined(ALTARS)
Xstruct obj *
Xmk_aligned_artifact(align)
Xint align;
X{
X	register struct artifact *artif;
X	register struct obj *otmp;
X	register int n = 0;
X
X	for(artif = artilist; artif->otyp; artif++)
X	    if(align == artif->align && !(artif->spfx & SPFX_NOGEN)) n++;
X	if (n) {
X		n = rnd(n);
X		for(artif = artilist; artif->otyp && n > 0; ) {
X		    if(align == artif->align && !(artif->spfx & SPFX_NOGEN))
X			n--;
X		    if (n > 0) artif++;
X		}
X		if(artif->otyp) {
X			otmp = mksobj((int)artif->otyp, FALSE);
X			otmp = oname(otmp, artif->name, 0);
X			return (otmp);
X		}
X	}
X	return ((struct obj *) 0);
X}
X# endif
X
Xint
Xdefends(adtyp, otmp)
Xregister int adtyp;
Xregister struct obj *otmp;
X{
X	register struct artifact *weap;
X
X	if(weap = get_artifact(otmp))
X		return(weap->defn.adtyp == adtyp);
X	return(0);
X}
X
Xstatic int
Xspec_applies(weap, ptr)
Xregister struct artifact *weap;
Xstruct permonst *ptr;
X{
X	if(!(weap->spfx & (SPFX_DMONS | SPFX_DCLAS | SPFX_ATTK)))
X	    return(1);
X
X	if(weap->spfx & SPFX_DMONS)
X	    return((ptr == &mons[weap->mtype]));
X	else if(weap->spfx & SPFX_DCLAS) {
X
X	    if(weap->mtype)
X		return((weap->mtype == ptr->mlet));
X	    else {
X		if(!strcmp(weap->name, "Sunsword"))
X		    return(is_undead(ptr));
X		else if(!strcmp(weap->name, "Demonbane"))
X		    return(is_demon(ptr));
X		else if(!strcmp(weap->name, "Werebane"))
X		    return(is_were(ptr));
X		else if(!strcmp(weap->name, "Giantslayer"))
X		    return(is_giant(ptr));
X		else impossible("Weird class specific weapon '%s'",
X				weap->name);
X	    }
X	} else if(weap->spfx & SPFX_ATTK) {
X	    switch(weap->attk.adtyp) {
X		case AD_FIRE:	return(!resists_fire(ptr));
X		case AD_COLD:	return(!resists_cold(ptr));
X		case AD_ELEC:	return(!resists_elec(ptr));
X		case AD_DRLI:	return(!resists_drli(ptr));
X		case AD_STON:	return(!resists_ston(ptr));
X		default:	impossible("Weird special attack for '%s'",
X					   weap->name);
X	    }
X	}
X	return(0);
X}
X
Xint
Xspec_abon(otmp, ptr)
Xstruct obj *otmp;
Xstruct permonst *ptr;
X{
X	register struct artifact *weap;
X
X	if((weap = get_artifact(otmp)))
X		if(spec_applies(weap, ptr))
X		    return((weap->attk.damn) ? rnd((int)weap->attk.damn) : 0);
X	return(0);
X}
X
Xint
Xspec_dbon(otmp, ptr, tmp)
Xregister struct obj *otmp;
Xregister struct permonst *ptr;
Xregister int	tmp;
X{
X	register struct artifact *weap;
X
X	if((weap = get_artifact(otmp)))
X		if(spec_applies(weap, ptr))
X		    return((weap->attk.damd) ? rnd((int)weap->attk.damd) : tmp);
X	return(0);
X}
X#endif /* NAMED_ITEMS */
END_OF_FILE
if test 6525 -ne `wc -c <'src/artifact.c'`; then
    echo shar: \"'src/artifact.c'\" unpacked with wrong size!
fi
# end of 'src/artifact.c'
fi
if test -f 'src/makemon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/makemon.c'\"
else
echo shar: Extracting \"'src/makemon.c'\" \(28290 characters\)
sed "s/^X//" >'src/makemon.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)makemon.c	3.0	88/04/11
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include	"hack.h"
X
Xstruct monst zeromonst;
Xstatic int uncommon P((struct permonst *));
X
Xstatic int monstr[NUMMONS];
X
X#define m_initsgrp(mtmp, x, y) m_initgrp(mtmp, x, y, 3)
X#define m_initlgrp(mtmp, x, y) m_initgrp(mtmp, x, y, 10)
X#define toostrong(monindx, lev) (monstr[monindx] > lev)
X#define tooweak(monindx, lev)	(monstr[monindx] < lev)
X
Xstatic void
Xm_initgrp(mtmp, x, y, n)	/* make a group just like mtmp */
Xregister struct monst *mtmp;
Xregister int x, y, n;
X{
X	coord mm;
X	register int cnt = rnd(n);
X	struct monst *mon;
X
X	mm.x = x;
X	mm.y = y;
X	while(cnt--) {
X		if (peace_minded(mtmp->data)) continue;
X		/* Don't create groups of peaceful monsters since they'll get
X		 * in our way.  If the monster has a percentage chance so some
X		 * are peaceful and some are not, the result will just be a
X		 * smaller group.
X		 */
X		enexto(&mm, mm.x, mm.y);
X		mon = makemon(mtmp->data, mm.x, mm.y);
X		mon->mpeaceful = 0;
X		set_malign(mon);
X		/* Undo the second peace_minded() check in makemon(); if the
X		 * monster turned out to be peaceful the first time we didn't
X		 * create it at all; we don't want a second check.
X		 */
X	}
X}
X
Xstatic void
Xm_initthrow(mtmp,otyp,oquan)
Xstruct monst *mtmp;
Xint otyp,oquan;
X{
X	register struct obj *otmp;
X
X	otmp = mksobj(otyp,FALSE);
X	otmp->quan = 2 + rnd(oquan);
X	otmp->owt = weight(otmp);
X#ifdef TOLKIEN
X	if (otyp == ORCISH_ARROW) otmp->opoisoned = 1;
X#endif
X	mpickobj(mtmp, otmp);
X}
X
Xstatic void
Xm_initweap(mtmp)
Xregister struct monst *mtmp;
X{
X	register struct permonst *ptr = mtmp->data;
X#ifdef REINCARNATION
X	if (dlevel==rogue_level) return;
X#endif
X/*
X *	first a few special cases:
X *
X *		giants get a boulder to throw sometimes.
X *		ettins get clubs
X *		kobolds get darts to throw
X *		centaurs get some sort of bow & arrows or bolts
X *		soldiers get all sorts of things.
X *		kops get clubs & cream pies.
X */
X	switch (mtmp->data->mlet) {
X	    case S_GIANT:
X		if (rn2(2)) (void)mongets(mtmp, (ptr != &mons[PM_ETTIN]) ?
X				    BOULDER : CLUB);
X		break;
X	    case S_HUMAN:
X		if(is_mercenary(ptr))
X		    switch(monsndx(ptr)) {
X
X#ifdef ARMY
X			case PM_SOLDIER:
X			  (void) mongets(mtmp, rn2(2) ? SPEAR : SHORT_SWORD);
X			  break;
X			case PM_SERGEANT:
X			  (void) mongets(mtmp, rn2(2) ? FLAIL : MACE);
X			  break;
X			case PM_LIEUTENANT:
X			  (void) mongets(mtmp, rn2(2) ? GLAIVE : LONG_SWORD);
X			  break;
X			case PM_CAPTAIN:
X			  (void) mongets(mtmp, rn2(2) ? LONG_SWORD : SCIMITAR);
X			  break;
X#endif
X			default:    if (!rn2(4)) (void) mongets(mtmp, DAGGER);
X				    if (!rn2(7)) (void) mongets(mtmp, SPEAR);
X				    break;
X		    }
X		    break;
X
X	    case S_HUMANOID:
X#ifdef TOLKIEN
X		if (monsndx(ptr) == PM_HOBBIT) {
X		    switch (rn2(3)) {
X		  	case 0:
X			    (void)mongets(mtmp, DAGGER);
X			    break;
X			case 1:
X			    (void)mongets(mtmp, ELVEN_DAGGER);
X			    break;
X		      }
X		    if (!rn2(10)) (void)mongets(mtmp, ELVEN_MITHRIL_COAT);
X		} else if (is_dwarf(ptr)) {
X		    (void)mongets(mtmp, DWARVISH_CLOAK);
X		    (void)mongets(mtmp, IRON_SHOES);
X		    if (!rn2(4)) {
X			(void)mongets(mtmp, DWARVISH_SHORT_SWORD);
X			(void)mongets(mtmp,
X			    rn2(3) ? DWARVISH_MATTOCK : AXE);
X			(void)mongets(mtmp, DWARVISH_IRON_HELM);
X			(void)mongets(mtmp, DWARVISH_ROUNDSHIELD);
X			if (!rn2(3))
X			    (void)mongets(mtmp, DWARVISH_MITHRIL_COAT);
X		    } else {
X			(void)mongets(mtmp, PICK_AXE);
X		    }
X		} else if (is_elf(ptr)) {
X		    (void)mongets(mtmp,
X			rn2(2) ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK);
X		    if (rn2(2)) (void)mongets(mtmp, ELVEN_LEATHER_HELM);
X		    if (rn2(3)) (void)mongets(mtmp, ELVEN_DAGGER);
X		    switch (rn2(3)) {
X			case 0:
X			    if (!rn2(4)) (void)mongets(mtmp, ELVEN_SHIELD);
X			    (void)mongets(mtmp, ELVEN_SHORT_SWORD);
X			    (void)mongets(mtmp, ELVEN_BOW);
X			    m_initthrow(mtmp, ELVEN_ARROW, 12);
X			    break;
X			case 1:
X			    (void)mongets(mtmp, ELVEN_BROADSWORD);
X			    if (rn2(2)) (void)mongets(mtmp, ELVEN_SHIELD);
X			    break;
X			case 2:
X			    (void)mongets(mtmp, ELVEN_SPEAR);
X			    (void)mongets(mtmp, ELVEN_SHIELD);
X			    break;
X		    }
X		}
X#else /* TOLKIEN */
X		if (is_dwarf(ptr)) {
X		    (void)mongets(mtmp, IRON_SHOES);
X		    if (rn2(4) == 0) {
X			(void)mongets(mtmp, SHORT_SWORD);
X			(void)mongets(mtmp,
X			    (rn2(3) == 0) ? AXE : TWO_HANDED_SWORD);
X			(void)mongets(mtmp, LARGE_SHIELD);
X			if (rn2(3) == 0)
X			    (void)mongets(mtmp, DWARVISH_MITHRIL_COAT);
X		    } else {
X			(void)mongets(mtmp, PICK_AXE);
X		    }
X		} else if (is_elf(ptr)) {
X		    (void)mongets(mtmp, ELVEN_CLOAK);
X		    if (rn2(3)) (void)mongets(mtmp, DAGGER);
X		    switch (rn2(3)) {
X			case 0:
X			    if (!rn2(4)) (void)mongets(mtmp, SMALL_SHIELD);
X			    (void)mongets(mtmp, SHORT_SWORD);
X			    (void)mongets(mtmp, BOW);
X			    m_initthrow(mtmp, ARROW, 12);
X			    break;
X			case 1:
X			    (void)mongets(mtmp, BROADSWORD);
X			    if (rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
X			    break;
X			case 2:
X			    (void)mongets(mtmp, SPEAR);
X			    (void)mongets(mtmp, SMALL_SHIELD);
X			    break;
X		    }
X		}
X#endif /* TOLKIEN */
X		break;
X# ifdef KOPS
X	    case S_KOP:		/* create Keystone Kops with cream pies to
X				 * throw. As suggested by KAA.	   [MRS]
X				 */
X		if (!rn2(4)) m_initthrow(mtmp, CREAM_PIE, 2);
X		if (!rn2(3)) (void)mongets(mtmp, (rn2(2)) ? CLUB : RUBBER_HOSE);
X		break;
X#endif
X	    case S_ORC:
X#ifdef TOLKIEN
X		{ int mm = monsndx(ptr);
X		  if(rn2(2)) (void)mongets(mtmp, ORCISH_HELM);
X		  if (mm == PM_MORDOR_ORC ||
X		     (mm == PM_ORC_CAPTAIN && rn2(2))) {
X		      if(rn2(2)) (void)mongets(mtmp, SCIMITAR);
X		      if(rn2(2)) (void)mongets(mtmp, ORCISH_SHIELD);
X		      if(rn2(2)) (void)mongets(mtmp, KNIFE);
X		      if(rn2(2)) (void)mongets(mtmp, ORCISH_CHAIN_MAIL);
X		  } else if (mm == PM_URUK_HAI || mm == PM_ORC_CAPTAIN) {
X		      if(rn2(2)) (void)mongets(mtmp, ORCISH_CLOAK);
X		      if(rn2(2)) (void)mongets(mtmp, ORCISH_SHORT_SWORD);
X		      if(rn2(2)) (void)mongets(mtmp, IRON_SHOES);
X		      if(rn2(2)) {
X			  (void)mongets(mtmp, ORCISH_BOW);
X			  m_initthrow(mtmp, ORCISH_ARROW, 12);
X		      }
X		      if(rn2(2)) (void)mongets(mtmp, URUK_HAI_SHIELD);
X		  } else if (mm != PM_ORC_SHAMAN) {
X		      (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ?
X				    ORCISH_DAGGER : SCIMITAR);
X		  }
X		}
X#else /* TOLKIEN */
X		{ int mm = monsndx(ptr);
X		  if(rn2(2)) (void)mongets(mtmp, ORCISH_HELM);
X		  if (mm == PM_ORC_CAPTAIN) {
X		      if(rn2(2)) {
X			  if(rn2(2)) (void)mongets(mtmp, SCIMITAR);
X			  if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
X			  if(rn2(2)) (void)mongets(mtmp, KNIFE);
X			  if(rn2(2)) (void)mongets(mtmp, CHAIN_MAIL);
X		      } else {
X			  if(rn2(2)) (void)mongets(mtmp, SHORT_SWORD);
X			  if(rn2(2)) (void)mongets(mtmp, IRON_SHOES);
X			  if(rn2(2)) {
X			      (void)mongets(mtmp, BOW);
X			      m_initthrow(mtmp, ARROW, 12);
X			  }
X			  if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
X		      }
X		  } else if (mm != PM_ORC_SHAMAN) {
X		      (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ?
X				    DAGGER : SCIMITAR);
X		  }
X		}
X#endif /* TOLKIEN */
X		break;
X	    case S_KOBOLD:
X		if (!rn2(4)) m_initthrow(mtmp, DART, 12);
X		break;
X
X	    case S_CENTAUR:
X		if (rn2(2)) {
X		    if(ptr == &mons[PM_FOREST_CENTAUR]) {
X			(void)mongets(mtmp, BOW);
X			m_initthrow(mtmp, ARROW, 12);
X		    } else {
X			(void)mongets(mtmp, CROSSBOW);
X			m_initthrow(mtmp, CROSSBOW_BOLT, 12);
X		    }
X		}
X		break;
X	    case S_WRAITH:
X		(void)mongets(mtmp, KNIFE);
X		(void)mongets(mtmp, LONG_SWORD);
X		break;
X	    case S_DEMON:
X#ifdef HARD
X		if (monsndx(ptr) == PM_BALROG) {
X		    (void)mongets(mtmp, BULLWHIP);
X		    (void)mongets(mtmp, BROADSWORD);
X		    break;
X		}
X#endif
X		/* prevent djinnis and mail daemons from leaving objects when
X		 * they vanish
X		 */
X		if (!is_demon(ptr)) break;
X		/* fall thru */
X/*
X *	Now the general case, ~40% chance of getting some type
X *	of weapon. TODO: Add more weapons types (use bigmonst());
X */
X	    default:
X		switch(rnd(12)) {
X		    case 1:
X			m_initthrow(mtmp, DART, 12);
X			break;
X		    case 2:
X			(void) mongets(mtmp, CROSSBOW);
X			m_initthrow(mtmp, CROSSBOW_BOLT, 12);
X			break;
X		    case 3:
X			(void) mongets(mtmp, BOW);
X			m_initthrow(mtmp, ARROW, 12);
X			break;
X		    case 4:
X			m_initthrow(mtmp, DAGGER, 3);
X			break;
X		    case 5:
X			(void) mongets(mtmp, AKLYS);
X			break;
X		    default:
X			break;
X		}
X		break;
X	}
X}
X
Xstatic void
Xm_initinv(mtmp)
Xregister struct	monst	*mtmp;
X{
X	register int cnt;
X	register struct obj *otmp;
X	register struct permonst *ptr = mtmp->data;
X#ifdef REINCARNATION
X	if (dlevel==rogue_level) return;
X#endif
X/*
X *	Soldiers get armour & rations - armour approximates their ac.
X *	Nymphs may get mirror or potion of object detection.
X */
X	switch(mtmp->data->mlet) {
X
X	    case S_HUMAN:
X		if(is_mercenary(ptr)) {
X		    register int mac;
X
X		    if((mac = ptr->ac) < -1)
X			mac += 7 + mongets(mtmp, (rn2(5)) ?
X					   PLATE_MAIL : CRYSTAL_PLATE_MAIL);
X		    else if(mac < 3)
X			mac += 6 + mongets(mtmp, (rn2(3)) ?
X					   SPLINT_MAIL : BANDED_MAIL);
X		    else
X			mac += 3 + mongets(mtmp, (rn2(3)) ?
X					   RING_MAIL : STUDDED_LEATHER_ARMOR);
X
X		    if(mac < 10) {
X			mac += 1 + mongets(mtmp, HELMET);
X			if(mac < 10) {
X			    mac += 1 + mongets(mtmp, SMALL_SHIELD);
X			    if(mac < 10) {
X				mac += 1 + mongets(mtmp, ELVEN_CLOAK);
X				if(mac < 10)
X				    mac += 1 +mongets(mtmp, LEATHER_GLOVES);
X			    }
X			}
X		    }
X
X		    if(mac != 10) {	/* make up the difference */
X			otmp = mksobj(RIN_PROTECTION,FALSE);
X			otmp->spe = (10 - mac);
X			if(otmp->spe < 0) curse(otmp);
X			mpickobj(mtmp, otmp);
X		    }
X#ifdef ARMY
X		    if(ptr != &mons[PM_GUARD]) {
X			if (!rn2(3)) (void) mongets(mtmp, K_RATION);
X			if (!rn2(2)) (void) mongets(mtmp, C_RATION);
X		    }
X#endif
X		}
X		break;
X
X	    case S_NYMPH:
X#ifdef MEDUSA
X		if(!rn2(2)) (void) mongets(mtmp, MIRROR);
X#endif
X		if(!rn2(2)) (void) mongets(mtmp, POT_OBJECT_DETECTION);
X		break;
X
X	    case S_GIANT:
X		if(mtmp->data == &mons[PM_MINOTAUR])
X		    (void) mongets(mtmp, WAN_DIGGING);
X		else if (is_giant(mtmp->data)) {
X		    for(cnt = rn2((int)(mtmp->m_lev / 2)); cnt; cnt--) {
X			    do
X				otmp = mkobj(GEM_SYM,FALSE);
X			    while (otmp->otyp >= LAST_GEM+5);
X			    otmp->quan = 2 + rnd(2);
X			    otmp->owt = weight(otmp);
X			    mpickobj(mtmp, otmp);
X		    }
X		}
X		break;
X#ifdef TOLKIEN
X	    case S_WRAITH:
X		if(mtmp->data == &mons[PM_NAZGUL]) {
X			otmp = mksobj(RIN_INVISIBILITY, FALSE);
X			curse(otmp);
X			mpickobj(mtmp, otmp);
X		}
X		break;
X#endif
X	    default:
X		break;
X	}
X}
X
X/*
X * called with [x,y] = coordinates;
X *	[0,0] means anyplace
X *	[u.ux,u.uy] means: call mnexto (if !in_mklev)
X *
X *	In case we make a monster group, only return the one at [x,y].
X */
Xstruct monst *
Xmakemon(ptr, x, y)
Xregister struct permonst *ptr;
Xregister int	x, y;
X{
X	register struct monst *mtmp;
X	register int	ct;
X	boolean anything = (!ptr);
X
X	/* if caller wants random location, do it here */
X	if(x == 0 && y == 0) {
X		do {
X			x = rn1(COLNO-3,2);
X			y = rn2(ROWNO);
X		} while(!goodpos(x, y));
X	}
X
X	/* if a monster already exists at the position, return */
X	if(levl[x][y].mmask) return((struct monst *) 0);
X
X	if(ptr){
X		/* if you are to make a specific monster and it has 
X		   already been genocided, return */
X		if(ptr->geno & G_GENOD) return((struct monst *) 0);
X	} else {
X		/* make a random (common) monster. */
X#ifdef REINCARNATION
X		if (!(ptr = (dlevel==rogue_level) ? roguemon() : rndmonst()))
X#else
X		if(!(ptr = rndmonst()))
X#endif
X		{
X#ifdef DEBUG
X		    pline("Warning: no monster.");
X#endif
X		    return((struct monst *) 0);	/* no more monsters! */
X		}
X	}
X	/* if it's unique, don't ever make it again */
X	if (ptr->geno & G_UNIQ) ptr->geno &= G_GENOD;
X/* gotmon:	/* label not referenced */
X	mtmp = newmonst(ptr->pxlth);
X	*mtmp = zeromonst;		/* clear all entries in structure */
X	for(ct = 0; ct < ptr->pxlth; ct++)
X		((char *) &(mtmp->mextra[0]))[ct] = 0;
X 	if(type_is_pname(ptr))
X 		Strcpy(NAME(mtmp), ptr->mname);
X	mtmp->nmon = fmon;
X	fmon = mtmp;
X	mtmp->m_id = flags.ident++;
X	mtmp->data = ptr;
X	mtmp->mxlth = ptr->pxlth;
X
X	mtmp->m_lev = adj_lev(ptr);
X#ifdef GOLEMS
X	if (is_golem(ptr))
X	    mtmp->mhpmax = mtmp->mhp = golemhp(monsndx(ptr));
X	else
X#endif /* GOLEMS */
X 	if(ptr->mlevel > 49) {
X	    /* "special" fixed hp monster
X	     * the hit points are encoded in the mlevel in a somewhat strange
X	     * way to fit in the 50..127 positive range of a signed character
X	     * above the 1..49 that indicate "normal" monster levels */
X 	    mtmp->mhpmax = mtmp->mhp = 2*(ptr->mlevel - 6);
X 	    mtmp->m_lev = mtmp->mhp / 4;	/* approximation */
X 	} else if((ptr->mlet == S_DRAGON) && (ptr >= &mons[PM_GREY_DRAGON]))
X	    mtmp->mhpmax = mtmp->mhp = 80;
X	else if(!mtmp->m_lev) mtmp->mhpmax = mtmp->mhp = rnd(4);
X	else mtmp->mhpmax = mtmp->mhp = d((int)mtmp->m_lev, 8);
X	mtmp->mx = x;
X	mtmp->my = y;
X	levl[x][y].mmask = 1;
X	mtmp->mcansee = 1;
X	mtmp->mpeaceful = peace_minded(ptr);
X
X	switch(ptr->mlet) {
X		case S_MIMIC:
X			set_mimic_sym(mtmp);
X			break;
X		case S_SPIDER:
X		case S_SNAKE:
X			mtmp->mhide = mtmp->mundetected = 1;
X			if(in_mklev)
X			    if(mtmp->mx && mtmp->my)
X				(void) mkobj_at(0, mtmp->mx, mtmp->my);
X			break;
X		case S_CHAMELEON:
X			/* If you're protected with a ring, don't create
X			 * any shape-changing chameleons -dgk
X			 */
X			if (Protection_from_shape_changers)
X				mtmp->cham = 0;
X			else {
X				mtmp->cham = 1;
X				(void) newcham(mtmp, rndmonst());
X			}
X			break;
X		case S_STALKER:
X		case S_EEL:
X			mtmp->minvis = 1;
X			break;
X		case S_LEPRECHAUN:
X			mtmp->msleep = 1;
X			break;
X		case S_NYMPH:
X			if(rn2(5) && !u.uhave_amulet) mtmp->msleep = 1;
X			break;
X		case S_UNICORN:
X			if ((ptr==&mons[PM_WHITE_UNICORN] && 
X				u.ualigntyp == U_LAWFUL) ||
X			(ptr==&mons[PM_GREY_UNICORN] && 
X				u.ualigntyp == U_NEUTRAL) ||
X			(ptr==&mons[PM_BLACK_UNICORN] && 
X				u.ualigntyp == U_CHAOTIC))
X				mtmp->mpeaceful = 1;
X			break;
X	}
X	if (ptr == &mons[PM_WIZARD_OF_YENDOR]) {
X		mtmp->iswiz = 1;
X		flags.no_of_wizards++;
X	}
X
X	if(in_mklev) {
X		if(((is_ndemon(ptr)) ||
X		    (ptr == &mons[PM_WUMPUS]) ||
X#ifdef WORM
X		    (ptr == &mons[PM_LONG_WORM]) ||
X#endif
X		    (ptr == &mons[PM_GIANT_EEL])) && rn2(5))
X			mtmp->msleep = 1;
X	} else {
X		if(x == u.ux && y == u.uy && ptr->mlet != S_GHOST) {
X			mnexto(mtmp);
X			if (ptr->mlet == S_MIMIC) set_mimic_sym(mtmp);
X		}
X	}
X#ifdef HARD
X	if(is_dprince(ptr)) {
X	    mtmp->mpeaceful = mtmp->minvis = 1;
X# ifdef NAMED_ITEMS
X	    if(uwep)
X		if(!strcmp(ONAME(uwep), "Excalibur"))
X		    mtmp->mpeaceful = mtmp->mtame = 0;
X# endif
X	}
X#endif
X#ifdef WORM
X	if(ptr == &mons[PM_LONG_WORM] && getwn(mtmp))  initworm(mtmp);
X#endif
X	set_malign(mtmp);		/* having finished peaceful changes */
X	if(anything) {
X	    if((ptr->geno & G_SGROUP) && rn2(2))
X		m_initsgrp(mtmp, mtmp->mx, mtmp->my);
X	    else if(ptr->geno & G_LGROUP) {
X			if(rn2(3))  m_initlgrp(mtmp, mtmp->mx, mtmp->my);
X			else	    m_initsgrp(mtmp, mtmp->mx, mtmp->my);
X	    }
X	}
X
X	if(is_armed(ptr))
X		m_initweap(mtmp);	/* equip with weapons / armour */
X	m_initinv(mtmp);		/* add on a few special items */
X
X	return(mtmp);
X}
X
Xvoid
Xenexto(cc, xx,yy)
Xcoord *cc;
Xregister xchar xx, yy;
X{
X	register xchar x,y;
X	coord foo[15], *tfoo;
X	int range, i;
X
X	tfoo = foo;
X	range = 1;
X	do {	/* full kludge action. */
X		for(x = xx-range; x <= xx+range; x++)
X			if(goodpos(x, yy-range)) {
X				tfoo->x = x;
X				(tfoo++)->y = yy-range;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		for(x = xx-range; x <= xx+range; x++)
X			if(goodpos(x,yy+range)) {
X				tfoo->x = x;
X				(tfoo++)->y = yy+range;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		for(y = yy+1-range; y < yy+range; y++)
X			if(goodpos(xx-range,y)) {
X				tfoo->x = xx-range;
X				(tfoo++)->y = y;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		for(y = yy+1-range; y < yy+range; y++)
X			if(goodpos(xx+range,y)) {
X				tfoo->x = xx+range;
X				(tfoo++)->y = y;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		range++;
X	} while(tfoo == foo);
Xfoofull:
X	i = rn2(tfoo - foo);
X	cc->x = foo[i].x;
X	cc->y = foo[i].y;
X	return;
X}
X
Xint
Xgoodpos(x, y)
X{
X#ifdef STUPID
X	if (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 ||
X	    levl[x][y].mmask || !ACCESSIBLE(levl[x][y].typ))
X	  return 0;
X	if (IS_DOOR(levl[x][y].typ) &&
X	    (levl[x][y].doormask & (D_LOCKED | D_CLOSED)))
X	  return 0;
X	return !((x == u.ux && y == u.uy) || sobj_at(BOULDER, x, y));
X#else
X	return
X	! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 ||
X	   levl[x][y].mmask || !ACCESSIBLE(levl[x][y].typ) ||
X	   (IS_DOOR(levl[x][y].typ) && 
X		(levl[x][y].doormask & (D_LOCKED | D_CLOSED)) )
X	   || (x == u.ux && y == u.uy)
X	   || sobj_at(BOULDER, x, y)
X	);
X#endif /* STUPID */
X}
X
Xvoid
Xrloc(mtmp)
Xstruct monst *mtmp;
X{
X	register int tx, ty;
X
X#ifdef WORM		/* do not relocate worms */
X	if(mtmp->wormno && mtmp->mx) return;
X#endif
X	/* if the wiz teleports away to heal, try the up staircase,
X	   to block the player's escaping before he's healed */
X	if(!mtmp->iswiz || !goodpos(tx = xupstair, ty = yupstair))
X	   do {
X		tx = rn1(COLNO-3,2);
X		ty = rn2(ROWNO);
X	   } while(!goodpos(tx,ty));
X	if(mtmp->mx != 0 && mtmp->my != 0)
X		levl[mtmp->mx][mtmp->my].mmask = 0;
X	mtmp->mx = tx;
X	mtmp->my = ty;
X	levl[tx][ty].mmask = 1;
X	if(u.ustuck == mtmp){
X		if(u.uswallow) {
X			u.ux = tx;
X			u.uy = ty;
X			docrt();
X		} else	u.ustuck = 0;
X	}
X	pmon(mtmp);
X	set_apparxy(mtmp);
X}
X
Xstruct monst *
Xmkmon_at(name, x, y)
Xchar *name;
Xregister int x,y;
X{
X	register int ct;
X	register struct permonst *ptr;
X
X	for(ct = PM_CHAMELEON; ct >= 0; ct--) { /* Chameleon is last monster */
X		ptr = &mons[ct];
X		if(!strcmp(ptr->mname, name))
X			return(makemon(ptr, x, y));
X	}
X	return((struct monst *)0);
X}
X
Xstatic int
Xcmnum()	{	/* return the number of "common" monsters */
X
X	int	i, count;
X
X	for(i = count = 0; mons[i].mlet; i++)
X	   if(!uncommon(&mons[i]))  count++;
X
X	return(count);
X}
X
Xstatic int
Xuncommon(ptr)
Xstruct	permonst *ptr;
X{
X	return (ptr->geno & (G_GENOD | G_NOGEN | G_UNIQ)) ||
X		(!Inhell ? ptr->geno & G_HELL : ptr->maligntyp > 0);
X}
X
X/* This routine is designed to return an integer value which represents
X * an approximation of monster strength.  It uses a similar method of
X * determination as "experience()" to arrive at the strength.
X */
Xstatic int
Xmstrength(ptr)
Xstruct permonst *ptr;
X{
X	int	i, tmp2, n, tmp = ptr->mlevel;
X
X 	if(tmp > 49)		/* special fixed hp monster */
X	    tmp = 2*(tmp - 6) / 4;
X
X/*	For creation in groups */
X	n = (!!(ptr->geno & G_SGROUP));
X	n += (!!(ptr->geno & G_LGROUP)) << 1;
X
X/*	For higher ac values */
X	n += (ptr->ac < 0);
X
X/*	For very fast monsters */
X	n += (ptr->mmove >= 18);
X
X/*	For each attack and "special" attack */
X	for(i = 0; i < NATTK; i++) {
X
X	    tmp2 = ptr->mattk[i].aatyp;
X	    n += (tmp2 > 0);
X	    n += (tmp2 == AT_MAGC);
X	}
X
X/*	For each "special" damage type */
X	for(i = 0; i < NATTK; i++) {
X
X	    tmp2 = ptr->mattk[i].adtyp;
X	    if((tmp2 == AD_DRLI) || (tmp2 == AD_STON)) n += 2;
X	    else n += (tmp2 != AD_PHYS);
X	    n += ((ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
X	}
X
X/*	Finally, adjust the monster level  0 <= n <= 24 (approx.) */
X	if(n == 0) tmp--;
X	else if(n >= 6) tmp += ( n / 2 );
X	else tmp += ( n / 3 + 1);
X
X	return((tmp >= 0) ? tmp : 0);
X}
X
Xvoid
Xinit_monstr()
X{
X	register int ct;
X
X	for(ct = 0; mons[ct].mlet; ct++)
X		monstr[ct] = mstrength(&(mons[ct]));
X}
X
Xstruct	permonst *
Xrndmonst() {		/* select a random monster */
X	register struct permonst *ptr;
X	register int i, ct;
X	register int zlevel;
X	static int minmlev, maxmlev, accept;
X	static long oldmoves = 0L;	/* != 1, starting value of moves */
X
X	if(oldmoves != moves) {		/* must recalculate accept */
X	    oldmoves = moves;
X	    zlevel = u.uhave_amulet ? MAXLEVEL : dlevel;
X	    if(cmnum() <= 0) {
X#ifdef DEBUG
X		pline("cmnum() fails!");
X#endif
X		return((struct permonst *) 0);
X	    }
X
X	    /* determine the level of the weakest monster to make. */
X	    minmlev = zlevel/6;
X	    /* determine the level of the strongest monster to make. */
X	    maxmlev = (zlevel + u.ulevel)>>1;
X/*
X *	Find out how many monsters exist in the range we have selected.
X */
X	    for(accept = ct = 0 ; mons[ct].mlet; ct++) {
X		ptr = &(mons[ct]);
X		if(uncommon(ptr)) continue;
X		if(tooweak(ct, minmlev) || toostrong(ct, maxmlev))
X		    continue;
X		accept += (ptr->geno & G_FREQ);
X	    }
X	}
X
X	if(!accept) {
X#ifdef DEBUG
X		pline("no accept!");
X#endif
X		return((struct permonst *) 0);
X	}
X/*
X *	Now, select a monster at random.
X */
X	ct = rnd(accept);
X	for(i = 0; mons[i].mlet && ct > 0; i++) {
X		ptr = &(mons[i]);
X		if(uncommon(ptr)) continue;
X		if(tooweak(i, minmlev) || toostrong(i, maxmlev))
X		    continue;
X		ct -= (ptr->geno & G_FREQ);
X	}
X	if(ct > 0) {
X#ifdef DEBUG
X		pline("no count!");
X#endif
X		return((struct permonst *) 0);
X	}
X	return(ptr);
X}
X
X/*	The routine below is used to make one of the multiple types
X *	of a given monster class.  It will return 0 if no monsters
X *	in that class can be made.
X */
X
Xstruct permonst *
Xmkclass(mlet)
Xchar	mlet;
X{
X	register int	first, last, num = 0;
X
X	if(!mlet) {
X	    impossible("mkclass called with null arg!");
X	    return((struct permonst *) 0);
X	}
X/*	Assumption #1:	monsters of a given class are contiguous in the
X *			mons[] array.
X */
X	for(first = 0; mons[first].mlet != mlet; first++)
X		if(!mons[first].mlet)	return((struct permonst *) 0);
X
X	for(last = first; mons[last].mlet && mons[last].mlet == mlet; last++)
X	    if(!(mons[last].geno & (G_GENOD | G_NOGEN | G_UNIQ)))
X		num += mons[last].geno & G_FREQ;
X
X	if(!num) return((struct permonst *) 0);
X
X/*	Assumption #2:	monsters of a given class are presented in ascending
X *			order of strength.
X */
X	for(num = rnd(num); num > 0; first++)
X	    if(!(mons[first].geno & (G_GENOD | G_NOGEN | G_UNIQ))) { /* consider it */
X		/* skew towards lower value monsters at lower exp. levels */
X		if(adj_lev(&mons[first]) > (u.ulevel*2)) num--;
X		num -= mons[first].geno & G_FREQ;
X	    }
X	first--; /* correct an off-by-one error */
X
X	return(&mons[first]);
X}
X
Xint
Xadj_lev(ptr)	/* adjust strength of monsters based on dlevel and u.ulevel */
Xregister struct permonst *ptr;
X{
X	int	tmp, tmp2;
X
X	if((tmp = ptr->mlevel) > 49) return(50); /* "special" demons/devils */
X	tmp2 = (dlevel - tmp);
X	if(tmp2 < 0) tmp--;		/* if mlevel > dlevel decrement tmp */
X	else tmp += (tmp2 / 5);		/* else increment 1 per five diff */
X
X	tmp2 = (u.ulevel - ptr->mlevel);	/* adjust vs. the player */
X	if(tmp2 > 0) tmp += (tmp2 / 4);		/* level as well */
X
X	tmp2 = 3 * ptr->mlevel/ 2;		/* crude upper limit */
X	return((tmp > tmp2) ? tmp2 : (tmp > 0 ? tmp : 0)); /* 0 lower limit */
X}
X
Xstruct permonst *
Xgrow_up(mtmp)		/* mon mtmp "grows up" to a bigger version. */
Xregister struct monst *mtmp;
X{
X	register int newtype;
X	register struct permonst *ptr = mtmp->data;
X
X	if (ptr->mlevel >= 50 || mtmp->mhpmax <= 8*mtmp->m_lev)
X	    return ptr;
X	newtype = little_to_big(monsndx(ptr));
X	if (++mtmp->m_lev >= mons[newtype].mlevel) {
X		if (mons[newtype].geno & G_GENOD) {
X			pline("As %s grows up into a%s %s, %s dies!",
X				mon_nam(mtmp),
X				index(vowels,*mons[newtype].mname) ? "n" : "",
X				mons[newtype].mname,
X				mon_nam(mtmp));
X			mondied(mtmp);
X			return (struct permonst *)0;
X		}
X		mtmp->data = &mons[newtype];
X		mtmp->m_lev = mons[newtype].mlevel;
X	}
X	if (mtmp->m_lev > 3*mtmp->data->mlevel / 2)
X		mtmp->m_lev = 3*mtmp->data->mlevel / 2;
X	return(mtmp->data);
X}
X
Xint
Xmongets(mtmp, otyp)
Xregister struct monst *mtmp;
Xregister int otyp;
X{
X	register struct obj *otmp;
X
X	if((otmp = (otyp) ? mksobj(otyp,FALSE) : mkobj(otyp,FALSE))) {
X	    if (mtmp->data->mlet == S_DEMON) {
X		/* demons always get cursed objects */
X		curse(otmp);
X	    }
X	    mpickobj(mtmp, otmp);
X	    return(otmp->spe);	    
X	} else return(0);
X}
X
X#ifdef REINCARNATION
Xstruct permonst *
Xroguemon()
X{
X/* Make a monster for a Rogue-like level; only capital letters.  There are
X * no checks for "too hard" or "too easy", though dragons are specifically
X * ruled out because playtesting showed they made the level too hard.
X * Modified from rndmonst().
X */
X#define isupper(x) ('A'<=(x) && (x)<='Z')
X	register struct permonst *ptr;
X	register int accept,ct,i;
X
X	/* See how many there are. */
X	accept = 0;
X	for(ct = PM_APE ; isupper(mons[ct].mlet); ct++) {
X		if (mons[ct].mlet == S_DRAGON) continue;
X		ptr = &(mons[ct]);
X		if(uncommon(ptr)) continue;
X		accept += (ptr->geno & G_FREQ);
X	}
X	if(!accept) return((struct permonst *) 0);
X
X	/* Now, select one at random. */
X	ct = rnd(accept);
X	for(i = PM_APE; isupper(mons[i].mlet) && ct > 0; i++) {
X		if (mons[i].mlet == S_DRAGON) continue;
X		ptr = &(mons[i]);
X		if(uncommon(ptr)) continue;
X		ct -= (ptr->geno & G_FREQ);
X	}
X	if(ct > 0) return((struct permonst *) 0);
X	return(ptr);
X}
X#endif
X
X#ifdef GOLEMS
Xint
Xgolemhp(type)
Xint type;
X{
X	switch(type) {
X		case PM_STRAW_GOLEM: return 20;
X		case PM_ROPE_GOLEM: return 30;
X		case PM_LEATHER_GOLEM: return 40;
X		case PM_WOOD_GOLEM: return 50;
X		case PM_FLESH_GOLEM: return 40;
X		case PM_CLAY_GOLEM: return 50;
X		case PM_STONE_GOLEM: return 60;
X		case PM_IRON_GOLEM: return 80;
X		default: return 0;
X	}
X}
X#endif /* GOLEMS */
X
X/*
X *	Alignment vs. yours determines monster's attitude to you.
X *	( some "animal" types are co-aligned, but also hungry )
X */
Xboolean
Xpeace_minded(ptr)
Xregister struct permonst *ptr;
X{
X	schar mal = ptr->maligntyp, ual = u.ualigntyp;
X
X	if (always_peaceful(ptr)) return TRUE;
X	if (always_hostile(ptr)) return FALSE;
X
X	/* the monster is hostile if its alignment is different from the
X	 * player's */
X	if (sgn(mal) != sgn(ual)) return FALSE;
X
X	/* Negative monster hostile to player with Amulet. */
X	if (mal < 0 && u.uhave_amulet) return FALSE;
X
X	/* Last case:  a chance of a co-aligned monster being
X	 * hostile.  This chance is greater if the player has strayed
X	 * (u.ualign negative) or the monster is not strongly aligned.
X	 */
X	return !!rn2(16 + (u.ualign < -15 ? -15 : u.ualign)) &&
X		!!rn2(2 + abs(mal));
X}
X
X/* Set malign to have the proper effect on player alignment if monster is
X * killed.  Negative numbers mean it's bad to kill this monster; positive
X * numbers mean it's good.  Since there are more hostile monsters than
X * peaceful monsters, the penalty for killing a peaceful monster should be
X * greater than the bonus for killing a hostile monster to maintain balance.
X * Rules:
X *   it's bad to kill peaceful monsters, potentially worse to kill always-
X *	peaceful monsters
X *   it's never bad to kill a hostile monster, although it may not be good
X */
Xvoid
Xset_malign(mtmp)
Xstruct monst *mtmp;
X{
X	schar mal = mtmp->data->maligntyp;
X	boolean coaligned = (sgn(mal) == sgn(u.ualigntyp));
X
X	if (always_peaceful(mtmp->data))
X		mtmp->malign = -3*max(5,abs(mal));
X	else if (always_hostile(mtmp->data)) {
X		if (coaligned)
X			mtmp->malign = 0;
X		else
X			mtmp->malign = max(5,abs(mal));
X	} else if (coaligned) {
X		if (mtmp->mpeaceful)
X			mtmp->malign = -3*max(3,abs(mal));
X		else	/* renegade */
X			mtmp->malign = max(3,abs(mal));
X	} else	/* not coaligned and therefore hostile */
X		mtmp->malign = abs(mal);
X}
X
Xstatic char syms[] = { 0, 0, RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, GOLD_SYM,
X	SCROLL_SYM, POTION_SYM, ARMOR_SYM, AMULET_SYM, TOOL_SYM, ROCK_SYM,
X	GEM_SYM,
X#ifdef SPELLS
X	SPBOOK_SYM,
X#endif
X	S_MIMIC_DEF, S_MIMIC_DEF, S_MIMIC_DEF,
X};
X
Xvoid
Xset_mimic_sym(mtmp) /* KAA */
Xregister struct monst *mtmp;
X{
X	int roomno, rt;
X	char sym;
X	if (!mtmp) return;
X
X	syms[0] = UP_SYM;
X	syms[1] = DN_SYM;
X
X	mtmp->mimic = 1;
X	roomno = inroom(mtmp->mx, mtmp->my);
X	if (levl[mtmp->mx][mtmp->my].gmask)
X		sym = GOLD_SYM;
X	else if (levl[mtmp->mx][mtmp->my].omask)
X		sym = o_at(mtmp->mx,mtmp->my)->olet;
X	else if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ) ||
X		 IS_WALL(levl[mtmp->mx][mtmp->my].typ))
X		sym = DOOR_SYM;
X	else if (is_maze_lev)
X		sym = rn2(2) ? ROCK_SYM : syms[rn2(sizeof syms)];
X	else if (roomno < 0)
X		sym = ROCK_SYM;
X	else if ((rt = rooms[roomno].rtype) == ZOO || rt == VAULT)
X		sym = GOLD_SYM;
X#ifdef ORACLE
X	else if (rt == DELPHI)
X		sym = rn2(2) ? ROCK_SYM : FOUNTAIN_SYM;
X#endif
X#ifdef ALTARS
X	else if (rt == TEMPLE)
X		sym = ALTAR_SYM;
X#endif
X	/* We won't bother with beehives, morgues, barracks, throne rooms
X	 * since they shouldn't contain mimics anyway...
X	 */
X	else if (rt >= SHOPBASE) {
X		int s_sym = get_shop_item(rt - SHOPBASE);
X
X		if (s_sym < 0) sym = objects[-sym].oc_olet;
X		else if (sym == RANDOM_SYM)
X			sym = syms[rn2(sizeof(syms)-2) + 2];
X		else sym = s_sym;
X	} else sym = syms[rn2(sizeof syms)];
X	mtmp->mappearance = sym;
X}
END_OF_FILE
if test 28290 -ne `wc -c <'src/makemon.c'`; then
    echo shar: \"'src/makemon.c'\" unpacked with wrong size!
fi
# end of 'src/makemon.c'
fi
if test -f 'src/options.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/options.c'\"
else
echo shar: Extracting \"'src/options.c'\" \(16326 characters\)
sed "s/^X//" >'src/options.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)options.c	3.0	88/11/09
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
Xstatic boolean set_order;
X
Xstatic void nmcpy();
X
Xvoid
Xinitoptions()
X{
X	register char *opts;
X
X	flags.time = flags.nonews = flags.notombstone = flags.end_own =
X	flags.standout = flags.nonull = flags.ignintr = FALSE;
X	flags.no_rest_on_space = flags.invlet_constant = TRUE;
X	flags.end_top = 5;
X	flags.end_around = 4;
X	flags.female = FALSE;			/* players are usually male */
X	flags.sortpack = TRUE;
X	flags.soundok = TRUE;
X	flags.verbose = TRUE;
X	flags.confirm = TRUE;
X	flags.safe_dog = TRUE;
X	flags.silent = 	flags.pickup = TRUE;
X	nmcpy(pl_fruit, objects[SLIME_MOLD].oc_name, PL_FSIZ);
X	flags.num_pad = FALSE;
X#ifdef MSDOS
X#ifdef DECRAINBOW
X	flags.DECRainbow = FALSE;
X#endif
X#ifdef DGK
X	flags.IBMBIOS =
X	flags.rawio = FALSE;
X#endif
X	read_config_file();
X#endif /* MSDOS */
X	if(opts = getenv("NETHACKOPTIONS"))
X		parseoptions(opts,TRUE);
X	(void)fruitadd(pl_fruit);
X	objects[SLIME_MOLD].oc_name = "\033";
X	/* Put something untypable in there */
X	/* We cannot just use NULL because that marks the end of objects */
X}
X
Xstatic void
Xnmcpy(dest, source, maxlen)
X	char	*dest, *source;
X	int	maxlen;
X{
X	char	*cs, *cd;
X	int	count;
X
X	cd = dest;
X	cs = source;
X	for(count = 1; count < maxlen; count++) {
X		if(*cs == ',' || *cs == '\0') break; /*exit on \0 terminator*/
X		*cd++ = *cs++;
X	}
X	*cd = 0;
X}
X
X/*
X * escapes: escape expansion for showsyms. C-style escapes understood include
X * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix
X * for control characters is also understood, and \[mM] followed by any of the
X * previous forms or by a character has the effect of 'meta'-ing the value (so
X * that the alternate character set will be enabled).
X */
Xvoid
Xescapes(cp, tp)
Xchar	*cp, *tp;
X{
X    while (*cp)
X    {
X	int	cval = 0, meta = 0;
X
X	if (*cp == '\\' && index("mM", cp[1])) {
X		meta = 1;
X		cp += 2;
X	}
X	if (*cp == '\\' && index("0123456789xXoO", cp[1]))
X	{
X	    char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
X	    int dcount = 0;
X
X	    cp++;
X	    if (*cp == 'x' || *cp == 'X')
X		for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
X		    cval = (cval * 16) + (dp - hex) / 2;
X	    else if (*cp == 'o' || *cp == 'O')
X		for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++)
X		    cval = (cval * 8) + (*cp - '0');
X	    else
X		for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++)
X		    cval = (cval * 10) + (*cp - '0');
X	}
X	else if (*cp == '\\')		/* C-style character escapes */
X	{
X	    switch (*++cp)
X	    {
X	    case '\\': cval = '\\'; break;
X	    case 'n': cval = '\n'; break;
X	    case 't': cval = '\t'; break;
X	    case 'b': cval = '\b'; break;
X	    case 'r': cval = '\r'; break;
X	    default: cval = *cp;
X	    }
X	    cp++;
X	}
X	else if (*cp == '^')		/* expand control-character syntax */
X	{
X	    cval = (*++cp & 0x1f);
X	    cp++;
X	}
X	else
X	    cval = *cp++;
X	if (meta)
X	    cval |= 0x80;
X	*tp++ = cval;
X    }
X    *tp = '\0';
X}
X
Xvoid
Xparseoptions(opts, from_env)
Xregister char *opts;
Xboolean from_env;
X{
X	register char *op;
X/*
X	register char *op2;
X*/
X	unsigned num;
X	boolean negated;
X
X	if(op = index(opts, ',')) {
X		*op++ = 0;
X		parseoptions(op, from_env);
X	}
X/*
X	if(op = index(opts, ' ')) {
X		op2 = op;
X		while(*op++)
X			if(*op != ' ') *op2++ = *op;
X	}
X*/
X	if(!*opts) return;
X	negated = FALSE;
X	while((*opts == '!') || !strncmp(opts, "no", 2)) {
X		if(*opts == '!') opts++; else opts += 2;
X		negated = !negated;
X	}
X	
X#ifndef MSDOS
X	if (!strncmp(opts, "standout", 4)) {
X		flags.standout = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "null", 4)) {
X		flags.nonull = negated;
X		return;
X	}
X#endif
X
X	if (!strncmp(opts, "ignintr", 3)) {
X		flags.ignintr = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "tombstone", 4)) {
X		flags.notombstone = negated;
X		return;
X	}
X
X#ifdef NEWS
X	if (!strncmp(opts, "news", 4)) {
X		flags.nonews = negated;
X		return;
X	}
X#endif
X
X	if (!strncmp(opts, "confirm", 4)) {
X		flags.confirm = !negated;
X		return;
X	}
X	if (!strncmp(opts, "safe", 4)) {
X		flags.safe_dog = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "silent", 4)) {
X		flags.silent = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "verbose", 4)) {
X		flags.verbose = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "pickup", 4)) {
X		flags.pickup = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "number_pad", 4)) {
X		flags.num_pad = !negated;
X		return;
X	}
X
X#ifdef DGK
X	if (!strncmp(opts, "IBM", 3)) {
X		flags.IBMBIOS = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "rawio", 4)) {
X		if (from_env)
X			flags.rawio = !negated;
X		else
X			pline("\"rawio\" settable only from %s.", configfile);
X		return;
X	}
X
X#ifdef DECRAINBOW
X	if (!strncmp(opts, "DEC", 3)) {
X		flags.DECRainbow = !negated;
X		return;
X	}
X#endif /* DECRAINBOW */
X#endif
X
X	if (!strncmp(opts, "sort", 4)) {
X		flags.sortpack = !negated;
X		return;
X	}
X
X	/*
X	 * the order to list the pack
X	 */
X	if (!strncmp(opts, "packorder", 4)) {
X		register char	*sp, *tmp;
X		int tmpend;
X
X		op = index(opts,':');
X		if(!op) goto bad;
X		op++;			/* skip : */
X
X		/* Missing characters in new order are filled in at the end 
X		 * from inv_order.
X		 */
X		for (sp = op; *sp; sp++)
X			if (!index(inv_order, *sp))
X				goto bad;		/* bad char in order */
X			else if (index(sp + 1, *sp))
X				goto bad;		/* dup char in order */
X		tmp = (char *) alloc((unsigned)(strlen(inv_order)+1));
X		Strcpy(tmp, op);
X		for (sp = inv_order, tmpend = strlen(tmp); *sp; sp++)
X			if (!index(tmp, *sp)) {
X				tmp[tmpend++] = *sp;
X				tmp[tmpend] = 0;
X			}
X		Strcpy(inv_order, tmp);
X		free((genericptr_t)tmp);
X		set_order = TRUE;
X		return;
X	}
X
X	if (!strncmp(opts, "time", 4)) {
X		flags.time = !negated;
X		flags.botl = 1;
X		return;
X	}
X
X	if (!strncmp(opts, "rest_on_space", 4)) {
X		flags.no_rest_on_space = negated;
X		return;
X	}
X
X	if (!strncmp(opts, "fixinv", 3)) {
X		flags.invlet_constant = !negated;
X		if(!from_env && flags.invlet_constant) reassign ();
X		return;
X	}
X
X	if (!strncmp(opts, "male", 4)) {
X		if(!from_env && flags.female != negated)
X			pline("That is not anatomically possible.");
X		else
X			flags.female = negated;
X		return;
X	}
X	if (!strncmp(opts, "female", 3)) {
X		if(!from_env && flags.female == negated)
X			pline("That is not anatomically possible.");
X		else
X			flags.female = !negated;
X		return;
X	}
X
X	/* name:string */
X	if (!strncmp(opts, "name", 4)) {
X		if(!from_env) {
X#ifdef MSDOS
X		  pline("\"name\" settable only from %s.", configfile);
X#else
X		  pline("The playername can be set only from NETHACKOPTIONS.");
X#endif
X		  return;
X		}
X		op = index(opts,':');
X		if(!op) goto bad;
X		nmcpy(plname, op+1, sizeof(plname)-1);
X		return;
X	}
X
X	/* graphics:string */
X	if (!strncmp(opts, "graphics", 4)) {
X		if(!from_env) {
X#ifdef MSDOS
X		  pline("\"graphics\" settable only from %s.", configfile);
X#else
X		  pline("The graphics string can be set only from NETHACKOPTIONS.");
X#endif
X		  return;
X		}
X		op = index(opts,':');
X		if(!op)
X		    goto bad;
X		else
X		    opts = op + 1;
X		escapes(opts, opts);
X#define SETPCHAR(f, n)	showsyms.f = (strlen(opts) > n) ? opts[n] : defsyms.f
X		SETPCHAR(stone, 0);
X		SETPCHAR(vwall, 1);
X		SETPCHAR(hwall, 2);
X		SETPCHAR(tlcorn, 3);
X		SETPCHAR(trcorn, 4);
X		SETPCHAR(blcorn, 5);
X		SETPCHAR(brcorn, 6);
X		SETPCHAR(crwall, 7);
X		SETPCHAR(tuwall, 8);
X		SETPCHAR(tdwall, 9);
X		SETPCHAR(tlwall, 10);
X		SETPCHAR(trwall, 11);
X		SETPCHAR(vbeam, 12);
X		SETPCHAR(hbeam, 13);
X		SETPCHAR(lslant, 14);
X		SETPCHAR(rslant, 15);
X		SETPCHAR(door, 16);
X		SETPCHAR(room, 17);
X		SETPCHAR(corr, 18);
X		SETPCHAR(upstair, 19);
X		SETPCHAR(dnstair, 20);
X		SETPCHAR(trap, 21);
X		SETPCHAR(web, 22);
X		SETPCHAR(pool, 23);
X#ifdef FOUNTAINS
X		SETPCHAR(fountain, 24);
X#endif
X#ifdef SINKS
X		SETPCHAR(sink, 25);
X#endif
X#ifdef THRONES
X		SETPCHAR(throne, 26);
X#endif
X#ifdef ALTARS
X		SETPCHAR(altar, 27);
X#endif
X#ifdef STRONGHOLD
X		SETPCHAR(upladder, 28);
X		SETPCHAR(dnladder, 29);
X		SETPCHAR(dbvwall, 30);
X		SETPCHAR(dbhwall, 31);
X#endif
X#undef SETPCHAR
X		return;
X	}
X
X	/* endgame:5t[op] 5a[round] o[wn] */
X	if (!strncmp(opts, "endgame", 3)) {
X		op = index(opts,':');
X		if(!op) goto bad;
X		op++;
X		while(*op) {
X			num = 1;
X			if(digit(*op)) {
X				num = atoi(op);
X				while(digit(*op)) op++;
X			} else
X			if(*op == '!') {
X				negated = !negated;
X				op++;
X			}
X			switch(*op) {
X			case 't':
X				flags.end_top = num;
X				break;
X			case 'a':
X				flags.end_around = num;
X				break;
X			case 'o':
X				flags.end_own = !negated;
X				break;
X			default:
X				goto bad;
X			}
X			while(letter(*++op)) ;
X			if(*op == '/') op++;
X		}
X		return;
X	}
X	if (!strncmp(opts, "dogname", 3)) {
X		if(!from_env) {
X#ifdef MSDOS
X		  pline("\"dogname\" settable only from %s.", configfile);
X#else
X		  Your("dog's name can be set only from NETHACKOPTIONS.");
X#endif
X		  return;
X		}
X		op = index(opts, ':');
X		if (!op) goto bad;
X		nmcpy(dogname, ++op, 62);
X		return;
X	}
X	if (!strncmp(opts, "catname", 3)) {
X		if(!from_env) {
X#ifdef MSDOS
X		  pline("\"catname\" settable only from %s.", configfile);
X#else
X		  Your("cat's name can be set only from NETHACKOPTIONS.");
X#endif
X		  return;
X		}
X		op = index(opts, ':');
X		if (!op) goto bad;
X		nmcpy(catname, ++op, 62);
X		return;
X	}
X	if (!strncmp(opts, "fruit", 2)) {
X		op = index(opts, ':');
X		if (!op++) goto bad;
X		if (!from_env) {
X		    struct fruit *f;
X		    int numfruits = 0;
X
X		    for(f=ffruit; f; f=f->nextf) {
X			if (!strcmp(op, f->fname)) goto goodfruit;
X			numfruits++;
X		    }
X		    if (numfruits >= 100) {
X			pline("Doing that so many times isn't very fruitful.");
X			return;
X		    }
X		}
Xgoodfruit:
X		nmcpy(pl_fruit, op, PL_FSIZ);
X		if (!from_env)
X		    (void)fruitadd(pl_fruit);
X		/* If from_env, then initoptions is allowed to do it instead
X		 * of here (initoptions always has to do it even if there's
X		 * no fruit option at all.  Also, we don't want people
X		 * setting multiple fruits in their options.)
X		 */
X		return;
X	}
Xbad:
X	if(!from_env) {
X		if(!strncmp(opts, "h", 1) ||
X		   !strncmp(opts, "?", 1)) {
X			option_help();
X			return;
X		}
X		pline("Unknown option: %s.  Enter \"O?\" for help.", opts);
X		return;
X	}
X#ifdef MSDOS
X	Printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts);
X#else
X	Printf("Bad syntax in NETHACKOPTIONS: %s.", opts);
X	(void) puts("Use for example:");
X	(void) puts(
X"NETHACKOPTIONS=\"!rest_on_space,notombstone,endgame:own/5 topscorers/4 around me\""
X	);
X#endif
X	getret();
X}
X
Xint
Xdoset()
X{
X	char buf[BUFSZ];
X
X	pline("What options do you want to set? ");
X	getlin(buf);
X	if(!buf[0] || buf[0] == '\033') {
X#ifdef MSDOS
X	    Strcpy(buf,"OPTIONS=");
X#ifdef DGK
X	    if (flags.rawio) Strcat(buf,"rawio,");
X	    if (flags.IBMBIOS) Strcat(buf,"IBM_BIOS,");
X#endif /* DGK */
X#ifdef DECRAINBOW
X	    if (flags.DECRainbow) Strcat(buf,"DEC_Rainbow,");
X#endif /* DECRAINBOW */
X#else /* MSDOS */
X	    Strcpy(buf,"NETHACKOPTIONS=");
X	    if(flags.standout) Strcat(buf,"standout,");
X	    if(flags.nonull) Strcat(buf,"nonull,");
X#endif /* MSDOS */
X	    if(flags.ignintr) Strcat(buf,"ignintr,");
X	    if(flags.num_pad) Strcat(buf,"number_pad,");
X#ifdef NEWS
X	    if(flags.nonews) Strcat(buf,"nonews,");
X#endif
X	    if(flags.notombstone) Strcat(buf,"notombstone,");
X	    Strcat(buf, flags.female ? "female," : "male,");
X	    if(flags.no_rest_on_space)	Strcat(buf,"!rest_on_space,");
X	    if (flags.invlet_constant) Strcat(buf,"fixinv,");
X	    if (flags.sortpack) Strcat(buf,"sortpack,");
X	    if (set_order){
X		Strcat(buf, "packorder: ");
X		Strcat(buf, inv_order);
X		Strcat(buf, ",");
X	    }
X	    if (flags.confirm) Strcat(buf,"confirm,");
X	    if (flags.safe_dog) Strcat(buf,"safe_pet,");
X	    if (flags.pickup) Strcat(buf,"pickup,");
X	    if (flags.silent) Strcat(buf,"silent,");
X	    if (flags.time) Strcat(buf,"time,");
X	    if (flags.verbose) Strcat(buf,"verbose,");
X	    Sprintf(eos(buf), "fruit:%s,", pl_fruit);
X	    if(flags.end_top != 5 || flags.end_around != 4 || flags.end_own){
X		Sprintf(eos(buf), "endgame: %u top scores/%u around me",
X			flags.end_top, flags.end_around);
X		if(flags.end_own) Strcat(buf, "/own scores");
X	    } else {
X		register char *eop = eos(buf);
X		if(*--eop == ',') *eop = 0;
X	    }
X	    pline(buf);
X	} else {
X	    clrlin();
X	    parseoptions(buf, FALSE);
X	}
X
X	return 0;
X}
X
Xint
Xdotogglepickup() {
X	flags.pickup = !flags.pickup;
X	pline("Pickup: %s.", flags.pickup ? "ON" : "OFF");
X	return 0;
X}
X
Xchar	packorder[] =	{
X	AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM,
X# ifdef SPELLS
X	SPBOOK_SYM,
X# endif
X	WAND_SYM, RING_SYM, POTION_SYM, TOOL_SYM, GEM_SYM, BALL_SYM, ROCK_SYM };
X#define Page_line(x)	if(page_line(x)) goto quit
X
Xvoid
Xoption_help() {
X	char	buf[BUFSZ];
X
X	set_pager(0);
X	Sprintf(buf, "                 NetHack Options Help:");
X	if(page_line("") || page_line(buf) || page_line(""))	 goto quit;
X
X#ifdef MSDOS
X	Sprintf(buf, "To set options use OPTIONS=<options> in %s;", configfile);
X	Page_line(buf);
X#else
X	Page_line("To set options use `NETHACKOPTIONS=\"<options>\"' in your environment;");
X#endif
X
X	Page_line("or press \"O\" while playing, and type your <options> at the prompt.");
X	Page_line("In either case, <options> is a list of options separated by commas.");
X	Page_line("");
X
X	Page_line("Boolean options (which can be negated by prefixing them with '!' or \"no\"):");
X	Page_line("confirm, (fe)male, fixinv, pickup, rest_on_space, safe_pet, silent, sortpack,");
X#ifdef MSDOS
X#ifdef NEWS
X	Page_line("time, tombstone, verbose, news, number_pad, rawio, and IBM_BIOS");
X#else
X	Page_line("time, tombstone, verbose, number_pad, rawio, and IBM_BIOS");
X#endif
X#ifdef DECRAINBOW
X	Page_line("and DEC_Rainbow.");
X#endif /* DECRAINBOW */
X#else /* MSDOS */
X#ifdef NEWS
X	Page_line("time, tombstone, verbose, news, null, ignintr, and standout.");
X#else
X	Page_line("time, tombstone, verbose, null, ignintr, and standout.");
X#endif
X#endif /* MSDOS */
X	Page_line("");
X
X	Page_line("Compound options:");
X	Page_line("`name'      - your character's name (e.g., name:Merlin-W),");
X	Page_line("`dogname'   - the name of your (first) dog (e.g., dogname:Fang),");
X
X	Page_line("`packorder' - the inventory order of the items in your pack");
X	Sprintf(buf, "              (currently, packorder:%s ),", packorder);
X	Page_line(buf);
X	Page_line("`fruit'     - the name of a fruit you enjoy eating,");
X
X	Page_line("`endgame'   - the parts of the score list you wish to see,");
X
X	Page_line("`graphics'  - defines the symbols to use in drawing the dungeon map.");
X	Page_line("");
X	Page_line("Some of the options can be set only before the game is started.  You will");
X	Page_line("be so informed, if you attempt to set them while in the game.");
X	set_pager(1);
X	return;
Xquit:
X	set_pager(2);
X	return;
X}
X
X/* Returns the fid of the fruit type; if that type already exists, it
X * returns the fid of that one; if it does not exist, it adds a new fruit
X * type to the chain and returns the new one.
X */
Xint
Xfruitadd(str)
Xchar *str;
X{
X	register int i,j;
X	register struct fruit *f;
X	struct fruit *lastf;
X	int highest_fruit_id = 0;
X	char buf[PL_FSIZ];
X	boolean user_specified = (str == pl_fruit);
X	/* if not user-specified, then it's a fruit name for a fruit on
X	 * a bones level...
X	 */
X
X	/* Note: every fruit has an id (spe for fruit objects) of at least
X	 * 1; 0 is an error.
X	 */
X	if (user_specified) {
X		/* disallow naming after other foods (since it'd be impossible
X		 * to tell the difference)
X		 */
X
X		boolean found = FALSE;
X
X		for(i = bases[j=letindex(FOOD_SYM)]; i < bases[j+1]; i++) {
X			if (!strcmp(objects[i].oc_name, pl_fruit)) {
X				found = TRUE;
X				break;
X			}
X		}
X		if (found ||
X		    (!strncmp(buf, "tin of ", 7) && name_to_mon(buf+7) > -1) ||
X		    !strcmp(buf, "empty tin") ||
X		    !strcmp(buf, "tin of spinach") ||
X		    (!strncmp(eos(buf)-6," corpse",6) && name_to_mon(buf) > -1))
X			{
X				Strcpy(buf, pl_fruit);
X				Strcpy(pl_fruit, "candied ");
X				nmcpy(pl_fruit+8, buf, PL_FSIZ-8);
X		}
X	}
X	for(f=ffruit; f; f = f->nextf) {
X		lastf = f;
X		if(f->fid > highest_fruit_id) highest_fruit_id = f->fid;
X		if(!strncmp(str, f->fname, PL_FSIZ))
X			goto nonew;
X	}
X	/* if adding another fruit would overflow spe, use a random
X	   fruit instead... we've got a lot to choose from. */
X	if (highest_fruit_id >= 127) return rnd(127);
X	highest_fruit_id++;
X	f = newfruit();
X	if (ffruit) lastf->nextf = f;
X	else ffruit = f;
X	Strcpy(f->fname, str);
X	f->fid = highest_fruit_id;
X	f->nextf = 0;
Xnonew:
X	if (user_specified) current_fruit = highest_fruit_id;
X	return f->fid;
X}
END_OF_FILE
if test 16326 -ne `wc -c <'src/options.c'`; then
    echo shar: \"'src/options.c'\" unpacked with wrong size!
fi
# end of 'src/options.c'
fi
echo shar: End of archive 18 \(of 38\).
cp /dev/null ark18isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 38 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0