noah@condor.UUCP (Noah Morgan) (08/08/86)
*** 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