Phantasia (part 3 of 3)
8-01-83"Edward E 9723i
estes at tty3b.UUCP
Sat Sep 8 08:14:53 AEST 1984
------------CUT---------------CUT--------------CUT-------------CUT----------
: This is a shar archieve. Extract with sh, not csh.
: The rest of this file will extract:
: func2.c main.c fight.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 = 0;
X
X move(3,0);
X clrtoeol();
X if (stat->typ < 20 && !su) /* king */
X {
X addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
X ch = rgetch();
X move(3,0);
X clrtoeol();
X switch (ch)
X {
X case '1':
X arg = TRANSPORT;
X cp = "transport";
X break;
X case '2':
X arg = CURSED;
X cp = "curse";
X break;
X case '3':
X addstr("Enter the X Y coordinates of void ? ");
X getstring(aline,30);
X sscanf(aline,"%F %F",&temp1,&temp2);
X vbuf.x = floor(temp1);
X vbuf.y = floor(temp2);
X vbuf.active = TRUE;
X voidupdate(&vbuf,allocvoid());
X goto EXIT;
X case '4':
X arg = GOLD;
X addstr("How much gold to bestow ? ");
X temp1 = inflt();
X if (temp1 > stat->gld || temp1 < 0)
X {
X mvaddstr(6,0,"You don't have that !\n");
X return;
X }
X stat->gld -= floor(temp1);
X cp = "give gold to";
X break;
X case '5':
X fp = fopen(goldfile,"r");
X fread((char *) &temp1,sizeof(double),1,fp);
X fclose(fp);
X mvprintw(6,0,"You have collected %.0f in gold.\n",temp1);
X stat->gld += floor(temp1);
X fp = fopen(goldfile,"w");
X temp1 = 0.0;
X fwrite((char *) &temp1,sizeof(double),1,fp);
X fclose(fp);
X return;
X default:
X return;
X }
X }
X else /* council of wise, valar, etc. */
X {
X addstr("1:Heal ");
X if (stat->pal || su)
X addstr("2:Seek Grail ");
X if (stat->typ == 99 || su)
X addstr("3:Throw Monster 4:Relocate 5:Bless ");
X if (su)
X addstr("6:Vaporize ");
X ch = rgetch();
X if (!su && ch > '2' && stat->typ != 99)
X {
X illcmd();
X return;
X }
X switch (ch)
X {
X case '1':
X arg = HEAL;
X cp = "heal";
X break;
X case '2':
X if (stat->pal)
X {
X fp = fopen(voidfile,"r");
X fread((char *) &vbuf,sizeof(vbuf),1,fp);
X fclose(fp);
X temp1 = hypot(stat->x - vbuf.x,stat->y - vbuf.y);
X temp1 = floor(temp1 + roll(-temp1/10.0,temp1/5.0));
X mvprintw(6,0,"The palantir says the Grail is about %.0f away.\n",temp1);
X return;
X }
X else
X {
X mvaddstr(6,0,"You need a palantir to seek the Grail.\n");
X return;
X }
X case '3':
X mvaddstr(3,0,"Which monster [0-99] ? ");
X temp1 = inflt();
X temp1 = max(0,min(99,temp1));
X cp = "throw a monster at";
X arg = MONSTER;
X break;
X case '4':
X mvaddstr(3,0,"New X Y coordinates ? ");
X getstring(aline,30);
X sscanf(aline,"%F %F",&temp1,&temp2);
X cp = "relocate";
X arg = MOVED;
X break;
X case '5':
X arg = BLESS;
X cp = "bless";
X break;
X case '6':
X if (su)
X {
X cp = "vaporize";
X arg = VAPORIZED;
X break;
X }
X default:
X return;
X }
X }
X mvprintw(3,0,"Who do you want to %s ? ",cp);
X getstring(aline,21);
X trunc(aline);
X if (strcmp(stat->name,aline))
X {
X fp = fopen(peoplefile,"r");
X while (fread((char *) &sbuf,sizeof(sbuf),1,fp))
X if (strcmp(aline,sbuf.name))
X ++loc;
X else
X {
X fclose(fp);
X if (sbuf.tampered)
X {
X mvaddstr(6,0,"That person has something pending already.\n");
X return;
X }
X else
X {
X sbuf.tampered = arg;
X sbuf.scratch1 = floor(temp1);
X sbuf.scratch2 = floor(temp2);
X update(&sbuf,loc);
XEXIT: mvaddstr(6,0,"It is done.\n");
X return;
X }
X }
X fclose(fp);
X mvaddstr(6,0,"There is no one by that name.\n");
X }
X else
X mvaddstr(6,0,"You may not do it to yourself!\n");
X}
X
Xvoid checktampered(stat) /* see if decree'd etc. */
Xreg struct stats *stat;
X{
Xstruct nrgvoid vbuf;
Xstruct stats sbuf;
XFILE *fp;
Xreg int loc = 0;
X
X /* first check for energy voids */
X fp = fopen(voidfile,"r");
X while (fread((char *) &vbuf,sizeof(vbuf),1,fp))
X if (vbuf.active && vbuf.x == stat->x && vbuf.y == stat->y)
X {
X fclose(fp);
X if (loc)
X {
X vbuf.active = FALSE;
X voidupdate(&vbuf,loc);
X tampered(stat,NRGVOID,&sbuf);
X }
X else if (stat->status != CLOAKED)
X tampered(stat,GRAIL,&sbuf);
X break;
X }
X else
X ++loc;
X fclose(fp);
X /* now check for other things */
X statread(&sbuf,fileloc);
X if (sbuf.tampered)
X tampered(stat,sbuf.tampered,&sbuf);
X}
X
Xvoid voidupdate(vp,loc) /* update an energy void */
Xreg struct nrgvoid *vp;
Xreg int loc;
X{
XFILE *fp;
X
X fp = fopen(voidfile,ACCESS);
X fseek(fp,(long) loc*sizeof(*vp),0);
X fwrite((char *) vp,sizeof(*vp),1,fp);
X fclose(fp);
X}
X
Xint allocvoid() /* find a space to put an energy void */
X{
XFILE *fp;
Xreg int loc = 0;
Xstruct nrgvoid vbuf;
X
X fp = fopen(voidfile,"r");
X while (fread((char *) &vbuf,sizeof(vbuf),1,fp))
X if (vbuf.active)
X ++loc;
X else
X {
X fclose(fp);
X return (loc);
X }
X fclose(fp);
X return (loc);
X}
X
Xvoid statread(stat,loc) /* read a charac. structure */
Xreg struct stats *stat;
Xreg int loc;
X{
XFILE *fp;
X
X fp = fopen(peoplefile,"r");
X fseek(fp,(long) loc * sizeof(*stat),0);
X fread((char *) stat,sizeof(*stat),1,fp);
X fclose(fp);
X}
X
Xvoid tampered(stat,what,bufp) /* decree'd, intervened, etc. */
Xreg struct stats *stat, *bufp;
Xshort what;
X{
Xstruct nrgvoid vbuf;
Xreg int loc;
Xstruct stats sbuf;
XFILE *fp;
X
X changed = TRUE;
X move(6,0);
X stat->tampered = OFF;
X switch ((int) what)
X {
X case NRGVOID:
X addstr("You've hit an energy void !\n");
X stat->man /= 3;
X stat->nrg /= 2;
X stat->gld = floor(stat->gld/1.25) + 0.1;
X stat->x += 10;
X break;
X case TRANSPORT:
X addstr("The king transported you ! ");
X if (stat->chm)
X {
X addstr("But your charm save you. . .\n");
X --stat->chm;
X }
X else
X {
X stat->x += roll(-50,100) * circ(stat->x,stat->y);
X stat->y += roll(-50,100) * circ(stat->x,stat->y);
X addch('\n');
X }
X break;
X case GOLD:
X printw("The king has bestowed %.0f gold pieces on you !\n",bufp->scratch1);
X stat->gld += bufp->scratch1;
X break;
X case CURSED:
X addstr("You've been cursed ! ");
X if (stat->bls)
X {
X addstr("But your blessing saved you. . .\n");
X stat->bls = FALSE;
X }
X else
X {
X addch('\n');
X stat->psn += 2;
X stat->nrg = 10;
X stat->mxn *= 0.95;
X stat->status = PLAYING;
X }
X break;
X case VAPORIZED:
X addstr("Woops! You've been vaporized!\n");
X death(stat);
X break;
X case MONSTER:
X addstr("The Valar zapped you with a monster!\n");
X paws(7);
X fight(stat,(int) bufp->scratch1);
X return;
X case BLESS:
X addstr("The Valar has blessed you!\n");
X stat->nrg = (stat->mxn *= 1.05) + stat->shd;
X stat->man += 500;
X stat->str += 0.5;
X stat->brn += 0.5;
X stat->mag += 0.5;
X stat->psn = min(0.5,stat->psn);
X break;
X case MOVED:
X addstr("You've been relocated. . .\n");
X stat->x = bufp->scratch1;
X stat->y = bufp->scratch2;
X break;
X case HEAL:
X addstr("You've been healed!\n");
X stat->psn -= 0.25;
X stat->nrg = stat->mxn + stat->shd;
X break;
X case STOLEN:
X addstr("You'Ve been bumped off as Valar!\n");
X stat->typ = 20 + roll(1,6);
X break;
X case GRAIL:
X addstr("You have found The Holy Grail!!\n");
X if (stat->typ < 20)
X {
X addstr("However, you are not experienced enough to behold it.\n");
X stat->sin *= stat->sin;
X stat->man += 1000;
X }
X else if (stat->typ == 99 || stat->typ == 90)
X {
X addstr("You have made it to the position of Valar once already.\n");
X addstr("The Grail is of no more use to you now.\n");
X }
X else
X {
X addstr("It is now time to see if you are worthy to behold it. . .\n");
X refresh();
X sleep(4);
X if (rnd() / 2.0 < stat->sin)
X {
X addstr("You blew this one!\n");
X stat->str = stat->man = stat->quk = stat->nrg = stat->mxn = stat->x = stat->y =
X stat->mag = stat->brn = stat->exp =1;
X stat->lvl = 0;
X }
X else
X {
X addstr("You made to position of Valar!\n");
X stat->typ = 99;
X fp = fopen(peoplefile,"r");
X loc = 0;
X while (fread((char *) &sbuf,sizeof(sbuf),1,fp))
X if (sbuf.typ == 99)
X {
X sbuf.tampered = STOLEN;
X update(&sbuf,loc);
X break;
X }
X else
X ++loc;
X fclose(fp);
X }
X }
X vbuf.active = TRUE;
X vbuf.x = roll(-1e6,2e6);
X vbuf.y = roll(-1e6,2e6);
X voidupdate(&vbuf,0);
X break;
X }
X}
X
Xvoid adjuststats(stat) /* make sure things are within limits, etc. */
Xreg struct stats *stat;
X{
Xlong ltemp;
Xreg int temp;
X stat->x = floor(stat->x);
X stat->y = floor(stat->y);
X valhala = (stat->typ == 99);
X throne = (stat->x == 0.0 && stat->y == 0.0);
X temp = abs(stat->x)/400;
X if (temp > 16)
X temp = 0;
X if (stat->y == 0.0 && !throne && !valhala && temp == abs(stat->x)/400 && sgn(stat->x) == (int) pow(-1.0, (double) temp))
X {
X if (!wmhl)
X stat->wormhole = temp;
X wmhl = TRUE;
X }
X else
X wmhl = FALSE;
X speed = stat->quk + stat->quks - spdcalc(stat->lvl,stat->gld,stat->gem);
X strength = stat->str + stat->swd - strcalc(stat->str,stat->psn);
X time(<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 movelvl(stat);
X stat->gld = floor(stat->gld) + 0.1;
X stat->gem = floor(stat->gem) + 0.1;
X if (stat->rng.type)
X stat->nrg = stat->mxn + stat->shd;
X if (stat->rng.type && stat->rng.duration <= 0) /* clean up rings */
X switch (stat->rng.type)
X {
X case DLBAD:
X case NAZBAD:
X stat->rng.type = SPOILED;
X stat->rng.duration = roll(10,25);
X break;
X case NAZREG:
X stat->rng.type = NONE;
X break;
X case SPOILED:
X death(stat);
X break;
X } /* DLREG is ok, so do nothing with it */
X stat->nrg += (stat->mxn+stat->shd)/15+stat->lvl/3+2;
X stat->nrg = min(stat->nrg,stat->mxn + stat->shd);
X if (stat->age > stat->degen * 2500)
X {
X ++stat->degen;
X if (stat->quk > 23)
X --stat->quk;
X stat->str *= 0.97;
X stat->brn *= 0.95;
X stat->mag *= 0.97;
X stat->mxn *= 0.95;
X if (stat->quks)
X --stat->quks;
X stat->swd *= 0.93;
X stat->shd *= 0.95;
X }
X}
X
Xvoid checkinterm(stat) /* see if other person on same x,y */
Xreg struct stats *stat;
X{
XFILE *fp;
Xstruct stats sbuf;
Xreg int foeloc = 0;
X
X users = 0;
X fp = fopen(peoplefile,"r");
X while (fread((char *) &sbuf,sizeof(sbuf),1,fp))
X {
X if (sbuf.status && (sbuf.status != CLOAKED || sbuf.typ != 99))
X {
X ++users;
X if (stat->x == sbuf.x && stat->y == sbuf.y
X && foeloc != fileloc && sbuf.typ != 99
X && stat->typ !=99 && !stat->wormhole && !sbuf.wormhole)
X {
X fclose(fp);
X interm(stat,foeloc);
X return;
X }
X }
X ++foeloc;
X }
X fclose(fp);
X}
X
Xint gch(rngtyp) /* get a character from terminal, but check ring if crazy */
Xshort rngtyp;
X{
X refresh();
X if (abs(rngtyp) != SPOILED)
X return (getch());
X else
X {
X getch();
X return (roll(0,5) + '0');
X }
X}
X
Xint rngcalc(chartyp) /* pick a duration of a ring */
Xshort chartyp;
X{
Xstatic int rngtab[] = { 0, 10, 20, 13, 25, 40, 20};
X
X if (chartyp > 10)
X chartyp -= 10;
X return (rngtab[chartyp - 1]);
X}
X
Xvoid interm(stat,who) /* interterminal battle routine */
Xreg struct stats *stat;
Xint who;
X{
X#define MAXWAIT 20
X#define BLOCK sizeof(struct stats)
X#define RAN 1
X#define STUCK 2
X#define BLEWIT 3
X#define KILLED 4
X#define readfoe() fseek(fin,foeplace,0); \
X fread((char *) foe,BLOCK,1,fin)
X#define updateme() fseek(fout,myplace,0); \
X fwrite((char *) stat,BLOCK,1,fout); \
X fflush(fout)
X
XFILE *fin, *fout; /* pointers for input, output */
Xdouble temp, foespeed, oldhits = 0.0, myhits;
Xstruct stats sbuf;
Xreg struct stats *foe;
Xreg int loop, lines = 5;
Xint ch;
Xlong myplace, foeplace;
Xshort oldtags;
Xbool luckout = FALSE;
Xchar foename[21];
X
X fghting = TRUE;
X mvaddstr(4,0,"Preparing for battle!\n");
X refresh();
X /* set up variables, file, etc. */
X myplace = fileloc * BLOCK;
X foeplace = who * BLOCK;
X fin = fopen(peoplefile,"r");
X setbuf(fin, (char *) NULL);
X fout = fopen(peoplefile,ACCESS);
X stat->status = INBATTLE;
X myhits = stat->nrg;
X stat->tampered = oldtags = 1; /* this must be non-zero to prevent a king or valar from trashing it */
X stat->scratch1 = stat->scratch2 = 0.0;
X updateme();
X foe = &sbuf;
X readfoe();
X foespeed = foe->quk + foe->quks - spdcalc(foe->lvl,foe->gld,foe->gem);
X if (abs(stat->lvl - foe->lvl) > 20) /* see if greatly mismatched */
X {
X temp = ((double) (stat->lvl - foe->lvl))/((double) max(stat->lvl,foe->lvl));
X if (temp > 0.5) /* this one outweighs his/her foe */
X foespeed *= 2.0;
X else if (temp < -0.5) /* foe outweighs this one */
X speed *= 2.0;
X }
X if (stat->blind)
X strcpy(foename,"someone");
X else
X strcpy(foename,foe->name);
X mvprintw(3,0,"You have encountered %s Level: %d\n",foename,foe->lvl);
X refresh();
X /* now wait for foe to respond */
X for (loop = 1.5*MAXWAIT; foe->status != INBATTLE && loop; --loop)
X {
X readfoe();
X sleep(1);
X }
X if (foe->status != INBATTLE)
X {
X mvprintw(4,0,"%s is not responding.\n",foename);
X goto LEAVE;
X }
X
X /* otherwise, everything is set to go */
X move(4,0);
X clrtoeol();
X /* check to see who goes first */
X if (speed > foespeed)
X goto HITFOE;
X else if (foespeed > speed)
X goto WAIT;
X else if (stat->lvl > foe->lvl)
X goto HITFOE;
X else if (foe->lvl > stat->lvl)
X goto WAIT;
X else /* no one is faster */
X {
X printw("You can't fight %s yet.",foename);
X goto LEAVE;
X }
X
X/* routine to hit, etc */
XHITFOE: printstats(stat);
X mvprintw(1,26,"%20.0f",myhits);
X mvaddstr(4,0,"1:Fight 2:Run Away! 3:Power Blast ");
X if (luckout)
X clrtoeol();
X else
X addstr("4:Luckout ");
X ch = gch(stat->rng.type);
X move(lines = 5,0);
X clrtobot();
X switch (ch)
X {
X default: /* fight */
X temp = roll(2,strength);
XHIT: mvprintw(lines++,0,"You hit %s %.0f times!",foename,temp);
X stat->sin += 0.5;
X stat->scratch1 += temp;
X stat->scratch2 = FALSE;
X break;
X case '2': /* run away */
X --stat->scratch1; /* this value changes to indicate action */
X if (rnd() > 0.25)
X {
X mvaddstr(lines++,0,"You got away!");
X stat->scratch2 = RAN;
X goto LEAVE;
X }
X mvprintw(lines++,0,"%s is still after you!",foename);
X stat->scratch2 = STUCK;
X break;
X case '3': /* power blast */
X temp = min(stat->man,stat->lvl*5);
X stat->man -= temp;
X temp = (rnd() + 0.5) * temp * stat->mag * 0.2 + 2;
X mvprintw(lines++,0,"You blasted %s !",foename);
X goto HIT;
X case '4': /* luckout */
X if (luckout || rnd() > 0.1)
X {
X luckout = TRUE;
X mvaddstr(lines++,0,"Not this time...");
X --stat->scratch1;
X stat->scratch2 = BLEWIT;
X }
X else
X {
X mvaddstr(lines++,0,"You just lucked out!");
X stat->scratch1 = foe->nrg + 5;
X }
X break;
X }
X refresh();
X stat->scratch1 = floor(stat->scratch1); /* clean up any mess */
X if (stat->scratch1 > foe->nrg)
X stat->scratch2 = KILLED;
X else if (rnd() * speed < rnd() * foespeed)
X { /* foe's turn */
X ++stat->tampered;
X updateme();
X goto WAIT;
X }
X updateme();
X
X if (((int) stat->scratch2) == KILLED)
X {
X mvprintw(lines++,0,"You killed %s!",foename);
X stat->exp += foe->exp;
X stat->crn += (stat->lvl < 1000) ? foe->crn : 0;
X stat->amu += foe->amu;
X stat->chm += foe->chm;
X stat->gld += foe->gld;
X stat->gem += foe->gem;
X stat->swd = max(stat->swd,foe->swd);
X stat->shd = max(stat->shd,foe->shd);
X stat->quks = max(stat->quks,foe->quks);
X sleep(3); /* give other person time to die */
X goto LEAVE;
X }
X goto HITFOE; /* otherwise, my turn again */
X
X/* routine to wait for foe to do something */
XWAIT: printstats(stat);
X mvprintw(1,26,"%20.0f",myhits);
X mvaddstr(4,0,"Waiting...\n");
X refresh();
X for (loop = MAXWAIT; loop; --loop)
X {
X readfoe();
X if (foe->scratch1 != oldhits)
X switch ((int) foe->scratch2)
X {
X case RAN:
X mvprintw(lines++,0,"%s ran away!",foename);
X goto LEAVE;
X case STUCK:
X mvprintw(lines++,0,"%s tried to run away.",foename);
X goto BOT;
X case BLEWIT:
X mvprintw(lines++,0,"%s tried to luckout!",foename);
X goto BOT;
X default:
X temp = foe->scratch1 - oldhits;
X mvprintw(lines++,0,"%s hit you %.0f times!",foename,temp);
X myhits -= temp;
X goto BOT;
X }
X sleep(1);
X }
X /* timeout */
X mvaddstr(23,0,"Timeout: waiting for response. Do you want to wait ? ");
X refresh();
X ch = getch();
X move(23,0);
X clrtoeol();
X if (toupper(ch) == 'Y')
X goto WAIT;
X goto LEAVE;
X
X/* routine to decide what happens next */
XBOT: refresh();
X if (lines > 21)
X {
X paws(lines);
X move(lines = 5,0);
X clrtobot();
X }
X if (((int) foe->scratch2) == KILLED || myhits < 0.0)
X {
X myhits = -2;
X goto LEAVE; /* main will pick up death */
X }
X oldhits = foe->scratch1;
X if (foe->tampered != oldtags)
X {
X oldtags = foe->tampered;
X goto HITFOE;
X }
X goto WAIT;
X
X/* routine to clean up things and leave */
XLEAVE: updateme();
X fclose(fin);
X fclose(fout);
X stat->x += roll(5,-10);
X stat->y += roll(5,-10);
X stat->nrg = myhits;
X stat->tampered = OFF;
X stat->status = PLAYING;
X changed = TRUE;
X paws(lines);
X move(3,0);
X clrtobot();
X}
X
Xint interrupt() /* call when break key is hit */
X{
Xchar line[81];
Xreg int loop;
Xint x, y, ch;
X
X#ifdef USG3
X signal(SIGINT,SIG_IGN);
X#endif
X#ifdef USG5
X signal(SIGINT,SIG_IGN);
X#endif
X getyx(stdscr,y,x);
X for (loop = 79; loop >= 0; --loop) /* snarf line */
X {
X move(4,loop);
X line[loop] = inch();
X }
X line[80] = '\0';
X clrtoeol();
X if (fghting)
X {
X move(4,0);
X clrtoeol();
X addstr("Quitting now will automatically kill your character. Still want to ? ");
X ch = rgetch();
X if (toupper(ch) == 'Y')
X longjmp(mainenv,DIE);
X }
X else
X {
X move(4,0);
X clrtoeol();
X addstr("Do you really want to quit ? ");
X ch = rgetch();
X if (toupper(ch) == 'Y')
X longjmp(mainenv,QUIT);
X }
X mvaddstr(4,0,line); /* return screen to previous state */
X move(y,x);
X refresh();
X#ifdef USG3
X signal(SIGINT,interrupt);
X#endif
X#ifdef USG5
X signal(SIGINT,interrupt);
X#endif
X}
X
Xint rgetch() /* refresh, then get a char. */
X{
X refresh();
X return (getch());
X}
X
Xvoid purge() /* remove old players */
X{
XFILE *fin, *fout;
Xstruct stats sbuf;
Xreg int loc, today, temp;
Xlong ltime;
X
X loc = 0;
X time(<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,"<null>");
X fseek(fout,(long) loc * sizeof(sbuf),0);
X fwrite((char *) &sbuf,sizeof(sbuf),1,fout);
X }
X ++loc;
X }
X fclose(fin);
X fclose(fout);
X}
!EOR!
echo extracting - main.c
sed 's/^X//' > main.c << '!EOR!'
X/*
X * Phantasia 3.2 -- Interterminal fantasy game
X *
X * Edward A. Estes
X * AT&T Teletype Corp., September 4, 1984
X */
X
X/*
X * This is the program which drives the whole mess. Hopefully, you will be
X * able to wade throught the garbage if you have to fix something.
X * several undocumented items exist. The program checks uid and sets the
X * boolean flag 'su' (super user) if the person is allowed special powers.
X * The 'su' may execute any of the valar/council options. Also,
X * a 'vaporize' option exists to kill anybody at will. The 'su' can select
X * character type 7, which starts out with the maximum possible in each
X * category. (The resulting character is an experimento.) The 'su' may
X * also change the stats of other characters with the -x option.
X */
X
X/*
X * The program allocates as much file space as it needs to store characters,
X * so the possibility exists for the character file to grow without bound.
X * The file is purged upon normal entry to try to avoid that problem.
X * A similar problem exists for energy voids. To alleviate the problem here,
X * the void file is cleared with every new king.
X */
X
X/*
X * The support functions are split between various files with no apparent
X * order. Use of 'ctags' is recommended to find a particular function.
X */
X
X/*
X * Put one line of text into the file 'motd' for announcements, etc.
X */
X
X/*
X * If ENEMY is defined, a list of restricted login names is checked
X * in the file 'enemy'. These names are listed, one per line, with
X * no trailing blanks.
X */
X
X#include "phant.h"
X
Xdouble strength, speed;
Xbool beyond, marsh, throne, valhala, changed, fghting, su, wmhl;
Xint fileloc, users;
Xjmp_buf fightenv, mainenv;
Xlong secs;
X/*
X * worm hole map -- This table is carefully set up so that one can always
X * return the way he/she came by inverting the initial path.
X */
Xstruct worm_hole w_h[] =
X {
X 0,0,0,0, 35,22,2,0, 2,2,0,1, 59,34,64,0,
X 54,47,0,60, 50,62,0,56, 19,31,25,0, 0,35,41,41,
X 0,46,40,23, 24,0,29,30, 44,57,56,0, 0,44,39,40,
X 61,41,0,42, 32,0,17,18, 57,0,63,64, 0,33,26,34,
X 48,0,54,55, 28,23,22,13, 63,25,13,19, 34,6,18,20,
X 27,26,19,21, 15,27,20,27, 1,28,34,17, 17,29,8,24,
X 29,9,23,25, 18,30,24,6, 20,32,27,15, 21,20,21,26,
X 22,17,46,29, 23,24,28,9, 25,38,9,31, 6,39,30,32,
X 26,13,31,33, 15,40,32,35, 3,19,15,22, 7,1,33,36,
X 37,37,35,37, 36,36,36,38, 30,42,37,39, 31,43,38,11,
X 33,45,11,8, 12,48,7,7, 38,49,12,43, 39,51,42,44,
X 11,10,43,45, 40,52,44,46, 8,53,45,28, 4,54,51,48,
X 41,16,47,49, 42,55,48,50, 62,5,49,51, 43,56,50,47,
X 45,58,53,53, 46,59,52,52, 47,4,55,16, 49,61,16,54,
X 51,63,5,10, 10,14,59,58, 52,64,57,59, 53,3,58,57,
X 60,60,4,61, 55,12,60,62, 5,50,61,63, 56,18,62,14,
X 58,33,14,3
X };
X
Xmain(argc,argv) /* Phantasia main routine */
Xint argc;
Xchar *argv[];
X{
Xstruct stats charac;
Xchar aline[200], *login = NULL;
Xdouble x = 0.0, y = 0.0;
Xint ch, ch2;
Xreg int loop, temp;
XFILE *fp;
Xbool shrt = FALSE, examine = FALSE, header = FALSE;
X
X if ((login = getlogin()) == NULL)
X login = getpwuid(getuid())->pw_name;
X#ifdef ENEMY
X /* check hit list of restricted accounts */
X if ((fp = fopen(enemyfile, "r")) != NULL)
X {
X char enemy[20];
X
X while (fscanf(fp, "%s", enemy) != EOF)
X if (!strcmp(login,enemy))
X {
X printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", login);
X printf ("Mail comments to %s.\n", WIZARD);
X exit (0);
X }
X fclose (fp);
X }
X#endif
X setbuf(stdin, (char *) NULL); /* this may or may not be necessary */
X su = (getuid() == UID);
X fghting = FALSE;
X users = 0;
X if (argc > 1 && (*++argv)[0] == '-')
X switch ((*argv)[1])
X {
X case 'h': /* help */
X printhelp();
X exit(0);
X /*NOTREACHED*/
X case 's': /* short */
X shrt = TRUE;
X break;
X case 'x': /* examine */
X examine = TRUE;
X break;
X case 'H': /* Header */
X header = TRUE;
X break;
X case 'm': /* monsters */
X printmonster();
X exit(0);
X /*NOTREACHED*/
X case 'a': /* all users */
X showusers();
X exit(0);
X /*NOTREACHED*/
X case 'p': /* purge old players */
X purge();
X exit(0);
X /*NOTREACHED*/
X }
X if (!isatty(0)) /* don't let non-tty's play */
X exit(0);
X init1(); /* set up for screen stuff */
X if (examine)
X {
X cstat();
X exit1();
X /*NOTREACHED*/
X }
X if (!shrt)
X {
X titlestuff();
X purge(); /* clean up old characters */
X }
X if (header)
X {
X exit1();
X /*NOTREACHED*/
X }
X#ifdef OK_TO_PLAY
X if (!ok_to_play())
X {
X mvaddstr(23,27,"Sorry, you can't play now.\n");
X exit1();
X /*NOTREACHED*/
X }
X#endif
X mvaddstr(23,24,"Do you have a character to run? ");
X ch = rgetch();
X if (toupper(ch) == 'Y')
X fileloc = findchar(&charac);
X else
X {
X initchar(&charac);
X clear();
X mvaddstr(5,21,"Which type of character do you want:");
X mvaddstr(10,4,"1:Magic User 2:Fighter 3:Elf 4:Dwarf 5:Halfling 6:Experimento ? ");
X ch = rgetch();
X do
X {
X genchar(&charac,ch);
X mvprintw(15,14,"Strength: %2.0f Manna : %3.0f Quickness : %2d",
X charac.str,charac.man,charac.quk);
X mvprintw(16,14,"Brains : %2.0f Magic Level: %2.0f Energy Level: %2.0f",
X charac.brn,charac.mag,charac.nrg);
X if (charac.typ != 6)
X {
X mvaddstr(17,14,"Type '1' to keep >");
X ch2 = rgetch();
X }
X else
X break;
X }
X while (ch2 != '1');
X if (charac.typ == 6)
X {
X mvaddstr(19,0,"Enter the X Y coordinates of your experimento ? ");
X getstring(aline,80);
X sscanf(aline,"%F %F",&x,&y);
X charac.x = (abs(x) > 1.2e+6) ? sgn(x)*1.2e+6 : floor(x);
X charac.y = (abs(y) > 1.2e+6) ? sgn(y)*1.2e+6 : floor(y);
X }
X do
X {
X mvaddstr(20,0,"Give your character a name [up to 20 characters] ? ");
X getstring(aline,80);
X strncpy(charac.name,aline,20);
X charac.name[20] = '\0';
X }
X while (findname(charac.name));
X putchar('\n');
X fflush(stdout);
X nocrmode();
X do
X {
X strcpy(charac.pswd,getpass("Give your character a password [up to 8 characters] ? "));
X putchar('\n');
X strcpy(aline,getpass("One more time to verify ? "));
X }
X while (strcmp(charac.pswd,aline));
X fileloc = findspace();
X }
X crmode();
X if (charac.status)
X {
X clear();
X addstr("Your character did not exit normally last time.\n");
X addstr("If you think you have good cause to have you character saved,\n");
X printw("you may quit and mail your reason to '%s'.\n",WIZARD);
X addstr("Do you want to quit ? ");
X ch = rgetch();
X if (toupper(ch) == 'Y')
X {
X charac.quk = -100;
X leave(&charac);
X /*NOTREACHED*/
X }
X death(&charac);
X }
X charac.status = PLAYING;
X strcpy(charac.login,login);
X time(&secs);
X charac.lastused = localtime(&secs)->tm_yday;
X update(&charac,fileloc);
X clear();
X#ifdef BSD41
X sigset(SIGINT,interrupt);
X#endif
X#ifdef BSD42
X signal(SIGINT,interrupt,-1);
X#endif
X#ifdef USG3
X signal(SIGINT,interrupt);
X#endif
X#ifdef USG5
X signal(SIGINT,interrupt);
X#endif
X
X/* all set for now */
X
XTOP: switch (setjmp(mainenv))
X {
X case QUIT:
X#ifdef BSD41
X sigrelse(SIGINT);
X#endif
X#ifdef BSD42
X signal(SIGINT,interrupt,-1);
X#endif
X#ifdef USG3
X signal(SIGINT,interrupt);
X#endif
X#ifdef USG5
X signal(SIGINT,interrupt);
X#endif
X leave(&charac);
X /*NOTREACHED*/
X case DIE:
X#ifdef BSD41
X sigrelse(SIGINT);
X#endif
X#ifdef BSD42
X signal(SIGINT,interrupt,-1);
X#endif
X#ifdef USG3
X signal(SIGINT,interrupt);
X#endif
X#ifdef USG5
X signal(SIGINT,interrupt);
X#endif
X death(&charac);
X break;
X }
X#ifdef OK_TO_PLAY
X if (!ok_to_play())
X {
X mvaddstr(6,0,"Whoops! Can't play now.\n");
X leave(&charac);
X /*NOTREACHED*/
X }
X#endif
X fghting = FALSE;
X adjuststats(&charac);
X if (throne && !charac.crn && (charac.typ < 10 || charac.typ > 20))
X {
X mvaddstr(6,0,"You're not allowed in the Lord's Chamber without a crown.\n");
X changed = TRUE;
X charac.x = charac.y = 10;
X }
X if (charac.status != CLOAKED && abs(charac.x) == abs(charac.y)
X && floor(sqrt(fabs(charac.x/100.0))) == sqrt(fabs(charac.x/100.0)) && !throne)
X {
X trade(&charac);
X clear();
X }
X checktampered(&charac);
X checkinterm(&charac);
X if (charac.nrg < 0 || (charac.lvl >= 10000 && charac.typ != 99))
X death(&charac);
X neatstuff(&charac);
X if (changed)
X {
X update(&charac,fileloc);
X changed = FALSE;
X goto TOP;
X }
X move(5,0);
X clrtoeol();
X fp = fopen(messfile,"r");
X if (fgets(aline,160,fp))
X addstr(aline);
X fclose(fp);
X printstats(&charac);
X move(3,0);
X clrtoeol();
X if (!wmhl)
X {
X if (throne)
X kingstuff(&charac);
X addstr("1:Move 2:Players 3:Talk 4:Stats 5:Quit ");
X if (charac.lvl >= 5 && charac.mag >= 15)
X addstr("6:Cloak ");
X if (charac.lvl >= 10 && charac.mag >= 25)
X addstr("7:Teleport ");
X if (charac.typ > 20)
X addstr("8:Intervention");
X ch = gch(charac.rng.type);
X clrtoeol();
X move(6,0);
X clrtobot();
X if (charac.typ == 99 && (ch == '1' || ch == '7'))
X ch = ' ';
X switch (ch2 = toupper(ch))
X {
X case 'N':
X charac.y += maxmove;
X break;
X case 'S':
X charac.y -= maxmove;
X break;
X case 'E':
X charac.x += maxmove;
X break;
X case 'W':
X charac.x -= maxmove;
X break;
X default: /* rest */
X if (charac.status == CLOAKED)
X if (charac.man > 3.0)
X charac.man -= 3;
X else
X {
X charac.status = PLAYING;
X changed = TRUE;
X }
X else
X {
X charac.man += circ(charac.x,charac.y)/3+0.5;
X charac.man += charac.lvl/5+0.5;
X }
X rndattack();
X break;
X case '1': /* move */
X for (loop = 3; loop; --loop)
X {
X mvaddstr(5,0,"X Y Coordinates ? ");
X getstring(aline,80);
X if (sscanf(aline,"%F %F",&x,&y) < 2)
X ;
X else
X if (hypot((double) charac.x - x, (double) charac.y - y) > maxmove)
X illmove();
X else
X {
X charac.x = x;
X charac.y = y;
X break;
X }
X }
X break;
X case '2': /* players */
X printplayers(&charac);
X break;
X case '3': /* message */
X talk(charac.name);
X break;
X case '4': /* stats */
X showall(&charac);
X break;
X case '5': /* good-bye */
X leave(&charac);
X /*NOTREACHED*/
X case '6': /* cloak */
X if (charac.lvl < 5 || charac.mag < 15)
X illcmd();
X else if (charac.status == CLOAKED)
X charac.status = PLAYING;
X else if (charac.man < 35)
X {
X mvaddstr(6,0,"No power left.\n");
X refresh();
X }
X else
X {
X changed = TRUE;
X charac.man -= 35;
X charac.status = CLOAKED;
X }
X break;
X case '7': /* teleport */
X if (charac.lvl < 10 || charac.mag < 25)
X illcmd();
X else
X for (loop = 3; loop; --loop)
X {
X mvaddstr(5,0,"X Y Coordinates ? ");
X getstring(aline,80);
X if (sscanf(aline,"%F %F",&x,&y) == 2)
X if ((temp = hypot(charac.x-x,charac.y-y))
X > (charac.lvl+charac.mag)*5+((charac.typ > 20) ? 1e+6 : 0)
X && !throne)
X illmove();
X else if ((temp = (temp/75+1)*20) > charac.man && !throne)
X mvaddstr(6,0,"Not enough power for that distance.\n");
X else
X {
X charac.x = x;
X charac.y = y;
X if (!throne)
X charac.man -= temp;
X break;
X }
X }
X break;
X case '9': /* monster */
X if (throne)
X mvaddstr(6,0,"No monsters in the chamber!\n");
X else if (charac.typ != 99)
X {
X charac.status = PLAYING;
X changed = TRUE;
X charac.sin += 1e-6;
X fight(&charac,-1);
X }
X break;
X case '0': /* decree */
X if (su || charac.typ > 10 && charac.typ < 20 && throne)
X decree(&charac);
X else
X illcmd();
X break;
X case '8': /* intervention */
X if (su || charac.typ > 20)
X valarstuff(&charac);
X else
X illcmd();
X break;
X case '\014': /* redo screen */
X clear();
X }
X if (ch2 == 'E' || ch2 == 'W' || ch2 == 'N' || ch2 == 'S'
X || ch2 == '1' || ch2 == '7')
X {
X checkmov(&charac);
X rndattack();
X changed = TRUE;
X }
X }
X else
X {
X addstr("F:Forward B:Back R:Right L:Left Q:Quit T:Talk P:Players S:Stats ");
X ch = rgetch();
X move(6,0);
X clrtobot();
X switch (toupper(ch))
X {
X default:
X if (charac.status == CLOAKED)
X if (charac.man > 3.0)
X charac.man -= 3;
X else
X {
X charac.status = PLAYING;
X changed = TRUE;
X }
X else
X charac.man += charac.lvl/5+0.5;
X break;
X case 'F':
X temp = (int) w_h[charac.wormhole].f;
X goto CHKMOVE;
X case 'B':
X temp = (int) w_h[charac.wormhole].b;
X goto CHKMOVE;
X case 'R':
X temp = (int) w_h[charac.wormhole].r;
X goto CHKMOVE;
X case 'L':
X temp = (int) w_h[charac.wormhole].l;
X goto CHKMOVE;
X case 'Q':
X leave(&charac);
X /*NOTREACHED*/
X case 'T':
X talk(charac.name);
X break;
X case 'P':
X printplayers(&charac);
X break;
X case 'S':
X showall(&charac);
X break;
X case '\014': /* redo screen */
X clear();
X }
X goto TOP;
XCHKMOVE: if (!temp)
X {
X charac.y = 0.0;
X charac.x = pow(-1.0,(double) charac.wormhole) * charac.wormhole * 400 - 1.0;
X charac.wormhole = 0;
X changed = TRUE;
X }
X else
X charac.wormhole = temp;
X }
X goto TOP;
X}
X
X/*
X * This function is provided to allow one to restrict access to the game.
X * Tailor this routine as appropriate.
X */
X
X#ifdef OK_TO_PLAY
X#include <sys/types.h>
X#include <utmp.h> /* used for counting users on system */
X
Xbool ok_to_play() /* return FALSE if playing is not allowed at this time */
X{
X#define MAXUSERS 8 /* max. number of people on system */
Xreg struct tm *tp;
Xreg int numusers = 0;
XFILE *fp;
Xlong now;
Xstruct utmp ubuf;
X
X if (su)
X return (TRUE);
X /* check time of day */
X time(&now);
X if (((tp = localtime(&now))->tm_hour > 8 && tp->tm_hour < 12) /* 8-noon */
X || (tp->tm_hour > 13 && tp->tm_hour < 16)) /* 1-4 pm */
X return (FALSE);
X /* check # of users */
X fp = fopen("/etc/utmp","r");
X while (fread((char *) &ubuf,sizeof(ubuf),1,fp))
X#ifdef USG5
X if (ubuf.ut_type == USER_PROCESS)
X#else
X if (*ubuf.ut_name)
X#endif
X ++numusers;
X fclose(fp);
X if (numusers > MAXUSERS)
X return (FALSE);
X return (TRUE);
X}
X#endif
!EOR!
echo extracting - fight.c
sed 's/^X//' > fight.c << '!EOR!'
X/*
X * fight.c Phantasia monster fighting routine
X */
X
X/*
X * The code exists here for fight to the finish. Simply add code to
X * set 'fgttofin = TRUE' as an option. Everything else is here.
X */
X#include "phant.h"
X
Xvoid fight(stat,particular) /* monster fighting routine */
Xreg struct stats *stat;
Xint particular;
X{
Xbool fghttofin = FALSE, luckout = FALSE;
Xchar aline[80];
Xdouble monhit, mdamage, sdamage, monspd, maxspd, inflict, monstr, temp, shield;
Xint ch;
Xreg int whichm, size, howmany, lines;
Xstruct mstats monster;
X
X fghting = changed = TRUE;
X shield = 0.0;
X if (setjmp(fightenv) == 2)
X shield = roll(100 + (stat->mxn + stat->shd)*6.2,3000);
X howmany = 0;
X size = (valhala) ? stat->lvl/5 : circ(stat->x,stat->y);
X if (particular >= 0)
X whichm = particular;
X else if (marsh)
X whichm = roll(0,15);
X else if (size > 24)
X whichm = roll(14,86);
X else if (size > 15)
X whichm = roll(0,50) + roll(14,37);
X else if (size > 8)
X whichm = roll(0,50) + roll(14,26);
X else if (size > 3)
X whichm = roll(14,50);
X else
X whichm = roll(14,25);
X
XCALL: move(3,0);
X clrtobot();
X move(5,0);
X lines = 6;
X callmonster(whichm,size,&monster);
X if (stat->blind)
X strcpy(monster.name,"a monster");
X ++howmany;
X if (monster.typ == 1) /* unicorn */
X if (stat->vrg)
X {
X printw("You just subdued %s, thanx to the virgin.",monster.name);
X stat->vrg = FALSE;
X goto FINISH;
X }
X else
X {
X printw("You just saw %s running away!",monster.name);
X goto LEAVE;
X }
X if (monster.typ == 2 && stat->typ > 20)
X {
X strcpy(monster.name,"Morgoth");
X monster.str = rnd()*(stat->mxn + stat->shd)/1.4 + rnd()*(stat->mxn + stat->shd)/1.5;
X monster.brn = stat->brn;
X monster.hit = stat->str*30;
X monster.typ = 23;
X monster.spd = speed*1.1 + speed*(stat->typ == 90);
X monster.flk = monster.trs = monster.exp = 0;
X mvprintw(4,0,"You've encountered %s, Bane of the Council and Valar.",monster.name);
X }
X fghttofin = luckout = FALSE;
X monstr = monster.str;
X monhit = monster.hit;
X mdamage = sdamage = 0;
X monspd = maxspd = monster.spd;
X *monster.name = toupper(*monster.name);
X
XTOP: mvprintw(5,0,"You are being attacked by %s, EXP: %.0f (Size: %d)",monster.name,monster.exp,size);
X printstats(stat);
X mvprintw(1,26,"%20.0f",stat->nrg + shield);
X if (monster.typ == 4 && stat->bls && stat->chm)
X {
X mvprintw(6,0,"You just overpowered %s!",monster.name);
X lines = 7;
X stat->bls = FALSE;
X --stat->chm;
X goto FINISH;
X }
X monster.spd = min(monster.spd + 1,maxspd);
X if (rnd()*monster.spd > rnd()*speed && monster.typ != 4 && monster.typ != 16)
X {
X if (monster.typ)
X switch (monster.typ) /* do special things */
X {
X case 5: /* Leanan-Sidhe */
X if (rnd() > 0.25)
X goto NORMALHIT;
X inflict = roll(1,(size - 1)/2);
X inflict = min(stat->str,inflict);
X mvprintw(lines++,0,"%s sapped %0.f of your strength!",monster.name,inflict);
X stat->str -= inflict;
X strength -= inflict;
X break;
X case 6: /* Saruman */
X if (stat->pal)
X {
X mvprintw(lines++,0,"Wormtongue stole your palantir!");
X stat->pal = FALSE;
X }
X else if (rnd() > 0.2)
X goto NORMALHIT;
X else if (rnd() > 0.5)
X {
X mvprintw(lines++,0,"%s transformed your gems into gold!",monster.name);
X stat->gld += stat->gem;
X stat->gem = 0.0;
X }
X else
X {
X mvprintw(lines++,0,"%s scrambled your stats!",monster.name);
X scramble(stat);
X }
X break;
X case 7: /* Thaumaturgist */
X if (rnd() > 0.15)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s transported you!",monster.name);
X stat->x += sgn(stat->x)*roll(50*size,250*size);
X stat->y += sgn(stat->y)*roll(50*size,250*size);
X goto LEAVE;
X case 8: /* Balrog */
X inflict = roll(10,monster.str);
X inflict = min(stat->exp,inflict);
X mvprintw(lines++,0,"%s took away %0.f experience points.",monster.name,inflict);
X stat->exp -= inflict;
X break;
X case 9: /* Vortex */
X if (rnd() > 0.2)
X goto NORMALHIT;
X inflict = roll(0,7.5*size);
X inflict = min(stat->man,floor(inflict));
X mvprintw(lines++,0,"%s sucked up %.0f of your manna!",monster.name,inflict);
X stat->man -= inflict;
X break;
X case 10: /* Nazgul */
X if (rnd() > 0.3)
X goto NORMALHIT;
X if (stat->rng.type && stat->rng.type < 10)
X {
X mvaddstr(lines++,0,"Will you relinguish your ring ? ");
X ch = rgetch();
X if (toupper(ch) == 'Y')
X {
X stat->rng.type = NONE;
X goto LEAVE;
X }
X }
X mvprintw(lines++,0,"%s neutralized 1/5 of your brain!",monster.name);
X stat->brn *= 0.8;
X break;
X case 11: /* Tiamat */
X if (rnd() > 0.6)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s took half your gold and gems and flew off.",monster.name);
X stat->gld = floor(stat->gld/2);
X stat->gem = floor(stat->gem/2);
X goto LEAVE;
X case 12: /* Kobold */
X if (rnd() >.7)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s stole one gold piece and ran away.",monster.name);
X stat->gld = max(0,stat->gld-1);
X goto LEAVE;
X case 13: /* Shelob */
X if (rnd() > 0.5)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s has bitten and poisoned you!",monster.name);
X ++stat->psn;
X break;
X case 14: /* Faeries */
X if (!stat->hw)
X goto NORMALHIT;
X mvprintw(lines++,0,"Your holy water killed it!");
X --stat->hw;
X goto FINISH;
X case 15: /* Lamprey */
X if (rnd() > 0.7)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s bit and poisoned you!",monster.name);
X stat->psn += 0.25;
X break;
X case 17: /* Bonnacon */
X if (rnd() > 0.1)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s farted and scampered off.",monster.name);
X stat->nrg /= 2;
X goto LEAVE;
X case 18: /* Smeagol */
X if (rnd() > 0.5 || !stat->rng.type)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s tried to steal your ring, ",monster.name);
X if (rnd() > 0.1)
X addstr("but was unsuccessful.");
X else
X {
X addstr("and ran away with it!");
X stat->rng.type = NONE;
X goto LEAVE;
X }
X break;
X case 19: /* Succubus */
X if (rnd() > 0.3)
X goto NORMALHIT;
X inflict = roll(15,size*10);
X inflict = min(inflict,stat->nrg);
X mvprintw(lines++,0,"%s sapped %0.f of your energy.",monster.name,inflict);
X stat->nrg -= inflict;
X break;
X case 20: /* Cerberus */
X if (rnd() > 0.25)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s took all your metal treasures!",monster.name);
X stat->swd = stat->shd =stat->gld = stat->crn = 0;
X goto LEAVE;
X case 21: /* Ungoliant */
X if (rnd() > 0.1)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s poisoned you, and took one quik.",monster.name);
X stat->psn += 5;
X --stat->quk;
X break;
X case 22: /* Jabberwock */
X if (rnd() > 0.1)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s flew away, and left you to contend with one of its friends.",monster.name);
X whichm = 55 + 22*(rnd() > 0.5);
X goto CALL;
X case 24: /* Troll */
X if (rnd() > 0.5)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s partially regenerated his energy.!",monster.name);
X monster.hit += floor((monhit*size - monster.hit)/2);
X monster.str = monstr;
X mdamage = sdamage = 0;
X maxspd = monspd;
X break;
X case 25: /* wraith */
X if (rnd() > 0.3 || stat->blind)
X goto NORMALHIT;
X mvprintw(lines++,0,"%s blindeed you!",monster.name);
X stat->blind = TRUE;
X break;
X default:
X goto NORMALHIT;
X }
X else
XNORMALHIT: {
X inflict = rnd()*monster.str + 0.5;
X mvprintw(lines++,0,"%s hit you %.0f times!",monster.name,inflict);
XSPECIALHIT: if ((shield -= inflict) < 0)
X {
X stat->nrg += shield;
X shield = 0;
X }
X }
X }
X else
X {
X if (fghttofin)
X goto MELEE;
X mvaddstr(3,0,"1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick ");
X if (!luckout)
X if (monster.typ == 23)
X addstr("6:Ally ");
X else
X addstr("6:Luckout ");
X if (stat->rng.type > 0)
X addstr("7:Use Ring ");
X else
X clrtoeol();
X ch = gch(stat->rng.type);
X move(lines = 6,0);
X clrtobot();
X switch (ch)
X {
X default:
X case '1': /* melee */
XMELEE: inflict = roll(strength/2 + 5,1.3*strength) + (stat->rng.type < 0 ? strength : 0);
X mdamage += inflict;
X monster.str = monstr - mdamage/monhit*monstr/4;
X goto HITMONSTER;
X case '2': /* skirmish */
X inflict = roll(strength/3 + 3,1.1*strength) + (stat->rng.type < 0 ? strength : 0);
X sdamage += inflict;
X maxspd = monspd - sdamage/monhit*monspd/4;
X goto HITMONSTER;
X case '3': /* evade */
X if ((monster.typ == 4 || monster.typ == 16
X || rnd()*speed*stat->brn > rnd()*monster.spd*monster.brn)
X && (monster.typ != 23))
X {
X mvaddstr(lines++,0,"You got away!");
X stat->x += roll(-2,5);
X stat->y += roll(-2,5);
X goto LEAVE;
X }
X else
X mvprintw(lines++,0,"%s is still after you!",monster.name);
X break;
X case '4': /* spell */
X lines = 7;
X mvaddstr(3,0,"\n\n");
X mvaddstr(3,0,"1:All or Nothing");
X if (stat->mag >= 3)
X mvaddstr(3,18,"2:Magic Bolt");
X if (stat->mag >= 7)
X mvaddstr(3,32,"3:Force Field");
X if (stat->mag >= 10)
X mvaddstr(3,47,"4:Transform");
X if(stat->mag >= 15)
X mvaddstr(3,60,"5:Increase Might\n");
X if (stat->mag >= 20)
X mvaddstr(4,0,"6:Invisibility");
X if (stat->mag >= 25)
X mvaddstr(4,18,"7:Transport");
X if (stat->mag >= 30)
X mvaddstr(4,32,"8:Paralyze");
X if (stat->typ > 20)
X mvaddstr(4,52,"9:Specify");
X mvaddstr(6,0,"Spell ? ");
X ch = rgetch();
X mvaddstr(3,0,"\n\n");
X if (monster.typ == 23 && ch != '4')
X illspell();
X else
X switch (ch)
X {
X case '1': /* all or nothing */
X {
X inflict = (rnd() < 0.25) ? (monster.hit*1.0001 + 1) : 0;
X if (monster.typ == 4)
X inflict *= .9;
X if (stat->man)
X --stat->man;
X maxspd *= 2;
X monspd *= 2;
X monster.spd = max(1,monster.spd * 2);
X monstr = monster.str *= 2;
X goto HITMONSTER;
X }
X case '2': /* magic bolt */
X if (stat->mag < 3)
X illspell();
X else
X {
X do
X {
X mvaddstr(6,0,"How much manna for bolt? ");
X getstring(aline,80);
X sscanf(aline,"%F",&temp);
X }
X while (temp < 0 || temp > stat->man);
X stat->man -= floor(temp);
X inflict = temp*roll(10,sqrt(stat->mag/3.0 + 1.0));
X mvaddstr(6,0,"Magic Bolt fired!\n");
X if (monster.typ == 4)
X inflict = 0.0;
X goto HITMONSTER;
X }
X case '5': /* increase might */
X {
X if (stat->mag < 15)
X illspell();
X else if (stat->man < 55)
X nomanna();
X else
X {
X stat->man -= 55;
X strength += (1.2*(stat->str+stat->swd)+5-strength)/2;
X mvprintw(6,0,"New strength: %.0f\n",strength);
X }
X break;
X }
X case '3': /* force field */
X {
X if (stat->mag < 7)
X illspell();
X else if (stat->man < 20)
X nomanna();
X else
X {
X shield = (stat->mxn + stat->shd)*4.2 + 45;
X stat->man -= 20;
X mvaddstr(6,0,"Force Field up.\n");
X }
X break;
X }
X case '4': /* transform */
X {
X if (stat->mag < 10)
X illspell();
X else if (stat->man < 35)
X nomanna();
X else
X {
X stat->man -= 35;
X whichm = roll(0,100);
X goto CALL;
X }
X break;
X }
X case '6': /* invisible */
X {
X if (stat->mag < 20)
X illspell();
X else if (stat->man < 45)
X nomanna();
X else
X {
X stat->man -= 45;
X speed += (1.2*(stat->quk+stat->quks)+5-speed)/2;
X mvprintw(6,0,"New quik : %.0f\n",speed);
X }
X break;
X }
X case '7': /* transport */
X {
X if (stat->mag < 25)
X illspell();
X else if (stat->man < 50)
X nomanna();
X else
X {
X stat->man -= 50;
X if (stat->brn + stat->mag < monster.exp/300*rnd())
X {
X mvaddstr(6,0,"Transport backfired!\n");
X stat->x += (250*size*rnd() + 50*size)*sgn(stat->x);
X stat->y += (250*size*rnd() + 50*size)*sgn(stat->y);
X goto LEAVE;
X }
X else
X {
X mvprintw(6,0,"%s is transported.\n",monster.name);
X monster.trs *= (rnd() > 0.3);
X goto FINISH;
X }
X }
X break;
X }
X case '8': /* paralyze */
X {
X if (stat->mag < 30)
X illspell();
X else if (stat->man < 60)
X nomanna();
X else
X {
X stat->man -= 60;
X if (stat->mag > monster.exp/1000*rnd())
X {
X mvprintw(6,0,"%s is held.\n",monster.name);
X monster.spd = -2;
X }
X else
X mvaddstr(6,0,"Monster unaffected.\n");
X }
X break;
X }
X case '9': /* specify */
X {
X if (stat->typ < 20)
X illspell();
X else if (stat->man < 1000)
X nomanna();
X else
X {
X mvaddstr(6,0,"Which monster do you want [0-99] ? ");
X whichm = inflt();
X whichm = max(0,min(99,whichm));
X stat->man -= 1000;
X goto CALL;
X }
X break;
X }
X }
X break;
X case '5':
X inflict = 1 + stat->swd;
X stat->exp += floor(monster.exp/10);
X monster.exp *= 0.92;
X maxspd += 2;
X monster.spd = (monster.spd < 0) ? 0 : monster.spd + 2;
X if (monster.typ == 4)
X {
X mvprintw(lines++,0,"You hit %s %.0f times, and made him mad!",monster.name,inflict);
X stat->quk /= 2;
X stat->x += sgn(stat->x)*roll(50*size,250*size);
X stat->y += sgn(stat->y)*roll(50*size,250*size);
X stat->y += (250*size*rnd() + 50*size)*sgn(stat->y);
X goto LEAVE;
X }
X else
X goto HITMONSTER;
X case '6': /* luckout */
X if (luckout)
X mvaddstr(lines++,0,"You already tried that.");
X else
X if (monster.typ == 23)
X if (rnd() < stat->sin/100) {
X mvprintw(lines++,0,"%s accepted!",monster.name);
X goto LEAVE;
X }
X else
X {
X luckout = TRUE;
X mvaddstr(lines++,0,"Nope, he's not interested.");
X }
X else
X if ((rnd() + .333)*stat->brn < (rnd() + .333)*monster.brn)
X {
X luckout = TRUE;
X mvprintw(lines++,0,"You blew it, %s.",stat->name);
X }
X else
X {
X mvaddstr(lines++,0,"You made it!");
X goto FINISH;
X }
X break;
X case '\014': /* clear screen */
X clear();
X break;
X case '7': /* use ring */
X if (stat->rng.type > 0)
X {
X mvaddstr(lines++,0,"Now using ring.");
X stat->rng.type = -stat->rng.type;
X if (abs(stat->rng.type) != DLREG)
X --stat->rng.duration;
X goto NORMALHIT;
X }
X break;
X }
X goto BOT;
XHITMONSTER: {
X inflict = floor(inflict);
X mvprintw(lines++,0,"You hit %s %.0f times!",monster.name,inflict);
X if ((monster.hit -= inflict) >0)
X switch (monster.typ)
X {
X case 4: /* dark lord */
X inflict = stat->nrg + shield +1;
X goto SPECIALHIT;
X case 16: /* shrieker */
X mvaddstr(lines++,0,"Shreeeek!! You scared it, and it called one of its friends.");
X paws(lines);
X whichm = roll(70,30);
X goto CALL;
X }
X else
X {
X if (monster.typ == 23) /* morgoth */
X mvaddstr(lines++,0,"You have defeated Morgoth, but he may return. . .");
X else
X mvprintw(lines++,0,"You killed it. Good work, %s.",stat->name);
X goto FINISH;
X }
X }
X }
XBOT: refresh();
X if (lines == 23)
X {
X paws(23);
X move(lines = 6,0);
X clrtobot();
X }
X if (stat->nrg <= 0)
X {
X paws(lines);
X death(stat);
X goto LEAVE;
X }
X goto TOP;
XFINISH: stat->exp += monster.exp;
X if (rnd() < monster.flk/100.0) /* flock monster */
X {
X paws(lines);
X fghttofin = FALSE;
X goto CALL;
X }
X else if (size > 1 && monster.trs && rnd() > pow(0.6,(double) (howmany/3 + size/3))) /* this takes # of flocks and size into account */
X {
X paws(lines);
X treasure(stat,monster.trs,size);
X }
XLEAVE: stat->rng.type = abs(stat->rng.type);
X paws(lines+3);
X move(4,0);
X clrtobot();
X fghting = FALSE;
X}
!EOR!
More information about the Comp.sources.unix
mailing list