Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

larn 12.0 part 4/6

25 views
Skip to first unread message

Noah Morgan

unread,
Aug 8, 1986, 1:09:49 PM8/8/86
to
*** REPLACE THIS LINE WITH YOUR MESSAGE ***
#! /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
# moreobj.c
# movem.c
# .lfortune
# This archive created: Wed Aug 6 14:59:31 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'monster.c'" '(41515 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 altar 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=getchar())=='D')
{ seemagic(-1); cursors(); lprcat(eys); }
if (a=='\33') goto over; /* to escape casting a spell */
if ((b=getchar())=='\33') goto over; /* to escape casting a spell */
if ((d=getchar())=='\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(getchar())
{
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=getchar());
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 41515 -ne "`wc -c < 'monster.c'`"
then
echo shar: error transmitting "'monster.c'" '(should have been 41515 characters)'
fi
fi
echo shar: extracting "'moreobj.c'" '(9022 characters)'
if test -f 'moreobj.c'
then
echo shar: will not over-write existing file "'moreobj.c'"
else
cat << \SHAR_EOF > 'moreobj.c'
/* moreobj.c Larn is copyrighted 1986 by Noah Morgan.
*
* Routines in this file:
*
* oaltar()
* othrone()
* ochest()
* ofountain()
*/
#include "header.h"

/*
* ******
* OALTAR
* ******
*
* subroutine to process an altar object
*/
oaltar()
{
unsigned long k;

lprcat("\nDo you (p) pray (d) desecrate"); iopts();
while (1)
{
while (1) switch(getchar())
{
case 'p': lprcat(" pray\nDo you (m) give money or (j) just pray? ");
while (1) switch(getchar())
{
case 'j': if (rnd(100)<75)
lprcat("\nnothing happens");
else if (rnd(13)<4) ohear();
else if (rnd(43) == 10)
{
if (c[WEAR]) lprcat("\nYou feel your armor vibrate for a moment");
enchantarmor(); return;
}
else if (rnd(43) == 10)
{
if (c[WIELD]) lprcat("\nYou feel your weapon vibrate for a moment");
enchweapon(); return;
}
else createmonster(makemonst(level+1));
return;

case 'm': lprcat("\n\n"); cursor(1,24); cltoeoln();
cursor(1,23); cltoeoln();
lprcat("how much do you donate? ");
k = readnum((long)c[GOLD]);
if (c[GOLD]<k)
{
lprcat("\nYou don't have that much!");
return;
}
c[GOLD] -= k;
if (k < c[GOLD]/10 || k<rnd(50))
{ createmonster(makemonst(level+1)); c[AGGRAVATE] += 200; }
else if (rnd(101) > 50) { ohear(); return; }
else if (rnd(43) == 5)
{
if (c[WEAR]) lprcat("\nYou feel your armor vibrate for a moment");
enchantarmor(); return;
}
else if (rnd(43) == 8)
{
if (c[WIELD]) lprcat("\nYou feel your weapon vibrate for a moment");
enchweapon(); return;
}
else lprcat("\nThank You.");
bottomline(); return;

case '\33': return;
};

case 'd': lprcat(" desecrate");
if (rnd(100)<60)
{ createmonster(makemonst(level+2)+8); c[AGGRAVATE] += 2500; }
else
if (rnd(101)<30)
{
lprcat("\nThe altar crumbles into a pile of dust before your eyes");
forget(); /* remember to destroy the altar */
}
else
lprcat("\nnothing happens");
return;

case 'i':
case '\33': ignore();
if (rnd(100)<30) { createmonster(makemonst(level+1)); c[AGGRAVATE] += rnd(450); }
else lprcat("\nnothing happens");
return;
};
}
}

/*
function to cast a +3 protection on the player
*/
static ohear()
{
lprcat("\nYou have been heard!");
if (c[ALTPRO]==0) c[MOREDEFENSES]+=3;
c[ALTPRO] += 500; /* protection field */
bottomline();
}

/*
*******
OTHRONE
*******

subroutine to process a throne object
*/
othrone(arg)
int arg;
{
register int i,k;

lprcat("\nDo you (p) pry off jewels, (s) sit down"); iopts();
while (1)
{
while (1) switch(getchar())
{
case 'p': lprcat(" pry off"); k=rnd(101);
if (k<25)
{
for (i=0; i<rnd(4); i++) creategem(); /* gems pop off the throne */
item[playerx][playery]=ODEADTHRONE;
know[playerx][playery]=0;
}
else if (k<40 && arg==0)
{
createmonster(GNOMEKING);
item[playerx][playery]=OTHRONE2;
know[playerx][playery]=0;
}
else lprcat("\nnothing happens");
return;

case 's': lprcat(" sit down"); k=rnd(101);
if (k<30 && arg==0)
{
createmonster(GNOMEKING);
item[playerx][playery]=OTHRONE2;
know[playerx][playery]=0;
}
else if (k<35) { lprcat("\nZaaaappp! You've been teleported!\n"); beep(); oteleport(0); }
else lprcat("\nnothing happens");
return;

case 'i':
case '\33': ignore(); return;
};
}
}

odeadthrone()
{
register int k;

lprcat("\nDo you (s) sit down"); iopts();
while (1)
{
while (1) switch(getchar())
{
case 's': lprcat(" sit down"); k=rnd(101);
if (k<35) { lprcat("\nZaaaappp! You've been teleported!\n"); beep(); oteleport(0); }
else lprcat("\nnothing happens");
return;

case 'i':
case '\33': ignore(); return;
};
}
}

/*
******
OCHEST
******

subroutine to process a throne object
*/
ochest()
{
register int i,k;
lprcat("\nDo you (t) take it, (o) try to open it"); iopts();
while (1)
{
while (1) switch(getchar())
{
case 'o': lprcat(" open it"); k=rnd(101);
if (k<40)
{
lprcat("\nThe chest explodes as you open it"); beep();
i = rnd(10); lastnum=281; /* in case he dies */
lprintf("\nYou suffer %d hit points damage!",(long)i);
checkloss(i);
switch(rnd(10)) /* see if he gets a curse */
{
case 1: c[ITCHING]+= rnd(1000)+100;
lprcat("\nYou feel an irritation spread over your skin!");
beep();
break;

case 2: c[CLUMSINESS]+= rnd(1600)+200;
lprcat("\nYou begin to lose hand to eye coordination!");
beep();
break;

case 3: c[HALFDAM]+= rnd(1600)+200;
beep();
lprcat("\nA sickness engulfs you!"); break;
};
item[playerx][playery]=know[playerx][playery]=0;
if (rnd(100)<69) creategem(); /* gems from the chest */
dropgold(rnd(110*iarg[playerx][playery]+200));
for (i=0; i<rnd(4); i++) something(iarg[playerx][playery]+2);
}
else lprcat("\nnothing happens");
return;

case 't': lprcat(" take");
if (take(OCHEST,iarg[playerx][playery])==0)
item[playerx][playery]=know[playerx][playery]=0;
return;

case 'i':
case '\33': ignore(); return;
};
}
}

/*
*********
OFOUNTAIN
*********
*/

ofountain()
{
register int x;
cursors();
lprcat("\nDo you (d) drink, (w) wash yourself"); iopts();
while (1) switch(getchar())
{
case 'd': lprcat("drink");
if (rnd(1501)<2)
{
lprcat("\nOops! You seem to have caught the dreadful sleep!");
beep(); lflush(); sleep(3); died(280); return;
}
x = rnd(100);
if (x<7)
{
c[HALFDAM] += 200+rnd(200);
lprcat("\nYou feel a sickness coming on");
}
else if (x<13) quaffpotion(23); /* see invisible */
else if (x < 45)
lprcat("\nnothing seems to have happened");
else if (rnd(3) != 2)
fntchange(1); /* change char levels upward */
else
fntchange(-1); /* change char levels downward */
if (rnd(12)<3)
{
lprcat("\nThe fountains bubbling slowly quiets");
item[playerx][playery]=ODEADFOUNTAIN; /* dead fountain */
know[playerx][playery]=0;
}
return;

case '\33':
case 'i': ignore(); return;

case 'w': lprcat("wash yourself");
if (rnd(100) < 11)
{
x=rnd((level<<2)+2);
lprintf("\nOh no! The water was foul! You suffer %d hit points!",(long)x);
lastnum=273; losehp(x); bottomline(); cursors();
}
else
if (rnd(100) < 29)
lprcat("\nYou got the dirt off!");
else
if (rnd(100) < 31)
lprcat("\nThis water seems to be hard water! The dirt didn't come off!");
else
if (rnd(100) < 34)
createmonster(WATERLORD); /* make water lord */
else
lprcat("\nnothing seems to have happened");
return;
}
}

/*
a subroutine to raise or lower character levels
if x > 0 they are raised if x < 0 they are lowered
*/
fntchange(how)
int how;
{
register long j;
lprc('\n');
switch(rnd(9))
{
case 1: lprcat("Your strength"); fch(how,&c[0]); break;
case 2: lprcat("Your intelligence"); fch(how,&c[1]); break;
case 3: lprcat("Your wisdom"); fch(how,&c[2]); break;
case 4: lprcat("Your constitution"); fch(how,&c[3]); break;
case 5: lprcat("Your dexterity"); fch(how,&c[4]); break;
case 6: lprcat("Your charm"); fch(how,&c[5]); break;
case 7: j=rnd(level+1);
if (how < 0)
{ lprintf("You lose %d hit point",(long)j); if (j>1) lprcat("s!"); else lprc('!'); losemhp((int)j); }
else
{ lprintf("You gain %d hit point",(long)j); if (j>1) lprcat("s!"); else lprc('!'); raisemhp((int)j); }
bottomline(); break;

case 8: j=rnd(level+1);
if (how > 0)
{
lprintf("You just gained %d spell",(long)j); raisemspells((int)j);
if (j>1) lprcat("s!"); else lprc('!');
}
else
{
lprintf("You just lost %d spell",(long)j); losemspells((int)j);
if (j>1) lprcat("s!"); else lprc('!');
}
bottomline(); break;

case 9: j = 5*rnd((level+1)*(level+1));
if (how < 0)
{
lprintf("You just lost %d experience point",(long)j);
if (j>1) lprcat("s!"); else lprc('!'); loseexperience((long)j);
}
else
{
lprintf("You just gained %d experience point",(long)j);
if (j>1) lprcat("s!"); else lprc('!'); raiseexperience((long)j);
}
break;
}
cursors();
}

/*
***
FCH
***

subroutine to process an up/down of a character attribute for ofountain
*/
static fch(how,x)
int how;
long *x;
{
if (how < 0) { lprcat(" went down by one!"); --(*x); }
else { lprcat(" went up by one!"); (*x)++; }
bottomline();
}
SHAR_EOF
if test 9022 -ne "`wc -c < 'moreobj.c'`"
then
echo shar: error transmitting "'moreobj.c'" '(should have been 9022 characters)'
fi
fi
echo shar: extracting "'movem.c'" '(10154 characters)'
if test -f 'movem.c'
then
echo shar: will not over-write existing file "'movem.c'"
else
cat << \SHAR_EOF > 'movem.c'
/*
* movem.c (move monster) Larn is copyrighted 1986 by Noah Morgan.
*
* Here are the functions in this file:
*
* movemonst() Routine to move the monsters toward the player
* movemt(x,y) Function to move a monster at (x,y) -- must determine where
* mmove(x,y,xd,yd) Function to actually perform the monster movement
* movsphere() Function to look for and move spheres of annihilation
*/
#include "header.h"

/*
* movemonst() Routine to move the monsters toward the player
*
* This routine has the responsibility to determine which monsters are to
* move, and call movemt() to do the move.
* Returns no value.
*/
static short w1[9],w1x[9],w1y[9];
static int tmp1,tmp2,tmp3,tmp4,distance;
movemonst()
{
register int i,j;
if (c[TIMESTOP]) return; /* no action if time is stopped */
if (c[HASTESELF]) if ((c[HASTESELF]&1)==0) return;
if (spheres) movsphere(); /* move the spheres of annihilation if any */
if (c[HOLDMONST]) return; /* no action if monsters are held */

if (c[AGGRAVATE]) /* determine window of monsters to move */
{
tmp1=playery-5; tmp2=playery+6; tmp3=playerx-10; tmp4=playerx+11;
distance=40; /* depth of intelligent monster movement */
}
else
{
tmp1=playery-3; tmp2=playery+4; tmp3=playerx-5; tmp4=playerx+6;
distance=17; /* depth of intelligent monster movement */
}

if (level == 0) /* if on outside level monsters can move in perimeter */
{
if (tmp1 < 0) tmp1=0; if (tmp2 > MAXY) tmp2=MAXY;
if (tmp3 < 0) tmp3=0; if (tmp4 > MAXX) tmp4=MAXX;
}
else /* if in a dungeon monsters can't be on the perimeter (wall there) */
{
if (tmp1 < 1) tmp1=1; if (tmp2 > MAXY-1) tmp2=MAXY-1;
if (tmp3 < 1) tmp3=1; if (tmp4 > MAXX-1) tmp4=MAXX-1;
}

for (j=tmp1; j<tmp2; j++) /* now reset monster moved flags */
for (i=tmp3; i<tmp4; i++)
moved[i][j] = 0;
moved[lasthx][lasthy]=0;

if (c[AGGRAVATE] || !c[STEALTH]) /* who gets moved? split for efficiency */
{
for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */
for (i=tmp3; i<tmp4; i++)
if (mitem[i][j]) /* if there is a monster to move */
if (moved[i][j]==0) /* if it has not already been moved */
movemt(i,j); /* go and move the monster */
}
else /* not aggravated and not stealth */
{
for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */
for (i=tmp3; i<tmp4; i++)
if (mitem[i][j]) /* if there is a monster to move */
if (moved[i][j]==0) /* if it has not already been moved */
if (stealth[i][j]) /* if it is asleep due to stealth */
movemt(i,j); /* go and move the monster */
}

if (mitem[lasthx][lasthy]) /* now move monster last hit by player if not already moved */
{
if (moved[lasthx][lasthy]==0) /* if it has not already been moved */
{
movemt(lasthx,lasthy);
lasthx = w1x[0]; lasthy = w1y[0];
}
}
}

/*
* movemt(x,y) Function to move a monster at (x,y) -- must determine where
* int x,y;
*
* This routine is responsible for determining where one monster at (x,y) will
* move to. Enter with the monsters coordinates in (x,y).
* Returns no value.
*/
static int tmpitem,xl,xh,yl,yh;
movemt(i,j)
int i,j;
{
register int k,m,z,tmp,xtmp,ytmp,monst;
switch(monst=mitem[i][j]) /* for half speed monsters */
{
case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART:
case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return;
};

if (c[SCAREMONST]) /* choose destination randomly if scared */
{
if ((xl = i+rnd(3)-2) < 0) xl=0; if (xl >= MAXX) xl=MAXX-1;
if ((yl = j+rnd(3)-2) < 0) yl=0; if (yl >= MAXY) yl=MAXY-1;
if ((tmp=item[xl][yl]) != OWALL)
if (mitem[xl][yl] == 0)
if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
if (tmp != OCLOSEDDOOR) mmove(i,j,xl,yl);
return;
}

if (monster[monst].intelligence > 10-c[HARDGAME]) /* if smart monster */
/* intelligent movement here -- first setup screen array */
{
xl=tmp3-2; yl=tmp1-2; xh=tmp4+2; yh=tmp2+2;
vxy(&xl,&yl); vxy(&xh,&yh);
for (k=yl; k<yh; k++)
for (m=xl; m<xh; m++)
{
switch(item[m][k])
{
case OWALL: case OPIT: case OTRAPARROW: case ODARTRAP:
case OCLOSEDDOOR: case OTRAPDOOR: case OTELEPORTER:
smm: screen[m][k]=127; break;
case OMIRROR: if (mitem[m][k]==VAMPIRE) goto smm;
default: screen[m][k]= 0; break;
};
}
screen[playerx][playery]=1;

/* now perform proximity ripple from playerx,playery to monster */
xl=tmp3-1; yl=tmp1-1; xh=tmp4+1; yh=tmp2+1;
vxy(&xl,&yl); vxy(&xh,&yh);
for (tmp=1; tmp<distance; tmp++) /* only up to 20 squares away */
for (k=yl; k<yh; k++)
for (m=xl; m<xh; m++)
if (screen[m][k]==tmp) /* if find proximity n advance it */
for (z=1; z<9; z++) /* go around in a circle */
{
if (screen[xtmp=m+diroffx[z]][ytmp=k+diroffy[z]]==0)
screen[xtmp][ytmp]=tmp+1;
if (xtmp==i && ytmp==j) goto out;
}

out: if (tmp<distance) /* did find connectivity */
/* now select lowest value around playerx,playery */
for (z=1; z<9; z++) /* go around in a circle */
if (screen[xl=i+diroffx[z]][yl=j+diroffy[z]]==tmp)
if (!mitem[xl][yl]) { mmove(i,j,w1x[0]=xl,w1y[0]=yl); return; }
}

/* dumb monsters move here */
xl=i-1; yl=j-1; xh=i+2; yh=j+2;
if (i<playerx) xl++; else if (i>playerx) --xh;
if (j<playery) yl++; else if (j>playery) --yh;
for (k=0; k<9; k++) w1[k] = 10000;

for (k=xl; k<xh; k++)
for (m=yl; m<yh; m++) /* for each square compute distance to player */
{
tmp = k-i+4+3*(m-j);
tmpitem = item[k][m];
if (tmpitem!=OWALL || (k==playerx && m==playery))
if (mitem[k][m]==0)
if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
if (tmpitem!=OCLOSEDDOOR)
{
w1[tmp] = (playerx-k)*(playerx-k)+(playery-m)*(playery-m);
w1x[tmp] = k; w1y[tmp] = m;
}
}

tmp = 0;
for (k=1; k<9; k++) if (w1[tmp] > w1[k]) tmp=k;

if (w1[tmp] < 10000)
if ((i!=w1x[tmp]) || (j!=w1y[tmp]))
mmove(i,j,w1x[tmp],w1y[tmp]);
}

/*
* mmove(x,y,xd,yd) Function to actually perform the monster movement
* int x,y,xd,yd;
*
* Enter with the from coordinates in (x,y) and the destination coordinates
* in (xd,yd).
*/
mmove(aa,bb,cc,dd)
int aa,bb,cc,dd;
{
register int tmp,i,flag;
char *who,*p;
flag=0; /* set to 1 if monster hit by arrow trap */
if ((cc==playerx) && (dd==playery))
{
hitplayer(aa,bb); moved[aa][bb] = 1; return;
}
i=item[cc][dd];
if ((i==OPIT) || (i==OTRAPDOOR))
switch(mitem[aa][bb])
{
case SPIRITNAGA: case PLATINUMDRAGON: case WRAITH:
case VAMPIRE: case SILVERDRAGON: case POLTERGEIST:
case DEMONLORD: case DEMONLORD+1: case DEMONLORD+2:
case DEMONLORD+3: case DEMONLORD+4: case DEMONLORD+5:
case DEMONLORD+6: case DEMONPRINCE: break;

default: mitem[aa][bb]=0; /* fell in a pit or trapdoor */
};
tmp = mitem[cc][dd] = mitem[aa][bb];
if (i==OANNIHILATION)
{
if (tmp>=DEMONLORD+3) /* demons dispel spheres */
{
cursors();
lprintf("\nThe %s dispels the sphere!",monster[tmp].name);
rmsphere(cc,dd); /* delete the sphere */
}
else i=tmp=mitem[cc][dd]=0;
}
stealth[cc][dd]=1;
if ((hitp[cc][dd] = hitp[aa][bb]) < 0) hitp[cc][dd]=1;
mitem[aa][bb] = 0; moved[cc][dd] = 1;
if (tmp == LEPRECHAUN)
switch(i)
{
case OGOLDPILE: case OMAXGOLD: case OKGOLD: case ODGOLD:
case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
item[cc][dd] = 0; /* leprechaun takes gold */
};

if (tmp == TROLL) /* if a troll regenerate him */
if ((gtime & 1) == 0)
if (monster[tmp].hitpoints > hitp[cc][dd]) hitp[cc][dd]++;

if (i==OTRAPARROW) /* arrow hits monster */
{ who = "An arrow"; if ((hitp[cc][dd] -= rnd(10)+level) <= 0)
{ mitem[cc][dd]=0; flag=2; } else flag=1; }
if (i==ODARTRAP) /* dart hits monster */
{ who = "A dart"; if ((hitp[cc][dd] -= rnd(6)) <= 0)
{ mitem[cc][dd]=0; flag=2; } else flag=1; }
if (i==OTELEPORTER) /* monster hits teleport trap */
{ flag=3; fillmonst(mitem[cc][dd]); mitem[cc][dd]=0; }
if (c[BLINDCOUNT]) return; /* if blind don't show where monsters are */
if (know[cc][dd] & 1)
{
p=0;
if (flag) cursors();
switch(flag)
{
case 1: p="\n%s hits the %s"; break;
case 2: p="\n%s hits and kills the %s"; break;
case 3: p="\nThe %s%s gets teleported"; who=""; break;
};
if (p) { lprintf(p,who,monster[tmp].name); beep(); }
}
/* if (yrepcount>1) { know[aa][bb] &= 2; know[cc][dd] &= 2; return; } */
if (know[aa][bb] & 1) show1cell(aa,bb);
if (know[cc][dd] & 1) show1cell(cc,dd);
}

/*
* movsphere() Function to look for and move spheres of annihilation
*
* This function works on the sphere linked list, first duplicating the list
* (the act of moving changes the list), then processing each sphere in order
* to move it. They eat anything in their way, including stairs, volcanic
* shafts, potions, etc, except for upper level demons, who can dispel
* spheres.
* No value is returned.
*/
#define SPHMAX 20 /* maximum number of spheres movsphere can handle */
movsphere()
{
register int x,y,dir,len;
register struct sphere *sp,*sp2;
struct sphere sph[SPHMAX];

/* first duplicate sphere list */
for (sp=0,x=0,sp2=spheres; sp2; sp2=sp2->p) /* look through sphere list */
if (sp2->lev == level) /* only if this level */
{
sph[x] = *sp2; sph[x++].p = 0; /* copy the struct */
if (x>1) sph[x-2].p = &sph[x-1]; /* link pointers */
}
if (x) sp= sph; /* if any spheres, point to them */
else return; /* no spheres */

for (sp=sph; sp; sp=sp->p) /* look through sphere list */
{
x = sp->x; y = sp->y;
if (item[x][y]!=OANNIHILATION) continue; /* not really there */
if (--(sp->lifetime) < 0) /* has sphere run out of gas? */
{
rmsphere(x,y); /* delete sphere */
continue;
}
switch(rnd((int)max(7,c[INTELLIGENCE]>>1))) /* time to move the sphere */
{
case 1:
case 2: /* change direction to a random one */
sp->dir = rnd(8);
default: /* move in normal direction */
dir = sp->dir; len = sp->lifetime;
rmsphere(x,y);
newsphere(x+diroffx[dir],y+diroffy[dir],dir,len);
};
}
}
SHAR_EOF
if test 10154 -ne "`wc -c < 'movem.c'`"
then
echo shar: error transmitting "'movem.c'" '(should have been 10154 characters)'
fi
fi
echo shar: extracting "'.lfortune'" '(1324 characters)'
if test -f '.lfortune'
then
echo shar: will not over-write existing file "'.lfortune'"
else
cat << \SHAR_EOF > '.lfortune'
gem value = gem * 2 ^ perfection
sitting down can have unexpected results
don't pry into the affairs of others
drinking can be hazardous to your health
beware of the gusher!
some monsters are greedy
nymphs have light fingers
try kissing a disenchantress!
hammers and brains don't mix
what does a potion of cure dianthroritis taste like?
hit point gain/loss when raising a level depends on constitution
healing a mighty wizard can be exhilarating
be sure to pay your taxes
are Vampires afraid of something?
some dragons can fly
dos thou strive for perfection?
patience is a virtue, unless your daughter dies
what does the Eye of Larn see in its guardian?
a level 25 player casts like crazy!
energy rings affect spell regeneration
difficulty affects regeneration
control of the pesty spirits is most helpful
don't fall into a bottomless pit
dexterity allows you to carry more
you can get 2 points of WC for the price of one
never enter the dungeon naked! the monsters will laugh at you!
did someone put itching powder in your armor?
you klutz!
avoid opening doors. you never know whats on the other side.
infinite regeneration ---> temptation
the greatest weapon in the game has not the highest Weapon Class
you can't buy the most powerful scroll
identify things before you use them
there's more than one way through a wall
SHAR_EOF
if test 1324 -ne "`wc -c < '.lfortune'`"
then
echo shar: error transmitting "'.lfortune'" '(should have been 1324 characters)'
fi
fi
exit 0
# End of shell archive

0 new messages