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(&ltemp);
X	stat->age += ltemp - secs;
X	secs = ltemp;
X	stat->quks = min(99,stat->quks);
X	stat->man = min(stat->man,stat->lvl*15 + 5000);
X	stat->chm = min(stat->chm,stat->lvl + 10);
X	stat->typ = (stat->crn && stat->typ < 10) ? -abs(stat->typ) : abs(stat->typ);
X	if (level(stat->exp) > stat->lvl)
X		movelvl(stat);
X	stat->gld = floor(stat->gld) + 0.1;
X	stat->gem = floor(stat->gem) + 0.1;
X	if (stat->rng.type)
X		stat->nrg = stat->mxn + stat->shd;
X	if (stat->rng.type && stat->rng.duration <= 0)	/* clean up rings */
X		switch (stat->rng.type)
X			{
X			case DLBAD:
X			case NAZBAD:
X				stat->rng.type = SPOILED;
X				stat->rng.duration = roll(10,25);
X				break;
X			case NAZREG:
X				stat->rng.type = NONE;
X				break;
X			case SPOILED:
X				death(stat);
X				break;
X			}	/* DLREG is ok, so do nothing with it */
X	stat->nrg += (stat->mxn+stat->shd)/15+stat->lvl/3+2;
X	stat->nrg = min(stat->nrg,stat->mxn + stat->shd);
X	if (stat->age > stat->degen * 2500)
X		{
X		++stat->degen;
X		if (stat->quk > 23)
X			--stat->quk;
X		stat->str *= 0.97;
X		stat->brn *= 0.95;
X		stat->mag *= 0.97;
X		stat->mxn *= 0.95;
X		if (stat->quks)
X			--stat->quks;
X		stat->swd *= 0.93;
X		stat->shd *= 0.95;
X		}
X}
X
Xvoid	checkinterm(stat)				/* see if other person on same x,y */
Xreg	struct	stats	*stat;
X{
XFILE	*fp;
Xstruct	stats	sbuf;
Xreg	int	foeloc = 0;
X
X	users = 0;
X	fp = fopen(peoplefile,"r");
X	while (fread((char *) &sbuf,sizeof(sbuf),1,fp))
X		{
X		if (sbuf.status && (sbuf.status != CLOAKED || sbuf.typ != 99))
X			{
X			++users;
X			if (stat->x == sbuf.x && stat->y == sbuf.y
X			   && foeloc != fileloc && sbuf.typ != 99
X			   && stat->typ !=99 && !stat->wormhole && !sbuf.wormhole)
X				{
X				fclose(fp);
X				interm(stat,foeloc);
X				return;
X				}
X			}
X		++foeloc;
X		}
X	fclose(fp);
X}
X
Xint	gch(rngtyp)			/* get a character from terminal, but check ring if crazy */
Xshort	rngtyp;
X{
X	refresh();
X	if (abs(rngtyp) != SPOILED)
X		return (getch());
X	else
X		{
X		getch();
X		return (roll(0,5) + '0');
X		}
X}
X
Xint	rngcalc(chartyp)				/* pick a duration of a ring */
Xshort	chartyp;
X{
Xstatic	int	rngtab[] = { 0, 10, 20, 13, 25, 40, 20};
X
X	if (chartyp > 10)
X		chartyp -= 10;
X	return (rngtab[chartyp - 1]);
X}
X
Xvoid	interm(stat,who)				/* interterminal battle routine */
Xreg	struct	stats	*stat;
Xint	who;
X{
X#define	MAXWAIT	20
X#define	BLOCK	sizeof(struct stats)
X#define	RAN	1
X#define	STUCK	2
X#define	BLEWIT	3
X#define	KILLED	4
X#define readfoe()	fseek(fin,foeplace,0);  \
X			fread((char *) foe,BLOCK,1,fin)
X#define updateme()	fseek(fout,myplace,0);  \
X			fwrite((char *) stat,BLOCK,1,fout);  \
X			fflush(fout)
X
XFILE	*fin, *fout;	/* pointers for input, output */
Xdouble	temp, foespeed, oldhits = 0.0, myhits;
Xstruct	stats	sbuf;
Xreg	struct	stats *foe;
Xreg	int	loop, lines = 5;
Xint	ch;
Xlong	myplace, foeplace;
Xshort	oldtags;
Xbool	luckout = FALSE;
Xchar	foename[21];
X
X	fghting = TRUE;
X	mvaddstr(4,0,"Preparing for battle!\n");
X	refresh();
X		/* set up variables, file, etc. */
X	myplace = fileloc * BLOCK;
X	foeplace = who * BLOCK;
X	fin = fopen(peoplefile,"r");
X	setbuf(fin, (char *) NULL);
X	fout = fopen(peoplefile,ACCESS);
X	stat->status = INBATTLE;
X	myhits = stat->nrg;
X	stat->tampered = oldtags = 1;	/* this must be non-zero to prevent a king or valar from trashing it */
X	stat->scratch1 = stat->scratch2 = 0.0;
X	updateme();
X	foe = &sbuf;
X	readfoe();
X	foespeed = foe->quk + foe->quks - spdcalc(foe->lvl,foe->gld,foe->gem);
X	if (abs(stat->lvl - foe->lvl) > 20)		/* see if greatly mismatched */
X		{
X		temp = ((double) (stat->lvl - foe->lvl))/((double) max(stat->lvl,foe->lvl));
X		if (temp > 0.5)		/* this one outweighs his/her foe */
X			foespeed *= 2.0;
X		else if (temp < -0.5)	/* foe outweighs this one */
X			speed *= 2.0;
X		}
X	if (stat->blind)
X		strcpy(foename,"someone");
X	else
X		strcpy(foename,foe->name);
X	mvprintw(3,0,"You have encountered %s   Level: %d\n",foename,foe->lvl);
X	refresh();
X		/* now wait for foe to respond */
X	for (loop = 1.5*MAXWAIT; foe->status != INBATTLE && loop; --loop)
X		{
X		readfoe();
X		sleep(1);
X		}
X	if (foe->status != INBATTLE)
X		{
X		mvprintw(4,0,"%s is not responding.\n",foename);
X		goto LEAVE;
X		}
X
X	/* otherwise, everything is set to go */
X	move(4,0);
X	clrtoeol();
X		/* check to see who goes first */
X	if (speed > foespeed)
X		goto HITFOE;
X	else if (foespeed > speed)
X		goto WAIT;
X	else if (stat->lvl > foe->lvl)
X		goto HITFOE;
X	else if (foe->lvl > stat->lvl)
X		goto WAIT;
X	else	/* no one is faster */
X		{
X		printw("You can't fight %s yet.",foename);
X		goto LEAVE;
X		}
X
X/* routine to hit, etc */
XHITFOE:	printstats(stat);
X	mvprintw(1,26,"%20.0f",myhits);
X	mvaddstr(4,0,"1:Fight  2:Run Away!  3:Power Blast  ");
X	if (luckout)
X		clrtoeol();
X	else
X		addstr("4:Luckout  ");
X	ch = gch(stat->rng.type);
X	move(lines = 5,0);
X	clrtobot();
X	switch (ch)
X		{
X		default:	/* fight */
X			temp = roll(2,strength);
XHIT:			mvprintw(lines++,0,"You hit %s %.0f times!",foename,temp);
X			stat->sin += 0.5;
X			stat->scratch1 += temp;
X			stat->scratch2 = FALSE;
X			break;
X		case '2':	/* run away */
X			--stat->scratch1;	/* this value changes to indicate action */
X			if (rnd() > 0.25)
X				{
X				mvaddstr(lines++,0,"You got away!");
X				stat->scratch2 = RAN;
X				goto LEAVE;
X				}
X			mvprintw(lines++,0,"%s is still after you!",foename);
X			stat->scratch2 = STUCK;
X			break;
X		case '3':	/* power blast */
X			temp = min(stat->man,stat->lvl*5);
X			stat->man -= temp;
X			temp = (rnd() + 0.5) * temp * stat->mag * 0.2 + 2;
X			mvprintw(lines++,0,"You blasted %s !",foename);
X			goto HIT;
X		case '4':	/* luckout */
X			if (luckout || rnd() > 0.1)
X				{
X				luckout = TRUE;
X				mvaddstr(lines++,0,"Not this time...");
X				--stat->scratch1;
X				stat->scratch2 = BLEWIT;
X				}
X			else
X				{
X				mvaddstr(lines++,0,"You just lucked out!");
X				stat->scratch1 = foe->nrg + 5;
X				}
X			break;
X		}
X	refresh();
X	stat->scratch1 = floor(stat->scratch1);		/* clean up any mess */
X	if (stat->scratch1 > foe->nrg)
X		stat->scratch2 = KILLED;
X	else if (rnd() * speed < rnd() * foespeed)
X		{		/* foe's turn */
X		++stat->tampered;
X		updateme();
X		goto WAIT;
X		}
X	updateme();
X
X	if (((int) stat->scratch2) == KILLED)
X		{
X		mvprintw(lines++,0,"You killed %s!",foename);
X		stat->exp += foe->exp;
X		stat->crn += (stat->lvl < 1000) ? foe->crn : 0;
X		stat->amu += foe->amu;
X		stat->chm += foe->chm;
X		stat->gld += foe->gld;
X		stat->gem += foe->gem;
X		stat->swd = max(stat->swd,foe->swd);
X		stat->shd = max(stat->shd,foe->shd);
X		stat->quks = max(stat->quks,foe->quks);
X		sleep(3);	  /* give other person time to die */
X		goto LEAVE;
X		}
X	goto HITFOE;	/* otherwise, my turn again */
X
X/* routine to wait for foe to do something */
XWAIT:	printstats(stat);
X	mvprintw(1,26,"%20.0f",myhits);
X	mvaddstr(4,0,"Waiting...\n");
X	refresh();
X	for (loop = MAXWAIT; loop; --loop)
X		{
X		readfoe();
X		if (foe->scratch1 != oldhits)
X			switch ((int) foe->scratch2)
X				{
X				case RAN:
X					mvprintw(lines++,0,"%s ran away!",foename);
X					goto LEAVE;
X				case STUCK:
X					mvprintw(lines++,0,"%s tried to run away.",foename);
X					goto BOT;
X				case BLEWIT:
X					mvprintw(lines++,0,"%s tried to luckout!",foename);
X					goto BOT;
X				default:
X					temp = foe->scratch1 - oldhits;
X					mvprintw(lines++,0,"%s hit you %.0f times!",foename,temp);
X					myhits -= temp;
X					goto BOT;
X				}
X		sleep(1);
X		}
X	/* timeout */
X	mvaddstr(23,0,"Timeout: waiting for response.  Do you want to wait ? ");
X	refresh();
X	ch = getch();
X	move(23,0);
X	clrtoeol();
X	if (toupper(ch) == 'Y')
X		goto WAIT;
X	goto LEAVE;
X
X/* routine to decide what happens next */
XBOT:	refresh();
X	if (lines > 21)
X		{
X		paws(lines);
X		move(lines = 5,0);
X		clrtobot();
X		}
X	if (((int) foe->scratch2) == KILLED || myhits < 0.0)
X		{
X		myhits = -2;
X		goto LEAVE;		/* main will pick up death */
X		}
X	oldhits = foe->scratch1;
X	if (foe->tampered != oldtags)
X		{
X		oldtags = foe->tampered;
X		goto HITFOE;
X		}
X	goto WAIT;
X
X/* routine to clean up things and leave */
XLEAVE:	updateme();
X	fclose(fin);
X	fclose(fout);
X	stat->x += roll(5,-10);
X	stat->y += roll(5,-10);
X	stat->nrg = myhits;
X	stat->tampered = OFF;
X	stat->status = PLAYING;
X	changed = TRUE;
X	paws(lines);
X	move(3,0);
X	clrtobot();
X}
X
Xint	interrupt()				/* call when break key is hit */
X{
Xchar	line[81];
Xreg	int	loop;
Xint	x, y, ch;
X
X#ifdef USG3
X	signal(SIGINT,SIG_IGN);
X#endif
X#ifdef USG5
X	signal(SIGINT,SIG_IGN);
X#endif
X	getyx(stdscr,y,x);
X	for (loop = 79; loop >= 0; --loop)	/* snarf line */
X		{
X		move(4,loop);
X		line[loop] = inch();
X		}
X	line[80] = '\0';
X	clrtoeol();
X	if (fghting)
X		{
X		move(4,0);
X		clrtoeol();
X		addstr("Quitting now will automatically kill your character.  Still want to ? ");
X		ch = rgetch();
X		if (toupper(ch) == 'Y')
X			longjmp(mainenv,DIE);
X		}
X	else
X		{
X		move(4,0);
X		clrtoeol();
X		addstr("Do you really want to quit ? ");
X		ch = rgetch();
X		if (toupper(ch) == 'Y')
X			longjmp(mainenv,QUIT);
X		}
X	mvaddstr(4,0,line);	/* return screen to previous state */
X	move(y,x);
X	refresh();
X#ifdef USG3
X	signal(SIGINT,interrupt);
X#endif
X#ifdef USG5
X	signal(SIGINT,interrupt);
X#endif
X}
X
Xint	rgetch()		/* refresh, then get a char. */
X{
X	refresh();
X	return (getch());
X}
X
Xvoid	purge() 	/* remove old players */
X{
XFILE	*fin, *fout;
Xstruct	stats	sbuf;
Xreg	int	loc, today, temp;
Xlong	ltime;
X
X	loc = 0;
X	time(&ltime);
X	today = localtime(&ltime)->tm_yday;
X	fin = fopen(peoplefile,"r");
X	fout = fopen(peoplefile,ACCESS);
X	while(fread((char *) &sbuf,sizeof(sbuf),1,fin))
X		{
X		temp = today - sbuf.lastused;
X		if (temp < 0)
X			temp += 365;
X		if (temp > 9)		/* ten days old --> delete */
X			{
X			initchar(&sbuf);
X			strcpy(sbuf.name,"<null>");
X			fseek(fout,(long) loc * sizeof(sbuf),0);
X			fwrite((char *) &sbuf,sizeof(sbuf),1,fout);
X			}
X		++loc;
X		}
X	fclose(fin);
X	fclose(fout);
X}
!EOR!
echo extracting - 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