Subject: v12i059: larn2 - dungeon type adventure game (V12.3), Part06/12 Newsgroups: comp.sources.games Approved: billr@saab.CNA.TEK.COM Submitted-by: routley@tle.ENET.DEC.COM (Kevin Routley) Posting-number: Volume 12, Issue 59 Archive-name: larn2/Part06 Supersedes: larn: Volume 11, Issue 84-94 Environment: Unix, VMS, MS-DOS, OS/2, termcap #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'monster.c' <<'END_OF_FILE' X/* X * monster.c X * X * createmonster(monstno) Function to create a monster next to the player X * int monstno; X * X * int cgood(x,y,itm,monst) Function to check location for emptiness X * int x,y,itm,monst; X * X * createitem(it,arg) Routine to place an item next to the player X * int it,arg; X * X * vxy(x,y) Routine to verify/fix (*x,*y) for being within bounds X * int *x,*y; X * X * hitmonster(x,y) Function to hit a monster at the designated coordinates X * int x,y; X * X * hitm(x,y,amt) Function to just hit a monster at a given coordinates X * int x,y,amt; X * X * hitplayer(x,y) Function for the monster to hit the player from (x,y) X * int x,y; X * X * dropsomething(monst) Function to create an object when a monster dies X * int monst; X * X * dropgold(amount) Function to drop some gold around player X * int amount; X * X * something(level) Function to create a random item around player X * int level; X * X * newobject(lev,i) Routine to return a randomly selected new object X * int lev,*i; X * X * spattack(atckno,xx,yy) Function to process special attacks from monsters X * int atckno,xx,yy; X * X * checkloss(x) Routine to subtract hp from user and flag bottomline display X * int x; X * X */ X#include "header.h" X#include "larndefs.h" X#include "monsters.h" X#include "objects.h" X#include "player.h" X X#include X#define min(x,y) (((x)>(y))?(y):(x)) X#define max(x,y) (((x)>(y))?(x):(y)) X Xextern fullhit(), ifblind(); X X/* X * createmonster(monstno) Function to create a monster next to the player X * int monstno; X * X * Enter with the monster number (1 to MAXMONST+8) X * Returns no value. X */ Xcreatemonster(mon) X int mon; X { X register int x,y,k,i; X if (mon<1 || mon>MAXMONST+8) /* check for monster number out of bounds */ X { X beep(); lprintf("\ncan't createmonst(%d)\n",(long)mon); nap(3000); return; X } X while (monster[mon].genocided && mon8) k=1; /* wraparound the diroff arrays */ X x = playerx + diroffx[k]; y = playery + diroffy[k]; X if (cgood(x,y,0,1)) /* if we can create here */ X { X mitem[x][y] = mon; X hitp[x][y] = monster[mon].hitpoints; X stealth[x][y]=0; X know[x][y] &= ~KNOWHERE; X switch(mon) X { X case ROTHE: case POLTERGEIST: case VAMPIRE: stealth[x][y]=1; X }; X return; X } X } X } X X/* X * int cgood(x,y,itm,monst) Function to check location for emptiness X * int x,y,itm,monst; X * X * Routine to return TRUE if a location does not have itm or monst there X * returns FALSE (0) otherwise X * Enter with itm or monst TRUE or FALSE if checking it X * Example: if itm==TRUE check for no item at this location X * if monst==TRUE check for no monster at this location X * This routine will return FALSE if at a wall,door or the dungeon exit X * on level 1 X */ Xstatic int cgood(x,y,itm,monst) X register int x,y; X int itm,monst; X { X /* cannot create either monster or item if: X - out of bounds X - wall X - closed door X - dungeon entrance X */ X if (((y < 0) || (y > MAXY-1) || (x < 0) || (x > MAXX-1)) || X (item[x][y] == OWALL) || X (item[x][y] == OCLOSEDDOOR) || X ((level == 1) && (x == 33) && (y == MAXY-1))) X return( FALSE ); X X /* if checking for an item, return False if one there already X */ X if ( itm && item[x][y]) X return( FALSE ); X X /* if checking for a monster, return False if one there already _or_ X there is a pit/trap there. X */ X if (monst) X { X if (mitem[x][y]) X return (FALSE); X switch(item[x][y]) X { X /* note: not invisible traps, since monsters are not affected X by them. X */ X case OPIT: case OANNIHILATION: X case OTELEPORTER: case OTRAPARROW: X case ODARTRAP: case OTRAPDOOR: X return(FALSE); X break; X default: X break; X } X } X return(TRUE); X } X X/* X * createitem(it,arg) Routine to place an item next to the player X * int it,arg; X * X * Enter with the item number and its argument (iven[], ivenarg[]) X * Returns no value, thus we don't know about createitem() failures. X */ Xcreateitem(it,arg) X int it,arg; X { X register int x,y,k,i; X if (it >= MAXOBJ) return; /* no such object */ X for (k=rnd(8), i= -8; i<0; i++,k++) /* choose direction, then try all */ X { X if (k>8) k=1; /* wraparound the diroff arrays */ X x = playerx + diroffx[k]; y = playery + diroffy[k]; X if (cgood(x,y,1,0)) /* if we can create here */ X { X item[x][y] = it; know[x][y]=0; iarg[x][y]=arg; return; X } X } X } X X X/* X * vxy(x,y) Routine to verify/fix coordinates for being within bounds X * int *x,*y; X * X * Function to verify x & y are within the bounds for a level X * If *x or *y is not within the absolute bounds for a level, fix them so that X * they are on the level. X * Returns TRUE if it was out of bounds, and the *x & *y in the calling X * routine are affected. X */ Xvxy(x,y) X int *x,*y; X { X int flag=0; X if (*x<0) { *x=0; flag++; } X if (*y<0) { *y=0; flag++; } X if (*x>=MAXX) { *x=MAXX-1; flag++; } X if (*y>=MAXY) { *y=MAXY-1; flag++; } X return(flag); X } X X/* X * hitmonster(x,y) Function to hit a monster at the designated coordinates X * int x,y; X * X * This routine is used for a bash & slash type attack on a monster X * Enter with the coordinates of the monster in (x,y). X * Returns no value. X */ Xhitmonster(x,y) X int x,y; X { X extern char lastmonst[] ; X register int tmp,monst,damag,flag; X if (c[TIMESTOP]) return; /* not if time stopped */ X vxy(&x,&y); /* verify coordinates are within range */ X if ((monst = mitem[x][y]) == 0) return; X hit3flag=1; ifblind(x,y); X tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS]/4 - 12; X cursors(); X if ((rnd(20) < tmp-c[HARDGAME]) || (rnd(71) < 5)) /* need at least random chance to hit */ X { X lprcat("\nYou hit"); flag=1; X damag = fullhit(1); X if (damag<9999) damag=rnd(damag)+1; X } X else X { X lprcat("\nYou missed"); flag=0; X } X lprcat(" the "); lprcat(lastmonst); X if (flag) /* if the monster was hit */ X if ((monst==RUSTMONSTER) || (monst==DISENCHANTRESS) || (monst==CUBE)) X if (c[WIELD]>=0) X if (ivenarg[c[WIELD]] > -10) X { X lprintf("\nYour weapon is dulled by the %s",lastmonst); beep(); X --ivenarg[c[WIELD]]; X X /* fix for dulled rings of strength,cleverness, and dexterity X bug. X */ X switch (iven[c[WIELD]]) X { X case ODEXRING : X c[DEXTERITY]--; X break; X case OSTRRING : X c[STREXTRA]--; X break; X case OCLEVERRING : X c[INTELLIGENCE]--; X break; X } X } X if (flag) hitm(x,y,damag); X if (monst == VAMPIRE) if (hitp[x][y]<25) { mitem[x][y]=BAT; know[x][y]=0; } X } X X/* X * hitm(x,y,amt) Function to just hit a monster at a given coordinates X * int x,y,amt; X * X * Returns the number of hitpoints the monster absorbed X * This routine is used to specifically damage a monster at a location (x,y) X * Called by hitmonster(x,y) X */ Xhitm(x,y,amt) X int x,y; X register amt; X { X extern char lastmonst[] ; X register int monst; X int hpoints,amt2; X vxy(&x,&y); /* verify coordinates are within range */ X amt2 = amt; /* save initial damage so we can return it */ X monst = mitem[x][y]; X if (c[HALFDAM]) amt >>= 1; /* if half damage curse adjust damage points */ X if (amt<=0) amt2 = amt = 1; X lasthx=x; lasthy=y; X stealth[x][y]=1; /* make sure hitting monst breaks stealth condition */ X c[HOLDMONST]=0; /* hit a monster breaks hold monster spell */ X switch(monst) /* if a dragon and orb(s) of dragon slaying */ X { X case WHITEDRAGON: case REDDRAGON: case GREENDRAGON: X case BRONZEDRAGON: case PLATINUMDRAGON: case SILVERDRAGON: X amt *= 1+(c[SLAYING]<<1); break; X } X/* invincible monster fix is here */ X if (hitp[x][y] > monster[monst].hitpoints) X hitp[x][y] = monster[monst].hitpoints; X if ((hpoints = hitp[x][y]) <= amt) X { X#ifdef EXTRA X c[MONSTKILLED]++; X#endif X lprintf("\nThe %s died!",lastmonst); X raiseexperience((long)monster[monst].experience); X amt = monster[monst].gold; if (amt>0) dropgold(rnd(amt)+amt); X dropsomething(monst); disappear(x,y); bottomline(); X return(hpoints); X } X hitp[x][y] = hpoints-amt; return(amt2); X } X X/* X * hitplayer(x,y) Function for the monster to hit the player from (x,y) X * int x,y; X * X * Function for the monster to hit the player with monster at location x,y X * Returns nothing of value. X */ Xhitplayer(x,y) X int x,y; X { X extern char lastmonst[] ; X register int dam,tmp,mster,bias; X vxy(&x,&y); /* verify coordinates are within range */ X lastnum = mster = mitem[x][y]; X/* spirit naga's and poltergeist's do nothing if scarab of negate spirit */ X if (c[NEGATESPIRIT] || c[SPIRITPRO]) if ((mster ==POLTERGEIST) || (mster ==SPIRITNAGA)) return; X/* if undead and cube of undead control */ X if (c[CUBEofUNDEAD] || c[UNDEADPRO]) if ((mster ==VAMPIRE) || (mster ==WRAITH) || (mster ==ZOMBIE)) return; X if ((know[x][y] & KNOWHERE) == 0) X show1cell(x,y); X bias = (c[HARDGAME]) + 1; X hitflag = hit2flag = hit3flag = 1; X yrepcount=0; X cursors(); ifblind(x,y); X if (c[INVISIBILITY]) if (rnd(33)<20) X { X lprintf("\nThe %s misses wildly",lastmonst); return; X } X if (c[CHARMCOUNT]) if (rnd(30)+5*monster[mster].level-c[CHARISMA]<30) X { X lprintf("\nThe %s is awestruck at your magnificence!",lastmonst); X return; X } X if (mster==BAT) dam=1; X else X { X dam = monster[mster].damage; X dam += rnd((int)((dam<1)?1:dam)) + monster[mster].level; X } X tmp = 0; X if (monster[mster].attack>0) X if (((dam + bias + 8) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1)) X { if (spattack(monster[mster].attack,x,y)) { lflushall(); return; } X tmp = 1; bias -= 2; cursors(); } X if (((dam + bias) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1)) X { X lprintf("\n The %s hit you ",lastmonst); tmp = 1; X if ((dam -= c[AC]) < 0) dam=0; X if (dam > 0) { losehp(dam); bottomhp(); lflushall(); } X } X if (tmp == 0) lprintf("\n The %s missed ",lastmonst); X } X X/* X * dropsomething(monst) Function to create an object when a monster dies X * int monst; X * X * Function to create an object near the player when certain monsters are killed X * Enter with the monster number X * Returns nothing of value. X */ Xstatic dropsomething(monst) X int monst; X { X switch(monst) X { X case ORC: case NYMPH: case ELF: case TROGLODYTE: X case TROLL: case ROTHE: case VIOLETFUNGI: X case PLATINUMDRAGON: case GNOMEKING: case REDDRAGON: X something(level); return; X X case LEPRECHAUN: if (rnd(101)>=75) creategem(); X if (rnd(5)==1) dropsomething(LEPRECHAUN); return; X } X } X X/* X * dropgold(amount) Function to drop some gold around player X * int amount; X * X * Enter with the number of gold pieces to drop X * Returns nothing of value. X */ Xdropgold(amount) X register int amount; X { X if (amount > 250) X createitem(OMAXGOLD,amount/100); X else X createitem(OGOLDPILE,amount); X } X X/* X * something(level) Function to create a random item around player X * int level; X * X * Function to create an item from a designed probability around player X * Enter with the cave level on which something is to be dropped X * Returns nothing of value. X */ Xsomething(level) X int level; X { X register int j; X int i; X if (level<0 || level>MAXLEVEL+MAXVLEVEL) return; /* correct level? */ X if (rnd(101)<8) X something(level); /* possibly more than one item */ X j = newobject(level,&i); X createitem(j,i); X } X X/* X * newobject(lev,i) Routine to return a randomly selected new object X * int lev,*i; X * X * Routine to return a randomly selected object to be created X * Returns the object number created, and sets *i for its argument X * Enter with the cave level and a pointer to the items arg X */ Xstatic char nobjtab[] = { 0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION, X OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE, X OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER, X OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR, X OBELT, ORING, OSTUDLEATHER, OSHIELD, OCOOKIE, OFLAIL, OCHAIN, OBATTLEAXE, X OSPLINT, O2SWORD, OCLEVERRING, OPLATE, OLONGSWORD }; X Xnewobject(lev,i) X register int lev,*i; X { X register int tmp=33,j; X if (level<0 || level>MAXLEVEL+MAXVLEVEL) return(0); /* correct level? */ X if (lev>6) tmp=41; else if (lev>4) tmp=39; X j = nobjtab[tmp=rnd(tmp)]; /* the object type */ X switch(tmp) X { X case 1: case 2: case 3: case 4: /* scroll */ X *i=newscroll(); break; X case 5: case 6: case 7: case 8: /* potion */ X *i=newpotion(); break; X case 9: case 10: case 11: case 12: /* gold */ X *i=rnd((lev+1)*10)+lev*10+10; break; X case 13: case 14: case 15: case 16: /* book */ X *i=lev; break; X case 17: case 18: case 19: /* dagger */ X if (!(*i=newdagger())) return(0); break; X case 20: case 21: case 22: /* leather armor */ X if (!(*i=newleather())) return(0); break; X case 23: case 32: case 38: /* regen ring, shield, 2-hand sword */ X *i=rund(lev/3+1); break; X case 24: case 26: /* prot ring, dexterity ring */ X *i=rnd(lev/4+1); break; X case 25: /* energy ring */ X *i=rund(lev/4+1); break; X case 27: case 39: /* strength ring, cleverness ring */ X *i=rnd(lev/2+1); break; X case 30: case 34: /* ring mail, flail */ X *i=rund(lev/2+1); break; X case 28: case 36: /* spear, battleaxe */ X *i=rund(lev/3+1); if (*i==0) return(0); break; X case 29: case 31: case 37: /* belt, studded leather, splint */ X *i=rund(lev/2+1); if (*i==0) return(0); break; X case 33: /* fortune cookie */ X *i=0; break; X case 35: /* chain mail */ X *i=newchain(); break; X case 40: /* plate mail */ X *i=newplate(); break; X case 41: /* longsword */ X *i=newsword(); break; X } X return(j); X } X X/* X * spattack(atckno,xx,yy) Function to process special attacks from monsters X * int atckno,xx,yy; X * X * Enter with the special attack number, and the coordinates (xx,yy) X * of the monster that is special attacking X * Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise X * X * atckno monster effect X * --------------------------------------------------- X * 0 none X * 1 rust monster eat armor X * 2 hell hound breathe light fire X * 3 dragon breathe fire X * 4 giant centipede weakening sing X * 5 white dragon cold breath X * 6 wraith drain level X * 7 waterlord water gusher X * 8 leprechaun steal gold X * 9 disenchantress disenchant weapon or armor X * 10 ice lizard hits with barbed tail X * 11 umber hulk confusion X * 12 spirit naga cast spells taken from special attacks X * 13 platinum dragon psionics X * 14 nymph steal objects X * 15 bugbear bite X * 16 osequip bite X * X * char rustarm[ARMORTYPES][2]; X * special array for maximum rust damage to armor from rustmonster X * format is: { armor type , minimum attribute X */ X#define ARMORTYPES 6 X#if __STDC__ Xstatic signed char rustarm[ARMORTYPES][2] = X#else Xstatic char rustarm[ARMORTYPES][2] = X#endif X { OSTUDLEATHER,-2, ORING, -4, X OCHAIN, -5, OSPLINT, -6, X OPLATE, -8, OPLATEARMOR,-9 }; Xstatic char spsel[] = { 1, 2, 3, 5, 6, 8, 9, 11, 13, 14 }; Xstatic spattack(x,xx,yy) X int x,xx,yy; X { X extern char lastmonst[] ; X register int i,j=0,k,m; X register char *p=0; X if (c[CANCELLATION]) return(0); X vxy(&xx,&yy); /* verify x & y coordinates */ X switch(x) X { X case 1: /* rust your armor, j=1 when rusting has occurred */ X m = k = c[WEAR]; X if ((i=c[SHIELD]) != -1) X if (--ivenarg[i] < -1) ivenarg[i]= -1; else j=1; X if ((j==0) && (k != -1)) X { X m = iven[k]; X for (i=0; i3) X { X p="\nThe %s stung you! You feel weaker"; beep(); X --c[STRENGTH]; X } X else p="\nThe %s stung you!"; X break; X X case 5: p="\nThe %s blasts you with his cold breath"; X i = rnd(15)+18-c[AC]; goto spout2; X X case 6: lprintf("\nThe %s drains you of your life energy!",lastmonst); X loselevel(); beep(); return(0); X X case 7: p="\nThe %s got you with a gusher!"; X i = rnd(15)+25-c[AC]; goto spout2; X X case 8: if (c[NOTHEFT]) return(0); /* he has a device of no theft */ X if (c[GOLD]) X { X p="\nThe %s hit you -- Your purse feels lighter"; X if (c[GOLD]>32767) c[GOLD]>>=1; X else c[GOLD] -= rnd((int)(1+(c[GOLD]>>1))); X if (c[GOLD] < 0) c[GOLD]=0; X } X else p="\nThe %s couldn't find any gold to steal"; X lprintf(p,lastmonst); disappear(xx,yy); beep(); X bottomgold(); return(1); X X case 9: for(j=50; ; ) /* disenchant */ X { X i=rund(26); m=iven[i]; /* randomly select item */ X if (m>0 && ivenarg[i]>0 && m!=OSCROLL && m!=OPOTION) X { X if ((ivenarg[i] -= 3)<0) ivenarg[i]=0; X lprintf("\nThe %s hits you -- you feel a sense of loss",lastmonst); X beep(); show3(i); bottomline(); return(0); X } X if (--j<=0) X { X p="\nThe %s nearly misses"; break; X } X break; X } X break; X X case 10: p="\nThe %s hit you with his barbed tail"; X i = rnd(25)-c[AC]; goto spout2; X X case 11: p="\nThe %s has confused you"; beep(); X c[CONFUSE]+= 10+rnd(10); break; X X case 12: /* performs any number of other special attacks */ X return(spattack(spsel[rund(10)],xx,yy)); X X case 13: p="\nThe %s flattens you with his psionics!"; X i = rnd(15)+30-c[AC]; goto spout2; X X case 14: if (c[NOTHEFT]) return(0); /* he has device of no theft */ X if (emptyhanded()==1) X { X p="\nThe %s couldn't find anything to steal"; X break; X } X lprintf("\nThe %s picks your pocket and takes:",lastmonst); X beep(); X if (stealsomething()==0) lprcat(" nothing"); disappear(xx,yy); X bottomline(); return(1); X X case 15: i= rnd(10)+ 5-c[AC]; X spout3: p="\nThe %s bit you!"; X goto spout2; X X case 16: i= rnd(15)+10-c[AC]; goto spout3; X }; X if (p) { lprintf(p,lastmonst); bottomline(); } X return(0); X } X X/* X * checkloss(x) Routine to subtract hp from user and flag bottomline display X * int x; X * X * Routine to subtract hitpoints from the user and flag the bottomline display X * Enter with the number of hit points to lose X * Note: if x > c[HP] this routine could kill the player! X */ Xcheckloss(x) X int x; X { X if (x>0) { losehp(x); bottomhp(); } X } END_OF_FILE if test 22497 -ne `wc -c <'monster.c'`; then echo shar: \"'monster.c'\" unpacked with wrong size! fi # end of 'monster.c' fi if test -f 'spells.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'spells.c'\" else echo shar: Extracting \"'spells.c'\" \(27345 characters\) sed "s/^X//" >'spells.c' <<'END_OF_FILE' X/* X cast() Subroutine called by parse to cast a spell for the user X speldamage(x) Function to perform spell functions cast by the player X loseint() Routine to decrement your int (intelligence) if > 3 X isconfuse() Routine to check to see if player is confused X nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster X fullhit(xx) Function to return full damage against a monst (aka web) X direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir X godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks X ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt X tdirect(spnum) Routine to teleport away a monster X omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player X dirsub(x,y) Routine to ask for direction, then modify x,y for it X dirpoly(spnum) Routine to ask for a direction and polymorph a monst X annihilate() Routine to annihilate monsters around player, playerx,playery X genmonst() Function to ask for monster and genocide from game X*/ X X#include "header.h" X#include "larndefs.h" X#include "objects.h" X#include "monsters.h" X#include "player.h" X#include X X#define min(x,y) (((x)>(y))?(y):(x)) X#define max(x,y) (((x)>(y))?(x):(y)) X Xstruct isave /* used for altar reality */ X { X char type; /* 0=item, 1=monster */ X char id; /* item number or monster number */ X short arg; /* the type of item or hitpoints of monster */ X }; X X/* Forward declarations X*/ Xstatic void create_guardian(); Xextern hitm(); Xextern char spelweird[MAXMONST+8][SPNUM]; X X/* X * cast() Subroutine called by parse to cast a spell for the user X * X * No arguments and no return value. X */ Xstatic char eys[] = "\nEnter your spell: "; Xcast() X { X register int i,j,a,b,d; X cursors(); X if (c[SPELLS]<=0) X { X lprcat("\nYou don't have any spells!"); X return; X } X lprcat(eys); X --c[SPELLS]; X while ((a=ttgetch())=='I') X { X seemagic(-1); X cursors(); X lprcat(eys); X } X if (a=='\33') X goto over; /* to escape casting a spell */ X if ((b=ttgetch())=='\33') X goto over; /* to escape casting a spell */ X if ((d=ttgetch())=='\33') X { Xover: X lprcat(aborted); X c[SPELLS]++; X return; X } /* to escape casting a spell */ X#ifdef EXTRA X c[SPELLSCAST]++; X#endif X for (lprc('\n'),j= -1,i=0; i=SPNUM) return; /* no such spell */ X if (c[TIMESTOP]) { lprcat(" It didn't seem to work"); return; } /* not if time stopped */ X clev = c[LEVEL]; X if ((rnd(23)==7) || (rnd(18) > c[INTELLIGENCE])) X { lprcat(" It didn't work!"); return; } X if (clev*3+2 < x) X { X lprcat(" Nothing happens. You seem inexperienced at this"); X return; X } X X switch(x) X { X/* ----- LEVEL 1 SPELLS ----- */ X X case 0: if (c[PROTECTIONTIME]==0) c[MOREDEFENSES]+=2; /* protection field +2 */ X c[PROTECTIONTIME] += 250; return; X X case 1: i = rnd(((clev+1)<<1)) + clev + 3; X godirect(x,i,(clev>=2)?" Your missiles hit the %s":" Your missile hit the %s",100,'+'); /* magic missile */ X X return; X X case 2: if (c[DEXCOUNT]==0) c[DEXTERITY]+=3; /* dexterity */ X c[DEXCOUNT] += 400; return; X X case 3: i=rnd(3)+1; X p=" While the %s slept, you smashed it %d times"; X ws: direct(x,fullhit(i),p,i); /* sleep */ return; X X case 4: /* charm monster */ c[CHARMCOUNT] += c[CHARISMA]<<1; return; X X case 5: godirect(x,rnd(10)+15+clev," The sound damages the %s",70,'@'); /* sonic spear */ X return; X X/* ----- LEVEL 2 SPELLS ----- */ X X case 6: i=rnd(3)+2; p=" While the %s is entangled, you hit %d times"; X goto ws; /* web */ X X case 7: if (c[STRCOUNT]==0) c[STREXTRA]+=3; /* strength */ X c[STRCOUNT] += 150+rnd(100); return; X X case 8: yl = playery-5; /* enlightenment */ X yh = playery+6; xl = playerx-15; xh = playerx+16; X vxy(&xl,&yl); vxy(&xh,&yh); /* check bounds */ X for (i=yl; i<=yh; i++) /* enlightenment */ X for (j=xl; j<=xh; j++) X know[j][i]=KNOWALL; X draws(xl,xh+1,yl,yh+1); return; X X case 9: raisehp(20+(clev<<1)); return; /* healing */ X X case 10: c[BLINDCOUNT]=0; return; /* cure blindness */ X X case 11: createmonster(makemonst(level+1)+8); return; X X case 12: if (rnd(11)+7 <= c[WISDOM]) direct(x,rnd(20)+20+clev," The %s believed!",0); X else lprcat(" It didn't believe the illusions!"); X return; X X case 13: /* if he has the amulet of invisibility then add more time */ X for (j=i=0; i<26; i++) X if (iven[i]==OAMULET) j+= 1+ivenarg[i]; X c[INVISIBILITY] += (j<<7)+12; return; X X/* ----- LEVEL 3 SPELLS ----- */ X X case 14: godirect(x,rnd(25+clev)+25+clev," The fireball hits the %s",40,'*'); return; /* fireball */ X X case 15: godirect(x,rnd(25)+20+clev," Your cone of cold strikes the %s",60,'O'); /* cold */ X return; X X case 16: dirpoly(x); return; /* polymorph */ X X case 17: c[CANCELLATION]+= 5+clev; return; /* cancellation */ X X case 18: c[HASTESELF]+= 7+clev; return; /* haste self */ X X case 19: omnidirect(x,30+rnd(10)," The %s gasps for air"); /* cloud kill */ X return; X X case 20: xh = min(playerx+1,MAXX-2); yh = min(playery+1,MAXY-2); X for (i=max(playerx-1,1); i<=xh; i++) /* vaporize rock */ X for (j=max(playery-1,1); j<=yh; j++) X { X kn = &know[i][j]; X pm = &mitem[i][j]; X switch(*(p= &item[i][j])) X { X case OWALL: if (level < MAXLEVEL+MAXVLEVEL-1) X *p = *kn = 0; X break; X X case OSTATUE: if (c[HARDGAME]<3) X { X *p=OBOOK; iarg[i][j]=level; *kn=0; X } X break; X X case OTHRONE: X *p= OTHRONE2; X create_guardian( GNOMEKING, i, j ); X break; X X case OALTAR: X create_guardian( DEMONPRINCE, i, j ); X break; X X case OFOUNTAIN: X create_guardian( WATERLORD, i, j ); X break; X }; X switch(*pm) X { X case XORN: ifblind(i,j); hitm(i,j,200); break; /* Xorn takes damage from vpr */ X } X } X return; X X/* ----- LEVEL 4 SPELLS ----- */ X X case 21: direct(x,100+clev," The %s shrivels up",0); /* dehydration */ X return; X X case 22: godirect(x,rnd(25)+20+(clev<<1)," A lightning bolt hits the %s",1,'~'); /* lightning */ X return; X X case 23: i=min(c[HP]-1,c[HPMAX]/2); /* drain life */ X direct(x,i+i,"",0); c[HP] -= i; return; X X case 24: if (c[GLOBE]==0) c[MOREDEFENSES] += 10; X c[GLOBE] += 200; loseint(); /* globe of invulnerability */ X return; X X case 25: omnidirect(x,32+clev," The %s struggles for air in your flood!"); /* flood */ X return; X X case 26: if (rnd(151)==63) { beep(); lprcat("\nYour heart stopped!\n"); nap(4000); died(270); return; } X if (c[WISDOM]>rnd(10)+10) direct(x,2000," The %s's heart stopped",0); /* finger of death */ X else lprcat(" It didn't work"); return; X X/* ----- LEVEL 5 SPELLS ----- */ X X case 27: c[SCAREMONST] += rnd(10)+clev; return; /* scare monster */ X X case 28: c[HOLDMONST] += rnd(10)+clev; return; /* hold monster */ X X case 29: c[TIMESTOP] += rnd(20)+(clev<<1); return; /* time stop */ X X case 30: tdirect(x); return; /* teleport away */ X X case 31: omnidirect(x,35+rnd(10)+clev," The %s cringes from the flame"); /* magic fire */ X return; X X/* ----- LEVEL 6 SPELLS ----- */ X X case 32: if ((rnd(23)==5) && (wizard==0)) /* sphere of annihilation */ X { X beep(); lprcat("\nYou have been enveloped by the zone of nothingness!\n"); X nap(4000); died(258); return; X } X xl=playerx; yl=playery; X loseint(); X i=dirsub(&xl,&yl); /* get direction of sphere */ X newsphere(xl,yl,i,rnd(20)+11); /* make a sphere */ X return; X X case 33: genmonst(); spelknow[33]=0; /* genocide */ X loseint(); X return; X X case 34: /* summon demon */ X if (rnd(100) > 30) { direct(x,150," The demon strikes at the %s",0); return; } X if (rnd(100) > 15) { lprcat(" Nothing seems to have happened"); return; } X lprcat(" The demon turned on you and vanished!"); beep(); X i=rnd(40)+30; lastnum=277; X losehp(i); /* must say killed by a demon */ return; X X case 35: /* walk through walls */ X c[WTW] += rnd(10)+5; return; X X case 36: /* alter reality */ X { X struct isave *save; /* pointer to item save structure */ X int sc; sc=0; /* # items saved */ X save = (struct isave *)malloc(sizeof(struct isave)*MAXX*MAXY*2); X if (save == NULL) X { X lprcat("\nPolinneaus won't let you mess with his dungeon!"); X return; X } X for (j=0; j0) /* put objects back in level */ X { X --sc; X if (save[sc].type == 0) X { X int trys; X for (trys=100, i=j=1; --trys>0 && item[i][j]; i=rnd(MAXX-1), j=rnd(MAXY-1)); X if (trys) { item[i][j]=save[sc].id; iarg[i][j]=save[sc].arg; } X } X else X { /* put monsters back in */ X int trys; X for (trys=100, i=j=1; --trys>0 && (item[i][j]==OWALL || mitem[i][j]); i=rnd(MAXX-1), j=rnd(MAXY-1)); X if (trys) { mitem[i][j]=save[sc].id; hitp[i][j]=save[sc].arg; } X } X } X loseint(); X draws(0,MAXX,0,MAXY); if (wizard==0) spelknow[36]=0; X free((char*)save); positionplayer(); return; X } X X case 37: /* permanence */ adjtime(-99999L); spelknow[37]=0; /* forget */ X loseint(); X return; X X default: lprintf(" spell %d not available!",(long)x); beep(); return; X }; X } X X/* X Create a guardian for a throne/altar/fountain, as a result of the player X using a VPR spell or pulverization scroll on it. X*/ Xstatic void create_guardian( monst, x, y ) Xint monst; /* monster code for the guardian */ Xint x, y; /* coords of the object being guarded */ X { X int k ; X X /* prevent the guardian from being created on top of the player X */ X if ((x == playerx) && (y == playery)) X { X k = rnd(8); X x += diroffx[k]; X y += diroffy[k]; X } X know[x][y] = 0; X mitem[x][y] = monst ; X hitp[x][y] = monster[monst].hitpoints; X } X X/* X * loseint() Routine to subtract 1 from your int (intelligence) if > 3 X * X * No arguments and no return value X */ Xstatic loseint() X { X if (--c[INTELLIGENCE]<3) c[INTELLIGENCE]=3; X } X X/* X * isconfuse() Routine to check to see if player is confused X * X * This routine prints out a message saying "You can't aim your magic!" X * returns 0 if not confused, non-zero (time remaining confused) if confused X */ Xstatic isconfuse() X { X if (c[CONFUSE]) { lprcat(" You can't aim your magic!"); beep(); } X return(c[CONFUSE]); X } X X/* X * nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster X * int x,monst; X * X * Subroutine to return 1 if the spell can't affect the monster X * otherwise returns 0 X * Enter with the spell number in x, and the monster number in monst. X */ Xstatic nospell(x,monst) X int x,monst; X { X register int tmp; X if (x>=SPNUM || monst>=MAXMONST+8 || monst<0 || x<0) return(0); /* bad spell or monst */ X if ((tmp=spelweird[monst-1][x])==0) return(0); X cursors(); lprc('\n'); lprintf(spelmes[tmp],monster[monst].name); return(1); X } X X/* X * fullhit(xx) Function to return full damage against a monster (aka web) X * int xx; X * X * Function to return hp damage to monster due to a number of full hits X * Enter with the number of full hits being done X */ Xfullhit(xx) X int xx; X { X register int i; X if (xx<0 || xx>20) return(0); /* fullhits are out of range */ X if (c[LANCEDEATH]) return(10000); /* lance of death */ X i = xx * ((c[WCLASS]>>1)+c[STRENGTH]+c[STREXTRA]-c[HARDGAME]-12+c[MOREDAM]); X return( (i>=1) ? i : xx ); X } X X/* X * direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir X * int spnum,dam,arg; X * char *str; X * X * Routine to ask for a direction to a spell and then hit the monster X * Enter with the spell number in spnum, the damage to be done in dam, X * lprintf format string in str, and lprintf's argument in arg. X * Returns no value. X */ Xstatic direct(spnum,dam,str,arg) X int spnum,dam,arg; X char *str; X { X extern char lastmonst[]; X int x,y; X register int m; X if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad arguments */ X if (isconfuse()) return; X dirsub(&x,&y); X m = mitem[x][y]; X if (item[x][y]==OMIRROR) X { X if (spnum==3) /* sleep */ X { X lprcat("You fall asleep! "); beep(); X fool: X arg += 2; X while (arg-- > 0) { parse2(); nap(1000); } X return; X } X else if (spnum==6) /* web */ X { X lprcat("You get stuck in your own web! "); beep(); X goto fool; X } X else X { X lastnum=278; X lprintf(str,"spell caster (thats you)",(long)arg); X beep(); losehp(dam); return; X } X } X if (m==0) X { lprcat(" There wasn't anything there!"); return; } X ifblind(x,y); X if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; } X lprintf(str,lastmonst,(long)arg); hitm(x,y,dam); X } X X/* X * godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks X * int spnum,dam,delay; X * char *str,cshow; X * X * Function to hit in a direction from a missile weapon and have it keep X * on going in that direction until its power is exhausted X * Enter with the spell number in spnum, the power of the weapon in hp, X * lprintf format string in str, the # of milliseconds to delay between X * locations in delay, and the character to represent the weapon in cshow. X * Returns no value. X */ Xgodirect(spnum,dam,str,delay,cshow) X int spnum,dam,delay; X char *str,cshow; X { X extern char lastmonst[] ; X register char *p; X register int x,y,m; X int dx,dy; X if (spnum<0 || spnum>=SPNUM || str==0 || delay<0) return; /* bad args */ X if (isconfuse()) return; X dirsub(&dx,&dy); x=dx; y=dy; X dx = x-playerx; dy = y-playery; x = playerx; y = playery; X while (dam>0) X { X x += dx; y += dy; X if ((x > MAXX-1) || (y > MAXY-1) || (x < 0) || (y < 0)) X { X dam=0; break; /* out of bounds */ X } X if ((x==playerx) && (y==playery)) /* if energy hits player */ X { X cursors(); lprcat("\nYou are hit my your own magic!"); beep(); X lastnum=278; losehp(dam); return; X } X if (c[BLINDCOUNT]==0) /* if not blind show effect */ X { X cursor(x+1,y+1); lprc(cshow); nap(delay); show1cell(x,y); X } X if ((m=mitem[x][y])) /* is there a monster there? */ X { X ifblind(x,y); X if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; } X cursors(); lprc('\n'); X lprintf(str,lastmonst); dam -= hitm(x,y,dam); X show1cell(x,y); nap(1000); x -= dx; y -= dy; X } X else switch (*(p= &item[x][y])) X { X case OWALL: X cursors(); X lprc('\n'); X lprintf(str,"wall"); X if (dam>=50+c[HARDGAME]) /* enough damage? */ X if (level=40) X { X lprcat(" The door is blasted apart"); X *p = 0; X know[x][y] = 0; X show1cell( x, y ); X } X dam = 0 ; X break; X X case OSTATUE: X cursors(); X lprc('\n'); X lprintf(str,"statue"); X if (c[HARDGAME]<3) X if (dam>44) X { X lprcat(" The statue crumbles"); X *p=OBOOK; X iarg[x][y]=level; X know[x][y] = 0; X show1cell( x, y ); X } X dam = 0 ; X break; X X case OTHRONE: X cursors(); X lprc('\n'); X lprintf(str,"throne"); X if (dam>39) X { X *p = OTHRONE2; X create_guardian( GNOMEKING, x, y ); X show1cell( x, y ); X } X dam = 0; X break; X X case OALTAR: X cursors(); X lprc('\n'); X lprintf(str, "altar"); X if ( dam > 75 - ( c[HARDGAME] >> 2 )) X { X create_guardian( DEMONPRINCE, x, y ); X show1cell( x, y ); X } X dam = 0 ; X break; X X case OFOUNTAIN: X cursors(); X lprc('\n'); X lprintf(str, "fountain"); X if ( dam > 55 ) X { X create_guardian( WATERLORD, x, y ); X show1cell( x, y ); X } X dam = 0 ; X break; X X case OMIRROR: X { X int bounce = FALSE, odx=dx, ody=dy ; X /* spells may bounce directly back or off at an angle X */ X if (rnd(100) < 50 ) X { X bounce = TRUE ; X dx *= -1; X } X if (rnd(100) < 50 ) X { X bounce = TRUE ; X dy *= -1; X } X if (!bounce || ((odx==dx) && (ody==dy))) /* guarentee a bounce */ X { X dx = -odx; X dy = -ody; X } X } X break; X }; X dam -= 3 + (c[HARDGAME]>>1); X } X } X X/* X * ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt X * int x,y; X * X * Subroutine to copy the word "monster" into lastmonst if the player is blind X * Enter with the coordinates (x,y) of the monster X * Returns no value. X */ Xifblind(x,y) X int x,y; X { X extern char lastmonst[] ; X char *p; X vxy(&x,&y); /* verify correct x,y coordinates */ X if (c[BLINDCOUNT]) { lastnum=279; p="monster"; } X else { lastnum=mitem[x][y]; p=monster[lastnum].name; } X strcpy(lastmonst,p); X } X X/* X * tdirect(spnum) Routine to teleport away a monster X * int spnum; X * X * Routine to ask for a direction to a spell and then teleport away monster X * Enter with the spell number that wants to teleport away X * Returns no value. X */ Xstatic tdirect(spnum) X int spnum; X { X int x,y; X register int m; X if (spnum<0 || spnum>=SPNUM) return; /* bad args */ X if (isconfuse()) return; X dirsub(&x,&y); X if ((m=mitem[x][y])==0) X { lprcat(" There wasn't anything there!"); return; } X ifblind(x,y); X if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; } X fillmonst(m); mitem[x][y]=0; know[x][y] &= ~KNOWHERE; X } X X/* X * omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player X * int sp,dam; X * char *str; X * X * Routine to cast a spell and then hit the monster in all directions X * Enter with the spell number in sp, the damage done to wach square in dam, X * and the lprintf string to identify the spell in str. X * Returns no value. X */ Xstatic omnidirect(spnum,dam,str) X int spnum,dam; X char *str; X { X extern char lastmonst[] ; X register int x,y,m; X if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad args */ X for (x=playerx-1; x=SPNUM) return; /* bad args */ X if (isconfuse()) return; /* if he is confused, he can't aim his magic */ X dirsub(&x,&y); X if (mitem[x][y]==0) X { lprcat(" There wasn't anything there!"); return; } X ifblind(x,y); X if (nospell(spnum,mitem[x][y])) { lasthx=x; lasthy=y; return; } X# ifdef MSDOS X do { X m = rnd(MAXMONST+7); X mitem[x][y] = m; X } while ( monster[m].genocided ); X# else X while ( monster[m = mitem[x][y] = rnd(MAXMONST+7)].genocided ); X# endif X hitp[x][y] = monster[m].hitpoints; X show1cell(x,y); /* show the new monster */ X } X X/* X * annihilate() Routine to annihilate all monsters around player (playerx,playery) X * X * Gives player experience, but no dropped objects X * Returns the experience gained from all monsters killed X */ Xannihilate() X { X int i,j; X register long k; X register char *p; X for (k=0, i=playerx-1; i<=playerx+1; i++) X for (j=playery-1; j<=playery+1; j++) X if (!vxy(&i,&j)) /* if not out of bounds */ X if (*(p= &mitem[i][j])) /* if a monster there */ X if (*p>1) + 1; /* lose half hit points*/ X } X if (k>0) X { X lprcat("\nYou hear loud screams of agony!"); raiseexperience((long)k); X } X return(k); X } X X/* X * genmonst() Function to ask for monster and genocide from game X * X * This is done by setting a flag in the monster[] structure X */ Xstatic genmonst() X { X register int i,j; X cursors(); lprcat("\nGenocide what monster? "); X for (i=0; (!isalpha(i)) && (i!=' '); i=ttgetch()); X lprc(i); X for (j=0; j'vmsreadme.txt' <<'END_OF_FILE' XThis is a VMS version of LARN 12.3. To run it, larndir must be defined as a Xlogical name that points to the directory containing the support files X(LARN.MAZ, LARN.HLP, etc). Larn looks for LARN.OPT in SYS$LOGIN. VMS Version X5.x may be required. X XThe first entry in the larn.pid file (1000) can be the wizard if the password is Xknown (same password as in MS-DOS edition; see LARN122.DOC). X XThe sources have been compiled with termcap. It will look for the Xtermcap file either through the logical name "termcap", in the current Xdirectory as "termcap.", or as "sys$library:termcap." If there is Xa symbol or logical called "term" then the value of that will Xbe used for the terminal, otherwise the value from "terminal" will be Xused. X XThis version includes VMS Keypad support on VT class terminals. The keypad Xkeys must be set to application mode (SET TERM/APPLICATION) in order for LARN Xto recognise the keys. It is not necessary to set the KEYPAD option in the XLARN.OPT file. The key mappings are: X X PF1 PF2 PF3 PF4 X '@' X KP7 KP8 KP9 KP- X 'y' 'k' 'u' X KP4 KP5 KP6 KP, X 'h' '.' 'l' ',' X ^ KP1 KP2 KP3 KP X 'K' 'b' 'j' 'n' Enter X < v > KP0 KP. X 'H' 'J' 'L' 'i' '.' X XKeypad mode occasionally seems flakey, especially on DECTerms. Until I can Xre-work it, this will have to do. Customization of the keypad is not Xcurrently supported. X X Kevin Routley END_OF_FILE if test 1388 -ne `wc -c <'vmsreadme.txt'`; then echo shar: \"'vmsreadme.txt'\" unpacked with wrong size! fi # end of 'vmsreadme.txt' fi echo shar: End of archive 6 \(of 12\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 12 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0