Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.1 6/24/83; site ttrda.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxj!mhuxn!ihnp4!nwuxg!cuuxc!cuuxb!ltuxa!ttrdc!ttrda!estes
From: estes@ttrda.UUCP (Edward Estes )
Newsgroups: net.sources.games
Subject: Phantasia 3.3 (part 3 of 3)
Message-ID: <127@ttrda.UUCP>
Date: Tue, 16-Jul-85 01:37:01 EDT
Article-I.D.: ttrda.127
Posted: Tue Jul 16 01:37:01 1985
Date-Received: Thu, 11-Jul-85 08:16:14 EDT
Organization: AT&T Teletype Corp., Skokie, IL
Lines: 1935

: This is a shar archieve.  Extract with sh, not csh.
: The rest of this file will extract:
: func2.c main.c monsters pathdefs.c setup.c func3.c
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;
X
X    move(6,0);
X    clrtoeol();
X    if (stat->typ < 20 && !su)	/* king */
X	{
X	addstr("0:Census  1:Transport  2:Curse  3:Energy Void  4:Bestow  5:Collect Taxes  ");
X	ch = getans(" ", TRUE);
X	move(6,0);
X	clrtoeol();
X	move(4,0);
X	switch (ch)
X	    {
X	    case '0':
X		showusers(TRUE);
X		return;
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		if ((loc = allocvoid()) > 20)
X		    mvaddstr(5,0,"Sorry, void creation limit reached.\n");
X		else
X		    voidupdate(&vbuf,loc);
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(5,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(4,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 = getans(" ", TRUE);
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 = dist(stat->x, vbuf.x, stat->y, vbuf.y);
X		    temp1 = floor(temp1 + roll(-temp1/10.0,temp1/5.0));
X		    mvprintw(5,0,"The palantir says the Grail is about %.0f away.\n",temp1);
X		    return;
X		    }
X		else
X		    {
X		    mvaddstr(5,0,"You need a palantir to seek the Grail.\n");
X		    return;
X		    }
X	    case '3':
X		mvaddstr(4,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(4,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(4,0,"Who do you want to %s ? ",cp);
X    getstring(aline,21);
X    trunc(aline);
X    if (strcmp(stat->name,aline))
X	{
X	if ((loc = findname(aline,&sbuf)) >= 0)
X	    {
X	    fclose(fp);
X	    if (sbuf.tampered)
X		{
X		mvaddstr(5,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(5,0,"It is done.\n");
X		return;
X		}
X	    }
X	else
X	    mvaddstr(5,0,"There is no one by that name.\n");
X	}
X    else
X	mvaddstr(5,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    if ((fp = fopen(voidfile,"r")) == NULL)
X	{
X	error(voidfile);
X	/*NOTREACHED*/
X	}
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(4,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 += roll(-12,25);
X	    stat->y += roll(-12,25);
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
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#ifndef SMALL
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#endif
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(<emp);
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	{
X	movelvl(stat);
X	if (stat->lvl > 5)
X	    timeout = TRUE;
X	}
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    if (stat->age > stat->degen * 5000)
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 (getans("T ", TRUE));
X    else
X	{
X	getans(" ", TRUE);
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 = 8;
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 = 0.0;
X    stat->istat = 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(6,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(5,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    mesg();
X    mvprintw(1,26,"%20.0f",myhits);
X    mvaddstr(7,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 = 8,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->istat = 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->istat = RAN;
X		goto LEAVE;
X		}
X	    mvprintw(lines++,0,"%s is still after you!",foename);
X	    stat->istat = 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->istat = 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->istat = 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 (stat->istat == 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    mesg();
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 (foe->istat)
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(22,0,"Timeout: waiting for response.  Do you want to wait ? ");
X    refresh();
X    ch = getans("NY", FALSE);
X    move(22,0);
X    clrtobot();
X    if (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 = 8,0);
X	clrtobot();
X	}
X    if (foe->istat == 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(4,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 SYS3
X    signal(SIGINT,SIG_IGN);
X#endif
X#ifdef SYS5
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 = getans("NY", FALSE);
X	if (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 = getans("NY", FALSE);
X	if (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 SYS3
X    signal(SIGINT,interrupt);
X#endif
X#ifdef SYS5
X    signal(SIGINT,interrupt);
X#endif
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(<ime);
X    today = localtime(<ime)->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,"");
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 - main.c
sed 's/^X//' > main.c << '!EOR!'
X/*
X * Phantasia 3.3 -- Interterminal fantasy game
X *
X * Edward A. Estes
X * AT&T Teletype Corporation, July 9, 1985
X */
X
X/* DISCLAIMER:
X *
X * This game is distributed for free as is.  It is not guaranteed to work
X * in every conceivable environment.  It is not even guaranteed to work
X * in ANY environment.
X *
X * This game is distributed without notice of copyright, therefore it
X * may be used in any manner the recipient sees fit.  However, the
X * author assumes no responsibility for maintaining or revising this
X * game, in its original form, or any derivitives thereof.
X *
X * The author shall not be responsible for any loss, cost, or damage,
X * including consequential damage, caused by reliance on this material.
X *
X * The author makes no warranties, express or implied, including warranties
X * of merchantability or fitness for a particular purpose or use.
X *
X * AT&T and AT&T Teletype Corporation are in no way connected with this
X * game.
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, timeout;
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 */
X#ifndef SMALL
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#endif
X
Xmain(argc,argv) 	    /* Phantasia main routine */
Xint argc;
Xchar	*argv[];
X{
Xstatic	struct	stats	charac;
Xchar	aline[200], *login = NULL;
Xdouble	x = 0.0, y = 0.0;
Xint ch, ch2, 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[25];
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 = FALSE;
X    fghting = FALSE;
X    timeout = FALSE;
X    users = 0;
X    while (--argc && (*++argv)[0] == '-')
X	switch ((*argv)[1])
X	    {
X	    case 'h':	    /* help */
X		if ((fp = fopen(helpfile, "r")) != NULL)
X		    {
X		    while (fgets(aline, 200, fp))
X		    fputs(aline, stdout);
X		    fclose(fp);
X		    }
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(FALSE);
X		    exit(0);
X		    /*NOTREACHED*/
X		case 'p':	    /* purge old players */
X		    purge();
X		    exit(0);
X		    /*NOTREACHED*/
X		case 'S':
X		    su = (getuid() == UID);
X		    break;
X		case 'b':
X		    show_sb();
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(21,24,"Do you have a character to run? ");
X    ch = getans("NY", FALSE);
X    if (ch == 'Y')
X	fileloc = findchar(&charac);
X    else
X	{
X	initchar(&charac);
X	clear();
X	mvaddstr(4,21,"Which type of character do you want:");
X	mvaddstr(8,4,"1:Magic User  2:Fighter  3:Elf  4:Dwarf  5:Halfling  6:Experimento  ? ");
X	ch = getans("2134567", FALSE);
X	do
X	    {
X	    genchar(&charac,ch);
X	    mvprintw(12,14,"Strength:  %2.0f  Mana       : %3.0f  Quickness   :  %2d",
X	    charac.str,charac.man,charac.quk);
X	    mvprintw(13,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(14,14,"Type '1' to keep >");
X		ch2 = getans(" ", TRUE);
X		}
X	    else
X		break;
X	    }
X	while (ch2 != '1');
X	if (charac.typ == 6)
X	    for (;;)
X		{
X		mvaddstr(16,0,"Enter the X Y coordinates of your experimento ? ");
X		getstring(aline,80);
X		sscanf(aline,"%F %F",&charac.x,&charac.y);
X		if (abs(charac.x) > 1.2e6 || abs(charac.y) > 1.2e6)
X		    mvaddstr(17,0,"Invalid coordinates.  Try again.\n");
X		else
X		    break;
X		}
X	for (;;)
X	    {
X	    mvaddstr(18,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	    trunc(charac.name);
X	    if (charac.name[0] == '\0')
X		mvaddstr(19,0,"Invalid name.");
X	    else if (findname(charac.name, (struct stats *) NULL) >= 0)
X		mvaddstr(19,0,"Name already in use.");
X	    else
X		break;
X	    addstr("  Pick another.\n");
X	    }
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 your character saved,\n");
X	printw("you may quit and mail your reason to '%s'.\n",WIZARD);
X	addstr("Otherwise, continuing spells certain death.\n");
X	addstr("Do you want to quit ? ");
X	ch = getans("YN", FALSE);
X	if (ch== 'Y')
X	    {
X	    charac.tampered = charac.quk;	/* store this away */
X	    charac.quk = -100;
X	    leave(&charac);
X	    /*NOTREACHED*/
X	    }
X	death(&charac);
X	}
X    charac.status = PLAYING;
X    if (charac.lvl > 5)
X	timeout = TRUE;
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);
X#endif
X#ifdef	SYS3
X    signal(SIGINT,interrupt);
X#endif
X#ifdef	SYS5
X    signal(SIGINT,interrupt);
X#endif
X
X    /* all set for now */
X
XTOP:
X    switch (setjmp(mainenv))
X	{
X	case QUIT:
X#ifdef	BSD41
X	    sigrelse(SIGINT);
X#endif
X#ifdef	BSD42
X	    signal(SIGINT,interrupt);
X#endif
X#ifdef	SYS3
X	    signal(SIGINT,interrupt);
X#endif
X#ifdef	SYS5
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);
X#endif
X#ifdef	SYS3
X	    signal(SIGINT,interrupt);
X#endif
X#ifdef	SYS5
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(5,0,"You're not allowed in the Lord's Chamber without a crown.\n");
X	changed = TRUE;
X	charac.x = charac.y = 10 + roll(8, 5);
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    mesg();
X    printstats(&charac);
X    move(6,0);
X#ifndef SMALL
X    if (!wmhl)
X#endif
X	{
X	if (throne)
X	    kingstuff(&charac);
X	addstr("NSEW1:Move  2:Players  3:Talk  4:Stats  5:Quit  ");
X	if (charac.lvl >= 7 && charac.mag >= 20)
X	    addstr("6:Cloak  ");
X	if (charac.lvl >= 12 && charac.mag >= 40)
X	    addstr("7:Teleport  ");
X	if (charac.typ > 20)
X	    addstr("8:Intervene");
X	ch = gch(charac.rng.type);
X	mvaddstr(4,0,"\n\n");
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	move(7,0);
X	clrtobot();
X	if (charac.typ == 99 && (ch == '1' || ch == '7'))
X	    ch = ' ';
X	switch (ch2 = 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		charac.nrg += (charac.mxn+charac.shd)/15+charac.lvl/3+2;
X		charac.nrg = min(charac.nrg,charac.mxn + charac.shd);
X		if (charac.status != CLOAKED)
X		    {
X		    charac.man += circ(charac.x,charac.y)/4;
X		    charac.man += charac.lvl/6;
X		    rndattack();
X		    }
X		break;
X	    case '1':   /* move */
X		for (loop = 3; loop; --loop)
X		    {
X		    mvaddstr(4,0,"X Y Coordinates ? ");
X		    getstring(aline,80);
X		    if (sscanf(aline,"%F %F",&x,&y) != 2)
X			mvaddstr(5,0,"Try again\n");
X		    else if (dist(charac.x, x, 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		mvaddstr(4,0,"Message ? ");
X		getstring(aline, 80);
X		fp = fopen(messfile, "w");
X		if (*aline)
X		    fprintf(fp, "%s: %s", charac.name, aline);
X		fclose(fp);
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 < 7 || charac.mag < 20)
X		    illcmd();
X		else if (charac.status == CLOAKED)
X		    charac.status = PLAYING;
X		else if (charac.man < 35)
X		    {
X		    mvaddstr(5,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 < 12 || charac.mag < 40)
X		    illcmd();
X		else 
X		    for (loop = 3; loop; --loop)
X			{
X			mvaddstr(4,0,"X Y Coordinates ? ");
X			getstring(aline,80);
X			if (sscanf(aline,"%F %F",&x,&y) == 2)
X			    if ((temp = dist(charac.x,x,charac.y,y))
X				> (charac.lvl+charac.mag)*20+((charac.typ > 30) ? 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#ifndef SMALL
X    else
X	{
X	addstr("F:Forward  B:Back  R:Right  L:Left  Q:Quit  T:Talk  P:Players  S:Stats  ");
X	ch = getans(" ", TRUE);
X	move(6,0);
X	clrtobot();
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	switch (ch)
X	    {
X	    default:	/* rest */
X		charac.nrg += (charac.mxn+charac.shd)/15+charac.lvl/3+2;
X		charac.nrg = min(charac.nrg,charac.mxn + charac.shd);
X		if (charac.status != CLOAKED)
X		    charac.man += charac.lvl/5;
X		break;
X	    case 'F':
X		temp = w_h[charac.wormhole].f;
X		goto CHKMOVE;
X	    case 'B':
X		temp = w_h[charac.wormhole].b;
X		goto CHKMOVE;
X	    case 'R':
X		temp = w_h[charac.wormhole].r;
X		goto CHKMOVE;
X	    case 'L':
X		temp = w_h[charac.wormhole].l;
X		goto CHKMOVE;
X	    case 'Q':
X		leave(&charac);
X		/*NOTREACHED*/
X	    case 'T':
X		mvaddstr(4,0,"Message ? ");
X		getstring(aline, 80);
X		fp = fopen(messfile, "w");
X		if (*aline)
X		    fprintf(fp, "%s: %s", charac.name, aline);
X		fclose(fp);
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:
X	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#endif
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 
X#include    /* 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    30	/* 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 > 12 && tp->tm_hour < 16))	/* 1-4 pm */
X	    return (FALSE);
X    /* check # of users */
X    if ((fp = fopen("/etc/utmp","r")) != NULL)
X	{
X	while (fread((char *) &ubuf,sizeof(ubuf),1,fp))
X#ifdef	SYS5
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	}
X    return (TRUE);
X}
X#endif
!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
Xan  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            100     25      7       264     1257    4       0       13
Xa Jubjub Bird           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 - pathdefs.c
sed 's/^X//' > pathdefs.c << '!EOR!'
X/*
X * pathdefs.c
X *
X * Edit these values to put things in different places.
X */
X
X#include "phant.h"
X
Xchar	monsterfile[] = PATH/monsters",
X	peoplefile[] = PATH/characs",
X	gameprog[] = PATH/phantasia",
X	messfile[] = PATH/mess",
X	lastdead[] = PATH/lastdead",
X	helpfile[] = PATH/phant.help",
X	motd[] = PATH/motd",
X	goldfile[] = PATH/gold",
X	voidfile[] = PATH/void",
X#ifdef ENEMY
X	enemyfile[] = PATH/enemy",
X#endif
X	sbfile[] = PATH/scoreboard";
!EOR!
echo extracting - setup.c
sed 's/^X//' > setup.c << '!EOR!'
X/*
X * setup.c  Program to set up all files for Phantasia
X *
X *	This program tries to verify the parameters specified in
X *	the Makefile.  Since Phantasia assumes its files exist,
X *	simple errors can result in core dumps.
X *
X *	This program tries to check against this.
X * 
X *	Note that this is not fool-proof, and that this could
X *	be much more clever in checking everything.
X */
X
X#include "phant.h"
X#include 
X#include 
X
Xmain(argc,argv) 		/* program to init. files for Phantasia */
Xint argc;
Xchar	**argv;
X{
XFILE	*fp;
Xstruct	stats	sbuf;
Xstruct	nrgvoid grail;
Xstruct	stat	fbuf;
Xregister    int loop;
Xchar	stbuf[128];
X
X    srand((int) time(NULL));	/* prime random numbers */
X    /* try to check RAND definition */
X    for (loop = 1000; loop; loop--)
X	{
X	if (rand() > ((int) RAND))
X	    {
X	    sprintf(stbuf,"%.1f",(double) RAND);
X	    Error("%s is a bad value for RAND.\n",stbuf);
X	    }
X	}
X    umask(077);
X    /* check where Phantasia lives */
X    if (stat(PATH",&fbuf) < 0)
X	{
X	perror(PATH");
X	exit(1);
X	/*NOTREACHED*/
X	}
X    if (fbuf.st_mode & S_IFDIR == 0)
X	Error("%s is not a directory.\n",PATH");
X    /* try to create data files */
X    if ((fp = fopen(goldfile,"w")) == NULL)
X	Error("cannot create %s.\n",goldfile);
X    else
X	fclose(fp);
X    if ((fp = fopen(motd,"w")) == NULL)
X	Error("cannot create %s.\n",motd);
X    else
X	fclose(fp);
X    if ((fp = fopen(messfile,"w")) == NULL)
X	Error("cannot create %s.\n",messfile);
X    else
X	fclose(fp);
X    /* do not reset character file if it already exists */
X    if (stat(peoplefile,&fbuf) < 0)
X	{
X	buildchar(&sbuf);
X	strcpy(sbuf.name,"");
X	if ((fp = fopen(peoplefile,"w")) == NULL)
X	    Error("cannot create %s.\n",peoplefile);
X	else
X	    {
X	    fwrite(&sbuf,sizeof(sbuf),1,fp);
X	    fclose(fp);
X	    }
X	}
X    grail.active = TRUE;
X    grail.x = roll(-1.0e6,2.0e6);
X    grail.y = roll(-1.0e6,2.0e6);
X    if ((fp = fopen(voidfile,"w")) == NULL)
X	Error("cannot create %s.\n",voidfile);
X    else
X	{
X	fwrite(&grail,sizeof(grail),1,fp);
X	fclose(fp);
X	}
X    if ((fp = fopen(lastdead,"w")) == NULL)
X	Error("cannot create %s.\n",lastdead);
X    else
X	{
X	fputs(" ",fp);
X	fclose(fp);
X	}
X#ifdef ENEMY
X    if ((fp = fopen(enemyfile,"w")) == NULL)
X	Error("cannot create %s.\n",enemyfile);
X    else
X	fclose(fp);
X#endif
X    if ((fp = fopen(sbfile,"w")) == NULL)
X	Error("cannot create %s.\n",sbfile)
X    else
X	fclose(fp);
X    if (getuid() != UID)
X	fprintf(stderr,"Warning: UID (%d) is not equal to current uid.\n",UID);
X    exit(0);
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}
X
XError(str,file)     /* print an error message, and exit */
Xchar	*str, *file;
X{
X    fprintf(stderr,"Error: ");
X    fprintf(stderr,str,file);
X    exit(1);
X    /*NOTREACHED*/
X}
!EOR!
echo extracting - func3.c
sed 's/^X//' > func3.c << '!EOR!'
X/*
X * func3.c	Phantasia support routines
X */
X#include "phant.h"
X
Xjmp_buf btimeout;
Xint catchalarm();
X
Xint getans(choices, def)	/* get a one character option from keyboard */
Xchar	*choices;
Xbool	def;
X{
Xint ch, loop, oldx, oldy;
Xchar	*cptr;
X
X    getyx(stdscr, oldy, oldx);
X    alarm(0);
X
X    for (loop = 3; loop; --loop)
X	if (setjmp(btimeout))
X	    if (def)
X		return(*choices);
X	    else if (loop > 1)
X		goto YELL;
X	    else
X		break;
X	else
X	    {
X	    clrtoeol();
X	    refresh();
X#ifdef BSD41
X	    sigset(SIGALRM, catchalarm);
X#else
X	    signal(SIGALRM, catchalarm);
X#endif
X	    if (timeout)
X		alarm(7);
X	    else
X		alarm(600);
X	    ch = getch();
X	    alarm(0);
X	    if ((cptr = strchr(choices, toupper(ch))) != NULL)
X		return(*cptr);
X	    else if (def)
X		return(toupper(ch));
X	    else if (!def && loop > 1)
X		{
XYELL:		mvprintw(oldy+1,0,"Please choose one of : [%s]\n", choices);
X		move(oldy, oldx);
X		clrtoeol();
X		continue;
X		}
X	    else
X		break;
X	    }
X    return(*choices);
X}
X
Xint catchalarm()
X{
X    longjmp(btimeout, 1);
X}
X
Xvoid	error(whichfile)
Xchar	*whichfile;
X{
Xextern int errno;
X
X    clear();
X    printw("An unrecoverable error has occurred reading %s.  (errno = %d)\n", whichfile, errno);
X    addstr("Please run 'setup' to determine the problem.\n");
X    exit1();
X    /*NOTREACHED*/
X}
X
X
Xvoid	mesg()
X{
XFILE	*fp;
Xchar	s[100];
X
X    move(3,0);
X    clrtoeol();
X    if ((fp = fopen(messfile, "r")) != NULL)
X	{
X	if (fgets(s,100,fp))
X	    addstr(s);
X	fclose(fp);
X	}
X}
X
Xdouble	dist(x1, x2, y1, y2)
Xdouble	x1, x2, y1, y2;
X{
Xdouble	deltax, deltay;
X
X    deltax = x1 - x2;
X    deltay = y1 - y2;
X    return(sqrt(deltax * deltax + deltay * deltay));
X}
X
Xvoid scoreboard(stat)		    /* enter login into scoreboard */
Xreg struct stats *stat;
X{
Xstatic	struct	sb_ent sbuf;
XFILE	*fp;
Xreg int loc = 0;
Xbool	found = FALSE;
X
X    if ((fp = fopen(sbfile, "r")) != NULL)
X	{
X	while (fread((char *) &sbuf, sizeof(sbuf), 1, fp))
X	    if (!strcmp(stat->login, sbuf.login))
X		{
X		found = TRUE;
X		break;
X		}
X	    else
X		++loc;
X	fclose(fp);
X	}
X
X    /*
X     * At this point, 'loc' will either indicate a point beyond
X     * the end of file, or the place where the previous entry
X     * was found.
X     */
X
X    if ((!found) || stat->lvl > sbuf.level)
X	{
X	strcpy(sbuf.login, stat->login);
X	strcpy(sbuf.name, stat->name);
X	sbuf.level = stat->lvl;
X	sbuf.type = stat->typ;
X	}
X    if ((fp = fopen(sbfile, ACCESS)) == NULL)
X	{
X	error(sbfile);
X	/*NOTREACHED*/
X	}
X    fseek(fp, (long) (loc * sizeof(sbuf)), 0);
X    fwrite((char *) &sbuf, sizeof(sbuf), 1, fp);
X    fclose(fp);
X}
X
X
Xvoid show_sb()			/* printout the scoreboard */
X{
Xstatic	struct	sb_ent	sbuf;
XFILE	*fp;
X
X    if ((fp = fopen(sbfile, "r")) != NULL)
X	while (fread((char *) &sbuf, sizeof(sbuf), 1, fp))
X	    printf("%-20s   Login: %-9s  Level: %6d  Type: %3d\n",
X		sbuf.name, sbuf.login, sbuf.level, sbuf.type);
X}
X
Xint ill_sig(whichsig)		/* come here on bad signals */
Xint whichsig;
X{
X    clear();
X    printw("Error: caught signal # %d.\n", whichsig);
X    exit1();
X    /*NOTREACHED*/
X}
!EOR!