Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site tty3b.UUCP Path: utzoo!watmath!clyde!burl!mgnetp!ltuxa!tty3b!estes From: estes@tty3b.UUCP (8-01-83"Edward E 9723i) Newsgroups: net.sources Subject: Phantasia (part 3 of 3) Message-ID: <491@tty3b.UUCP> Date: Fri, 7-Sep-84 18:14:53 EDT Article-I.D.: tty3b.491 Posted: Fri Sep 7 18:14:53 1984 Date-Received: Thu, 13-Sep-84 06:14:53 EDT Organization: Teletype Corp., Skokie, Ill Lines: 2036 ------------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,""); 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 X#include /* used for counting users on system */ X Xbool ok_to_play() /* return FALSE if playing is not allowed at this time */ X{ X#define MAXUSERS 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!