Google Groups không còn hỗ trợ đăng ký sử dụng hoặc đăng nội dung mới trên Usenet. Bạn vẫn có thể xem nội dung cũ.

VMS Larn 12.0 is here! (part 5 of 6)

35 lượt xem
Chuyển tới thư đầu tiên chưa đọc

u566393908ea

chưa đọc,
18:06:34 30 thg 8, 198630/8/86
đến
Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save
his/her daughter!! Just unpack using /bin/sh and read readme.txt.

- Mark Nagel

P.S. Thanks to Lord Kahless for letting me post this!

-------------------------------cut here-------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# monster.c
# regen.c
# savelev.c
# signal.c
# tok.c
# This archive created: Sat Aug 30 14:52:16 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'monster.c'" '(45763 characters)'
if test -f 'monster.c'
then
echo shar: will not over-write existing file "'monster.c'"
else
cat << \SHAR_EOF > 'monster.c'

/*
* monster.c Larn is copyrighted 1986 by Noah Morgan.
*
*This file contains the following functions:
*----------------------------------------------------------------------------
*
*createmonster(monstno) Function to create a monster next to the player
*int monstno;
*
*int cgood(x,y,itm,monst) Function to check location for emptiness
*int x,y,itm,monst;
*
*createitem(it,arg) Routine to place an item next to the player
*int it,arg;
*
*cast() Subroutine called by parse to cast a spell for the user
*
*speldamage(x) Function to perform spell functions cast by the player
*int x;
*
*loseint() Routine to decrement your int(intelligence) if > 3
*
*isconfuse() Routine to check to see if player is confused
*
*nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster
*int x,monst;
*
*fullhit(xx) Function to return full damage against a monst(aka web)
*int xx;
*
*direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir
*int spnum,dam,arg;
*char *str;
*
*godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks
*int spnum,dam,delay;
*char *str,cshow;
*
*ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt
*int x,y;
*
*tdirect(spnum) Routine to teleport away a monster
*int spnum;
*
*omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player
*int sp,dam;
*char *str;
*
*dirsub(x,y) Routine to ask for direction, then modify x,y for it
*int *x,*y;
*
*vxy(x,y) Routine to verify/fix(*x,*y) for being within bounds
*int *x,*y;
*
*dirpoly(spnum) Routine to ask for a direction and polymorph a monst
*int spnum;
*
*hitmonster(x,y) Function to hit a monster at the designated coordinates
*int x,y;
*
*hitm(x,y,amt) Function to just hit a monster at a given coordinates
*int x,y,amt;
*
*hitplayer(x,y) Function for the monster to hit the player from(x,y)
*int x,y;
*
*dropsomething(monst) Function to create an object when a monster dies
*int monst;
*
*dropgold(amount) Function to drop some gold around player
*int amount;
*
*something(level) Function to create a random item around player
*int level;
*
*newobject(lev,i) Routine to return a randomly selected new object
*int lev,*i;
*
*spattack(atckno,xx,yy) Function to process special attacks from monsters
*int atckno,xx,yy;
*
*checkloss(x) Routine to subtract hp from user and flag bottomline display
*int x;
*
*annihilate() Routine to annihilate monsters around player, playerx,playery
*
*newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation
*int x,y,dir,lifetime;
*
*rmsphere(x,y) Function to delete a sphere of annihilation from list
*int x,y;
*
*sphboom(x,y) Function to perform the effects of a sphere detonation
*int x,y;
*
*genmonst() Function to ask for monster and genocide from game
*
*/

#include "header.h"

struct isave { /* used for alter reality */
char type; /* 0=item, 1=monster */
char id; /* item number or monster number */
short arg; /* the type of item or hitpoints of monster */
};

/*
*createmonster(monstno) Function to create a monster next to the player
*int monstno;
*
* Enter with the monster number(1 to MAXMONST+8)
* Returns no value.
*/
createmonster(mon)
int mon;
{
register int x,
y,
k,
i;
if (mon < 1 || mon > MAXMONST + 8) {/* check for monster number out of bounds */
beep();
lprintf("\ncan't createmonst(%d)\n",(long) mon);
nap(3000);
return;
}
while (monster[mon].genocided && mon < MAXMONST)
mon++; /* genocided? */
for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */
if (k > 8)
k = 1; /* wraparound the diroff arrays */
x = playerx + diroffx[k];
y = playery + diroffy[k];
if (cgood(x, y, 0, 1)) {/* if we can create here */
mitem[x][y] = mon;
hitp[x][y] = monster[mon].hitpoints;
stealth[x][y] = know[x][y] = 0;
switch(mon) {
case ROTHE:
case POLTERGEIST:
case VAMPIRE:
stealth[x][y] = 1;
};
return;
}
}
}

/*
* int cgood(x,y,itm,monst) Function to check location for emptiness
* int x,y,itm,monst;
*
* Routine to return TRUE if a location does not have itm or monst there
* returns FALSE(0) otherwise
* Enter with itm or monst TRUE or FALSE if checking it
* Example: if itm==TRUE check for no item at this location
* if monst==TRUE check for no monster at this location
* This routine will return FALSE if at a wall or the dungeon exit on level 1
*/
int cgood(x, y, itm, monst)
register int x,
y;
int itm,
monst;
{
if ((y >= 0) && (y <= MAXY - 1) && (x >= 0) && (x <= MAXX - 1))/* within bounds? */
if (item[x][y] != OWALL)/* can't make anything on walls */
if (itm == 0 || (item[x][y] == 0))/* is it free of items? */
if (monst == 0 || (mitem[x][y] == 0))/* is it free of monsters? */
if ((level != 1) || (x != 33) || (y != MAXY - 1))/* not exit to level 1 */
return(1);
return(0);
}

/*
* createitem(it,arg) Routine to place an item next to the player
* int it,arg;
*
* Enter with the item number and its argument(iven[], ivenarg[])
* Returns no value, thus we don't know about createitem() failures.
*/
createitem(it, arg)
int it,
arg;
{
register int x,
y,
k,
i;
if (it >= MAXOBJ)
return; /* no such object */
for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */
if (k > 8)
k = 1; /* wraparound the diroff arrays */
x = playerx + diroffx[k];
y = playery + diroffy[k];
if (cgood(x, y, 1, 0)) {/* if we can create here */
item[x][y] = it;
know[x][y] = 0;
iarg[x][y] = arg;
return;
}
}
}

/*
* cast() Subroutine called by parse to cast a spell for the user
*
* No arguments and no return value.
*/
static char eys[] = "\nEnter your spell: ";
cast()
{
register int i,j,a,b,d;

cursors();
if (c[SPELLS] <= 0) {
lprcat("\nYou don't have any spells!");
return;
}
lprcat(eys);
--c[SPELLS];
while ((a = readchar()) == 'D') {
seemagic(-1);
cursors();
lprcat(eys);
}
if (a == '\33')
goto over; /* to escape casting a spell */
if ((b = readchar()) == '\33')
goto over; /* to escape casting a spell */
if ((d = readchar()) == '\33') {
over:
lprcat(aborted);
c[SPELLS]++;
return;
} /* to escape casting a spell */
#ifdef EXTRA
c[SPELLSCAST]++;
#endif
for (lprc('\n'), j = -1, i = 0; i < SPNUM; i++)/* seq search for his spell, hash? */
if ((spelcode[i][0] == a) && (spelcode[i][1] == b) && (spelcode[i][2] == d))
if (spelknow[i]) {
speldamage(i);
j = 1;
i = SPNUM;
}

if (j == -1)
lprcat(" Nothing Happened ");
bottomline();
}

/*
* speldamage(x) Function to perform spell functions cast by the player
* int x;
*
* Enter with the spell number, returns no value.
* Please insure that there are 2 spaces before all messages here
*/
speldamage(x)
int x;
{
register int i,
j,
clev;
int xl,
xh,
yl,
yh;
register char *p,
*kn,
*pm;
if (x >= SPNUM)
return; /* no such spell */
if (c[TIMESTOP]) {
lprcat(" It didn't seem to work");
return;
} /* not if time stopped */
clev = c[LEVEL];
if ((rnd(23) == 7) || (rnd(18) > c[INTELLIGENCE])) {
lprcat(" It didn't work!");
return;
}
if (clev * 3 + 2 < x) {
lprcat(" Nothing happens. You seem inexperienced at this");
return;
}

switch(x) {
/* ----- LEVEL 1 SPELLS ----- */

case 0:
if (c[PROTECTIONTIME] == 0)
c[MOREDEFENSES] += 2;/* protection field +2 */
c[PROTECTIONTIME] += 250;
return;

case 1:
i = rnd(((clev + 1) << 1)) + clev + 3;
godirect(x, i,(clev >= 2) ? " Your missiles hit the %s" : " Your missile hit the %s", 100, '+');
/* magic missile */

return;

case 2:
if (c[DEXCOUNT] == 0)
c[DEXTERITY] += 3;/* dexterity */
c[DEXCOUNT] += 400;
return;

case 3:
i = rnd(3) + 1;
p = " While the %s slept, you smashed it %d times";
ws:
direct(x, fullhit(i), p, i);/* sleep */
return;

case 4: /* charm monster */
c[CHARMCOUNT] += c[CHARISMA] << 1;
return;

case 5:
godirect(x, rnd(10) + 15 + clev, " The sound damages the %s", 70, '@');/* sonic spear */
return;

/* ----- LEVEL 2 SPELLS ----- */

case 6:
i = rnd(3) + 2;
p = " While the %s is entangled, you hit %d times";
goto ws; /* web */

case 7:
if (c[STRCOUNT] == 0)
c[STREXTRA] += 3;/* strength */
c[STRCOUNT] += 150 + rnd(100);
return;

case 8:
yl = playery - 5; /* enlightenment */
yh = playery + 6;
xl = playerx - 15;
xh = playerx + 16;
vxy(&xl, &yl);
vxy(&xh, &yh); /* check bounds */
for (i = yl; i <= yh; i++)/* enlightenment */
for (j = xl; j <= xh; j++)
know[j][i] = 1;
draws(xl, xh + 1, yl, yh + 1);
return;

case 9:
raisehp(20 +(clev << 1));
return; /* healing */

case 10:
c[BLINDCOUNT] = 0;
return; /* cure blindness */

case 11:
createmonster(makemonst(level + 1) + 8);
return;

case 12:
if (rnd(11) + 7 <= c[WISDOM])
direct(x, rnd(20) + 20 + clev, " The %s believed!", 0);
else
lprcat(" It didn't believe the illusions!");
return;

case 13: /* if he has the amulet of invisibility then add more time */
for (j = i = 0; i < 26; i++)
if (iven[i] == OAMULET)
j += 1 + ivenarg[i];
c[INVISIBILITY] +=(j << 7) + 12;
return;

/* ----- LEVEL 3 SPELLS ----- */

case 14:
godirect(x, rnd(25 + clev) + 25 + clev, " The fireball hits the %s", 40, '*');
return; /* fireball */

case 15:
godirect(x, rnd(25) + 20 + clev, " Your cone of cold strikes the %s", 60, 'O');/* cold */
return;

case 16:
dirpoly(x);
return; /* polymorph */

case 17:
c[CANCELLATION] += 5 + clev;
return; /* cancellation */

case 18:
c[HASTESELF] += 7 + clev;
return; /* haste self */

case 19:
omnidirect(x, 30 + rnd(10), " The %s gasps for air");/* cloud kill */
return;

case 20:
xh = min(playerx + 1, MAXX - 2);
yh = min(playery + 1, MAXY - 2);
for (i = max(playerx - 1, 1); i <= xh; i++)/* vaporize rock */
for (j = max(playery - 1, 1); j <= yh; j++) {
kn = &know[i][j];
pm = &mitem[i][j];
switch(*(p = &item[i][j])) {
case OWALL:
if (level < MAXLEVEL + MAXVLEVEL - 1)
*p = *kn = 0;
break;

case OSTATUE:
if (c[HARDGAME] < 3) {
*p = OBOOK;
iarg[i][j] = level;
*kn = 0;
}
break;

case OTHRONE:
*pm = GNOMEKING;
*kn = 0;
*p = OTHRONE2;
hitp[i][j] = monster[GNOMEKING].hitpoints;
break;

case OALTAR:
*pm = DEMONPRINCE;
*kn = 0;
hitp[i][j] = monster[DEMONPRINCE].hitpoints;
break;
};
switch(*pm) {
case XORN:
ifblind(i, j);
hitm(i, j, 200);
break;/* Xorn takes damage from vpr */
}
}
return;

/* ----- LEVEL 4 SPELLS ----- */

case 21:
direct(x, 100 + clev, " The %s shrivels up", 0);/* dehydration */
return;

case 22:
godirect(x, rnd(25) + 20 +(clev << 1), " A lightning bolt hits the %s", 1, '~');/* lightning */
return;

case 23:
i = min(c[HP] - 1, c[HPMAX] / 2);/* drain life */
direct(x, i + i, "", 0);
c[HP] -= i;
return;

case 24:
if (c[GLOBE] == 0)
c[MOREDEFENSES] += 10;
c[GLOBE] += 200;
loseint(); /* globe of invulnerability */
return;

case 25:
omnidirect(x, 32 + clev, " The %s struggles for air in your flood!");/* flood */
return;

case 26:
if (rnd(151) == 63) {
beep();
lprcat("\nYour heart stopped!\n");
nap(4000);
died(270);
return;
}
if (c[WISDOM] > rnd(10) + 10)
direct(x, 2000, " The %s's heart stopped", 0);/* finger of death */
else
lprcat(" It didn't work");
return;

/* ----- LEVEL 5 SPELLS ----- */

case 27:
c[SCAREMONST] += rnd(10) + clev;
return; /* scare monster */

case 28:
c[HOLDMONST] += rnd(10) + clev;
return; /* hold monster */

case 29:
c[TIMESTOP] += rnd(20) +(clev << 1);
return; /* time stop */

case 30:
tdirect(x);
return; /* teleport away */

case 31:
omnidirect(x, 35 + rnd(10) + clev, " The %s cringes from the flame");/* magic fire */
return;

/* ----- LEVEL 6 SPELLS ----- */

case 32:
if ((rnd(23) == 5) && (wizard == 0)) {/* sphere of annihilation */
beep();
lprcat("\nYou have been enveloped by the zone of nothingness!\n");
nap(4000);
died(258);
return;
}
xl = playerx;
yl = playery;
loseint();
i = dirsub(&xl, &yl);/* get direction of sphere */
newsphere(xl, yl, i, rnd(20) + 11);/* make a sphere */
return;

case 33:
genmonst();
spelknow[33] = 0; /* genocide */
loseint();
return;

case 34: /* summon demon */
if (rnd(100) > 30) {
direct(x, 150, " The demon strikes at the %s", 0);
return;
}
if (rnd(100) > 15) {
lprcat(" Nothing seems to have happened");
return;
}
lprcat(" The demon turned on you and vanished!");
beep();
i = rnd(40) + 30;
lastnum = 277;
losehp(i); /* must say killed by a demon */
return;

case 35: /* walk through walls */
c[WTW] += rnd(10) + 5;
return;

case 36: /* alter reality */
{
struct isave *save;/* pointer to item save structure */
int sc;
sc = 0; /* # items saved */
save =(struct isave *) malloc(sizeof(struct isave) * MAXX * MAXY * 2);
for (j = 0; j < MAXY; j++)
for (i = 0; i < MAXX; i++) {/* save all items and monsters */
xl = item[i][j];
if (xl && xl != OWALL && xl != OANNIHILATION) {
save[sc].type = 0;
save[sc].id = item[i][j];
save[sc++].arg = iarg[i][j];
}
if (mitem[i][j]) {
save[sc].type = 1;
save[sc].id = mitem[i][j];
save[sc++].arg = hitp[i][j];
}
item[i][j] = OWALL;
mitem[i][j] = 0;
if (wizard)
know[i][j] = 1;
else
know[i][j] = 0;
}
eat(1, 1);
if (level == 1)
item[33][MAXY - 1] = 0;
for (j = rnd(MAXY - 2), i = 1; i < MAXX - 1; i++)
item[i][j] = 0;
while (sc > 0) {/* put objects back in level */
--sc;
if (save[sc].type == 0) {
int trys;
for (trys = 100, i = j = 1; --trys > 0 && item[i][j]; i = rnd(MAXX - 1), j = rnd(MAXY - 1));
if (trys) {
item[i][j] = save[sc].id;
iarg[i][j] = save[sc].arg;
}
}
else { /* put monsters back in */
int trys;
for (trys = 100, i = j = 1; --trys > 0 && (item[i][j] == OWALL || mitem[i][j]); i = rnd(MAXX - 1), j = rnd(MAXY - 1));
if (trys) {
mitem[i][j] = save[sc].id;
hitp[i][j] = save[sc].arg;
}
}
}
loseint();
draws(0, MAXX, 0, MAXY);
if (wizard == 0)
spelknow[36] = 0;
free((char *) save);
positionplayer();
return;
}

case 37: /* permanence */
adjtime(-99999L);
spelknow[37] = 0; /* forget */
loseint();
return;

default:
lprintf(" spell %d not available!",(long) x);
beep();
return;
};
}

/*
* loseint() Routine to subtract 1 from your int(intelligence) if > 3
*
* No arguments and no return value
*/
loseint()
{
if (--c[INTELLIGENCE] < 3)
c[INTELLIGENCE] = 3;
}

/*
* isconfuse() Routine to check to see if player is confused
*
* This routine prints out a message saying "You can't aim your magic!"
* returns 0 if not confused, non-zero(time remaining confused) if confused
*/
isconfuse()
{
if (c[CONFUSE]) {
lprcat(" You can't aim your magic!");
beep();
}
return(c[CONFUSE]);
}

/*
* nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster
* int x,monst;
*
* Subroutine to return 1 if the spell can't affect the monster
* otherwise returns 0
* Enter with the spell number in x, and the monster number in monst.
*/
nospell(x, monst)
int x,
monst;
{
register int tmp;
if (x >= SPNUM || monst >= MAXMONST + 8 || monst < 0 || x < 0)
return(0); /* bad spell or monst */
if ((tmp = spelweird[monst - 1][x]) == 0)
return(0);
cursors();
lprc('\n');
lprintf(spelmes[tmp], monster[monst].name);
return(1);
}

/*
* fullhit(xx) Function to return full damage against a monster(aka web)
* int xx;
*
* Function to return hp damage to monster due to a number of full hits
* Enter with the number of full hits being done
*/
fullhit(xx)
int xx;
{
register int i;
if (xx < 0 || xx > 20)
return(0); /* fullhits are out of range */
if (c[LANCEDEATH])
return(10000); /* lance of death */
i = xx *((c[WCLASS] >> 1) + c[STRENGTH] + c[STREXTRA] - c[HARDGAME] - 12 + c[MOREDAM]);
return((i >= 1) ? i : xx);
}

/*
* direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir
* int spnum,dam,arg;
* char *str;
*
* Routine to ask for a direction to a spell and then hit the monster
* Enter with the spell number in spnum, the damage to be done in dam,
* lprintf format string in str, and lprintf's argument in arg.
* Returns no value.
*/
direct(spnum, dam, str, arg)
int spnum,
dam,
arg;
char *str;
{
int x,
y;
register int m;
if (spnum < 0 || spnum >= SPNUM || str == 0)
return; /* bad arguments */
if (isconfuse())
return;
dirsub(&x, &y);
m = mitem[x][y];
if (item[x][y] == OMIRROR) {
if (spnum == 3) { /* sleep */
lprcat("You fall asleep! ");
beep();
fool:
arg += 2;
while (arg-- > 0) {
parse2();
nap(1000);
}
return;
}
else
if (spnum == 6) { /* web */
lprcat("You get stuck in your own web! ");
beep();
goto fool;
}
else {
lastnum = 278;
lprintf(str, "spell caster(thats you)",(long) arg);
beep();
losehp(dam);
return;
}
}
if (m == 0) {
lprcat(" There wasn't anything there!");
return;
}
ifblind(x, y);
if (nospell(spnum, m)) {
lasthx = x;
lasthy = y;
return;
}
lprintf(str, lastmonst,(long) arg);
hitm(x, y, dam);
}

/*
* godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks
* int spnum,dam,delay;
* char *str,cshow;
*
* Function to hit in a direction from a missile weapon and have it keep
* on going in that direction until its power is exhausted
* Enter with the spell number in spnum, the power of the weapon in hp,
* lprintf format string in str, the # of milliseconds to delay between
* locations in delay, and the character to represent the weapon in cshow.
* Returns no value.
*/
godirect(spnum, dam, str, delay, cshow)
int spnum,
dam,
delay;
char *str,
cshow;
{
register char *p;
register int x,
y,
m;
int dx,
dy;
if (spnum < 0 || spnum >= SPNUM || str == 0 || delay < 0)
return; /* bad args */
if (isconfuse())
return;
dirsub(&dx, &dy);
x = dx;
y = dy;
dx = x - playerx;
dy = y - playery;
x = playerx;
y = playery;
while (dam > 0) {
x += dx;
y += dy;
if ((x > MAXX - 1) || (y > MAXY - 1) || (x < 0) || (y < 0)) {
dam = 0;
break; /* out of bounds */
}
if ((x == playerx) && (y == playery)) {/* if energy hits player */
cursors();
lprcat("\nYou are hit my your own magic!");
beep();
lastnum = 278;
losehp(dam);
return;
}
if (c[BLINDCOUNT] == 0) {/* if not blind show effect */
cursor(x + 1, y + 1);
lprc(cshow);
nap(delay);
show1cell(x, y);
}
if ((m = mitem[x][y])) {/* is there a monster there? */
ifblind(x, y);
if (nospell(spnum, m)) {
lasthx = x;
lasthy = y;
return;
}
cursors();
lprc('\n');
lprintf(str, lastmonst);
dam -= hitm(x, y, dam);
show1cell(x, y);
nap(1000);
x -= dx;
y -= dy;
}
else
switch(*(p = &item[x][y])) {
case OWALL:
cursors();
lprc('\n');
lprintf(str, "wall");
if (dam >= 50 + c[HARDGAME])/* enough damage? */
if (level < MAXLEVEL + MAXVLEVEL - 1)/* not on V3 */
if ((x < MAXX - 1) && (y < MAXY - 1) && (x) && (y)) {
lprcat(" The wall crumbles");
god3:
*p = 0;
god:
know[x][y] = 0;
show1cell(x, y);
}
god2:
dam = 0;
break;

case OCLOSEDDOOR:
cursors();
lprc('\n');
lprintf(str, "door");
if (dam >= 40) {
lprcat(" The door is blasted apart");
goto god3;
}
goto god2;

case OSTATUE:
cursors();
lprc('\n');
lprintf(str, "statue");
if (c[HARDGAME] < 3)
if (dam > 44) {
lprcat(" The statue crumbles");
*p = OBOOK;
iarg[x][y] = level;
goto god;
}
goto god2;

case OTHRONE:
cursors();
lprc('\n');
lprintf(str, "throne");
if (dam > 39) {
mitem[x][y] = GNOMEKING;
hitp[x][y] = monster[GNOMEKING].hitpoints;
*p = OTHRONE2;
goto god;
}
goto god2;

case OMIRROR:
dx *= -1;
dy *= -1;
break;
};
dam -= 3 +(c[HARDGAME] >> 1);
}
}

/*
* ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt
* int x,y;
*
* Subroutine to copy the word "monster" into lastmonst if the player is blind
* Enter with the coordinates(x,y) of the monster
* Returns no value.
*/
ifblind(x, y)
int x,
y;
{
char *p;
vxy(&x, &y); /* verify correct x,y coordinates */
if (c[BLINDCOUNT]) {
lastnum = 279;
p = "monster";
}
else {
lastnum = mitem[x][y];
p = monster[lastnum].name;
}
strcpy(lastmonst, p);
}

/*
* tdirect(spnum) Routine to teleport away a monster
* int spnum;
*
* Routine to ask for a direction to a spell and then teleport away monster
* Enter with the spell number that wants to teleport away
* Returns no value.
*/
tdirect(spnum)
int spnum;
{
int x,
y;
register int m;
if (spnum < 0 || spnum >= SPNUM)
return; /* bad args */
if (isconfuse())
return;
dirsub(&x, &y);
if ((m = mitem[x][y]) == 0) {
lprcat(" There wasn't anything there!");
return;
}
ifblind(x, y);
if (nospell(spnum, m)) {
lasthx = x;
lasthy = y;
return;
}
fillmonst(m);
mitem[x][y] = know[x][y] = 0;
}

/*
* omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player
* int sp,dam;
* char *str;
*
* Routine to cast a spell and then hit the monster in all directions
* Enter with the spell number in sp, the damage done to wach square in dam,
* and the lprintf string to identify the spell in str.
* Returns no value.
*/
omnidirect(spnum, dam, str)
int spnum,
dam;
char *str;
{
register int x,
y,
m;
if (spnum < 0 || spnum >= SPNUM || str == 0)
return; /* bad args */
for (x = playerx - 1; x < playerx + 2; x++)
for (y = playery - 1; y < playery + 2; y++) {
if (m = mitem[x][y])
if (nospell(spnum, m) == 0) {
ifblind(x, y);
cursors();
lprc('\n');
lprintf(str, lastmonst);
hitm(x, y, dam);
nap(800);
}
else {
lasthx = x;
lasthy = y;
}
}
}

/*
* static dirsub(x,y) Routine to ask for direction, then modify x,y for it
* int *x,*y;
*
* Function to ask for a direction and modify an x,y for that direction
* Enter with the origination coordinates in(x,y).
* Returns index into diroffx[](0-8).
*/
static dirsub(x, y)
int *x,
*y;
{
register int i;
lprcat("\nIn What Direction? ");
for (i = 0;;)
switch(readchar()) {
case 'b':
i++;
case 'n':
i++;
case 'y':
i++;
case 'u':
i++;
case 'h':
i++;
case 'k':
i++;
case 'l':
i++;
case 'j':
i++;
goto out;
};
out:
*x = playerx + diroffx[i];
*y = playery + diroffy[i];
vxy(x, y);
return(i);
}

/*
* vxy(x,y) Routine to verify/fix coordinates for being within bounds
* int *x,*y;
*
* Function to verify x & y are within the bounds for a level
* If *x or *y is not within the absolute bounds for a level, fix them so that
* they are on the level.
* Returns TRUE if it was out of bounds, and the *x & *y in the calling
* routine are affected.
*/
vxy(x, y)
int *x,
*y;
{
int flag = 0;
if (*x < 0) {
*x = 0;
flag++;
}
if (*y < 0) {
*y = 0;
flag++;
}
if (*x >= MAXX) {
*x = MAXX - 1;
flag++;
}
if (*y >= MAXY) {
*y = MAXY - 1;
flag++;
}
return(flag);
}

/*
* dirpoly(spnum) Routine to ask for a direction and polymorph a monst
* int spnum;
*
* Subroutine to polymorph a monster and ask for the direction its in
* Enter with the spell number in spmun.
* Returns no value.
*/
dirpoly(spnum)
int spnum;
{
int x,
y,
m;
if (spnum < 0 || spnum >= SPNUM)
return; /* bad args */
if (isconfuse())
return; /* if he is confused, he can't aim his magic */
dirsub(&x, &y);
if (mitem[x][y] == 0) {
lprcat(" There wasn't anything there!");
return;
}
ifblind(x, y);
if (nospell(spnum, mitem[x][y])) {
lasthx = x;
lasthy = y;
return;
}
while (monster[m = mitem[x][y] = rnd(MAXMONST + 7)].genocided);
hitp[x][y] = monster[m].hitpoints;
show1cell(x, y); /* show the new monster */
}

/*
* hitmonster(x,y) Function to hit a monster at the designated coordinates
* int x,y;
*
* This routine is used for a bash & slash type attack on a monster
* Enter with the coordinates of the monster in(x,y).
* Returns no value.
*/
hitmonster(x, y)
int x,
y;
{
register int tmp,
monst,
damag,
flag;
if (c[TIMESTOP])
return; /* not if time stopped */
vxy(&x, &y); /* verify coordinates are within range */
if ((monst = mitem[x][y]) == 0)
return;
hit3flag = 1;
ifblind(x, y);
tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS] / 4 - 12;
cursors();
if ((rnd(20) < tmp - c[HARDGAME]) || (rnd(71) < 5)) {/* need at least random chance to hit */
lprcat("\nYou hit");
flag = 1;
damag = fullhit(1);
if (damag < 9999)
damag = rnd(damag) + 1;
}
else {
lprcat("\nYou missed");
flag = 0;
}
lprcat(" the ");
lprcat(lastmonst);
if (flag) /* if the monster was hit */
if ((monst == RUSTMONSTER) || (monst == DISENCHANTRESS) || (monst == CUBE))
if (c[WIELD] > 0)
if (ivenarg[c[WIELD]] > -10) {
lprintf("\nYour weapon is dulled by the %s", lastmonst);
beep();
--ivenarg[c[WIELD]];
}
if (flag)
hitm(x, y, damag);
if (monst == VAMPIRE)
if (hitp[x][y] < 25) {
mitem[x][y] = BAT;
know[x][y] = 0;
}
}

/*
* hitm(x,y,amt) Function to just hit a monster at a given coordinates
* int x,y,amt;
*
* Returns the number of hitpoints the monster absorbed
* This routine is used to specifically damage a monster at a location(x,y)
* Called by hitmonster(x,y)
*/
hitm(x, y, amt)
int x,
y;
register amt;
{
register int monst;
int hpoints,
amt2;
vxy(&x, &y); /* verify coordinates are within range */
amt2 = amt; /* save initial damage so we can return it */
monst = mitem[x][y];
if (c[HALFDAM])
amt >>= 1; /* if half damage curse adjust damage points */
if (amt <= 0)
amt2 = amt = 1;
lasthx = x;
lasthy = y;
stealth[x][y] = 1; /* make sure hitting monst breaks stealth condition */
c[HOLDMONST] = 0; /* hit a monster breaks hold monster spell */
switch(monst) { /* if a dragon and orb(s) of dragon slaying */
case WHITEDRAGON:
case REDDRAGON:
case GREENDRAGON:
case BRONZEDRAGON:
case PLATINUMDRAGON:
case SILVERDRAGON:
amt *= 1 +(c[SLAYING] << 1);
break;
}
/* invincible monster fix is here */
if (hitp[x][y] > monster[monst].hitpoints)
hitp[x][y] = monster[monst].hitpoints;
if ((hpoints = hitp[x][y]) <= amt) {
#ifdef EXTRA
c[MONSTKILLED]++;
#endif
lprintf("\nThe %s died!", lastmonst);
raiseexperience((long) monster[monst].experience);
amt = monster[monst].gold;
if (amt > 0)
dropgold(rnd(amt) + amt);
dropsomething(monst);
disappear(x, y);
bottomline();
return(hpoints);
}
hitp[x][y] = hpoints - amt;
return(amt2);
}

/*
* hitplayer(x,y) Function for the monster to hit the player from(x,y)
* int x,y;
*
* Function for the monster to hit the player with monster at location x,y
* Returns nothing of value.
*/
hitplayer(x, y)
int x,
y;
{
register int dam,
tmp,
mster,
bias;
vxy(&x, &y); /* verify coordinates are within range */
lastnum = mster = mitem[x][y];
/* spirit naga's and poltergeist's do nothing if scarab of negate spirit */
if (c[NEGATESPIRIT] || c[SPIRITPRO])
if ((mster == POLTERGEIST) || (mster == SPIRITNAGA))
return;
/* if undead and cube of undead control */
if (c[CUBEofUNDEAD] || c[UNDEADPRO])
if ((mster == VAMPIRE) || (mster == WRAITH) || (mster == ZOMBIE))
return;
if ((know[x][y] & 1) == 0) {
know[x][y] = 1;
show1cell(x, y);
}
bias =(c[HARDGAME]) + 1;
hitflag = hit2flag = hit3flag = 1;
yrepcount = 0;
cursors();
ifblind(x, y);
if (c[INVISIBILITY])
if (rnd(33) < 20) {
lprintf("\nThe %s misses wildly", lastmonst);
return;
}
if (c[CHARMCOUNT])
if (rnd(30) + 5 * monster[mster].level - c[CHARISMA] < 30) {
lprintf("\nThe %s is awestruck at your magnificence!", lastmonst);
return;
}
if (mster == BAT)
dam = 1;
else {
dam = monster[mster].damage;
dam += rnd((int)((dam < 1) ? 1 : dam)) + monster[mster].level;
}
tmp = 0;
if (monster[mster].attack > 0)
if (((dam + bias + 8) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) {
if (spattack(monster[mster].attack, x, y)) {
flushall();
return;
}
tmp = 1;
bias -= 2;
cursors();
}
if (((dam + bias) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) {
lprintf("\n The %s hit you ", lastmonst);
tmp = 1;
if ((dam -= c[AC]) < 0)
dam = 0;
if (dam > 0) {
losehp(dam);
bottomhp();
flushall();
}
}
if (tmp == 0)
lprintf("\n The %s missed ", lastmonst);
}

/*
* dropsomething(monst) Function to create an object when a monster dies
* int monst;
*
* Function to create an object near the player when certain monsters are killed
* Enter with the monster number
* Returns nothing of value.
*/
dropsomething(monst)
int monst;
{
switch(monst) {
case ORC:
case NYMPH:
case ELF:
case TROGLODYTE:
case TROLL:
case ROTHE:
case VIOLETFUNGI:
case PLATINUMDRAGON:
case GNOMEKING:
case REDDRAGON:
something(level);
return;

case LEPRECHAUN:
if (rnd(101) >= 75)
creategem();
if (rnd(5) == 1)
dropsomething(LEPRECHAUN);
return;
}
}

/*
* dropgold(amount) Function to drop some gold around player
* int amount;
*
* Enter with the number of gold pieces to drop
* Returns nothing of value.
*/
dropgold(amount)
register int amount;
{
if (amount > 250)
createitem(OMAXGOLD, amount / 100);
else
createitem(OGOLDPILE, amount);
}

/*
* something(level) Function to create a random item around player
* int level;
*
* Function to create an item from a designed probability around player
* Enter with the cave level on which something is to be dropped
* Returns nothing of value.
*/
something(level)
int level;
{
register int j;
int i;
if (level < 0 || level > MAXLEVEL + MAXVLEVEL)
return; /* correct level? */
if (rnd(101) < 8)
something(level); /* possibly more than one item */
j = newobject(level, &i);
createitem(j, i);
}

/*
* newobject(lev,i) Routine to return a randomly selected new object
* int lev,*i;
*
* Routine to return a randomly selected object to be created
* Returns the object number created, and sets *i for its argument
* Enter with the cave level and a pointer to the items arg
*/
static char nobjtab[] = {
0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION,
OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE,
OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER,
OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR,
OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE,
OLONGSWORD
};

newobject(lev, i)
register int lev,
*i;
{
register int tmp = 32,
j;
if (level < 0 || level > MAXLEVEL + MAXVLEVEL)
return(0); /* correct level? */
if (lev > 6)
tmp = 37;
else
if (lev > 4)
tmp = 35;
j = nobjtab[tmp = rnd(tmp)];/* the object type */
switch(tmp) {
case 1:
case 2:
case 3:
case 4:
*i = newscroll();
break;
case 5:
case 6:
case 7:
case 8:
*i = newpotion();
break;
case 9:
case 10:
case 11:
case 12:
*i = rnd((lev + 1) * 10) + lev * 10 + 10;
break;
case 13:
case 14:
case 15:
case 16:
*i = lev;
break;
case 17:
case 18:
case 19:
if (!(*i = newdagger()))
return(0);
break;
case 20:
case 21:
case 22:
if (!(*i = newleather()))
return(0);
break;
case 23:
case 32:
case 35:
*i = rund(lev / 3 + 1);
break;
case 24:
case 26:
*i = rnd(lev / 4 + 1);
break;
case 25:
*i = rund(lev / 4 + 1);
break;
case 27:
*i = rnd(lev / 2 + 1);
break;
case 30:
case 33:
*i = rund(lev / 2 + 1);
break;
case 28:
*i = rund(lev / 3 + 1);
if (*i == 0)
return(0);
break;
case 29:
case 31:
*i = rund(lev / 2 + 1);
if (*i == 0)
return(0);
break;
case 34:
*i = newchain();
break;
case 36:
*i = newplate();
break;
case 37:
*i = newsword();
break;
}
return(j);
}

/*
* spattack(atckno,xx,yy) Function to process special attacks from monsters
* int atckno,xx,yy;
*
* Enter with the special attack number, and the coordinates(xx,yy)
* of the monster that is special attacking
* Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise
*
* atckno monster effect
* ---------------------------------------------------
* 0 none
* 1 rust monster eat armor
* 2 hell hound breathe light fire
* 3 dragon breathe fire
* 4 giant centipede weakening sing
* 5 white dragon cold breath
* 6 wraith drain level
* 7 waterlord water gusher
* 8 leprechaun steal gold
* 9 disenchantress disenchant weapon or armor
* 10 ice lizard hits with barbed tail
* 11 umber hulk confusion
* 12 spirit naga cast spells taken from special attacks
* 13 platinum dragon psionics
* 14 nymph steal objects
* 15 bugbear bite
* 16 osequip bite
*
* char rustarm[ARMORTYPES][2];
* special array for maximum rust damage to armor from rustmonster
* format is: { armor type , minimum attribute
*/
#define ARMORTYPES 6
static char rustarm[ARMORTYPES][2] = {
OSTUDLEATHER, -2, ORING, -4, OCHAIN, -5,
OSPLINT, -6, OPLATE, -8, OPLATEARMOR, -9
};
static char spsel[] = {
1, 2, 3, 5, 6, 8, 9, 11, 13, 14
};
spattack(x, xx, yy)
int x,
xx,
yy;
{
register int i,
j = 0,
k,
m;
register char *p = 0;
if (c[CANCELLATION])
return(0);
vxy(&xx, &yy); /* verify x & y coordinates */
switch(x) {
case 1: /* rust your armor, j=1 when rusting has occurred */
m = k = c[WEAR];
if ((i = c[SHIELD]) != -1)
if (--ivenarg[i] < -1)
ivenarg[i] = -1;
else
j = 1;
if ((j == 0) && (k != -1)) {
m = iven[k];
for (i = 0; i < ARMORTYPES; i++)
if (m == rustarm[i][0]) {/* find his armor in table */
if (--ivenarg[k] < rustarm[i][1])
ivenarg[k] = rustarm[i][1];
else
j = 1;
break;
}
}
if (j == 0) /* if rusting did not occur */
switch(m) {
case OLEATHER:
p = "\nThe %s hit you -- Your lucky you have leather on";
break;
case OSSPLATE:
p = "\nThe %s hit you -- Your fortunate to have stainless steel armor!";
break;
}
else {
beep();
p = "\nThe %s hit you -- your armor feels weaker";
}
break;

case 2:
i = rnd(15) + 8 - c[AC];
spout:
p = "\nThe %s breathes fire at you!";
if (c[FIRERESISTANCE])
p = "\nThe %s's flame doesn't phase you!";
else
spout2:
if (p) {
lprintf(p, lastmonst);
beep();
}
checkloss(i);
return(0);

case 3:
i = rnd(20) + 25 - c[AC];
goto spout;

case 4:
if (c[STRENGTH] > 3) {
p = "\nThe %s stung you! You feel weaker";
beep();
--c[STRENGTH];
}
else
p = "\nThe %s stung you!";
break;

case 5:
p = "\nThe %s blasts you with his cold breath";
i = rnd(15) + 18 - c[AC];
goto spout2;

case 6:
lprintf("\nThe %s drains you of your life energy!", lastmonst);
loselevel();
beep();
return(0);

case 7:
p = "\nThe %s got you with a gusher!";
i = rnd(15) + 25 - c[AC];
goto spout2;

case 8:
if (c[NOTHEFT])
return(0); /* he has a device of no theft */
if (c[GOLD]) {
p = "\nThe %s hit you -- Your purse feels lighter";
if (c[GOLD] > 32767)
c[GOLD] >>= 1;
else
c[GOLD] -= rnd((int)(1 +(c[GOLD] >> 1)));
if (c[GOLD] < 0)
c[GOLD] = 0;
}
else
p = "\nThe %s couldn't find any gold to steal";
lprintf(p, lastmonst);
disappear(xx, yy);
beep();
bottomgold();
return(1);

case 9:
for (j = 50;;) { /* disenchant */
i = rund(26);
m = iven[i]; /* randomly select item */
if (m > 0 && ivenarg[i] > 0 && m != OSCROLL && m != OPOTION) {
if ((ivenarg[i] -= 3) < 0)
ivenarg[i] = 0;
lprintf("\nThe %s hits you -- you feel a sense of loss", lastmonst);
srcount = 0;
beep();
show3(i);
bottomline();
return(0);
}
if (--j <= 0) {
p = "\nThe %s nearly misses";
break;
}
break;
}
break;

case 10:
p = "\nThe %s hit you with his barbed tail";
i = rnd(25) - c[AC];
goto spout2;

case 11:
p = "\nThe %s has confused you";
beep();
c[CONFUSE] += 10 + rnd(10);
break;

case 12: /* performs any number of other special attacks */
return(spattack(spsel[rund(10)], xx, yy));

case 13:
p = "\nThe %s flattens you with his psionics!";
i = rnd(15) + 30 - c[AC];
goto spout2;

case 14:
if (c[NOTHEFT])
return(0); /* he has device of no theft */
if (emptyhanded() == 1) {
p = "\nThe %s couldn't find anything to steal";
break;
}
lprintf("\nThe %s picks your pocket and takes:", lastmonst);
beep();
if (stealsomething() == 0)
lprcat(" nothing");
disappear(xx, yy);
bottomline();
return(1);

case 15:
i = rnd(10) + 5 - c[AC];
spout3:
p = "\nThe %s bit you!";
goto spout2;

case 16:
i = rnd(15) + 10 - c[AC];
goto spout3;
};
if (p) {
lprintf(p, lastmonst);
bottomline();
}
return(0);
}

/*
* checkloss(x) Routine to subtract hp from user and flag bottomline display
* int x;
*
* Routine to subtract hitpoints from the user and flag the bottomline display
* Enter with the number of hit points to lose
* Note: if x > c[HP] this routine could kill the player!
*/
checkloss(x)
int x;
{
if (x > 0) {
losehp(x);
bottomhp();
}
}

/*
* annihilate() Routine to annihilate all monsters around player(playerx,playery)
*
* Gives player experience, but no dropped objects
* Returns the experience gained from all monsters killed
*/
annihilate()
{
int i,j;
register long k;
register char *p;

for (k = 0, i = playerx - 1; i <= playerx + 1; i++)
for (j = playery - 1; j <= playery + 1; j++)
if (!vxy(&i, &j)) /* if not out of bounds */
if (*(p = &mitem[i][j]))/* if a monster there */
if (*p < DEMONLORD + 2) {
k += monster[*p].experience;
*p = know[i][j] = 0;
}
else {
lprintf("\nThe %s barely escapes being annihilated!", monster[*p].name);
hitp[i][j] =(hitp[i][j] >> 1) + 1;/* lose half hit points */
}
if (k > 0) {
lprcat("\nYou hear loud screams of agony!");
raiseexperience((long) k);
}
return(k);
}

/*
* newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation
* int x,y,dir,lifetime;
*
* Enter with the coordinates of the sphere in x,y
* the direction(0-8 diroffx format) in dir, and the lifespan of the
* sphere in lifetime(in turns)
* Returns the number of spheres currently in existence
*/
newsphere(x, y, dir, life)
int x,
y,
dir,
life;
{
int m;
struct sphere *sp;
if (((sp =(struct sphere *) malloc(sizeof(struct sphere)))) == 0)
return(c[SPHCAST]);/* can't malloc, therefore failure */
if (dir >= 9)
dir = 0; /* no movement if direction not found */
if (level == 0)
vxy(&x, &y); /* don't go out of bounds */
else {
if (x < 1)
x = 1;
if (x >= MAXX - 1)
x = MAXX - 2;
if (y < 1)
y = 1;
if (y >= MAXY - 1)
y = MAXY - 2;
}
if ((m = mitem[x][y]) >= DEMONLORD + 4) {/* demons dispel spheres */
know[x][y] = 1;
show1cell(x, y); /* show the demon(ha ha) */
cursors();
lprintf("\nThe %s dispels the sphere!", monster[m].name);
beep();
rmsphere(x, y); /* remove any spheres that are here */
return(c[SPHCAST]);
}
if (m == DISENCHANTRESS) { /* disenchantress cancels spheres */
cursors();
lprintf("\nThe %s causes cancellation of the sphere!", monster[m].name);
beep();
boom:
sphboom(x, y); /* blow up stuff around sphere */
rmsphere(x, y); /* remove any spheres that are here */
return(c[SPHCAST]);
}
if (c[CANCELLATION]) { /* cancellation cancels spheres */
cursors();
lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!");
beep();
goto boom;
}
if (item[x][y] == OANNIHILATION) {/* collision of spheres detonates spheres */
cursors();
lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!");
beep();
rmsphere(x, y);
goto boom;
}
if (playerx == x && playery == y) {/* collision of sphere and player! */
cursors();
lprcat("\nYou have been enveloped by the zone of nothingness!\n");
beep();
rmsphere(x, y); /* remove any spheres that are here */
nap(4000);
died(258);
}
item[x][y] = OANNIHILATION;
mitem[x][y] = 0;
know[x][y] = 1;
show1cell(x, y); /* show the new sphere */
sp -> x = x;
sp -> y = y;
sp -> lev = level;
sp -> dir = dir;
sp -> lifetime = life;
sp -> p = 0;
if (spheres == 0)
spheres = sp; /* if first node in the sphere list */
else { /* add sphere to beginning of linked list */
sp -> p = spheres;
spheres = sp;
}
return(++c[SPHCAST]); /* one more sphere in the world */
}

/*
* rmsphere(x,y) Function to delete a sphere of annihilation from list
* int x,y;
*
* Enter with the coordinates of the sphere(on current level)
* Returns the number of spheres currently in existence
*/
rmsphere(x, y)
int x,y;
{
register struct sphere *sp,*sp2 = 0;

for (sp = spheres; sp; sp2 = sp, sp = sp -> p)
if (level == sp -> lev) /* is sphere on this level? */
if ((x == sp -> x) && (y == sp -> y)) {/* locate sphere at this location */
item[x][y] = mitem[x][y] = 0;
know[x][y] = 1;
show1cell(x, y);/* show the now missing sphere */
--c[SPHCAST];
if (sp == spheres) {
sp2 = sp;
spheres = sp -> p;
free((char *) sp2);
}
else {
sp2 -> p = sp -> p;
free((char *) sp);
}
break;
}
return(c[SPHCAST]); /* return number of spheres in the world */
}

/*
* sphboom(x,y) Function to perform the effects of a sphere detonation
* int x,y;
*
* Enter with the coordinates of the blast, Returns no value
*/
sphboom(x, y)
int x,
y;
{
register int i,
j;
if (c[HOLDMONST])
c[HOLDMONST] = 1;
if (c[CANCELLATION])
c[CANCELLATION] = 1;
for (j = max(1, x - 2); j < min(x + 3, MAXX - 1); j++)
for (i = max(1, y - 2); i < min(y + 3, MAXY - 1); i++) {
item[j][i] = mitem[j][i] = 0;
show1cell(j, i);
if (playerx == j && playery == i) {
cursors();
beep();
lprcat("\nYou were too close to the sphere!");
nap(3000);
died(283); /* player killed in explosion */
}
}
}

/*
* genmonst() Function to ask for monster and genocide from game
*
* This is done by setting a flag in the monster[] structure
*/
genmonst()
{
register int i,j;

cursors();
lprcat("\nGenocide what monster? ");
for (i = 0;(!isalpha(i)) && (i != ' '); i = readchar());
lprc(i);
for (j = 0; j < MAXMONST; j++)/* search for the monster type */
if (monstnamelist[j] == i) {/* have we found it? */
monster[j].genocided = 1;/* genocided from game */
lprintf(" There will be no more %s's", monster[j].name);
/* now wipe out monsters on this level */
newcavelevel(level);
draws(0, MAXX, 0, MAXY);
bot_linex();
return;
}
lprcat(" You sense failure!");
}
SHAR_EOF
if test 45763 -ne "`wc -c < 'monster.c'`"
then
echo shar: error transmitting "'monster.c'" '(should have been 45763 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'regen.c'" '(3839 characters)'
if test -f 'regen.c'
then
echo shar: will not over-write existing file "'regen.c'"
else
cat << \SHAR_EOF > 'regen.c'
/* regen.c Larn is copyrighted 1986 by Noah Morgan. */
#include "header.h"
/*
*******
REGEN()
*******
regen()

subroutine to regenerate player hp and spells
*/
regen () {
register int i,
flag;
register long *d;
d = c;
#ifdef EXTRA
d[MOVESMADE]++;
#endif
if (d[TIMESTOP]) {
if (--d[TIMESTOP] <= 0)
bottomline ();
return;
} /* for stop time spell */
flag = 0;

if (d[STRENGTH] < 3) {
d[STRENGTH] = 3;
flag = 1;
}
if ((d[HASTESELF] == 0) || ((d[HASTESELF] & 1) == 0))
gtime++;

if (d[HP] != d[HPMAX])
if (d[REGENCOUNTER]-- <= 0) {/* regenerate hit points */
d[REGENCOUNTER] = 22 + (d[HARDGAME] << 1) - d[LEVEL];
if ((d[HP] += d[REGEN]) > d[HPMAX])
d[HP] = d[HPMAX];
bottomhp ();
}

if (d[SPELLS] < d[SPELLMAX])/* regenerate spells */
if (d[ECOUNTER]-- <= 0) {
d[ECOUNTER] = 100 + 4 * (d[HARDGAME] - d[LEVEL] - d[ENERGY]);
d[SPELLS]++;
bottomspell ();
}

if (d[HERO])
if (--d[HERO] <= 0) {
for (i = 0; i < 6; i++)
d[i] -= 10;
flag = 1;
}
if (d[ALTPRO])
if (--d[ALTPRO] <= 0) {
d[MOREDEFENSES] -= 3;
flag = 1;
}
if (d[PROTECTIONTIME])
if (--d[PROTECTIONTIME] <= 0) {
d[MOREDEFENSES] -= 2;
flag = 1;
}
if (d[DEXCOUNT])
if (--d[DEXCOUNT] <= 0) {
d[DEXTERITY] -= 3;
flag = 1;
}
if (d[STRCOUNT])
if (--d[STRCOUNT] <= 0) {
d[STREXTRA] -= 3;
flag = 1;
}
if (d[BLINDCOUNT])
if (--d[BLINDCOUNT] <= 0) {
cursors ();
lprcat ("\nThe blindness lifts ");
beep ();
}
if (d[CONFUSE])
if (--d[CONFUSE] <= 0) {
cursors ();
lprcat ("\nYou regain your senses");
beep ();
}
if (d[GIANTSTR])
if (--d[GIANTSTR] <= 0) {
d[STREXTRA] -= 20;
flag = 1;
}
if (d[CHARMCOUNT])
if ((--d[CHARMCOUNT]) <= 0)
flag = 1;
if (d[INVISIBILITY])
if ((--d[INVISIBILITY]) <= 0)
flag = 1;
if (d[CANCELLATION])
if ((--d[CANCELLATION]) <= 0)
flag = 1;
if (d[WTW])
if ((--d[WTW]) <= 0)
flag = 1;
if (d[HASTESELF])
if ((--d[HASTESELF]) <= 0)
flag = 1;
if (d[AGGRAVATE])
--d[AGGRAVATE];
if (d[SCAREMONST])
if ((--d[SCAREMONST]) <= 0)
flag = 1;
if (d[STEALTH])
if ((--d[STEALTH]) <= 0)
flag = 1;
if (d[AWARENESS])
--d[AWARENESS];
if (d[HOLDMONST])
if ((--d[HOLDMONST]) <= 0)
flag = 1;
if (d[HASTEMONST])
--d[HASTEMONST];
if (d[FIRERESISTANCE])
if ((--d[FIRERESISTANCE]) <= 0)
flag = 1;
if (d[GLOBE])
if (--d[GLOBE] <= 0) {
d[MOREDEFENSES] -= 10;
flag = 1;
}
if (d[SPIRITPRO])
if (--d[SPIRITPRO] <= 0)
flag = 1;
if (d[UNDEADPRO])
if (--d[UNDEADPRO] <= 0)
flag = 1;
if (d[HALFDAM])
if (--d[HALFDAM] <= 0) {
cursors ();
lprcat ("\nYou now feel better ");
beep ();
}
if (d[SEEINVISIBLE])
if (--d[SEEINVISIBLE] <= 0) {
monstnamelist[INVISIBLESTALKER] = ' ';
cursors ();
lprcat ("\nYou feel your vision return to normal");
beep ();
}
if (d[ITCHING]) {
if (d[ITCHING] > 1)
if ((d[WEAR] != -1) || (d[SHIELD] != -1))
if (rnd (100) < 50) {
d[WEAR] = d[SHIELD] = -1;
cursors ();
lprcat ("\nThe hysteria of itching forces you to remove your armor!");
beep ();
recalc ();
bottomline ();
}
if (--d[ITCHING] <= 0) {
cursors ();
lprcat ("\nYou now feel the irritation subside!");
beep ();
}
}
if (d[CLUMSINESS]) {
if (d[WIELD] != -1)
if (d[CLUMSINESS] > 1)
if (item[playerx][playery] == 0)/* only if nothing there */
if (rnd (100) < 33)/* drop your weapon due to clumsiness */
drop_object ((int) d[WIELD]);
if (--d[CLUMSINESS] <= 0) {
cursors ();
lprcat ("\nYou now feel less awkward!");
beep ();
}
}
if (flag)
bottomline ();
}
SHAR_EOF
if test 3839 -ne "`wc -c < 'regen.c'`"
then
echo shar: error transmitting "'regen.c'" '(should have been 3839 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'savelev.c'" '(852 characters)'
if test -f 'savelev.c'
then
echo shar: will not over-write existing file "'savelev.c'"
else
cat << \SHAR_EOF > 'savelev.c'

/* savelev.c Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

/*
* routine to save the present level into storage
*/
savelevel ()
{
register int x,y,t;

t = level * (MAXX*MAXY);
for (x = 0; x < MAXX; x++) {
t += MAXY;
for (y = 0; y < MAXY; y++) {
cell[t+y].item = item[x][y];
cell[t+y].iarg = iarg[x][y];
cell[t+y].know = know[x][y];
cell[t+y].mitem = mitem[x][y];
cell[t+y].hitp = hitp[x][y];
}
}
}


/*
* routine to restore a level from storage
*/
getlevel ()
{
register int x,y,t;

t = level * (MAXX*MAXY);
for (x = 0; x < MAXX; x++) {
t += MAXY;
for (y = 0; y < MAXY; y++) {
item[x][y] = cell[t+y].item;
iarg[x][y] = cell[t+y].iarg;
know[x][y] = cell[t+y].know;
mitem[x][y] = cell[t+y].mitem;
hitp[x][y] = cell[t+y].hitp;
}
}
}
SHAR_EOF
if test 852 -ne "`wc -c < 'savelev.c'`"
then
echo shar: error transmitting "'savelev.c'" '(should have been 852 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'signal.c'" '(2848 characters)'
if test -f 'signal.c'
then
echo shar: will not over-write existing file "'signal.c'"
else
cat << \SHAR_EOF > 'signal.c'

#include <signal.h>
#include "header.h" /* "Larn is copyrighted 1986 by Noah Morgan.\n" */

#define BIT(a)(1<<((a)-1))

/* text to be displayed if ^C during intro screen */
static s2choose()
{
cursor(1, 24);
lprcat("Press ");
setbold();
lprcat("return");
resetbold();
lprcat(" to continue: ");
lflush();
}

/* what to do for a ^C */
static cntlc()
{
if (nosignal)
return; /* don't do anything if inhibited */
signal(SIGQUIT, SIG_IGN);
signal(SIGINT, SIG_IGN);
quit();
if (predostuff == 1)
s2choose();
else
showplayer();
lflush();
signal(SIGQUIT, cntlc);
signal(SIGINT, cntlc);
}


/*
* subroutine to save the game if a hangup signal
*/
static sgam()
{
savegame(savefilename);
wizard = 1;
died(-257); /* hangup signal */
}


/*
* subroutine to issue the needed signal traps - called from main()
*/
static sigill()
{
sigpanic(SIGILL);
}

static sigtrap()
{
sigpanic(SIGTRAP);
}

static sigiot()
{
sigpanic(SIGIOT);
}

static sigemt()
{
sigpanic(SIGEMT);
}

static sigfpe()
{
sigpanic(SIGFPE);
}

static sigbus()
{
sigpanic(SIGBUS);
}

static sigsegv()
{
sigpanic(SIGSEGV);
}

static sigsys()
{
sigpanic(SIGSYS);
}

static sigpipe()
{
sigpanic(SIGPIPE);
}

static sigterm()
{
sigpanic(SIGTERM);
}

sigsetup() {
signal(SIGQUIT, cntlc);
signal(SIGINT, cntlc);
signal(SIGKILL, SIG_IGN);
signal(SIGHUP, sgam);
signal(SIGILL, sigill);
signal(SIGTRAP, sigtrap);
signal(SIGIOT, sigiot);
signal(SIGEMT, sigemt);
signal(SIGFPE, sigfpe);
signal(SIGBUS, sigbus);
signal(SIGSEGV, sigsegv);
signal(SIGSYS, sigsys);
signal(SIGPIPE, sigpipe);
signal(SIGTERM, sigterm);
}

static char *signame[NSIG] = {
"",
"SIGHUP", /* 1 hangup */
"SIGINT", /* 2 interrupt */
"SIGQUIT", /* 3 quit */
"SIGILL", /* 4 illegal instruction(not reset when caught) */
"SIGTRAP", /* 5 trace trap(not reset when caught) */
"SIGIOT", /* 6 IOT instruction */
"SIGEMT", /* 7 EMT instruction */
"SIGFPE", /* 8 floating point exception */
"SIGKILL", /* 9 kill(cannot be caught or ignored) */
"SIGBUS", /* 10 bus error */
"SIGSEGV", /* 11 segmentation violation */
"SIGSYS", /* 12 bad argument to system call */
"SIGPIPE", /* 13 write on a pipe with no one to read it */
"SIGALRM", /* 14 alarm clock */
"SIGTERM" /* 15 software termination signal from kill */
};

/*
* routine to process a fatal error signal
*/
static sigpanic(sig)
int sig;
{
char buf[128];

signal(sig, SIG_DFL);
sprintf(buf, "\nLarn - Panic! Signal %d received [%s]", sig, signame[sig]);
write(2, buf, strlen(buf));
sleep(2);
sncbr();
savegame(savefilename);
kill(getpid(), sig); /* this will terminate us */
}
SHAR_EOF
if test 2848 -ne "`wc -c < 'signal.c'`"
then
echo shar: error transmitting "'signal.c'" '(should have been 2848 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tok.c'" '(5032 characters)'
if test -f 'tok.c'
then
echo shar: will not over-write existing file "'tok.c'"
else
cat << \SHAR_EOF > 'tok.c'


/* tok.c Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

static char lastok = 0;
globaldef int yrepcount = 0,dayplay = 0;

#define MAXUM 52 /* maximum number of user re-named monsters */
#define MAXMNAME 40 /* max length of a monster re-name */
static char usermonster[MAXUM][MAXMNAME];/* the user named monster name goes here */
static char usermpoint = 0; /* the user monster pointer */

/*
lexical analyzer for larn
*/
yylex ()
{
char cc;
int ic;

if (hit2flag) {
hit2flag = 0;
yrepcount = 0;
return (' ');
}
if (yrepcount > 0) {
--yrepcount;
return (lastok);
} else
yrepcount = 0;
if (yrepcount == 0) {
bottomdo ();
showplayer ();
} /* show where the player is */
lflush ();
while (1) {
c[BYTESIN]++;
if (ckpflag) /* check for periodic checkpointing */
if ((c[BYTESIN] % 400) == 0) {
savegame (ckpfile);

#ifdef TIMECHECK
if (dayplay == 0)
if (playable ()) {
cursor (1, 19);
lprcat ("\nSorry, but it is now time for work. Your game has been saved.\n");
beep ();
lflush ();
savegame (savefilename);
wizard = nomove = 1;
sleep (4);
died (-257);
}
#endif TIMECHECK

}

if ((cc = KeySense(0)) == -1)
return (lastok = -1);

if (cc == 'Y' - 64) { /* control Y -- shell escape */
resetscroll ();
clear(); /* scrolling region, home, clear, no attributes */
system(0);

setscroll ();
return (lastok = 'L' - 64); /* redisplay screen */
}

if ((cc <= '9') && (cc >= '0')) {
yrepcount = yrepcount * 10 + cc - '0';
} else {
if (yrepcount > 0)
--yrepcount;
return (lastok = cc);
}
}
}


/*
* flushall() Function to flush all type-ahead in the input buffer
*/
flushall ()
{
/* if keyboard input buffer is too big, flush some of it */
while (KeySense(0) >= 0);
}


/*
function to set the desired hardness
enter with hard= -1 for default hardness, else any desired hardness
*/
sethard (hard)
int hard;
{
register int j,k,i;

j = c[HARDGAME];
hashewon ();
if (restorflag == 0) { /* don't set c[HARDGAME] if restoring game */
if (hard >= 0)
c[HARDGAME] = hard;
} else
c[HARDGAME] = j; /* set c[HARDGAME] to proper value if restoring game */

if (k = c[HARDGAME])
for (j = 0; j <= MAXMONST + 8; j++) {
i = ((6 + k) * monster[j].hitpoints + 1) / 6;
monster[j].hitpoints = (i < 0) ? 32767 : i;
i = ((6 + k) * monster[j].damage + 1) / 5;
monster[j].damage = (i > 127) ? 127 : i;
i = (10 * monster[j].gold) / (10 + k);
monster[j].gold = (i > 32767) ? 32767 : i;
i = monster[j].armorclass - k;
monster[j].armorclass = (i < -127) ? -127 : i;
i = (7 * monster[j].experience) / (7 + k) + 1;
monster[j].experience = (i <= 0) ? 1 : i;
}
}


/*
function to read and process the larn options file
*/
readopts ()
{
register char *i;
register int j,k;
int flag = 1; /* set to 0 if he specifies a name for his character */

if (lopen (optsfile) < 0) {
strcpy (logname, loginname);
return; /* user name if no character name */
}
i = " ";
while (*i) {
if ((i = (char *) lgetw ()) == 0)
break; /* check for EOF */
while ((*i == ' ') || (*i == '\t'))
i++; /* eat leading whitespace */
switch (*i) {
case 'b':
if (strcmp (i, "bold-objects") == 0)
boldon = 1;
break;

case 'e':
if (strcmp (i, "enable-checkpointing") == 0)
ckpflag = 1;
break;

case 'i':
if (strcmp (i, "inverse-objects") == 0)
boldon = 0;
break;

case 'f':
if (strcmp (i, "female") == 0)
sex = 0; /* male or female */
break;

case 'm':
if (strcmp (i, "monster:") == 0) {/* name favorite monster */
if ((i = lgetw ()) == 0)
break;
if (strlen (i) >= MAXMNAME)
i[MAXMNAME - 1] = 0;
strcpy (usermonster[usermpoint], i);
if (usermpoint >= MAXUM)
break; /* defined all of em */
if (isalpha (j = usermonster[usermpoint][0])) {
for (k = 1; k < MAXMONST + 8; k++)/* find monster */
if (monstnamelist[k] == j) {
monster[k].name = &usermonster[usermpoint++][0];
break;
}
}
} else
if (strcmp (i, "male") == 0)
sex = 1;
break;

case 'n':
if (strcmp (i, "name:") == 0) {/* defining players name */
if ((i = lgetw ()) == 0)
break;
if (strlen (i) >= LOGNAMESIZE)
i[LOGNAMESIZE - 1] = 0;
strcpy (logname, i);
flag = 0;
} else
if (strcmp (i, "no-introduction") == 0)
nowelcome = 1;
else
if (strcmp (i, "no-beep") == 0)
nobeep = 1;
break;

case 'p':
if (strcmp (i, "play-day-play") == 0)
dayplay = 1;
break;

case 's':
if (strcmp (i, "savefile:") == 0) {/* defining savefilename */
if ((i = lgetw ()) == 0)
break;
if (strlen (i) >= SAVEFILENAMESIZE)/* avoid overflow */
i[SAVEFILENAMESIZE - 1] = 0;
strcpy (savefilename, i);
flag = 0;
}
break;
};
}
if (flag)
strcpy (logname, loginname);
}
SHAR_EOF
if test 5032 -ne "`wc -c < 'tok.c'`"
then
echo shar: error transmitting "'tok.c'" '(should have been 5032 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0

0 tin nhắn mới