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

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

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



#! /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 27 (of 38)."
# Contents:  others/pcmain.c src/mkmaze.c src/sp_lev.c src/unixmain.c
# Wrapped by billr@saab on Sun Jul 23 21:33:10 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'others/pcmain.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'others/pcmain.c'\"
else
echo shar: Extracting \"'others/pcmain.c'\" \(12406 characters\)
sed "s/^X//" >'others/pcmain.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)pcmain.c	3.0	88/11/23
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X/* main.c - (PC, TOS and AMIGA) version */
X
X#ifndef TOS
X#include <signal.h>
X#else
X#define msmsg	cprintf
X#endif
X#include "hack.h"
X
Xchar orgdir[PATHLEN];
X
Xextern struct permonst mons[NUMMONS];
Xextern char plname[PL_NSIZ], pl_character[PL_CSIZ];
X
Xint (*afternmv)(), (*occupation)();
Xstatic void moveloop();	/* a helper function for MSC optimizer */
X
X#if defined(DGK) && !defined(TOS)
Xstruct finfo	zfinfo = ZFINFO;
Xint i;
X#endif /* DGK && !TOS */
X
Xchar SAVEF[FILENAME];
Xchar *hname = "NetHack";	/* used for syntax messages */
Xchar obuf[BUFSIZ];	/* BUFSIZ is defined in stdio.h */
Xint hackpid;		/* not used anymore, but kept in for save files */
X
Xextern char *nomovemsg;
Xextern long wailmsg;
X#ifdef __TURBOC__	/* tell Turbo C to make a bigger stack */
Xextern unsigned _stklen = 0x2000;	/* 8K */
Xextern unsigned char _osmajor;
X#endif
X
X#ifdef TOS
X#define OMASK	0x8000
X#else
X#define OMASK	0
X#endif
X
Xint
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	extern int x_maze_max, y_maze_max;
X	register int fd;
X	register char *dir;
X
X#ifdef AMIGA
X	/*
X	 *  Make sure screen IO is initialized before anything happens.
X	 */
X	gettty();
X	startup();
X#else /* AMIGA */
X	/* Save current directory and make sure it gets restored when
X	 * the game is exited.
X	 */
X	int (*funcp)();
X
X# ifdef __TURBOC__
X	if (_osmajor >= 3) hname = argv[0];	/* DOS 3.0+ */
X# endif
X	if (getcwd(orgdir, sizeof orgdir) == NULL) {
X		xputs("NetHack: current directory path too long\n");
X		_exit(1);
X	}
X	funcp = exit;	/* Kludge to get around LINT_ARGS of signal.
X			 * This will produce a compiler warning, but that's OK.
X			 */
X# ifndef TOS
X	signal(SIGINT, (SIG_RET_TYPE) funcp);	/* restore original directory */
X# endif
X#endif /* AMIGA */
X
X	/* Set the default values of the presentation characters */
X	memcpy((genericptr_t) &showsyms, (genericptr_t) &defsyms, sizeof(struct symbols));
X	if ((dir = getenv("HACKDIR")) != NULL) {
X		Strcpy(hackdir, dir);
X#ifdef CHDIR
X		chdirx (dir, 1);
X#endif
X	}
X#if defined(DGK) && !defined(TOS)
X	/* zero "fileinfo" array to prevent crashes on level change */
X	for (i = 0 ; i <= MAXLEVEL + 1; i++)
X		fileinfo[i] = zfinfo;
X#endif /* DGK && !TOS */
X	initoptions();
X	if (!hackdir[0])
X		Strcpy(hackdir, orgdir);
X#ifdef TOS
X	if(argc > 1 && !strncmp(argv[1], "-D", 2)) {
X#else
X	if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
X#endif
X		argc--;
X		argv++;
X		dir = argv[0]+2;
X		if(*dir == '=' || *dir == ':') dir++;
X		if(!*dir && argc > 1) {
X			argc--;
X			argv++;
X			dir = argv[0];
X		}
X		if(!*dir)
X		    error("Flag -d must be followed by a directory name.");
X		Strcpy(hackdir, dir);
X	}
X
X	/*
X	 * Now we know the directory containing 'record' and
X	 * may do a prscore().
X	 */
X#ifdef TOS
X	if(argc > 1 && !strncmp(argv[1], "-S", 2)) {
X#else
X	if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
X#endif
X#ifdef CHDIR
X		chdirx(hackdir,0);
X#endif
X		prscore(argc, argv);
X		exit(0);
X	}
X
X#ifndef AMIGA
X	/*
X	 * It seems he really wants to play.
X	 * Remember tty modes, to be restored on exit.
X	 */
X	gettty();
X	setbuf(stdout,obuf);
X	startup();
X#endif
X	setrandom();
X	cls();
X	u.uhp = 1;	/* prevent RIP on early quits */
X	u.ux = FAR;	/* prevent nscr() */
X#ifndef TOS
X	/*
X	 * We cannot do chdir earlier, otherwise gethdate will fail.
X	 */
X#ifdef CHDIR
X	chdirx(hackdir,1);
X#endif
X#endif
X	/*
X	 * Process options.
X	 */
X	while(argc > 1 && argv[1][0] == '-'){
X		argv++;
X		argc--;
X		switch(argv[0][1]){
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X#ifndef TOS
X		case 'D':
X#endif	/* TOS */
X		case 'X':
X# ifdef WIZARD
X			/* Must have "name" set correctly by NETHACK.CNF,
X			 * NETHACKOPTIONS, or -U
X			 * before this flag to enter wizard mode. */
X			if(!strcmp(plname, WIZARD))
X				wizard = TRUE;
X# endif
X# if defined(WIZARD) && defined(EXPLORE_MODE)
X			else
X# endif
X# ifdef EXPLORE_MODE
X				discover = TRUE;
X# endif
X			break;
X#endif
X#ifdef NEWS
X		case 'N':
X			flags.nonews = TRUE;
X			break;
X#endif
X		case 'U':
X			if(argv[0][2])
X			  (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
X			else if(argc > 1) {
X			  argc--;
X			  argv++;
X			  (void) strncpy(plname, argv[0], sizeof(plname)-1);
X			} else
X				Printf("Player name expected after -U\n");
X			break;
X#ifdef DGK
X		/* Person does not want to use a ram disk
X		 */
X		case 'R':
X			ramdisk = FALSE;
X			break;
X#endif
X		case 'C':   /* character role is next character */
X			/* allow -T for Tourist, etc. */
X			(void) strncpy(pl_character, argv[0]+2,
X				sizeof(pl_character)-1);
X		default:
X			Printf("Unknown option: %s\n", *argv);
X		}
X	}
X
X#ifdef DGK
X	set_lock_and_bones();
X	copybones(FROMPERM);
X#endif
X#ifdef WIZARD
X	if (wizard)
X		Strcpy(plname, "wizard");
X	else
X#endif
X	if (!*plname)
X		askname();
X	plnamesuffix();		/* strip suffix from name; calls askname() */
X				/* again if suffix was whole name */
X				/* accepts any suffix */
X#ifndef DGK
X	Strcpy(lock,plname);
X	Strcat(lock,".99");
X#endif
X	start_screen();
X
X	/*
X	 * Initialisation of the boundaries of the mazes
X	 * Both boundaries have to be even.
X	 */
X
X	x_maze_max = COLNO-1;
X	if (x_maze_max % 2)
X		x_maze_max--;
X	y_maze_max = ROWNO-1;
X	if (y_maze_max % 2)
X		y_maze_max--;
X
X	/* initialize static monster strength array */
X	init_monstr();
X
X#ifdef AMIGA
X	(void) strncat(SAVEF, plname, 31-4);
X#else
X	(void) strncat(SAVEF, plname, 8);
X#endif
X	Strcat(SAVEF, ".sav");
X	cls();
X	if (
X#ifdef DGK
X	    saveDiskPrompt(1) &&
X#endif /* DGK */
X	    ((fd = open(SAVEF, OMASK)) >= 0) &&
X	    (uptodate(fd) || !unlink(SAVEF))) {
X#ifndef TOS
X		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X		pline("Restoring old save file...");
X		(void) fflush(stdout);
X		if(!dorecover(fd))
X			goto not_recovered;
X		pline("Hello %s, welcome to NetHack!", plname);
X		/* get shopkeeper set properly if restore is in shop */
X		(void) inshop();
X#ifdef EXPLORE_MODE
X		if (discover) {
X			You("are in non-scoring discovery mode.");
X			pline("Do you want to keep the save file? ");
X			if(yn() == 'n')
X				(void) unlink(SAVEF);
X		}
X#endif
X		flags.move = 0;
X	} else {
Xnot_recovered:
X#ifdef DGK
X		gameDiskPrompt();
X#endif
X		fobj = fcobj = invent = 0;
X		fmon = fallen_down = 0;
X		ftrap = 0;
X		fgold = 0;
X		flags.ident = 1;
X		init_objects();
X		u_init();
X#ifndef TOS
X		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X		mklev();
X		u.ux = xupstair;
X		u.uy = yupstair;
X		(void) inshop();
X		setsee();
X		flags.botlx = 1;
X		/* Fix bug with dog not being made because a monster
X		 * was on the level 1 staircase
X		 */
X		if(levl[u.ux][u.uy].mmask) mnexto(m_at(u.ux, u.uy));
X		(void) makedog();
X		seemons();
X#ifdef NEWS
X		if(flags.nonews || !readnews())
X			/* after reading news we did docrt() already */
X#endif
X			docrt();
X
X		/* give welcome message before pickup messages */
X		pline("Hello %s, welcome to NetHack!", plname);
X		set_wear();
X		pickup(1);
X		read_engr_at(u.ux,u.uy);
X		flags.move = 0;
X	}
X	flags.moonphase = phase_of_the_moon();
X	if(flags.moonphase == FULL_MOON) {
X		You("are lucky!  Full moon tonight.");
X		if(!u.uluck) change_luck(1);
X	} else if(flags.moonphase == NEW_MOON) {
X		pline("Be careful!  New moon tonight.");
X	}
X
X	initrack();
X#ifndef TOS
X	(void) signal(SIGINT, SIG_IGN);
X#endif
X	/* Help for Microsoft optimizer.  Otherwise main is too large -dgk*/
X	moveloop();
X	return 0;
X}
X
Xstatic void
Xmoveloop()
X{
X	char ch;
X	int abort;
X
X	for(;;) {
X		if(flags.move) {	/* actual time passed */
X
X#ifdef SOUNDS
X			dosounds();
X#endif
X			settrack();
X
X			if(moves%2 == 0 ||
X			  (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
X				movemon();
X#ifdef HARD
X				if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
X#else
X				if(!rn2(70))
X#endif
X				    (void) makemon((struct permonst *)0, 0, 0);
X			}
X			if(Glib) glibr();
X			timeout();
X			++moves;
X#ifdef THEOLOGY
X			if (u.ublesscnt)  u.ublesscnt--;
X#endif
X#ifdef POLYSELF
X			if(u.mtimedone)
X			    if(u.mh < 1) rehumanize();
X			else
X#endif
X			    if(u.uhp < 1) {
X				You("die...");
X				done("died");
X			    }
X#ifdef POLYSELF
X			if (u.mtimedone) {
X			    if (u.mh < u.mhmax) {
X				if (Regeneration || !(moves%20)) {
X					flags.botl = 1;
X					u.mh++;
X				}
X			    }
X			}
X#endif
X			if(u.uhp < u.uhpmax) {
X				if(u.ulevel > 9) {
X				    int heal;
X
X				    if(HRegeneration || !(moves%3)) {
X					flags.botl = 1;
X					if (ACURR(A_CON) <= 12) heal = 1;
X					else heal = rnd((int) ACURR(A_CON)-12);
X					if (heal > u.ulevel-9) heal = u.ulevel-9;
X					u.uhp += heal;
X					if(u.uhp > u.uhpmax)
X					    u.uhp = u.uhpmax;
X				    }
X				} else if(HRegeneration ||
X					(!(moves%((MAXULEV+12)/(u.ulevel+2)+1)))) {
X					flags.botl = 1;
X					u.uhp++;
X				}
X			}
X#ifdef SPELLS
X			if ((u.uen<u.uenmax) && (!(moves%(19-ACURR(A_INT)/2)))) {
X				u.uen += rn2((int)ACURR(A_WIS)/5 + 1) + 1;
X				if (u.uen > u.uenmax)  u.uen = u.uenmax;
X				flags.botl = 1;
X			}
X#endif
X			if(Teleportation && !rn2(85)) tele();
X#ifdef POLYSELF
X			if(Polymorph && !rn2(100))
X				polyself();
X			if(u.ulycn >= 0 && !rn2(80 - (20 * night())))
X				you_were();
X#endif
X			if(Searching && multi >= 0) (void) dosearch0(1);
X			gethungry();
X			hatch_eggs();
X			invault();
X			amulet();
X#ifdef HARD
X			if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3));
X			if (u.udemigod) {
X
X				u.udg_cnt--;
X				if(u.udg_cnt <= 0) {
X
X					intervene();
X					u.udg_cnt = rn1(200, 50);
X				}
X			}
X#endif
X			restore_attrib();
X		}
X		if(multi < 0) {
X			if(!++multi){
X				pline(nomovemsg ? nomovemsg :
X					"You can move again.");
X				nomovemsg = 0;
X				if(afternmv) (*afternmv)();
X				afternmv = 0;
X			}
X		}
X
X		find_ac();
X		if(!flags.mv || Blind)
X		{
X			seeobjs();
X			seemons();
X			seeglds();
X			nscr();
X		}
X		if(flags.time) flags.botl = 1;
X
X		if(flags.botl || flags.botlx) bot();
X
X		flags.move = 1;
X
X		if(multi >= 0 && occupation) {
X			abort = 0;
X			if (kbhit()) {
X				if ((ch = Getchar()) == ABORT)
X					abort++;
X#ifdef REDO
X				else
X					pushch(ch);
X#endif /* REDO */
X			}
X			if(abort || monster_nearby())
X				stop_occupation();
X			else if ((*occupation)() == 0)
X				occupation = 0;
X			if (!(++occtime % 7))
X				(void) fflush(stdout);
X			continue;
X		}
X
X		if((u.uhave_amulet || Clairvoyant) && 
X#ifdef ENDGAME
X			dlevel != ENDLEVEL &&
X#endif
X			!(moves%15) && !rn2(2)) do_vicinity_map();
X
X		u.umoved = FALSE;
X		if(multi > 0) {
X			lookaround();
X			if(!multi) {	/* lookaround may clear multi */
X				flags.move = 0;
X				continue;
X			}
X			if(flags.mv) {
X				if(multi < COLNO && !--multi)
X					flags.mv = flags.run = 0;
X				domove();
X			} else {
X				--multi;
X				rhack(save_cm);
X			}
X		} else if(multi == 0) {
X#ifdef MAIL
X			ckmailstatus();
X#endif
X			rhack(NULL);
X		}
X		if(multi && multi%7 == 0)
X			(void) fflush(stdout);
X	}
X}
X
X/*
X * plname is filled either by an option (-U Player  or  -UPlayer) or
X * explicitly (by being the wizard) or by askname.
X * It may still contain a suffix denoting pl_character.
X */
Xvoid
Xaskname() {
X	register int c, ct;
X
X	Printf("\nWho are you? ");
X	(void) fflush(stdout);
X	ct = 0;
X	while((c = Getchar()) != '\n') {
X		if(c == EOF) error("End of input\n");
X		/* some people get confused when their erase char is not ^H */
X		if(c == '\b') {
X			if(ct) {
X				ct--;
X#ifdef MSDOS
X				msmsg("\b \b");
X#endif
X			}
X			continue;
X		}
X		if(c != '-')
X		if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
X		if(ct < sizeof(plname)-1) {
X#ifdef MSDOS
X			msmsg("%c", c);
X#endif
X			plname[ct++] = c;
X	}
X	}
X	plname[ct] = 0;
X	if(ct == 0) askname();
X}
X
X/*VARARGS1*/
Xvoid
Ximpossible(s,x1,x2)
X	register char *s, *x1, *x2;
X{
X	pline(s,x1,x2);
X	pline("Program in disorder - perhaps you'd better Quit.");
X}
X
X#ifdef CHDIR
Xvoid
Xchdirx(dir, wr)
Xchar *dir;
Xboolean wr;
X{
X
X	if(dir && chdir(dir) < 0) {
X		error("Cannot chdir to %s.", dir);
X	}
X
X	/* Change the default drive as well.
X	 */
X#ifndef AMIGA
X	chdrive(dir);
X#endif
X
X	/* warn the player if he cannot write the record file */
X	/* perhaps we should also test whether . is writable */
X	/* unfortunately the access systemcall is worthless */
X	if(wr) {
X	    register int fd;
X
X	    if(dir == NULL)
X#ifdef AMIGA
X		dir = "";
X#else
X		dir = ".";
X#endif
X	    if((fd = open(RECORD, 2)) < 0) {
X#ifdef DGK
X		char tmp[PATHLEN];
X
X		Strcpy(tmp, dir);
X		append_slash(tmp);
X		msmsg("Warning: cannot write %s%s\n", tmp, RECORD);
X		getreturn("to continue");
X#else
X		Printf("Warning: cannot write %s/%s", dir, RECORD);
X		getret();
X#endif
X	    } else
X		(void) close(fd);
X	}
X}
X#endif /* CHDIR /**/
X
Xvoid
Xstop_occupation()
X{
X	if(occupation) {
X		You("stop %s.", occtxt);
X		occupation = 0;
X#ifdef REDO
X		multi = 0;
X		pushch(0);
X#endif
X	}
X}
END_OF_FILE
if test 12406 -ne `wc -c <'others/pcmain.c'`; then
    echo shar: \"'others/pcmain.c'\" unpacked with wrong size!
fi
# end of 'others/pcmain.c'
fi
if test -f 'src/mkmaze.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/mkmaze.c'\"
else
echo shar: Extracting \"'src/mkmaze.c'\" \(12398 characters\)
sed "s/^X//" >'src/mkmaze.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)mkmaze.c	3.0	88/10/25
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X
Xextern int x_maze_max, y_maze_max;
X
X#if defined(WALLIFIED_MAZE) || defined(STRONGHOLD)
Xstatic int
Xiswall(x,y)
Xint x,y;
X{
X# ifndef WALLIFIED_MAZE
X	if (x<0 || y<0 || x>COLNO-1 || y>ROWNO-1)
X# else
X	if (x<0 || y<0 || x>COLNO || y>ROWNO)
X# endif
X		return 0;
X	return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)
X		|| levl[x][y].typ == SDOOR);
X}
X
Xvoid
Xwallification(x1, y1, x2, y2, see)
Xint x1, y1, x2, y2;
Xboolean see;
X{
X	char type;
X	short x,y;
X	register struct rm *room;
X
X	if (x1 < 0) x1 = 0;
X	if (x2 < x1) x2 = x1;
X	if (x2 > COLNO-1) x2 = COLNO-1;
X	if (x1 > x2) x1 = x2;
X	if (y1 < 0) y1 = 0;
X	if (y2 < y1) y2 = y1;
X	if (y2 > COLNO-1) y2 = ROWNO-1;
X	if (y1 > y2) y1 = y2;
X	for(x = x1; x <= x2; x++)
X	    for(y = y1; y <= y2; y++) {
X		room = &levl[x][y];
X		type = room->typ;
X		if (iswall(x,y)) {
X		    if (IS_DOOR(type)) {
X			room->scrsym = DOOR_SYM;
X			continue;
X		    } else
X		    if (iswall(x,y-1))
X			if (iswall(x,y+1))
X			    if (iswall(x-1,y))
X				if (iswall(x+1,y)) {
X					room->scrsym = CRWALL_SYM; /* -+- */
X					room->typ = CROSSWALL;
X				} else {
X					room->scrsym = TLWALL_SYM; /* -| */
X					room->typ = TLWALL;
X				}
X			    else
X				if (iswall(x+1,y)) {
X					room->scrsym = TRWALL_SYM; /* |- */
X					room->typ = TRWALL;
X				} else {
X					room->typ = VWALL;
X#ifdef STRONGHOLD
X					if (is_drawbridge_wall(x,y) >= 0)
X					    room->scrsym = DB_VWALL_SYM;
X					else
X#endif
X					    room->scrsym = VWALL_SYM; /* | */
X				}
X			else
X			    if (iswall(x-1,y))
X				if (iswall(x+1,y)) {		      
X					room->scrsym = TUWALL_SYM;  /*  |  */
X					room->typ = TUWALL;	    /* -+- */
X				} else {
X					room->scrsym = BRCORN_SYM;  /*	| */
X					room->typ = BRCORNER;	    /* -+ */
X				}
X			    else
X				if (iswall(x+1,y)) {		    
X					room->scrsym = BLCORN_SYM;  /* |  */
X					room->typ = BLCORNER;	    /* +- */
X				} else {
X					room->typ = VWALL;
X#ifdef STRONGHOLD
X					if (is_drawbridge_wall(x,y) >= 0)
X					    room->scrsym = DB_VWALL_SYM;
X					else
X#endif
X					    room->scrsym = VWALL_SYM; /* | */
X				}
X		    else
X			if (iswall(x,y+1))
X			    if (iswall(x-1,y))
X				if (iswall(x+1,y)) {
X					room->scrsym = TDWALL_SYM;  /* -+- */
X					room->typ = TDWALL;	    /*	| */
X				} else {
X					room->scrsym = TRCORN_SYM;  /* -+ */
X					room->typ = TRCORNER;	    /*	| */
X				}
X			    else
X				if (iswall(x+1,y)) {
X					room->scrsym = TLCORN_SYM;  /* +- */
X					room->typ = TLCORNER;	    /* |  */
X				} else {
X					room->typ = VWALL;
X#ifdef STRONGHOLD
X					if (is_drawbridge_wall(x,y) >= 0)
X					    room->scrsym = DB_VWALL_SYM;
X					else
X#endif
X					    room->scrsym = VWALL_SYM; /* | */
X				}
X			else {
X				room->typ = HWALL;
X#ifdef STRONGHOLD
X				if (is_drawbridge_wall(x,y) >= 0)
X				    room->scrsym = DB_HWALL_SYM;
X				else
X#endif
X				    room->scrsym = HWALL_SYM;
X			}
X		    if (type == SDOOR) room->typ = type;
X		    if (see) room->seen = 0;
X		} else {
X		    switch(room->typ) {
X			case STONE:
X				room->scrsym = STONE_SYM;
X				break;
X			case CORR:
X				room->scrsym = CORR_SYM;
X				break;
X			case ROOM:
X				room->scrsym = ROOM_SYM;
X		    }
X		    if (see) room->seen = 0;
X		}
X	    }
X}
X#endif /* WALLIFIED_MAZE /**/
X
Xstatic boolean
Xokay(x,y,dir)
Xint x,y;
Xregister int dir;
X{
X	move(&x,&y,dir);
X	move(&x,&y,dir);
X	if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0)
X		return(FALSE);
X	return(TRUE);
X}
X
Xstatic void
Xmaze0xy(cc)	/* find random starting point for maze generation */
X	coord	*cc;
X{
X	cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
X	cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
X	return;
X}
X
Xstatic const uchar tower[] = {
X	MOAT,	  MOAT,     MOAT,     MOAT,	MOAT,	  MOAT,     MOAT,
X	MOAT,	  MOAT,     TLCORNER, HWALL,	TRCORNER, MOAT,     MOAT,
X	MOAT,	  TLCORNER, BRCORNER, ROOM,	BLCORNER, TRCORNER, MOAT,
X	MOAT,	  VWALL,    ROOM,     ROOM,	ROOM,	  VWALL,    MOAT,
X	MOAT,	  BLCORNER, TRCORNER, ROOM,	TLCORNER, BRCORNER, MOAT,
X	MOAT,	  MOAT,     BLCORNER, HWALL,	BRCORNER, MOAT,     MOAT,
X	MOAT,	  MOAT,     MOAT,     MOAT,	MOAT,	  MOAT,     MOAT,
X};
X 
Xvoid
Xmakemaz()
X{
X	int x,y;
X	register int zx,zy;
X	coord mm;
X	int i;
X
X	is_maze_lev = TRUE;
X#ifdef STRONGHOLD
X	xdnladder = ydnladder = xupladder = yupladder = 0;
X	if (dlevel == stronghold_level) {
X		if (load_special("castle")) {
X			xupstair = yupstair = 3;
X			levl[xupstair][yupstair].scrsym = UP_SYM;
X			levl[xupstair][yupstair].typ = STAIRS;
X			return;
X		}
X		impossible("Cannot build the STRONGHOLD!");
X	}
X	if (dlevel == tower_level) {
X		if (load_special("tower1")) {
X			xupstair = yupstair = 3;
X			levl[xupstair][yupstair].scrsym = UP_SYM;
X			levl[xupstair][yupstair].typ = STAIRS;
X			return;
X		}
X		impossible("Cannot build the TOWER!");
X	}
X	if (dlevel == tower_level+1) {
X		if (load_special("tower2")) {
X			xupstair = yupstair = 3;
X			levl[xupstair][yupstair].scrsym = UP_SYM;
X			levl[xupstair][yupstair].typ = STAIRS;
X			return;
X		}
X		impossible("Cannot build the TOWER!");
X	}
X	if (dlevel == tower_level+2) {
X		if (load_special("tower3")) {
X			xupstair = yupstair = 3;
X			levl[xupstair][yupstair].scrsym = UP_SYM;
X			levl[xupstair][yupstair].typ = STAIRS;
X			return;
X		}
X		impossible("Cannot build the TOWER!");
X	}
X# ifdef ENDGAME
X	if (dlevel == ENDLEVEL) {	/* EndGame level */
X		if (load_special("endgame")) {
X			pline("Well done, mortal!");
X			pline("But now thou must face the final Test...");
X			pline("Prove thyself worthy or perish!");
X			u.ux = x_maze_max - 1;
X			u.uy = y_maze_max - 1;
X			xupstair = yupstair = 0;
X			return;
X		}
X		impossible("Cannot build the EndGame Level!");
X		done("escaped");
X	}
X# endif
X#endif
X#ifndef WALLIFIED_MAZE
X	for(x = 2; x < x_maze_max; x++)
X		for(y = 2; y < y_maze_max; y++)
X			levl[x][y].typ = STONE;
X#else
X	for(x = 2; x <= x_maze_max; x++)
X		for(y = 2; y <= y_maze_max; y++)
X			levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
X#endif
X
X	/* make decoy wizard levels */
X	if((dlevel == wiz_level) ||
X#ifdef STRONGHOLD
X	   (!rn2(3) && (dlevel > stronghold_level+1))) {
X#else
X	   (!rn2(3) && (dlevel > medusa_level+1))) {
X#endif
X
X	    register struct monst *mtmp;
X
X	    zx = x_maze_max / 2;
X	    zy = y_maze_max / 2;
X	    if (!(zx % 2)) zx++;
X	    if (!(zy % 2)) zy++;
X	    for(y = zy-3, i=0; y <= zy+3; y++)
X		for(x = zx-3; x <= zx+3; x++)
X		    levl[x][y].typ = tower[i++];
X	    walkfrom(zx+4, zy);
X	    if(mtmp = makemon(&mons[PM_HELL_HOUND], zx+1, zy))
X		mtmp->msleep = 1;
X	    (void) makemon(&mons[PM_KRAKEN], zx+2, zy+2);
X	    if (dlevel == wiz_level) {
X
X		(void) mksobj_at(AMULET_OF_YENDOR, zx, zy);
X		flags.made_amulet = 1;
X#ifndef STRONGHOLD
X		if(mtmp = makemon(&mons[PM_VLAD_THE_IMPALER], zx-1, zy))
X			mtmp->msleep = 1;
X#endif
X		if(mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], zx, zy))
X			mtmp->msleep = 1;
X	    } else {
X		struct obj *ot;
X	    	/* make a cheap plastic imitation */
X		if (ot = mksobj_at(AMULET_OF_YENDOR, zx, zy))
X		    ot-> spe = -1;
X#ifndef STRONGHOLD
X		if (mtmp = makemon(&mons[PM_VAMPIRE_LORD], zx-1, zy))
X		    mtmp->msleep = 1;
X#endif
X		(void) makemon(&mons[dprince()], zx, zy);
X	    }
X	    /* they should wake up when we intrude */
X	    (void) maketrap(zx-1, zy, SQBRD);
X	    (void) maketrap(zx+1, zy, SQBRD);
X	    (void) maketrap(zx, zy-1, SQBRD);
X	    (void) maketrap(zx, zy+1, SQBRD);
X	} else {
X	    maze0xy(&mm);
X	    zx = mm.x;
X	    zy = mm.y;
X	    walkfrom(zx,zy);
X#ifndef STRONGHOLD	/* it's in the castle */
X# ifdef HARD		/* only one wand of wishing created */
X	    if(!rn2(10) || (dlevel == medusa_level + 1))
X# endif
X		(void) mksobj_at(WAN_WISHING, zx, zy);
X#endif
X	    (void) mksobj_at(BOULDER, zx, zy);  /* put a boulder on top of it */
X	}
X
X#ifdef WALLIFIED_MAZE
X	wallification(2, 2, x_maze_max, y_maze_max, TRUE);
X#else
X	for(x = 2; x < x_maze_max; x++)
X		for(y = 2; y < y_maze_max; y++) {
X			switch(levl[x][y].typ) {
X			case STONE:
X				levl[x][y].scrsym = STONE_SYM;
X				break;
X			case CORR:
X				levl[x][y].scrsym = CORR_SYM;
X				break;
X			case ROOM:
X				levl[x][y].scrsym = ROOM_SYM;
X				break;
X			case HWALL:
X				levl[x][y].scrsym = HWALL_SYM;
X				break;
X			case VWALL:
X				levl[x][y].scrsym = VWALL_SYM;
X				break;
X			case TLCORNER:
X				levl[x][y].scrsym = TLCORN_SYM;
X				break;
X			case TRCORNER:
X				levl[x][y].scrsym = TRCORN_SYM;
X				break;
X			case BLCORNER:
X				levl[x][y].scrsym = BLCORN_SYM;
X				break;
X			case BRCORNER:
X				levl[x][y].scrsym = BRCORN_SYM;
X				break;
X			}
X		}
X#endif
X	mazexy(&mm);
X	levl[(xupstair = mm.x)][(yupstair = mm.y)].scrsym = UP_SYM;
X	levl[xupstair][yupstair].typ = STAIRS;
X	xdnstair = ydnstair = 0;
X#ifdef STRONGHOLD
X	if (dlevel < stronghold_level) {
X		mazexy(&mm);
X		levl[(xdnstair = mm.x)][(ydnstair = mm.y)].scrsym = DN_SYM;
X		levl[xdnstair][ydnstair].typ = STAIRS;
X	}
X#endif
X	for(x = rn1(8,11); x; x--) {
X		mazexy(&mm);
X		(void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y);
X	}
X	for(x = rn1(10,2); x; x--) {
X		mazexy(&mm);
X		(void) mksobj_at(BOULDER, mm.x, mm.y);
X	}
X	mazexy(&mm);
X	(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
X	for(x = rn1(5,7); x; x--) {
X		mazexy(&mm);
X		(void) makemon((struct permonst *) 0, mm.x, mm.y);
X	}
X	for(x = rn1(6,7); x; x--) {
X		mazexy(&mm);
X		mkgold(0L,mm.x,mm.y);
X	}
X	for(x = rn1(6,7); x; x--)
X		mktrap(0,1,(struct mkroom *) 0);
X}
X
X#ifdef MSDOS
X/* Make the mazewalk iterative by faking a stack.  This is needed to
X * ensure the mazewalk is successful in the limited stack space of
X * the program.  This iterative version uses the mimumum amount of stack
X * that is totally safe.
X */
Xvoid
Xwalkfrom(x,y)
Xint x,y;
X{
X#define CELLS (ROWNO * COLNO) / 4		/* a maze cell is 4 squares */
X	char mazex[CELLS + 1], mazey[CELLS + 1];	/* char's are OK */
X	int q, a, dir, pos;
X	int dirs[4];
X
X	pos = 1;
X	mazex[pos] = (char) x;
X	mazey[pos] = (char) y;
X	while (pos) {
X		x = (int) mazex[pos];
X		y = (int) mazey[pos];
X#ifndef WALLIFIED_MAZE
X		levl[x][y].typ = CORR;
X#else
X		levl[x][y].typ = ROOM;
X#endif
X		q = 0;
X		for (a = 0; a < 4; a++)
X			if(okay(x, y, a)) dirs[q++]= a;
X		if (!q)
X			pos--;
X		else {
X			dir = dirs[rn2(q)];
X			move(&x, &y, dir);
X#ifndef WALLIFIED_MAZE
X			levl[x][y].typ = CORR;
X#else
X			levl[x][y].typ = ROOM;
X#endif
X			move(&x, &y, dir);
X			pos++;
X			if (pos > CELLS)
X				panic("Overflow in walkfrom");
X			mazex[pos] = (char) x;
X			mazey[pos] = (char) y;
X		}
X	}
X}
X#else
X
Xvoid
Xwalkfrom(x,y) int x,y; {
Xregister int q,a,dir;
Xint dirs[4];
X#ifndef WALLIFIED_MAZE
X	levl[x][y].typ = CORR;
X#else
X	levl[x][y].typ = ROOM;
X#endif
X	while(1) {
X		q = 0;
X		for(a = 0; a < 4; a++)
X			if(okay(x,y,a)) dirs[q++]= a;
X		if(!q) return;
X		dir = dirs[rn2(q)];
X		move(&x,&y,dir);
X#ifndef WALLIFIED_MAZE
X		levl[x][y].typ = CORR;
X#else
X		levl[x][y].typ = ROOM;
X#endif
X		move(&x,&y,dir);
X		walkfrom(x,y);
X	}
X}
X#endif /* MSDOS */
X
Xvoid
Xmove(x,y,dir)
Xregister int *x, *y;
Xregister int dir;
X{
X	switch(dir){
X		case 0: --(*y); break;
X		case 1: (*x)++; break;
X		case 2: (*y)++; break;
X		case 3: --(*x); break;
X	}
X}
X
Xvoid
Xmazexy(cc)	/* find random point in generated corridors
X		   i.e., don't create items in moats, bunkers, or walls */
X	coord	*cc;
X{
X	int cpt=0;
X
X	do {
X	    cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
X	    cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
X	    cpt++;
X#ifndef WALLIFIED_MAZE
X	} while (cpt < 100 && levl[cc->x][cc->y].typ != CORR);
X#else
X	} while (cpt < 100 && levl[cc->x][cc->y].typ != ROOM);
X#endif
X	if (cpt >= 100) panic("mazexy: can't find a place!");
X	return;
X}
X
Xvoid
Xbound_digging()
X/* put a non-diggable boundary around the initial portion of a level map.
X * assumes that no level will initially put things beyond the isok() range.
X */
X{
X	register int x,y;
X	register boolean found;
X	int xmin,xmax,ymin,ymax;
X
X	found = FALSE;
X	for(xmin=1; !found; xmin++)
X		for(y=0; y<=ROWNO-1; y++)
X			if(levl[xmin][y].typ != STONE) found = TRUE;
X	xmin -= 2;
X
X	found = FALSE;
X	for(xmax=COLNO-2; !found; xmax--)
X		for(y=0; y<=ROWNO-1; y++)
X			if(levl[xmax][y].typ != STONE) found = TRUE;
X	xmax += 2;
X
X	found = FALSE;
X	for(ymin=1; !found; ymin++)
X		for(x=xmin; x<=xmax; x++)
X			if(levl[x][ymin].typ != STONE) found = TRUE;
X	ymin -= 2;
X
X	found = FALSE;
X	for(ymax=ROWNO-2; !found; ymax--)
X		for(x=xmin; x<=xmax; x++)
X			if(levl[x][ymax].typ != STONE) found = TRUE;
X	ymax += 2;
X
X	for(x=xmin; x<=xmax; x++) {
X		levl[x][ymin].diggable = W_NONDIGGABLE;
X		levl[x][ymax].diggable = W_NONDIGGABLE;
X	}
X
X	for(y=ymin; y<=ymax; y++) {
X		levl[xmin][y].diggable = W_NONDIGGABLE;
X		levl[xmax][y].diggable = W_NONDIGGABLE;
X	}
X}
END_OF_FILE
if test 12398 -ne `wc -c <'src/mkmaze.c'`; then
    echo shar: \"'src/mkmaze.c'\" unpacked with wrong size!
fi
# end of 'src/mkmaze.c'
fi
if test -f 'src/sp_lev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/sp_lev.c'\"
else
echo shar: Extracting \"'src/sp_lev.c'\" \(12800 characters\)
sed "s/^X//" >'src/sp_lev.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)sp_lev.c	3.0	89/01/11
X/*	Copyright (c) 1989 by Jean-Christophe Collet */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/*
X * This file contains the various functions that are related to the special
X * levels.
X * It contains also the special level loader.
X *
X */
X
X#include "hack.h"
X
X#ifdef STRONGHOLD
X#include "sp_lev.h"
X
X#if defined(MSDOS) && !defined(AMIGA)
X# define RDMODE "rb"
X#else
X# define RDMODE "r"
X#endif
X
X#define LEFT	1
X#define CENTER	2
X#define RIGHT	3
X#define TOP	1
X#define BOTTOM	3
X
Xstatic walk walklist[50];
Xextern int x_maze_max, y_maze_max;
X
Xstatic char Map[COLNO][ROWNO];
Xstatic char robjects[10], rloc_x[10], rloc_y[10], rmonst[10],
X	ralign[3] = { A_CHAOS, A_NEUTRAL, A_LAW };
Xstatic xchar xstart, ystart, xsize, ysize;
X
X/*
X * Make walls of the area (x1, y1, x2, y2) non diggable
X */
X
Xstatic void
Xmake_walls_nondiggable(x1,y1,x2,y2)
Xxchar x1, y1, x2, y2;
X{
X	register xchar x, y;
X
X	for(y = y1; y <= y2; y++)
X	    for(x = x1; x <= x2; x++)
X		if(IS_WALL(levl[x][y].typ))
X		    levl[x][y].diggable |= W_NONDIGGABLE;
X}
X
X/*
X * Choose randomly the state (nodoor, open, closed or locked) for a door
X */
X
Xstatic int
Xrnddoor()
X{
X	int i;
X	
X	i = 1 << rn2(5);
X	i >>= 1;
X	return i;
X}
X
X/* 
X * Select a random trap
X */
X
Xstatic int
Xrndtrap()
X{
X	return(rnd(TRAPNUM-1));
X}
X
X/* 
X * Coordinates in special level files are handled specially:
X *
X *	if x or y is -11, we generate a random coordinate.
X *	if x or y is between -1 and -10, we read one from the corresponding
X *	register (x0, x1, ... x9).
X *	if x or y is nonnegative, we convert it from relative to the local map
X *	to global coordinates.
X */
X
Xstatic void
Xget_location(x, y)
Xschar *x, *y;
X{
X	int cpt = 0;
X
X	if (*x >= 0) {			/* normal locations */
X		*x += xstart;
X		*y += ystart;
X	} else if (*x > -11) {		/* special locations */
X		*y = ystart + rloc_y[ - *y - 1];
X		*x = xstart + rloc_x[ - *x - 1];
X	} else {			/* random location */
X		do {
X		    *x = xstart + rn2((int)xsize);
X		    *y = ystart + rn2((int)ysize);
X		} while (cpt < 100 &&
X			 levl[*x][*y].typ != ROOM &&
X			 levl[*x][*y].typ != CORR);
X		if(cpt >= 100)
X		    panic("get_location: can't find a place!");
X	}
X
X	if (*x < 0 || *x > x_maze_max || *y < 0 || *y > y_maze_max) {
X	    impossible("get_location: (%d,%d) out of bounds", *x, *y);
X	    *x = x_maze_max; *y = y_maze_max;
X	}
X}
X
X/*
X * Shuffle the registers for locations, objects or monsters
X */
X
Xstatic void
Xshuffle(list, n)
Xchar list[];
Xxchar n;
X{
X	int i, j;
X	char k;
X
X	for(i = n-1; i; i--) {
X		j = rn2(i);
X
X		k = list[j];
X		list[j] = list[i];
X		list[i] = k;
X	}
X}
X
X/* 
X * Shuffle two arrays in the same order (for rloc_x & rloc_y)
X */
X
Xstatic void
Xshuffle2(list1, list2, n)
Xchar list1[], list2[];
Xxchar n;
X{
X	int i, j;
X	char k1, k2;
X
X	for(i = n-1; i; i--) {
X		j = rn2(i);
X
X		k1 = list1[j];
X		k2 = list2[j];
X
X		list1[j] = list1[i];
X		list2[j] = list2[i];
X
X		list1[i] = k1;
X		list2[i] = k2;
X	}
X}
X
X/* 
X * NOT YET IMPLEMENTED!!!
X */
X
Xstatic boolean
Xload_rooms(fd)
XFILE *fd;
X{
X	return FALSE;
X}
X
X/*
X * Select a random coordinate in the maze.
X *
X * We want a place not 'touched' by the loader.  That is, a place in
X * the maze outside every part of the special level.
X */
X
Xstatic void
Xmaze1xy(m)
Xcoord *m;
X{
X	do {
X		m->x = rn1(x_maze_max - 3, 3);
X		m->y = rn1(y_maze_max - 3, 3);
X	} while (!(m->x % 2) || !(m->y % 2) || Map[m->x][m->y]);
X}
X
X/* 
X * The Big Thing: special maze loader
X *
X * Could be cleaner, but it works.
X */
X
Xstatic boolean
Xload_maze(fd)
XFILE *fd;
X{
X    xchar   x, y, n, typ;
X    char    c;
X
X    xchar   numpart = 0, nwalk = 0;
X    uchar   halign, valign;
X
X    int     xi, yi, dir;
X    coord   mm;
X    int     mapcount, mapcountmax, mapfact;
X
X    region  tmpregion;
X    door    tmpdoor;
X    trap    tmptrap;
X    monster tmpmons;
X    object  tmpobj;
X    drawbridge tmpdb;
X    walk    tmpwalk;
X    dig     tmpdig;
X    lad     tmplad;
X#ifdef ALTARS
X    altar   tmpaltar;
X#endif
X
X    /* shuffle alignments */
X    shuffle(ralign,3);
X
X    /* Initialize map */
X    xupstair = yupstair = xdnstair = ydnstair = doorindex = 0;
X    for(x = 2; x <= x_maze_max; x++)
X	for(y = 2; y <= y_maze_max; y++) {
X#ifndef WALLIFIED_MAZE
X	    levl[x][y].typ = STONE;
X#else
X	    levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
X#endif
X	    Map[x][y] = 0;
X	}
X
X    /* Start reading the file */
X    numpart = fgetc(fd); /* Number of parts */
X    if (!numpart || numpart > 9)
X	panic("load_maze error: numpart = %d", (int) numpart);
X
X    while (numpart--) {
X	halign = fgetc(fd); /* Horizontal alignment */
X	valign = fgetc(fd); /* Vertical alignment */
X	xsize  = fgetc(fd); /* size in X */
X	ysize  = fgetc(fd); /* size in Y */
X
X	switch((int) halign) {
X	    case LEFT:	    xstart = 3; 				break;
X	    case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);	break;
X	    case RIGHT:     xstart = x_maze_max-xsize-1;		break;
X	}
X	switch((int) valign) {
X	    case TOP:	    ystart = 3; 				break;
X	    case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);	break;
X	    case BOTTOM:    ystart = y_maze_max-ysize-1;		break;
X	}
X	if (!(xstart % 2)) xstart++;
X	if (!(ystart % 2)) ystart++;
X
X	/* Load the map */
X	for(y = ystart; y < ystart+ysize; y++)
X	    for(x = xstart; x < xstart+xsize; x++) {
X		levl[x][y].typ = fgetc(fd);
X		initsym(x,y);
X		/* secret doors default closed */
X		if (levl[x][y].typ == SDOOR)
X		  levl[x][y].doormask = D_CLOSED;
X		Map[x][y] = 1;
X	    }
X
X	n = fgetc(fd); /* Random objects */
X	if(n) {
X		(void) fread((genericptr_t)robjects, 1, (int) n, fd);
X		shuffle(robjects, n);
X	}
X
X	n = fgetc(fd); /* Random locations */
X	if(n) {
X		(void) fread((genericptr_t)rloc_x, 1, (int) n, fd);
X		(void) fread((genericptr_t)rloc_y, 1, (int) n, fd);
X		shuffle2(rloc_x, rloc_y, n);
X	}
X
X	n = fgetc(fd); /* Random monsters */
X	if(n) {
X		(void) fread((genericptr_t)rmonst, 1, (int) n, fd);
X		shuffle(rmonst, n);
X	}
X
X	n = fgetc(fd); /* Number of subrooms */
X	while(n--) {
X		(void) fread((genericptr_t)&tmpregion, sizeof(tmpregion), 1, fd);
X		if (nroom >= MAXNROFROOMS) continue;
X
X		get_location(&tmpregion.x1, &tmpregion.y1);
X		get_location(&tmpregion.x2, &tmpregion.y2);
X
X		rooms[nroom].lx = tmpregion.x1;
X		rooms[nroom].ly = tmpregion.y1;
X		rooms[nroom].hx = tmpregion.x2;
X		rooms[nroom].hy = tmpregion.y2;
X		rooms[nroom].rtype = tmpregion.rtype;
X		rooms[nroom].rlit = tmpregion.rlit;
X		if (tmpregion.rlit == 1)
X			for(x = rooms[nroom].lx-1; x <= rooms[nroom].hx+1; x++)
X				for(y = rooms[nroom].ly-1; y <= rooms[nroom].hy+1; y++)
X					levl[x][y].lit = 1;
X
X		rooms[nroom].fdoor = rooms[nroom].doorct = 0;
X
X		++nroom;
X		rooms[nroom].hx = -1;
X	}
X
X	n = fgetc(fd); /* Number of doors */
X	while(n--) {
X		struct mkroom *croom = &rooms[0], *broom;
X		int tmp;
X
X		(void) fread((genericptr_t)&tmpdoor, sizeof(tmpdoor), 1, fd);
X
X		x = tmpdoor.x;	y = tmpdoor.y;
X		typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
X
X		get_location(&x, &y);
X		levl[x][y].doormask = typ;
X
X		/* Now the complicated part, list it with each subroom */
X		/* The dog move and mail daemon routines use this */
X		while(croom->hx >= 0 && doorindex < DOORMAX) {
X		    if(croom->hx >= x-1 && croom->lx <= x+1 &&
X		       croom->hy >= y-1 && croom->ly <= y+1) {
X			/* Found it */
X			croom->doorct++;
X
X			/* Append or insert into doors[] */
X			broom = croom+1;
X			if(broom->hx < 0) tmp = doorindex;
X			else
X			    for(tmp = doorindex; tmp > broom->fdoor; tmp--)
X				doors[tmp] = doors[tmp-1];
X
X			doors[tmp].x = x;
X			doors[tmp].y = y;
X			doorindex++;
X
X			for( ; broom->hx >= 0; broom++) broom->fdoor++;
X		    }
X		    croom++;
X		}
X	}
X
X	n = fgetc(fd); /* Number of traps */
X	while(n--) {
X		(void) fread((genericptr_t)&tmptrap, sizeof(tmptrap), 1, fd);
X
X		x = tmptrap.x;	y = tmptrap.y;
X		typ = (tmptrap.type == -1 ? rndtrap() : tmptrap.type);
X
X		get_location(&x, &y);
X		(void) maketrap(x, y, typ);
X	}
X
X	n = fgetc(fd);	/* Number of monsters */
X	while(n--) {
X		(void) fread((genericptr_t)&tmpmons, sizeof(tmpmons), 1, fd);
X
X		x = tmpmons.x;	y = tmpmons.y;
X		get_location(&x, &y);
X
X		if	(tmpmons.class >= 0)
X			c = tmpmons.class;
X		else if (tmpmons.class > -11)
X			c = rmonst[-tmpmons.class - 1];
X		else
X			c = 0;
X
X		if (!c)
X			(void) makemon((struct permonst *) 0, x, y);
X		else if (tmpmons.id != -1)
X			(void) makemon(&mons[tmpmons.id], x, y);
X		else
X			(void) makemon(mkclass(c), x, y);
X	}
X
X	n = fgetc(fd); /* Number of objects */
X	while(n--) {
X		(void) fread((genericptr_t) &tmpobj, sizeof(object),1, fd);
X
X		x = tmpobj.x;  y = tmpobj.y;
X		get_location(&x, &y);
X
X		if	(tmpobj.class >= 0)
X			c = tmpobj.class;
X		else if (tmpobj.class > -11)
X			c = robjects[-tmpobj.class - 1];
X		else
X			c = 0;
X
X		if (!c)
X			(void) mkobj_at(0, x, y);
X		else if (tmpobj.id != -1)
X			(void) mksobj_at(tmpobj.id, x, y);
X		else
X			(void) mkobj_at(c, x, y);
X	}
X
X	n = fgetc(fd); /* Number of drawbridges */
X	while(n--) {
X		(void) fread((genericptr_t)&tmpdb, sizeof(tmpdb), 1, fd);
X
X		x = tmpdb.x;  y = tmpdb.y;
X		get_location(&x, &y);
X
X		if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.open))
X		    impossible("Cannot create drawbridge.");
X	}
X
X	n = fgetc(fd); /* Number of mazewalks */
X	while(n--) {
X		(void) fread((genericptr_t)&tmpwalk, sizeof(tmpwalk), 1, fd);
X
X		get_location(&tmpwalk.x, &tmpwalk.y);
X
X		walklist[nwalk++] = tmpwalk;
X	}
X
X	n = fgetc(fd); /* Number of non_diggables */
X	while(n--) {
X		(void) fread((genericptr_t)&tmpdig, sizeof(tmpdig), 1, fd);
X
X		get_location(&tmpdig.x1, &tmpdig.y1);
X		get_location(&tmpdig.x2, &tmpdig.y2);
X
X		make_walls_nondiggable(tmpdig.x1, tmpdig.y1,
X				       tmpdig.x2, tmpdig.y2);
X	}
X
X	n = fgetc(fd); /* Number of ladders */
X	while(n--) {
X		(void) fread((genericptr_t)&tmplad, sizeof(tmplad), 1, fd);
X
X		x = tmplad.x;  y = tmplad.y;
X		get_location(&x, &y);
X
X		levl[x][y].typ = LADDER;
X		if (tmplad.up == 1) {
X			xupladder = x;	yupladder = y;
X			levl[x][y].ladder = LA_UP;
X		} else {
X			xdnladder = x;	ydnladder = y;
X			levl[x][y].ladder = LA_DOWN;
X		}
X	}
X
X#ifdef ALTARS
X	n = fgetc(fd); /* Number of altars */
X	while(n--) {
X		(void) fread((genericptr_t)&tmpaltar, sizeof(tmpaltar), 1, fd);
X
X		x = tmpaltar.x;  y = tmpaltar.y;
X		get_location(&x, &y);
X
X		typ = tmpaltar.align == -11 ? rn2(3) :
X		      tmpaltar.align < 0    ? ralign[-tmpaltar.align-1] :
X					      tmpaltar.align;
X		if (tmpaltar.shrine)
X		    typ |= A_SHRINE;
X
X		levl[x][y].typ = ALTAR;
X		levl[x][y].altarmask = typ;
X	}
X#endif /* ALTARS /**/
X    }
X
X    while(nwalk--) {
X	    xi = walklist[nwalk].x;
X	    yi = walklist[nwalk].y;
X	    dir = walklist[nwalk].dir;
X
X	    move(&xi, &yi, dir);
X	    x = xi;
X	    y = yi;
X
X#ifndef WALLIFIED_MAZE
X	    levl[x][y].typ = CORR;
X#else
X	    levl[x][y].typ = ROOM;
X#endif
X
X	    /*
X	     * We must be sure that the parity of the coordinates for
X	     * walkfrom() is odd.  But we must also take into account
X	     * what direction was chosen.
X	     */
X	    if(!(x % 2))
X		if (dir == W_EAST)
X		    x++;
X		else
X		    x--;
X
X#ifndef WALLIFIED_MAZE
X	    levl[x][y].typ = CORR;
X#else
X	    levl[x][y].typ = ROOM;
X#endif
X
X	    if (!(y % 2))
X		if (dir == W_SOUTH)
X		    y++;
X		else
X		    y--;
X
X	    walkfrom(x, y);
X    }
X    wallification(2, 2, x_maze_max, y_maze_max, TRUE);
X
X    /*
X     * If there's a significant portion of maze unused by the special level,
X     * we don't want it empty.
X     *
X     * Makes the number of traps, monsters, etc. proportional
X     * to the size of the maze.
X     */
X    mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
X
X    for(x = 2; x < x_maze_max; x++)
X	for(y = 2; y < y_maze_max; y++)
X	    if(Map[x][y]) mapcount--;
X
X    if (mapcount > (int) (mapcountmax / 10)) {
X	    mapfact = (int) ((mapcount * 100L) / mapcountmax);
X	    for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
X		    maze1xy(&mm);
X		    (void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y);
X	    }
X	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
X		    maze1xy(&mm);
X		    (void) mksobj_at(BOULDER, mm.x, mm.y);
X	    }
X	    maze1xy(&mm);
X	    (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
X	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
X		    maze1xy(&mm);
X		    (void) makemon((struct permonst *) 0, mm.x, mm.y);
X	    }
X	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
X		    maze1xy(&mm);
X		    mkgold(0L,mm.x,mm.y);
X	    }
X	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
X		    maze1xy(&mm);
X		    (void) maketrap(mm.x, mm.y,rndtrap());
X	    }
X    }
X    return TRUE;
X}
X
X/*
X * General loader
X */
X
Xboolean
Xload_special(name)
Xchar *name;
X{
X	FILE *fd;
X	boolean result;
X	schar c;
X
X	fd = fopen(name, RDMODE);
X	if (!fd) return FALSE;
X
X	if ((c = fgetc(fd)) == EOF) {
X		(void)fclose(fd);
X		return FALSE;
X	}
X
X	switch (c) {
X		case 1: 	/* Alas, this is not yet implemented. */
X		    result = load_rooms(fd);
X		    break;
X		case 2: 	/* But this is implemented :-) */
X		    result = load_maze(fd);
X		    break;
X		default:	/* ??? */
X		    result = FALSE;
X	}
X	(void)fclose(fd);
X	return result;
X}
X#endif /* STRONGHOLD /**/
END_OF_FILE
if test 12800 -ne `wc -c <'src/sp_lev.c'`; then
    echo shar: \"'src/sp_lev.c'\" unpacked with wrong size!
fi
# end of 'src/sp_lev.c'
fi
if test -f 'src/unixmain.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/unixmain.c'\"
else
echo shar: Extracting \"'src/unixmain.c'\" \(12696 characters\)
sed "s/^X//" >'src/unixmain.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)unixmain.c	3.0	89/01/13
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X/* main.c - (Unix) version */
X
X#include <signal.h>
X#include <pwd.h>
X
X#include "hack.h"
X
Xint hackpid = 0;				/* current pid */
Xint locknum = 0;				/* max num of players */
X#ifdef DEF_PAGER
Xchar *catmore = 0;				/* default pager */
X#endif
Xchar SAVEF[PL_NSIZ + 11] = "save/";	/* save/99999player */
Xchar *hname = 0;		/* name of the game (argv[0] of call) */
Xchar obuf[BUFSIZ];	/* BUFSIZ is defined in stdio.h */
X
Xint (*occupation)() = DUMMY;
Xint (*afternmv)() = DUMMY;
X#ifdef CHDIR
Xstatic void chdirx();
X#endif /* CHDIR */
Xstatic void whoami(), newgame();
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	struct passwd *pw;
X	extern struct passwd *getpwuid();
X	extern int x_maze_max, y_maze_max;
X	register int fd;
X#ifdef CHDIR
X	register char *dir;
X#endif
X#ifdef COMPRESS
X	char	cmd[80], old[80];
X#endif
X	hname = argv[0];
X	hackpid = getpid();
X	(void) umask(0);
X
X#ifdef CHDIR			/* otherwise no chdir() */
X	/*
X	 * See if we must change directory to the playground.
X	 * (Perhaps hack runs suid and playground is inaccessible
X	 *  for the player.)
X	 * The environment variable HACKDIR is overridden by a
X	 *  -d command line option (must be the first option given)
X	 */
X
X	dir = getenv("HACKDIR");
X	if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
X		argc--;
X		argv++;
X		dir = argv[0]+2;
X		if(*dir == '=' || *dir == ':') dir++;
X		if(!*dir && argc > 1) {
X			argc--;
X			argv++;
X			dir = argv[0];
X		}
X		if(!*dir)
X		    error("Flag -d must be followed by a directory name.");
X	}
X#endif /* CHDIR /**/
X	/* Set the default values of the presentation characters */
X	(void) memcpy((char *) &showsyms, 
X		(char *) &defsyms, sizeof(struct symbols));
X	initoptions();
X	whoami();
X	/*
X	 * Now we know the directory containing 'record' and
X	 * may do a prscore().
X	 */
X	if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
X#ifdef CHDIR
X		chdirx(dir,0);
X#endif
X		prscore(argc, argv);
X		exit(0);
X	}
X
X	/*
X	 * It seems he really wants to play.
X	 * Remember tty modes, to be restored on exit.
X	 */
X	gettty();
X	setbuf(stdout,obuf);
X	setrandom();
X	startup();
X	cls();
X	u.uhp = 1;	/* prevent RIP on early quits */
X	u.ux = FAR;	/* prevent nscr() */
X	(void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
X
X	/*
X	 * Find the creation date of this game,
X	 * so as to avoid restoring outdated savefiles.
X	 */
X	gethdate(hname);
X
X	/*
X	 * We cannot do chdir earlier, otherwise gethdate will fail.
X	 */
X#ifdef CHDIR
X	chdirx(dir,1);
X#endif
X
X	/*
X	 * Process options.
X	 */
X	while(argc > 1 && argv[1][0] == '-'){
X		argv++;
X		argc--;
X		switch(argv[0][1]){
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X		case 'D':
X		case 'X':
X			pw = getpwuid(getuid());
X# ifdef WIZARD
X			if(!strcmp(pw->pw_name, WIZARD))
X				wizard = TRUE;
X# endif
X# if defined(WIZARD) && defined(EXPLORE_MODE)
X			else
X# endif
X# ifdef EXPLORE_MODE
X				discover = TRUE;
X# endif
X			break;
X#endif
X#ifdef NEWS
X		case 'n':
X			flags.nonews = TRUE;
X			break;
X#endif
X		case 'u':
X			if(argv[0][2])
X			  (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
X			else if(argc > 1) {
X			  argc--;
X			  argv++;
X			  (void) strncpy(plname, argv[0], sizeof(plname)-1);
X			} else
X				Printf("Player name expected after -u\n");
X			break;
X		default:
X			/* allow -T for Tourist, etc. */
X			(void) strncpy(pl_character, argv[0]+1,
X				sizeof(pl_character)-1);
X
X			/* Printf("Unknown option: %s\n", *argv); */
X		}
X	}
X
X	if(argc > 1)
X		locknum = atoi(argv[1]);
X#ifdef MAX_NR_OF_PLAYERS
X	if(!locknum || locknum > MAX_NR_OF_PLAYERS)
X		locknum = MAX_NR_OF_PLAYERS;
X#endif
X#ifdef DEF_PAGER
X	if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
X		catmore = DEF_PAGER;
X#endif
X#ifdef MAIL
X	getmailstatus();
X#endif
X#ifdef WIZARD
X	if(wizard) Strcpy(plname, "wizard"); else
X#endif
X	if(!*plname || !strncmp(plname, "player", 4)
X		    || !strncmp(plname, "games", 4))
X		askname();
X	plnamesuffix();		/* strip suffix from name; calls askname() */
X				/* again if suffix was whole name */
X				/* accepts any suffix */
X#ifdef WIZARD
X	if(!wizard) {
X#endif
X		/*
X		 * check for multiple games under the same name
X		 * (if !locknum) or check max nr of players (otherwise)
X		 */
X		(void) signal(SIGQUIT,SIG_IGN);
X		(void) signal(SIGINT,SIG_IGN);
X		if(!locknum)
X			Strcpy(lock,plname);
X		getlock();	/* sets lock if locknum != 0 */
X#ifdef WIZARD
X	} else
X		Strcpy(lock,plname);
X#endif /* WIZARD /**/
X	setftty();
X
X	/* 
X	 * Initialisation of the boundaries of the mazes
X	 * Both boundaries have to be even.
X	 */
X	 
X	x_maze_max = COLNO-1;
X	if (x_maze_max % 2) 
X		x_maze_max--;
X	y_maze_max = ROWNO-1;
X	if (y_maze_max % 2) 
X		y_maze_max--;
X
X	/* initialize static monster strength array */
X	init_monstr();
X
X	Sprintf(SAVEF, "save/%d%s", getuid(), plname);
X	regularize(SAVEF+5);		/* avoid . or / in name */
X#ifdef COMPRESS
X	Strcpy(old,SAVEF);
X	Strcat(SAVEF,".Z");
X	if((fd = open(SAVEF,0)) >= 0) {
X 	    (void) close(fd);
X	    Strcpy(cmd, COMPRESS);
X	    Strcat(cmd, " -d ");	/* uncompress */
X# ifdef COMPRESS_OPTIONS
X	    Strcat(cmd, COMPRESS_OPTIONS);
X	    Strcat(cmd, " ");
X# endif
X	    Strcat(cmd,SAVEF);
X	    (void) system(cmd);
X	}
X	Strcpy(SAVEF,old);
X#endif
X	if((fd = open(SAVEF,0)) >= 0 &&
X	   (uptodate(fd) || unlink(SAVEF) == 666)) {
X		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X		pline("Restoring old save file...");
X		(void) fflush(stdout);
X		if(!dorecover(fd))
X			goto not_recovered;
X		pline("Hello %s, welcome to NetHack!", plname);
X		/* get shopkeeper set properly if restore is in shop */
X		(void) inshop();
X#ifdef EXPLORE_MODE
X		if (discover) {
X			You("are in non-scoring discovery mode.");
X			pline("Do you want to keep the save file? ");
X			if(yn() == 'n')
X				(void) unlink(SAVEF);
X		}
X#endif
X		flags.move = 0;
X	} else {
Xnot_recovered:
X		newgame();
X		/* give welcome message before pickup messages */
X		pline("Hello %s, welcome to NetHack!", plname);
X#ifdef EXPLORE_MODE
X		if (discover)
X			You("are in non-scoring discovery mode.");
X#endif
X		flags.move = 0;
X		set_wear();
X		pickup(1);
X		read_engr_at(u.ux,u.uy);
X	}
X
X	flags.moonphase = phase_of_the_moon();
X	if(flags.moonphase == FULL_MOON) {
X		You("are lucky!  Full moon tonight.");
X		if(!u.uluck) change_luck(1);
X	} else if(flags.moonphase == NEW_MOON) {
X		pline("Be careful!  New moon tonight.");
X	}
X
X	initrack();
X
X	for(;;) {
X		if(flags.move) {	/* actual time passed */
X
X#ifdef SOUNDS
X			dosounds();
X#endif
X			settrack();
X
X			if(moves%2 == 0 ||
X			  (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
X				movemon();
X#ifdef HARD
X				if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
X#else
X				if(!rn2(70))
X#endif
X				    (void) makemon((struct permonst *)0, 0, 0);
X			}
X			if(Glib) glibr();
X			timeout();
X			++moves;
X#ifdef THEOLOGY
X			if (u.ublesscnt)  u.ublesscnt--;
X#endif
X			if(flags.time) flags.botl = 1;
X#ifdef POLYSELF
X			if(u.mtimedone)
X			    if(u.mh < 1) rehumanize();
X			else
X#endif
X			    if(u.uhp < 1) {
X				You("die...");
X				done("died");
X			    }
X#ifdef POLYSELF
X			if (u.mtimedone) {
X			    if (u.mh < u.mhmax) {
X				if (Regeneration || !(moves%20)) {
X					flags.botl = 1;
X					u.mh++;
X				}
X			    }
X			}
X#endif
X			if(u.uhp < u.uhpmax) {
X				if(u.ulevel > 9) {
X				    int heal;
X
X				    if(HRegeneration || !(moves%3)) {
X					flags.botl = 1;
X					if (ACURR(A_CON) <= 12) heal = 1;
X					else heal = rnd((int) ACURR(A_CON)-12);
X					if (heal > u.ulevel-9) heal = u.ulevel-9;
X					u.uhp += heal;
X					if(u.uhp > u.uhpmax)
X					    u.uhp = u.uhpmax;
X				    }
X				} else if(HRegeneration ||
X				      (!(moves%((MAXULEV+12)/(u.ulevel+2)+1)))) {
X					flags.botl = 1;
X					u.uhp++;
X				}
X			}
X#ifdef SPELLS
X			if ((u.uen<u.uenmax) && (!(moves%(19-ACURR(A_INT)/2)))) {
X				u.uen += rn2((int)ACURR(A_WIS)/5 + 1) + 1;
X				if (u.uen > u.uenmax)  u.uen = u.uenmax;
X				flags.botl = 1;
X			}
X#endif
X			if(Teleportation && !rn2(85)) tele();
X#ifdef POLYSELF
X			if(Polymorph && !rn2(100)) polyself();
X			if(u.ulycn >= 0 && !rn2(80 - (20 * night())))
X				you_were();
X#endif
X			if(Searching && multi >= 0) (void) dosearch0(1);
X			hatch_eggs();
X			gethungry();
X			invault();
X			amulet();
X#ifdef HARD
X			if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3));
X			if (u.udemigod) {
X
X				if(u.udg_cnt) u.udg_cnt--;
X				if(!u.udg_cnt) {
X
X					intervene();
X					u.udg_cnt = rn1(200, 50);
X				}
X			}
X#endif
X			restore_attrib();
X		}
X		if(multi < 0) {
X			if(!++multi){
X				pline(nomovemsg ? nomovemsg :
X					"You can move again.");
X				nomovemsg = 0;
X				if(afternmv) (*afternmv)();
X				afternmv = 0;
X			}
X		}
X
X		find_ac();
X		if(!flags.mv || Blind)
X		{
X			seeobjs();
X			seemons();
X			seeglds();
X			nscr();
X		}
X		if(flags.botl || flags.botlx) bot();
X
X		flags.move = 1;
X
X		if(multi >= 0 && occupation) {
X
X			if(monster_nearby())
X				stop_occupation();
X			else if ((*occupation)() == 0)
X				occupation = 0;
X			continue;
X		}
X
X		if((u.uhave_amulet || Clairvoyant) && 
X#ifdef ENDGAME
X			dlevel != ENDLEVEL &&
X#endif
X			!(moves%15) && !rn2(2)) do_vicinity_map();
X
X		u.umoved = FALSE;
X		if(multi > 0) {
X			lookaround();
X			if(!multi) {	/* lookaround may clear multi */
X				flags.move = 0;
X				continue;
X			}
X			if(flags.mv) {
X				if(multi < COLNO && !--multi)
X					flags.mv = flags.run = 0;
X				domove();
X			} else {
X				--multi;
X				rhack(save_cm);
X			}
X		} else if(multi == 0) {
X#ifdef MAIL
X			ckmailstatus();
X#endif
X			rhack(NULL);
X		}
X		if(multi && multi%7 == 0)
X			(void) fflush(stdout);
X	}
X}
X
Xvoid
Xglo(foo)
Xregister int foo;
X{
X	/* construct the string  xlock.n  */
X	register char *tf;
X
X	tf = lock;
X	while(*tf && *tf != '.') tf++;
X	Sprintf(tf, ".%d", foo);
X}
X
X/*
X * plname is filled either by an option (-u Player  or  -uPlayer) or
X * explicitly (by being the wizard) or by askname.
X * It may still contain a suffix denoting pl_character.
X */
Xvoid
Xaskname(){
Xregister int c,ct;
X	Printf("\nWho are you? ");
X	(void) fflush(stdout);
X	ct = 0;
X	while((c = Getchar()) != '\n'){
X		if(c == EOF) error("End of input\n");
X		/* some people get confused when their erase char is not ^H */
X		if(c == '\010') {
X			if(ct) ct--;
X			continue;
X		}
X		if(c != '-')
X		if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
X		if(ct < sizeof(plname)-1) plname[ct++] = c;
X	}
X	plname[ct] = 0;
X	if(ct == 0) askname();
X}
X
X/*VARARGS1*/
Xvoid
Ximpossible(s,x1,x2)
Xregister char *s, *x1, *x2;
X{
X	pline(s,x1,x2);
X	pline("Program in disorder - perhaps you'd better Quit.");
X}
X
X#ifdef CHDIR
Xstatic void
Xchdirx(dir, wr)
Xchar *dir;
Xboolean wr;
X{
X
X# ifdef SECURE
X	if(dir					/* User specified directory? */
X#  ifdef HACKDIR
X	       && strcmp(dir, HACKDIR)		/* and not the default? */
X#  endif
X		) {
X		(void) setgid(getgid());
X		(void) setuid(getuid());		/* Ron Wessels */
X	}
X# endif
X
X# ifdef HACKDIR
X	if(dir == NULL)
X		dir = HACKDIR;
X# endif
X
X	if(dir && chdir(dir) < 0) {
X		perror(dir);
X		error("Cannot chdir to %s.", dir);
X	}
X
X	/* warn the player if he cannot write the record file */
X	/* perhaps we should also test whether . is writable */
X	/* unfortunately the access systemcall is worthless */
X	if(wr) {
X	    register int fd;
X
X	    if(dir == NULL)
X		dir = ".";
X	    if((fd = open(RECORD, 2)) < 0) {
X		Printf("Warning: cannot write %s/%s", dir, RECORD);
X		getret();
X	    } else
X		(void) close(fd);
X	}
X}
X#endif /* CHDIR /**/
X
Xvoid
Xstop_occupation()
X{
X	if(occupation) {
X		You("stop %s.", occtxt);
X		occupation = 0;
X#ifdef REDO
X		multi = 0;
X		pushch(0);		
X#endif
X	}
X}
X
Xstatic void
Xwhoami() {
X	/*
X	 * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
X	 *			2. Use $USER or $LOGNAME	(if 1. fails)
X	 *			3. Use getlogin()		(if 2. fails)
X	 * The resulting name is overridden by command line options.
X	 * If everything fails, or if the resulting name is some generic
X	 * account like "games", "play", "player", "hack" then eventually
X	 * we'll ask him.
X	 * Note that we trust him here; it is possible to play under
X	 * somebody else's name.
X	 */
X	register char *s;
X
X	if(!*plname && (s = getenv("USER")))
X		(void) strncpy(plname, s, sizeof(plname)-1);
X	if(!*plname && (s = getenv("LOGNAME")))
X		(void) strncpy(plname, s, sizeof(plname)-1);
X	if(!*plname && (s = getlogin()))
X		(void) strncpy(plname, s, sizeof(plname)-1);
X}
X
Xstatic void
Xnewgame() {
X	fobj = fcobj = invent = 0;
X	fmon = fallen_down = 0;
X	ftrap = 0;
X	fgold = 0;
X	flags.ident = 1;
X
X	init_objects();
X	u_init();
X
X	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X
X	mklev();
X	u.ux = xupstair;
X	u.uy = yupstair;
X	(void) inshop();
X
X	setsee();
X	flags.botlx = 1;
X
X	/* Move the monster from under you or else
X	 * makedog() will fail when it calls makemon().
X	 * 			- ucsfcgl!kneller
X	 */
X	if(levl[u.ux][u.uy].mmask) mnexto(m_at(u.ux, u.uy));
X
X	(void) makedog();
X	seemons();
X#ifdef NEWS
X	if(flags.nonews || !readnews())
X		/* after reading news we did docrt() already */
X#endif
X		docrt();
X
X	return;
X}
END_OF_FILE
if test 12696 -ne `wc -c <'src/unixmain.c'`; then
    echo shar: \"'src/unixmain.c'\" unpacked with wrong size!
fi
# end of 'src/unixmain.c'
fi
echo shar: End of archive 27 \(of 38\).
cp /dev/null ark27isdone
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