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!