[comp.sources.games] v10i073: nethack3p9 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 73
Archive-name: nethack3p9/Part28
Supersedes: NetHack3: Volume 7, Issue 56-93



#! /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 28 (of 56)."
# Contents:  src/do.c src/options.c
# Wrapped by billr@saab on Wed Jul 11 17:11:34 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/do.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/do.c'\"
else
echo shar: Extracting \"'src/do.c'\" \(25176 characters\)
sed "s/^X//" >'src/do.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)do.c	3.0	89/11/20
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/* Contains code for 'd', 'D' (drop), '>', '<' (up, down) */
X
X#include "hack.h"
X#ifndef STUPID_CPP
X/* fortunately, only errno is used from <errno.h> and all known STUPID_CPPs
X * are on UNIX SYSV and will thus all be using the extern int errno; declared
X * below 
X */
X#include <errno.h>
X#endif
X
X#if defined(DGK)
Xextern struct finfo fileinfo[];
X#else
Xextern boolean level_exists[];
X#endif
X
X#ifdef SINKS
X# ifdef OVLB
Xstatic void FDECL(trycall, (struct obj *));
X# endif /* OVLB */
XSTATIC_DCL void FDECL(dosinkring, (struct obj *));
X#endif /* SINKS */
XSTATIC_PTR int FDECL(drop, (struct obj *));
XSTATIC_DCL void NDECL(litter);
XSTATIC_PTR int NDECL(wipeoff);
Xboolean NDECL(drag_down);
X
X#ifdef OVLB
X
Xstatic const char NEARDATA drop_types[] = { '0', GOLD_SYM, '#', 0 };
X
Xint
Xdodrop() {
X	return(drop(getobj(drop_types, "drop")));
X}
X
X#endif /* OVLB */
X#ifdef OVL0
X
X/* Used for objects which sometimes do special things when dropped; must be
X * called with the object not in any chain.  Returns 1 if the object is
X * gone.
X */
Xboolean
Xflooreffects(obj,x,y)
Xstruct obj *obj;
Xint x,y;
X{
X	struct trap *t = t_at(x,y);
X	boolean pool = is_pool(x,y);
X
X	if(obj->otyp == BOULDER && (pool ||
X	  (t && (t->ttyp==PIT || t->ttyp==SPIKED_PIT || t->ttyp==TRAPDOOR)))) {
X	    if (pool) {
X#ifdef STRONGHOLD
X		if(levl[x][y].typ == DRAWBRIDGE_UP)
X		    levl[x][y].drawbridgemask |= DB_FLOOR;
X		else
X#endif
X		    levl[x][y].typ = ROOM;
X		if (cansee(x,y))
X		  pline("There is a large splash as the boulder fills the %s.",
X			(levl[x][y].typ==POOL) ? "pool" : "moat");
X		else if (flags.soundok)
X		    You("hear a splash.");
X	    } else if (t) {
X		if(is_maze_lev
X#ifdef STRONGHOLD
X		 	&& (dlevel > stronghold_level)
X#endif
X			&& t->ttyp == TRAPDOOR) return FALSE;
X		if (Blind) You("hear the boulder roll.");
X		else pline("The boulder %sfills a %s.",
X			t->tseen ? "" : "triggers and ",
X			t->ttyp == TRAPDOOR ? "trap door" : "pit");
X		deltrap(t);
X		if (u.utrap && x==u.ux && y==u.uy) {
X		    u.utrap = 0;
X#ifdef POLYSELF
X		    if (!passes_walls(uasmon)) {
X#endif
X			pline("Unfortunately, you were still in it.");
X			losehp(rnd(15),
X			  self_pronoun("dropped a boulder onto %sself","him"),
X			  NO_KILLER_PREFIX);
X#ifdef POLYSELF
X		    }
X#endif
X		}
X	    }
X	    obfree(obj, (struct obj *)0);
X	    mnewsym(x,y);
X	    if (!vism_at(x,y) && (x != u.ux || y != u.uy || Invisible) && !Blind)
X		newsym(x,y);
X	    return TRUE;
X	}
X	return FALSE;
X}
X
X#endif /* OVL0 */
X#ifdef OVLB
X
X#ifdef ALTARS
Xvoid
Xdoaltarobj(obj)  /* obj is an object dropped on an altar */
X	register struct obj *obj;
X{
X	if (Blind) return;
X	if (obj->blessed || obj->cursed) {
X		pline("There is %s flash as %s hit%s the altar.",
X		      an(Hallucination ? hcolor() :
X			 obj->blessed ? amber : black),
X		      doname(obj),
X		      (obj->quan==1) ? "s" : "");
X		if (!Hallucination) obj->bknown = 1;
X	} else {
X		pline("%s land%s on the altar.", Doname2(obj),
X			(obj->quan==1) ? "s" : "");
X		obj->bknown = 1;
X	}
X}
X#endif
X
X#ifdef SINKS
Xstatic
Xvoid
Xtrycall(obj)
Xregister struct obj *obj;
X{
X	if(!objects[obj->otyp].oc_name_known &&
X	   !objects[obj->otyp].oc_uname)
X	   docall(obj);
X}
X
XSTATIC_OVL
Xvoid
Xdosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */
Xregister struct obj *obj;
X{
X	register struct obj *otmp,*otmp2;
X	register boolean ideed = TRUE;
X
X	You("drop %s down the drain.", doname(obj));
X	switch(obj->otyp) {	/* effects that can be noticed without eyes */
X	    case RIN_SEARCHING:
X		You("thought your %s got lost in the sink, but there it is!",
X			xname(obj));
X		dropx(obj);
X		trycall(obj);
X		return;
X	    case RIN_LEVITATION:
X		pline("The sink quivers upward for a moment.");
X		break;
X	    case RIN_POISON_RESISTANCE:
X#ifdef TUTTI_FRUTTI
X		You("smell rotten %s.", makeplural(pl_fruit));
X#else
X		You("smell rotten fruit.");
X#endif
X		break;
X	    case RIN_AGGRAVATE_MONSTER:
X		pline("Several flies buzz angrily around the sink.");
X		break;
X	    case RIN_SHOCK_RESISTANCE:
X		pline("Static electricity surrounds the sink.");
X		break;
X	    case RIN_CONFLICT:
X		You("hear loud noises coming from the drain.");
X		break;
X	    case RIN_GAIN_STRENGTH:
X		pline("The water flow seems %ser now.",
X			(obj->spe<0) ? "weak" : "strong");
X		break;
X	    case RIN_INCREASE_DAMAGE:
X		pline("The water's force seems %ser now.",
X			(obj->spe<0) ? "small" : "great");
X		break;
X	    default:
X		ideed = FALSE;
X		break;
X	}
X	if(!Blind && !ideed) {
X	    ideed = TRUE;
X	    switch(obj->otyp) {		/* effects that need eyes */
X		case RIN_ADORNMENT:
X		    pline("The faucets flash brightly for a moment.");
X		    break;
X		case RIN_REGENERATION:
X		    pline("The sink looks as good as new.");
X		    break;
X		case RIN_INVISIBILITY:
X		    You("don't see anything happen to the sink.");
X		    break;
X		case RIN_SEE_INVISIBLE:
X		    You("see some air in the sink.");
X		    break;
X		case RIN_STEALTH:
X		pline("The sink seems to blend into the floor for a moment.");
X		    break;
X		case RIN_HUNGER:
X		    ideed = FALSE;
X		    for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
X			otmp2 = otmp->nexthere;
X			if(otmp != uball && otmp != uchain) {
X			    pline("Suddenly, %s vanishes from the sink!",
X							doname(otmp));
X			    delobj(otmp);
X			    ideed = TRUE;
X			}
X		    }
X		    break;
X		case RIN_FIRE_RESISTANCE:
X		pline("The hot water faucet flashes brightly for a moment.");
X		    break;
X		case RIN_COLD_RESISTANCE:
X		pline("The cold water faucet flashes brightly for a moment.");
X		    break;
X		case RIN_PROTECTION_FROM_SHAPE_CHAN:
X		    pline("The sink looks nothing like a fountain.");
X		    break;
X		case RIN_PROTECTION:
X		    pline("The sink glows %s for a moment.",
X			    Hallucination ? hcolor() :
X			    (obj->spe<0) ? black : silver);
X		    break;
X		case RIN_WARNING:
X		    pline("The sink glows %s for a moment.",
X			    Hallucination ? hcolor() : white);
X		    break;
X		case RIN_TELEPORTATION:
X		    pline("The sink momentarily vanishes.");
X		    break;
X		case RIN_TELEPORT_CONTROL:
X	    pline("The sink looks like it is being beamed aboard somewhere.");
X		    break;
X#ifdef POLYSELF
X		case RIN_POLYMORPH:
X		    pline("The sink momentarily looks like a fountain.");
X		    break;
X		case RIN_POLYMORPH_CONTROL:
X	pline("The sink momentarily looks like a regularly erupting geyser.");
X		    break;
X#endif
X	    }
X	}
X	if(ideed)
X	    trycall(obj);
X	else
X	    You("hear the ring bouncing down the drainpipe.");
X	if (!rn2(20)) {
X		pline("The sink backs up, leaving %s.", doname(obj));
X		dropx(obj);
X	}
X	else
X		useup(obj);
X}
X#endif
X
X#endif /* OVLB */
X#ifdef OVL0
X
X/* some common tests when trying to drop or throw items */
Xboolean
Xcanletgo(obj,word)
Xregister struct obj *obj;
Xregister const char *word;
X{
X	if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
X	       if (*word)
X			You("cannot %s something you are wearing.",word);
X		return(FALSE);
X	}
X	if (obj->otyp == LOADSTONE && obj->cursed) {
X		if (*word)
X			pline("For some reason, you cannot %s the stone%s!",
X				word,
X		      		plur((long)obj->quan));
X		/* Kludge -- see invent.c */
X		if (obj->corpsenm) {
X			struct obj *otmp;
X
X			otmp = obj;
X			obj = obj->nobj;
X			obj->quan += otmp->quan;
X			obj->owt = weight(obj);
X			freeinv(otmp);
X			obfree(otmp, obj);
X		}
X		obj->bknown = 1;
X		return(FALSE);
X	}
X#ifdef WALKIES
X	if (obj->otyp == LEASH && obj->leashmon != 0) {
X	       if (*word)
X			pline ("The leash is tied around your %s.",
X					body_part(HAND));
X		return(FALSE);
X	}
X#endif
X	return(TRUE);
X}
X
XSTATIC_PTR
Xint
Xdrop(obj) register struct obj *obj; {
X	if(!obj) return(0);
X	if(obj->olet == GOLD_SYM) {		/* pseudo object */
X		register long amount = OGOLD(obj);
X
X/* Fix bug with dropping huge amounts of gold read as negative    KAA */
X		if(amount < 0) {
X			u.ugold += amount;
X	pline("The LRS would be very interested to know you have that much.");
X		} else {
X			/* uswallow test added by GAN 01/29/87 */
X			if(flags.verbose)
X			    You("drop %ld gold piece%s.",
X				   amount, plur(amount));
X			if(u.uswallow)
X				(u.ustuck)->mgold += amount;
X			else {
X				mkgold(amount, u.ux, u.uy);
X				if(Invisible) newsym(u.ux, u.uy);
X			}
X		}
X		free((genericptr_t) obj);
X		return(1);
X	}
X	if(!canletgo(obj,"drop"))
X		return(0);
X	if(obj == uwep) {
X		if(welded(uwep)) {
X			weldmsg(obj, FALSE);
X			return(0);
X		}
X		setuwep((struct obj *)0);
X		if(uwep) return 0; /* lifesaved and rewielded */
X	}
X#ifdef SINKS
X	if((obj->olet == RING_SYM) && IS_SINK(levl[u.ux][u.uy].typ)
X							&& !u.uswallow) {
X		dosinkring(obj);
X		return(1);
X	}
X#endif
X#ifdef ALTARS
X	if (IS_ALTAR(levl[u.ux][u.uy].typ) && !u.uswallow) {
X		/* turn water into [(un)holy] water */
X		if (obj->otyp == POT_WATER) {
X			obj->blessed = !!(levl[u.ux][u.uy].altarmask & A_LAW);
X			obj->cursed =
X			    !(levl[u.ux][u.uy].altarmask & (A_LAW | A_NEUTRAL));
X		}
X		doaltarobj(obj);	/* set bknown */
X	} else
X#endif
X	if(flags.verbose) You("drop %s.", doname(obj));
X	dropx(obj);
X	return(1);
X}
X
X/* Called in several places - should not produce texts */
Xvoid
Xdropx(obj)
Xregister struct obj *obj;
X{
X	freeinv(obj);
X	dropy(obj);
X}
X
Xvoid
Xdropy(obj)
Xregister struct obj *obj;
X{
X	if (flooreffects(obj,u.ux,u.uy)) return;
X#ifdef WORM
X	if(obj->otyp == CRYSKNIFE)
X		obj->otyp = WORM_TOOTH;
X#endif
X	/* uswallow check done by GAN 01/29/87 */
X	if(u.uswallow)
X		mpickobj(u.ustuck,obj);
X	else  {
X		obj->nobj = fobj;
X		fobj = obj;
X		place_object(obj, u.ux, u.uy);
X		if(Invisible) newsym(u.ux,u.uy);
X		if(obj != uball) sellobj(obj);
X		stackobj(obj);
X	}
X}
X
X/* drop several things */
Xint
Xdoddrop() {
X	return(ggetobj("drop", drop, 0));
X}
X
X#endif /* OVL0 */
X#ifdef OVL2
X
X#ifdef STRONGHOLD
Xstatic boolean NEARDATA at_ladder = FALSE;	/* on a ladder, used in goto_level */
X#endif
X
Xint
Xdodown()
X{
X	struct trap *trap = 0;
X
X	if((u.ux != xdnstair || u.uy != ydnstair)
X#ifdef STRONGHOLD
X	   && (!xdnladder || u.ux != xdnladder || u.uy != ydnladder)
X#endif
X	  ) {
X		if (!(trap = t_at(u.ux,u.uy)) || trap->ttyp != TRAPDOOR
X			|| (is_maze_lev
X#ifdef STRONGHOLD
X				&& (dlevel > stronghold_level)
X#endif
X								)
X							|| !trap->tseen) {
X			You("can't go down here.");
X			return(0);
X		}
X	}
X	if(u.ustuck) {
X		You("are being held, and cannot go down.");
X		return(1);
X	}
X	if(Levitation) {
X		pline("You're floating high above the %s.",
X			levl[u.ux][u.uy].typ == STAIRS ? "stairs" :
X#ifdef STRONGHOLD
X			levl[u.ux][u.uy].typ == LADDER ? "ladder" :
X#endif
X			"trap door");
X		return(0);
X	}
X
X#ifdef WALKIES
X	if(!next_to_u()) {
X		You("are held back by your pet!");
X		return(0);
X	} else {
X#endif
X		unsee();
X#ifdef STRONGHOLD
X		if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
X#endif
X		if (trap)
X#ifdef POLYSELF
X			You("%s into the trap door.",
X				locomotion(uasmon, "jump"));
X#else
X			You("jump into the trap door.");
X#endif
X		goto_level(dlevel+1, !trap, TRUE);
X#ifdef STRONGHOLD
X		at_ladder = FALSE;
X#endif
X#ifdef WALKIES
X	}
X#endif
X	return(1);
X}
X
Xint
Xdoup()
X{
X	if((u.ux != xupstair || u.uy != yupstair)
X#ifdef STRONGHOLD
X	   && (!xupladder || u.ux != xupladder || u.uy != yupladder)
X#endif
X	  ) {
X		You("can't go up here.");
X		return(0);
X	}
X	if(u.ustuck) {
X		You("are being held, and cannot go up.");
X		return(1);
X	}
X#ifdef POLYSELF
X	/* Some monsters have carrying capacities less than 5, and we don't
X	 * want to totally keep them from going upstairs.
X	 */
X	if((invent || u.ugold) && inv_weight() + 5 > 0) {
X#else
X	if(inv_weight() + 5 > 0) {
X#endif
X		/* No levitation check; inv_weight() already allows for it */
X#ifdef STRONGHOLD
X		Your("load is too heavy to climb the %s.",
X		      levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
X#else
X		Your("load is too heavy to climb the stairs.");
X#endif
X		return(1);
X	}
X	if (dlevel == 1) {
X#ifdef MACOS
X		if(!flags.silent) SysBeep(20);
X		if(UseMacAlertText(128,
X		    "Beware, there will be no return!  Still climb?") != 1) {
X			return 0;
X		}
X#else
X		pline("Beware, there will be no return!  Still climb? ");
X		if (yn() != 'y') return(0);
X#endif /* MACOS */
X	}
X#ifdef WALKIES
X	if(!next_to_u()) {
X		You("are held back by your pet!");
X		return(0);
X	} else {
X#endif
X		unsee();
X#ifdef STRONGHOLD
X		if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
X		goto_level(dlevel-1, 
X		    (dlevel-1 < stronghold_level || (at_ladder && 
X		       dlevel-1 >= tower_level && dlevel-1 < tower_level+2)),
X			   FALSE);
X		at_ladder = FALSE;
X#else
X		goto_level(dlevel-1, (dlevel-1 <= medusa_level), FALSE);
X#endif
X#ifdef WALKIES
X	}
X#endif
X	return(1);
X}
X
X#endif /* OVL2 */
X#ifdef OVLB
X
XSTATIC_OVL
Xvoid
Xlitter()
X{
X	struct obj *otmp = invent, *nextobj;
X	int capacity = weight_cap();
X
X	while (otmp) {
X		nextobj = otmp->nobj;
X		if ((otmp != uball) && (rnd(capacity) <= otmp->owt)) {
X			if (otmp == uwep)
X				setuwep((struct obj *)0);
X			if ((otmp != uwep) && (canletgo(otmp, ""))) {
X				Your("%s you down the stairs.",
X				     aobjnam(otmp, "follow"));
X				dropx(otmp);
X			}
X		}
X		otmp = nextobj;
X	}
X}
X
Xboolean
Xdrag_down()
X{
X	boolean forward;
X	uchar dragchance = 3;
X
X
X	/* 
X		Assume that the ball falls forward if:
X
X		a) the character is wielding it, or
X		b) the character has both hands available to hold it (i.e. is 
X		   not wielding any weapon), or 
X		c) (perhaps) it falls forward out of his non-weapon hand
X	*/
X
X	forward = (!(carried(uball))? 
X		  FALSE : ((uwep == uball) || (!uwep))? 
X			  TRUE : (boolean)(rn2(3) / 2));
X
X	if (carried(uball)) 
X		You("lose your grip on the iron ball.");
X
X	if(forward) {
X		if(rn2(6)) {
X			You("get dragged downstairs by the iron ball.");
X			losehp(rnd(6), "dragged downstairs by an iron ball",
X				NO_KILLER_PREFIX);
X			return(TRUE);
X		}
X	} else {
X		if(rn2(2)) {
X			pline("The iron ball smacks into you!");
X			losehp(rnd(20), "iron ball collision", KILLED_BY_AN);
X			dragchance -= 2;
X		} 
X		if(dragchance >= rnd(6)) {
X			You("get dragged downstairs by the iron ball.");
X			losehp(rnd(3), "dragged downstairs by an iron ball",
X				NO_KILLER_PREFIX);
X			return(TRUE);
X		}
X	}
X	return(FALSE);
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
Xint save_dlevel = 0;
X
Xvoid
Xgoto_level(newlevel, at_stairs, falling)
Xregister int newlevel;
Xregister boolean at_stairs, falling;
X{
X	register int fd;
X	register boolean up = (newlevel < dlevel);
X
X#ifdef ENDGAME
X	if(dlevel == ENDLEVEL) return;	/* To be on the safe side.. */
X#endif
X	if(newlevel > MAXLEVEL) newlevel = MAXLEVEL;
X	if(newlevel <= 0)
X#ifdef ENDGAME
X	    if(u.uhave_amulet)
X		newlevel = ENDLEVEL;	/* Endgame Level !!! */
X	    else
X#endif
X		done(ESCAPED);		/* in fact < 0 is impossible */
X
X#ifdef MACOS
X	freeSegs(&segments);
X#endif
X/*	If you have the amulet and are trying to get out of Hell, going
X *	up a set of stairs sometimes does some very strange things!
X */
X#ifdef HARD
X	if(Inhell && up && !at_ladder &&
X			(dlevel < MAXLEVEL-3) && u.uhave_amulet) {
X	    int olev = newlevel;
X
X	    newlevel = (rn2(4) ? newlevel :
X/* neutral */	     !u.ualigntyp ? (rn2(2) ? dlevel : dlevel + (rnd(5) - 2)) :
X/* lawful */	     (u.ualigntyp == U_LAWFUL) ? dlevel + (rnd(5) - 2) :
X/* chaotic */	     dlevel);
X	    if(newlevel < 1) newlevel = dlevel;
X	    if(newlevel != olev)
X	        pline("A mysterious force momentarily surrounds you...");
X	    if(newlevel == dlevel) {
X		(void) dotele();
X		return;
X	    }
X	}
X#endif /* HARD /* */
X	if(newlevel == dlevel) return;	      /* this can happen */
X#ifdef STRONGHOLD
X	/* In Nethack 3.0, Hell starts after the stronghold.  Moreover,
X	 * there are traps in the stronghold, that can send the player
X	 * to hell (gnark, gnark)!  So we have to test here:
X	 */
X	if(!Inhell && newlevel > stronghold_level && !up && !at_ladder
X# ifdef ENDGAME
X	&& newlevel < ENDLEVEL
X# endif
X	) {
X#else
X	if(!Inhell && newlevel >= HELLLEVEL && !up) {
X#endif /* STRONGHOLD /**/
X	    You("arrive at the center of the earth...");
X	    pline("Unfortunately, it is here that hell is located.");
X#ifdef MSDOS
X	    (void) fflush(stdout);
X#endif
X	    if(Fire_resistance) {
X		pline("But the fire doesn't seem to harm you.");
X	    } else {
X		save_dlevel = dlevel;
X		You("burn to a crisp.");
X		You("die...");
X		dlevel = maxdlevel = newlevel;
X		killer_format = KILLED_BY_AN;
X		killer = "visit to hell";
X		done(BURNING);
X		dlevel = newlevel = save_dlevel; /* in case they survive */
X		save_dlevel = 0;
X	    }
X	}
X
X	glo(dlevel);
X#ifdef MSDOS
X	/* Use O_TRUNC to force the file to be shortened if it already
X	 * exists and is currently longer.
X	 */
X	fd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
X#else
X# ifdef MACOS
X	{
X		Str255	fileName;
X		OSErr	er;
X		short	refNum;
X		struct term_info	*t;
X		extern WindowPtr	HackWindow;
X		
X		t = (term_info *)GetWRefCon(HackWindow);
X		fileName[0] = (char)strlen(lock);
X		Strcpy((char *)&fileName[1],lock);
X		if (FSOpen(fileName, t->system.sysVRefNum, &refNum)) {
X				if (er = Create(&fileName,t->system.sysVRefNum,
X							CREATOR,LEVEL_TYPE))
X					SysBeep(20);
X		} else {
X			(void)SetEOF(refNum,0L);
X			(void)FSClose(refNum);
X		}
X		SetVol(0L,t->system.sysVRefNum);
X		fd = open(lock,O_WRONLY | O_BINARY | ((er) ? O_CREAT : 0));
X	}
X# else
X	fd = creat(lock, FCMASK);
X# endif /* MACOS */
X#endif
X	if(fd < 0) {
X		/*
X		 * This is not quite impossible: e.g., we may have
X		 * exceeded our quota. If that is the case then we
X		 * cannot leave this level, and cannot save either.
X		 * Another possibility is that the directory was not
X		 * writable.
X		 */
X#ifdef DGK
X		pline("Cannot create level file '%s'.", lock);
X#else
X		pline("A mysterious force prevents you from going %s.",
X			up ? "up" : "down");
X#endif
X		return;
X	}
X
X#ifdef DGK
X	if (!savelev(fd, dlevel, COUNT)) {
X# ifdef ZEROCOMP
X		bflush(fd);
X# endif
X		(void) close(fd);
X		(void) unlink(lock);
X		pline("NetHack is out of disk space for making levels!");
X		You("can save, quit, or continue playing.");
X		return;
X	}
X#endif
X	if(Punished) unplacebc();
X	u.utrap = 0;				/* needed in level_tele */
X	u.ustuck = 0;				/* idem */
X	keepdogs();
X	seeoff(1);
X	if(u.uswallow)				/* idem */
X		u.uswldtim = u.uswallow = 0;
X	flags.nscrinh = 1;
X	u.ux = u.ux0 = FAR;				/* hack */
X	(void) inshop();			/* probably was a trap door */
X
X#ifdef DGK
X# ifdef ZEROCOMP
X	bflush(fd);	/* forget buffer */
X# endif
X	savelev(fd,dlevel, WRITE);
X#else
X	savelev(fd,dlevel);
X#endif
X#ifdef ZEROCOMP
X	bflush(fd);	/* flush buffer */
X#endif
X	(void) close(fd);
X#ifdef REINCARNATION
X	if (newlevel == rogue_level || dlevel == rogue_level) {
X		/* No graphics characters on Rogue levels */
X		if (dlevel != rogue_level) {
X			(void) memcpy((genericptr_t)savesyms,
X				      (genericptr_t)showsyms, sizeof savesyms);
X			(void) memcpy((genericptr_t)showsyms,
X				      (genericptr_t)defsyms, sizeof showsyms);
X			showsyms[S_vodoor] = showsyms[S_hodoor] = 
X			    showsyms[S_ndoor] = '+';
X		}
X		if (newlevel != rogue_level)
X			(void) memcpy((genericptr_t)showsyms,
X				      (genericptr_t)savesyms, sizeof showsyms);
X	}
X#endif
X	dlevel = newlevel;
X	if(maxdlevel < dlevel)
X		maxdlevel = dlevel;
X	glo(dlevel);
X	if(
X# ifdef ENDGAME
X	   dlevel == ENDLEVEL ||
X# endif
X#if defined(DGK)
X	/* If the level has no .where yet, it hasn't been made */
X	   !fileinfo[dlevel].where)
X#else
X	   !level_exists[dlevel])
X#endif
X		mklev();
X	else {
X#if defined(DGK)
X		/* If not currently accessible, swap it in. */
X		if (fileinfo[dlevel].where != ACTIVE)
X			swapin_file(dlevel);
X#endif
X#if (defined(MSDOS) && !defined(TOS)) || defined(MACOS)
X		if((fd = open(lock, O_RDONLY | O_BINARY)) < 0) {
X#else
X		if((fd = open(lock,0)) < 0) {
X#endif
X			extern int errno;
X			pline("Cannot open \"%s\" (errno %d).", lock, errno);
X			pline("Probably someone removed it.");
X			done(TRICKED);
X		}
X#ifdef ZEROCOMP
X		minit();
X#endif
X		getlev(fd, hackpid, dlevel, FALSE);
X		(void) close(fd);
X	}
X
X#ifdef MACOS
X	{
X		OSErr	er;
X		struct term_info	*t;
X		extern WindowPtr	HackWindow;
X		
X		t = (term_info *)GetWRefCon(HackWindow);
X		SetVol(0L,t->system.sysVRefNum);
X	}
X#endif
X#ifdef ENDGAME
X	if(dlevel != ENDLEVEL)
X#endif
X	if(at_stairs) {
X	    if(up) {
X#ifdef STRONGHOLD
X		if (!at_ladder) {
X#endif
X		    u.ux = xdnstair;
X		    u.uy = ydnstair;
X#ifdef STRONGHOLD
X		} else {
X		    u.ux = xdnladder;
X		    u.uy = ydnladder;
X		}
X#endif
X/* Remove bug which crashes with levitation/punishment  KAA */
X		if(Punished) {
X		    if(!Levitation)
X#ifdef STRONGHOLD
X			pline("With great effort you climb the %s.",
X			      !at_ladder ? "stairs" : "ladder");
X#else
X			pline("With great effort you climb the stairs.");
X#endif
X		    placebc(1);
X		}
X	    } else {
X#ifdef STRONGHOLD
X		if (!at_ladder) {
X#endif
X		    u.ux = xupstair;
X		    u.uy = yupstair;
X#ifdef STRONGHOLD
X		} else {
X		    u.ux = xupladder;
X		    u.uy = yupladder;
X		}
X#endif
X		if(at_stairs && !up && ((inv_weight() + 5 > 0) || 
X					Punished || Fumbling)) {
X#ifdef STRONGHOLD
X			You("fall down the %s.",
X			    !at_ladder ? "stairs" : "ladder");
X#else
X			You("fall down the stairs.");
X#endif
X			if (Punished) {
X				if (drag_down())
X					litter();
X				if (carried(uball)) {
X					if (uwep == uball)
X						setuwep((struct obj *)0);
X					if (uwep != uball)
X						freeinv(uball);
X				}
X				placebc(1);
X			} 
X			losehp(rnd(3), "falling downstairs", KILLED_BY);
X			selftouch("Falling, you");
X		}
X	    }
X	} else {	/* trap door or level_tele */
X	    register int tryct = 0;
X	    do {
X#ifdef STRONGHOLD
X		/* Prevent teleport-landing inside the castle */
X		if(dlevel == stronghold_level) {
X			if(up) u.ux = (COLNO - rnd(8));
X			else u.ux = rnd(6);
X		}
X		else
X		/* Prevent teleport-landing inside Vlad's tower */
X		if(dlevel >= tower_level && dlevel <= tower_level+2) {
X			do {
X			    u.ux = rnd(COLNO-1);
X			} while (u.ux > 29 && u.ux < 47); 
X		}
X		else
X#endif
X		u.ux = rnd(COLNO-1);
X		u.uy = rn2(ROWNO);
X	    } while(tryct++ < 100 && (levl[u.ux][u.uy].typ != ROOM &&
X		     levl[u.ux][u.uy].typ != CORR) || MON_AT(u.ux, u.uy));
X	    if(tryct >= 100)
X		panic("goto_level: could not relocate player!");
X	    if(Punished) {
X		if(falling) {
X			boolean gets_hit;
X
X			gets_hit = (uwep == uball)? FALSE : (boolean)rn2(5);
X			if (carried(uball)) {
X				pline("Startled, you drop the iron ball.");
X				if (uwep == uball)
X					setuwep((struct obj *)0);
X				if (uwep != uball)
X					freeinv(uball);
X			} 
X			if(gets_hit){
X					pline("The iron ball falls on your %s.",
X					body_part(HEAD));
X				if (uarmh)
X					Your("helmet doesn't help too much...");
X				losehp(rnd(25),
X					"Crunched in the head by an iron ball",
X					NO_KILLER_PREFIX);
X			}
X		}
X		placebc(1);
X	    }
X	    if(falling)
X		selftouch("Falling, you");
X	}
X	(void) inshop();
X	initrack();
X
X	losedogs();
X	if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy));
X	if(MON_AT(u.ux, u.uy)) {
X		impossible("mnexto failed (do.c)?");
X		rloc(m_at(u.ux, u.uy));
X	}
X	flags.nscrinh = 0;
X	setsee();
X	seeobjs();	/* make old cadavers disappear - riv05!a3 */
X	docrt();
X	if(!flags.nopick && (OBJ_AT(u.ux, u.uy) || levl[u.ux][u.uy].gmask))
X	    pickup(1);
X	else read_engr_at(u.ux,u.uy);
X#ifdef HARD
X	/* Final confrontation */
X	if (dlevel == 1 && u.uhave_amulet && flags.no_of_wizards == 0)
X	    resurrect();
X#endif
X	is_maze_lev = (rooms[0].hx < 0
X#ifdef STRONGHOLD
X		|| dlevel == stronghold_level
X		|| (dlevel >= tower_level && dlevel <= tower_level + 2)
X#endif
X#ifdef ENDGAME
X		|| dlevel == ENDLEVEL
X#endif
X		);
X#ifdef MACOS
X	freeSegs(&segments);
X	segments = SEG_DO;
X#endif
X}
X
X#endif /* OVL2 */
X#ifdef OVL3
X
Xint
Xdonull() {
X	return(1);	/* Do nothing, but let other things happen */
X}
X
X#endif /* OVL3 */
X#ifdef OVLB
X
XSTATIC_PTR int
Xwipeoff() {
X	if(u.ucreamed < 4)	u.ucreamed = 0;
X	else			u.ucreamed -= 4;
X	if (Blinded < 4)	Blinded = 0;
X	else			Blinded -= 4;
X	if (!Blinded) {
X		pline("You've got the glop off.");
X		u.ucreamed = 0;
X		make_blinded(0L,TRUE);
X		return(0);
X	} else if (!u.ucreamed) {
X		Your("%s feels clean now.", body_part(FACE));
X		return(0);
X	}
X	return(1);		/* still busy */
X}
X
Xint
Xdowipe()
X{
X	if(u.ucreamed)  {
X		static char NEARDATA buf[39];
X
X		Sprintf(buf, "wiping off your %s", body_part(FACE));
X		set_occupation(wipeoff, buf, 0);
X		/* Not totally correct; what if they change back after now
X		 * but before they're finished wiping?
X		 */
X		return(1);
X	}
X	Your("%s is already clean.", body_part(FACE));
X	return(1);
X}
X
X#endif /* OVLB */
X#ifdef OVL1
X
X/* split obj so that it gets size num */
X/* remainder is put in the object structure delivered by this call */
Xstruct obj *
Xsplitobj(obj, num) register struct obj *obj; register int num; {
Xregister struct obj *otmp;
X	otmp = newobj(obj->onamelth);
X	*otmp = *obj;		/* copies whole structure */
X	otmp->o_id = flags.ident++;
X	obj->quan = num;
X	obj->owt = weight(obj);
X	otmp->quan -= num;
X	otmp->owt = weight(otmp);	/* -= obj->owt ? */
X	obj->nobj = obj->nexthere = otmp;
X	if (obj->onamelth)
X		(void)strncpy(ONAME(otmp), ONAME(obj), (int)obj->onamelth);
X	if(obj->unpaid) splitbill(obj,otmp);
X	return(otmp);
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xvoid
Xset_wounded_legs(side, timex)
Xregister long side;
Xregister int timex;
X{
X	if(!Wounded_legs) {
X		ATEMP(A_DEX)--;
X		flags.botl = 1;
X	}
X
X	if(!Wounded_legs || (Wounded_legs & TIMEOUT))
X		Wounded_legs |= side + timex;
X	else
X		Wounded_legs |= side;
X}
X
Xvoid
Xheal_legs()
X{
X	if(Wounded_legs) {
X		if (ATEMP(A_DEX) < 0) ATEMP(A_DEX)++;
X
X		if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) {
X			Your("%s feel somewhat better.",
X				makeplural(body_part(LEG)));
X		} else {
X			Your("%s feels somewhat better.",
X				body_part(LEG));
X		}
X		Wounded_legs = 0;
X	}
X}
X
X#endif /* OVLB */
END_OF_FILE
if test 25176 -ne `wc -c <'src/do.c'`; then
    echo shar: \"'src/do.c'\" unpacked with wrong size!
fi
# end of 'src/do.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'\" \(30155 characters\)
sed "s/^X//" >'src/options.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)options.c	3.0	89/11/15
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X#include "termcap.h"
X
Xstatic boolean NEARDATA set_order;
X
Xstatic void FDECL(nmcpy, (char *, const char *, int));
Xvoid FDECL(escapes,(const char *, char *));
X
X#ifdef AMIGA_WBENCH
Xextern int FromWBench;
X#endif
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 = 3;
X	flags.end_around = 2;
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#ifdef TUTTI_FRUTTI
X	nmcpy(pl_fruit, objects[SLIME_MOLD].oc_name, PL_FSIZ);
X#endif
X	flags.num_pad = FALSE;
X	flags.help = TRUE;
X	flags.IBMgraphics = FALSE;
X	flags.DECgraphics = FALSE;
X#ifdef TEXTCOLOR
X	flags.use_color = TRUE;
X#endif
X#ifdef AMIFLUSH
X	flags.amiflush = FALSE;	/* default to original behaviour */
X#endif
X#ifdef MSDOS
X#ifdef DGK
X	flags.IBMBIOS =
X#ifdef TOS
X	TRUE;			/* BIOS might as well always be on for TOS */
X#endif
X	flags.rawio = FALSE;
X#endif
X	read_config_file();
X#endif /* MSDOS */
X#ifdef MACOS
X	read_config_file();
X	flags.standout = TRUE;	
X#endif
X	if(opts = getenv("NETHACKOPTIONS"))
X		parseoptions(opts,TRUE);
X#ifdef TUTTI_FRUTTI
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#endif
X}
X
Xstatic void
Xnmcpy(dest, src, maxlen)
X	char	*dest;
X	const char *src;
X	int	maxlen;
X{
X	int	count;
X
X	for(count = 1; count < maxlen; count++) {
X		if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/
X		*dest++ = *src++;
X	}
X	*dest = 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)
Xconst char	*cp;
Xchar *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	    const 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
Xassign_graphics(graph_ints,glth)
Xregister unsigned int *graph_ints;
Xregister int glth;
X{
X	register int i;
X
X	if (glth > MAXPCHARS) glth = MAXPCHARS;		/* sanity check */
X	for (i = 0; i < glth; i++)
X		showsyms[i] = graph_ints[i];
X	for (i = glth; i < MAXPCHARS; i++)
X		showsyms[i] = defsyms[i];
X}
X
X/*
X * Use the nice IBM Extended ASCII line-drawing characters (codepage 437).
X *
X * OS/2 defaults to a multilingual character set (codepage 850, corresponding
X * to the ISO 8859 character set.  We should probably do a VioSetCp() call to
X * set the codepage to 437.
X */
Xvoid
Xassign_ibm_graphics()
X{
X#ifdef ASCIIGRAPH
X	flags.IBMgraphics = TRUE;	/* not set from command line */
X
X	showsyms[S_vwall] = 0xb3;	/* meta-3, vertical rule */
X	showsyms[S_hwall] = 0xc4;	/* meta-D, horizontal rule */
X	showsyms[S_tlcorn] = 0xda;	/* meta-Z, top left corner */
X	showsyms[S_trcorn] = 0xbf;	/* meta-?, top right corner */
X	showsyms[S_blcorn] = 0xc0;	/* meta-@, bottom left */
X	showsyms[S_brcorn] = 0xd9;	/* meta-Y, bottom right */
X	showsyms[S_crwall] = 0xc5;	/* meta-E, cross */
X	showsyms[S_tuwall] = 0xc1;	/* meta-A, T up */
X	showsyms[S_tdwall] = 0xc2;	/* meta-B, T down */
X	showsyms[S_tlwall] = 0xb4;	/* meta-4, T left */
X	showsyms[S_trwall] = 0xc3;	/* meta-C, T right */
X	showsyms[S_vbeam] = 0xb3;	/* meta-3, vertical rule */
X	showsyms[S_hbeam] = 0xc4;	/* meta-D, horizontal rule */
X	showsyms[S_ndoor] = 0xfa;
X	showsyms[S_vodoor] = 0xfe;	/* meta-~, small centered square */
X	showsyms[S_hodoor] = 0xfe;	/* meta-~, small centered square */
X	showsyms[S_room] = 0xfa;	/* meta-z, centered dot */
X	showsyms[S_pool] = 0xf7;	/* meta-w, approx. equals */
X#endif  /* ASCIIGRAPH */
X}
X
X/* Use VT100 graphics for terminals that have them */
Xvoid
Xassign_dec_graphics()
X{
X#ifdef TERMLIB
X	flags.DECgraphics = TRUE;	/* not set from command line */
X
X	showsyms[S_vwall] = 0xf8;	/* vertical rule */
X	showsyms[S_hwall] = 0xf1;	/* horizontal rule */
X	showsyms[S_tlcorn] = 0xec;	/* top left corner */
X	showsyms[S_trcorn] = 0xeb;	/* top right corner */
X	showsyms[S_blcorn] = 0xed;	/* bottom left */
X	showsyms[S_brcorn] = 0xea;	/* bottom right */
X	showsyms[S_crwall] = 0xee;	/* cross */
X	showsyms[S_tuwall] = 0xf6;	/* T up */
X	showsyms[S_tdwall] = 0xf7;	/* T down */
X	showsyms[S_tlwall] = 0xf5;	/* T left */
X	showsyms[S_trwall] = 0xf4;	/* T right */
X	showsyms[S_vbeam] = 0xf8;	/* vertical rule */
X	showsyms[S_hbeam] = 0xf1;	/* horizontal rule */
X	showsyms[S_ndoor] = 0xfe;
X	showsyms[S_vodoor] = 0xe1;	/* small centered square */
X	showsyms[S_hodoor] = 0xe1;	/* small centered square */
X	showsyms[S_room] = 0xfe;	/* centered dot */
X	showsyms[S_pool] = 0xe0;	/* diamond */
X#endif  /* TERMLIB */
X}
X
Xvoid
Xparseoptions(opts, from_env)
Xregister char *opts;
Xboolean from_env;
X{
X#ifndef MACOS
X	register char *op;
X	unsigned num;
X	boolean negated;
X
X	if(op = index(opts, ',')) {
X		*op++ = 0;
X		parseoptions(op, from_env);
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, "stan", 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, "ign", 3)) {
X		flags.ignintr = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "tomb", 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, "conf", 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, "sil", 3)) {
X		flags.silent = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "verb", 4)) {
X		flags.verbose = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "pick", 4)) {
X		flags.pickup = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "num", 3)) {
X		flags.num_pad = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "hel", 3)) {
X		flags.help = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "IBMg", 4)) {
X		if(from_env) {
X		    flags.IBMgraphics = !negated;
X		    if(flags.IBMgraphics) assign_ibm_graphics();
X		} else {
X#ifdef MSDOS
X		  pline("\"IBMgraphics\" settable only from %s.", configfile);
X#else
X		  pline("IBMgraphics can be set only from NETHACKOPTIONS.");
X#endif
X		}
X		return;
X	}
X
X	if (!strncmp(opts, "DEC", 3)) {
X		if(from_env) {
X		    flags.DECgraphics = !negated;
X		    if(flags.DECgraphics) assign_dec_graphics();
X		} else {
X#ifdef MSDOS
X		  pline("\"DECgraphics\" settable only from %s.", configfile);
X#else
X		  pline("DECgraphics can be set only from NETHACKOPTIONS.");
X#endif
X		}
X		return;
X	}
X
X#ifdef TEXTCOLOR
X	if (!strncmp(opts, "col", 3)) {
X		flags.use_color = !negated;
X		return;
X	}
X#endif
X#ifdef AMIFLUSH
X	if (!strncmp(opts, "flus", 4)) {
X		flags.amiflush = !negated;
X		return;
X	}
X#endif
X#ifdef DGK
X	if (!strncmp(opts, "IBM_", 4)) {
X		flags.IBMBIOS = !negated;
X		return;
X	}
X
X	if (!strncmp(opts, "raw", 3)) {
X		if (from_env)
X			flags.rawio = !negated;
X		else
X			pline("\"rawio\" settable only from %s.", configfile);
X		return;
X	}
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, "pack", 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", 4)) {
X		flags.no_rest_on_space = negated;
X		return;
X	}
X
X	if (!strncmp(opts, "fix", 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, "fem", 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# ifdef AMIGA_WBENCH
X		 if(FromWBench){
X		  pline("\"name\" settable only from %s or in icon.",
X			configfile);
X		 } else
X# endif
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, "gr", 2)) {
X		unsigned int translate[MAXPCHARS+1];
X		int i, lth;
X
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
X		lth = strlen(opts);
X		if(lth > MAXPCHARS) lth = MAXPCHARS;
X		/* match the form obtained from PC configuration files */
X		for(i = 0; i < lth; i++)
X			translate[i] = opts[i];
X		assign_graphics(translate,lth);
X		return;
X	}
X
X	/* endgame:5t[op] 5a[round] o[wn] */
X	if (!strncmp(opts, "end", 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 if(*op == '!') {
X				negated = !negated;
X				op++;
X			}
X			while(*op == ' ') 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) || *op == ' ') ;
X			if(*op == '/') op++;
X		}
X		return;
X	}
X	if (!strncmp(opts, "dog", 3)) {
X		if(!from_env) {
X#ifdef MSDOS
X# ifdef AMIGA_WBENCH
X		if(FromWBench){
X		 pline("\"dogname\" settable only from %s or in icon.",
X			configfile);
X		} else
X# endif
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, "cat", 3)) {
X		if(!from_env) {
X#ifdef MSDOS
X# ifdef AMIGA_WBENCH
X		if(FromWBench){
X		 pline("\"catname\" settable only from %s or in icon.",
X			configfile);
X		} else
X# endif
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#ifdef TUTTI_FRUTTI
X	if (!strncmp(opts, "fr", 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	}
X#endif
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# ifdef AMIGA_WBENCH
X	if(ami_wbench_badopt(opts))
X# endif
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#endif /* MACOS */
X}
X
Xint
Xdoset()
X{
X#ifdef MACOS
X#define	OPTIONS			"Nethack prefs"
X#define OK_BUTTON 1
X#define SAVE_BUTTON 2
X#define CANCEL_BUTTON 3
X#define MIN_CHECKBOX 4
X#define EXPLORE_BOX 4
X#define FEM_BOX 5
X#define NEWS_BOX 6
X#define MIN_OK_CHECKBOX 7
X#define FIXINV_BOX 7
X#define TOMB_BOX 8
X#define TIME_BOX 9
X#define VERBOSE_BOX 10
X#define SILENT_BOX 11
X#define AUTOZOOM_BOX 12
X#define INVERSE_BOX 13
X#define SORT_BOX 14
X#define COLOR_BOX 15
X#define PICKUP_BOX 16
X#define CONFIRM_BOX 17
X#define SAFE_BOX 18
X#define REST_SPACE_BOX 19
X#define MAX_CHECKBOX 19
X#define PLAYER_NAME 20
X#define CAT_NAME 21
X#define DOG_NAME 22
X#define FRUIT_NAME 23
X#define PACKORDER 24
X#define END_TOP 26
X#define END_AROUND 27
X#define FRUIT_TEXT 35
X#define PACK_TEXT 34
X#define ENABLE_INFO_BOX 38
X#define ALT_CURS_BOX 41
X#define ITEMTEXT(item,text) {GetDItem(optionDlg,item,&type,&ItemHndl,&box); \
X					         (void)CtoPstr(text); \
X					         SetIText(ItemHndl,text);\
X					         (void)PtoCstr(text);}
X#define HIDEITEM(item) {GetDItem(optionDlg,item,&type,&ItemHndl,&box); \
X				        HideControl(ItemHndl);\
X				        SetDItem(optionDlg,item,type+128,ItemHndl,&box);}
X#define HIDETEXT(item) {GetDItem(optionDlg,item,&type,&ItemHndl,&box);\
X						SetDItem(optionDlg,item,128+statText,ItemHndl,&box);\
X						SetIText(ItemHndl,"\0");}
X#define SHOWITEM(item) {GetDItem(optionDlg,item,&type,&ItemHndl,&box);\
X						SetDItem(optionDlg,item,type-128,ItemHndl,&box);\
X						ShowControl(ItemHndl);}
X#define GETTEXT(item,maxsize) {GetDItem(optionDlg,item,&type,&ItemHndl,&box);\
X					GetIText (ItemHndl, &tmp_name);\
X					tmp_name[tmp_name[0]+1] = 0;\
X					if (tmp_name[0] > maxsize)\
X						tmp_name[0] = maxsize;}
X	static boolean NEARDATA *flag_ptrs[20] = {0, 0, 0, 0, &flags.explore,
X			&flags.female, &flags.nonews,&flags.invlet_constant,
X			&flags.notombstone, &flags.time, &flags.verbose,
X			&flags.silent, 0, &flags.standout, &flags.sortpack,
X#ifdef TEXTCOLOR
X			&flags.use_color,
X#else
X			0,
X#endif
X			&flags.pickup, &flags.confirm,
X			&flags.safe_dog, &flags.no_rest_on_space};
X	extern short macflags;
X	extern short altCurs;
X	short dlgItem, type;
X	Rect box;
X	extern WindowPtr	HackWindow;
X	Handle ItemHndl;
X	unsigned num;
X	char *op;
X	char tmp_name[256];
X	DialogPtr optionDlg;
X	DialogTHndl	th, centreDlgBox();
X	boolean done = FALSE;
X    short savemacflags = macflags;
X	register char	*sp, *tmp;
X	char a_k_a[PL_NSIZ];
X	boolean fairsex, debugger, explorer;
X
X/* Option handling:
X	Startup: read options from Prefs (making changes!)
X	Save exit: write current options to prefs
X	Cancel exit: revert to options as defined in Prefs
X	Use exit: allow changes. erased at next dialog
X*/
X	strncpy(a_k_a, plname, strlen(plname));
X	a_k_a[(int)strlen(plname)] = '\0';
X	fairsex = flags.female;
X	debugger = flags.debug;
X	explorer = flags.explore;
X	read_config_file();
X	macflags = savemacflags;
X	SetCursor(&ARROW_CURSOR);
X	
X	th = centreDlgBox(130, FALSE);
X
X	optionDlg = GetNewDialog(130, (Ptr)NULL, (WindowPtr)-1);
X/* set initial values of text items */
X	ITEMTEXT(PLAYER_NAME,plname);
X	if(*dogname) ITEMTEXT(DOG_NAME,dogname);
X	if(*catname) ITEMTEXT(CAT_NAME,catname);
X#ifdef TUTTI_FRUTTI
X	if(*pl_fruit) ITEMTEXT(FRUIT_NAME,pl_fruit);
X#else
X	HIDETEXT(FRUIT_NAME);
X	HIDETEXT(FRUIT_TEXT);
X#endif
X	ITEMTEXT(PACKORDER,inv_order);
X/* set initial values of record items */
X	Sprintf(tmp_name,"%u",flags.end_top);
X	ITEMTEXT(END_TOP,tmp_name);
X	Sprintf(tmp_name,"%u",flags.end_around);
X	ITEMTEXT(END_AROUND,tmp_name);
X/* set initial values of checkboxes */
X	for(dlgItem = MIN_CHECKBOX; dlgItem <= MAX_CHECKBOX; dlgItem++) {
X		GetDItem(optionDlg, dlgItem, &type, &ItemHndl, &box);
X		switch (dlgItem){
X			case NEWS_BOX:
X#ifndef NEWS
X				HIDEITEM(NEWS_BOX);
X				break;
X#endif
X			case AUTOZOOM_BOX:
X				SetCtlValue(ItemHndl,macflags & fZoomOnContextSwitch);
X				break;
X#ifndef TEXTCOLOR
X			case COLOR_BOX:
X				HIDEITEM(COLOR_BOX);
X				break;
X#endif
X			default:
X				SetCtlValue(ItemHndl,*(flag_ptrs[dlgItem]));
X		}
X	}
X	GetDItem(optionDlg, ENABLE_INFO_BOX, &type, &ItemHndl, &box);
X	SetCtlValue(ItemHndl, (int)flags.help);
X	GetDItem(optionDlg, ALT_CURS_BOX, &type, &ItemHndl, &box);
X 	SetCtlValue(ItemHndl, (short)altCurs);
X
X	SelIText(optionDlg, PLAYER_NAME, 0, 32767);
X	ShowWindow(optionDlg);
X	GetDItem(optionDlg, OK_BUTTON, &type, &ItemHndl, &box);
X	SetPort (optionDlg);
X	PenSize(3, 3);
X	InsetRect (&box, -4, -4);
X	FrameRoundRect (&box, 16, 16);
X	
X	while(!done) {
X		ModalDialog((ProcPtr)0, &dlgItem);
X		GetDItem(optionDlg, dlgItem, &type, &ItemHndl, &box);
X		if ((dlgItem >= MIN_CHECKBOX && dlgItem <= MAX_CHECKBOX)
X			|| dlgItem == ENABLE_INFO_BOX || dlgItem == ALT_CURS_BOX) {
X			SetCtlValue(ItemHndl, ! GetCtlValue (ItemHndl));
X		}
X		else switch(dlgItem){
X			case SAVE_BUTTON:
X				for(dlgItem = MIN_CHECKBOX; dlgItem <= MAX_CHECKBOX; dlgItem++) {
X					GetDItem(optionDlg, dlgItem, &type, &ItemHndl, &box);
X					if (dlgItem == AUTOZOOM_BOX) {
X						if ((boolean)GetCtlValue(ItemHndl)) {
X							macflags |= fZoomOnContextSwitch;
X						} else {
X							macflags &= ~fZoomOnContextSwitch;
X						}
X					} else {
X						*(flag_ptrs[dlgItem]) = GetCtlValue(ItemHndl);
X					}
X				}
X				GetDItem(optionDlg, ENABLE_INFO_BOX, &type, &ItemHndl, &box);
X				flags.help = GetCtlValue(ItemHndl);
X				GetDItem(optionDlg, ALT_CURS_BOX, &type, &ItemHndl, &box);
X				altCurs = (short)GetCtlValue(ItemHndl);
X				GETTEXT(PLAYER_NAME,PL_NSIZ-1);
X				strncpy(plname, tmp_name, tmp_name[0]+1);
X				(void)PtoCstr (plname);
X			
X				GETTEXT(DOG_NAME,62);
X				strncpy(dogname, tmp_name, tmp_name[0]+1);
X				(void)PtoCstr (dogname);
X			
X				GETTEXT(CAT_NAME,62);
X				strncpy(catname, tmp_name, tmp_name[0]+1);
X				(void)PtoCstr (catname);
X
X#ifdef TUTTI_FRUTTI
X				GETTEXT(FRUIT_NAME,PL_FSIZ-1);
X				strncpy(pl_fruit, tmp_name, tmp_name[0]+1);
X				(void)PtoCstr (pl_fruit);
X#endif
X
X				GETTEXT(PACKORDER,19);
X				op = tmp_name+1;
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))||(index(sp+1, *sp))){
X						for(tmp = sp; *tmp;tmp++)
X							tmp[0]=tmp[1];
X						sp--;
X					}			/* bad or duplicate char in order - remove it*/
X				tmp = (char *) alloc((unsigned)(strlen(inv_order)+1));
X				Strcpy(tmp, op);
X				for (sp = inv_order, num = strlen(tmp); *sp; sp++)
X					if (!index(tmp, *sp)) {
X						tmp[num++] = *sp;
X						tmp[num] = 0;
X					}
X				Strcpy(inv_order, tmp);
X				free((genericptr_t)tmp);
X
X				GETTEXT(END_TOP,5);
X				op = tmp_name+1;
X				while(*op) {
X					num = 1;
X					if(digit(*op)) {
X						num = atoi(op);
X						while(digit(*op)) op++;
X					} else op++;
X				}
X				flags.end_top=num;
X				GETTEXT(END_AROUND,5);
X				op = tmp_name+1;
X				while(*op) {
X					num = 1;
X					if(digit(*op)) {
X						num = atoi(op);
X						while(digit(*op)) op++;
X					} else op++;
X				}
X				flags.end_around = num;
X				
X				write_opts();
X				done = TRUE;
X				break;
X			case CANCEL_BUTTON:
X				done = TRUE;
X				break;
X			case OK_BUTTON:
X				for (dlgItem = MIN_OK_CHECKBOX; dlgItem <= MAX_CHECKBOX; dlgItem++) {
X					GetDItem(optionDlg, dlgItem, &type, &ItemHndl, &box);
X					if (dlgItem == AUTOZOOM_BOX) {
X						if ((boolean)GetCtlValue(ItemHndl)) {
X							macflags |= fZoomOnContextSwitch;
X						} else {
X							macflags &= ~fZoomOnContextSwitch;
X						}
X					} else {
X						*(flag_ptrs[dlgItem]) = GetCtlValue(ItemHndl);
X					}
X				}
X				GetDItem(optionDlg, ENABLE_INFO_BOX, &type, &ItemHndl, &box);
X				flags.help = GetCtlValue(ItemHndl);
X				GetDItem(optionDlg, ALT_CURS_BOX, &type, &ItemHndl, &box);
X				altCurs = (short)GetCtlValue(ItemHndl);
X				GETTEXT(END_TOP,5);
X				op = tmp_name+1;
X				while(*op) {
X					num = 1;
X					if(digit(*op)) {
X						num = atoi(op);
X						while(digit(*op)) op++;
X					} else op++;
X				}
X				flags.end_top=num;
X				GETTEXT(END_AROUND,5);
X				op = tmp_name+1;
X				while(*op) {
X					num = 1;
X					if(digit(*op)) {
X						num = atoi(op);
X						while(digit(*op)) op++;
X					} else op++;
X				}
X				flags.end_around = num;
X#ifdef TUTTI_FRUTTI
X				GETTEXT(FRUIT_NAME,PL_FSIZ-1);
X				(void)PtoCstr (tmp_name);
X				(void)fruitadd(tmp_name);
X				nmcpy(pl_fruit,tmp_name,PL_FSIZ-1);
X#endif
X				GETTEXT(PACKORDER,19);
X				op = tmp_name+1;
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))||(index(sp+1, *sp))){
X						for (tmp = sp; *tmp;tmp++)
X							tmp[0]=tmp[1];
X						sp--;
X					}			/* bad or duplicate char in order - remove it*/
X				tmp = (char *) alloc((unsigned)(strlen(inv_order)+1));
X				Strcpy(tmp, op);
X				for (sp = inv_order, num = strlen(tmp); *sp; sp++)
X					if (!index(tmp, *sp)) {
X						tmp[num++] = *sp;
X						tmp[num] = 0;
X					}
X				Strcpy(inv_order, tmp);
X				free((genericptr_t)tmp);
X				done = TRUE;
X				break;
X			default:;
X		}
X	} 
X	flags.explore = explorer;
X	flags.debug = debugger;
X	flags.female = fairsex;
X	strncpy(plname, a_k_a, strlen(a_k_a));
X	plname[(int)strlen(a_k_a)] = '\0';
X	HideWindow(optionDlg);
X	DisposDialog (optionDlg);
X	SetPort (HackWindow);
X	return 0; 
X#else
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#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#ifdef TEXTCOLOR
X	    if (flags.use_color) Strcat(buf, "color,");
X#endif
X#ifdef AMIFLUSH
X	    if (flags.amiflush) Strcat(buf, "flush,");
X#endif
X	    if (!flags.help) Strcat(buf, "nohelp,");
X	    if (flags.IBMgraphics) Strcat(buf,"IBMgraphics,");
X	    if (flags.DECgraphics) Strcat(buf,"DECgraphics,");
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#ifdef TUTTI_FRUTTI
X	    Sprintf(eos(buf), "fruit:%s,", pl_fruit);
X#endif
X	    if(flags.end_top != 3 || flags.end_around != 2 || 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#endif /* MACOS */
X}
X
Xint
Xdotogglepickup() {
X	flags.pickup = !flags.pickup;
X	pline("Pickup: %s.", flags.pickup ? "ON" : "OFF");
X	return 0;
X}
X
X#define Page_line(x)	if(page_line(x)) goto quit
X#define Next_opt(x)	if (next_opt(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# ifdef AMIGA_WBENCH
X	if(FromWBench){
X	 Sprintf(buf,"Set options as OPTIONS= in %s or in icon;",configfile);
X	} else
X# endif
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	Next_opt("DECgraphics, ");
X#ifdef MSDOS
X	Next_opt("IBM_BIOS, ");
X#endif
X	Next_opt("IBMgraphics, ");
X#ifdef AMIFLUSH
X	Next_opt("flush, ");
X#endif
X#ifdef TEXTCOLOR
X	Next_opt("color, ");
X#endif
X	Next_opt("confirm, ");
X	Next_opt("(fe)male, "); Next_opt("fixinv, ");
X#ifdef UNIX
X	Next_opt("ignintr, ");
X#endif
X	Next_opt("help, ");
X#ifdef NEWS
X	Next_opt("news, ");
X#endif
X#ifdef UNIX
X	Next_opt("null, ");
X#endif
X	Next_opt("number_pad, ");
X	Next_opt("pickup, ");
X#ifdef MSDOS
X	Next_opt("rawio, ");
X#endif
X	Next_opt("rest_on_space, "); Next_opt("safe_pet, ");
X	Next_opt("silent, "); Next_opt("sortpack, ");
X#ifdef UNIX
X	Next_opt("standout, ");
X#endif
X	Next_opt("time, "); Next_opt("tombstone, ");
X	Next_opt("and verbose.");
X	Next_opt("");
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	Page_line("`catname'   - the name of your (first) cat (e.g., catname:Tabby),");
X
X	Page_line("`packorder' - the inventory order of the items in your pack");
X	Sprintf(buf, "              (currently, packorder:%s ),", inv_order);
X	Page_line(buf);
X#ifdef TUTTI_FRUTTI
X	Page_line("`fruit'     - the name of a fruit you enjoy eating,");
X#endif
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	(void) next_opt("\033");
X	set_pager(2);
X	return;
X}
X
X/*
X * prints the next boolean option, on the same line if possible, on a new
X * line if not. End with next_opt(""). Note that next_opt("\033") may be
X * used to abort.
X */
Xint
Xnext_opt(str)
Xconst char *str;
X{
X	static char buf[121];
X	static int i = 0;
X	int r = 0;
X
X	if (*str == '\033') {
X		i = 0; buf[0] = 0; return 0;
X	}
X	i += strlen(str);
X	if (i > min(CO - 2, 120) || !*str) {
X		r = page_line(buf);
X		buf[0] = 0;
X		i = strlen(str);
X	}
X	if (*str)
X		Strcat(buf, str);
X	else
X		(void) page_line(str);	/* always returns 0 on "" */
X	return r;
X}
X
X#ifdef TUTTI_FRUTTI
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#ifdef __GNULINT__
X	struct fruit *lastf = 0;
X#else
X	struct fruit *lastf;
X#endif
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",7) ||
X						!strncmp(eos(buf)-3, " egg",4))
X			&& 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}
X#endif
END_OF_FILE
if test 30155 -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 28 \(of 56\).
cp /dev/null ark28isdone
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 56 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