[comp.sources.games] v12i059: larn2 - dungeon type adventure game

billr@saab.CNA.TEK.COM (Bill Randle) (04/24/91)

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 <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 12)."
# Contents:  monster.c spells.c vmsreadme.txt
# Wrapped by billr@saab on Tue Apr 23 13:50:31 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'monster.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'monster.c'\"
else
echo shar: Extracting \"'monster.c'\" \(22497 characters\)
sed "s/^X//" >'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 <ctype.h>
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 && mon<MAXMONST) mon++; /* genocided? */
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,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; i<ARMORTYPES; i++)
X                    if (m == rustarm[i][0]) /* find his armor in table */
X                        {
X                        if (--ivenarg[k]< rustarm[i][1])
X                            ivenarg[k]= rustarm[i][1]; else j=1; 
X                        break;
X                        }
X                  }
X                if (j==0)   /* if rusting did not occur */
X                  switch(m)
X                    {
X                    case OLEATHER:  p = "\nThe %s hit you -- Your lucky you have leather on";
X                                    break;
X                    case OSSPLATE:  p = "\nThe %s hit you -- Your fortunate to have stainless steel armor!";
X                                    break;
X                    }
X                else  { beep(); p = "\nThe %s hit you -- your armor feels weaker"; }
X                break;
X
X        case 2:     i = rnd(15)+8-c[AC];
X            spout:  p="\nThe %s breathes fire at you!";
X                    if (c[FIRERESISTANCE])
X                      p="\nThe %s's flame doesn't phase you!";
X                    else
X            spout2: if (p) { lprintf(p,lastmonst); beep(); }
X                    checkloss(i);
X                    return(0);
X
X        case 3:     i = rnd(20)+25-c[AC];  goto spout;
X
X        case 4: if (c[STRENGTH]>3)
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 <ctype.h>
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; i++) /*seq search for his spell, hash?*/
X        if ((spelcode[i][0]==a) && (spelcode[i][1]==b) && (spelcode[i][2]==d))
X            if (spelknow[i])
X                {  speldamage(i);  j = 1;  i=SPNUM; }
X
X    if (j == -1) lprcat("  Nothing Happened ");
X    bottomline();
X    }
X
X/*
X *  speldamage(x)       Function to perform spell functions cast by the player
X *      int x;
X *
X *  Enter with the spell number, returns no value.
X *  Please insure that there are 2 spaces before all messages here
X */
Xstatic speldamage(x)
X    int x;
X    {
X    register int i,j,clev;
X    int xl,xh,yl,yh;
X    register char *p,*kn,*pm;
X
X    if (x>=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; j<MAXY; j++)
X                        for (i=0; i<MAXX; i++) /* save all items and monsters */
X                            {
X                            xl = item[i][j];
X                            if (xl && xl!=OWALL && xl!=OANNIHILATION) 
X                                {
X                                save[sc].type=0;  save[sc].id=item[i][j];
X                                save[sc++].arg=iarg[i][j];
X                                }
X                            if (mitem[i][j]) 
X                                {
X                                save[sc].type=1;  save[sc].id=mitem[i][j];
X                                save[sc++].arg=hitp[i][j];
X                                }
X                            item[i][j]=OWALL;   mitem[i][j]=0;
X                        if (wizard)
X                            know[i][j]=KNOWALL;
X                        else
X                            know[i][j]=0;
X                            }
X                    eat(1,1);   if (level==1) item[33][MAXY-1]=OENTRANCE;
X                    for (j=rnd(MAXY-2), i=1; i<MAXX-1; i++) item[i][j]=0;
X                    while (sc>0) /* 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<MAXLEVEL+MAXVLEVEL-1) /* not on V3 */
X            if ((x<MAXX-1) && (y<MAXY-1) && (x) && (y))
X                            {
X                            lprcat("  The wall crumbles");
X                *p=0;
X                know[x][y]=0;
X                            show1cell(x,y);
X                            }
X        dam = 0;
X        break;
X
X        case OCLOSEDDOOR:
X        cursors();
X        lprc('\n');
X        lprintf(str,"door");
X        if (dam>=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<playerx+2; x++)
X        for (y=playery-1; y<playery+2; y++)
X            {
X            if (m=mitem[x][y])
X                if (nospell(spnum,m) == 0)
X                    {
X                    ifblind(x,y);
X                    cursors(); lprc('\n'); lprintf(str,lastmonst);
X                    hitm(x,y,dam);  nap(800);
X                    }
X                else  { lasthx=x;  lasthy=y; }
X            }
X    }
X
X/*
X *  dirsub(x,y)      Routine to ask for direction, then modify playerx,
X *                   playery for it
X *      int *x,*y;
X *
X *  Function to ask for a direction and modify an x,y for that direction
X *  Enter with the coordinate destination (x,y).
X *  Returns index into diroffx[] (0-8).
X */
Xdirsub(x,y)
X    int *x,*y;
X    {
X    register int i;
X    lprcat("\nIn What Direction? ");
X    for (i=0; ; )
X        switch(ttgetch())
X            {
X            case 'b':   i++;
X            case 'n':   i++;
X            case 'y':   i++;
X            case 'u':   i++;
X            case 'h':   i++;
X            case 'k':   i++;
X            case 'l':   i++;
X            case 'j':   i++;        goto out;
X            };
Xout:
X    *x = playerx+diroffx[i];        *y = playery+diroffy[i];
X    vxy(x,y);  return(i);
X    }
X
X/*
X *  dirpoly(spnum)      Routine to ask for a direction and polymorph a monst
X *      int spnum;
X *
X *  Subroutine to polymorph a monster and ask for the direction its in
X *  Enter with the spell number in spmun.
X *  Returns no value.
X */
Xstatic dirpoly(spnum)
X    int spnum;
X    {
X    int x,y,m;
X    if (spnum<0 || spnum>=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<DEMONLORD+2)
X                    {
X                    k += monster[*p].experience;    *p=know[i][j] &= ~KNOWHERE;
X                    }
X                else
X                    {
X                    lprintf("\nThe %s barely escapes being annihilated!",monster[*p].name);
X                    hitp[i][j] = (hitp[i][j]>>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<MAXMONST; j++)  /* search for the monster type */
X        if (monstnamelist[j]==i)    /* have we found it? */
X            {
X            monster[j].genocided=1; /* genocided from game */
X            lprintf("  There will be no more %s's",monster[j].name);
X            /* now wipe out monsters on this level */
X            newcavelevel(level); draws(0,MAXX,0,MAXY); bot_linex();
X            return;
X            }
X    lprcat("  You sense failure!");
X    }
END_OF_FILE
if test 27345 -ne `wc -c <'spells.c'`; then
    echo shar: \"'spells.c'\" unpacked with wrong size!
fi
# end of 'spells.c'
fi
if test -f 'vmsreadme.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vmsreadme.txt'\"
else
echo shar: Extracting \"'vmsreadme.txt'\" \(1388 characters\)
sed "s/^X//" >'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