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

larn 12.0 part 3/6

22 views
Skip to first unread message

Noah Morgan

unread,
Aug 8, 1986, 1:09:10 PM8/8/86
to
*** REPLACE THIS LINE WITH YOUR MESSAGE ***
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# header.h
# io.c
# main.c
# .larnopts
# This archive created: Wed Aug 6 14:59:17 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'header.h'" '(12291 characters)'
if test -f 'header.h'
then
echo shar: will not over-write existing file "'header.h'"
else
cat << \SHAR_EOF > 'header.h'
/* header.h Larn is copyrighted 1986 by Noah Morgan. */

#define SCORENAME ".lscore12.0"
#define LOGFNAME ".llog12.0"
#define HELPNAME ".larn.help"
#define LEVELSNAME ".larnmaze"
#define FORTSNAME ".lfortune"
#define PLAYERIDS ".playerids"
#define HOLIFILE ".holidays"

#define MAXLEVEL 11
/* max # levels in the dungeon */
#define MAXVLEVEL 3
/* max # of levels in the temple of the luran */
#define MAXX 67
#define MAXY 17

#define SCORESIZE 10
/* this is the number of people on a scoreboard max */
#define MAXPLEVEL 100
/* maximum player level allowed */
#define MAXMONST 56
/* maximum # monsters in the dungeon */
#define SPNUM 38
/* maximum number of spells in existance */
#define MAXSCROLL 28
/* maximum number of scrolls that are possible */
#define MAXPOTION 35
/* maximum number of potions that are possible */
#define TIMELIMIT 30000
/* the maximum number of moves before the game is called */
#define TAXRATE 1/20
/* the tax rate for the LRS */
#define MAXOBJ 93
/* the maximum number of objects n < MAXOBJ */

/* this is the structure definition of the monster data */
struct monst
{
char *name;
char level;
short armorclass;
char damage;
char attack;
char defense;
char genocided;
char intelligence; /* monsters intelligence -- used to choose movement */
short gold;
short hitpoints;
unsigned long experience;
};

/* this is the structure definition for the items in the dnd store */
struct _itm
{
short price;
char **mem;
char obj;
char arg;
char qty;
};

/* this is the structure that holds the entire dungeon specifications */
struct cel
{
short hitp; /* monster's hit points */
char mitem; /* the monster ID */
char item; /* the object's ID */
short iarg; /* the object's argument */
char know; /* have we been here before*/
};

/* this is the structure for maintaining & moving the spheres of annihilation */
struct sphere
{
struct sphere *p; /* pointer to next structure */
char x,y,lev; /* location of the sphere */
char dir; /* direction sphere is going in */
char lifetime; /* duration of the sphere */
};

/* defines for the character attribute array c[] */
#define STRENGTH 0 /* characters physical strength not due to objects */
#define INTELLIGENCE 1
#define WISDOM 2
#define CONSTITUTION 3
#define DEXTERITY 4
#define CHARISMA 5
#define HPMAX 6
#define HP 7
#define GOLD 8
#define EXPERIENCE 9
#define LEVEL 10
#define REGEN 11
#define WCLASS 12
#define AC 13
#define BANKACCOUNT 14
#define SPELLMAX 15
#define SPELLS 16
#define ENERGY 17
#define ECOUNTER 18
#define MOREDEFENSES 19
#define WEAR 20
#define PROTECTIONTIME 21
#define WIELD 22
#define AMULET 23
#define REGENCOUNTER 24
#define MOREDAM 25
#define DEXCOUNT 26
#define STRCOUNT 27
#define BLINDCOUNT 28
#define CAVELEVEL 29
#define CONFUSE 30
#define ALTPRO 31
#define HERO 32
#define CHARMCOUNT 33
#define INVISIBILITY 34
#define CANCELLATION 35
#define HASTESELF 36
#define EYEOFLARN 37
#define AGGRAVATE 38
#define GLOBE 39
#define TELEFLAG 40
#define SLAYING 41
#define NEGATESPIRIT 42
#define SCAREMONST 43
#define AWARENESS 44
#define HOLDMONST 45
#define TIMESTOP 46
#define HASTEMONST 47
#define CUBEofUNDEAD 48
#define GIANTSTR 49
#define FIRERESISTANCE 50
#define BESSMANN 51
#define NOTHEFT 52
#define HARDGAME 53
#define CPUTIME 54
#define BYTESIN 55
#define BYTESOUT 56
#define MOVESMADE 57
#define MONSTKILLED 58
#define SPELLSCAST 59
#define LANCEDEATH 60
#define SPIRITPRO 61
#define UNDEADPRO 62
#define SHIELD 63
#define STEALTH 64
#define ITCHING 65
#define LAUGHING 66
#define DRAINSTRENGTH 67
#define CLUMSINESS 68
#define INFEEBLEMENT 69
#define HALFDAM 70
#define SEEINVISIBLE 71
#define FILLROOM 72
#define RANDOMWALK 73
#define SPHCAST 74 /* nz if an active sphere of annihilation */
#define WTW 75 /* walk through walls */
#define STREXTRA 76 /* character strength due to objects or enchantments */
#define TMP 77 /* misc scratch space */
#define LIFEPROT 78 /* life protection counter */

/* defines for the objects in the game */

#define OALTAR 1
#define OTHRONE 2
#define OORB 3
#define OPIT 4
#define OSTAIRSUP 5
#define OELEVATORUP 6
#define OFOUNTAIN 7
#define OSTATUE 8
#define OTELEPORTER 9
#define OSCHOOL 10
#define OMIRROR 11
#define ODNDSTORE 12
#define OSTAIRSDOWN 13
#define OELEVATORDOWN 14
#define OBANK2 15
#define OBANK 16
#define ODEADFOUNTAIN 17
#define OMAXGOLD 70
#define OGOLDPILE 18
#define OOPENDOOR 19
#define OCLOSEDDOOR 20
#define OWALL 21
#define OTRAPARROW 66
#define OTRAPARROWIV 67

#define OLARNEYE 22

#define OPLATE 23
#define OCHAIN 24
#define OLEATHER 25
#define ORING 60
#define OSTUDLEATHER 61
#define OSPLINT 62
#define OPLATEARMOR 63
#define OSSPLATE 64
#define OSHIELD 68
#define OELVENCHAIN 92

#define OSWORDofSLASHING 26
#define OHAMMER 27
#define OSWORD 28
#define O2SWORD 29
#define OSPEAR 30
#define ODAGGER 31
#define OBATTLEAXE 57
#define OLONGSWORD 58
#define OFLAIL 59
#define OLANCE 65
#define OVORPAL 90
#define OSLAYER 91

#define ORINGOFEXTRA 32
#define OREGENRING 33
#define OPROTRING 34
#define OENERGYRING 35
#define ODEXRING 36
#define OSTRRING 37
#define OCLEVERRING 38
#define ODAMRING 39

#define OBELT 40

#define OSCROLL 41
#define OPOTION 42
#define OBOOK 43
#define OCHEST 44
#define OAMULET 45

#define OORBOFDRAGON 46
#define OSPIRITSCARAB 47
#define OCUBEofUNDEAD 48
#define ONOTHEFT 49

#define ODIAMOND 50
#define ORUBY 51
#define OEMERALD 52
#define OSAPPHIRE 53

#define OENTRANCE 54
#define OVOLDOWN 55
#define OVOLUP 56
#define OHOME 69

#define OKGOLD 71
#define ODGOLD 72
#define OIVDARTRAP 73
#define ODARTRAP 74
#define OTRAPDOOR 75
#define OIVTRAPDOOR 76
#define OTRADEPOST 77
#define OIVTELETRAP 78
#define ODEADTHRONE 79
#define OANNIHILATION 80 /* sphere of annihilation */
#define OTHRONE2 81
#define OLRS 82 /* Larn Revenue Service */
#define OCOOKIE 83
#define OURN 84
#define OBRASSLAMP 85
#define OHANDofFEAR 86 /* hand of fear */
#define OSPHTAILSMAN 87 /* tailsman of the sphere */
#define OWWAND 88 /* wand of wonder */
#define OPSTAFF 89 /* staff of power */
/* used up to 92 */

/* defines for the monsters as objects */

#define BAT 1
#define GNOME 2
#define HOBGOBLIN 3
#define JACKAL 4
#define KOBOLD 5
#define ORC 6
#define SNAKE 7
#define CENTIPEDE 8
#define JACULI 9
#define TROGLODYTE 10
#define ANT 11
#define EYE 12
#define LEPRECHAUN 13
#define NYMPH 14
#define QUASIT 15
#define RUSTMONSTER 16
#define ZOMBIE 17
#define ASSASSINBUG 18
#define BUGBEAR 19
#define HELLHOUND 20
#define ICELIZARD 21
#define CENTAUR 22
#define TROLL 23
#define YETI 24
#define WHITEDRAGON 25
#define ELF 26
#define CUBE 27
#define METAMORPH 28
#define VORTEX 29
#define ZILLER 30
#define VIOLETFUNGI 31
#define WRAITH 32
#define FORVALAKA 33
#define LAMANOBE 34
#define OSEQUIP 35
#define ROTHE 36
#define XORN 37
#define VAMPIRE 38
#define INVISIBLESTALKER 39
#define POLTERGEIST 40
#define DISENCHANTRESS 41
#define SHAMBLINGMOUND 42
#define YELLOWMOLD 43
#define UMBERHULK 44
#define GNOMEKING 45
#define MIMIC 46
#define WATERLORD 47
#define BRONZEDRAGON 48
#define GREENDRAGON 49
#define PURPLEWORM 50
#define XVART 51
#define SPIRITNAGA 52
#define SILVERDRAGON 53
#define PLATINUMDRAGON 54
#define GREENURCHIN 55
#define REDDRAGON 56
#define DEMONLORD 57
#define DEMONPRINCE 64

#define NULL 0
#define BUFBIG 4096 /* size of the output buffer */
#define MAXIBUF 4096 /* size of the input buffer */
#define LOGNAMESIZE 40 /* max size of the players name */
#define PSNAMESIZE 40 /* max size of the process name */
#define SAVEFILENAMESIZE 128 /* max size of the savefile path */

#ifndef NODEFS
extern char VERSION,SUBVERSION;
extern char aborted[],alpha[],beenhere[],boldon,cheat,ckpfile[],ckpflag;
extern char *class[],course[],diagfile[],fortfile[],helpfile[],holifile[];
extern char *inbuffer,is_alpha[],is_digit[];
extern char item[MAXX][MAXY],iven[],know[MAXX][MAXY],larnlevels[],lastmonst[];
extern char level,*levelname[],logfile[],loginname[],logname[],*lpbuf,*lpend;
extern char *lpnt,moved[MAXX][MAXY],mitem[MAXX][MAXY],monstlevel[];
extern char monstnamelist[],nch[],ndgg[],nlpts[],nomove,nosignal,nowelcome;
extern char nplt[],nsw[],*objectname[];
extern char objnamelist[],optsfile[],*potionname[],playerids[],potprob[];
extern char predostuff,psname[],restorflag,savefilename[],scorefile[],scprob[];
extern char screen[MAXX][MAXY],*scrollname[],sex,*spelcode[],*speldescript[];
extern char spelknow[],*spelname[],*spelmes[],spelweird[MAXMONST+8][SPNUM];
extern char splev[],stealth[MAXX][MAXY],to_lower[],to_upper[],wizard;
extern short diroffx[],diroffy[],hitflag,hit2flag,hit3flag,hitp[MAXX][MAXY];
extern short iarg[MAXX][MAXY],ivenarg[],lasthx,lasthy,lastnum,lastpx,lastpy;
extern short nobeep,oldx,oldy,playerx,playery;
extern int dayplay,enable_scroll,srcount,yrepcount,userid,wisid,lfd,fd;
extern long initialtime,outstanding_taxes,skill[],gtime,c[],cbak[];
extern unsigned long randx;
extern struct cel *cell;
extern struct monst monster[];
extern struct sphere *spheres;
extern struct _itm itm[];

char *fortune(),*malloc(),*getenv(),*getlogin(),*lgetw(),*lgetl(),*ctime();
char *tmcapcnv(),*tgetstr(),*tgoto();
long paytaxes(),lgetc(),lrint(),time();
unsigned long readnum();

/* macro to create scroll #'s with probability of occurrence */
#define newscroll() (scprob[rund(81)])
/* macro to return a potion # created with probability of occurrence */
#define newpotion() (potprob[rund(41)])
/* macro to return the + points on created leather armor */
#define newleather() (nlpts[rund(c[HARDGAME]?13:15)])
/* macro to return the + points on chain armor */
#define newchain() (nch[rund(10)])
/* macro to return + points on plate armor */
#define newplate() (nplt[rund(c[HARDGAME]?4:12)])
/* macro to return + points on new daggers */
#define newdagger() (ndgg[rund(13)])
/* macro to return + points on new swords */
#define newsword() (nsw[rund(c[HARDGAME]?6:13)])
/* macro to destroy object at present location */
#define forget() (item[playerx][playery]=know[playerx][playery]=0)
/* macro to wipe out a monster at a location */
#define disappear(x,y) (mitem[x][y]=know[x][y]=0)

#ifdef VT100
/* macro to turn on bold display for the terminal */
#define setbold() (lprcat(boldon?"\33[1m":"\33[7m"))
/* macro to turn off bold display for the terminal */
#define resetbold() (lprcat("\33[m"))
/* macro to setup the scrolling region for the terminal */
#define setscroll() (lprcat("\33[20;24r"))
/* macro to clear the scrolling region for the terminal */
#define resetscroll() (lprcat("\33[;24r"))
/* macro to clear the screen and home the cursor */
#define clear() (lprcat("\33[2J\33[f"), cbak[SPELLS]= -50)
#define cltoeoln() lprcat("\33[K")
#else VT100
/* defines below are for use in the termcap mode only */
#define ST_START 1
#define ST_END 2
#define BOLD 3
#define END_BOLD 4
#define CLEAR 5
#define CL_LINE 6
#define CL_DOWN 14
#define CURSOR 15
/* macro to turn on bold display for the terminal */
#define setbold() (*lpnt++ = ST_START)
/* macro to turn off bold display for the terminal */
#define resetbold() (*lpnt++ = ST_END)
/* macro to setup the scrolling region for the terminal */
#define setscroll() enable_scroll=1
/* macro to clear the scrolling region for the terminal */
#define resetscroll() enable_scroll=0
/* macro to clear the screen and home the cursor */
#define clear() (*lpnt++ =CLEAR, cbak[SPELLS]= -50)
/* macro to clear to end of line */
#define cltoeoln() (*lpnt++ = CL_LINE)
#endif VT100

/* macro to output one byte to the output buffer */
#define lprc(ch) ((lpnt>=lpend)?(*lpnt++ =(ch), lflush()):(*lpnt++ =(ch)))

/* macro to seed the random number generator */
#define srand(x) (randx=x)
#ifdef MACRORND
/* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */
#define rnd(x) ((((randx=randx*1103515245+12345)>>7)%(x))+1)
#define rund(x) ((((randx=randx*1103515245+12345)>>7)%(x)) )
#endif MACRORND
/* macros for miscellaneous data conversion */
#define min(x,y) (((x)>(y))?(y):(x))
#define max(x,y) (((x)>(y))?(x):(y))
#define isalpha(x) (is_alpha[x])
#define isdigit(x) (is_digit[x])
#define tolower(x) (to_lower[x])
#define toupper(x) (to_upper[x])
#define lcc(x) (to_lower[x])
#define ucc(x) (to_upper[x])
#endif NODEFS

SHAR_EOF
if test 12291 -ne "`wc -c < 'header.h'`"
then
echo shar: error transmitting "'header.h'" '(should have been 12291 characters)'
fi
fi
echo shar: extracting "'io.c'" '(22441 characters)'
if test -f 'io.c'
then
echo shar: will not over-write existing file "'io.c'"
else
cat << \SHAR_EOF > 'io.c'
/* io.c Larn is copyrighted 1986 by Noah Morgan.
*
* Below are the functions in this file:
*
* setupvt100() Subroutine to set up terminal in correct mode for game
* clearvt100() Subroutine to clean up terminal when the game is over
* getchar() Routine to read in one character from the terminal
* scbr() Function to set cbreak -echo for the terminal
* sncbr() Function to set -cbreak echo for the terminal
* newgame() Subroutine to save the initial time and seed rnd()
*
* FILE OUTPUT ROUTINES
*
* lprintf(format,args . . .) printf to the output buffer
* lprint(integer) send binary integer to output buffer
* lwrite(buf,len) write a buffer to the output buffer
* lprcat(str) sent string to output buffer
*
* FILE OUTPUT MACROS (in header.h)
*
* lprc(character) put the character into the output buffer
*
* FILE INPUT ROUTINES
*
* long lgetc() read one character from input buffer
* long lrint() read one integer from input buffer
* lrfill(address,number) put input bytes into a buffer
* char *lgetw() get a whitespace ended word from input
* char *lgetl() get a \n or EOF ended line from input
*
* FILE OPEN / CLOSE ROUTINES
*
* lcreat(filename) create a new file for write
* lopen(filename) open a file for read
* lappend(filename) open for append to an existing file
* lrclose() close the input file
* lwclose() close output file
* lflush() flush the output buffer
*
* Other Routines
*
* cursor(x,y) position cursor at [x,y]
* cursors() position cursor at [1,24] (saves memory)
* cl_line(x,y) Clear line at [1,y] and leave cursor at [x,y]
* cl_up(x,y) Clear screen from [x,1] to current line.
* cl_dn(x,y) Clear screen from [1,y] to end of display.
* standout(str) Print the string in standout mode.
* set_score_output() Called when output should be literally printed.
** putchar(ch) Print one character in decoded output buffer.
** flush_buf() Flush buffer with decoded output.
** init_term() Terminal initialization -- setup termcap info
** char *tmcapcnv(sd,ss) Routine to convert VT100 \33's to termcap format
* beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
*
* Note: ** entries are available only in termcap mode.
*/

#include "header.h"

#ifdef SYSV /* system III or system V */
#include <termio.h>
#define sgttyb termio
#define stty(_a,_b) ioctl(_a,TCSETA,_b)
#define gtty(_a,_b) ioctl(_a,TCGETA,_b)
static int rawflg = 0;
static char saveeof,saveeol;
#define doraw(_a) if(!rawflg){++rawflg;saveeof=_a.c_cc[VMIN];saveeol=_a.c_cc[VTIME];}\
_a.c_cc[VMIN]=1;_a.c_cc[VTIME]=1;_a.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL)
#define unraw(_a) _a.c_cc[VMIN]=saveeof;_a.c_cc[VTIME]=saveeol;_a.c_lflag |= ICANON|ECHO|ECHOE|ECHOK|ECHONL

#else not SYSV

#ifndef BSD
#define CBREAK RAW /* V7 has no CBREAK */
#endif

#define doraw(_a) (_a.sg_flags |= CBREAK,_a.sg_flags &= ~ECHO)
#define unraw(_a) (_a.sg_flags &= ~CBREAK,_a.sg_flags |= ECHO)
#include <sgtty.h>
#endif not SYSV

#ifndef NOVARARGS /* if we have varargs */
#include <varargs.h>
#else NOVARARGS /* if we don't have varargs */
typedef char *va_list;
#define va_dcl int va_alist;
#define va_start(plist) plist = (char *) &va_alist
#define va_end(plist)
#define va_arg(plist,mode) ((mode *)(plist += sizeof(mode)))[-1]
#endif NOVARARGS

#define LINBUFSIZE 128 /* size of the lgetw() and lgetl() buffer */
int lfd; /* output file numbers */
int fd; /* input file numbers */
static struct sgttyb ttx; /* storage for the tty modes */
static int ipoint=MAXIBUF,iepoint=MAXIBUF; /* input buffering pointers */
static char lgetwbuf[LINBUFSIZE]; /* get line (word) buffer */

/*
* setupvt100() Subroutine to set up terminal in correct mode for game
*
* Attributes off, clear screen, set scrolling region, set tty mode
*/
setupvt100()
{
clear(); setscroll(); scbr(); /* system("stty cbreak -echo"); */
}

/*
* clearvt100() Subroutine to clean up terminal when the game is over
*
* Attributes off, clear screen, unset scrolling region, restore tty mode
*/
clearvt100()
{
resetscroll(); clear(); sncbr(); /* system("stty -cbreak echo"); */
}

/*
* getchar() Routine to read in one character from the terminal
*/
getchar()
{
char byt;
#ifdef EXTRA
c[BYTESIN]++;
#endif
lflush(); /* be sure output buffer is flushed */
read(0,&byt,1); /* get byte from terminal */
return(byt);
}

/*
* scbr() Function to set cbreak -echo for the terminal
*
* like: system("stty cbreak -echo")
*/
scbr()
{
gtty(0,&ttx); doraw(ttx); stty(0,&ttx);
}

/*
* sncbr() Function to set -cbreak echo for the terminal
*
* like: system("stty -cbreak echo")
*/
sncbr()
{
gtty(0,&ttx); unraw(ttx); stty(0,&ttx);
}

/*
* newgame() Subroutine to save the initial time and seed rnd()
*/
newgame()
{
register long *p,*pe;
for (p=c,pe=c+100; p<pe; *p++ =0);
time(&initialtime); srand(initialtime);
lcreat((char*)0); /* open buffering for output to terminal */
}

/*
* lprintf(format,args . . .) printf to the output buffer
* char *format;
* ??? args . . .
*
* Enter with the format string in "format", as per printf() usage
* and any needed arguments following it
* Note: lprintf() only supports %s, %c and %d, with width modifier and left
* or right justification.
* No correct checking for output buffer overflow is done, but flushes
* are done beforehand if needed.
* Returns nothing of value.
*/
#ifdef lint
/*VARARGS*/
lprintf(str)
char *str;
{
char *str2;
str2 = str;
str = str2; /* to make lint happy */
}
/*VARARGS*/
sprintf(str)
char *str;
{
char *str2;
str2 = str;
str = str2; /* to make lint happy */
}
#else lint
/*VARARGS*/
lprintf(va_alist)
va_dcl
{
va_list ap; /* pointer for variable argument list */
register char *fmt;
register char *outb,*tmpb;
register long wide,left,cont,n; /* data for lprintf */
char db[12]; /* %d buffer in lprintf */

va_start(ap); /* initialize the var args pointer */
fmt = va_arg(ap, char *); /* pointer to format string */
if (lpnt >= lpend) lflush();
outb = lpnt;
for ( ; ; )
{
while (*fmt != '%')
if (*fmt) *outb++ = *fmt++; else { lpnt=outb; return; }
wide = 0; left = 1; cont=1;
while (cont)
switch(*(++fmt))
{
case 'd': n = va_arg(ap, long);
if (n<0) { n = -n; *outb++ = '-'; if (wide) --wide; }
tmpb = db+11; *tmpb = (char)(n % 10 + '0');
while (n>9) *(--tmpb) = (char)((n /= 10) % 10 + '0');
if (wide==0) while (tmpb < db+12) *outb++ = *tmpb++;
else
{
wide -= db-tmpb+12;
if (left) while (wide-- > 0) *outb++ = ' ';
while (tmpb < db+12) *outb++ = *tmpb++;
if (left==0) while (wide-- > 0) *outb++ = ' ';
}
cont=0; break;

case 's': tmpb = va_arg(ap, char *);
if (wide==0) { while (*outb++ = *tmpb++); --outb; }
else
{
n = wide - strlen(tmpb);
if (left) while (n-- > 0) *outb++ = ' ';
while (*outb++ = *tmpb++); --outb;
if (left==0) while (n-- > 0) *outb++ = ' ';
}
cont=0; break;

case 'c': *outb++ = va_arg(ap, int); cont=0; break;

case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': wide = 10*wide + *fmt - '0'; break;

case '-': left = 0; break;

default: *outb++ = *fmt; cont=0; break;
};
fmt++;
}
va_end(ap);
}
#endif lint

/*
* lprint(long-integer) send binary integer to output buffer
* long integer;
*
* +---------+---------+---------+---------+
* | high | | | low |
* | order | | | order |
* | byte | | | byte |
* +---------+---------+---------+---------+
* 31 --- 24 23 --- 16 15 --- 8 7 --- 0
*
* The save order is low order first, to high order (4 bytes total)
* and is written to be system independent.
* No checking for output buffer overflow is done, but flushes if needed!
* Returns nothing of value.
*/
lprint(x)
register long x;
{
if (lpnt >= lpend) lflush();
*lpnt++ = 255 & x; *lpnt++ = 255 & (x>>8);
*lpnt++ = 255 & (x>>16); *lpnt++ = 255 & (x>>24);
}

/*
* lwrite(buf,len) write a buffer to the output buffer
* char *buf;
* int len;
*
* Enter with the address and number of bytes to write out
* Returns nothing of value
*/
lwrite(buf,len)
register char *buf;
int len;
{
register char *str;
register int num2;
if (len > 399) /* don't copy data if can just write it */
{
#ifdef EXTRA
c[BYTESOUT] += len;
#endif

#ifndef VT100
for (str=buf; len>0; --len)
lprc(*str++);
#else VT100
lflush();
write(lfd,buf,len);
#endif VT100
}
else while (len)
{
if (lpnt >= lpend) lflush(); /* if buffer is full flush it */
num2 = lpbuf+BUFBIG-lpnt; /* # bytes left in output buffer */
if (num2 > len) num2=len;
str = lpnt; len -= num2;
while (num2--) *str++ = *buf++; /* copy in the bytes */
lpnt = str;
}
}

/*
* long lgetc() Read one character from input buffer
*
* Returns 0 if EOF, otherwise the character
*/
long lgetc()
{
register int i;
if (ipoint != iepoint) return(inbuffer[ipoint++]);
if (iepoint!=MAXIBUF) return(0);
if ((i=read(fd,inbuffer,MAXIBUF))<=0)
{
if (i!=0) write(1,"error reading from input file\n",30);
iepoint = ipoint = 0; return(0);
}
ipoint=1; iepoint=i; return(*inbuffer);
}

/*
* long lrint() Read one integer from input buffer
*
* +---------+---------+---------+---------+
* | high | | | low |
* | order | | | order |
* | byte | | | byte |
* +---------+---------+---------+---------+
* 31 --- 24 23 --- 16 15 --- 8 7 --- 0
*
* The save order is low order first, to high order (4 bytes total)
* Returns the int read
*/
long lrint()
{
register unsigned long i;
i = 255 & lgetc(); i |= (255 & lgetc()) << 8;
i |= (255 & lgetc()) << 16; i |= (255 & lgetc()) << 24;
return(i);
}

/*
* lrfill(address,number) put input bytes into a buffer
* char *address;
* int number;
*
* Reads "number" bytes into the buffer pointed to by "address".
* Returns nothing of value
*/
lrfill(adr,num)
register char *adr;
int num;
{
register char *pnt;
register int num2;
while (num)
{
if (iepoint == ipoint)
{
if (num>5) /* fast way */
{
if (read(fd,adr,num) != num)
write(2,"error reading from input file\n",30);
num=0;
}
else { *adr++ = lgetc(); --num; }
}
else
{
num2 = iepoint-ipoint; /* # of bytes left in the buffer */
if (num2 > num) num2=num;
pnt = inbuffer+ipoint; num -= num2; ipoint += num2;
while (num2--) *adr++ = *pnt++;
}
}
}

/*
* char *lgetw() Get a whitespace ended word from input
*
* Returns pointer to a buffer that contains word. If EOF, returns a NULL
*/
char *lgetw()
{
register char *lgp,cc;
register int n=LINBUFSIZE,quote=0;
lgp = lgetwbuf;
do cc=lgetc(); while ((cc <= 32) && (cc > NULL)); /* eat whitespace */
for ( ; ; --n,cc=lgetc())
{
if ((cc==NULL) && (lgp==lgetwbuf)) return(NULL); /* EOF */
if ((n<=1) || ((cc<=32) && (quote==0))) { *lgp=NULL; return(lgetwbuf); }
if (cc != '"') *lgp++ = cc; else quote ^= 1;
}
}

/*
* char *lgetl() Function to read in a line ended by newline or EOF
*
* Returns pointer to a buffer that contains the line. If EOF, returns NULL
*/
char *lgetl()
{
register int i=LINBUFSIZE,ch;
register char *str=lgetwbuf;
for ( ; ; --i)
{
if ((*str++ = ch = lgetc()) == NULL)
{
if (str == lgetwbuf+1) return(NULL); /* EOF */
ot: *str = NULL; return(lgetwbuf); /* line ended by EOF */
}
if ((ch=='\n') || (i<=1)) goto ot; /* line ended by \n */
}
}

/*
* lcreat(filename) Create a new file for write
* char *filename;
*
* lcreat((char*)0); means to the terminal
* Returns -1 if error, otherwise the file descriptor opened.
*/
lcreat(str)
char *str;
{
lpnt = lpbuf; lpend = lpbuf+BUFBIG;
if (str==NULL) return(lfd=1);
if ((lfd=creat(str,0644)) < 0)
{
lfd=1; lprintf("error creating file <%s>\n",str); lflush(); return(-1);
}
return(lfd);
}

/*
* lopen(filename) Open a file for read
* char *filename;
*
* lopen(0) means from the terminal
* Returns -1 if error, otherwise the file descriptor opened.
*/
lopen(str)
char *str;
{
ipoint = iepoint = MAXIBUF;
if (str==NULL) return(fd=0);
if ((fd=open(str,0)) < 0)
{
lwclose(); lfd=1; lpnt=lpbuf; return(-1);
}
return(fd);
}

/*
* lappend(filename) Open for append to an existing file
* char *filename;
*
* lappend(0) means to the terminal
* Returns -1 if error, otherwise the file descriptor opened.
*/
lappend(str)
char *str;
{
lpnt = lpbuf; lpend = lpbuf+BUFBIG;
if (str==NULL) return(lfd=1);
if ((lfd=open(str,2)) < 0)
{
lfd=1; return(-1);
}
lseek(lfd,0,2); /* seek to end of file */
return(lfd);
}

/*
* lrclose() close the input file
*
* Returns nothing of value.
*/
lrclose()
{
if (fd > 0) close(fd);
}

/*
* lwclose() close output file flushing if needed
*
* Returns nothing of value.
*/
lwclose()
{
lflush(); if (lfd > 2) close(lfd);
}

/*
* lprcat(string) append a string to the output buffer
* avoids calls to lprintf (time consuming)
*/
lprcat(str)
register char *str;
{
register char *str2;
if (lpnt >= lpend) lflush();
str2 = lpnt;
while (*str2++ = *str++);
lpnt = str2 - 1;
}

#ifdef VT100
/*
* cursor(x,y) Subroutine to set the cursor position
*
* x and y are the cursor coordinates, and lpbuff is the output buffer where
* escape sequence will be placed.
*/
static char *y_num[]= { "\33[","\33[","\33[2","\33[3","\33[4","\33[5","\33[6",
"\33[7","\33[8","\33[9","\33[10","\33[11","\33[12","\33[13","\33[14",
"\33[15","\33[16","\33[17","\33[18","\33[19","\33[20","\33[21","\33[22",
"\33[23","\33[24" };

static char *x_num[]= { "H","H",";2H",";3H",";4H",";5H",";6H",";7H",";8H",";9H",
";10H",";11H",";12H",";13H",";14H",";15H",";16H",";17H",";18H",";19H",
";20H",";21H",";22H",";23H",";24H",";25H",";26H",";27H",";28H",";29H",
";30H",";31H",";32H",";33H",";34H",";35H",";36H",";37H",";38H",";39H",
";40H",";41H",";42H",";43H",";44H",";45H",";46H",";47H",";48H",";49H",
";50H",";51H",";52H",";53H",";54H",";55H",";56H",";57H",";58H",";59H",
";60H",";61H",";62H",";63H",";64H",";65H",";66H",";67H",";68H",";69H",
";70H",";71H",";72H",";73H",";74H",";75H",";76H",";77H",";78H",";79H",
";80H" };

cursor(x,y)
int x,y;
{
register char *p;
if (lpnt >= lpend) lflush();

p = y_num[y]; /* get the string to print */
while (*p) *lpnt++ = *p++; /* print the string */

p = x_num[x]; /* get the string to print */
while (*p) *lpnt++ = *p++; /* print the string */
}
#else VT100
/*
* cursor(x,y) Put cursor at specified coordinates staring at [1,1] (termcap)
*/
cursor (x,y)
int x,y;
{
if (lpnt >= lpend) lflush ();

*lpnt++ = CURSOR; *lpnt++ = x; *lpnt++ = y;
}
#endif VT100

/*
* Routine to position cursor at beginning of 24th line
*/
cursors()
{
cursor(1,24);
}

#ifndef VT100
/*
* Warning: ringing the bell is control code 7. Don't use in defines.
* Don't change the order of these defines.
* Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
* obvious meanings.
*/

static char cap[256];
char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL;/* Termcap capabilities */
static char *outbuf=0; /* translated output buffer */

int putchar ();

/*
* init_term() Terminal initialization -- setup termcap info
*/
init_term()
{
char termbuf[1024];
char *capptr = cap+10;
char *term;

switch (tgetent(termbuf, term = getenv("TERM")))
{
case -1:
write(2, "Cannot open termcap file.\n", 26); exit();
case 0:
write(2, "Cannot find entry of ", 21);
write(2, term, strlen (term));
write(2, " in termcap\n", 12);
exit();
};

CM = tgetstr("cm", &capptr); /* Cursor motion */
CE = tgetstr("ce", &capptr); /* Clear to eoln */
CL = tgetstr("cl", &capptr); /* Clear screen */

/* OPTIONAL */
AL = tgetstr("al", &capptr); /* Insert line */
DL = tgetstr("dl", &capptr); /* Delete line */
SO = tgetstr("so", &capptr); /* Begin standout mode */
SE = tgetstr("se", &capptr); /* End standout mode */
CD = tgetstr("cd", &capptr); /* Clear to end of display */

if (!CM) /* can't find cursor motion entry */
{
write(2, "Sorry, for a ",13); write(2, term, strlen(term));
write(2, ", I can't find the cursor motion entry in termcap\n",50);
exit();
}
if (!CE) /* can't find clear to end of line entry */
{
write(2, "Sorry, for a ",13); write(2, term, strlen(term));
write(2,", I can't find the clear to end of line entry in termcap\n",57);
exit();
}
if (!CL) /* can't find clear entire screen entry */
{
write(2, "Sorry, for a ",13); write(2, term, strlen(term));
write(2, ", I can't find the clear entire screen entry in termcap\n",56);
exit();
}
if ((outbuf=malloc(BUFBIG+16))==0) /* get memory for decoded output buffer*/
{
write(2,"Error malloc'ing memory for decoded output buffer\n",50);
died(-285); /* malloc() failure */
}
}
#endif VT100

/*
* cl_line(x,y) Clear the whole line indicated by 'y' and leave cursor at [x,y]
*/
cl_line(x,y)
int x,y;
{
#ifdef VT100
cursor(x,y); lprcat("\33[2K");
#else VT100
cursor(1,y); *lpnt++ = CL_LINE; cursor(x,y);
#endif VT100
}

/*
* cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
*/
cl_up(x,y)
register int x,y;
{
#ifdef VT100
cursor(x,y); lprcat("\33[1J\33[2K");
#else VT100
register int i;
cursor(1,1);
for (i=1; i<=y; i++) { *lpnt++ = CL_LINE; *lpnt++ = '\n'; }
cursor(x,y);
#endif VT100
}

/*
* cl_dn(x,y) Clear screen from [1,y] to end of display. Leave cursor at [x,y]
*/
cl_dn(x,y)
register int x,y;
{
#ifdef VT100
cursor(x,y); lprcat("\33[J\33[2K");
#else VT100
register int i;
cursor(1,y);
if (!CD)
{
*lpnt++ = CL_LINE;
for (i=y; i<=24; i++) { *lpnt++ = CL_LINE; if (i!=24) *lpnt++ = '\n'; }
cursor(x,y);
}
else
*lpnt++ = CL_DOWN;
cursor(x,y);
#endif VT100
}

/*
* standout(str) Print the argument string in inverse video (standout mode).
*/
standout(str)
register char *str;
{
#ifdef VT100
setbold();
while (*str)
*lpnt++ = *str++;
resetbold();
#else VT100
*lpnt++ = ST_START;
while (*str)
*lpnt++ = *str++;
*lpnt++ = ST_END;
#endif VT100
}

/*
* set_score_output() Called when output should be literally printed.
*/
set_score_output()
{
enable_scroll = -1;
}

/*
* lflush() Flush the output buffer
*
* Returns nothing of value.
* for termcap version: Flush output in output buffer according to output
* status as indicated by `enable_scroll'
*/
#ifndef VT100
static int scrline=18; /* line # for wraparound instead of scrolling if no DL */
lflush ()
{
register int lpoint;
register char *str;
static int curx = 0;
static int cury = 0;

if ((lpoint = lpnt - lpbuf) > 0)
{
#ifdef EXTRA
c[BYTESOUT] += lpoint;
#endif
if (enable_scroll <= -1)
{
flush_buf();
if (write(lfd,lpbuf,lpoint) != lpoint)
write(2,"error writing to output file\n",29);
lpnt = lpbuf; /* point back to beginning of buffer */
return;
}
for (str = lpbuf; str < lpnt; str++)
{
if (*str>=32) { putchar (*str); curx++; }
else switch (*str)
{
case CLEAR: tputs (CL, 0, putchar); curx = cury = 0;
break;

case CL_LINE: tputs (CE, 0, putchar);
break;

case CL_DOWN: tputs (CD, 0, putchar);
break;

case ST_START: tputs (SO, 0, putchar);
break;

case ST_END: tputs (SE, 0, putchar);
break;

case CURSOR: curx = *++str - 1; cury = *++str - 1;
tputs (tgoto (CM, curx, cury), 0, putchar);
break;

case '\n': if ((cury == 23) && enable_scroll)
{
if (!DL || !AL) /* wraparound or scroll? */
{
if (++scrline > 23) scrline=19;

if (++scrline > 23) scrline=19;
tputs (tgoto (CM, 0, scrline), 0, putchar);
tputs (CE, 0, putchar);

if (--scrline < 19) scrline=23;
tputs (tgoto (CM, 0, scrline), 0, putchar);
tputs (CE, 0, putchar);
}
else
{
tputs (tgoto (CM, 0, 19), 0, putchar);
tputs (DL, 0, putchar);
tputs (tgoto (CM, 0, 23), 0, putchar);
/* tputs (AL, 0, putchar); */
}
}
else
{
putchar ('\n'); cury++;
}
curx = 0;
break;

default: putchar (*str); curx++;
};
}
}
lpnt = lpbuf;
flush_buf(); /* flush real output buffer now */
}
#else VT100
/*
* lflush() flush the output buffer
*
* Returns nothing of value.
*/
lflush()
{
register int lpoint;
if ((lpoint = lpnt - lpbuf) > 0)
{
#ifdef EXTRA
c[BYTESOUT] += lpoint;
#endif
if (write(lfd,lpbuf,lpoint) != lpoint)
write(2,"error writing to output file\n",29);
}
lpnt = lpbuf; /* point back to beginning of buffer */
}
#endif VT100

#ifndef VT100
static int index=0;
/*
* putchar(ch) Print one character in decoded output buffer.
*/
int putchar(c)
int c;
{
outbuf[index++] = c;
if (index >= BUFBIG) flush_buf();
}

/*
* flush_buf() Flush buffer with decoded output.
*/
flush_buf()
{
if (index) write(lfd, outbuf, index);
index = 0;
}

/*
* char *tmcapcnv(sd,ss) Routine to convert VT100 escapes to termcap format
*
* Processes only the \33[#m sequence (converts . files for termcap use
*/
char *tmcapcnv(sd,ss)
register char *sd,*ss;
{
register int tmstate=0; /* 0=normal, 1=\33 2=[ 3=# */
char tmdigit=0; /* the # in \33[#m */
while (*ss)
{
switch(tmstate)
{
case 0: if (*ss=='\33') { tmstate++; break; }
ign: *sd++ = *ss;
ign2: tmstate = 0;
break;
case 1: if (*ss!='[') goto ign;
tmstate++;
break;
case 2: if (isdigit(*ss)) { tmdigit= *ss-'0'; tmstate++; break; }
if (*ss == 'm') { *sd++ = ST_END; goto ign2; }
goto ign;
case 3: if (*ss == 'm')
{
if (tmdigit) *sd++ = ST_START;
else *sd++ = ST_END;
goto ign2;
}
default: goto ign;
};
ss++;
}
*sd=0; /* NULL terminator */
return(sd);
}
#endif VT100

/*
* beep() Routine to emit a beep if enabled (see no-beep in .larnopts)
*/
beep()
{
if (!nobeep) *lpnt++ = '\7';
}
SHAR_EOF
if test 22441 -ne "`wc -c < 'io.c'`"
then
echo shar: error transmitting "'io.c'" '(should have been 22441 characters)'
fi
fi
echo shar: extracting "'main.c'" '(25702 characters)'
if test -f 'main.c'
then
echo shar: will not over-write existing file "'main.c'"
else
cat << \SHAR_EOF > 'main.c'
/* main.c */
#include "header.h"
#include <pwd.h>
static char copyright[]="\nLarn is copyrighted 1986 by Noah Morgan.\n";
int srcount=0; /* line counter for showstr() */
int dropflag=0; /* if 1 then don't lookforobject() next round */
int rmst=80; /* random monster creation counter */
int userid; /* the players login user id number */
char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a move */
static char viewflag=0;
/* if viewflag then we have done a 99 stay here and don't showcell in the main loop */
char restorflag=0; /* 1 means restore has been done */
static char cmdhelp[] = "\
Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
-s show the scoreboard\n\
-l show the logfile (wizard id only)\n\
-i show scoreboard with inventories of dead characters\n\
-c create new scoreboard (wizard id only)\n\
-n suppress welcome message on starting game\n\
-## specify level of difficulty (example: -5)\n\
-h print this help text\n\
++ restore game from checkpoint file\n\
-o<optsfile> specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
";
#ifdef VT100
static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
"vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
"vt341" };
#endif VT100
/*
************
MAIN PROGRAM
************
*/
main(argc,argv)
int argc;
char **argv;
{
register int i,j;
int hard;
char *ptr=0,*ttype;
struct passwd *pwe,*getpwuid();

/*
* first task is to identify the player
*/
#ifndef VT100
init_term(); /* setup the terminal (find out what type) for termcap */
#endif VT100
if (((ptr = getlogin()) == 0) || (*ptr==0)) /* try to get login name */
if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
ptr = pwe->pw_name;
else
if ((ptr = getenv("USER")) == 0)
if ((ptr = getenv("LOGNAME")) == 0)
{
noone: write(2, "Can't find your logname. Who Are You?\n",39);
exit();
}
if (ptr==0) goto noone;
if (strlen(ptr)==0) goto noone;
/*
* second task is to prepare the pathnames the player will need
*/
strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
strcpy(logname,ptr); /* this will be overwritten with the players name */
if ((ptr = getenv("HOME")) == 0) ptr = ".";
#ifdef SAVEINHOME
strcpy(savefilename, ptr);
strcat(savefilename, "/Larn.sav"); /* save file name in home directory */
#else
strcat(savefilename,logname); /* prepare savefile name */
strcat(savefilename,".sav"); /* prepare savefile name */
#endif
sprintf(optsfile, "%s/.larnopts",ptr); /* the .larnopts filename */
strcat(scorefile, SCORENAME); /* the larn scoreboard filename */
strcat(logfile, LOGFNAME); /* larn activity logging filename */
strcat(helpfile, HELPNAME); /* the larn on-line help file */
strcat(larnlevels, LEVELSNAME); /* the pre-made cave level data file */
strcat(fortfile, FORTSNAME); /* the fortune data file name */
strcat(playerids, PLAYERIDS); /* the playerid data file name */
strcat(holifile, HOLIFILE); /* the holiday data file name */

/*
* now malloc the memory for the dungeon
*/
cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
if (cell == 0) died(-285); /* malloc failure */
lpbuf = malloc((5* BUFBIG)>>2); /* output buffer */
inbuffer = malloc((5*MAXIBUF)>>2); /* output buffer */
if ((lpbuf==0) || (inbuffer==0)) died(-285); /* malloc() failure */

lcreat((char*)0); newgame(); /* set the initial clock */ hard= -1;

#ifdef VT100
/*
* check terminal type to avoid users who have not vt100 type terminals
*/
ttype = getenv("TERM");
for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
if (strcmp(ttype,termtypes[i]) == 0) { j=0; break; }
if (j)
{
lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
exit();
}
#endif VT100

/*
* now make scoreboard if it is not there (don't clear)
*/
if (access(scorefile,0) == -1) /* not there */
makeboard();

/*
* now process the command line arguments
*/
for (i=1; i<argc; i++)
{
if (argv[i][0] == '-')
switch(argv[i][1])
{
case 's': showscores(); exit(); /* show scoreboard */

case 'l': /* show log file */
diedlog(); exit();

case 'i': showallscores(); exit(); /* show all scoreboard */

case 'c': /* anyone with password can create scoreboard */
lprcat("Preparing to initialize the scoreboard.\n");
if (getpassword() != 0) /*make new scoreboard*/
{
makeboard(); lprc('\n'); showscores();
}
exit();

case 'n': /* no welcome msg */ nowelcome=1; argv[i][0]=0; break;

case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': /* for hardness */
sscanf(&argv[i][1],"%d",&hard);
break;

case 'h': /* print out command line arguments */
write(1,cmdhelp,sizeof(cmdhelp)); exit();

case 'o': /* specify a .larnopts filename */
strncpy(optsfile,argv[i]+2,127); break;

default: printf("Unknown option <%s>\n",argv[i]); exit();
};

if (argv[i][0] == '+')
{
clear(); restorflag = 1;
if (argv[i][1] == '+')
{
hitflag=1; restoregame(ckpfile); /* restore checkpointed game */
}
i = argc;
}
}

readopts(); /* read the options file if there is one */

#ifdef TIMECHECK
/*
* this section of code checks to see if larn is allowed during working hours
*/
if (dayplay==0) /* check for not-during-daytime-hours */
if (playable())
{
write(2,"Sorry, Larn can not be played during working hours.\n",52);
exit();
}
#endif TIMECHECK

#ifdef UIDSCORE
userid = geteuid(); /* obtain the user's effective id number */
#else UIDSCORE
userid = getplid(logname); /* obtain the players id number */
#endif UIDSCORE
if (userid < 0) { write(2,"Can't obtain playerid\n",22); exit(); }

#ifdef HIDEBYLINK
/*
* this section of code causes the program to look like something else to ps
*/
if (strcmp(psname,argv[0])) /* if a different process name only */
{
if ((i=access(psname,1)) < 0)
{ /* link not there */
if (link(argv[0],psname)>=0)
{
argv[0] = psname; execv(psname,argv);
}
}
else
unlink(psname);
}

for (i=1; i<argc; i++)
{
szero(argv[i]); /* zero the argument to avoid ps snooping */
}
#endif HIDEBYLINK

if (access(savefilename,0)==0) /* restore game if need to */
{
clear(); restorflag = 1;
hitflag=1; restoregame(savefilename); /* restore last game */
}
sigsetup(); /* trap all needed signals */
sethard(hard); /* set up the desired difficulty */
setupvt100(); /* setup the terminal special mode */
if (c[HP]==0) /* create new game */
{
makeplayer(); /* make the character that will play */
newcavelevel(0);/* make the dungeon */
predostuff = 1; /* tell signals that we are in the welcome screen */
if (nowelcome==0) welcome(); /* welcome the player to the game */
}
drawscreen(); /* show the initial dungeon */
predostuff = 2; /* tell the trap functions that they must do a showplayer()
from here on */
/* nice(1); /* games should be run niced */
yrepcount = hit2flag = 0;
while (1)
{
if (dropflag==0) lookforobject(); /* see if there is an object here */
else dropflag=0; /* don't show it just dropped an item */
if (hitflag==0) { if (c[HASTEMONST]) movemonst(); movemonst(); } /* move the monsters */
if (viewflag==0) showcell(playerx,playery); else viewflag=0; /* show stuff around player */
if (hit3flag) flushall();
hitflag=hit3flag=0; nomove=1;
bot_linex(); /* update bottom line */
while (nomove)
{
if (hit3flag) flushall();
nomove=0; parse();
} /* get commands and make moves */
regen(); /* regenerate hp and spells */
if (c[TIMESTOP]==0)
if (--rmst <= 0)
{ rmst = 120-(level<<2); fillmonst(makemonst(level)); }
}
}

/*
showstr()

show character's inventory
*/
showstr()
{
register int i,number;
for (number=3, i=0; i<26; i++)
if (iven[i]) number++; /* count items in inventory */
t_setup(number); qshowstr(); t_endup(number);
}

qshowstr()
{
register int i,j,k,sigsav;
srcount=0; sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
if (c[GOLD]) { lprintf(".) %d gold pieces",(long)c[GOLD]); srcount++; }
for (k=26; k>=0; k--)
if (iven[k])
{ for (i=22; i<84; i++)
for (j=0; j<=k; j++) if (i==iven[j]) show3(j); k=0; }

lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime+99)/100+1),(long)((TIMELIMIT-gtime)/100));
more(); nosignal=sigsav;
}

/*
* subroutine to clear screen depending on # lines to display
*/
t_setup(count)
register int count;
{
if (count<20) /* how do we clear the screen? */
{
cl_up(79,count); cursor(1,1);
}
else
{
resetscroll(); clear();
}
}

/*
* subroutine to restore normal display screen depending on t_setup()
*/
t_endup(count)
register int count;
{
if (count<18) /* how did we clear the screen? */
draws(0,MAXX,0,(count>MAXY) ? MAXY : count);
else
{
drawscreen(); setscroll();
}
}

/*
function to show the things player is wearing only
*/
showwear()
{
register int i,j,sigsav,count;
sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
srcount=0;

for (count=2,j=0; j<=26; j++) /* count number of items we will display */
if (i=iven[j])
switch(i)
{
case OLEATHER: case OPLATE: case OCHAIN:
case ORING: case OSTUDLEATHER: case OSPLINT:
case OPLATEARMOR: case OSSPLATE: case OSHIELD:
count++;
};

t_setup(count);

for (i=22; i<84; i++)
for (j=0; j<=26; j++)
if (i==iven[j])
switch(i)
{
case OLEATHER: case OPLATE: case OCHAIN:
case ORING: case OSTUDLEATHER: case OSPLINT:
case OPLATEARMOR: case OSSPLATE: case OSHIELD:
show3(j);
};
more(); nosignal=sigsav; t_endup(count);
}

/*
function to show the things player can wield only
*/
showwield()
{
register int i,j,sigsav,count;
sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
srcount=0;

for (count=2,j=0; j<=26; j++) /* count how many items */
if (i=iven[j])
switch(i)
{
case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
case OSPIRITSCARAB: case OCUBEofUNDEAD:
case OPOTION: case OSCROLL: break;
default: count++;
};

t_setup(count);

for (i=22; i<84; i++)
for (j=0; j<=26; j++)
if (i==iven[j])
switch(i)
{
case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT:
case OSPIRITSCARAB: case OCUBEofUNDEAD:
case OPOTION: case OSCROLL: break;
default: show3(j);
};
more(); nosignal=sigsav; t_endup(count);
}

/*
* function to show the things player can read only
*/
showread()
{
register int i,j,sigsav,count;
sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
srcount=0;

for (count=2,j=0; j<=26; j++)
switch(iven[j])
{
case OBOOK: case OSCROLL: count++;
};
t_setup(count);

for (i=22; i<84; i++)
for (j=0; j<=26; j++)
if (i==iven[j])
switch(i)
{
case OBOOK: case OSCROLL: show3(j);
};
more(); nosignal=sigsav; t_endup(count);
}

/*
* function to show the things player can eat only
*/
showeat()
{
register int i,j,sigsav,count;
sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
srcount=0;

for (count=2,j=0; j<=26; j++)
switch(iven[j])
{
case OCOOKIE: count++;
};
t_setup(count);

for (i=22; i<84; i++)
for (j=0; j<=26; j++)
if (i==iven[j])
switch(i)
{
case OCOOKIE: show3(j);
};
more(); nosignal=sigsav; t_endup(count);
}

/*
function to show the things player can quaff only
*/
showquaff()
{
register int i,j,sigsav,count;
sigsav=nosignal; nosignal=1; /* don't allow ^c etc */
srcount=0;

for (count=2,j=0; j<=26; j++)
switch(iven[j])
{
case OPOTION: count++;
};
t_setup(count);

for (i=22; i<84; i++)
for (j=0; j<=26; j++)
if (i==iven[j])
switch(i)
{
case OPOTION: show3(j);
};
more(); nosignal=sigsav; t_endup(count);
}

show1(idx,str2)
register int idx;
register char *str2[];
{
if (str2==0) lprintf("\n%c) %s",idx+'a',objectname[iven[idx]]);
else if (*str2[ivenarg[idx]]==0) lprintf("\n%c) %s",idx+'a',objectname[iven[idx]]);
else lprintf("\n%c) %s of%s",idx+'a',objectname[iven[idx]],str2[ivenarg[idx]]);
}

show3(index)
register int index;
{
switch(iven[index])
{
case OPOTION: show1(index,potionname); break;
case OSCROLL: show1(index,scrollname); break;

case OLARNEYE: case OBOOK: case OSPIRITSCARAB:
case ODIAMOND: case ORUBY: case OCUBEofUNDEAD:
case OEMERALD: case OCHEST: case OCOOKIE:
case OSAPPHIRE: case ONOTHEFT: show1(index,(char **)0); break;

default: lprintf("\n%c) %s",index+'a',objectname[iven[index]]);
if (ivenarg[index]>0) lprintf(" + %d",(long)ivenarg[index]);
else if (ivenarg[index]<0) lprintf(" %d",(long)ivenarg[index]);
break;
}
if (c[WIELD]==index) lprcat(" (weapon in hand)");
if ((c[WEAR]==index) || (c[SHIELD]==index)) lprcat(" (being worn)");
if (++srcount>=22) { srcount=0; more(); clear(); }
}

/*
subroutine to randomly create monsters if needed
*/
randmonst()
{
if (c[TIMESTOP]) return; /* don't make monsters if time is stopped */
if (--rmst <= 0)
{
rmst = 120 - (level<<2); fillmonst(makemonst(level));
}
}


/*
parse()

get and execute a command
*/
parse()
{
register int i,j,k,flag;
while (1)
{
k = yylex();
switch(k) /* get the token from the input and switch on it */
{
case 'h': moveplayer(4); return; /* west */
case 'H': run(4); return; /* west */
case 'l': moveplayer(2); return; /* east */
case 'L': run(2); return; /* east */
case 'j': moveplayer(1); return; /* south */
case 'J': run(1); return; /* south */
case 'k': moveplayer(3); return; /* north */
case 'K': run(3); return; /* north */
case 'u': moveplayer(5); return; /* northeast */
case 'U': run(5); return; /* northeast */
case 'y': moveplayer(6); return; /* northwest */
case 'Y': run(6); return; /* northwest */
case 'n': moveplayer(7); return; /* southeast */
case 'N': run(7); return; /* southeast */
case 'b': moveplayer(8); return; /* southwest */
case 'B': run(8); return; /* southwest */

case '.': if (yrepcount) viewflag=1; return; /* stay here */

case 'w': yrepcount=0; wield(); return; /* wield a weapon */

case 'W': yrepcount=0; wear(); return; /* wear armor */

case 'r': yrepcount=0;
if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else
if (c[TIMESTOP]==0) readscr(); return; /* to read a scroll */

case 'q': yrepcount=0; if (c[TIMESTOP]==0) quaff(); return; /* quaff a potion */

case 'd': yrepcount=0; if (c[TIMESTOP]==0) dropobj(); return; /* to drop an object */

case 'c': yrepcount=0; cast(); return; /* cast a spell */

case 'i': yrepcount=0; nomove=1; showstr(); return; /* status */

case 'e': yrepcount=0;
if (c[TIMESTOP]==0) eatcookie(); return; /* to eat a fortune cookie */

case 'D': yrepcount=0; seemagic(0); nomove=1; return; /* list spells and scrolls */

case '?': yrepcount=0; help(); nomove=1; return; /* give the help screen*/

case 'S': clear(); lprcat("Saving . . ."); lflush();
savegame(savefilename); wizard=1; died(-257); /* save the game - doesn't return */

case 'Z': yrepcount=0; if (c[LEVEL]>9) { oteleport(1); return; }
cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation");
return; /* teleport yourself */

case '^': /* identify traps */ flag=yrepcount=0; cursors();
lprc('\n'); for (j=playery-1; j<playery+2; j++)
{
if (j < 0) j=0; if (j >= MAXY) break;
for (i=playerx-1; i<playerx+2; i++)
{
if (i < 0) i=0; if (i >= MAXX) break;
switch(item[i][j])
{
case OTRAPDOOR: case ODARTRAP:
case OTRAPARROW: case OTELEPORTER:
lprcat("\nIts "); lprcat(objectname[item[i][j]]); flag++;
};
}
}
if (flag==0) lprcat("\nNo traps are visible");
return;

#if WIZID
case '_': /* this is the fudge player password for wizard mode*/
yrepcount=0; cursors(); nomove=1;
if (userid!=wisid)
{
lprcat("Sorry, you are not empowered to be a wizard.\n");
scbr(); /* system("stty -echo cbreak"); */
lflush(); return;
}
if (getpassword()==0)
{
scbr(); /* system("stty -echo cbreak"); */ return;
}
wizard=1; scbr(); /* system("stty -echo cbreak"); */
for (i=0; i<6; i++) c[i]=70; iven[0]=iven[1]=0;
take(OPROTRING,50); take(OLANCE,25); c[WIELD]=1;
c[LANCEDEATH]=1; c[WEAR] = c[SHIELD] = -1;
raiseexperience(6000000L); c[AWARENESS] += 25000;
{
register int i,j;
for (i=0; i<MAXY; i++)
for (j=0; j<MAXX; j++) know[j][i]=1;
for (i=0; i<SPNUM; i++) spelknow[i]=1;
for (i=0; i<MAXSCROLL; i++) scrollname[i][0]=' ';
for (i=0; i<MAXPOTION; i++) potionname[i][0]=' ';
}
for (i=0; i<MAXSCROLL; i++)
if (strlen(scrollname[i])>2) /* no null items */
{ item[i][0]=OSCROLL; iarg[i][0]=i; }
for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
{ item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
for (i=1; i<MAXY; i++)
{ item[0][i]=i; iarg[0][i]=0; }
for (i=MAXY; i<MAXY+MAXX; i++)
{ item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
for (i=MAXX+MAXY; i<MAXX+MAXY+MAXY; i++)
{ item[MAXX-1][i-MAXX-MAXY]=i; iarg[MAXX-1][i-MAXX-MAXY]=0; }
c[GOLD]+=250000; drawscreen(); return;
#endif

case 'T': yrepcount=0; cursors(); if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
else lprcat("\nYou aren't wearing anything");
return;

case 'g': cursors();
lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
case ' ': yrepcount=0; nomove=1; return;

case 'v': yrepcount=0; cursors();
lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)c[HARDGAME]);
if (wizard) lprcat(" Wizard"); nomove=1;
if (cheat) lprcat(" Cheater");
lprcat(copyright);
return;

case 'Q': yrepcount=0; quit(); nomove=1; return; /* quit */

case 'L'-64: yrepcount=0; drawscreen(); nomove=1; return; /* look */

#if WIZID
#ifdef EXTRA
case 'A': yrepcount=0; nomove=1; if (wizard) { diag(); return; } /* create diagnostic file */
return;
#endif
#endif
case 'P': cursors();
if (outstanding_taxes>0)
lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
else
lprcat("\nYou do not owe any taxes.");
return;
};
}
}

parse2()
{
if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters */
randmonst(); regen();
}

run(dir)
int dir;
{
register int i;
i=1; while (i)
{
i=moveplayer(dir);
if (i>0) { if (c[HASTEMONST]) movemonst(); movemonst(); randmonst(); regen(); }
if (hitflag) i=0;
if (i!=0) showcell(playerx,playery);
}
}

/*
function to wield a weapon
*/
wield()
{
register int i;
while (1)
{
if ((i = whatitem("wield"))=='\33') return;
if (i != '.')
{
if (i=='*') showwield();
else if (iven[i-'a']==0) { ydhi(i); return; }
else if (iven[i-'a']==OPOTION) { ycwi(i); return; }
else if (iven[i-'a']==OSCROLL) { ycwi(i); return; }
else if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; }
else { c[WIELD]=i-'a'; if (iven[i-'a'] == OLANCE) c[LANCEDEATH]=1; else c[LANCEDEATH]=0; bottomline(); return; }
}
}
}

/*
common routine to say you don't have an item
*/
ydhi(x)
int x;
{ cursors(); lprintf("\nYou don't have item %c!",x); }
ycwi(x)
int x;
{ cursors(); lprintf("\nYou can't wield item %c!",x); }

/*
function to wear armor
*/
wear()
{
register int i;
while (1)
{
if ((i = whatitem("wear"))=='\33') return;
if (i != '.')
{
if (i=='*') showwear(); else
switch(iven[i-'a'])
{
case 0: ydhi(i); return;
case OLEATHER: case OCHAIN: case OPLATE: case OSTUDLEATHER:
case ORING: case OSPLINT: case OPLATEARMOR: case OSSPLATE:
if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
c[WEAR]=i-'a'; bottomline(); return;
case OSHIELD: if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
c[SHIELD] = i-'a'; bottomline(); return;
default: lprcat("\nYou can't wear that!");
};
}
}
}

/*
function to drop an object
*/
dropobj()
{
register int i;
register char *p;
long amt;
p = &item[playerx][playery];
while (1)
{
if ((i = whatitem("drop"))=='\33') return;
if (i=='*') showstr(); else
{
if (i=='.') /* drop some gold */
{
if (*p) { lprcat("\nThere's something here already!"); return; }
lprcat("\n\n");
cl_dn(1,23);
lprcat("How much gold do you drop? ");
if ((amt=readnum((long)c[GOLD])) == 0) return;
if (amt>c[GOLD])
{ lprcat("\nYou don't have that much!"); return; }
if (amt<=32767)
{ *p=OGOLDPILE; i=amt; }
else if (amt<=327670L)
{ *p=ODGOLD; i=amt/10; amt = 10*i; }
else if (amt<=3276700L)
{ *p=OMAXGOLD; i=amt/100; amt = 100*i; }
else if (amt<=32767000L)
{ *p=OKGOLD; i=amt/1000; amt = 1000*i; }
else
{ *p=OKGOLD; i=32767; amt = 32767000L; }
c[GOLD] -= amt;
lprintf("You drop %d gold pieces",(long)amt);
iarg[playerx][playery]=i; bottomgold();
know[playerx][playery]=0; dropflag=1; return;
}
drop_object(i-'a');
return;
}
}
}

/*
* readscr() Subroutine to read a scroll one is carrying
*/
readscr()
{
register int i;
while (1)
{
if ((i = whatitem("read"))=='\33') return;
if (i != '.')
{
if (i=='*') showread(); else
{
if (iven[i-'a']==OSCROLL) { read_scroll(ivenarg[i-'a']); iven[i-'a']=0; return; }
if (iven[i-'a']==OBOOK) { readbook(ivenarg[i-'a']); iven[i-'a']=0; return; }
if (iven[i-'a']==0) { ydhi(i); return; }
lprcat("\nThere's nothing on it to read"); return;
}
}
}
}

/*
* subroutine to eat a cookie one is carrying
*/
eatcookie()
{
register int i;
char *p;
while (1)
{
if ((i = whatitem("eat"))=='\33') return;
if (i != '.')
if (i=='*') showeat(); else
{
if (iven[i-'a']==OCOOKIE)
{
lprcat("\nThe cookie was delicious.");
iven[i-'a']=0;
if (!c[BLINDCOUNT])
{
if (p=fortune(fortfile))
{
lprcat(" Inside you find a scrap of paper that says:\n");
lprcat(p);
}
}
return;
}
if (iven[i-'a']==0) { ydhi(i); return; }
lprcat("\nYou can't eat that!"); return;
}
}
}

/*
* subroutine to quaff a potion one is carrying
*/
quaff()
{
register int i;
while (1)
{
if ((i = whatitem("quaff"))=='\33') return;
if (i != '.')
{
if (i=='*') showquaff(); else
{
if (iven[i-'a']==OPOTION) { quaffpotion(ivenarg[i-'a']); iven[i-'a']=0; return; }
if (iven[i-'a']==0) { ydhi(i); return; }
lprcat("\nYou wouldn't want to quaff that, would you? "); return;
}
}
}
}

/*
function to ask what player wants to do
*/
whatitem(str)
char *str;
{
int i;
cursors(); lprintf("\nWhat do you want to %s [* for all] ? ",str);
i=0; while (i>'z' || (i<'a' && i!='*' && i!='\33' && i!='.')) i=getchar();
if (i=='\33') lprcat(" aborted");
return(i);
}

/*
subroutine to get a number from the player
and allow * to mean return amt, else return the number entered
*/
unsigned long readnum(mx)
long mx;
{
register int i;
register unsigned long amt=0;
sncbr();
if ((i=getchar()) == '*') amt = mx; /* allow him to say * for all gold */
else
while (i != '\n')
{
if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
if ((i <= '9') && (i >= '0') && (amt<999999999))
amt = amt*10+i-'0';
i = getchar();
}
scbr(); return(amt);
}

#ifdef HIDEBYLINK
/*
* routine to zero every byte in a string
*/
szero(str)
register char *str;
{
while (*str)
*str++ = 0;
}
#endif HIDEBYLINK

#ifdef TIMECHECK
/*
* routine to check the time of day and return 1 if its during work hours
* checks the file ".holidays" for forms like "mmm dd comment..."
*/
int playable()
{
long g_time,time();
int hour,day,year;
char *date,*month,*p;

time(&g_time); /* get the time and date */
date = ctime(&g_time); /* format: Fri Jul 4 00:27:56 EDT 1986 */
year = atoi(date+20);
hour = (date[11]-'0')*10 + date[12]-'0';
day = (date[8]!=' ') ? ((date[8]-'0')*10 + date[9]-'0') : (date[9]-'0');
month = date+4; date[7]=0; /* point to and NULL terminate month */

if (((hour>=8 && hour<17)) /* 8AM - 5PM */
&& strncmp("Sat",date,3)!=0 /* not a Saturday */
&& strncmp("Sun",date,3)!=0) /* not a Sunday */
{
/* now check for a .holidays datafile */
lflush();
if (lopen(holifile) >= 0)
for ( ; ; )
{
if ((p=lgetw())==0) break;
if (strlen(p)<6) continue;
if ((strncmp(p,month,3)==0) && (day==atoi(p+4)) && (year==atoi(p+7)))
return(0); /* a holiday */
}
lrclose(); lcreat((char*)0);
return(1);
}
return(0);
}
#endif TIMECHECK
SHAR_EOF
if test 25702 -ne "`wc -c < 'main.c'`"
then
echo shar: error transmitting "'main.c'" '(should have been 25702 characters)'
fi
fi
echo shar: extracting "'.larnopts'" '(253 characters)'
if test -f '.larnopts'
then
echo shar: will not over-write existing file "'.larnopts'"
else
cat << \SHAR_EOF > '.larnopts'
process-name: "Winnie-the-Pooh"
enable-checkpointing
bold-objects
male
play-day-play
no-introduction
name: "King of the Realm"
monster: "abominable snowman"
monster: "tooth fairy"
monster: "Yaccerous Lexicous"
savefile: "/save/noah/games/Larn12.0.sav"

SHAR_EOF
if test 253 -ne "`wc -c < '.larnopts'`"
then
echo shar: error transmitting "'.larnopts'" '(should have been 253 characters)'
fi
fi
exit 0
# End of shell archive

0 new messages