[net.sources] Another silly game

estes@tty3b.UUCP (8-01-83"Edward E 9723i) (09/05/84)

---
The following is the source for a fairly entertaining inter-terminal game.

The game is called Phantasia, and is a type of role-playing game with
monsters and things.  It is text-based (as opposed to graphic).

The game has been running at pur-ee for the past two years, and has quite
a following (although I can't figure out why).

Anyway, do with it what you will.  If you send bug reports or suggestions
to me, perhaps I will be able to find the time to generate a new version
of Phantasia after while.  (However, I can do without comments about how
mindless the game is.)

I've done my best to make the thing portable, and put dependencies in
the Makefile.  So far, I've run it on a VAX with 4.1bsd, a VAX with
4.2 bsd, a PDP-11/70 (you need separate I/D) with Unix 4.0, and a
3B20S with System 5.0.

Enjoy.
-------CUT----------CUT---------CUT-----------CUT---------CUT------------
: This is a shar archieve.  Extract with sh, not csh.
: The rest of this file will extract:
: Makefile phant.h main.c func0.c func1.c func2.c fight.c setfiles.c monsters phant.nr
echo extracting - Makefile
sed 's/^X//' > Makefile << '!EOR!'
X# Makefile for Phantasia 3.2
X#
X# To create game:
X#
X# 1)  Set up a directory where the game and its support files will live.
X#        (It is suggested that the source be kept somewhere else.)
X# 2)  Set up the variables in Makefile to reflect your particular situation.
X# 3)  Check out ok_to_play() at the end of main.c if you want to include
X#        code to restrict access at certain times.
X# 4)  'make install' and watch it fly.
X
XXSTR =		/t2/estes/bin/xstr
XRM =		-rm
X
X# Add '-ljobs' to LIBS if 4.1bsd
XLIBS =		-lm -lcurses -ltermlib
X# May need '-I/usr/include/sys' for 4.2bsd
XCFLAGS =	-O -I.
X
X# DEST is where the program and its support files reside
XDEST =		/t2/estes/phantsrc
X
X# The following are program constants which are implementation dependent.
X#
X# PATH is the same as $DEST.
X# WIZARD is the login of the one who will clean up things.
X# UID is the uid of game wizard.
X# RAND is one more than the largest number generated by rand().
X#	Possible values for this are:
X#		32768.0		(for 15 bit rand())
X#		65536.0		(for 16 bit rand())
X#		2147483648.0	(for 31 bit rand())
X# ACCESS is fopen() access to open a file for writing, but no
X#	clearing the file,  e.g. "a", or "r+".  (Use "r+" if you have it.)
X# define OK_TO_PLAY to restrict playing access.  Also see function ok_to_play()
X#	in main.c, and tailor to your own needs.
X# define ENEMY to include code for checking of a 'hit list' of resricted 
X#	accounts.  The list of logins goes in the file 'enemy'.
X# define BSD41 for 4.1bsd
X# define BSD42 for 4.2bsd
X# define USG3 for System III, or similar
X# define USG5 for System V
XFLAGS = 	-DPATH=\"${DEST} \
X		-DWIZARD=\"estes\" \
X		-DUID=419 \
X		-DRAND=32767.0 \
X		-DACCESS=\"r+\" \
X		-DOK_TO_PLAY \
X		-DENEMY \
X		-DUSG5
X
XOFILES =	main.o fight.o func0.o func1.o func2.o
X
Xall:		phantasia setfiles phant.help
X
X# need separate i/d space on small machines
Xphantasia:	${OFILES} strings.o
X		${CC} ${OFILES} strings.o ${LIBS} -o phantasia
X
X${OFILES}:	phant.h
X		${CC} -E ${CFLAGS} ${FLAGS} $*.c | ${XSTR} -c -
X		${CC} -c ${CFLAGS} x.c
X		mv x.o $*.o
X
Xstrings.o:	${OFILES} strings
X		${XSTR}
X		${CC} -c xs.c
X		mv xs.o strings.o
X
Xsetfiles:	phant.h setfiles.c
X		${CC} ${CFLAGS} ${FLAGS} setfiles.c -o setfiles -lm
X
X# the flags below on tbl and nroff are to make a line printable version
Xphant.help:	phant.nr
X		tbl -TX phant.nr | nroff -man -Ttn300 > phant.help
X
Xinstall:	all
X		cp phantasia monsters phant.help ${DEST}
X		chmod 755 ${DEST}
X		chmod 4711 ${DEST}/phantasia
X		chmod 644 ${DEST}/phant.help
X		setfiles
X
Xclean:
X		${RM} -f *.o phantasia phant.help strings x.c xs.c
!EOR!
echo extracting - phant.h
sed 's/^X//' > phant.h << '!EOR!'
X/*
X * phant.h	Include file for Phantasia
X */
X
X#include <setjmp.h>
X#include <curses.h>
X#include <time.h>
X#include <pwd.h>
X#include <signal.h>
X#include <math.h>
X
X/* ring constants */
X#define NONE	0
X#define NAZBAD	1
X#define NAZREG	2
X#define DLREG	3
X#define DLBAD	4
X#define SPOILED 5
X
X/* some functions and pseudo-functions */
X#define toupper(CH)	((CH) > 96 ? (CH) ^ 32 : (CH))	/* may be upper or lower */
X#define tolower(CH)	((CH) | 32)			/* must be upper */
X#define rnd()		(((double) rand()) / RAND)
X#define roll(BASE,INTERVAL)	floor((BASE) + (INTERVAL) * rnd())
X#define sgn(x)	(-(x < 0) + (x > 0))
X#define abs(x)	((x) < 0 ? -(x) : (x))
X#define circ(x,y)	floor(sqrt((double) ((x) * (x) + (y) * (y))) / 125 + 1)
X#define max(A,B)	((A) > (B) ? (A) : (B))
X#define min(A,B)	((A) < (B) ? (A) : (B))
X#define valarstuff(ARG)	decree(ARG)
X#define illcmd()	mvaddstr(6,0,"Illegal command.\n")
X#define maxmove 	floor(charac.lvl * 1.5 + 1)
X#define illmove()	mvaddstr(6,0,"Too far.\n")
X#define rndattack()	if (rnd() < 0.2 && charac.status == PLAYING && !throne) \
X				fight(&charac,-1)
X#define strcalc(STR,SICK)	max(0,min(0.9 * STR, SICK * STR/20))
X#define spdcalc(LVL,GLD,GEM)	max(0,((GLD + GEM/2) - 1000)/200.0 - LVL)
X#define illspell()	mvaddstr(6,0,"Illegal spell.\n")
X#define nomanna()	mvaddstr(6,0,"Not enough manna for that spell.\n")
X#define somebetter()	addstr("But you already have something better.\n")
X
X/* status constants */
X#define OFF	0
X#define PLAYING 1
X#define CLOAKED 2
X#define INBATTLE	3
X#define DIE	4
X#define QUIT	5
X
X/* tampered constants */
X#define NRGVOID 1
X#define GRAIL	2
X#define TRANSPORT	3
X#define GOLD	4
X#define CURSED	5
X#define MONSTER 6
X#define BLESS	7
X#define MOVED	8
X#define HEAL	9
X#define VAPORIZED	10
X#define STOLEN	11
X
X/* structure definitions */
Xstruct	stats		/* player stats */
X	{
X	char	name[21];	/* name */
X	char	pswd[9];	/* password */
X	char	login[10];	/* login */
X	double	x;		/* x coord */
X	double	y;		/* y coord */
X	double	exp;		/* experience */
X	int	lvl;		/* level */
X	short	quk;		/* quick */
X	double	str;		/* strength */
X	double	sin;		/* sin */
X	double	man;		/* manna */
X	double	gld;		/* gold */
X	double	nrg;		/* energy */
X	double	mxn;		/* max. energy */
X	double	mag;		/* magic level */
X	double	brn;		/* brains */
X	short	crn;		/* crowns */
X	struct
X		{
X		short	type;
X		short	duration;
X		}	rng;	/* ring stuff */
X	bool	pal;		/* palantir */
X	double	psn;		/* poison */
X	short	hw;		/* holy water */
X	short	amu;		/* amulets */
X	bool	bls;		/* blessing */
X	short	chm;		/* charms */
X	double	gem;		/* gems */
X	short	quks;		/* quicksilver */
X	double	swd;		/* sword */
X	double	shd;		/* shield */
X	short	typ;		/* character type */
X	bool	vrg;		/* virgin */
X	short	lastused;	/* day of year last used */
X	short	status; 	/* playing, cloaked, etc. */
X	short	tampered;	/* decree'd, etc. flag */
X	double	scratch1, scratch2;	/* var's for above */
X	bool	blind;		/* blindness */
X	int	wormhole;	/* # of wormhole, 0 = none */
X	long	age;		/* age in seconds */
X	short	degen;		/* age/2500 last degenerated */
X	};
X
Xstruct	mstats		/* monster stats */
X	{
X	char	name[26];	/* name */
X	double	str;		/* strength */
X	double	brn;		/* brains */
X	double	spd;		/* speed */
X	double	hit;		/* hits (energy) */
X	double	exp;		/* experience */
X	int	trs;		/* treasure type */
X	int	typ;		/* special type */
X	int	flk;		/* % flock */
X	};
X
Xstruct	nrgvoid 	/* energy void */
X	{
X	bool	active; 	/* active or not */
X	double	x,y;		/* coordinates */
X	};
X
Xstruct	worm_hole	/* worm hole */
X	{
X	char	f, b, l, r;	/* forward, back, left, right */
X	};
X
X/* files */
X#define monsterfile	PATH/monsters"
X#define peoplefile	PATH/characs"
X#define gameprog	PATH/phantasia"
X#define messfile	PATH/mess"
X#define lastdead	PATH/lastdead"
X#define helpfile	PATH/phant.help"
X#define motd		PATH/motd"
X#define goldfile	PATH/gold"
X#define voidfile	PATH/void"
X#define	enemyfile	PATH/enemy"
X
X/* library functions and system calls */
Xunsigned sleep();
Xlong	time(), ftell();
Xchar	*getlogin(), *getpass(), *ctime();
Xstruct	passwd	*getpwuid();
Xchar	*strcpy(), *strncpy();
X
X/* function and global variable declarations */
Xvoid	adjuststats(), callmonster(), checkinterm(), checkmov(), checktampered(),
X	cstat(), death(), decree(), exit1(), fight(), genchar(), getstring(), init1(),
X	initchar(), interm(), kingstuff(), leave(), movelvl(), neatstuf(),
X	paws(), printhelp(), printmonster(), printplayers(), printstats(), purge(),
X	showall(), showusers(), statread(), talk(), tampered(), titlestuff(),
X	trade(), treasure(), trunc(), update(), voidupdate();
Xint	allocvoid(), findchar(), findspace(), gch(), interrupt(), rgetch(), rngcalc();
Xunsigned level();
Xdouble	inflt();
Xchar	*printloc();
Xbool	findname();
X#ifdef	OK_TO_PLAY
Xbool	ok_to_play();
X#endif
X
Xextern	jmp_buf fightenv, mainenv;
Xextern	double	strength, speed;
Xextern	bool	beyond, marsh, throne, valhala, changed, fghting, su, wmhl;
Xextern	struct worm_hole	w_h[];
Xextern	long	secs;
Xextern	int	fileloc, users;
!EOR!
echo extracting - main.c
sed 's/^X//' > main.c << '!EOR!'
X/*
X * Phantasia 3.2 -- Interterminal fantasy game
X *
X * Edward A. Estes
X * AT&T Teletype Corp., September 4, 1984
X */
X
X/*
X * This is the program which drives the whole mess.  Hopefully, you will be
X * able to wade throught the garbage if you have to fix something.
X * several undocumented items exist.  The program checks uid and sets the
X * boolean flag 'su' (super user) if the person is allowed special powers.
X * The 'su' may execute any of the valar/council options.  Also,
X * a 'vaporize' option exists to kill anybody at will.  The 'su' can select
X * character type 7, which starts out with the maximum possible in each
X * category.  (The resulting character is an experimento.)  The 'su' may
X * also change the stats of other characters with the -x option.
X */
X
X/*
X * The program allocates as much file space as it needs to store characters,
X * so the possibility exists for the character file to grow without bound.
X * The file is purged upon normal entry to try to avoid that problem.
X * A similar problem exists for energy voids.  To alleviate the problem here,
X * the void file is cleared with every new king.
X */
X
X/*
X * The support functions are split between various files with no apparent
X * order.  Use of 'ctags' is recommended to find a particular function.
X */
X
X/*
X * Put one line of text into the file 'motd' for announcements, etc.
X */
X
X/*
X * If ENEMY is defined, a list of restricted login names is checked
X * in the file 'enemy'.  These names are listed, one per line, with
X * no trailing blanks.
X */
X
X#include "phant.h"
X
Xdouble	strength, speed;
Xbool	beyond, marsh, throne, valhala, changed, fghting, su, wmhl;
Xint	fileloc, users;
Xjmp_buf	fightenv, mainenv;
Xlong	secs;
X/*
X * worm hole map -- This table is carefully set up so that one can always
X * return the way he/she came by inverting the initial path.
X */
Xstruct	worm_hole	w_h[] =
X	{
X	0,0,0,0,	35,22,2,0,	2,2,0,1,	59,34,64,0,
X	54,47,0,60,	50,62,0,56,	19,31,25,0,	0,35,41,41,
X	0,46,40,23,	24,0,29,30,	44,57,56,0,	0,44,39,40,
X	61,41,0,42,	32,0,17,18,	57,0,63,64,	0,33,26,34,
X	48,0,54,55,	28,23,22,13,	63,25,13,19,	34,6,18,20,
X	27,26,19,21,	15,27,20,27,	1,28,34,17,	17,29,8,24,
X	29,9,23,25,	18,30,24,6,	20,32,27,15,	21,20,21,26,
X	22,17,46,29,	23,24,28,9,	25,38,9,31,	6,39,30,32,
X	26,13,31,33,	15,40,32,35,	3,19,15,22,	7,1,33,36,
X	37,37,35,37,	36,36,36,38,	30,42,37,39,	31,43,38,11,
X	33,45,11,8,	12,48,7,7,	38,49,12,43,	39,51,42,44,
X	11,10,43,45,	40,52,44,46,	8,53,45,28,	4,54,51,48,
X	41,16,47,49,	42,55,48,50,	62,5,49,51,	43,56,50,47,
X	45,58,53,53,	46,59,52,52,	47,4,55,16,	49,61,16,54,
X	51,63,5,10,	10,14,59,58,	52,64,57,59,	53,3,58,57,
X	60,60,4,61,	55,12,60,62,	5,50,61,63,	56,18,62,14,
X	58,33,14,3
X	};
X
Xmain(argc,argv)				/* Phantasia main routine */
Xint	argc;
Xchar	*argv[];
X{
Xstruct	stats	charac;
Xchar	aline[200], *login = NULL;
Xdouble	x = 0.0, y = 0.0;
Xint	ch, ch2;
Xreg	int	loop, temp;
XFILE	*fp;
Xbool	shrt = FALSE, examine = FALSE, header = FALSE;
X
X	if ((login = getlogin()) == NULL)
X		login = getpwuid(getuid())->pw_name;
X#ifdef ENEMY
X	/* check hit list of restricted accounts */
X	if ((fp = fopen(enemyfile, "r")) != NULL)
X		{
X		char	enemy[20];
X
X		while (fscanf(fp, "%s", enemy) != EOF)
X			if (!strcmp(login,enemy))
X				{
X				printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", login);
X				printf ("Mail comments to %s.\n", WIZARD);
X				exit (0);
X				}
X		fclose (fp);
X		}
X#endif
X	setbuf(stdin, (char *) NULL);	/* this may or may not be necessary */
X	su = (getuid() == UID);
X	fghting = FALSE;
X	users = 0;
X	if (argc > 1 && (*++argv)[0] == '-')
X		switch ((*argv)[1])
X			{
X			case 'h':		/* help */
X				printhelp();
X				exit(0);
X				/*NOTREACHED*/
X			case 's':		/* short */
X				shrt = TRUE;
X				break;
X			case 'x':		/* examine */
X				examine = TRUE;
X				break;
X			case 'H':		/* Header */
X				header = TRUE;
X				break;
X			case 'm':		/* monsters */
X				printmonster();
X				exit(0);
X				/*NOTREACHED*/
X			case 'a':		/* all users */
X				showusers();
X				exit(0);
X				/*NOTREACHED*/
X			case 'p':		/* purge old players */
X				purge();
X				exit(0);
X				/*NOTREACHED*/
X			}
X	if (!isatty(0))	/* don't let non-tty's play */
X		exit(0);
X	init1();	/* set up for screen stuff */
X	if (examine)
X		{
X		cstat();
X		exit1();
X		/*NOTREACHED*/
X		}
X	if (!shrt)
X		{
X		titlestuff();
X		purge();	/* clean up old characters */
X		}
X	if (header)
X		{
X		exit1();
X		/*NOTREACHED*/
X		}
X#ifdef OK_TO_PLAY
X	if (!ok_to_play())
X		{
X		mvaddstr(23,27,"Sorry, you can't play now.\n");
X		exit1();
X		/*NOTREACHED*/
X		}
X#endif
X	mvaddstr(23,24,"Do you have a character to run? ");
X	ch = rgetch();
X	if (toupper(ch) == 'Y')
X		fileloc = findchar(&charac);
X	else
X		{
X		initchar(&charac);
X		clear();
X		mvaddstr(5,21,"Which type of character do you want:");
X		mvaddstr(10,4,"1:Magic User  2:Fighter  3:Elf  4:Dwarf  5:Halfling  6:Experimento  ? ");
X		ch = rgetch();
X		do
X			{
X			genchar(&charac,ch);
X			mvprintw(15,14,"Strength:  %2.0f  Manna      : %3.0f  Quickness   :  %2d",
X				charac.str,charac.man,charac.quk);
X			mvprintw(16,14,"Brains  :  %2.0f  Magic Level:  %2.0f  Energy Level:  %2.0f",
X				charac.brn,charac.mag,charac.nrg);
X			if (charac.typ != 6)
X				{
X				mvaddstr(17,14,"Type '1' to keep >");
X				ch2 = rgetch();
X				}
X			else
X				break;
X			}
X		while (ch2 != '1');
X		if (charac.typ == 6)
X			{
X			mvaddstr(19,0,"Enter the X Y coordinates of your experimento ? ");
X			getstring(aline,80);
X			sscanf(aline,"%F %F",&x,&y);
X			charac.x = (abs(x) > 1.2e+6) ? sgn(x)*1.2e+6 : floor(x);
X			charac.y = (abs(y) > 1.2e+6) ? sgn(y)*1.2e+6 : floor(y);
X			}
X		do
X			{
X			mvaddstr(20,0,"Give your character a name [up to 20 characters] ?  ");
X			getstring(aline,80);
X			strncpy(charac.name,aline,20);
X			charac.name[20] = '\0';
X			}
X		while (findname(charac.name));
X		putchar('\n');
X		fflush(stdout);
X		nocrmode();
X		do
X			{
X			strcpy(charac.pswd,getpass("Give your character a password [up to 8 characters] ? "));
X			putchar('\n');
X			strcpy(aline,getpass("One more time to verify ? "));
X			}
X		while (strcmp(charac.pswd,aline));
X		fileloc = findspace();
X		}
X	crmode();
X	if (charac.status)
X		{
X		clear();
X		addstr("Your character did not exit normally last time.\n");
X		addstr("If you think you have good cause to have you character saved,\n");
X		printw("you may quit and mail your reason to '%s'.\n",WIZARD);
X		addstr("Do you want to quit ? ");
X		ch = rgetch();
X		if (toupper(ch) == 'Y')
X			{
X			charac.quk = -100;
X			leave(&charac);
X			/*NOTREACHED*/
X			}
X		death(&charac);
X		}
X	charac.status = PLAYING;
X	strcpy(charac.login,login);
X	time(&secs);
X	charac.lastused = localtime(&secs)->tm_yday;
X	update(&charac,fileloc);
X	clear();
X#ifdef	BSD41
X	sigset(SIGINT,interrupt);
X#endif
X#ifdef	BSD42
X	signal(SIGINT,interrupt,-1);
X#endif
X#ifdef	USG3
X	signal(SIGINT,interrupt);
X#endif
X#ifdef	USG5
X	signal(SIGINT,interrupt);
X#endif
X
X/* all set for now */
X
XTOP:	switch (setjmp(mainenv))
X		{
X		case QUIT:
X#ifdef	BSD41
X			sigrelse(SIGINT);
X#endif
X#ifdef	BSD42
X			signal(SIGINT,interrupt,-1);
X#endif
X#ifdef	USG3
X			signal(SIGINT,interrupt);
X#endif
X#ifdef	USG5
X			signal(SIGINT,interrupt);
X#endif
X			leave(&charac);
X			/*NOTREACHED*/
X		case DIE:
X#ifdef	BSD41
X			sigrelse(SIGINT);
X#endif
X#ifdef	BSD42
X			signal(SIGINT,interrupt,-1);
X#endif
X#ifdef	USG3
X			signal(SIGINT,interrupt);
X#endif
X#ifdef	USG5
X			signal(SIGINT,interrupt);
X#endif
X			death(&charac);
X			break;
X		}
X#ifdef OK_TO_PLAY
X	if (!ok_to_play())
X		{
X		mvaddstr(6,0,"Whoops!  Can't play now.\n");
X		leave(&charac);
X		/*NOTREACHED*/
X		}
X#endif
X	fghting = FALSE;
X	adjuststats(&charac);
X	if (throne && !charac.crn && (charac.typ < 10 || charac.typ > 20))
X		{
X		mvaddstr(6,0,"You're not allowed in the Lord's Chamber without a crown.\n");
X		changed = TRUE;
X		charac.x = charac.y = 10;
X		}
X	if (charac.status != CLOAKED && abs(charac.x) == abs(charac.y)
X		 && floor(sqrt(fabs(charac.x/100.0))) == sqrt(fabs(charac.x/100.0)) && !throne)
X		{
X		trade(&charac);
X		clear();
X		}
X	checktampered(&charac);
X	checkinterm(&charac);
X	if (charac.nrg < 0 || (charac.lvl >= 10000 && charac.typ != 99))
X		death(&charac);
X	neatstuff(&charac);
X	if (changed)
X		{
X		update(&charac,fileloc);
X		changed = FALSE;
X		goto TOP;
X		}
X	move(5,0);
X	clrtoeol();
X	fp = fopen(messfile,"r");
X	if (fgets(aline,160,fp))
X		addstr(aline);
X	fclose(fp);
X	printstats(&charac);
X	move(3,0);
X	clrtoeol();
X	if (!wmhl)
X		{
X		if (throne)
X			kingstuff(&charac);
X		addstr("1:Move  2:Players  3:Talk  4:Stats  5:Quit  ");
X		if (charac.lvl >= 5 && charac.mag >= 15)
X			addstr("6:Cloak  ");
X		if (charac.lvl >= 10 && charac.mag >= 25)
X			addstr("7:Teleport  ");
X		if (charac.typ > 20)
X			addstr("8:Intervention");
X		ch = gch(charac.rng.type);
X		clrtoeol();
X		move(6,0);
X		clrtobot();
X		if (charac.typ == 99 && (ch == '1' || ch == '7'))
X			ch = ' ';
X		switch (ch2 = toupper(ch))
X			{
X			case 'N':
X				charac.y += maxmove;
X				break;
X			case 'S':
X				charac.y -= maxmove;
X				break;
X			case 'E':
X				charac.x += maxmove;
X				break;
X			case 'W':
X				charac.x -= maxmove;
X				break;
X			default:	/* rest */
X				if (charac.status == CLOAKED)
X					if (charac.man > 3.0)
X						charac.man -= 3;
X					else
X						{
X						charac.status = PLAYING;
X						changed = TRUE;
X						}
X				else
X					{
X					charac.man += circ(charac.x,charac.y)/3+0.5;
X					charac.man += charac.lvl/5+0.5;
X					}
X				rndattack();
X				break;
X			case '1':	/* move */
X				for (loop = 3; loop; --loop)
X					{
X					mvaddstr(5,0,"X Y Coordinates ? ");
X					getstring(aline,80);
X					if (sscanf(aline,"%F %F",&x,&y) < 2)
X						;
X					else
X						if (hypot((double) charac.x - x, (double) charac.y - y) > maxmove)
X							illmove();
X						else
X							{
X							charac.x = x;
X							charac.y = y;
X							break;
X							}
X					}
X				break;
X			case '2':	/* players */
X				printplayers(&charac);
X				break;
X			case '3':	/* message */
X				talk(charac.name);
X				break;
X			case '4':	/* stats */
X				showall(&charac);
X				break;
X			case '5':	/* good-bye */
X				leave(&charac);
X				/*NOTREACHED*/
X			case '6':	/* cloak */
X				if (charac.lvl < 5 || charac.mag < 15)
X					illcmd();
X				else if (charac.status == CLOAKED)
X					charac.status = PLAYING;
X				else if (charac.man < 35)
X					{
X					mvaddstr(6,0,"No power left.\n");
X					refresh();
X					}
X				else
X					{
X					changed = TRUE;
X					charac.man -= 35;
X					charac.status = CLOAKED;
X					}
X				break;
X			case '7':	/* teleport */
X				if (charac.lvl < 10 || charac.mag < 25)
X					illcmd();
X				else 
X					for (loop = 3; loop; --loop)
X						{
X						mvaddstr(5,0,"X Y Coordinates ? ");
X						getstring(aline,80);
X						if (sscanf(aline,"%F %F",&x,&y) == 2)
X							if ((temp = hypot(charac.x-x,charac.y-y))
X									> (charac.lvl+charac.mag)*5+((charac.typ > 20) ? 1e+6 : 0)
X									&& !throne)
X								illmove();
X							else if ((temp = (temp/75+1)*20) > charac.man && !throne)
X								mvaddstr(6,0,"Not enough power for that distance.\n");
X							else
X								{
X								charac.x = x;
X								charac.y = y;
X								if (!throne)
X									charac.man -= temp;
X								break;
X								}
X						}
X				break;
X			case '9':	/* monster */
X				if (throne)
X					mvaddstr(6,0,"No monsters in the chamber!\n");
X				else if (charac.typ != 99)
X					{
X					charac.status = PLAYING;
X					changed = TRUE;
X					charac.sin += 1e-6;
X					fight(&charac,-1);
X					}
X				break;
X			case '0':	/* decree */
X				if (su || charac.typ > 10 && charac.typ < 20 && throne)
X					decree(&charac);
X				else
X					illcmd();
X				break;
X			case '8':	/* intervention */
X				if (su || charac.typ > 20)
X					valarstuff(&charac);
X				else
X					illcmd();
X				break;
X			case '\014':	/* redo screen */
X				clear();
X			}
X		if (ch2 == 'E' || ch2 == 'W' || ch2 == 'N' || ch2 == 'S'
X			|| ch2 == '1' || ch2 == '7')
X			{
X			checkmov(&charac);
X			rndattack();
X			changed = TRUE;
X			}
X		}
X	else
X		{
X		addstr("F:Forward  B:Back  R:Right  L:Left  Q:Quit  T:Talk  P:Players  S:Stats  ");
X		ch = rgetch();
X		move(6,0);
X		clrtobot();
X		switch (toupper(ch))
X			{
X			default:
X				if (charac.status == CLOAKED)
X					if (charac.man > 3.0)
X						charac.man -= 3;
X					else
X						{
X						charac.status = PLAYING;
X						changed = TRUE;
X						}
X				else
X					charac.man += charac.lvl/5+0.5;
X				break;
X			case 'F':
X				temp = (int) w_h[charac.wormhole].f;
X				goto CHKMOVE;
X			case 'B':
X				temp = (int) w_h[charac.wormhole].b;
X				goto CHKMOVE;
X			case 'R':
X				temp = (int) w_h[charac.wormhole].r;
X				goto CHKMOVE;
X			case 'L':
X				temp = (int) w_h[charac.wormhole].l;
X				goto CHKMOVE;
X			case 'Q':
X				leave(&charac);
X				/*NOTREACHED*/
X			case 'T':
X				talk(charac.name);
X				break;
X			case 'P':
X				printplayers(&charac);
X				break;
X			case 'S':
X				showall(&charac);
X				break;
X			case '\014':	/* redo screen */
X				clear();
X			}
X		goto TOP;
XCHKMOVE:	if (!temp)
X				{
X				charac.y = 0.0;
X				charac.x = pow(-1.0,(double) charac.wormhole) * charac.wormhole * 400 - 1.0;
X				charac.wormhole = 0;
X				changed = TRUE;
X				}
X			else
X				charac.wormhole = temp;
X		}
X	goto TOP;
X}
X
X/*
X * This function is provided to allow one to restrict access to the game.
X * Tailor this routine as appropriate.
X */
X
X#ifdef	OK_TO_PLAY
X#include <sys/types.h>
X#include <utmp.h>	/* used for counting users on system */
X
Xbool	ok_to_play()		/* return FALSE if playing is not allowed at this time */
X{
X#define	MAXUSERS	8	/* max. number of people on system */
Xreg	struct	tm	*tp;
Xreg	int	numusers = 0;
XFILE	*fp;
Xlong	now;
Xstruct	utmp	ubuf;
X
X	if (su)
X		return (TRUE);
X	/* check time of day */
X	time(&now);
X	if (((tp = localtime(&now))->tm_hour > 8 && tp->tm_hour < 12)	/* 8-noon */
X		|| (tp->tm_hour > 13 && tp->tm_hour < 16))		/* 1-4 pm */
X		return (FALSE);
X	/* check # of users */
X	fp = fopen("/etc/utmp","r");
X	while (fread((char *) &ubuf,sizeof(ubuf),1,fp))
X#ifdef	USG5
X		if (ubuf.ut_type == USER_PROCESS)
X#else
X	if (*ubuf.ut_name)
X#endif
X			++numusers;
X	fclose(fp);
X	if (numusers > MAXUSERS)
X		return (FALSE);
X	return (TRUE);
X}
X#endif
!EOR!
echo extracting - func0.c
sed 's/^X//' > func0.c << '!EOR!'
X/*
X * func0.c	Phantasia support routines
X */
X
X#include "phant.h"
X
Xvoid	treasure(stat,treastyp,size)		/* select a treasure */
Xreg	struct	stats	*stat;
Xshort	treastyp;
Xreg	int	size;
X{
Xreg	int	which;
Xint	ch;
Xdouble	temp, temp2;
Xchar	aline[35];
XFILE	*fp;
X
X	which = roll(1,3);
X	move(3,0);
X	clrtobot();
X	move(5,0);
X	if (rnd() > 0.65)	/* gold and gems */
X		if (treastyp > 7)	/* gems */
X			{
X			temp = roll(1,(treastyp - 7)*(treastyp - 7)*(size - 1)/4);
X			printw("You have discovered %.0f gems!  Will you pick them up ? ",temp);
X			ch = rgetch();
X			addch('\n');
X			if (toupper(ch) == 'Y')
X				if (rnd() < treastyp/40 + 0.05)	/* cursed */
X					{
X					addstr("They were cursed!\n");
X					goto CURSE;
X					}
X				else
X					stat->gem += temp;
X			return;
X			}
X		else	/* gold */
X			{
X			temp = roll(treastyp*10,treastyp*treastyp*10*(size - 1));
X			printw("You have found %.0f gold pieces.  Do you want to pick them up ? ",temp);
X			ch = rgetch();
X			addch('\n');
X			if (toupper(ch) == 'Y')
X				if (rnd() < treastyp/35 + 0.04)	/* cursed */
X					{
X					addstr("They were cursed!\n");
X					goto CURSE;
X					}
X				else
X					{
X					stat->gld += floor(0.9 * temp);
X					fp = fopen(goldfile,"r");
X					fread((char *) &temp2,sizeof(double),1,fp);
X					fclose(fp);
X					fp = fopen(goldfile,"w");
X					temp2 += floor(temp/10);
X					fwrite((char *) &temp2,sizeof(double),1,fp);
X					fclose(fp);
X					}
X			return;
X			}
X	else	/* other treasures */
X		{
X		addstr("You have found some treasure.  Do you want to inspect it ? ");
X		ch = rgetch();
X		addch('\n');
X		if (toupper(ch) != 'Y')
X			return;
X		else
X			if (rnd() < 0.08 && treastyp != 4)
X				{
X				addstr("It was cursed!\n");
X				goto CURSE;
X				}
X			else
X				switch(treastyp)
X					{
X					case 1:
X						switch(which)
X							{
X							case 1:
X								addstr("You've discovered a power booster!\n");
X								stat->man += roll(size*4,size*30);
X								break;
X							case 2:
X								addstr("You have encountered a druid.\n");
X								stat->exp += roll(0,2000 + size*400);
X								break;
X							case 3:
X								addstr("You have found a holy orb.\n");
X								stat->sin = max(0,stat->sin - 0.25);
X								break;
X							}
X						break;
X					case 2:
X						switch (which)
X							{
X							case 1:
X								addstr("You have found an amulet.\n");
X								++stat->amu;
X								break;
X							case 2:
X								addstr("You've found some holy water!\n");
X								++stat->hw;
X								break;
X							case 3:
X								addstr("You've met a hermit!\n");
X								stat->sin *= 0.75;
X								stat->man += 12*size;
X								break;
X							}
X						break;
X					case 3:
X						switch (which)
X							{
X							case 1:
X								temp = roll(7,30 + size/10);
X								printw("You've found a +%.0f shield!\n",temp);
X								if (temp >= stat->shd)
X									stat->shd = temp;
X								else
X									somebetter();
X								break;
X							case 2:
X								addstr("You have rescued a virgin.  Will you be honorable ? ");
X								ch = rgetch();
X								if (toupper(ch) == 'Y')
X									stat->vrg = TRUE;
X								else
X									{
X									stat->exp += 2000*size;
X									++stat->sin;
X									}
X								break;
X							case 3:
X								addstr("You've discovered some athelas!\n");
X								--stat->psn;
X								break;
X							}
X						break;
X					case 4:
X						addstr("You've found a scroll.  Will you read it ? ");
X						ch = rgetch();
X						addch('\n');
X						if (toupper(ch) == 'Y')
X							switch ((int) roll(1,6))
X								{
X								case 1:
X									addstr("It throws up a shield for you next monster.\n");
X									paws(8);
X									longjmp(fightenv,2);
X									/*NOTREACHED*/
X								case 2:
X									addstr("It makes you invisible for you next monster.\n");
X									paws(8);
X									speed = 1e6;
X									longjmp(fightenv,0);
X									/*NOTREACHED*/
X								case 3:
X									addstr("It increases your strength ten fold to fight your next monster.\n");
X									paws(8);
X									strength *= 10;
X									longjmp(fightenv,0);
X									/*NOTREACHED*/
X								case 4:
X									addstr("It is a general knowledge scroll.\n");
X									stat->brn += roll(2,size);
X									stat->mag += roll(1,size/2);
X									break;
X							case 5:
X								addstr("It tells you how to pick your next monster.\n");
X								addstr("Which monster do you want [0-99] ? ");
X								which = inflt();
X								which = min(99,max(0,which));
X								fight(stat,which);
X								break;
X							case 6:
X								addstr("It was cursed!\n");
X								goto CURSE;
X							}
X						break;
X					case 5:
X						switch (which)
X							{
X							case 1:
X								temp = roll(size/4+5,size/2 + 9);
X								printw("You've discovered a +%.0f dagger.\n",temp);
X								if (temp >= stat->swd)
X									stat->swd = temp;
X								else
X									somebetter();
X								break;
X							case 2:
X								temp = roll(7.5 + size*3,size * 2 + 160);
X								printw("You have found some +%.0f armour!\n",temp);
X								if (temp >= stat->shd)
X									stat->shd = temp;
X								else
X									somebetter();
X								break;
X							case 3:
X								addstr("You've found a tablet.\n");
X								stat->brn += 4.5*size;
X								break;
X							}
X						break;
X					case 6:
X						switch (which)
X							{
X							case 1:
X								addstr("You've found a priest.\n");
X								stat->nrg = stat->mxn + stat->shd;
X								stat->sin /= 2;
X								stat->man += 24*size;
X								stat->brn += size;
X								break;
X							case 2:
X								addstr("You have come upon Robin Hood!\n");
X								stat->shd += size*2;
X								stat->str += size/2.5 + 1;
X								break;
X							case 3:
X									temp = roll(2 + size/4,size/1.2 + 10);
X								printw("You have found a +%.0f axe!\n",temp);
X								if (temp >= stat->swd)
X									stat->swd = temp;
X								else
X									somebetter();
X								break;
X							}
X						break;
X					case 7:
X						switch (which)
X							{
X							case 1:
X								addstr("You've discovered a charm!\n");
X								++stat->chm;
X								break;
X							case 2:
X								addstr("You have encountered Merlyn!\n");
X								stat->brn += size + 5;
X								stat->mag += size/3 + 5;
X								stat->man += size*10;
X								break;
X							case 3:
X								temp = roll(5+size/3,size/1.5 + 20);
X								printw("You have found a +%.0f war hammer!\n",temp);
X								if (temp >= stat->swd)
X									stat->swd = temp;
X								else
X									somebetter();
X								break;
X							}
X						break;
X					case 8:
X						switch (which)
X							{
X							case 1:
X								addstr("You have found a healing potion.\n");
X								stat->psn = min(-2,stat->psn-2);
X								break;
X							case 2:
X								addstr("You have discovered a transporter.  Do you wish to go anywhere ? ");
X								ch = rgetch();
X								addch('\n');
X								if (toupper(ch) == 'Y')
X									{
X									addstr("X Y Coordinates ? ");
X									getstring(aline,80);
X									sscanf(aline,"%F %F",&stat->x,&stat->y);
X									stat->x = floor(stat->x);
X									stat->y = floor(stat->y);
X									}
X								break;
X							case 3:
X								temp = roll(10 + size/1.2,size*3 + 30);
X								printw("You've found a +%.0f sword!\n",temp);
X								if (temp >= stat->swd)
X									stat->swd = temp;
X								else
X									somebetter();
X								break;
X							}
X						break;
X					case 10:
X					case 11:
X					case 12:
X					case 13:
X						if (rnd() < 0.33)
X							{
X							if (treastyp == 10)
X								{
X								addstr("You've found a pair of elven boots!\n");
X								stat->quk += 2;
X								break;
X								}
X							else if (treastyp == 11 && !stat->pal)
X								{
X								addstr("You've acquired Saruman's palantir.\n");
X								stat->pal = TRUE;
X								break;
X								}
X							else if (!stat->rng.type && stat->typ < 20 && (treastyp == 12 || treastyp == 13))
X								{
X								if (treastyp == 12)
X									if (rnd() < 0.8)
X										{
X										which = NAZREG;
X										temp = 15;
X										}
X									else
X										{
X										which = NAZBAD;
X										temp = 10 + rngcalc(stat->typ) + roll(0,5);
X										}
X								else
X									if (rnd() > 0.9)
X										{
X										which = DLREG;
X										temp = 0;
X										}
X									else
X										{
X										which = DLBAD;
X										temp = 15 + rngcalc(stat->typ) + roll(0,5);
X										}
X									addstr("You've discovered a ring.  Will you pick it up ? ");
X									ch = rgetch();
X									addch('\n');
X									if (toupper(ch) == 'Y')
X										{
X										stat->rng.type = which;
X										stat->rng.duration = temp;
X										}
X								}
X							break;
X							}
X						case 9:
X							switch (which)
X								{
X								case 1:
X									if (!(stat->lvl > 1000 || stat->crn > floor((double) stat->lvl/100)
X											|| stat->lvl < 10))
X										{
X										addstr("You have found a golden crown!\n");
X										++stat->crn;
X										break;
X										}
X								case 2:
X									addstr("You've been blessed!\n");
X									stat->bls = TRUE;
X									stat->sin /=3;
X									stat->nrg = stat->mxn + stat->shd;
X									stat->man += 100*size;
X									break;
X								case 3:
X									temp = roll(1,size/5+5);
X									temp = min(temp,99);
X									printw("You have discovered some +%.0f quicksilver!\n",temp);
X									if (temp >= stat->quks)
X										stat->quks = temp;
X									else
X										somebetter();
X									break;
X								}
X							break;
X						}
X		refresh();
X		return;
X		}
XCURSE:	if (stat->chm)
X		{
X		addstr("But your charm saved you!\n");
X		--stat->chm;
X		}
X	else if (stat->amu)
X		{
X		addstr("But your amulet saved you!\n");
X		--stat->amu;
X		}
X	else
X		{
X		stat->nrg = (stat->mxn + stat->shd)/10;
X		stat->psn += 0.25;
X		}
X}
X
Xvoid	callmonster(which,size,mons)		/* fill a structure with monster 'which' of size 'size' */
Xreg	int	which, size;
Xreg	struct	mstats	*mons;
X{
XFILE	*fp;
Xchar	instr[100];
X
X	which = min(which,99);
X	fp = fopen(monsterfile,"r");
X	for (++which; which; --which)
X		fgets(instr,100,fp);
X	strncpy(mons->name,instr,24);
X	mons->name[24] = '\0';
X	sscanf(instr + 24,"%F%F%F%F%F%d%d%d",&mons->str,&mons->brn,&mons->spd,&mons->hit,
X		&mons->exp,&mons->trs,&mons->typ,&mons->flk);
X	if (mons->typ == 2)	/* Modnar */
X		{
X		mons->str *= rnd() + 0.5;
X		mons->brn *= rnd() + 0.5;
X		mons->spd *= rnd() + 0.5;
X		mons->hit *= rnd() + 0.5;
X		mons->exp *= rnd() + 0.5;
X		mons->trs *= rnd();
X		}
X	else if (mons->typ == 3)	/* mimic */
X		{
X		fseek(fp,0L,0);
X		for (which = roll(0,100); which; --which)
X			fgets(instr,100,fp);
X		strncpy(mons->name,instr,24);
X		}
X	trunc(mons->name);
X	mons->str += (size-1)*mons->str/2;
X	mons->brn *= size;
X	mons->spd += size * 1.e-9;
X	mons->hit *= size;
X	mons->exp *= size;
X	fclose(fp);
X}
X
Xstruct	/* lookup table for rolling stats and making increases upon gaining levels */
X	{
X	struct
X		{
X		int	base;
X		int	interval;
X		float	increase;
X		} quick,      strength,      manna,	    energy,	   brains,	  magic;
X	} table[7] =
X		{
X/* mag. usr: */ 30, 6, 0.0,   20, 6, 2.0,    50,51,75.0,    30,16,20.0,    60,26, 6.0,	  5, 5,2.75,
X/* fighter:  */ 30, 6, 0.0,   40,16, 3.0,    30,21,40.0,    45,26,30.0,    25,21, 3.0,	  3, 4, 1.5,
X/* elf:      */ 32, 7, 0.0,   35,11, 2.5,    45,46,65.0,    30,21,25.0,    40,26, 4.0,	  4, 4, 2.0,
X/* dwarf:    */ 25, 6, 0.0,   45,21, 5.0,    25,21,30.0,    60,41,35.0,    20,21, 2.5,	  2, 4, 1.0,
X/* halfling: */ 34, 0, 0.0,   20, 6, 2.0,    25,21,30.0,    55,36,30.0,    40,36, 4.5,	  1, 4, 1.0,
X/* exprmnto: */ 27, 0, 0.0,   25, 0, 0.0,    100,0, 0.0,    35, 0, 0.0,    25, 0, 0.0,	  2, 0, 0.0,
X/* super:    */ 38, 0, 0.0,   65, 0, 0.0,    100,0, 0.0,    80, 0, 0.0,    85, 0, 0.0,	  9, 0, 0.0
X		};
X
Xvoid	genchar(res,type)				/* init a charac struct */
Xint	type;
Xreg	struct	stats	*res;
X{
Xregister int	subscript;
X
X	if (type < '1' || type > '6')
X		if (type != '7' || !su)
X			type = '2';	/* fighter is default */
X	subscript = type - '1';
X	res->quk = roll(table[subscript].quick.base,table[subscript].quick.interval);
X	res->str = roll(table[subscript].strength.base,table[subscript].strength.interval);
X	res->man = roll(table[subscript].manna.base,table[subscript].manna.interval);
X	res->mxn = res->nrg = roll(table[subscript].energy.base,table[subscript].energy.interval);
X	res->brn = roll(table[subscript].brains.base,table[subscript].brains.interval);
X	res->mag = roll(table[subscript].magic.base,table[subscript].magic.interval);
X	res->typ = subscript;
X	if (subscript < 6)
X		++res->typ;
X	if (type == '5')
X		res->exp = roll(600,200);	/* give halfling some exp. */
X}
X
Xvoid	movelvl(stat)				/* update stats for new level */
Xreg	struct	stats	*stat;
X{
Xreg	int	type;
Xreg	unsigned new;
Xdouble	inc;
X
X	changed = TRUE;
X	type = abs(stat->typ);
X	if (type < 6)
X		;	/* normal */
X	else if (type < 10)
X		type = roll(1,5);	/* experimento */
X	else if (type < 20)
X		{
X		type -= 10;	/* king */
X		if (type > 5)
X			type = roll(1,5);	/* experimento */
X		}
X	else if (type < 26)
X		type -= 20;	/* council of wise */
X	else
X		type = roll(1,5);	/* everything else */
X	new = level(stat->exp);
X	inc = new - stat->lvl;
X	--type; 		/* set up for subscripting into table */
X	stat->str += table[type].strength.increase * inc;
X	stat->man += table[type].manna.increase * inc;
X	stat->brn += table[type].brains.increase * inc;
X	stat->mag += table[type].magic.increase * inc;
X	stat->mxn += table[type].energy.increase * inc;
X	stat->nrg = stat->mxn + stat->shd;
X	if ((stat->lvl = min(10000,new)) >= 1000)
X		{	/* no longer able to be king */
X		stat->gld += stat->crn * 5000;
X		stat->crn = 0;
X		stat->typ = abs(stat->typ);
X		}
X	if (stat->lvl >= 3000 && stat->typ < 20)
X		{	/* make a member of the council */
X		mvaddstr(6,0,"You have made it to the Council of the Wise.\nGood Luck on your search for the Holy Grail.\n");
X		stat->rng.type = 0;
X		stat->rng.duration = 3;
X		stat->typ = abs(stat->typ) + (stat->typ > 10 ? 10 :20);
X		}
X}
X
Xchar	*printloc(x,y)			/* return a pointer to a string specifying location */
Xdouble	x,y;		/* also, set some global flags */
X{
Xreg	int	size, loc;
Xreg	char	*label;
Xstatic	char	res[80],
X		*nametable[4][4] =	 /* names of places */
X		{
X		"Anorien",	"Ithilien",	"Rohan",	"Lorien",
X		"Gondor",	"Mordor",	"Dunland",	"Rovanion",
X		"South Gondor", "Khand",	"Eriador",	"The Iron Hills",
X		"Far Harad",	"Near Harad",	"The Northern Waste", "Rhun"
X		};
X
X	throne = beyond = marsh = FALSE;
X	if (wmhl)
X		return (strcpy(res," is in the Wormholes"));
X	else if (valhala)
X		return (strcpy(res," is in Valhala"));
X	else if ((size = circ(x,y)) >= 1000)
X		{
X		if (max(abs(x),abs(y)) > 1100000)
X			{
X			label = "The Point of No Return";
X			beyond = TRUE;
X			}
X		else
X			label = "The Ashen Mountains";
X		}
X	else if (size >= 55)
X		label = "Morannon";
X	else if (size >= 35)
X		label = "Kennaquahair";
X	else if (size >= 20)
X		{
X		label = "The Dead Marshes";
X		marsh = TRUE;
X		}
X	else if (size >= 9)
X		label = "The Outer Waste";
X	else if (size >= 5)
X		label = "The Moors Adventurous";
X	else
X		{
X		if (!x && !y)
X			{
X			label = "The Lord's Chamber";
X			throne = TRUE;
X			}
X		else
X			{
X			loc = (x > 0) + 2 * (y >= 0);
X			label = nametable[size-1][loc];
X			}
X		}
X	sprintf(res," is in %s  (%.0f,%.0f)",label,x,y);
X	return (res);
X}
X
Xvoid	initchar(stat)				/* put in some default values */
Xreg	struct	stats	*stat;
X{
X	stat->x = roll(-125,251);
X	stat->y = roll(-125,251);
X	stat->exp = stat->lvl = stat->sin = 0;
X	stat->crn = stat->psn = 0;
X	stat->rng.type = NONE;
X	stat->rng.duration = 0;
X	stat->blind = stat->vrg = stat->pal = FALSE;
X	stat->hw = stat->amu = stat->bls = 0;
X	stat->chm = 0;
X	stat->gem = 0.1;
X	stat->gld = roll(25,50) + roll(0,25) + 0.1;
X	stat->quks = stat->swd = stat->shd = 0;
X	stat->typ = 0;
X	stat->status = stat->tampered = OFF;
X	stat->scratch1 = stat->scratch2 = 0.0;
X	stat->wormhole = 0;
X	stat->age = 0;
X	stat->degen = 1;
X}
X
Xvoid	trade(stat)				/* trading post */
Xreg	struct	stats	*stat;
X{
Xstatic	struct
X		{
X		char	*item;
X		int	cost;
X		}	menu[] =
X			{
X			"Manna",1,
X			"Shield",5,
X			"Book",200,
X			"Sword",500,
X			"Charm",1000,
X			"Quiksilver",2500,
X			"Blessing",7000,
X			"Gem",1000	/* this is only to ease changing the value of gems */
X			};
Xdouble	temp;
Xint	ch;
Xreg	int	size, loop;
Xbool	cheat = FALSE;
X
X	changed = TRUE;
X	clear();
X	addstr("You are at a trading post. All purchases must be made with gold.");
X	size = sqrt(abs(stat->x/100)) + 1;
X	size = min(7,size);
X	mvprintw(4,0,"L:Leave  P:Purchase  S:Sell Gems ? ");
X	move(6,0);
X	for (loop = 0; loop < size; ++loop)
X		printw("(%d) %-10s: %6d\n",loop+1,menu[loop].item,menu[loop].cost);
XPROMPT:	mvprintw(1,0,"Gold:  %9.0f  Gems:  %9.0f  Level:   %6u  Charms: %6d\n",stat->gld,stat->gem,stat->lvl,stat->chm);
X	printw("Shield:%9.0f  Sword: %9.0f  Quicksilver:%3d  Blessed: %s",
X		stat->shd,stat->swd,stat->quks,(stat->bls ? " True" : "False"));
X	move(4,36);
X	ch = rgetch();
X	move(15,0);
X	clrtobot();
X	switch(toupper(ch))
X		{
X		case 'L':
X		case '\n':
X			stat->x -= floor(stat->x/10);
X			stat->y -= floor(stat->y/10);
X			return;
X		case 'P':
X			mvaddstr(15,0,"What what would you like to buy ? ");
X			ch = rgetch();
X			move(15,0);
X			clrtoeol();
X			if (ch - '0' > size)
X				addstr("Sorry, this merchant doesn't have that.");
X			else
X				switch (toupper(ch))
X					{
X					case '1':
X						printw("Manna is one per %d gold piece.  How many do you want (%.0f max) ? ",menu[0].cost,floor(stat->gld/menu[0].cost));
X						temp = inflt();
X						if (temp * menu[0].cost > stat->gld || temp < 0)
X							goto CHEAT;
X						else
X							{
X							stat->gld -= floor(temp) * menu[0].cost;
X							if (rnd() < 0.02)
X								goto DISHON;
X							else
X								stat->man += floor(temp);
X							}
X						break;
X					case '2':
X						printw("Shields are %d per +1.  How many do you want (%.0f max) ? ",menu[1].cost,floor(stat->gld/menu[1].cost));
X						temp = inflt();
X						if (!temp)
X							break;
X						if (temp * menu[1].cost > stat->gld || temp < 0)
X							goto CHEAT;
X						else
X							{
X							stat->gld -= floor(temp) * menu[1].cost;
X							if (rnd() < 0.02)
X								goto DISHON;
X							else
X								stat->shd = floor(temp);
X							}
X						break;
X					case '3':
X						printw("A book costs %d gp.  How many do you want (%.0f max) ? ",menu[2].cost,floor(stat->gld/menu[2].cost));
X						temp = inflt();
X						if (temp * menu[2].cost > stat->gld || temp < 0)
X							goto CHEAT;
X						else
X							{
X							stat->gld -= floor(temp) * menu[2].cost;
X							if (rnd() < 0.02)
X								goto DISHON;
X							else
X								if (rnd()*temp > stat->lvl/10 && temp != 1)
X									{
X									printw("\nYou blew your mind!\n");
X									stat->brn /= 5;
X									}
X								else
X									stat->brn += floor(temp)*roll(25,10);
X							}
X						break;
X					case '4':
X						printw("Swords are %d gp per +1.  How many + do you want (%.0f max) ? ",menu[3].cost,floor(stat->gld/menu[3].cost));
X						temp = inflt();
X						if (!temp)
X							break;
X						if (temp * menu[3].cost > stat->gld || temp < 0)
X							goto CHEAT;
X						else
X							{
X							stat->gld -= floor(temp) * menu[3].cost;
X							if (rnd() < 0.02)
X								goto DISHON;
X							else
X								stat->swd = floor(temp);
X							}
X						break;
X					case '5':
X						printw("A charm costs %d gp.  How many do you want (%.0f max) ? ",menu[4].cost,floor(stat->gld/menu[4].cost));
X						temp = inflt();
X						if (temp * menu[4].cost > stat->gld || temp < 0)
X							goto CHEAT;
X						else
X							{
X							stat->gld -= floor(temp) * menu[4].cost;
X							if (rnd() < 0.02)
X								goto DISHON;
X							else
X								stat->chm += floor(temp);
X							}
X						break;
X					case '6':
X						printw("Quicksilver is %d gp per +1.  How many + do you want (%.0f max) ? ",menu[5].cost,floor(stat->gld/menu[5].cost));
X						temp = inflt();
X						if (!temp)
X							break;
X						if (temp * menu[5].cost > stat->gld || temp < 0)
X							goto CHEAT;
X						else
X							{
X							stat->gld -= floor(temp) * menu[5].cost;
X							if (rnd() < 0.02)
X								goto DISHON;
X							else
X								stat->quks = min(99,floor(temp));
X							}
X						break;
X					case '7':
X						printw("A blessing requires a %d gp donation.  Still want one ? ",menu[6].cost);
X						ch = rgetch();
X						if (toupper(ch) == 'Y')
X							if (stat->gld < menu[6].cost)
X								goto CHEAT;
X							else
X								{
X								stat->gld -= menu[6].cost;
X								if (rnd() < 0.02)
X									goto DISHON;
X								else
X									stat->bls = TRUE;
X								}
X						break;
X					}
X			break;
X		case 'S':
X			mvprintw(15,0,"A gem is worth %d gp.  How many do you want to sell (%.0f max) ? ",menu[7].cost,stat->gem);
X			temp = inflt();
X			if (temp > stat->gem || temp < 0)
X				goto CHEAT;
X			else
X				{
X				stat->gem -= floor(temp);
X				stat->gld += floor(temp) * menu[7].cost;
X				}
X		}
X	goto PROMPT;
X
XCHEAT:	move(17,0);
X	if (!cheat)
X		{
X		addstr("Come on, merchants aren't stupid.  Stop cheating.\n");
X		cheat = TRUE;
X		goto PROMPT;
X		}
X	else
X		{
X		addstr("You had your chance.  This merchant happens to be\n");
X		printw("a %.0f level magic user, and you made %s mad!\n",roll(size*10,size*20),(rnd() < 0.5) ? "him" : "her");
X		stat->x += roll(-250,500)*size;
X		stat->y += roll(-250,500)*size;
X		stat->nrg = min(size*20,stat->mxn);
X		++stat->sin;
X		paws(23);
X		}
X	return;
X
XDISHON:	mvaddstr(17,0,"The merchant stole your money!");
X	refresh();
X	stat->x -= floor(stat->x/10);
X	stat->y -= floor(stat->y/10);
X	sleep(2);
X}
X
Xvoid	printstats(stat)				/* show characteristics */
Xreg	struct	stats	*stat;
X{
X	mvprintw(0,0,"%s%s\n",stat->name,printloc(stat->x,stat->y));
X	mvprintw(1,0,"Level :%7u   Energy  :%9.0f(%9.0f)  Manna:%9.0f  Users:%3d\n",
X		stat->lvl,stat->nrg,stat->mxn + stat->shd,stat->man,users);
X	mvprintw(2,0,"Quick :%3.0f(%3d)  Strength:%9.0f(%9.0f)  Gold :%9.0f    ",
X		speed,stat->quk + stat->quks,strength,stat->str + stat->swd,stat->gld);
X	switch (stat->status)
X		{
X		case PLAYING:
X			if (stat->nrg < 0.2 * (stat->mxn + stat->shd))
X				addstr("Low Energy\n");
X			else if (stat->blind)
X				addstr("Blind\n");
X			else
X				clrtoeol();
X			break;
X		case CLOAKED:
X			addstr("Cloaked\n");
X			break;
X		case INBATTLE:
X			addstr("In Battle\n");
X			break;
X		case OFF:
X			addstr("Off\n");
X		}
X}
X
Xvoid	showall(stat)				/* show special items */
Xreg	struct	stats	*stat;
X{
Xstatic	char	*flags[] =
X			{
X			"False",
X			" True"
X			};
X
X	mvprintw(6,0,"Type: %3d  --  ",stat->typ);
X	switch (abs(stat->typ))
X		{
X		case 1:
X		case 11:
X		case 21:
X			addstr("Magic User");
X			break;
X		case 2:
X		case 12:
X		case 22:
X			addstr("Fighter");
X			break;
X		case 3:
X		case 13:
X		case 23:
X			addstr("Elf");
X			break;
X		case 4:
X		case 14:
X		case 24:
X			addstr("Dwarf");
X			break;
X		case 5:
X		case 15:
X		case 25:
X			addstr("Halfling");
X			break;
X		case 6:
X		case 16:
X		case 26:
X			addstr("Experimento");
X			break;
X		case 90:
X			addstr("Ex-Valar");
X			break;
X		case 99:
X			addstr("Valar");
X		}
X	if (stat->typ > 10 && stat->typ < 90)
X		if (stat->typ > 20)
X			addstr(" (Council of Wise)");
X		else
X			addstr(" (King)");
X		addch('\n');
X	mvprintw(7,0,"Experience: %9.0f",stat->exp);
X	mvprintw(8,0,"Brains    : %9.0f",stat->brn);
X	mvprintw(9,0,"Magic Lvl : %9.0f",stat->mag);
X	mvprintw(10,0,"Sin       : %9.5f",stat->sin);
X	mvprintw(11,0,"Poison    : %9.5f",stat->psn);
X	mvprintw(12,0,"Gems      : %9.0f",stat->gem);
X	mvprintw(13,0,"Age       : %9d",stat->age);
X	mvprintw(7,40,"Holy Water: %9d",stat->hw);
X	mvprintw(8,40,"Amulets   : %9d",stat->amu);
X	mvprintw(9,40,"Charms    : %9d",stat->chm);
X	mvprintw(10,40,"Crowns    : %9d",stat->crn);
X	mvprintw(11,40,"Shield    : %9.0f",stat->shd);
X	mvprintw(12,40,"Sword     : %9.0f",stat->swd);
X	mvprintw(13,40,"Quickslver: %9d",stat->quks);
X
X	mvprintw(14,0,"Blessing: %s   Ring: %s   Virgin: %s   Palantir: %s",
X		flags[stat->bls],flags[stat->rng.type != 0],flags[stat->vrg],flags[stat->pal]);
X}
X
Xvoid	neatstuff(stat) 			/* random things */
Xreg	struct	stats	*stat;
X{
Xdouble	temp;
Xint	ch;
X
X	switch ((int) roll(0,100))
X		{
X		case 1:
X		case 2:
X			if (stat->psn > 0)
X				{
X				mvaddstr(5,0,"You've found a medic!  How much will you offer to be cured ? ");
X				temp = inflt();
X				if (temp < 0 || temp > stat->gld)
X					{
X					mvaddstr(6,0,"He was not amused, and made you worse.\n");
X					++stat->psn;
X					}
X				else if (rnd()/2.0 > (temp + 1)/max(stat->gld,1))
X					mvaddstr(6,0,"Sorry, he wasn't interested.\n");
X				else
X					{
X					mvaddstr(6,0,"He accepted.");
X					stat->psn = max(0,stat->psn-1);
X					stat->gld -= floor(temp);
X					}
X				}
X			break;
X		case 3:
X			mvaddstr(6,0,"You've been caught raping and pillaging!\n");
X			stat->exp += 4000;
X			stat->sin += 0.5;
X			break;
X		case 4:
X			temp = roll(6,50);
X			mvprintw(5,0,"You've found %.0f gold pieces, want them ? ",temp);
X			clrtoeol();
X			ch = rgetch();
X			if (toupper(ch) == 'Y')
X				stat->gld += temp;
X			break;
X		case 5:
X			if (stat->sin > 1)
X				{
X				mvaddstr(6,0,"You've found a Holy Orb!\n");
X				stat->sin -= 0.25;
X				}
X			break;
X		case 6:
X			if (stat->psn < 1)
X				{
X				mvaddstr(6,0,"You've been hit with a plague!\n");
X				++stat->psn;
X				}
X			break;
X		case 7:
X			mvaddstr(6,0,"You've found some holy water.\n");
X			++stat->hw;
X			break;
X		case 8:
X			mvaddstr(6,0,"You've met a Guru. . .");
X			if (rnd()*stat->sin > 1)
X				addstr("You disgusted him with your sins!\n");
X			else if (stat->psn > 0)
X				{
X				addstr("He looked kindly upon you, and cured you.\n");
X				stat->psn = 0;
X				}
X			else
X				{
X				addstr("He rewarded you for your virtue.\n");
X				stat->man += 50;
X				stat->shd += 2;
X				}
X			break;
X		case 9:
X			mvaddstr(6,0,"You've found an amulet.\n");
X			++stat->amu;
X			break;
X		case 10:
X			if (stat->blind)
X				{
X				mvaddstr(6,0,"You've regained your sight!\n");
X				stat->blind = FALSE;
X				}
X			break;
X		default:
X			if (stat->psn > 0)
X				stat->nrg -= min(stat->psn*stat->mxn/45,0.9*stat->mxn);
X			stat->nrg = max(stat->nrg,floor(stat->mxn/11));
X		}
X}
!EOR!
echo extracting - func1.c
sed 's/^X//' > func1.c << '!EOR!'
X/*
X * func1.c	Phantasia support routines
X */
X
X#include "phant.h"
X
Xbool	findname(name)				/* return TRUE if name in use */
Xreg	char	*name;
X{
XFILE	*fp;
Xstruct	stats	buf;
X
X	fp = fopen(peoplefile,"r");
X	while (fread((char *) &buf,sizeof(buf),1,fp))
X		if (!strcmp(buf.name,name))
X			{
X			fclose(fp);
X			mvaddstr(21,0,"Name already in use.\n");
X			refresh();
X			return (TRUE);
X			}
X	fclose(fp);
X	return (FALSE);
X}
X
Xint	findspace()				/* allocate space for a character in peoplefile */
X{
XFILE	*fp;
Xstruct	stats	buf;
Xreg	int	loc;
X
X	loc = 0;
X	fp = fopen(peoplefile,"r");
X	while (fread((char *) &buf,sizeof(buf),1,fp))
X		{
X		if (!strcmp(buf.name,"<null>"))
X			{
X			fclose(fp);
X			return (loc);
X			}
X		else
X			++loc;
X		}
X	fclose(fp);
X	fp = fopen(peoplefile,ACCESS);
X	fseek(fp,(long) loc * sizeof(buf),0);
X	initchar(&buf);
X	strcpy(buf.name,"inuse");
X	fwrite((char *) &buf,sizeof(buf),1,fp);
X	fclose(fp);
X	return (loc);
X}
X
Xint	findchar(stat)				/* retrieve a character from file */
Xreg	struct	stats	*stat;
X{
Xreg	int	loc = 0, loop;
Xchar	name[21];
XFILE	*fp;
X
X	if (fp = fopen(peoplefile,"r"))
X		{
X		clear();
X		mvprintw(10,0,"What was your character's name ? ");
X		getstring(name,21);
X		trunc(name);
X		while (fread((char *) stat,sizeof(*stat),1,fp))
X			{
X			if (!strcmp(stat->name,name))
X				{
X				move(11,0);
X				refresh();
X				fclose(fp);
X				nocrmode();
X				for (loop = 0; loop < 2; ++loop)
X					if (!strcmp(getpass("Password ? "),stat->pswd))
X						{
X						crmode();
X						return (loc);
X						}
X					else
X						printf("No good.\n");
X				exit1();
X				/*NOTREACHED*/
X				}
X			++loc;
X			}
X		}
X	fclose(fp);
X	addstr("\n\nNot found.\n");
X	exit1();
X/*NOTREACHED*/
X}
X
Xvoid	leave(stat)				/* save character in file */
Xreg	struct	stats	*stat;
X{
Xlong	ltemp;
X
X	if (!stat->lvl)
X		strcpy(stat->name,"<null>");
X	stat->status = OFF;
X	time(&ltemp);
X	stat->age += ltemp - secs;
X	update(stat,fileloc);
X	exit1();
X	/*NOTREACHED*/
X}
X
Xvoid	talk(name)				/* send message to all players */
Xreg	char	*name;
X{
XFILE	*fp;
Xchar	aline[160];
X
X	mvaddstr(5,0,"Message ? ");
X	getstring(aline,160);
X	fp = fopen(messfile,"w");
X	if (*aline)
X		fprintf(fp,"%s:  %s",name,aline);
X	fclose(fp);
X}
X
Xvoid	death(stat)				/* remove a player after dying */
Xreg	struct	stats	*stat;
X{
XFILE	*fp;
Xchar	aline[100];
Xint	ch;
Xreg	int	loop;
Xlong	ltemp;
X
X	clear();
X	if (stat->typ == 99)
X		if (stat->rng.duration)
X			{
X			addstr("Valar should be more cautious.  You've been killed.\n");
X			printw("You only have %d more chance(s).\n",--stat->rng.duration);
X			paws(3);
X			stat->nrg = stat->mxn;
X			return;
X			}
X		else
X			{
X			addstr("You had your chances, but Valar aren't totally\n");
X			addstr("immortal.  You are now left to wither and die . . .\n");
X			paws(3);
X			stat->brn = stat->lvl /25;
X			stat->nrg = stat->mxn;
X			stat->quks = stat->swd = 0;
X			stat->typ = 90;
X			return;
X			}
X	if (stat->lvl > 9999)
X		addstr("Characters greater than level 10K must be retired.  Sorry.");
X	switch(stat->rng.type)
X		{
X		case -DLREG:
X		case -NAZREG:
X			mvaddstr(4,0,"Your ring saved you from death!\n");
X			refresh();
X			stat->rng.type = NONE;
X			stat->nrg = stat->mxn/12+1;
X			stat->crn -= (stat->crn > 0);
X			return;
X		case DLBAD:
X		case -DLBAD:
X		case NAZBAD:
X		case -NAZBAD:
X		case -SPOILED:
X		case SPOILED:
X			mvaddstr(4,0,"Your ring has taken control of you and turned you into a monster!\n");
X			fp = fopen(monsterfile,"r");
X			for (loop = 0; loop <= 13; ++loop)
X				fgets(aline,100,fp);
X			ltemp = ftell(fp);
X			fclose(fp);
X			fp = fopen(monsterfile,ACCESS);
X			fseek(fp,ltemp,0);
X			fprintf(fp,"%-20s",stat->name);
X			fclose(fp);
X		}
X	initchar(stat);
X	fp = fopen(lastdead,"w");
X	fprintf(fp,"%s   Login:  %s",stat->name,stat->login);
X	fclose(fp);
X	strcpy(stat->name,"<null>");
X	update(stat,fileloc);
X	clear();
X	move(10,0);
X	switch ((int) roll(1,5))
X		{
X		case 1:
X			addstr("You've crapped out!  ");
X			break;
X		case 2:
X			addstr("You have been disemboweled.  ");
X			break;
X		case 3:
X			addstr("You've been mashed, mauled, and spit upon.  (You're dead.)\n");
X			break;
X		case 4:
X			addstr("You died!  ");
X			break;
X		case 5:
X			addstr("You're a complete failure -- you've died!!\n");
X		}
X	addstr("Care to give it another try ? ");
X	ch = rgetch();
X	if (toupper(ch) == 'Y')
X		{
X		endwin();
X		execl(gameprog,"phantasia","-s",0);
X		}
X	exit1();
X	/*NOTREACHED*/
X}
X
Xvoid	update(stat,place)			/* update charac file */
Xreg	struct	stats	*stat;
Xreg	int	place;
X{
XFILE	*fp;
X
X	fp = fopen(peoplefile,ACCESS);
X	fseek(fp,(long) place*sizeof(*stat),0);
X	fwrite((char *) stat,sizeof(*stat),1,fp);
X	fclose(fp);
X}
X
Xvoid	printplayers(stat)			/* show users */
Xreg	struct	stats	*stat;
X{
XFILE	*fp;
Xstruct	stats	buf;
Xreg	int	loop = 0;
Xdouble	loc;
Xlong	ltmp;
Xint	ch;
X
X	if (stat->blind)
X		{
X		mvaddstr(6,0,"You can't see anyone.\n");
X		return;
X		}
X	loc = circ(stat->x,stat->y);
X	mvaddstr(6,0,"Name                         X         Y       Lvl  Type  Login\n");
X	fp = fopen(peoplefile,"r");
X	while (fread((char *) &buf,sizeof(buf),1,fp))
X		{
X		if (buf.status)
X			{
X			ch = (buf.status == CLOAKED) ? '?' : 'W';
X			if (stat->typ > 10 || buf.typ > 10 || loc >= circ(buf.x,buf.y) || stat->pal)
X				if (buf.status != CLOAKED || (stat->typ == 99 && stat->pal))
X					if (buf.typ == 99)
X						addstr("The Valar is watching you. . .\n");
X					else if (buf.wormhole)
X						printw("%-20s         %c         %c    %6u  %3d   %-9s\n",
X							buf.name,ch,ch,buf.lvl,buf.typ,buf.login);
X					else
X						printw("%-20s  %8.0f  %8.0f    %6u  %3d   %-9s\n",
X							buf.name,buf.x,buf.y,buf.lvl,buf.typ,buf.login);
X				else
X					if (buf.typ == 99)
X						--loop;
X					else
X						printw("%-20s         ?         ?    %6u  %3d   %-9s\n",
X							buf.name,buf.lvl,buf.typ,buf.login);
X			++loop;
X			}
X		}
X	fclose(fp);
X	time(&ltmp);
X	printw("Total users = %d    %s\n",loop,ctime(&ltmp));
X	refresh();
X}
X
X
Xvoid	printhelp()				/* print help file */
X{
XFILE	*fp;
Xchar	instr[100];
X
X	fp = fopen(helpfile,"r");
X	while (fgets(instr,100,fp))
X		fputs(instr,stdout);
X	fclose(fp);
X}
X
Xvoid	titlestuff()				/* print out a header */
X{
XFILE	*fp;
Xchar	instr[80], hiname[21], nxtname[21], aline[80];
Xbool	cowfound = FALSE, kingfound = FALSE;
Xstruct	stats	buf;
Xdouble	hiexp, nxtexp;
Xunsigned	hilvl, nxtlvl;
Xreg	int	loop;
X
X	mvaddstr(0,15,"W e l c o m e   t o   P h a n t a s i a (vers. 3.2)!");
X	fp = fopen(motd,"r");
X	if (fgets(instr,80,fp))
X		mvaddstr(2,40 - strlen(instr)/2,instr);
X	fclose(fp);
X	fp = fopen(peoplefile,"r");
X	while (fread((char *) &buf,sizeof(buf),1,fp))
X		if (buf.typ > 10 && buf.typ < 20)
X			{
X			sprintf(instr,"The present ruler is %s  Level:%d",buf.name,buf.lvl);
X			mvaddstr(4,40 - strlen(instr)/2,instr);
X			kingfound = TRUE;
X			break;
X			}
X	if (!kingfound)
X		mvaddstr(4,24,"There is no ruler at this time.");
X	fseek(fp,0L,0);
X	while (fread((char *) &buf,sizeof(buf),1,fp))
X		if (buf.typ == 99)
X			{
X			sprintf(instr,"The Valar is %s   Login:  %s",buf.name,buf.login);
X			mvaddstr(6,40 - strlen(instr)/2,instr);
X			break;
X			}
X	fseek(fp,0L,0);
X	while (fread((char *) &buf,sizeof(buf),1,fp))
X		if (buf.typ > 20 && buf.typ < 90)
X			{
X			if (!cowfound)
X				{
X				mvaddstr(8,30,"Council of the Wise:");
X				loop = 10;
X				cowfound = TRUE;
X				}
X			/* This assumes a finite (<=7) number of C.O.W.: */
X			sprintf(instr,"%s   Login:  %s",buf.name,buf.login);
X			mvaddstr(loop++,40 - strlen(instr)/2,instr);
X			}
X	fseek(fp,0L,0);
X	*nxtname = *hiname = '\0';
X	hiexp = 0.0;
X	nxtlvl = hilvl = 0;
X	while (fread((char *) &buf,sizeof(buf),1,fp))
X		if (buf.exp > hiexp && buf.typ < 20)
X			{
X			nxtexp = hiexp;
X			hiexp = buf.exp;
X			nxtlvl = hilvl;
X			hilvl = buf.lvl;
X			strcpy(nxtname,hiname);
X			strcpy(hiname,buf.name);
X			}
X		else if (buf.exp > nxtexp && buf.typ < 20)
X			{
X			nxtexp = buf.exp;
X			nxtlvl = buf.lvl;
X			strcpy(nxtname,buf.name);
X			}
X	fclose(fp);
X	mvaddstr(17,28,"Highest characters are:");
X	sprintf(instr,"%s  Level:%d   and   %s  Level:%d",hiname,hilvl,nxtname,nxtlvl);
X	mvaddstr(19,40 - strlen(instr)/2,instr);
X	fp = fopen(lastdead,"r");
X	fgets(aline,80,fp);
X	sprintf(instr,"The last character to die is %s",aline);
X	mvaddstr(21,40 - strlen(instr)/2,instr);
X	fclose(fp);
X	refresh();
X}
X
X
X
Xvoid	printmonster()				/* do a monster list on the terminal */
X{
XFILE	*fp;
Xreg	int	count = 0;
Xchar	instr[100];
X
X	puts(" #  Name                    Str     Brains  Quick   Hits    Exp     Treas   Type    Flock%\n");
X	fp = fopen(monsterfile,"r");
X	while (fgets(instr,100,fp))
X		printf("%2d  %s",count++,instr);
X	fclose(fp);
X}
X
Xvoid	exit1() 				/* exit, but cleanup */
X{
X	move(23,0);
X	refresh();
X	nocrmode();
X	endwin();
X	exit(0);
X	/*NOTREACHED*/
X}
X
Xvoid	init1() 				/* set up for screen updating */
X{
X		/* catch/ingnore signals */
X#ifdef	BSD41
X	sigignore(SIGQUIT);
X	sigignore(SIGALRM);
X	sigignore(SIGTERM);
X	sigignore(SIGTSTP);
X	sigignore(SIGTTIN);
X	sigignore(SIGTTOU);
X	sighold(SIGINT);
X#endif
X#ifdef	BSD42
X	signal(SIGQUIT,interrupt,1);
X	signal(SIGALRM,interrupt,1);
X	signal(SIGTERM,interrupt,1);
X	signal(SIGTSTP,interrupt,1);
X	signal(SIGTTIN,interrupt,1);
X	signal(SIGTTOU,interrupt,1);
X	signal(SIGINT,interrupt,1);
X#endif
X#ifdef	USG3
X	signal(SIGINT,SIG_IGN);
X	signal(SIGQUIT,SIG_IGN);
X	signal(SIGTERM,SIG_IGN);
X	signal(SIGALRM,SIG_IGN);
X#endif
X#ifdef	USG5
X	signal(SIGINT,SIG_IGN);
X	signal(SIGQUIT,SIG_IGN);
X	signal(SIGTERM,SIG_IGN);
X	signal(SIGALRM,SIG_IGN);
X#endif
X	srand((unsigned) time((long *) NULL));	/* prime random numbers */
X	initscr();
X	noecho();
X	crmode();
X	clear();
X	refresh();
X}
X
Xvoid	getstring(cp,mx)				/* get a string from the stdscr at current y,x */
Xreg	char	*cp;
Xreg	int	mx;
X{
Xreg	int	loop = 0, x, y, xorig;
Xint	ch;
X
X	getyx(stdscr,y,xorig);
X	clrtoeol();
X	refresh();
X	while((ch = getch()) != '\n' && loop < mx - 1)
X		switch (ch)
X			{
X			case '\033':	/* escape */
X			case '\010':	/* backspace */
X				if (loop)
X					{
X					--loop;
X					getyx(stdscr,y,x);
X					mvaddch(y,x-1,' ');
X					move(y,x-1);
X					refresh();
X					}
X				break;
X			case '\030':	/* ctrl-x */
X				loop = 0;
X				move(y,xorig);
X				clrtoeol();
X				refresh();
X				break;
X			default:
X				if (ch >= ' ') /* printing char */
X					{
X					addch(ch);
X					cp[loop++] = ch;
X					refresh();
X					}
X			}
X	cp[loop] = '\0';
X}
X
X
Xvoid	showusers()				/* print a list of all characters */
X{
Xstruct	stats	buf;
XFILE	*fp;
X
X	if (fp = fopen(peoplefile,"r"))
X		{
X		puts("Current characters on file are:\n");
X		while (fread((char *) &buf,sizeof(buf),1,fp))
X			if (strcmp("<null>",buf.name))
X				printf("%-20s   Login: %-9s  Level: %6u\n",buf.name,buf.login,buf.lvl);
X		fclose(fp);
X		}
X}
X
Xvoid	kingstuff(stat) 			/* stuff upon entering throne */
Xreg	struct 	stats	*stat;
X{
XFILE	*fp;
Xstruct	stats	buf;
Xstruct	nrgvoid	vbuf;
Xreg	int	loc = 0;
X
X	if (stat->typ < 10)	/* check to see if king -- assumes crown */
X		{
X		fp = fopen(peoplefile,"r");
X		while (fread((char *) &buf,sizeof(buf),1,fp))
X			if (buf.typ > 10 && buf.typ < 20)	/* found old king */
X				if (buf.status != OFF)
X					{
X					mvaddstr(6,0,"The king is playing, so you cannot steal his throne\n");
X					stat->x = stat->y = 9;
X					move(3,0);
X					fclose(fp);
X					return;
X					}
X				else
X					{
X					buf.typ -= 10;
X					if (buf.crn)
X						--buf.crn;
X					fclose(fp);
X					update(&buf,loc);
XKING:				stat->typ = abs(stat->typ) + 10;
X					mvaddstr(6,0,"You have become king!\n");
X					fp = fopen(messfile,"w");
X					fprintf(fp,"All hail the new king!");
X					fclose(fp);
X					/* clear all energy voids */
X					fp = fopen(voidfile,"r");
X					fread((char *) &vbuf,sizeof(vbuf),1,fp);
X					fclose(fp);
X					fp = fopen(voidfile,"w");
X					fwrite((char *) &vbuf,sizeof(vbuf),1,fp);
X					fclose(fp);
X					goto EXIT;
X					}
X			else
X				++loc;
X		fclose(fp);	  /* old king not found -- install new one */
X		goto KING;
X		}
XEXIT:	mvaddstr(3,0,"0:Decree  ");
X}
X
Xvoid	paws(where)				/* wait for input to continue */
Xint	where;
X{
X	mvaddstr(where,0,"-- more --");
X	rgetch();
X}
X
Xvoid	cstat() 				/* examine/change stats of a character */
X{
Xstruct	stats charac;
Xchar	s[60], flag[2];
XFILE	*fp;
Xreg	int	loc = 0;
Xint	c, temp, today;
Xlong	ltemp;
Xdouble	dtemp;
X
X	flag[0] = 'F';	flag[1] = 'T';
X	mvaddstr(10,0,"Which character do you want to look at ? ");
X	getstring(s,60);
X	if (fp = fopen(peoplefile,"r"))
X		while (fread((char *) &charac,sizeof(charac),1,fp))
X			if (!strcmp(s,charac.name))
X				goto FOUND;
X			else
X				++loc;
X	mvaddstr(11,0,"Not found.");
X	exit1();
X	/*NOTREACHED*/
X
XFOUND:	fclose(fp);
X	time(&ltemp);
X	today = localtime(&ltemp)->tm_yday;
X	if (!su)
X		strcpy(charac.pswd,"XXXXXXXX");
X	clear();
XTOP:	mvprintw(0,0,"a:Name         %s\n",charac.name);
X	printw("b:Password     %s\n",charac.pswd);
X	printw(" :Login        %s\n",charac.login);
X	temp = today - charac.lastused;
X	if (temp < 0)
X		temp += 365;
X	printw("c:Used         %d\n",temp);
X	mvprintw(5,0,"d:Experience   %.0f\n",charac.exp);
X	printw("e:Level        %d\n",charac.lvl);
X	printw("f:Strength     %.0f\n",charac.str);
X	printw("g:Sword        %.0f\n",charac.swd);
X	printw("h:Quickness    %d\n",charac.quk);
X	printw("i:Quikslvr     %d\n",charac.quks);
X	printw("j:Energy       %.0f\n",charac.nrg);
X	printw("k:Max-Nrg      %.0f\n",charac.mxn);
X	printw("l:Shield       %.0f\n",charac.shd);
X	printw("m:Magic        %.0f\n",charac.mag);
X	printw("n:Manna        %.0f\n",charac.man);
X	printw("o:Brains       %.0f\n",charac.brn);
X	mvprintw(0,40,"p:X-coord      %.0f\n",charac.x);
X	mvprintw(1,40,"q:Y-coord      %.0f\n",charac.y);
X	if (su)
X		mvprintw(2,40,"r:Wormhole     %d\n",charac.wormhole);
X	else
X		mvprintw(2,40,"r:Wormhole     %c\n",flag[charac.wormhole != 0]);
X	mvprintw(3,40,"s:Type         %d\n",charac.typ);
X	mvprintw(5,40,"t:Sin          %0.3f\n",charac.sin);
X	mvprintw(6,40,"u:Poison       %0.3f\n",charac.psn);
X	mvprintw(7,40,"v:Gold         %.0f\n",charac.gld);
X	mvprintw(8,40,"w:Gem          %.0f\n",charac.gem);
X	mvprintw(9,40,"x:Holy Water   %d\n",charac.hw);
X	mvprintw(10,40,"y:Charms       %d\n",charac.chm);
X	mvprintw(11,40,"z:Crowns       %d\n",charac.crn);
X	mvprintw(12,40,"1:Amulets      %d\n",charac.amu);
X	mvprintw(13,40,"2:Age          %d\n",charac.age);
X	mvprintw(18,5,"3:Virgin %c  4:Blessed %c  5:Ring %c  6:Blind %c  7:Palantir %c",
X		flag[charac.vrg],flag[charac.bls],flag[charac.rng.type != 0],flag[charac.blind],flag[charac.pal]);
X	if (!su)
X		exit1();
X	mvaddstr(15,40,"!:Quit");
X	mvaddstr(16,40,"?:Delete");
X	mvaddstr(19,30,"8:Duration");
X	mvaddstr(21,0,"What would you like to change? ");
X	c = rgetch();
X	switch(c)
X		{
X		case 'p':	/* change x coord */
X			mvprintw(23,0,"x = %f; x = ",charac.x);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.x = dtemp;
X			break;
X		case 'q':	/* change y coord */
X			mvprintw(23,0,"y = %f; y = ",charac.y);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.y = dtemp;
X			break;
X		case 'd':	/* change Experience */
X			mvprintw(23,0,"exp = %f; exp = ",charac.exp);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.exp = dtemp;
X			break;
X		case 'e':	/* change level */
X			mvprintw(23,0,"lvl = %d; lvl;= ",charac.lvl);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.lvl = dtemp;
X			break;
X		case 'h':	/* change quickness */
X			mvprintw(23,0,"quk = %d; quk;= ",charac.quk);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.quk = dtemp;
X			break;
X		case 'f':	/* change strength */
X			mvprintw(23,0,"str = %f; str;= ",charac.str);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.str = dtemp;
X			break;
X		case 't':	/* change Sin */
X			mvprintw(23,0,"sin = %f; sin;= ",charac.sin);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.sin = dtemp;
X			break;
X		case 'n':	/* change manna */
X			mvprintw(23,0,"man = %f; man;= ",charac.man);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.man = dtemp;
X			break;
X		case 'v':	/* change gold */
X			mvprintw(23,0,"gld = %f; gld;= ",charac.gld);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.gld = dtemp;
X			break;
X		case 'j':	/* change energy */
X			mvprintw(23,0,"nrg = %f; nrg;= ",charac.nrg);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.nrg = dtemp;
X			break;
X		case 'k':	/* change Maximum energy */
X			mvprintw(23,0,"mxn = %f; mxn;= ",charac.mxn);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.mxn = dtemp;
X			break;
X		case 'm':	/* change magic */
X			mvprintw(23,0,"mag = %f; mag;= ",charac.mag);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.mag = dtemp;
X			break;
X		case 'o':	/* change brains */
X			mvprintw(23,0,"brn = %f; brn;= ",charac.brn);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.brn = dtemp;
X			break;
X		case 'z':	/* change crowns */
X			mvprintw(23,0,"crn = %d; crn;= ",charac.crn);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.crn = dtemp;
X			break;
X		case '5':	/* change ring type */
X			mvprintw(23,0,"rng-type = %d; rng-type;= ",charac.rng.type);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.rng.type = dtemp;
X			break;
X		case '8':	/* change ring duration */
X			mvprintw(23,0,"rng-duration = %d; rng-duration;= ",charac.rng.duration);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.rng.duration = dtemp;
X			break;
X		case '7':	/* change palantir */
X			mvprintw(23,0,"pal = %d; pal;= ",charac.pal);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				{
X				charac.pal = dtemp;
X				charac.pal = (charac.pal != 0);
X				}
X			break;
X		case 'u':	/* change poison */
X			mvprintw(23,0,"psn = %f; psn;= ",charac.psn);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.psn = dtemp;
X			break;
X		case 'x':	/* change holy water */
X			mvprintw(23,0,"hw = %d; hw;= ",charac.hw);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.hw = dtemp;
X			break;
X		case '1':	/* change amulet */
X			mvprintw(23,0,"amu = %d; amu;= ",charac.amu);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.amu = dtemp;
X			break;
X		case '4':	/* change Blessing */
X			mvprintw(23,0,"bls = %d; bls;= ",charac.bls);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				{
X				charac.bls = dtemp;
X				charac.bls = (charac.bls != 0);
X				}
X			break;
X		case 'y':	/* change Charm */
X			mvprintw(23,0,"chm = %d; chm;= ",charac.chm);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.chm = dtemp;
X			break;
X		case 'w':	/* change Gems */
X			mvprintw(23,0,"gem = %f; gem;= ",charac.gem);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.gem = dtemp;
X			break;
X		case 'i':	/* change Quicksilver */
X			mvprintw(23,0,"quks = %d; quks;= ",charac.quks);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.quks = dtemp;
X			break;
X		case 'g':	/* change swords */
X			mvprintw(23,0,"swd = %f; swd;= ",charac.swd);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.swd = dtemp;
X			break;
X		case 'l':	/* change shields */
X			mvprintw(23,0,"shd = %f; shd;= ",charac.shd);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.shd = dtemp;
X			break;
X		case 's':	/* change type */
X			mvprintw(23,0,"typ = %d; typ;= ",charac.typ);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.typ = dtemp;
X			break;
X		case '3':	/* change virgin */
X			mvprintw(23,0,"vrg = %d; vrg;= ",charac.vrg);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				{
X				charac.vrg = dtemp;
X				charac.vrg = (charac.vrg != 0);
X				}
X			break;
X		case 'c':	/* change last-used */
X			mvprintw(23,0,"last-used = %d; last-used;= ",charac.lastused);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.lastused = dtemp;
X			break;
X		case 'b':		/* change password */
X			mvaddstr(23,0,"New password: ");
X			getstring(s,60);
X			if (*s)
X				strcpy(charac.pswd,s);
X			break;
X		case 'a':		/* change name */
X			mvaddstr(23,0,"New name: ");
X			getstring(s,60);
X			if (*s)
X				strcpy(charac.name,s);
X			break;
X		case 'r':	/* change wormhole */
X			mvprintw(23,0,"wormhole = %d; wormhole;= ",charac.wormhole);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.wormhole = dtemp;
X			break;
X		case '2':	/* change age */
X			mvprintw(23,0,"age = %d; age;= ",charac.age);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				charac.age = dtemp;
X			break;
X		case '6':	/* change blindness */
X			mvprintw(23,0,"blind = %d; blind;= ",charac.blind);
X			dtemp = inflt();
X			if (dtemp != 0.0)
X				{
X				charac.blind = dtemp;
X				charac.blind = (charac.blind != 0);
X				}
X			break;
X		case '!':	/* quit, update */
X			goto LEAVE;
X		case '?':	/* delete char */
X			strcpy(charac.name,"<null>");
X			initchar(&charac);
X			goto LEAVE;
X		}
X	goto TOP;
XLEAVE:	charac.status = OFF;
X	update(&charac,loc);
X}
X
Xunsigned level(expr)			/* calculate level */
Xdouble	expr;
X{
X	if (expr < 1.1e+7)
X		return (pow((expr/1000.0), 0.4875));
X	else
X		return (pow((expr/1250.0), 0.4865));
X}
X
Xvoid	trunc(str)				/* remove blank spaces at the end of str[] */
Xreg	char	*str;
X{
Xreg	int	loop;
X	loop = strlen(str) - 1;
X	while (str[--loop] == ' ')
X		str[loop] = '\0';
X}
X
Xdouble	inflt()				/* get a floating point # from the terminal */
X{
Xchar	aline[80];
Xdouble	res;
X	getstring(aline,80);
X	if (sscanf(aline,"%F",&res) < 1)
X		res = 0;
X	return (res);
X}
X
Xvoid	checkmov(stat)				/* see if beyond PONR */
Xreg	struct	stats	*stat;
X{
X	if (beyond)
X		{
X		stat->x = sgn(stat->x) * max(abs(stat->x),1.1e+6);
X		stat->y = sgn(stat->y) * max(abs(stat->y),1.1e+6);
X		}
X}
Xvoid	scramble(stat)			/* mix up some stats */
Xreg	struct	stats	*stat;
X{
Xdouble	buf[5],	temp;
Xreg	int	first, second;
Xreg	double	*bp;
X
X	bp = buf;
X	*bp++ = stat->str;
X	*bp++ = stat->man;
X	*bp++ = stat->brn;
X	*bp++ = stat->mag;
X	*bp++ = stat->nrg;
X
X	bp = buf;
X	first = roll(0,5);
X	second = roll(0,5);
X	temp = bp[first];
X	bp[first] = bp[second];
X	bp[second] = temp;
X
X	stat->str = *bp++;
X	stat->man = *bp++;
X	stat->brn = *bp++;
X	stat->mag = *bp++;
X	stat->nrg = *bp++;
X}
!EOR!
echo extracting - func2.c
sed 's/^X//' > func2.c << '!EOR!'
X/*
X * func2.c	Phantasia support routines
X */
X
X#include "phant.h"
X
Xvoid	decree(stat)				/* king and valar stuff */
Xreg	struct	stats	*stat;
X{
XFILE	*fp;
Xshort	arg;
Xchar	aline[80], *cp;
Xstruct	stats	sbuf;
Xstruct	nrgvoid	vbuf;
Xdouble	temp1 = 0.0, temp2 = 0.0;
Xint	ch;
Xreg	int	loc = 0;
X
X	move(3,0);
X	clrtoeol();
X	if (stat->typ < 20 && !su)	/* king */
X		{
X		addstr("1:Transport  2:Curse  3:Energy Void  4:Bestow  5:Collect Taxes  ");
X		ch = rgetch();
X		move(3,0);
X		clrtoeol();
X		switch (ch)
X			{
X			case '1':
X				arg = TRANSPORT;
X				cp = "transport";
X				break;
X			case '2':
X				arg = CURSED;
X				cp = "curse";
X				break;
X			case '3':
X				addstr("Enter the X Y coordinates of void ? ");
X				getstring(aline,30);
X				sscanf(aline,"%F %F",&temp1,&temp2);
X				vbuf.x = floor(temp1);
X				vbuf.y = floor(temp2);
X				vbuf.active = TRUE;
X				voidupdate(&vbuf,allocvoid());
X				goto EXIT;
X			case '4':
X				arg = GOLD;
X				addstr("How much gold to bestow ? ");
X				temp1 = inflt();
X				if (temp1 > stat->gld || temp1 < 0)
X					{
X					mvaddstr(6,0,"You don't have that !\n");
X					return;
X					}
X				stat->gld -= floor(temp1);
X				cp = "give gold to";
X				break;
X			case '5':
X				fp = fopen(goldfile,"r");
X				fread((char *) &temp1,sizeof(double),1,fp);
X				fclose(fp);
X				mvprintw(6,0,"You have collected %.0f in gold.\n",temp1);
X				stat->gld += floor(temp1);
X				fp = fopen(goldfile,"w");
X				temp1 = 0.0;
X				fwrite((char *) &temp1,sizeof(double),1,fp);
X				fclose(fp);
X				return;
X			default:
X				return;
X			}
X		}
X	else	/* council of wise, valar, etc. */
X		{
X		addstr("1:Heal  ");
X		if (stat->pal || su)
X			addstr("2:Seek Grail  ");
X		if (stat->typ == 99 || su)
X			addstr("3:Throw Monster  4:Relocate  5:Bless  ");
X		if (su)
X			addstr("6:Vaporize  ");
X		ch = rgetch();
X		if (!su && ch > '2' && stat->typ != 99)
X			{
X			illcmd();
X			return;
X			}
X		switch (ch)
X			{
X			case '1':
X				arg = HEAL;
X				cp = "heal";
X				break;
X			case '2':
X				if (stat->pal)
X					{
X					fp = fopen(voidfile,"r");
X					fread((char *) &vbuf,sizeof(vbuf),1,fp);
X					fclose(fp);
X					temp1 = hypot(stat->x - vbuf.x,stat->y - vbuf.y);
X					temp1 = floor(temp1 + roll(-temp1/10.0,temp1/5.0));
X					mvprintw(6,0,"The palantir says the Grail is about %.0f away.\n",temp1);
X					return;
X					}
X				else
X					{
X					mvaddstr(6,0,"You need a palantir to seek the Grail.\n");
X					return;
X					}
X			case '3':
X				mvaddstr(3,0,"Which monster [0-99] ? ");
X				temp1 = inflt();
X				temp1 = max(0,min(99,temp1));
X				cp = "throw a monster at";
X				arg = MONSTER;
X				break;
X			case '4':
X				mvaddstr(3,0,"New X Y coordinates ? ");
X				getstring(aline,30);
X				sscanf(aline,"%F %F",&temp1,&temp2);
X				cp = "relocate";
X				arg = MOVED;
X				break;
X			case '5':
X				arg = BLESS;
X				cp = "bless";
X				break;
X			case '6':
X				if (su)
X					{
X					cp = "vaporize";
X					arg = VAPORIZED;
X					break;
X					}
X			default:
X				return;
X			}
X		}
X	mvprintw(3,0,"Who do you want to %s ? ",cp);
X	getstring(aline,21);
X	trunc(aline);
X	if (strcmp(stat->name,aline))
X		{
X		fp = fopen(peoplefile,"r");
X		while (fread((char *) &sbuf,sizeof(sbuf),1,fp))
X			if (strcmp(aline,sbuf.name))
X				++loc;
X			else
X				{
X				fclose(fp);
X				if (sbuf.tampered)
X					{
X					mvaddstr(6,0,"That person has something pending already.\n");
X					return;
X					}
X				else
X					{
X					sbuf.tampered = arg;
X					sbuf.scratch1 = floor(temp1);
X					sbuf.scratch2 = floor(temp2);
X					update(&sbuf,loc);
XEXIT:					mvaddstr(6,0,"It is done.\n");
X					return;
X					}
X				}
X		fclose(fp);
X		mvaddstr(6,0,"There is no one by that name.\n");
X		}
X	else
X		mvaddstr(6,0,"You may not do it to yourself!\n");
X}
X
Xvoid	checktampered(stat)			/* see if decree'd etc. */
Xreg	struct	stats	*stat;
X{
Xstruct	nrgvoid	vbuf;
Xstruct	stats sbuf;
XFILE	*fp;
Xreg	int	loc = 0;
X
X	/* first check for energy voids */
X	fp = fopen(voidfile,"r");
X	while (fread((char *) &vbuf,sizeof(vbuf),1,fp))
X		if (vbuf.active && vbuf.x == stat->x && vbuf.y == stat->y)
X			{
X			fclose(fp);
X			if (loc)
X				{
X				vbuf.active = FALSE;
X				voidupdate(&vbuf,loc);
X				tampered(stat,NRGVOID,&sbuf);
X				}
X			else if (stat->status != CLOAKED)
X				tampered(stat,GRAIL,&sbuf);
X			break;
X			}
X		else
X			++loc;
X	fclose(fp);
X	/* now check for other things */
X	statread(&sbuf,fileloc);
X	if (sbuf.tampered)
X		tampered(stat,sbuf.tampered,&sbuf);
X}
X
Xvoid	voidupdate(vp,loc)			/* update an energy void */
Xreg	struct nrgvoid	*vp;
Xreg	int	loc;
X{
XFILE	*fp;
X
X	fp = fopen(voidfile,ACCESS);
X	fseek(fp,(long) loc*sizeof(*vp),0);
X	fwrite((char *) vp,sizeof(*vp),1,fp);
X	fclose(fp);
X}
X
Xint	allocvoid()				/* find a space to put an energy void */
X{
XFILE	*fp;
Xreg	int	loc = 0;
Xstruct	nrgvoid	vbuf;
X
X	fp = fopen(voidfile,"r");
X	while (fread((char *) &vbuf,sizeof(vbuf),1,fp))
X		if (vbuf.active)
X			++loc;
X		else
X			{
X			fclose(fp);
X			return (loc);
X			}
X	fclose(fp);
X	return (loc);
X}
X
Xvoid	statread(stat,loc)			/* read a charac. structure */
Xreg	struct	stats	*stat;
Xreg	int	loc;
X{
XFILE	*fp;
X
X	fp = fopen(peoplefile,"r");
X	fseek(fp,(long) loc * sizeof(*stat),0);
X	fread((char *) stat,sizeof(*stat),1,fp);
X	fclose(fp);
X}
X
Xvoid	tampered(stat,what,bufp)			/* decree'd, intervened, etc. */
Xreg	struct	stats	*stat, *bufp;
Xshort	what;
X{
Xstruct	nrgvoid	vbuf;
Xreg	int	loc;
Xstruct	stats	sbuf;
XFILE	*fp;
X
X	changed = TRUE;
X	move(6,0);
X	stat->tampered = OFF;
X	switch ((int) what)
X		{
X		case NRGVOID:
X			addstr("You've hit an energy void !\n");
X			stat->man /= 3;
X			stat->nrg /= 2;
X			stat->gld = floor(stat->gld/1.25) + 0.1;
X			stat->x += 10;
X			break;
X		case TRANSPORT:
X			addstr("The king transported you !  ");
X			if (stat->chm)
X				{
X				addstr("But your charm save you. . .\n");
X				--stat->chm;
X				}
X			else
X				{
X				stat->x += roll(-50,100) * circ(stat->x,stat->y);
X				stat->y += roll(-50,100) * circ(stat->x,stat->y);
X				addch('\n');
X				}
X			break;
X		case GOLD:
X			printw("The king has bestowed %.0f gold pieces on you !\n",bufp->scratch1);
X			stat->gld += bufp->scratch1;
X			break;
X		case CURSED:
X			addstr("You've been cursed !  ");
X			if (stat->bls)
X				{
X				addstr("But your blessing saved you. . .\n");
X				stat->bls = FALSE;
X				}
X			else
X				{
X				addch('\n');
X				stat->psn += 2;
X				stat->nrg = 10;
X				stat->mxn  *= 0.95;
X				stat->status = PLAYING;
X				}
X			break;
X		case VAPORIZED:
X			addstr("Woops!  You've been vaporized!\n");
X			death(stat);
X			break;
X		case MONSTER:
X			addstr("The Valar zapped you with a monster!\n");
X			paws(7);
X			fight(stat,(int) bufp->scratch1);
X			return;
X		case BLESS:
X			addstr("The Valar has blessed you!\n");
X			stat->nrg = (stat->mxn *= 1.05) + stat->shd;
X			stat->man += 500;
X			stat->str += 0.5;
X			stat->brn += 0.5;
X			stat->mag += 0.5;
X			stat->psn = min(0.5,stat->psn);
X			break;
X		case MOVED:
X			addstr("You've been relocated. . .\n");
X			stat->x = bufp->scratch1;
X			stat->y = bufp->scratch2;
X			break;
X		case HEAL:
X			addstr("You've been healed!\n");
X			stat->psn -=  0.25;
X			stat->nrg = stat->mxn + stat->shd;
X			break;
X		case STOLEN:
X			addstr("You'Ve been bumped off as Valar!\n");
X			stat->typ = 20 + roll(1,6);
X			break;
X		case GRAIL:
X			addstr("You have found The Holy Grail!!\n");
X			if (stat->typ < 20)
X				{
X				addstr("However, you are not experienced enough to behold it.\n");
X				stat->sin *= stat->sin;
X				stat->man +=  1000;
X				}
X			else if (stat->typ == 99 || stat->typ == 90)
X				{
X				addstr("You have made it to the position of Valar once already.\n");
X				addstr("The Grail is of no more use to you now.\n");
X				}
X			else
X				{
X				addstr("It is now time to see if you are worthy to behold it. . .\n");
X				refresh();
X				sleep(4);
X				if (rnd() / 2.0 < stat->sin)
X					{
X					addstr("You blew this one!\n");
X					stat->str = stat->man = stat->quk = stat->nrg = stat->mxn = stat->x = stat->y = 
X						stat->mag = stat->brn = stat->exp =1;
X					stat->lvl = 0;
X					}
X				else
X					{
X					addstr("You made to position of Valar!\n");
X					stat->typ = 99;
X					fp = fopen(peoplefile,"r");
X					loc = 0;
X					while (fread((char *) &sbuf,sizeof(sbuf),1,fp))
X						if (sbuf.typ == 99)
X							{
X							sbuf.tampered = STOLEN;
X							update(&sbuf,loc);
X							break;
X							}
X						else
X							++loc;
X					fclose(fp);
X					}
X				}
X			vbuf.active = TRUE;
X			vbuf.x = roll(-1e6,2e6);
X			vbuf.y = roll(-1e6,2e6);
X			voidupdate(&vbuf,0);
X			break;
X		}
X}
X
Xvoid	adjuststats(stat)				/* make sure things are within limits, etc. */
Xreg	struct	stats	*stat;
X{
Xlong	ltemp;
Xreg	int	temp;
X	stat->x = floor(stat->x);
X	stat->y = floor(stat->y);
X	valhala = (stat->typ == 99);
X	throne = (stat->x == 0.0 && stat->y == 0.0);
X	temp = abs(stat->x)/400;
X	if (temp > 16)
X		temp = 0;
X	if (stat->y == 0.0 && !throne && !valhala && temp == abs(stat->x)/400 && sgn(stat->x) == (int) pow(-1.0, (double) temp))
X		{
X		if (!wmhl)
X			stat->wormhole = temp;
X		wmhl = TRUE;
X		}
X	else
X		wmhl = FALSE;
X	speed = stat->quk + stat->quks - spdcalc(stat->lvl,stat->gld,stat->gem);
X	strength = stat->str + stat->swd - strcalc(stat->str,stat->psn);
X	time(&ltemp);
X	stat->age += ltemp - secs;
X	secs = ltemp;
X	stat->quks = min(99,stat->quks);
X	stat->man = min(stat->man,stat->lvl*15 + 5000);
X	stat->chm = min(stat->chm,stat->lvl + 10);
X	stat->typ = (stat->crn && stat->typ < 10) ? -abs(stat->typ) : abs(stat->typ);
X	if (level(stat->exp) > stat->lvl)
X		movelvl(stat);
X	stat->gld = floor(stat->gld) + 0.1;
X	stat->gem = floor(stat->gem) + 0.1;
X	if (stat->rng.type)
X		stat->nrg = stat->mxn + stat->shd;
X	if (stat->rng.type && stat->rng.duration <= 0)	/* clean up rings */
X		switch (stat->rng.type)
X			{
X			case DLBAD:
X			case NAZBAD:
X				stat->rng.type = SPOILED;
X				stat->rng.duration = roll(10,25);
X				break;
X			case NAZREG:
X				stat->rng.type = NONE;
X				break;
X			case SPOILED:
X				death(stat);
X				break;
X			}	/* DLREG is ok, so do nothing with it */
X	stat->nrg += (stat->mxn+stat->shd)/15+stat->lvl/3+2;
X	stat->nrg = min(stat->nrg,stat->mxn + stat->shd);
X	if (stat->age > stat->degen * 2500)
X		{
X		++stat->degen;
X		if (stat->quk > 23)
X			--stat->quk;
X		stat->str *= 0.97;
X		stat->brn *= 0.95;
X		stat->mag *= 0.97;
X		stat->mxn *= 0.95;
X		if (stat->quks)
X			--stat->quks;
X		stat->swd *= 0.93;
X		stat->shd *= 0.95;
X		}
X}
X
Xvoid	checkinterm(stat)				/* see if other person on same x,y */
Xreg	struct	stats	*stat;
X{
XFILE	*fp;
Xstruct	stats	sbuf;
Xreg	int	foeloc = 0;
X
X	users = 0;
X	fp = fopen(peoplefile,"r");
X	while (fread((char *) &sbuf,sizeof(sbuf),1,fp))
X		{
X		if (sbuf.status && (sbuf.status != CLOAKED || sbuf.typ != 99))
X			{
X			++users;
X			if (stat->x == sbuf.x && stat->y == sbuf.y
X			   && foeloc != fileloc && sbuf.typ != 99
X			   && stat->typ !=99 && !stat->wormhole && !sbuf.wormhole)
X				{
X				fclose(fp);
X				interm(stat,foeloc);
X				return;
X				}
X			}
X		++foeloc;
X		}
X	fclose(fp);
X}
X
Xint	gch(rngtyp)			/* get a character from terminal, but check ring if crazy */
Xshort	rngtyp;
X{
X	refresh();
X	if (abs(rngtyp) != SPOILED)
X		return (getch());
X	else
X		{
X		getch();
X		return (roll(0,5) + '0');
X		}
X}
X
Xint	rngcalc(chartyp)				/* pick a duration of a ring */
Xshort	chartyp;
X{
Xstatic	int	rngtab[] = { 0, 10, 20, 13, 25, 40, 20};
X
X	if (chartyp > 10)
X		chartyp -= 10;
X	return (rngtab[chartyp - 1]);
X}
X
Xvoid	interm(stat,who)				/* interterminal battle routine */
Xreg	struct	stats	*stat;
Xint	who;
X{
X#define	MAXWAIT	20
X#define	BLOCK	sizeof(struct stats)
X#define	RAN	1
X#define	STUCK	2
X#define	BLEWIT	3
X#define	KILLED	4
X#define readfoe()	fseek(fin,foeplace,0);  \
X			fread((char *) foe,BLOCK,1,fin)
X#define updateme()	fseek(fout,myplace,0);  \
X			fwrite((char *) stat,BLOCK,1,fout);  \
X			fflush(fout)
X
XFILE	*fin, *fout;	/* pointers for input, output */
Xdouble	temp, foespeed, oldhits = 0.0, myhits;
Xstruct	stats	sbuf;
Xreg	struct	stats *foe;
Xreg	int	loop, lines = 5;
Xint	ch;
Xlong	myplace, foeplace;
Xshort	oldtags;
Xbool	luckout = FALSE;
Xchar	foename[21];
X
X	fghting = TRUE;
X	mvaddstr(4,0,"Preparing for battle!\n");
X	refresh();
X		/* set up variables, file, etc. */
X	myplace = fileloc * BLOCK;
X	foeplace = who * BLOCK;
X	fin = fopen(peoplefile,"r");
X	setbuf(fin, (char *) NULL);
X	fout = fopen(peoplefile,ACCESS);
X	stat->status = INBATTLE;
X	myhits = stat->nrg;
X	stat->tampered = oldtags = 1;	/* this must be non-zero to prevent a king or valar from trashing it */
X	stat->scratch1 = stat->scratch2 = 0.0;
X	updateme();
X	foe = &sbuf;
X	readfoe();
X	foespeed = foe->quk + foe->quks - spdcalc(foe->lvl,foe->gld,foe->gem);
X	if (abs(stat->lvl - foe->lvl) > 20)		/* see if greatly mismatched */
X		{
X		temp = ((double) (stat->lvl - foe->lvl))/((double) max(stat->lvl,foe->lvl));
X		if (temp > 0.5)		/* this one outweighs his/her foe */
X			foespeed *= 2.0;
X		else if (temp < -0.5)	/* foe outweighs this one */
X			speed *= 2.0;
X		}
X	if (stat->blind)
X		strcpy(foename,"someone");
X	else
X		strcpy(foename,foe->name);
X	mvprintw(3,0,"You have encountered %s   Level: %d\n",foename,foe->lvl);
X	refresh();
X		/* now wait for foe to respond */
X	for (loop = 1.5*MAXWAIT; foe->status != INBATTLE && loop; --loop)
X		{
X		readfoe();
X		sleep(1);
X		}
X	if (foe->status != INBATTLE)
X		{
X		mvprintw(4,0,"%s is not responding.\n",foename);
X		goto LEAVE;
X		}
X
X	/* otherwise, everything is set to go */
X	move(4,0);
X	clrtoeol();
X		/* check to see who goes first */
X	if (speed > foespeed)
X		goto HITFOE;
X	else if (foespeed > speed)
X		goto WAIT;
X	else if (stat->lvl > foe->lvl)
X		goto HITFOE;
X	else if (foe->lvl > stat->lvl)
X		goto WAIT;
X	else	/* no one is faster */
X		{
X		printw("You can't fight %s yet.",foename);
X		goto LEAVE;
X		}
X
X/* routine to hit, etc */
XHITFOE:	printstats(stat);
X	mvprintw(1,26,"%20.0f",myhits);
X	mvaddstr(4,0,"1:Fight  2:Run Away!  3:Power Blast  ");
X	if (luckout)
X		clrtoeol();
X	else
X		addstr("4:Luckout  ");
X	ch = gch(stat->rng.type);
X	move(lines = 5,0);
X	clrtobot();
X	switch (ch)
X		{
X		default:	/* fight */
X			temp = roll(2,strength);
XHIT:			mvprintw(lines++,0,"You hit %s %.0f times!",foename,temp);
X			stat->sin += 0.5;
X			stat->scratch1 += temp;
X			stat->scratch2 = FALSE;
X			break;
X		case '2':	/* run away */
X			--stat->scratch1;	/* this value changes to indicate action */
X			if (rnd() > 0.25)
X				{
X				mvaddstr(lines++,0,"You got away!");
X				stat->scratch2 = RAN;
X				goto LEAVE;
X				}
X			mvprintw(lines++,0,"%s is still after you!",foename);
X			stat->scratch2 = STUCK;
X			break;
X		case '3':	/* power blast */
X			temp = min(stat->man,stat->lvl*5);
X			stat->man -= temp;
X			temp = (rnd() + 0.5) * temp * stat->mag * 0.2 + 2;
X			mvprintw(lines++,0,"You blasted %s !",foename);
X			goto HIT;
X		case '4':	/* luckout */
X			if (luckout || rnd() > 0.1)
X				{
X				luckout = TRUE;
X				mvaddstr(lines++,0,"Not this time...");
X				--stat->scratch1;
X				stat->scratch2 = BLEWIT;
X				}
X			else
X				{
X				mvaddstr(lines++,0,"You just lucked out!");
X				stat->scratch1 = foe->nrg + 5;
X				}
X			break;
X		}
X	refresh();
X	stat->scratch1 = floor(stat->scratch1);		/* clean up any mess */
X	if (stat->scratch1 > foe->nrg)
X		stat->scratch2 = KILLED;
X	else if (rnd() * speed < rnd() * foespeed)
X		{		/* foe's turn */
X		++stat->tampered;
X		updateme();
X		goto WAIT;
X		}
X	updateme();
X
X	if (((int) stat->scratch2) == KILLED)
X		{
X		mvprintw(lines++,0,"You killed %s!",foename);
X		stat->exp += foe->exp;
X		stat->crn += (stat->lvl < 1000) ? foe->crn : 0;
X		stat->amu += foe->amu;
X		stat->chm += foe->chm;
X		stat->gld += foe->gld;
X		stat->gem += foe->gem;
X		stat->swd = max(stat->swd,foe->swd);
X		stat->shd = max(stat->shd,foe->shd);
X		stat->quks = max(stat->quks,foe->quks);
X		sleep(3);	  /* give other person time to die */
X		goto LEAVE;
X		}
X	goto HITFOE;	/* otherwise, my turn again */
X
X/* routine to wait for foe to do something */
XWAIT:	printstats(stat);
X	mvprintw(1,26,"%20.0f",myhits);
X	mvaddstr(4,0,"Waiting...\n");
X	refresh();
X	for (loop = MAXWAIT; loop; --loop)
X		{
X		readfoe();
X		if (foe->scratch1 != oldhits)
X			switch ((int) foe->scratch2)
X				{
X				case RAN:
X					mvprintw(lines++,0,"%s ran away!",foename);
X					goto LEAVE;
X				case STUCK:
X					mvprintw(lines++,0,"%s tried to run away.",foename);
X					goto BOT;
X				case BLEWIT:
X					mvprintw(lines++,0,"%s tried to luckout!",foename);
X					goto BOT;
X				default:
X					temp = foe->scratch1 - oldhits;
X					mvprintw(lines++,0,"%s hit you %.0f times!",foename,temp);
X					myhits -= temp;
X					goto BOT;
X				}
X		sleep(1);
X		}
X	/* timeout */
X	mvaddstr(23,0,"Timeout: waiting for response.  Do you want to wait ? ");
X	refresh();
X	ch = getch();
X	move(23,0);
X	clrtoeol();
X	if (toupper(ch) == 'Y')
X		goto WAIT;
X	goto LEAVE;
X
X/* routine to decide what happens next */
XBOT:	refresh();
X	if (lines > 21)
X		{
X		paws(lines);
X		move(lines = 5,0);
X		clrtobot();
X		}
X	if (((int) foe->scratch2) == KILLED || myhits < 0.0)
X		{
X		myhits = -2;
X		goto LEAVE;		/* main will pick up death */
X		}
X	oldhits = foe->scratch1;
X	if (foe->tampered != oldtags)
X		{
X		oldtags = foe->tampered;
X		goto HITFOE;
X		}
X	goto WAIT;
X
X/* routine to clean up things and leave */
XLEAVE:	updateme();
X	fclose(fin);
X	fclose(fout);
X	stat->x += roll(5,-10);
X	stat->y += roll(5,-10);
X	stat->nrg = myhits;
X	stat->tampered = OFF;
X	stat->status = PLAYING;
X	changed = TRUE;
X	paws(lines);
X	move(3,0);
X	clrtobot();
X}
X
Xint	interrupt()				/* call when break key is hit */
X{
Xchar	line[81];
Xreg	int	loop;
Xint	x, y, ch;
X
X#ifdef USG3
X	signal(SIGINT,SIG_IGN);
X#endif
X#ifdef USG5
X	signal(SIGINT,SIG_IGN);
X#endif
X	getyx(stdscr,y,x);
X	for (loop = 79; loop >= 0; --loop)	/* snarf line */
X		{
X		move(4,loop);
X		line[loop] = inch();
X		}
X	line[80] = '\0';
X	clrtoeol();
X	if (fghting)
X		{
X		move(4,0);
X		clrtoeol();
X		addstr("Quitting now will automatically kill your character.  Still want to ? ");
X		ch = rgetch();
X		if (toupper(ch) == 'Y')
X			longjmp(mainenv,DIE);
X		}
X	else
X		{
X		move(4,0);
X		clrtoeol();
X		addstr("Do you really want to quit ? ");
X		ch = rgetch();
X		if (toupper(ch) == 'Y')
X			longjmp(mainenv,QUIT);
X		}
X	mvaddstr(4,0,line);	/* return screen to previous state */
X	move(y,x);
X	refresh();
X#ifdef USG3
X	signal(SIGINT,interrupt);
X#endif
X#ifdef USG5
X	signal(SIGINT,interrupt);
X#endif
X}
X
Xint	rgetch()		/* refresh, then get a char. */
X{
X	refresh();
X	return (getch());
X}
X
Xvoid	purge() 	/* remove old players */
X{
XFILE	*fin, *fout;
Xstruct	stats	sbuf;
Xreg	int	loc, today, temp;
Xlong	ltime;
X
X	loc = 0;
X	time(&ltime);
X	today = localtime(&ltime)->tm_yday;
X	fin = fopen(peoplefile,"r");
X	fout = fopen(peoplefile,ACCESS);
X	while(fread((char *) &sbuf,sizeof(sbuf),1,fin))
X		{
X		temp = today - sbuf.lastused;
X		if (temp < 0)
X			temp += 365;
X		if (temp > 9)		/* ten days old --> delete */
X			{
X			initchar(&sbuf);
X			strcpy(sbuf.name,"<null>");
X			fseek(fout,(long) loc * sizeof(sbuf),0);
X			fwrite((char *) &sbuf,sizeof(sbuf),1,fout);
X			}
X		++loc;
X		}
X	fclose(fin);
X	fclose(fout);
X}
!EOR!
echo extracting - fight.c
sed 's/^X//' > fight.c << '!EOR!'
X/*
X * fight.c   Phantasia monster fighting routine
X */
X
X/*
X * The code exists here for fight to the finish.  Simply add code to
X * set 'fgttofin = TRUE' as an option.	Everything else is here.
X */
X#include "phant.h"
X
Xvoid	fight(stat,particular)			/* monster fighting routine */
Xreg	struct	stats	*stat;
Xint	particular;
X{
Xbool	fghttofin = FALSE, luckout = FALSE;
Xchar	aline[80];
Xdouble	monhit, mdamage, sdamage, monspd, maxspd, inflict, monstr, temp, shield;
Xint	ch;
Xreg	int	whichm, size, howmany, lines;
Xstruct	mstats	monster;
X
X	fghting = changed = TRUE;
X	shield = 0.0;
X	if (setjmp(fightenv) == 2)
X		shield = roll(100 + (stat->mxn + stat->shd)*6.2,3000);
X	howmany = 0;
X	size = (valhala) ? stat->lvl/5 : circ(stat->x,stat->y);
X	if (particular >= 0)
X		whichm = particular;
X	else if (marsh)
X		whichm = roll(0,15);
X	else if (size > 24)
X		whichm = roll(14,86);
X	else if (size > 15)
X		whichm = roll(0,50) + roll(14,37);
X	else if (size > 8)
X		whichm = roll(0,50) + roll(14,26);
X	else if (size > 3)
X		whichm = roll(14,50);
X	else 
X		whichm = roll(14,25);
X
XCALL:	move(3,0);
X	clrtobot();
X	move(5,0);
X	lines = 6;
X	callmonster(whichm,size,&monster);
X	if (stat->blind)
X		strcpy(monster.name,"a monster");
X	++howmany;
X	if (monster.typ == 1)	/* unicorn */
X		if (stat->vrg)
X			{
X			printw("You just subdued %s, thanx to the virgin.",monster.name);
X			stat->vrg = FALSE;
X			goto FINISH;
X			}
X		else
X			{
X			printw("You just saw %s running away!",monster.name);
X			goto LEAVE;
X			}
X	if (monster.typ == 2 && stat->typ > 20)
X		{
X		strcpy(monster.name,"Morgoth");
X		monster.str = rnd()*(stat->mxn + stat->shd)/1.4 + rnd()*(stat->mxn + stat->shd)/1.5;
X		monster.brn = stat->brn;
X		monster.hit = stat->str*30;
X		monster.typ = 23;
X		monster.spd = speed*1.1 + speed*(stat->typ == 90);
X		monster.flk = monster.trs = monster.exp = 0;
X		mvprintw(4,0,"You've encountered %s, Bane of the Council and Valar.",monster.name);
X		}
X	fghttofin = luckout = FALSE;
X	monstr = monster.str;
X	monhit = monster.hit;
X	mdamage = sdamage = 0;
X	monspd = maxspd = monster.spd;
X	*monster.name = toupper(*monster.name);
X
XTOP:	mvprintw(5,0,"You are being attacked by %s,   EXP: %.0f   (Size: %d)",monster.name,monster.exp,size);
X	printstats(stat);
X	mvprintw(1,26,"%20.0f",stat->nrg + shield);
X	if (monster.typ == 4 && stat->bls && stat->chm)
X		{
X		mvprintw(6,0,"You just overpowered %s!",monster.name);
X		lines = 7;
X		stat->bls = FALSE;
X		--stat->chm;
X		goto FINISH;
X		}
X	monster.spd = min(monster.spd + 1,maxspd);
X	if (rnd()*monster.spd > rnd()*speed && monster.typ != 4 && monster.typ != 16)
X		{
X		if (monster.typ)
X			switch (monster.typ)	/* do special things */
X				{
X				case 5: /* Leanan-Sidhe */
X					if (rnd() > 0.25)
X						goto NORMALHIT;
X					inflict = roll(1,(size - 1)/2);
X					inflict = min(stat->str,inflict);
X					mvprintw(lines++,0,"%s sapped %0.f of your strength!",monster.name,inflict);
X					stat->str -= inflict;
X					strength -= inflict;
X					break;
X				case 6: /* Saruman */
X					if (stat->pal)
X						{
X						mvprintw(lines++,0,"Wormtongue stole your palantir!");
X						stat->pal = FALSE;
X						}
X					else if (rnd() > 0.2)
X						goto NORMALHIT;
X					else if (rnd() > 0.5)
X						{
X						mvprintw(lines++,0,"%s transformed your gems into gold!",monster.name);
X						stat->gld += stat->gem;
X						stat->gem = 0.0;
X						}
X					else
X						{
X						mvprintw(lines++,0,"%s scrambled your stats!",monster.name);
X						scramble(stat);
X						}
X					break;
X				case 7: /* Thaumaturgist */
X					if (rnd() > 0.15)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s transported you!",monster.name);
X					stat->x += sgn(stat->x)*roll(50*size,250*size);
X					stat->y += sgn(stat->y)*roll(50*size,250*size);
X					goto LEAVE;
X				case 8: /* Balrog */
X					inflict = roll(10,monster.str);
X					inflict = min(stat->exp,inflict);
X					mvprintw(lines++,0,"%s took away %0.f experience points.",monster.name,inflict);
X					stat->exp -= inflict;
X					break;
X				case 9: /* Vortex */
X					if (rnd() > 0.2)
X						goto NORMALHIT;
X					inflict = roll(0,7.5*size);
X					inflict = min(stat->man,floor(inflict));
X					mvprintw(lines++,0,"%s sucked up %.0f of your manna!",monster.name,inflict);
X					stat->man -= inflict;
X					break;
X				case 10:	/* Nazgul */
X					if (rnd() > 0.3)
X						goto NORMALHIT;
X					if (stat->rng.type && stat->rng.type < 10)
X						{
X						mvaddstr(lines++,0,"Will you relinguish your ring ? ");
X						ch = rgetch();
X						if (toupper(ch) == 'Y')
X							{
X							stat->rng.type = NONE;
X							goto LEAVE;
X							}
X						}
X					mvprintw(lines++,0,"%s neutralized 1/5 of your brain!",monster.name);
X					stat->brn *= 0.8;
X					break;
X				case 11:	/* Tiamat */
X					if (rnd() > 0.6)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s took half your gold and gems and flew off.",monster.name);
X					stat->gld = floor(stat->gld/2);
X					stat->gem = floor(stat->gem/2);
X					goto LEAVE;
X				case 12:	/* Kobold */
X					if (rnd() >.7)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s stole one gold piece and ran away.",monster.name);
X					stat->gld = max(0,stat->gld-1);
X					goto LEAVE;
X				case 13:	/* Shelob */
X					if (rnd() > 0.5)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s has bitten and poisoned you!",monster.name);
X					++stat->psn;
X					break;
X				case 14:	/* Faeries */
X					if (!stat->hw)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"Your holy water killed it!");
X					--stat->hw;
X					goto FINISH;
X				case 15:	/* Lamprey */
X					if (rnd() > 0.7)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s bit and poisoned you!",monster.name);
X					stat->psn += 0.25;
X					break;
X				case 17:	/* Bonnacon */
X					if (rnd() > 0.1)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s farted and scampered off.",monster.name);
X					stat->nrg /= 2;
X					goto LEAVE;
X				case 18:	/* Smeagol */
X					if (rnd() > 0.5 || !stat->rng.type)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s tried to steal your ring, ",monster.name);
X					if (rnd() > 0.1)
X						addstr("but was unsuccessful.");
X					else
X						{
X						addstr("and ran away with it!");
X						stat->rng.type = NONE;
X						goto LEAVE;
X						}
X					break;
X				case 19:	/* Succubus */
X					if (rnd() > 0.3)
X						goto NORMALHIT;
X					inflict = roll(15,size*10);
X					inflict = min(inflict,stat->nrg);
X					mvprintw(lines++,0,"%s sapped %0.f of your energy.",monster.name,inflict);
X					stat->nrg -= inflict;
X					break;
X				case 20:	/* Cerberus */
X					if (rnd() > 0.25)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s took all your metal treasures!",monster.name);
X					stat->swd = stat->shd =stat->gld = stat->crn = 0;
X					goto LEAVE;
X				case 21:	/* Ungoliant */
X					if (rnd() > 0.1)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s poisoned you, and took one quik.",monster.name);
X					stat->psn += 5;
X					--stat->quk;
X					break;
X				case 22:	/* Jabberwock */
X					if (rnd() > 0.1)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s flew away, and left you to contend with one of its friends.",monster.name);
X					whichm = 55 + 22*(rnd() > 0.5);
X					goto CALL;
X				case 24:	/* Troll */
X					if (rnd() > 0.5)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s partially regenerated his energy.!",monster.name);
X					monster.hit += floor((monhit*size - monster.hit)/2);
X					monster.str = monstr;
X					mdamage = sdamage = 0;
X					maxspd = monspd;
X					break;
X				case 25:	/* wraith */
X					if (rnd() > 0.3 || stat->blind)
X						goto NORMALHIT;
X					mvprintw(lines++,0,"%s blindeed you!",monster.name);
X					stat->blind = TRUE;
X					break;
X				default:
X					goto NORMALHIT;
X				}
X		else
XNORMALHIT:		{
X			inflict = rnd()*monster.str + 0.5;
X			mvprintw(lines++,0,"%s hit you %.0f times!",monster.name,inflict);
XSPECIALHIT:		if ((shield -= inflict) < 0)
X				{
X				stat->nrg += shield;
X				shield = 0;
X				}
X			}
X		}
X	else
X		{
X		if (fghttofin)
X			goto MELEE;
X		mvaddstr(3,0,"1:Melee  2:Skirmish  3:Evade  4:Spell  5:Nick  ");
X		if (!luckout)
X			if (monster.typ == 23)
X				addstr("6:Ally  ");
X			else
X				addstr("6:Luckout  ");
X		if (stat->rng.type > 0)
X			addstr("7:Use Ring  ");
X		else
X			clrtoeol();
X		ch = gch(stat->rng.type);
X		move(lines = 6,0);
X		clrtobot();
X		switch (ch)
X			{
X			default:
X			case '1':	/* melee */
XMELEE:				inflict = roll(strength/2 + 5,1.3*strength) + (stat->rng.type < 0 ? strength : 0);
X				mdamage += inflict;
X				monster.str = monstr - mdamage/monhit*monstr/4;
X				goto HITMONSTER;
X			case '2':	/* skirmish */
X				inflict = roll(strength/3 + 3,1.1*strength) + (stat->rng.type < 0 ? strength : 0);
X				sdamage += inflict;
X				maxspd = monspd - sdamage/monhit*monspd/4;
X				goto HITMONSTER;
X			case '3':	/* evade */
X				if ((monster.typ == 4 || monster.typ == 16
X				|| rnd()*speed*stat->brn > rnd()*monster.spd*monster.brn)
X				&& (monster.typ != 23))
X					{
X					mvaddstr(lines++,0,"You got away!");
X					stat->x += roll(-2,5);
X					stat->y += roll(-2,5);
X					goto LEAVE;
X					}
X				else
X					mvprintw(lines++,0,"%s is still after you!",monster.name);
X				break;
X			case '4':	/* spell */
X				lines = 7;
X				mvaddstr(3,0,"\n\n");
X				mvaddstr(3,0,"1:All or Nothing");
X				if (stat->mag >= 3)
X					mvaddstr(3,18,"2:Magic Bolt");
X				if (stat->mag >= 7)
X					mvaddstr(3,32,"3:Force Field");
X				if (stat->mag >= 10)
X					mvaddstr(3,47,"4:Transform");
X				if(stat->mag >= 15)
X					mvaddstr(3,60,"5:Increase Might\n");
X				if (stat->mag >= 20)
X					mvaddstr(4,0,"6:Invisibility");
X				if (stat->mag >= 25)
X					mvaddstr(4,18,"7:Transport");
X				if (stat->mag >= 30)
X					mvaddstr(4,32,"8:Paralyze");
X				if (stat->typ > 20)
X					mvaddstr(4,52,"9:Specify");
X				mvaddstr(6,0,"Spell ? ");
X				ch = rgetch();
X				mvaddstr(3,0,"\n\n");
X				if (monster.typ == 23 && ch != '4')
X					illspell();
X				else
X					switch (ch)
X						{
X						case '1':	/* all or nothing */
X							{
X							inflict = (rnd() < 0.25) ? (monster.hit*1.0001 + 1) : 0;
X							if (monster.typ == 4)
X								inflict *= .9;
X							if (stat->man)
X								--stat->man;
X							maxspd *= 2;
X							monspd *= 2;
X							monster.spd = max(1,monster.spd * 2);
X							monstr = monster.str *= 2;
X							goto HITMONSTER;
X							}
X						case '2':	/* magic bolt */
X							if (stat->mag < 3)
X								illspell();
X							else
X								{
X								do
X									{
X									mvaddstr(6,0,"How much manna for bolt? ");
X									getstring(aline,80);
X									sscanf(aline,"%F",&temp);
X									}
X								while (temp < 0 || temp > stat->man);
X								stat->man -= floor(temp);
X								inflict = temp*roll(10,sqrt(stat->mag/3.0 + 1.0));
X								mvaddstr(6,0,"Magic Bolt fired!\n");
X								if (monster.typ == 4)
X									inflict = 0.0;
X								goto HITMONSTER;
X								}
X						case '5':	/* increase might */
X							{
X							if (stat->mag < 15)
X								illspell();
X							else if (stat->man < 55)
X								nomanna();
X							else
X								{
X								stat->man -= 55;
X								strength += (1.2*(stat->str+stat->swd)+5-strength)/2;
X								mvprintw(6,0,"New strength:  %.0f\n",strength);
X								}
X							break;
X							}
X						case '3':	/* force field */
X							{
X							if (stat->mag < 7)
X								illspell();
X							else if (stat->man < 20)
X								nomanna();
X							else
X								{
X								shield = (stat->mxn + stat->shd)*4.2 + 45;
X								stat->man -= 20;
X								mvaddstr(6,0,"Force Field up.\n");
X								}
X							break;
X							}
X						case '4':	/* transform */
X							{
X							if (stat->mag < 10)
X								illspell();
X							else if (stat->man < 35)
X								nomanna();
X							else
X								{
X								stat->man -= 35;
X								whichm = roll(0,100);
X								goto CALL;
X								}
X							break;
X							}
X						case '6':	/* invisible */
X							{
X							if (stat->mag < 20)
X								illspell();
X							else if (stat->man < 45)
X								nomanna();
X							else
X								{
X								stat->man -= 45;
X								speed += (1.2*(stat->quk+stat->quks)+5-speed)/2;
X								mvprintw(6,0,"New quik :  %.0f\n",speed);
X								}
X							break;
X							}
X						case '7':	/* transport */
X							{
X							if (stat->mag < 25)
X								illspell();
X							else if (stat->man < 50)
X								nomanna();
X							else
X								{
X								stat->man -= 50;
X								if (stat->brn + stat->mag < monster.exp/300*rnd())
X									{
X									mvaddstr(6,0,"Transport backfired!\n");
X									stat->x += (250*size*rnd() + 50*size)*sgn(stat->x);
X									stat->y += (250*size*rnd() + 50*size)*sgn(stat->y);
X									goto LEAVE;
X									}
X								else
X									{
X									mvprintw(6,0,"%s is transported.\n",monster.name);
X									monster.trs *= (rnd() > 0.3);
X									goto FINISH;
X									}
X								}
X							break;
X							}
X						case '8':	/* paralyze */
X							{
X							if (stat->mag < 30)
X									illspell();
X							else if (stat->man < 60)
X								nomanna();
X							else
X								{
X								stat->man -= 60;
X								if (stat->mag > monster.exp/1000*rnd())
X									{
X									mvprintw(6,0,"%s is held.\n",monster.name);
X									monster.spd = -2;
X									}
X								else
X									mvaddstr(6,0,"Monster unaffected.\n");
X								}
X							break;
X							}
X						case '9':	/* specify */
X							{
X							if (stat->typ < 20)
X								illspell();
X							else if (stat->man < 1000)
X								nomanna();
X							else
X								{
X								mvaddstr(6,0,"Which monster do you want [0-99] ? ");
X								whichm = inflt();
X								whichm = max(0,min(99,whichm));
X								stat->man -= 1000;
X								goto CALL;
X								}
X							break;
X							}
X						}
X				break;
X			case '5':
X				inflict = 1 + stat->swd;
X				stat->exp += floor(monster.exp/10);
X				monster.exp *= 0.92;
X				maxspd += 2;
X				monster.spd = (monster.spd < 0) ? 0 : monster.spd + 2;
X				if (monster.typ == 4)
X					{
X					mvprintw(lines++,0,"You hit %s %.0f times, and made him mad!",monster.name,inflict);
X					stat->quk /= 2;
X					stat->x += sgn(stat->x)*roll(50*size,250*size);
X					stat->y += sgn(stat->y)*roll(50*size,250*size);
X					stat->y += (250*size*rnd() + 50*size)*sgn(stat->y);
X					goto LEAVE;
X					}
X				else
X					goto HITMONSTER;
X			case '6':	/* luckout */
X				if (luckout)
X					mvaddstr(lines++,0,"You already tried that.");
X				else
X					if (monster.typ == 23)
X						if (rnd() < stat->sin/100)								{
X							mvprintw(lines++,0,"%s accepted!",monster.name);
X							goto LEAVE;
X							}
X						else
X							{
X							luckout = TRUE;
X							mvaddstr(lines++,0,"Nope, he's not interested.");
X							}
X					else
X						if ((rnd() + .333)*stat->brn < (rnd() + .333)*monster.brn)
X							{
X							luckout = TRUE;
X							mvprintw(lines++,0,"You blew it, %s.",stat->name);
X							}
X						else
X							{
X							mvaddstr(lines++,0,"You made it!");
X							goto FINISH;
X							}
X				break;
X			case '\014':	/* clear screen */
X				clear();
X				break;
X			case '7':	/* use ring */
X				if (stat->rng.type > 0)
X					{
X					mvaddstr(lines++,0,"Now using ring.");
X						stat->rng.type = -stat->rng.type;
X						if (abs(stat->rng.type) != DLREG)
X							--stat->rng.duration;
X						goto NORMALHIT;
X					}
X				break;
X			}
X		goto BOT;
XHITMONSTER:		{
X			inflict = floor(inflict);
X			mvprintw(lines++,0,"You hit %s %.0f times!",monster.name,inflict);
X			if ((monster.hit -= inflict) >0)
X				switch (monster.typ)
X					{
X					case 4: /* dark lord */
X						inflict = stat->nrg + shield +1;
X						goto SPECIALHIT;
X					case 16:	/* shrieker */
X						mvaddstr(lines++,0,"Shreeeek!!  You scared it, and it called one of its friends.");
X						paws(lines);
X						whichm = roll(70,30);
X						goto CALL;
X					}
X			else
X				{
X				if (monster.typ == 23)	/* morgoth */
X					mvaddstr(lines++,0,"You have defeated Morgoth, but he may return. . .");
X				else
X					mvprintw(lines++,0,"You killed it.  Good work, %s.",stat->name);
X				goto FINISH;
X				}
X			}
X		}
XBOT:	refresh();
X	if (lines == 23)
X		{
X		paws(23);
X		move(lines = 6,0);
X		clrtobot();
X		}
X	if (stat->nrg <= 0)
X		{
X		paws(lines);
X		death(stat);
X		goto LEAVE;
X		}
X	goto TOP;
XFINISH:	stat->exp += monster.exp;
X	if (rnd() < monster.flk/100.0)	/* flock monster */
X		{
X		paws(lines);
X		fghttofin = FALSE;
X		goto CALL;
X		}
X	else if (size > 1 && monster.trs && rnd() > pow(0.6,(double) (howmany/3 + size/3)))	/* this takes # of flocks and size into account */
X		{
X		paws(lines);
X		treasure(stat,monster.trs,size);
X		}
XLEAVE:	stat->rng.type = abs(stat->rng.type);
X	paws(lines+3);
X	move(4,0);
X	clrtobot();
X	fghting = FALSE;
X}
!EOR!
echo extracting - setfiles.c
sed 's/^X//' > setfiles.c << '!EOR!'
X/*
X * setfiles.c	Program to set up all files for Phantasia
X */
X
X#include "phant.h"
X
Xmain(argc,argv)					/* program to init. files for Phantasia */
Xint	argc;
Xchar	**argv;
X{
XFILE	*fp;
Xstruct	stats	sbuf;
Xstruct	nrgvoid	grail;
Xint	ch;
X
X	umask(077);
X	srand((int) time(NULL));
X	fp = fopen(goldfile,"w");
X	fclose(fp);
X	fp = fopen(motd,"w");
X	fclose(fp);
X	fp = fopen(messfile,"w");
X	fclose(fp);
X	printf("Do you want to reset the character file (necessary for startup) ? ");
X	ch = getchar();
X	if (toupper(ch) == 'Y')
X		{
X		buildchar(&sbuf);
X		strcpy(sbuf.name,"<null>");
X		fp = fopen(peoplefile,"w");
X		fwrite(&sbuf,sizeof(sbuf),1,fp);
X		fclose(fp);
X		}
X	grail.active = TRUE;
X	grail.x = roll(-1.0e6,2.0e6);
X	grail.y = roll(-1.0e6,2.0e6);
X	fp = fopen(voidfile,"w");
X	fwrite(&grail,sizeof(grail),1,fp);
X	fclose(fp);
X	fp = fopen(lastdead,"w");
X	fputs(" ",fp);
X	fclose(fp);
X}
X
Xbuildchar(stat)				/* put in some default values */
X/* Note that this function is almost the same as initchar().
X   It is used to insure that unexpected values will not be found in a
X   new character file.							*/
Xstruct	stats	*stat;
X{
X	stat->x = roll(-125,251);
X	stat->y = roll(-125,251);
X	stat->exp = stat->lvl = stat->sin = 0;
X	stat->crn = stat->psn = 0;
X	stat->rng.type = NONE;
X	stat->rng.duration = 0;
X	stat->pal = FALSE;
X	stat->hw = stat->amu = stat->bls = 0;
X	stat->chm = 0;
X	stat->gem = 0.1;
X	stat->gld = roll(25,50) + roll(0,25) + 0.1;
X	stat->quks = stat->swd = stat->shd = 0;
X	stat->vrg = FALSE;
X	stat->typ = 0;
X}
!EOR!
echo extracting - monsters
sed 's/^X//' > monsters << '!EOR!'
Xa Water Leaper          12      14      16      24      59      0       0       62
Xa Leech                 4       19      29      30      66      0       0       73
Xa Urisk                 13      30      15      46      127     1       0       3
XShellycoat              28      21      18      63      226     2       0       0
Xa Naiad                 21      62      27      58      378     2       0       11
Xa Nixie                 22      58      28      108     604     3       0       6
Xa Glaistig              21      106     25      127     1002    3       0       0
Xa Mermaid               18      116     22      108     809     3       0       0
Xa Merman                24      115     23      109     808     4       0       0
Xa Siren                 22      128     31      89      915     4       0       24
Xa Lamprey               14      67      33      156     1562    4       15      37
Xa Kopoacinth            26      36      26      206     2006    5       0       20
Xa Kelpie                61      25      24      223     4025    5       0       0
Xan Aspidchelone         114     104     19      898     10041   7       0       2
Xan Idiot                13      14      16      28      49      0       0       0
Xsome Green Slime        1       5       45      100     57      0       0       26
Xa Pixie                 11      29      23      26      64      0       0       32
Xa Serpent               10      18      25      25      79      0       0       10
Xa Cluricaun             12      27      20      30      81      0       14      5
Xan Imp                  22      30      14      40      92      0       0       1
Xa Centipede             3       8       18      15      33      0       0       61
Xa Beetle                2       11      21      26      44      0       0       48
Xa Fir Darrig            18      22      17      35      107     0       14      1
XModnar                  15      23      20      40      101     7       2       12
Xa Gnome                 7       45      26      23      111     0       0       21
Xa Sprite                9       37      25      31      132     1       0       43
Xa Mimic                 11      55      29      47      213     1       3       2
Xa Kobold                13      10      14      21      121     1       12      68
Xa Spider                6       11      28      28      124     1       0       57
Xan Uldra                14      37      21      32      93      1       0       6
Xa Gnoll                 20      25      15      40      166     1       0       61
Xa Bogie                 23      28      19      57      189     1       0       57
Xa Fachan                9       40      15      45      139     1       14      10
Xa Moron                 3       1       10      10      28      0       0       100
Xan Orc                  25      13      16      26      141     1       0       92
Xa Ghillie Dhu           12      16      13      28      104     2       14      2
Xa Bogle                 19      15      16      35      157     2       14      15
Xa Shrieker              2       62      27      9       213     2       16      0
Xa Carrion Crawler       12      20      20      65      142     2       0       42
Xa Trow                  15      17      23      51      136     2       0       36
Xa Warg                  20      10      17      45      152     2       0       88
Xa Stirge                2       6       35      25      153     2       0       95
Xa Crebain               5       11      31      31      82      2       0       81
Xa Killmoulis            30      19      8       75      175     3       14      22
Xa Hob-goblin            35      20      15      72      246     3       0       18
Xa Unicorn               27      57      27      57      627     3       1       0
Xa Fenoderee             16      6       21      65      222     3       0       42
Xan Ogre                 42      14      16      115     409     3       0       19
Xa Dodo                  62      12      11      76      563     3       0       3
Xa Hydra                 14      27      33      99      599     3       0       27
Xa Hamadryad             23      47      26      62      426     3       0       12
Xa Bwca                  21      17      19      55      387     3       14      1
Xan Owlbear              35      16      18      100     623     4       0       22
XBlack Annis             37      52      15      65      786     4       0       2
Xa Jello Blob            45      23      12      114     1191    4       0       0
Xa Wichtlein             13      40      25      61      800     4       0       8
Xa Cocodrill             39      28      24      206     1438    4       0       38
Xa Troll                 75      12      20      185     1013    4       24      29
Xa Bonnacon              89      26      9       255     1661    4       17      14
Xa Gargoyle              22      21      29      200     1753    5       0       7
Xa Chaladrius            8       49      37      172     1929    5       0       20
Xa Gwyllion              27      73      20      65      1888    5       0       4
Xa Cinomulgus            23      2       10      199     263     5       0       18
Xa Peridexion            26      32      24      98      1300    5       0       2
XSmeagol                 41      33      27      373     2487    5       18      0
Xa Wraith                52      102     22      200     3112    5       25      13
Xa Snotgurgle            143     19      26      525     4752    6       0       3
Xa Phooka                42      63      21      300     4125    5       0       12
Xa Vortex                101     30      31      500     6992    6       9       4
XShelob                  147     64      28      628     5003    7       13      0
Xa Thaumaturgist         35      200     23      400     7628    6       7       0
XSmaug                   251     76      26      1022    9877    7       0       0
Xa Cold-drake            301     102     24      1222    10888   7       0       0
Xa Red Dragon            342     141     23      1299    11649   8       0       0
XScatha the Worm         406     208     20      1790    11999   8       0       0
XTiamat                  506     381     29      2000    13001   9       11      0
Xa Bandersnatch          105     98      22      450     7981    6       0       3
Xa Harpy                 103     49      24      263     7582    6       0       2
Xa Tigris                182     38      17      809     7777    6       0       3
Xa Gryphon               201     45      19      813     8888    7       0       1
Xa Coblynau              205     46      18      585     8333    6       0       2
Xa Chimaera              173     109     28      947     12006   7       0       0
Xa Jack-in-Irons         222     36      12      1000    9119    7       0       0
XSaruman                 55      373     17      1500    17101   11      6       0
Xa Balrog                500     100     25      705     8103    7       8       0
XArgus                   201     87      14      1500    10010   8       0       0
Xa Titan                 302     1483    12      1625    11011   8       0       0
XCacus                   256     43      19      1750    12012   8       0       0
XBegion                  403     154     10      1875    13013   8       0       0
XGrendel                 197     262     23      2000    14014   8       0       0
Xa Nazgul                250     251     26      1011    9988    12      10      9
Xa Succubus              186     1049    27      2007    19984   9       19      0
XRed Cap                 143     50      35      1965    23456   9       0       0
Xa Nuckelavee            300     75      20      2185    11111   8       0       0
XCerberus                236     96      29      2600    25862   9       20      0
Xa Jabberwock            185     136     25      2265    23256   9       22      0
XUngoliant               399     2398    37      2784    27849   10      21      0
XLeanan-Sidhe            486     5432    46      3000    30004   9       5       0
Xthe Dark Lord           9999    9999    31      19999   30005   13      4       0
!EOR!
echo extracting - phant.nr
sed 's/^X//' > phant.nr << '!EOR!'
X.de sh
X.br
X.ne 5
X.PP
X\fB\\$1\fR
X.PP
X..
X.TH PHANTASIA 6 GAMES
X.UC 4
X.SH NAME
Xphantasia \- an interterminal fantasy game
X.SH SYNOPSIS
X.B phantasia
X[
X.B \-s
X] [
X.B \-m
X] [
X.B \-a
X] [
X.B \-x
X] [
X.B \-h
X] [
X.B \-H
X] [
X.B \-p
X]
X.SH DESCRIPTION
X.I Phantasia
Xis a role playing game vaguely similar to dungeons and dragons.
XIt allows players to roll up characters of various types to fight
Xmonsters and other players.
XProgression of characters is based upon gaining experience from fighting
Xmonsters (and other players).
X.PP
XMost of the game is menu driven and self-explanatory (more or less).
XThe screen is cursor updated, so be sure to set up the
X.B TERM
Xvariable in your environment.
X.PP
XThe options provide for a variety of functions to support the game.
XThey are:
X.PP
X.TP .5i
X.B \-s
XInvokes 
X.I phantasia
Xwithout header information.
X.TP .5i
X.B \-m
XGet a monster listing.
X.TP .5i
X.B \-a
XGet a listing of all character names on file.
X.TP .5i
X.B \-x
XExamine/change a particular character on file.
X.TP .5i
X.B \-h
XGet a help listing (this message).
X.TP .5i
X.B \-H
XGet header listing only.
X.TP .5i
X.B \-p
XPurge old characters.
X.PP
XThe characters are saved on a common file, in order to make the game
Xinteractive between players.  The characters are given a password
Xin order to retrieve them later.  Only characters above
X.B level
Xzero are saved.  Characters unused for more than nine days will be
Xpurged.
X.SH AUTHOR
XEdward Estes, AT&T Teletype Corp.
X.SH PARTICULARS
X.sh "Playing in General"
XCertain of the player's more important statistics are almost always
Xdisplyed on the screen, with maximums (where applicable) in
Xparentheses.
X.PP
XThe character is placed randomly near the center of a cartesian
Xsystem.  One may move by hitting
X.B E, W, N,
Xor
X.B S
X(lower case may also be used, at no time is the game case dependent).
XTo move to a particular (x,y) coordinate, use the
X.B move
X('1') command.	The distance a character can move is calculated by
X1 plus 1.5 per
X.B level.
XMoving in a particular compass direction will move the player the maximum
Xallowed distance in that direction.
X.PP
XA player may at any time see who else is playing with a
X.B players
X('2') option.  One may see only those who are the same distance or closer
Xto the origin as he/she.
X.B Kings,
Xand
X.B council of the wise
Xcan see and can be seen by everyone.  A
X.B palantir
Xremoves these retrictions.
X.PP
XOne can talk to other players with the
X.B talk
X('3') option.  In general, this is a line or so of text.  To remove a current
Xmessage, just type <return> when prompted for a message.
X.PP
XThe
X.B stats
X('4') option shows a players characteristics in more detail.
X.PP
XOne may leave the game either with the
X.B quit
X('5') option, or by hitting interrupt.	Quitting during battle results
Xin death for obvious reasons.
X.PP
XOne may rest by default.  Resting lets one regain maximum
X.B energy level,
Xand also lets one find
X.B manna
X(more is found for larger levels and further distances from the origin).
X.PP
XOne may call a monster by hitting '9'.
X.PP
XSeveral other options become available as the player progress in
X.B level
Xand
X.B magic,
Xor to other positions in the game (
X.B valar, council of the wise, king
X).
XThese are described elsewhere.
XIn general, a control-L will force the redrawing of the screen.
X.PP
XOther things which may happen are more or less self-explanatory.
X.sh "Fighting Monsters"
XA player has several options while fighting monsters.  They are as follows:
X.TP 1.5i
X.B melee
XInflicts damage on the monster, based upon
X.B strength.
XAlso decreases the monster's
X.B strength
Xsome.
X.TP 1.5i
X.B skirmish
XInflicts a little less damage than
X.B melee,
Xbut decreases the monster's
X.B quickness
Xinstead.
X.TP 1.5i
X.B evade
XAttempt to run away.  Success is based upon both the player's and
Xthe monster's
X.B brains
Xand
X.B quickness.
X.TP 1.5i
X.B spell
XSeveral options for throwing spells (described elsewhere).
X.TP 1.5i
X.B nick
XHits the monster one plus the player's
X.B sword,
Xand gives the player 10% of the monster's
X.B experience.
XDecreases the monster's
X.B experience
Xan amount proportional to the amount granted.
XThis also increases the monster's quickness.
XParalyzed monsters wake up very fast when nicked.
X.TP 1.5i
X.B luckout
XThis is essentially a battle of wits with the monster.	Success is based
Xupon the player's and the monster's
X.B brains.
XThe player gets credit for slaying the monster if he/she succeeds.
XOtherwise, nothing happens, and the chance to
X.B luckout
Xis lost.
X.sh "Character Statistics"
X.TP 1.5i
X.B strength
Xdetermines how much damage a character can inflict.
X.TP 1.5i
X.B quickness
Xdetermines how many chances a character gets to make decisions while
Xfighting.
X.TP 1.5i
X.B energy level
Xspecifies how much damage a character may endure before dying.
X.TP 1.5i
X.B magic level
Xdetermines which spells a character may throw, and how effective those
Xspells will be.
X.TP 1.5i
X.B brains
Xbasically, the character's intelligence; used for various fighting options
Xand spells.
X.TP 1.5i
X.B manna
Xused as a power source for throwing spells.
X.TP 1.5i
X.B experience
Xgained by fighting monsters and other characters.
X.TP 1.5i
X.B level
Xindicative of how much experience a character has accumulated; progresses
Xgeometrically as
X.B experience
Xincreases.
X.TP 1.5i
X.B poison
Xsickness which degrades a character's performance (affects
X.B energy level
Xand
X.B strength
X).
X.TP 1.5i
X.B sin
Xaccumulated as a character does certain nasty things; used only rarely
Xin normal play of the game.
X.TP 1.5i
X.B age
Xnumber of seconds of playing time for the character.
XAs
X.B age
Xincreases, many personal statistics degenerate.
X.sh "Character Types"
XCharacter statistics are rolled randomly from the above list, according
Xto character type.  The types are as follows:
X.TP 1.5i
X.B magic user
Xstrong in
X.B magic level
Xand
X.B brains
X, weak in other areas.	Must rely on wits and magic to survive.
X.TP 1.5i
X.B fighter
Xgood in
X.B strength
Xand
X.B energy level
X, fairly good in other areas.  This adds up to a well-equipped fighter.
X.TP 1.5i
X.B elf
Xvery high
X.B quickness
Xand above average
X.B magic level
Xare
X.B elves
Xselling points.
X.TP 1.5i
X.B dwarf
Xvery high
X.B strength
Xand
X.B energy level
X, but with a tendency to be rather slow and not too bright.
X.TP 1.5i
X.B halfling
Xrather quick and smart, with high
X.B energy level
X, but poor in
X.B magic
Xand
X.B strength.
XBorn with some
X.B experience.
X.TP 1.5i
X.B experimento
Xvery mediocre in all areas.  However, the
X.B experimento
Xmay be placed almost anywhere within the playing grid.
X.PP
XThe possible ranges for starting statistics are summarized in
Xthe following table.
X.PP
X.TS
Xl c c c c c c
Xl c c c c c c.
XType	Strength	Quick	Manna	Energy	Brains	Magic
X_
XMag. User	20-25	30-35	50-100	30-45	60-85	5-9
XFighter	40-55	30-35	30-50	45-70	25-45	3-6
XElf	35-45	28-38	45-90	30-50	40-65	4-7
XDwarf	50-70	25-30	25-45	60-100	20-40	2-5
XHalfling	20-25	34	25-45	55-90	40-75	1-4
XExperimento	25	27	100	35	25	2
X.TE
X.PP
XNot only are the starting characteristics different for the different
Xcharacter types, the characteristics progress at different rates for the
Xdifferent types as the character goes up in
X.B level.  Experimentoes'
Xcharacteristics progress randomly as one of the other types.
XThe progression as characters increase in
X.B level
Xis summarized in the following table.
X.PP
X.TS
Xl c c c c c
Xl n n n n n.
XType	Strength	Manna	Energy	Brains	Magic
X_
XMag. User	2.0	75	20	6	2.75
XFighter	3.0	40	30	3.0	1.5
XElf	2.5	65	25	4.0	2.0
XDwarf	5	30	35	2.5	1
XHalfling	2.0	30	30	4.5	1
X.TE
X.PP
XCharacter types are identified by certain numeric values as follows:
X.br
X1:
X.B Magic User
X2:
X.B Fighter
X3:
X.B Elf
X4:
X.B Dwarf
X5:
X.B Halfling
X6:
X.B Experimento
X.PP
XCharacters with one or more
X.B crowns
Xare designated as a negative type.
X.B Kings
Xhave ten added to their type; members of the
X.B council of the wise
Xhave twenty added to their type.
X.B Valar
Xare type 99, and
X.B ex-valar
Xare type 90.
X.sh "Spells"
XDuring the course of the game, the player may exercise his/her particular
Xmagic powers.  These cases are described below.
X.TP 1.5i
X.B cloak
X.I magic level necessary:
X15 (plus level 5)
X.br
X.I manna used:
X35 plus 3 per rest period
X.br
XUsed during normal play.  Prevents monsters from finding the character,
Xas well as hiding the player from other players.  His/her coordinates
Xshow up as '?' in the
X.B players
Xoption.  Players cannot collect
X.B manna,
Xfind trading posts, or discover the
X.B grail
Xwhile cloaked.	Calling a monster uncloaks, as well as choosing
Xthis option while cloaked.
X.br
X.TP 1.5i
X.B teleport
X.I magic level necessary:
X25 (plus level 10)
X.br
X.I manna used:
X20 per 75 moved
X.br
XUsed during normal play.  Allows the player too move with much more freedom
Xthan with the
X.B move
Xoption, at the price of expending manna.  The maximum distance possible
Xto move is based upon
X.B level
Xand
X.B magic level.
X.TP 1.5i
X.B power blast
X.I magic level necessary:
Xnone
X.br
X.I manna used:
X5 times
X.B level
X.br
XUsed during inter-terminal battle.  Damage is based upon
X.B magic level
Xand
X.B strength.
XHits much harder than a normal hit.
X.TP 1.5i
X.B all or nothing
X.I magic level necessary:
Xnone
X.br
X.I manna used:
X1
X.br
XUsed while combatting monsters.
XHas a 25% chance of working.  If it works it hits the monster just enough
Xto kill it.  If it fails, it doesn't hit the monster, and doubles the
Xmonster's
X.B quickness
Xand
X.B strength.
XParalyzed monsters wake up much quicker as a result of this spell.
X.TP 1.5i
X.B magic bolt
X.I magic level necessary:
X3
X.br
X.I manna used:
Xvariable
X.br
XUsed while combatting monsters.  Hits the monster based upon the amount
Xof
X.B manna
Xexpended and
X.B magic level.
XGuaranteed to hit at least 10 per
X.B manna.
X.TP 1.5i
X.B force field
X.I magic level necessary:
X7
X.br
X.I manna used:
X20
X.br
XUsed during monster combat.  Throws up a shield to protect from damage.
XThe shield is added to actual energy level, and is a fixed number, based
Xupon maximum energy.  Normally, damage occurs first to the shield, and
Xthen to the players actual
X.B energy level.
X.TP 1.5i
X.B transform
X.I magic level necessary:
X10
X.br
X.I manna used:
X35
X.br
XUsed during monster combat.  Transforms the monster randomly into one
Xof the other 100 monsters from the monster file.
X.TP 1.5i
X.B increase might
X.I magic level necessary:
X15
X.br
X.I manna used:
X55
X.br
XUsed during combat with monsters.  Increases strength up to a certain maximum.
X.TP 1.5i
X.B invisibility
X.I magic level necessary:
X20
X.br
X.I manna used:
X45
X.br
XUsed while fighting monsters.  Makes it harder for the monster to hit,
Xby temporarily increasing the player's
X.B quickness.
XThis spell may be thrown several times, but a maximum level will be reached.
X.TP 1.5i
X.B transport
X.I magic level necessary:
X25
X.br
X.I manna used:
X50
X.br
XUsed during monster combat.  Transports the monster away from the
Xplayer.  Success is base upon player's
X.B magic
Xand
X.B brains,
Xand the monster's
X.B experience.
XIf it fails the player is transported instead.	60% of the time, the monster
Xwill drop any treasure it was carrying.
X.TP 1.5i
X.B paralyze
X.I magic level necessary:
X30
X.br
X.I manna used:
X60
X.br
XUsed during monster combat.  "Freezes" the monster by putting its
X.B quickness
Xslightly negative.  The monster will slowly wake up.  Success is based
Xupon player's
X.B magic
Xand the monster's
X.B experience.
XIf it fails, nothing happens.
X.TP 1.5i
X.B specify
X.I magic level necessary:
Xnone
X.br
X.I manna used:
X1000
X.br
XUsed during monster combat only by
X.B valar
Xor
X.B council of the wise.
XAllows the player to pick which monster to fight.
X.sh "Monsters"
XMonsters get bigger as one moves farther from the origin (0,0).  Rings of
Xdistance 125 from the origin determine the size.  A monster's
X.B experience, energy level,
Xand
X.B brains
Xare multiplied by the size.
X.B Strength
Xis increase 50% per size over one, and
X.B quickness
Xremains the same, regardless of size.
X.PP
XAlso, meaner monsters are to be found as one progress farther out
Xfrom the origin.  Monsters also may flock.  The percent chance of that
Xhappening is designated as
X.B flock%
Xin the monster listing.  Monsters outside the first ring
Xmay carry treasure, as determined by their treasure type.
XFlocking monsters, and bigger monsters increase the chances of treasure.
X.PP
XCertain monsters have special abilities; they are as follows:
X.TP 1.5i
X.B Unicorn
Xcan only be subdued if the player is in possession of a
X.B virgin.
X.TP 1.5i
X.B Modnar
Xhas random characteristics, including treasure type.
X.TP 1.5i
X.B Mimic
Xwill pick another name from the list of monsters in order to
Xconfuse.
X.TP 1.5i
X.B Dark Lord
Xvery nasty person.  Does not like to be hit (especially nicked),
Xand many spells do not work well against him.
XOne can always
X.B evade
Xfrom the
X.B Dark Lord.
X.TP 1.5i
X.B Leanan-Sidhe
Xalso a very nasty person.  She will permanently sap
X.B strength
Xfrom someone.
X.TP 1.5i
X.B Saruman
Xwanders around with
X.B Wormtongue
X, who can steal a
X.B palantir.
XAlso,
X.B Saruman
Xmay turn a player's gems into gold pieces,
Xor scramble her/his stats.
X.TP 1.5i
X.B Thaumaturgist
Xcan transport a player.
X.TP 1.5i
X.B Balrog
Xinflicts damage by taking away
X.B experience
X, not
X.B energy.
X.TP 1.5i
X.B Vortex
Xmay take some
X.B manna.
X.TP 1.5i
X.B Nazgul
Xmay try to steal a
X.B ring
Xor neutralize part of one's
X.B brains.
X.TP 1.5i
X.B Tiamat
Xmay take half a players
X.B gold
Xand
X.B gems
Xand escape.
X.TP 1.5i
X.B Kobold
Xmay get nasty and steal one gold piece and run away.
X.TP 1.5i
X.B Shelob
Xmay bite, inflicting the equivalent of one
X.B poison.
X.TP 1.5i
X.B Assorted Faeries
XThese are killed if attacking someone carrying
X.B holy water.
XThese are
X.B Cluricaun, Fir Darrig, Fachan,
X.B Ghille Dhu, Bogle, Killmoulis,
Xand
X.B Bwca.
X.TP 1.5i
X.B Lamprey
Xmay bite, inflicting 1/2 of a
X.B poison.
X.TP 1.5i
X.B Shrieker
Xwill call one of its (much bigger) buddies if picked upon.
X.TP 1.5i
X.B Bonnacon
Xwill become bored with battle, fart, and run off.
X.TP 1.5i
X.B Smeagol
Xwill try to steal a
X.B ring
Xfrom a player, if given the chance.
X.TP 1.5i
X.B Succubus
Xmay inflict damage through a
X.B force field.
XThis subtracts from
X.B energy level
Xinstead of any shield the player may have thrown up.
XThis is a very easy way to die.
X.TP 1.5i
X.B Cerberus
Xloves metal and will steal all the metal treasures from
Xa player if able.
X.TP 1.5i
X.B Ungoliant
Xcan bite and poison.  This inflicts five
X.B poisons
X, and also takes one from the player's
X.B quickness.
X.TP 1.5i
X.B Jabberwock
Xmay tire of battle, and leave after calling one of his friends
X(
X.B Jubjub Bird
Xor
X.B Bandersnatch
X).
X.TP 1.5i
X.B Morgoth
Xactually
X.B Modnar
X, but reserved for
X.B council of the wise, valar,
Xand
X.B ex-valar.
XFights with
X.B Morgoth
Xend when either he or the player dies.	His characteristics
Xare calculated based upon the player's.  The player is given
Xthe chance to ally with him.  No magic, except
X.B force field
Xworks when battling
X.B Morgoth.
X.TP 1.5i
X.B Troll
Xmay regenerate its
X.B energy
Xand
X.B strength
Xwhile in battle.
X.TP 1.5i
X.B Wraith
Xmay make a player blind.
X.sh "Treasures"
XVarious treasure types are as follows:
X.TP 1.5i
X.B Type zero
X.I none
X.TP 1.5i
X.B Type one
X.I power booster
X\- adds manna.
X.br
X.I druid
X\- adds experience.
X.br
X.I holy orb
X\- subtracts 0.25 sin.
X.TP 1.5i
X.B Type two
X.I amulet
X\- protects from cursed treasure.
X.br
X.I holy water
X\- kills
X.B assorted faeries.
X.br
X.I hermit
X\- reduces sin by 25% and adds some manna.
X.TP 1.5i
X.B Type three
X.I shield
X\- adds to maximum
X.B energy level
X.br
X.I virgin
X\- used to subdue a
X.B unicorn
X, or to give much
X.B experience
X(and some
X.B sin
X).
X.br
X.I athelas
X\- subtracts one
X.B poison.
X.TP 1.5i
X.B Type four (scrolls)
X.I shield
X* \- throws a bigger than normal
X.B force field.
X.br
X.I invisible
X* \- puts the finder's
X.B quickness
Xto one million.
X.br
X.I ten fold strength
X* \- multiplies finder's strength by ten.
X.br
X.I pick monster
X\- allows finder to pick next monster to battle.
X.br
X.I general knowledge
X\- adds to finder's
X.B brains
Xand
X.B magic level.
X.PP
XAll the scrolls except
X.B general knowledge
Xautomatically call a monster.  Those that are marked with a * preserve any
Xspells that were already in effect.  Those that call monsters are only in
Xeffect while in battle.
X.TP 1.5i
X.B Type five
X.I dagger
X\- adds to
X.B strength.
X.br
X.I armour
X\- same as a
X.B shield,
Xbut bigger.
X.br
X.I tablet
X\- adds brains.
X.TP 1.5i
X.B Type six
X.I priest
X\- rests to maximum; adds 
X.B manna, brains;
Xand halves
X.B sin.
X.br
X.I Robin Hood
X\- increases
X.B shield
Xand adds permanently to
X.B strength.
X.br
X.I axe
X\- like
X.B dagger,
Xbut bigger.
X.TP 1.5i
X.B Type seven
X.I charm
X\- protects from cursed treasure (used before
X.B amulet
X); used in conjunction with
X.B blessing
Xto battle
X.B Dark Lord.
X.br
X.I Merlyn
X\- adds
X.B brains, magic,
Xand
X.B manna.
X.br
X.I war hammer
X\- like an
X.B axe,
Xbut bigger.
X.TP 1.5i
X.B Type eight
X.I healing potion
X\- sets
X.B poison
Xto -2, or subtracts two from
X.B poison,
Xwhichever is better.
X.br
X.I transporter
X\- allows finder to move anywhere.
X.br
X.I sword
X\- like a
X.B war hammer
X, but bigger.
X.TP 1.5i
X.B Type nine
X.I golden crown
X\- allows the player to become
X.B king,
Xby going to (0,0).
X.br
X.I blessing
X\- cuts
X.B sin
Xto 1/3, adds
X.B manna,
Xrests to max., and kills
X.B Dark Lord
Xwith a
X.B charm.
X.br
X.I quicksilver
X\- adds to 
X.B quickness.
X.TP 1.5i
X.B Type ten
X.I elven boots
X\- adds permanently to
X.B quickness.
X.TP 1.5i
X.B Type eleven
X.I palantir
X\- allows one to see all the other players; used by
X.B council of the wise
Xto seek the
X.B grail.
X.TP 1.5i
X.B Type twelve/thirteen
X.I ring
X\- allows one to hit much harder in battle, etc.
X.PP
XAny treasure type 10-13 monsters may instead carry a type nine treasure.
X.PP
XA monster may also be carrying
X.B gold
Xor
X.B gems.
XThese are used at
X.B trading posts
Xto buy things.	A
X.B gem
Xis worth 1000 gold pieces.  Too much
X.B gold
Xwill slow a player down.  One may carry 1000 plus 200 per
X.B level
Xof
X.B gold.
XA
X.B gem
Xweighs one half a gold piece.
XMonsters of treasure type 7 or higher may carry
X.B gems.
X.PP
XThe chance of a cursed treasure is based upon treasure type.
XThe more valuable treasures have a greater chance of being cursed.
XA cursed treasure knocks
X.B energy level
Xvery low, and adds 0.25
X.B poison.
X.sh "Rings"
X.B Rings
Xare only carried by
X.B nazguls
Xand
X.B Dark Lord.
XThey come in four different flavors.
XAll
X.B rings
Xrest the player to maximum and cause him/her to hit much harder
Xin battle with monsters (assuming one has chosen to use the
X.B ring
Xfor battle.)
X.PP
XTwo types of
X.B rings
Xare cursed and come either from
X.B nazguls
Xor
X.B Dark Lord.
XAfter a few times of using these types, the player falls
Xunder the control of the
X.B ring,
Xand strange, random things will occur.
XEventually, the player dies, and gives his/her name to a monster
Xon the file.
XDying before the
X.B ring
Xis used up also renames the monster.
X.PP
XThe two remaining types of
X.B rings
Xare much more benign.
XThe one from a
X.B nazgul
Xis good for a limited number of battle rounds, and will save
Xthe player from death if it was being used when he/she died.
XThe one from
X.B Dark Lord
Xis the same, except that it never is used up.
X.B rings
Xdisappear after saving someone from death.
XIn general, cursed
X.B rings
Xoccur much more often than normal ones.
XIt is usually not a good idea to pick one up.
XThe only way to get rid of a
X.B ring
Xis to have a monster steal it.
X.sh "King"
XA player may become
X.B king by finding a
X.I crown
Xand going to (0,0).  Players must have a
X.B level
Xin the range of 10 to 1000 to be able to find a
X.I crown.
X.PP
XOnce a player is king, he/she may do certain things while in 
Xthe Lord's Chamber (0,0).  These fall under the
X.B decree
X('0') option.
X.TP 1.5i
X.I transport
XThis is done to another player.  It randomly moves the affected
Xplayer about.  A
X.B charm
Xprotects from transports.
X.TP 1.5i
X.I curse
XThis is done to another player.  It is analogous to cursed treasure,
Xbut worse.  It inflicts two
X.B poison,
Xknocks
X.B energy level
Xvery low, and degrades the maximum energy.  It also
Xremoves a
X.B cloak.
XA
X.B blessing
Xprotects from king's curses.
X.TP 1.5i
X.I energy void
XThe king may put as many of these (within reason) scattered about
Xhis/her kingdom as he/she pleases.
XIf a player hits one, he/she loses
X.B manna, energy,
Xand
X.B gold.
XThe energy void disappears after being hit.
X.TP 1.5i
X.I bestow
XThis is also done to another player.  The king may
Xwish to reward one or more loyal subjects by sharing his/her
Xriches (
X.B gold
X).  Or it is a convenient way to dispose of some unwanted
Xdeadweight.
X.TP 1.5i
X.I collect taxes
XEveryone pays 10% tax on all
X.B gold
Xcollected, regardless of the existence of a
X.B king.
XThe king may collect this amount with this option.
X.PP
XThe
X.B king
Xmay also 
X.B teleport
Xanywhere for free by using the origin as a starting place.
X.sh "Special Places"
XCertain regions of the playing grid have different names.
XIn general, this is only to give the player some idea of
Xhis/her present location.  Some special places do exist.
X.TP 1.5i
X.I Trading Posts
XThese are located at |x| == |y| == n*n*100 for n = 1, 2...1000.
XTrading posts farther out have more things for sale.
XBe careful about cheating merchants there, as they have short
Xtempers.
XMerchants are dishonest about 5% of the time.
X.TP 1.5i
X.I Lord's Chamber
XThis is located at (0,0).  Only players with
X.B crowns
Xmay enter.
X.TP 1.5i
X.I Point of No Return
XThis is located beyond 1.2e+6 in any direction.
XThe only way to return from here is a
X.B transporter
Xor to have a
X.B valar
Xrelocate the player.
X.TP 1.5i
X.I Dead Marshes
XThis is a band located fairly distant from the origin.	The first
Xfourteen monsters (water monsters) can normally only be found here.
X.TP 1.5i
X.I Valhala
XThis place is where the
X.B valar
Xresides.  It is associated with no particular coordinate on the
Xplaying grid.
X.TP 1.5i
X.I Wormholes
XAt fixed locations on the grid are several holes to underground
Xdefects in the playing area.
XSixty-four chambers exist; sixteen of which open to the outside
Xworld.
XWhile in the wormholes, one move by going forward, backward,
Xleft, or right.
XOne can always undo a move by going in the opposite direction.
XThe wormholes are mappable.
XFor example, to move from the first wormhole {at (-400,0)} to
Xthe second wormhole, type 'LL'.
X.sh "Miscellaneous"
XThere are several bits of trivial knowledge which fall under this category.
X.PP
XA
X.I guru
Xwill never be disgusted with your
X.B sins
Xif they are less than one.
X.PP
XA
X.I medic
Xwants half of a player's
X.B gold
Xto be happy.  Offering more than one has, or a negative amount
Xwill anger the
X.I medic,
Xwho will make the player worse (add one
X.B poison
X).
X.PP
XThe
X.B Holy Grail
Xdoes little for those who are not ready to behold it.
XWhenever anyone finds it, it moves.
XIt is always located within 1e+6 in any compass direction of the origin.
X.PP
XThere is a maximum amount of
X.B manna
Xand
X.B charms
Xa player may posses, based upon
X.B level.
X.I Quicksilver
Xis always limited to to a maximum of 99.
X.PP
X.I Books
Xbought at a
X.B trading post
Xincrease 
X.B brains,
Xbased upon the number bought.
XIt is unwise, however to buy more than 1/10 of one's
X.B level
Xin books at a time.
X.PP
XPlayers over level 10000 are automatically retired.
X.PP
XA
X.I blindness
Xgoes away in random time.
X.sh "Inter-terminal Battle"
XWhen two player's coordinates correspond, they may engage in battle.
XIn general, the player with the highest
X.B quickness
Xgets the first hit.
XIf the two players are severely mis-matched, the stronger player
Xis drastically handicapped for the battle.
XIn order to protect from being stuck in an infinite loop,
Xthe player waiting for response may time out.  Options for battle are:
X.TP 1.5i
X.I fight
XInflicts damage upon other person.
X.TP 1.5i
X.I run away
XEscape from battle.  Has a 75% chance of working.
X.TP 1.5i
X.I power blast
XBattle spell.
X.TP 1.5i
X.I luckout
XOne-time chance to try to win against the foe.	Has a 10% chance of working.
X.PP
XSometimes waits for the other player may be excessive, because
Xhe/she may be battling a monster.  Upon slaying a player in battle
Xthe winner gets the other's
X.B experience
Xand treasures.
X.B Rings
Xdo not work for inter-terminal battle.
X.sh "Council of the Wise, Valar"
XA player automatically becomes a member of the
X.B council of the wise
Xupon reaching level 3000.  Members of the council cannot have
X.B rings.
XMembers of the council have a few extra options which they can exercise.
XThese fall under the
X.B intervention
X('8') option.
XOne is to
X.I heal
Xanother player.  This is just a quick way for that player to be rested
Xto maximum and lose a little
X.B poison.
XThe main purpose in life for members of the council is to seek the
X.B Holy Grail.
XThis is done with a
X.B palantir
Xunder the
X.I seek grail
Xoption.  The distance cited by the seek is accurate within 10%, in order
Xnot to make it too easy to find the grail.  Seeking costs 1000
X.B manna.
XA player must have infintesimally small
X.B sin,
Xor else it's all over upon finding the grail.
XIn order to help members of the council on their quest, they
Xmay
X.I teleport
Xwith greater ease.
X.PP
XUpon finding the grail, the player advance to position of
X.B valar.
XHe/she may then exercise more and niftier options under
X.I intervention.
XThese include all of the council members' option plus the
Xability to move other players about, bless them, and throw monsters at
Xthem.
X.B Valar
Xare essentially immortal, but are actually given five lives.
XIf these are used up, the player is left to die, and becomes an
X.B ex-valar.
X.B Valar
Xcannot
X.I move, teleport,
Xor call monsters.
XAny monsters which a
X.B valar
Xencounters are based upon his/her size.
XOnly one valar may exists at a time.
XA player replaces the exiting valar upon finding the grail.
XThe valar is then bumped back to the council of the wise.
X.SH BUGS
XMany.  The whole program is a hack.  The handling of incorrectly
Xexitted characters is a kludge.  The screen is set up assuming a 24 by 80
Xcharacter screen; no attempt was made to provide otherwise.
XIf the program is not set uid, it crashes on the first attempt to open a
Xdata file.
XIf any of the data items get too big for the allotted space on the screen,
Xno guarantees are made about what will happen.
XThere should be a way to change a character's name.
!EOR!