[comp.sources.games] v12i062: 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 62
Archive-name: larn2/Part09
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 9 (of 12)."
# Contents:  action.c diag.c larnhlp.txt monsters.h tok.c
# Wrapped by billr@saab on Tue Apr 23 13:50:34 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'action.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'action.c'\"
else
echo shar: Extracting \"'action.c'\" \(13563 characters\)
sed "s/^X//" >'action.c' <<'END_OF_FILE'
X/*
X    action.c
X
X    Routines to perform the actual actions associated with various
X    player entered commands.
X
X    act_remove_gems         remove gems from a throne
X    act_sit_throne          sit on a throne
X    act_up_stairs           go up stairs
X    act_down_stairs         go down stairs
X    act_drink_fountain      drink from a fountain
X    act_wash_fountain       wash at a fountain
X    act_up_shaft            up volcanic shaft
X    act_down_shaft          down volcanic shaft
X    volshaft_climbed        place player near volcanic shaft
X    act_desecrate_altar     desecrate an altar
X    act_donation_pray       pray, donating money
X    act_just_pray           pray, not donating money
X    act_prayer_heard        prayer was heard
X    act_ignore_altar        ignore an altar
X    act_open_chest          open a chest
X    act_open_door           open a door
X*/
X
X#include "header.h"
X#include "larndefs.h"
X#include "monsters.h"
X#include "objects.h"
X#include "player.h"
X
X/*
X    act_remove_gems
X
X    Remove gems from a throne.
X
X    arg is zero if there is a gnome king associated with the throne
X
X    Assumes that cursors() has been called previously, and that a check
X    has been made that the throne actually has gems.
X*/
Xact_remove_gems( arg )
Xint arg ;
X    {
X    int i, k ;
X
X    k=rnd(101);
X    if (k<25)
X        {
X        for (i=0; i<rnd(4); i++) 
X            creategem(); /* gems pop off the throne */
X        item[playerx][playery]=ODEADTHRONE;
X        know[playerx][playery]=0;
X        }
X    else if (k<40 && arg==0)
X        {
X        createmonster(GNOMEKING);
X        item[playerx][playery]=OTHRONE2;
X        know[playerx][playery]=0;
X        }
X    else 
X        lprcat("\nNothing happens");
X
X    return ;
X    }
X
X/*
X    act_sit_throne
X
X    Sit on a throne.
X
X    arg is zero if there is a gnome king associated with the throne
X
X    Assumes that cursors() has been called previously.
X*/
Xact_sit_throne( arg )
Xint arg ;
X    {
X    int k ;
X
X    k=rnd(101);
X    if (k<30 && arg==0)
X        {
X        createmonster(GNOMEKING);
X        item[playerx][playery]=OTHRONE2;
X        know[playerx][playery]=0;
X        }
X    else if (k<35) 
X        { 
X        lprcat("\nZaaaappp!  You've been teleported!\n"); 
X        beep(); 
X        oteleport(0); 
X        }
X    else 
X        lprcat("\nNothing happens");
X
X    return ;
X    }
X
X/*
X    assumes that cursors() has been called and that a check has been made that
X    the user is actually standing at a set of up stairs.
X*/
Xact_up_stairs()
X    {
X    if (level >= 2 && level != 11)
X        {
X        newcavelevel( level - 1 )  ;
X        draws( 0, MAXX, 0, MAXY );
X        bot_linex() ;
X        }
X    else
X        lprcat("\nThe stairs lead to a dead end!") ;
X    return ;
X    }
X
X/*
X    assumes that cursors() has been called and that a check has been made that
X    the user is actually standing at a set of down stairs.
X*/
Xact_down_stairs()
X    {
X    if (level != 0 && level != 10 && level != 13)
X        {
X        newcavelevel( level + 1 )  ;
X        draws( 0, MAXX, 0, MAXY );
X        bot_linex() ;
X        }
X    else
X        lprcat("\nThe stairs lead to a dead end!") ;
X    return ;
X    }
X
X/*
X    Code to perform the action of drinking at a fountian.  Assumes that
X    cursors() has already been called, and that a check has been made that
X    the player is actually standing at a live fountain.
X*/
Xact_drink_fountain()
X    {
X    int x ;
X
X    if (rnd(1501)<2)
X        {
X        lprcat("\nOops!  You seem to have caught the dreadful sleep!");
X        beep(); 
X        lflush();  
X        sleep(3);  
X        died(280); 
X        return;
X        }
X
X    x = rnd(100);
X    if (x<7)
X        {
X        c[HALFDAM] += 200 + rnd(200);
X        lprcat("\nYou feel a sickness coming on");
X        }
X
X    else if (x < 13)
X        quaffpotion(23, FALSE ); /* see invisible,but don't know the potion */
X
X    else if (x < 45)
X        lprcat("\nnothing seems to have happened");
X
X    else if (rnd(3) != 2)
X        fntchange(1);   /*  change char levels upward   */
X
X    else
X        fntchange(-1);  /*  change char levels downward */
X
X    if (rnd(12)<3)
X        {
X        lprcat("\nThe fountains bubbling slowly quiets");
X        item[playerx][playery]=ODEADFOUNTAIN; /* dead fountain */
X        know[playerx][playery]=0;
X        }
X    return;
X    }
X
X/*
X    Code to perform the action of washing at a fountain.  Assumes that
X    cursors() has already been called and that a check has been made that
X    the player is actually standing at a live fountain.
X*/
Xact_wash_fountain()
X    {
X    int x ;
X
X    if (rnd(100) < 11)
X        {
X        x=rnd((level<<2)+2);
X        lprintf("\nOh no!  The water was foul!  You suffer %d hit points!",(long)x);
X        lastnum=273;
X        losehp(x); 
X        bottomline();  
X        cursors();
X        }
X
X    else if (rnd(100) < 29)
X        lprcat("\nYou got the dirt off!");
X
X    else if (rnd(100) < 31)
X        lprcat("\nThis water seems to be hard water!  The dirt didn't come off!");
X
X    else if (rnd(100) < 34)
X        createmonster(WATERLORD); /*    make water lord     */
X
X    else
X        lprcat("\nnothing seems to have happened");
X
X    return;
X    }
X
X/*
X    Perform the act of climbing down the volcanic shaft.  Assumes
X    cursors() has been called and that a check has been made that
X    are actually at a down shaft.
X*/
Xact_down_shaft()
X    {
X    if (level!=0)
X        {
X        lprcat("\nThe shaft only extends 5 feet downward!");
X        return;
X        }
X
X    if (packweight() > 45+3*(c[STRENGTH]+c[STREXTRA]))
X        {
X        lprcat("\nYou slip and fall down the shaft");
X        beep();
X        lastnum=275;
X        losehp(30+rnd(20));
X        bottomhp();
X        }
X    else if (prompt_mode)
X        lprcat("climb down");
X
X    newcavelevel(MAXLEVEL);
X    draws(0,MAXX,0,MAXY);
X    bot_linex();
X    return;
X    }
X
X/*
X    Perform the action of climbing up the volcanic shaft. Assumes
X    cursors() has been called and that a check has been made that
X    are actually at an up shaft.
X
X*/
Xact_up_shaft()
X    {
X    if (level!=11) 
X        { 
X        lprcat("\nThe shaft only extends 8 feet upwards before you find a blockage!"); 
X        return; 
X        }
X
X    if (packweight() > 45+5*(c[STRENGTH]+c[STREXTRA])) 
X        { 
X        lprcat("\nYou slip and fall down the shaft"); 
X        beep();
X        lastnum=275; 
X        losehp(15+rnd(20)); 
X        bottomhp(); 
X        return; 
X        }
X
X    if (prompt_mode)
X        lprcat("climb up"); 
X    lflush(); 
X    newcavelevel(0);
X    volshaft_climbed( OVOLDOWN );
X    return;
X    }
X
X/*
X    Perform the action of placing the player near the volcanic shaft
X    after it has been climbed.
X
X    Takes one parameter:  the volcanic shaft object to be found.  If have
X    climbed up, search for OVOLDOWN, otherwise search for OVOLUP.
X*/
Xstatic volshaft_climbed(object)
Xint object;
X    {
X    int i,j ;
X
X    /* place player near the volcanic shaft */
X    for (i=0; i<MAXY; i++)
X        for (j=0; j<MAXX; j++)
X            if (item[j][i] == object)
X                {
X                playerx=j;
X                playery=i;
X                positionplayer();
X                i=MAXY;
X                break;
X                }
X    draws(0,MAXX,0,MAXY);
X    bot_linex();
X    return ;
X    }
X
X/*
X    Perform the actions associated with Altar desecration.
X*/
Xact_desecrate_altar()
X    {
X    if (rnd(100)<60)
X    { 
X    createmonster(makemonst(level+2)+8); 
X    c[AGGRAVATE] += 2500; 
X    }
X    else if (rnd(101)<30)
X    {
X    lprcat("\nThe altar crumbles into a pile of dust before your eyes");
X    forget();   /*  remember to destroy the altar   */
X    }
X    else
X    lprcat("\nnothing happens");
X    return ;
X    }
X
X/*
X    Perform the actions associated with praying at an altar and giving a
X    donation.
X*/
Xact_donation_pray()
X    {
X    unsigned long k,temp ;
X
X    while (1)
X        {
X        lprcat("\n\n");
X        cursor(1,24);
X        cltoeoln();
X        cursor(1,23);
X        cltoeoln();
X        lprcat("how much do you donate? ");
X        k = readnum((long)c[GOLD]);
X
X        /* VMS has a problem with echo mode input (used in readnum()) such that the
X           next carriage return will shift the screen up one line.  To get around
X           this, if we are VMS, don't print the next carriage return.  Otherwise,
X           print the carriage return needed by all following messages.
X	Turns out that all but MS-DOS (which has 25 lines) has this problem.
X        */
X#ifdef MSDOS
X            lprcat("\n");
X#endif
X
X        /* make giving zero gold equivalent to 'just pray'ing.  Allows player to
X           'just pray' in command mode, without having to add yet another command.
X        */
X        if (k == 0)
X            {
X            act_just_pray();
X            return;
X            }
X
X        if (c[GOLD] >= k)
X            {
X            temp = c[GOLD] / 10 ;
X            c[GOLD] -= k;
X            bottomline();
X
X            /* if player gave less than 10% of _original_ gold, make a monster
X            */
X            if (k < temp || k < rnd(50))
X                {
X                createmonster(makemonst(level+1));
X                c[AGGRAVATE] += 200;
X                return;
X                }
X            if (rnd(101) > 50)
X                {
X                act_prayer_heard();
X                return;
X                }
X            if (rnd(43) == 5)
X                {
X                if (c[WEAR])
X                    lprcat("You feel your armor vibrate for a moment");
X                enchantarmor();
X                return;
X                }
X            if (rnd(43) == 8)
X                {
X                if (c[WIELD])
X                    lprcat("You feel your weapon vibrate for a moment");
X                enchweapon();
X                return;
X                }
X
X            lprcat("Thank You.");
X            return ;
X            }
X
X        /* Player donates more gold than they have.  Loop back around so
X           player can't escape the altar for free.
X        */
X        lprcat("You don't have that much!");
X        }
X    }
X
X/*
X    Performs the actions associated with 'just praying' at the altar.  Called
X    when the user responds 'just pray' when in prompt mode, or enters 0 to
X    the money prompt when praying.
X
X    Assumes cursors(), and that any leading \n have been printed (to get
X    around VMS echo mode problem.
X*/
Xact_just_pray()
X    {
X    if (rnd(100)<75) 
X    lprcat("nothing happens");
X    else if (rnd(43) == 10)
X    {
X    if (c[WEAR]) 
X        lprcat("You feel your armor vibrate for a moment");
X    enchantarmor(); 
X    return;
X    }
X    else if (rnd(43) == 10)
X    {
X    if (c[WIELD]) 
X        lprcat("You feel your weapon vibrate for a moment");
X    enchweapon(); 
X    return;
X    }
X    else 
X    createmonster(makemonst(level+1));
X    return;
X    }
X
X/*
X    function to cast a +3 protection on the player
X */
Xstatic act_prayer_heard()
X    {
X    lprcat("You have been heard!");
X    if (c[ALTPRO]==0) 
X        c[MOREDEFENSES]+=3;
X    c[ALTPRO] += 500;   /* protection field */
X    bottomline();
X    }
X
X/*
X    Performs the act of ignoring an altar.
X
X    Assumptions:  cursors() has been called.
X*/
Xact_ignore_altar()
X    {
X    if (rnd(100)<30)    
X        {
X        createmonster(makemonst(level+1)); 
X        c[AGGRAVATE] += rnd(450); 
X        }
X    else    
X        lprcat("\nNothing happens");
X    return;
X    }
X
X/*
X    Performs the act of opening a chest.  
X
X    Parameters:   x,y location of the chest to open.
X    Assumptions:  cursors() has been called previously
X*/
Xact_open_chest(x,y)
Xint x,y ;
X    {
X    int i,k;
X
X    k=rnd(101);
X    if (k<40)
X        {
X        lprcat("\nThe chest explodes as you open it"); beep();
X        i = rnd(10);  lastnum=281;  /* in case he dies */
X        lprintf("\nYou suffer %d hit points damage!",(long)i);
X        checkloss(i);
X        switch(rnd(10)) /* see if he gets a curse */
X            {
X            case 1: c[ITCHING]+= rnd(1000)+100;
X                    lprcat("\nYou feel an irritation spread over your skin!");
X                    beep();
X                    break;
X
X            case 2: c[CLUMSINESS]+= rnd(1600)+200;
X                    lprcat("\nYou begin to lose hand to eye coordination!");
X                    beep();
X                    break;
X
X            case 3: c[HALFDAM]+= rnd(1600)+200;
X                    beep();
X                    lprcat("\nA sickness engulfs you!");    break;
X            };
X    item[x][y]=know[x][y]=0;    /* destroy the chest */
X        if (rnd(100)<69) creategem(); /* gems from the chest */
X    dropgold(rnd(110*iarg[playerx][playery]+200));
X        for (i=0; i<rnd(4); i++) something(iarg[playerx][playery]+2);
X        }
X    else
X        lprcat("\nNothing happens");
X    return;
X    }
X
X/*
X    Perform the actions common to command and prompt mode when opening a
X    door.  Assumes cursors().
X
X    Parameters:     the X,Y location of the door to open.
X    Return value:   TRUE if successful in opening the door, false if not.
X*/
Xact_open_door( x, y )
Xint x ;
Xint y ;
X    {
X    if (rnd(11)<7)
X        {
X        switch(iarg[x][y])
X            {
X            case 6: c[AGGRAVATE] += rnd(400);   break;
X
X            case 7: lprcat("\nYou are jolted by an electric shock ");
X                    lastnum=274; losehp(rnd(20));  bottomline();  break;
X
X            case 8: loselevel();  break;
X
X            case 9: lprcat("\nYou suddenly feel weaker ");
X                    if (c[STRENGTH]>3) c[STRENGTH]--;
X                    bottomline();  break;
X
X            default:    break;
X            }
X    return( 0 );
X        }
X    else
X        {
X        know[x][y]=0;
X        item[x][y]=OOPENDOOR;
X        return( 1 );
X        }
X    }
END_OF_FILE
if test 13563 -ne `wc -c <'action.c'`; then
    echo shar: \"'action.c'\" unpacked with wrong size!
fi
# end of 'action.c'
fi
if test -f 'diag.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'diag.c'\"
else
echo shar: Extracting \"'diag.c'\" \(14017 characters\)
sed "s/^X//" >'diag.c' <<'END_OF_FILE'
X/* diag.c */
X#ifdef VMS
X# include <types.h>
X# include <stat.h>
X#else
X# include <sys/types.h>
X# include <sys/stat.h>
X#endif VMS
X
X#ifndef MSDOS
X# ifndef VMS
X#  include <sys/times.h>
X  static struct tms cputime;
X# endif VMS
X#endif MSDOS
X
X#include "header.h"
X#include "larndefs.h"
X#include "monsters.h"
X#include "objects.h"
X#include "player.h"
X
Xextern long int initialtime;
Xextern int rmst,maxitm,lasttime;
Xextern char nosignal;
X
X/*
X    ***************************
X    DIAG -- dungeon diagnostics
X    ***************************
X
X    subroutine to print out data for debugging
X */
X#ifdef EXTRA
Xstatic int rndcount[16];
Xdiag()
X    {
X    register int i,j;
X    int hit,dam;
X    cursors();  lwclose();
X    if (lcreat(diagfile) < 0)   /*  open the diagnostic file    */
X        {
X        lcreat((char*)0); lprcat("\ndiagnostic failure\n"); return(-1);
X        }
X
X    write(1,"\nDiagnosing . . .\n",18);
X    lprcat("\n\nBeginning of DIAG diagnostics ----------\n");
X
X/*  for the character attributes    */
X
X    lprintf("\n\nPlayer attributes:\n\nHit points: %2d(%2d)",(long)c[HP],(long)c[HPMAX]);
X    lprintf("\ngold: %d  Experience: %d  Character level: %d  Level in caverns: %d",
X        (long)c[GOLD],(long)c[EXPERIENCE],(long)c[LEVEL],(long)level);
X    lprintf("\nTotal types of monsters: %d",(long)MAXMONST+8);
X
X    lprcat("\f\nHere's the dungeon:\n\n");
X
X    i=level;
X    for (j=0; j<MAXLEVEL+MAXVLEVEL; j++)
X        {
X        newcavelevel(j);
X        lprintf("\nMaze for level %s:\n",levelname[level]);
X        diagdrawscreen();
X        }
X    newcavelevel(i);
X
X    lprcat("\f\nNow for the monster data:\n\n");
X    lprcat("   Monster Name      LEV  AC   DAM  ATT  DEF    GOLD   HP     EXP   \n");
X    lprcat("--------------------------------------------------------------------------\n");
X    for (i=0; i<=MAXMONST+8; i++)
X        {
X        lprintf("%19s  %2d  %3d ",monster[i].name,(long)monster[i].level,(long)monster[i].armorclass);
X        lprintf(" %3d  %3d  %3d  ",(long)monster[i].damage,(long)monster[i].attack,(long)monster[i].defense);
X        lprintf("%6d  %3d   %6d\n",(long)monster[i].gold,(long)monster[i].hitpoints,(long)monster[i].experience);
X        }
X
X    lprcat("\n\nHere's a Table for the to hit percentages\n");
X    lprcat("\n     We will be assuming that players level = 2 * monster level");
X    lprcat("\n     and that the players dexterity and strength are 16.");
X    lprcat("\n    to hit: if (rnd(22) < (2[monst AC] + your level + dex + WC/8 -1)/2) then hit");
X    lprcat("\n    damage = rund(8) + WC/2 + STR - c[HARDGAME] - 4");
X    lprcat("\n    to hit:  if rnd(22) < to hit  then player hits\n");
X    lprcat("\n    Each entry is as follows:  to hit / damage / number hits to kill\n");
X    lprcat("\n          monster     WC = 4         WC = 20        WC = 40");
X    lprcat("\n---------------------------------------------------------------");
X    for (i=0; i<=MAXMONST+8; i++)
X        {
X        hit = 2*monster[i].armorclass+2*monster[i].level+16;
X        dam = 16 - c[HARDGAME];
X        lprintf("\n%20s   %2d/%2d/%2d       %2d/%2d/%2d       %2d/%2d/%2d",
X                    monster[i].name,
X                    (long)(hit/2),(long)max(0,dam+2),(long)(monster[i].hitpoints/(dam+2)+1),
X                    (long)((hit+2)/2),(long)max(0,dam+10),(long)(monster[i].hitpoints/(dam+10)+1),
X                    (long)((hit+5)/2),(long)max(0,dam+20),(long)(monster[i].hitpoints/(dam+20)+1));
X        }
X
X    lprcat("\n\nHere's the list of available potions:\n\n");
X    for (i=0; i<MAXPOTION; i++) lprintf("%20s\n",&potionname[i][1]);
X    lprcat("\n\nHere's the list of available scrolls:\n\n");
X    for (i=0; i<MAXSCROLL; i++) lprintf("%20s\n",&scrollname[i][1]);
X    lprcat("\n\nHere's the spell list:\n\n");
X    lprcat("spell          name           description\n");
X    lprcat("-------------------------------------------------------------------------------------------\n\n");
X    for (j=0; j<SPNUM; j++)
X        {
X        lprc(' ');  lprcat(spelcode[j]);
X        lprintf(" %21s  %s\n",spelname[j],speldescript[j]); 
X        }
X
X    lprcat("\n\nFor the c[] array:\n");
X    for (j=0; j<100; j+=10)
X        {
X        lprintf("\nc[%2d] = ",(long)j); for (i=0; i<9; i++) lprintf("%5d ",(long)c[i+j]);
X        }
X
X    lprcat("\n\nTest of random number generator ----------------");
X    lprcat("\n    for 25,000 calls divided into 16 slots\n\n");
X
X    for (i=0; i<16; i++)  rndcount[i]=0;
X    for (i=0; i<25000; i++) rndcount[rund(16)]++;
X    for (i=0; i<16; i++)  { lprintf("  %5d",(long)rndcount[i]); if (i==7) lprc('\n'); }
X
X    lprcat("\n\n");         lwclose();
X    lcreat((char*)0);       lprcat("Done Diagnosing . . .");
X    return(0);
X    }
X/*
X    subroutine to count the number of occurrences of an object
X */
Xdcount(l)
X    int l;
X    {
X    register int i,j,p;
X    int k;
X    k=0;
X    for (i=0; i<MAXX; i++)
X        for (j=0; j<MAXY; j++)
X            for (p=0; p<MAXLEVEL; p++)
X                if (cell[(long) p*MAXX*MAXY+i*MAXY+j].item == l) k++;
X    return(k);
X    }
X
X/*
X    subroutine to draw the whole screen as the player knows it
X */
Xdiagdrawscreen()
X    {
X    register int i,j,k;
X
X    for (i=0; i<MAXY; i++)
X
X/*  for the east west walls of this line    */
X        {
X        for (j=0; j<MAXX; j++)  if (k=mitem[j][i]) lprc(monstnamelist[k]); else
X                                lprc(objnamelist[item[j][i]]);
X        lprc('\n');
X        }
X    }
X#endif
X
X/*
X    to save the game in a file
X */
Xstatic long int zzz=0;
Xsavegame(fname)
X    char *fname;
X    {
X    extern char lastmonst[], course[];
X    register int i,k;
X    register struct sphere *sp;
X    struct stat statbuf;
X# ifdef MSDOS
X    struct  cel buf[MAXX];
X    RAMBLOCK    *rp;
X    DISKBLOCK   *dp;
X# endif
X
X    nosignal=1;  lflush();  savelevel();
X    ointerest();
X    if (lcreat(fname) < 0)
X        {
X        lcreat((char*)0); lprintf("\nCan't open file <%s> to save game\n",fname);
X        nosignal=0;  return(-1);
X        }
X
X    set_score_output();
X
X# ifdef MSDOS
X    lwrite((char*)beenhere,MAXLEVEL+MAXVLEVEL);
X
X    /* Some levels may be out on disk, some are in memory.
X     */
X    for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++)
X        if (beenhere[k]) {
X
X            /* Is the level in memory already ?
X             */
X            for (rp = ramblks; rp; rp = rp->next)
X                if (rp->level == k)
X                    break;
X            if (rp != NULL) {
X                lwrite((char *) &rp->gtime, sizeof (long));
X                warn(" %d", k);
X# ifdef ndef
X                warn("From memory\n", k);
X# endif
X                lwrite((char *) rp->cell, sizeof rp->cell);
X                continue;
X            }
X
X            /* Is it on disk ?
X             */
X            for (dp = diskblks; dp; dp = dp->next)
X                if (dp->level == k)
X                    break;
X
X            if (dp == NULL) {
X                levelinfo();
X                error("Level %d is neither in memory nor on disk\n", k);
X            }
X
X            /* Copy the contents of the SWAPFILE */
X            lwrite((char *) &dp->gtime, sizeof (long));
X# ifdef ndef
X            warn("From swap file...\n", k);
X# endif
X            warn(" %ds", k);
X            if (lseek(swapfd, dp->fpos, 0) < 0) {
X                warn("Can't seek to %ld\n", dp->fpos);
X                return -1;
X            }
X            for (i = 0; i < MAXY; i++) {
X# ifdef ndef
X                warn("Copying swap file...\n");
X# endif
X                if (vread(swapfd, (char *) buf, sizeof buf) !=
X                    sizeof buf) {
X                    warn("Swap file short!\n");
X                    return -1;
X                }
X                lwrite((char *) buf, sizeof buf);
X            }
X        }
X# else
X    lwrite((char*)beenhere,MAXLEVEL+MAXVLEVEL);
X    for (k=0; k<MAXLEVEL+MAXVLEVEL; k++)
X        if (beenhere[k])
X            lwrite((char*)&cell[(long) k*MAXX*MAXY],sizeof(struct cel)*MAXY*MAXX);
X# endif
X#ifndef VMS
X# ifndef MSDOS
X    times(&cputime);    /* get cpu time */
X    c[CPUTIME] += (cputime.tms_utime+cputime.tms_stime)/60;
X# endif MSDOS
X#endif VMS
X    lwrite((char*)&c[0],100*sizeof(long));
X    lprint((long)gtime);        lprc(level);
X    lprc(playerx);      lprc(playery);
X    lwrite((char*)iven,26); lwrite((char*)ivenarg,26*sizeof(short));
X    for (k=0; k<MAXSCROLL; k++)  lprc(scrollname[k][0]);
X    for (k=0; k<MAXPOTION; k++)  lprc(potionname[k][0]);
X    lwrite((char*)spelknow,SPNUM);       lprc(wizard);
X    lprc(rmst);     /*  random monster generation counter */
X    for (i=0; i<90; i++)    lprc(itm[i].qty);
X    lwrite((char*)course,25);           lprc(cheat);        lprc(VERSION);
X    for (i=0; i<MAXMONST; i++) lprc(monster[i].genocided); /* genocide info */
X    for (sp=spheres; sp; sp=sp->p)
X        lwrite((char*)sp,sizeof(struct sphere));    /* save spheres of annihilation */
X    time(&zzz);         lprint((long)(zzz-initialtime));
X    lwrite((char*)&zzz,sizeof(long));
X# ifndef MSDOS
X    if (fstat(lfd,&statbuf)< 0) lprint(0L);
X    else lprint((long)statbuf.st_ino); /* inode # */
X# endif
X
X    lwclose();  lastmonst[0] = 0;
X#ifndef VT100
X    setscroll();
X#endif VT100
X    lcreat((char*)0);  nosignal=0;
X    return(0);
X    }
X
Xrestoregame(fname)
X    char *fname;
X    {
X    register int i,k;
X    register struct sphere *sp,*sp2;
X    struct stat filetimes;
X# ifdef MSDOS
X    RAMBLOCK    *rp, *getramblk();
X# endif
X
X    cursors(); lprcat("\nRestoring . . .");  lflush();
X    if (lopen(fname) <= 0)
X        {
X        lcreat((char*)0); lprintf("\nCan't open file <%s>to restore game\n",fname);
X        nap(2000); c[GOLD]=c[BANKACCOUNT]=0;  died(-265); return;
X        }
X    lrfill((char*)beenhere,MAXLEVEL+MAXVLEVEL);
X
X# ifdef MSDOS
X    /* As levels get read in from the save file, store them away
X     * by calling putsavelevel.
X     */
X    for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++)
X        if (beenhere[k]) {
X            rp = getramblk(k);
X            lrfill((char *) &rp->gtime, sizeof (long));
X            lrfill((char *) rp->cell, sizeof rp->cell);
X            rp->level = k;
X        }
X# else
X    for (k=0; k<MAXLEVEL+MAXVLEVEL; k++)
X        if (beenhere[k])
X            lrfill((char*)&cell[(long) k*MAXX*MAXY],sizeof(struct cel)*MAXY*MAXX);
X# endif
X
X    lrfill((char*)&c[0],100*sizeof(long));  gtime = lrint();
X    level = c[CAVELEVEL] = lgetc();
X    playerx = lgetc();      playery = lgetc();
X    lrfill((char*)iven,26);     lrfill((char*)ivenarg,26*sizeof(short));
X    for (k=0; k<MAXSCROLL; k++)  scrollname[k][0] = lgetc();
X    for (k=0; k<MAXPOTION; k++)  potionname[k][0] = lgetc();
X    lrfill((char*)spelknow,SPNUM);      wizard = lgetc();
X    rmst = lgetc();         /*  random monster creation flag */
X
X    for (i=0; i<90; i++)    itm[i].qty = lgetc();
X    lrfill((char*)course,25);           cheat = lgetc();
X    if (VERSION != lgetc())     /*  version number  */
X        {
X        cheat=1;
X        lprcat("Sorry, But your save file is for an older version of larn\n");
X        nap(2000); c[GOLD]=c[BANKACCOUNT]=0;  died(-266); return;
X        }
X
X    for (i=0; i<MAXMONST; i++) monster[i].genocided=lgetc(); /* genocide info */
X    for (sp=0,i=0; i<c[SPHCAST]; i++)
X        {
X        sp2 = sp;
X        sp = (struct sphere *)malloc(sizeof(struct sphere));
X        if (sp==0) { write(2,"Can't malloc() for sphere space\n",32); break; }
X        lrfill((char*)sp,sizeof(struct sphere));    /* get spheres of annihilation */
X        sp->p=0;    /* null out pointer */
X        if (i==0) spheres=sp;   /* beginning of list */
X            else sp2->p = sp;
X        }
X
X    time(&zzz);
X    initialtime = zzz-lrint();
X    fstat(fd,&filetimes);   /*  get the creation and modification time of file  */
X    lrfill((char*)&zzz,sizeof(long));   zzz += 6;
X    if (filetimes.st_ctime > zzz) fsorry(); /*  file create time    */
X    else if (filetimes.st_mtime > zzz) fsorry(); /* file modify time    */
X    if (c[HP]<0) { died(284); return; } /* died a post mortem death */
X
X    oldx = oldy = 0;
X#ifndef VMS
X# ifndef MSDOS
X    i = lrint();  /* inode # */
X    if (i && (filetimes.st_ino!=i)) fsorry();
X# endif MSDOS
X#endif VMS
X    lrclose();
X    if (strcmp(fname,ckpfile) == 0)
X        {
X        if (lappend(fname) < 0) fcheat();  else { lprc(' '); lwclose(); }
X        lcreat((char*)0);
X        }
X    else if (unlink(fname) < 0) fcheat(); /* can't unlink save file */
X/*  for the greedy cheater checker  */
X    for (k=0; k<6; k++) if (c[k]>99) greedy();
X    if (c[HPMAX]>999 || c[SPELLMAX]>125) greedy();
X    if (c[LEVEL]==25 && c[EXPERIENCE]>skill[24]) /* if patch up lev 25 player */
X        {
X        long tmp;
X        tmp = c[EXPERIENCE]-skill[24]; /* amount to go up */
X        c[EXPERIENCE] = skill[24];
X        raiseexperience((long)tmp);
X        }
X    getlevel();  lasttime=gtime;
X    }
X
X/*
X    subroutine to not allow greedy cheaters
X */
Xstatic greedy()
X    {
X#if WIZID
X    if (wizard) return;
X#endif
X
X    lprcat("\n\nI am so sorry, but your character is a little TOO good!  Since this\n");
X    lprcat("cannot normally happen from an honest game, I must assume that you cheated.\n");
X    lprcat("In that you are GREEDY as well as a CHEATER, I cannot allow this game\n");
X    lprcat("to continue.\n"); nap(5000);  c[GOLD]=c[BANKACCOUNT]=0;  died(-267); return;
X    }
X
X/*
X    subroutine to not allow altered save files and terminate the attempted
X    restart
X */
Xstatic fsorry()
X    {
X    lprcat("\nSorry, but your savefile has been altered.\n");
X    lprcat("However, seeing as I am a good sport, I will let you play.\n");
X    lprcat("Be advised though, you won't be placed on the normal scoreboard.");
X    cheat = 1;  nap(4000);
X    }
X
X/*
X    subroutine to not allow game if save file can't be deleted
X */
Xstatic fcheat()
X    {
X#if WIZID
X    if (wizard) return;
X#endif
X
X    lprcat("\nSorry, but your savefile can't be deleted.  This can only mean\n");
X    lprcat("that you tried to CHEAT by protecting the directory the savefile\n");
X    lprcat("is in.  Since this is unfair to the rest of the larn community, I\n");
X    lprcat("cannot let you play this game.\n");
X    nap(5000);  c[GOLD]=c[BANKACCOUNT]=0;  died(-268); return;
X    }
END_OF_FILE
if test 14017 -ne `wc -c <'diag.c'`; then
    echo shar: \"'diag.c'\" unpacked with wrong size!
fi
# end of 'diag.c'
fi
if test -f 'larnhlp.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'larnhlp.txt'\"
else
echo shar: Extracting \"'larnhlp.txt'\" \(8427 characters\)
sed "s/^X//" >'larnhlp.txt' <<'END_OF_FILE'
X7    Welcome to the game of Larn.  At this moment, you face a great problem.
XYour daughter has contracted a strange disease, and none of your home remedies
Xseem to have any effect.  You sense that she is in mortal danger, and you must
Xtry to save her.  Time ago you heard of a land of great danger and opportunity.
XPerhaps here is the solution you need.
X
X    It has been said that there once was a great magician who called himself
XPolinneaus.  Many years ago, after having many miraculous successes, Polinneaus
Xretired to the caverns of Larn, where he devoted most of his time to the
Xcreation of magic.   Rumors have it that one day Polinneaus set out to dispel
Xan attacking army in a forest some distance to the north.  It is believed that
Xhere he met his demise.
X
X    The caverns of Larn, it is thought, must be magnificent in design,
Xand contain much magic and treasure.  One option you have is to undertake a
Xjourney into these caverns.
X
X
X    Good Luck!  You're going to need it!
X
X
X
X
X                Help File for The Caverns of Larn, Prompt Mode
X
Xb  move southwest          B  run southwest            S  save the game
Xh  move left               H  run left                 .  stay here
Xj  move down               J  run down                 ^  identify a trap
Xk  move up                 K  run up                   T  take off armor
Xl  move right              L  run right
Xn  move southeast          N  run southeast
Xu  move northeast          U  run northeast
Xy  move northwest          Y  run northwest            ^L redraw the screen
Xc  cast a spell            Z  teleport yourself
Xd  drop an item            e  eat something
Xg  get present pack weight P  give tax status
Xi  inventory your pockets  I  list all items found     ?  this help screen
Xq  quaff a potion          Q  quit the game
Xr  read a scroll           v  print program version
Xw  wield a weapon          W  wear armor               ^L redraw the screen
X
X
X
X
X
X
X                Help File for The Caverns of Larn, Command Mode
X
Xb  move southwest          B  run southwest            A  desecrate an altar
Xc  cast a spell            C  close a door             Z  teleport yourself
Xd  drop an item            D  drink at a fountain      <  go up stairs or
Xe  eat something           E  enter a store, dungeon      volcanic shaft
Xg  get present pack weight                             >  go down stairs or
Xh  move left               H  run left                    volcanic shaft
Xi  inventory your pockets  I  list all items found     ?  this help screen
Xj  move down               J  run down                 ^  identify a trap
Xk  move up                 K  run up                   ,  pick up item
Xl  move right              L  run right                :  look at object you
Xn  move southeast          N  run southeast               are standing on
X                           O  open a door or chest     .  stay here
Xp  pray at an altar        P  give tax status          m  move without picking
Xq  quaff a potion          Q  quit the game               up an object
Xr  read a scroll           R  remove gems from throne  @  toggle auto-pickup
Xs  sit on a throne         S  save the game            /  identify objects in
Xt  tidy up at a fountain   T  take off armor              the game
Xu  move northeast          U  run northeast
Xv  print program version
Xw  wield a weapon          W  wear armor
Xy  move northwest          Y  run northwest            ^L redraw the screen
X                Special Notes
X
XWhen dropping gold, if you type '*' as your amount, all your gold gets dropped.
XIn general, typing in '*' means all of what your interested in.  This is true
Xwhen visiting the bank, or when contributing at altars.
X
XLarn needs the ANSI.SYS (or preferably, the NANSI.SYS) device driver installed
Xin your CONFIG.SYS file.  The supplied "termcap" file describes the escape
Xsequences to change video modes (see ch 13 of the DOS 2.0 manual).  See the
X"TERMCAP" section in LARN.DOC for further details.
X
XWhen in the store, trading post, school, or home, an <escape> will get you out.
X
XWhen casting a spell, if you need a list of spells you can cast, type 'I' as
Xthe first letter of your spell.  The available list of spells will be shown,
Xafter which you may enter the spell code.  This only works on the 1st letter
Xof the spell you are casting.
X
XWhen an inventory list is on the screen from a drop, quaff, read, or similar
Xcommand, you can type the letter of the object that you wish to act apon,
Xwithout having to type a space to get back to the prompt.
X
XThis version of Larn is by Kevin Routley.
X                        Larn Command Line Options
X
Xlarn ++                 restore checkpointed game
Xlarn -s                 list the scoreboard
Xlarn -i                 list scores with inventories
Xlarn -n                 suppress welcome message when beginning a game
Xlarn -h                 print out all the command line options
Xlarn -?                 print out all the command line options
Xlarn -<number>          specify difficulty of the game
Xlarn -o<optsfile>       specify the option file to be used
Xlarn -c                 create new scoreboards -- prompts for a password
Xlarn -l                 print out the larn log file
Xlarn -p                 play in prompt mode
X
X
X
X
X
X
X
X
X
X
X            Background Information for Larn
X
X    Welcome to the game of Larn.  At this moment, you face a great problem.
XYour daughter has contracted a strange disease, and none of your home remedies
Xseem to have any effect.  You sense that she is in mortal danger, and you must
Xtry to save her.  Time ago you heard of a land of great danger and opportunity.
XPerhaps here is the solution you need.
X
X    It has been said that there once was a great magician who called himself
XPolinneaus.  Many years ago, after having many miraculous successes, Polinneaus
Xretired to the caverns of Larn, where he devoted most of his time to the
Xcreation of magic.   Rumors have it that one day Polinneaus set out to dispel
Xan attacking army in a forest some distance to the north.  It is believed that
Xhere he met his demise.
X
X    The caverns of Larn, it is thought, must be magnificent in design,
Xand contain much magic and treasure.  One option you have is to undertake a
Xjourney into these caverns.
X
X    Good Luck!  You're going to need it!
X
X
X
X            How to use the larn.opt option file
X
XThe file "larn.opt", if used, should be in a directory along your PATH.
XA sequence of words terminated by whitespace is used to specify options.
X
X    Word                      Meaning
X    cursor: lowscan highscan  change the shape of the cursor
X    DECRainbow                tell LARN you have that computer
X    enable-checkpointing      turn on periodic checkpointing
X    graphics: wallc floorc    select graphics maze characters
X    keypad                    enable the numeric keypad for moving
X    larndir:  directory       the directory to use for larn files
X    monster:  "monst name"    choose a name for a monster
X    name:     "your name"     choose your playing name
X    no-beep                   disable beeping of the terminal
X    no-introduction           do not display intro message
X    savefile: save-file-name  define what the savegame filename will be
X    swapfile: swap-file-name  define the name of the swapfile
X
XYour name and monster names must be enclosed in double quotation marks and may
Xbe up to 34 characters long.  Longer names are truncated.  Anything enclosed in
Xquotation marks is considered one word, and must be separated from other words
Xby whitespace.
X           Explanation of the Larn scoreboard facility
X
X    Larn supports TWO scoreboards, one for winners, and one for deceased
Xcharacters.  Each player (by userid or playerid, see UIDSCORE in Makefile)
Xis allowed one slot on each scoreboard, if the score is in the top ten for
Xthat scoreboard.  This design helps insure that frequent players of Larn
Xdo not hog the scoreboard, and gives more players a chance for glory.  Level
Xof difficulty is also noted on the scoreboards, and this takes precedence
Xover score for determining what entry is on the scoreboard.  For example:
Xif "Yar, the Bug Slayer" has a score of 128003 on the scoreboard at diff 0,
Xthen a game at diff 1 and a score of 4112 would replace the previous
Xentry on the scoreboard.  Note that when a player dies, the inventory is
Xstored in the scoreboard so that everyone can see what items the player had
Xat the time of death.
X
X
X
X
X
X
X
X
X
X.
END_OF_FILE
if test 8427 -ne `wc -c <'larnhlp.txt'`; then
    echo shar: \"'larnhlp.txt'\" unpacked with wrong size!
fi
# end of 'larnhlp.txt'
fi
if test -f 'monsters.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'monsters.h'\"
else
echo shar: Extracting \"'monsters.h'\" \(1741 characters\)
sed "s/^X//" >'monsters.h' <<'END_OF_FILE'
X/*
X  Monster related definitions
X*/
X
X#define MAXMONST 56     /* maximum # monsters in the dungeon   */
X
X/*  this is the structure definition of the monster data
X*/
Xstruct monst
X    {
X    char    *name;
X    char    level;
X    short   armorclass;
X    char    damage;
X    char    attack;
X    char    defense;
X    char    genocided;
X    char    intelligence; /* monsters intelligence -- used to choose movement */
X    short   gold;
X    short   hitpoints;
X    unsigned long experience;
X    };
X
Xextern struct monst monster[];
X
X/*  defines for the monsters as objects     
X*/
X#define BAT 1
X#define GNOME 2
X#define HOBGOBLIN 3
X#define JACKAL 4
X#define KOBOLD 5
X#define ORC 6
X#define SNAKE 7
X#define CENTIPEDE 8
X#define JACULI 9
X#define TROGLODYTE 10
X#define ANT 11
X#define EYE 12 
X#define LEPRECHAUN 13
X#define NYMPH 14
X#define QUASIT 15 
X#define RUSTMONSTER 16 
X#define ZOMBIE 17 
X#define ASSASSINBUG 18 
X#define BUGBEAR 19 
X#define HELLHOUND 20 
X#define ICELIZARD 21 
X#define CENTAUR 22 
X#define TROLL 23 
X#define YETI 24 
X#define WHITEDRAGON 25
X#define ELF 26
X#define CUBE 27 
X#define METAMORPH 28 
X#define VORTEX 29 
X#define ZILLER 30 
X#define VIOLETFUNGI 31 
X#define WRAITH 32 
X#define FORVALAKA 33 
X#define LAMANOBE 34 
X#define OSEQUIP 35 
X#define ROTHE 36
X#define XORN 37
X#define VAMPIRE 38
X#define INVISIBLESTALKER 39
X#define POLTERGEIST 40
X#define DISENCHANTRESS 41
X#define SHAMBLINGMOUND 42
X#define YELLOWMOLD 43
X#define UMBERHULK 44
X#define GNOMEKING 45
X#define MIMIC 46
X#define WATERLORD 47
X#define BRONZEDRAGON 48
X#define GREENDRAGON 49
X#define PURPLEWORM 50
X#define XVART 51
X#define SPIRITNAGA 52
X#define SILVERDRAGON 53
X#define PLATINUMDRAGON 54
X#define GREENURCHIN 55
X#define REDDRAGON 56
X#define DEMONLORD 57
X#define DEMONPRINCE 64
END_OF_FILE
if test 1741 -ne `wc -c <'monsters.h'`; then
    echo shar: \"'monsters.h'\" unpacked with wrong size!
fi
# end of 'monsters.h'
fi
if test -f 'tok.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tok.c'\"
else
echo shar: Extracting \"'tok.c'\" \(13322 characters\)
sed "s/^X//" >'tok.c' <<'END_OF_FILE'
X/* tok.c */
X/*
X   yylex()
X   flushall()
X   sethard()
X   readopts()
X   actual_readopts()
X*/
X#ifdef VMS
X#include <types.h>
X#include <file.h>
X#include <iodef.h>
X#else VMS
X#include <sys/types.h>
X#ifdef SYSV
X#include <fcntl.h>
X# ifndef MSDOS
X#   include <termio.h>
X# endif
X#else SYSV
X# ifndef MSDOS
X#   include <sys/ioctl.h>
X# endif
X#endif SYSV
X#endif VMS
X
X#include <ctype.h>
X#include "header.h"
X#include "larndefs.h"
X#include "monsters.h"
X#include "objects.h"
X#include "player.h"
X
X#ifdef __STDC__
Xstatic void actual_readopts( char*, char* );
X#else
Xstatic void actual_readopts();
X#endif
X
X# define CHKPTINT   400
X
Xstatic char lastok=0;
Xint yrepcount=0;
Xchar move_no_pickup = FALSE ;
X
X#ifdef TIMECHECK
Xint dayplay=0;
X#endif TIMECHECK
X
X#ifndef FLUSHNO
X#define FLUSHNO 5
X#endif FLUSHNO
Xstatic int flushno=FLUSHNO; /* input queue flushing threshold */
X#define MAXUM 52    /* maximum number of user re-named monsters */
X#define MAXMNAME 40 /* max length of a monster re-name */
Xstatic char usermonster[MAXUM][MAXMNAME]; /* the user named monster name goes here */
Xstatic char usermpoint=0;           /* the user monster pointer */
X#ifdef MSDOS
X extern int rawio;
X#endif
X
X/*
X    lexical analyzer for larn
X */
Xyylex()
X    {
X    char cc;
X    int ic;
X    char firsttime = TRUE;
X
X    if (hit2flag)
X        {
X        hit2flag=0;
X        yrepcount=0;
X        return(' ');
X        }
X    if (yrepcount>0)
X        {
X        --yrepcount;
X        return(lastok);
X        }
X    else
X        yrepcount=0;
X    if (yrepcount==0) 
X        { 
X        bottomdo(); 
X        showplayer();               /* show where the player is */
X        move_no_pickup = FALSE;     /* clear 'm' flag */
X        }
X
X    lflush();
X    while (1)
X        {
X        c[BYTESIN]++;
X        if (ckpflag)
X          if ((c[BYTESIN] % CHKPTINT) == 0) /* check for periodic checkpointing */
X            {
X#ifndef DOCHECKPOINTS
X#ifdef MSDOS
X            cursors();
X            lprcat("\nCheckpointing . . .");
X            savegame(ckpfile);
X            lprcat("\nDone\n");
X            showplayer();
X            lflush();
X            lflushall(); /* Kill any stored key strokes */
X#else
X#ifdef VMS
X            savegame(ckpfile);
X#else
X            wait(0);    /* wait for other forks to finish */
X            if (fork() == 0) { savegame(ckpfile); exit(); }
X#endif
X#endif
X#else
X#ifdef VMS
X            savegame(ckpfile);
X#else
X            wait(0);    /* wait for other forks to finish */
X            if (fork() == 0) { savegame(ckpfile); exit(); }
X#endif
X#endif
X
X#ifdef TIMECHECK
X            if (dayplay==0)
X              if (playable())
X                {
X                cursor(1,19);
X                lprcat("\nSorry, but it is now time for work.  Your game has been saved.\n"); beep();
X                lflush();
X                savegame(savefilename);
X                wizard=nomove=1;
X                sleep(4);
X                died(-257);
X                }
X#endif TIMECHECK
X
X            }
X
X# ifndef MSDOS
X# ifdef VMS
X        /* If keyboard input buffer is too big then flush some? RDE */
X        /* Check this! but for now just ignore it... */
X# else
X#  ifndef SYSV
X        do /* if keyboard input buffer is too big, flush some of it */
X            {
X            ioctl(0,FIONREAD,&ic);
X            if (ic>flushno)   read(0,&cc,1);
X            }
X        while (ic>flushno);
X#  endif SYSV
X# endif VMS
X# endif MSDOS
X
X# ifdef MSDOS
X        cc = ttgetch();
X# else MSDOS
X# ifdef VMS
X        cc = ttgetch();
X# else
X        if (read(0,&cc,1) != 1)
X            return(lastok = -1);
X# endif VMS
X# endif MSDOS
X        if (cc == '!')      /* ! shell escape */
X            {
X            resetscroll();  /* scrolling region, home, clear, no attributes */
X            clear();
X# ifdef MSDOS
X            doshell();
X# else MSDOS
X# ifdef VMS
X            lflush();
X            sncbr();
X            oneliner("");
X            scbr();
X# else VMS
X            lflush();
X            sncbr();
X            if ((ic=fork())==0) /* child */
X                {
X#ifdef SYSV
X                char *s, *getenv();
X                if ((s=getenv("SHELL")) == (char *) 0)
X                    s = "/bin/sh";
X                execl(s,"larn-shell", (char *)0);
X                exit();
X#else
X                execl("/bin/csh",0);
X                exit();
X                wait(0);
X#endif
X                }
X            if (ic<0) /* error */
X                {
X                write(2,"Can't fork off a shell!\n",25);
X                sleep(2);
X                }
X#ifdef SYSV
X            else
X                wait( (int *)0 );
X#endif SYSV
X# endif VMS
X# endif MSDOS
X            setscroll();
X            return(lastok = 'L'-64);    /* redisplay screen */
X            }
X
X        /* get repeat count, showing to player
X        */
X        if ((cc <= '9') && (cc >= '0'))
X            {
X            yrepcount = yrepcount*10 + cc - '0';
X
X            /* show count to player for feedback
X            */
X            if ( yrepcount >= 10 )
X                {
X                cursors();
X                if (firsttime)
X                    lprcat("\n");
X                lprintf("count: %d", (long)yrepcount );
X                firsttime=FALSE;
X                lflush();  /* show count */
X                }
X            }
X        else
X            {
X            /* check for multi-character commands in command mode, and handle.
X            */
X            if ( cc == 'm' && !prompt_mode )
X                {
X                move_no_pickup = TRUE ;
X                cc = ttgetch();
X                }
X            if ( yrepcount > 0 )
X                --yrepcount;
X            return(lastok = cc);
X            }
X        }
X    }
X
X/*
X *  flushall()  Function to flush all type-ahead in the input buffer
X */
Xlflushall()
X    {
X# ifdef MSDOS
X    while (kbhit())
X        getch();
X# else MSDOS
X# ifdef VMS
X    /* Flush all type-ahead -- RDE */
X    extern int  iochan;     /* defined in IO.C  */
X    int     c;
X
X    SYS$QIOW(0,iochan,IO$_READLBLK|IO$M_TIMED|IO$M_PURGE,0,0,0,&c,1,0,0,0,0);
X
X# else VMS
X#ifdef SYSV
X    ioctl(0,TCFLSH,0);
X#else
X    char cc;
X    int ic;
X    for (;;) {      /* if keyboard input buffer is too big, flush some of it */
X        ioctl(0,FIONREAD,&ic);
X        if (ic<=0)
X            return;
X        while (ic>0) {
X            read(0,&cc,1);
X            --ic;
X        } /* gobble up the byte */
X    }
X# endif SYSV
X# endif VMS
X# endif MSDOS
X}
X
X/*
X    function to set the desired hardness
X    enter with hard= -1 for default hardness, else any desired hardness
X */
Xsethard(hard)
Xint hard;
X{
X    register int    j,k;
X    long        i;
X    struct monst    *mp;
X
X    j=c[HARDGAME]; hashewon();
X    if (restorflag==0)  /* don't set c[HARDGAME] if restoring game */
X        {
X        if (hard >= 0) c[HARDGAME]= hard;
X        }
X    else c[HARDGAME]=j; /* set c[HARDGAME] to proper value if restoring game */
X
X    if (k=c[HARDGAME])
X      for (j=0; j<=MAXMONST+8; j++) {
X        mp = &monster[j];
X        i = ((6+k) * mp->hitpoints + 1)/6;
X        mp->hitpoints = (i<0) ? 32767 : i;
X        i = ((6+k) * mp->damage + 1) / 5;
X        mp->damage = (i>127) ? 127 : i;
X        i = (10 * mp->gold)/(10+k);
X        mp->gold = (i>32767) ? 32767 : i;
X        i = mp->armorclass - k;
X        mp->armorclass = (i< -127) ? -127 : i;
X        i = (7*mp->experience)/(7+k) + 1;
X        mp->experience = (i<=0) ? 1 : i;
X    }
X}
X
X
X/*
X    function to read and process the larn options file
X*/
Xreadopts()
X    {
X    register int j;
X    char original_objects = FALSE ;
X    char namenotchanged = TRUE;     /* set to 0 if a name is specified */
X
X# ifdef MSDOS
X    if (plopen(optsfile) < 0)
X# else
X    if (lopen(optsfile) < 0)
X# endif
X        {
X        lprintf("Can't open options file \"%s\"\n", optsfile);
X        lflush();
X        sleep(1);
X        }
X    else
X        actual_readopts(&namenotchanged, &original_objects);
X
X    if (namenotchanged)
X        strcpy(logname,loginname);
X
X    /* original objects require object highlighting to be ON (in order
X       to distinguish between objects and monsters).  set up object list
X       properly.
X    */
X    if (original_objects)
X        {
X        boldobjects = TRUE ;
X        strncpy( objnamelist, original_objnamelist, MAXOBJECT );
X        }
X    else
X        strncpy( objnamelist, hacklike_objnamelist, MAXOBJECT );
X    objnamelist[MAXOBJECT] = '\0' ;
X
X    /* now set all the invisible objects and monsters to have the
X       same appearance as the floor (as defined by the user)
X    */
X    objnamelist[OWALL] = wallc;
X
X    objnamelist[0]        =
X    objnamelist[OIVTELETRAP]  =
X    objnamelist[OTRAPARROWIV] =
X    objnamelist[OIVDARTRAP]   =
X    objnamelist[OIVTRAPDOOR]  = floorc;
X    monstnamelist[0] =
X    monstnamelist[INVISIBLESTALKER] = floorc;
X    for (j=DEMONLORD; j<=DEMONPRINCE; j++)
X        monstnamelist[j] = floorc;
X    }
X
Xstatic void actual_readopts( namenotchanged, original_objects )
Xchar *namenotchanged;
Xchar *original_objects;
X    {
X    register char *i;
X    register int j,k;
X
X    i = " ";
X    while (*i)
X        {
X        /* check for EOF
X        */
X        if ((i=(char *)lgetw()) == 0)
X            return;
X#if 0
X        while (*i && ((*i==' ') || (*i=='\t'))) i++; /* eat leading whitespace */
X#endif
X        /* leading # a comment, eat the rest of the line.  Handle multiple
X           comment lines in a row.
X        */
X        while (*i == '#')
X            {
X            char cc;
X            do
X                cc = (char)lgetc();
X            while ( ( cc != '\n' ) && ( cc != NULL));
X            if ((i = (char *)lgetw()) == 0)
X                return;
X            }
X
X        if (strcmp(i,"bold-objects") == 0)
X            boldon=1;
X        else if (strcmp(i,"enable-checkpointing") == 0)
X            ckpflag=1;
X        else if (strcmp(i,"inverse-objects") == 0)
X            boldon=0;
X        else if (strcmp(i,"prompt-on-objects") == 0 )
X            prompt_mode = TRUE ;
X        else if (strcmp(i,"auto-pickup") == 0 )
X            auto_pickup = TRUE ;
X        else if (strcmp(i,"highlight-objects") == 0 )
X            boldobjects = TRUE ;
X        else if (strcmp(i,"original-objects") == 0 )
X            *original_objects = TRUE ;
X        else if (strcmp(i,"female") == 0)
X            sex=0; /* male or female */
X# ifdef MSDOS
X        else if (strcmp(i, "graphics:") == 0)
X            {
X            wallc = atoi(lgetw());
X            floorc = atoi(lgetw());
X            }
X        else if (strcmp(i, "larndir:") == 0)
X            {
X            if ((i=lgetw())==0)
X                break;
X            strncpy(larndir, i, DIRLEN);
X            larndir[DIRLEN - 1] = 0;
X            }
X        else if (strcmp(i, "rawio") == 0)
X            rawio = 1;
X        else if (strcmp(i, "swapfile:") == 0)
X            {
X            if ((i = (char *)lgetw()) == 0)
X                break;
X            strncpy(swapfile, i, PATHLEN);
X            swapfile[PATHLEN - 1] = 0;
X            }
X        else if (strcmp(i, "ramlevels:") == 0)
X            ramlevels = atoi(lgetw());
X        else if (strcmp(i, "cursor:") == 0)
X            {
X            cursorset = 1;
X            cursorstart = (unsigned char) atoi(lgetw());
X            cursorend = (unsigned char) atoi(lgetw());
X            }
X        else if (strcmp(i, "keypad") == 0)
X            keypad = 1;
X        else if (strcmp(i, "DECRainbow") == 0)
X            DECRainbow = 1;
X# endif
X        else if (strcmp(i,"monster:")== 0)   /* name favorite monster */
X            {
X            if ((i=(char *)lgetw())==0)
X                break;
X            if (strlen(i)>=MAXMNAME)
X                i[MAXMNAME-1]=0;
X            strcpy(usermonster[usermpoint],i);
X            if (usermpoint >= MAXUM)
X                break; /* defined all of em */
X            if (isalpha(j=usermonster[usermpoint][0]))
X                {
X                for (k=1; k<MAXMONST+8; k++) /* find monster */
X                  if (monstnamelist[k] == j)
X                    {
X                    monster[k].name = &usermonster[usermpoint++][0];
X                    break;
X                    }
X                }
X            }
X        else if (strcmp(i,"male") == 0)
X            sex=1;
X        else if (strcmp(i,"name:") == 0) /* defining players name */
X            {
X            if ((i=lgetw())==0)
X                break;
X            if (strlen(i)>=LOGNAMESIZE)
X                i[LOGNAMESIZE-1]=0;
X            strcpy(logname,i);
X            *namenotchanged = FALSE;
X# ifdef MSDOS
X            strcpy(loginname,i);
X# endif
X            }
X        else if (strcmp(i,"no-introduction") == 0)
X            nowelcome=1;
X        else if (strcmp(i,"no-beep") == 0)
X            nobeep=1;
X# ifndef MSDOS
X        else if (strcmp(i,"process-name:")== 0)
X            {
X            if ((i=lgetw())==0)
X                break;
X            if (strlen(i)>=PSNAMESIZE)
X                i[PSNAMESIZE-1]=0;
X            strcpy(psname,i);
X            }
X        else if (strcmp(i,"play-day-play") == 0)
X# ifdef TIMECHECK
X            dayplay=1;
X# else
X        ;
X# endif
X# endif
X        else if (strcmp(i,"savefile:") == 0) /* defining savefilename */
X            {
X            if ((i=lgetw())==0)
X                break;
X            if (strlen(i)>=SAVEFILENAMESIZE) /* avoid overflow */
X                i[SAVEFILENAMESIZE-1]=0;
X            strcpy(savefilename,i);
X            }
X        else
X            {
X            lprintf("Unknown option \"%s\"\n", i);
X            lflush();
X            sleep(1);
X            }
X        }
X    }
END_OF_FILE
if test 13322 -ne `wc -c <'tok.c'`; then
    echo shar: \"'tok.c'\" unpacked with wrong size!
fi
# end of 'tok.c'
fi
echo shar: End of archive 9 \(of 12\).
cp /dev/null ark9isdone
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