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

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

Submitted-by: routley@tle.ENET.DEC.COM (Kevin Routley)
Posting-number: Volume 12, Issue 64
Archive-name: larn2/Part11
Supersedes: larn: Volume 11, Issue 84-94
Environment: Unix, VMS, MS-DOS, OS/2, termcap



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 11 (of 12)."
# Contents:  larn123.fix makefile.pc nansi.doc regen.c signal.c
#   spheres.c tgetstr.c vms.c
# Wrapped by billr@saab on Tue Apr 23 13:50:37 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'larn123.fix' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'larn123.fix'\"
else
echo shar: Extracting \"'larn123.fix'\" \(7408 characters\)
sed "s/^X//" >'larn123.fix' <<'END_OF_FILE'
XThis is a list of the fixes and enhancements made to create Larn V12.3 from
XLarn 12.2.  SPOILER ALERT!
X
X1. The player's position is now marked with an ampersand, instead of just with
X   the cursor.
X
X2. The 'G' command ("give the stairs a kick") has been removed.  Since you can
X   tell the stairs apart (as opposed to the original Larn 12.0), this command
X   doesn't make sense anymore.
X
X3. The 'V' command has been removed and its information incorporated into the
X   'v' command.
X
X4. An idea from Ultra-Larn: when the player enters the 5th level branch of the
X   bank after teleporting, the '?' in the level display is changed to a '5'.
X
X5. Larn -? can be used to print command line arguments.
X
X6. The player is no longer positioned near the shaft of the volcano when
X   climbing down to the first volcano level.
X
X7. A couple of pauses were eliminated, making some actions very fast now.
X
X8. The player can no longer escape punishment by donating more gold then he
X   possesses when praying at the altar.
X
X9. When performing an action and doing an inventory list, a character typed at
X   the "press space for more" prompt is taken as the inventory item to select.
X   That is, if you say 'q' for quaff, '*' to see all the potions you can quaff,
X   Larn used to require that you type a space before you could select a potion,
X   causing the list to disappear.  You can now select an item in the list while
X   the list is displayed.  You can also use Escape and Return in place of a
X   space.
X
X10. The spells/potions/scrolls inventory ('I' command) are now sorted.
X
X11. The '/' command has been added, to allow the user to identify objects.
X    You can choose to either type a character or move the cursor around to
X    select a character to identify (a la Hack).  The only limitation is that
X    characters that have several objects (weapons, gems, dragons, etc) display
X    all the matching object names.
X
X12. The potion of gold detection has been changed into the potion of object
X    detection.  It will find scrolls, books, potions, weapons, armor, and
X    artifacts.  If you have an old savefile, all gold detection potions get
X    turned into object detection potions.
X
X13. It is now possible to find rings of cleverness in the dungeon.
X
X14. It is now possible for killed monsters to drop splint mail, battle axes,
X    cookies, and rings of cleverness.
X
X15. Source cleanup, reduction in the size of the executable and the memory
X    required, performance improvements.
X
X16. Fix problems with positioning the player when entering or leaving the
X    dungeon.  You will no longer find yourself on the opposite side of the
X    town level when leaving the dungeon.  You will no longer be able to enter
X    the dungeon on top of a monster.
X
X17. Prevented monsters from moving into the dungeon entrance, causing them to
X    be destroyed when the player exits the dungeon.  The top dungeon level now
X    has the dungeon entrance character where there used to be a space.
X
X18. If you are standing on a chest and try and open it, you will no longer pick
X    it up immediately if you have auto-pickup on.
X
X19. Added the capability to add comments to the options file.
X
X20. Fixed the bug where a missing options file prevented anything from being
X    displayed.
X
X21. There is now a visible repeat count when greater than 10 (a la Hack).  You
X    can also edit the repeat count.
X
X22. The 'm' command has been added to move onto an object without picking it
X    up (a la Hack).
X
X23. Fixed a problem where the a) item in the inventory couldn't be dulled.
X
X25. Allow a space between '-o' and the option filename.
X
X26. Fix possible errors when looking at the inventory.
X
X27. Prevent the player from changing levels into a level from the maze file with
X    a space that had no means of exit.
X
X================================================================================
X
XThis is a list of the fixes and enhancements made to create Larn V12.2 from
XLarn 12.0.  SPOILER ALERT!
X
XChanges made to create version 12.2 from 12.1:
X
X1.  Add messages to improve feedback to the user.
X
X2.  Improved screen drawing performance again.
X
X3.  Flying monsters (bats, floating eyes) are no longer affected by traps.
X
X4.  Added HACK-like objects, with 'original-objects' option.
X
X5.  Added 'bold-objects' option.
X
X6.  Fixed a bug where the game would apparently 'hang' for a long period of
X    time, especially just after killing a monster with a missile spell.
X
X7.  Prevented invulnerability when doing VPR on a throne or altar.
X
X8.  Scrolls of pulverization now have the same affect when directed against
X    an altar or fountain as they did directed against a throne.  VPR spell
X    cause a waterlord to appear when used near a fountain.
X
X9.  Added the '@' command and 'auto-pickup' option.
X
X10. Added 'prompt-on-objects' option.
X
X11. Improved monster movement performance again.
X
X12. You can now weild '-' to unweild your weapon.
X
X13. Waterlords can now be found in the dungeon, not just when washing at a
X    fountain.
X
X14. The Eye of Larn can now be sold in the Trading Post.
X
X15. Spells can now bounce off mirrors at an angle.
X
X
XChanges made to create version 12.1 from 12.0:
X
X1.  When drinking at a fountain, "improved sight" caused the "see invisible"
X    potion to be known by the player.  The player must now identify the potion
X    in the usual manner.
X
X2.  Falling through a pit told you the damage you received, but falling through
X    a trap door did not.  Made trap doors act the same as pits.
X
X3.  If you dropped a ring of dexterity/strength/cleverness that had been dulled
X    to a negative amount, the corresponding stat was permanently increased.  No
X    longer.
X
X4.  The potion of monster location would show invisible monsters as the floor
X    character on new levels.  Now prevented.
X
X5.  Selling all your gems at the bank could destroy items in your inventory.
X
X6.  Monster creation was being allowed on closed doors.  This was particularly
X    a problem with treasure rooms, since it meant that a monster much too
X    powerful for the player to handle was loose in the maze.  Monsters cannot
X    now be created on closed doors.
X
X7.  When entering a number (when entering gold amounts) you could not use the
X    backspace key to delete digits.  Fixed.
X
X8.  To make it more convenient when selling items in the Larn Trading Post, a
X    display of those items in the players inventory that can be sold has been
X    added.
X
X9.  Performance of the display has been improved slightly.
X
X10. Monster movement has been improved for large numbers of monsters.  It is
X    somewhat better on PC's, even with aggravation.
X
X11. I have added new mazes to LARN.MAZ.
X
X12. A Rogue-like command mode has been added, and is the default.  The
X    version 12.0 prompting mode has been preserved for those who like it,
X    accessible via a command line option.  Command letters have been added
X    to provide the ability to perform all the same actions as the prompt mode.
X    The help file and command line help have been updated.  When in command
X    mode, the player will automatically pick up objects, and can read, quaff,
X    eat, look at, and pick up objects that you are standing on.
X
X    In order to implement the new commands, the A and D commands from version
X    12.0 have been changed.  They are now ^A and I.  For consistancy, to see
X    the list of known spells at the spell prompt, 'I' also shows all known
X    spells.
END_OF_FILE
if test 7408 -ne `wc -c <'larn123.fix'`; then
    echo shar: \"'larn123.fix'\" unpacked with wrong size!
fi
# end of 'larn123.fix'
fi
if test -f 'makefile.pc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile.pc'\"
else
echo shar: Extracting \"'makefile.pc'\" \(6666 characters\)
sed "s/^X//" >'makefile.pc' <<'END_OF_FILE'
X############################################################################
X#
X# A list of available compile-time defines:
X#
X#   BSD           - use BSD specific features (mostly timer and signal stuff)
X#   BSD4.1        - use BSD4.1 to avoid some 4.2 dependencies (must be used with
X#                   BSD above; do not mix with SYSV)
X#   DECRainbow    - DEC Rainbow specific display code.
X#   DOCHECKPOINTS - if not defined, checkpoint files are periodically written
X#                   by the larn process (no forking) if enabled in the .larnopts
X#                   description file.  Checkpointing is handy on an unreliable
X#                   system, but takes CPU. Inclusion of DOCHECKPOINTS will cause
X#                   fork()ing to perform the checkpoints (again if enabled in
X#                   the .larnopts file).  This usually avoids pauses in larn
X#                   while the checkpointing is being done (on large machines).
X#   EXTRA         - incorporates code to gather additional performance stats
X#   FLUSHNO=#     - Set the input queue excess flushing threshold (default 5)
X#   HIDEBYLINK    - if defined, the program attempts to hide from ps
X#   MACRORND      - Define to use macro version of rnd() and rund() (fast & big)
X#   MAIL          - system supports mail messages (see bill.c).  Not useful on
X#                   non-networked machines.
X#   MSDOS         - MS-DOS specific code.
X#   OS2LARN       - OS/2 Specific code.  MSDOS must be defined.
X#   NONAP         - causes napms() to return immediately instead of delaying
X#                   n milliseconds.  This define may be needed on some systems
X#                   if the nap stuff does not work correctly (possible hang).
X#                   nap() is primarilly used to delay for effect when casting
X#                   missile type spells.
X#   NOVARARGS     - Define for systems that don't have varargs (a default
X#                   varargs will be used).
X#   RFCMAIL       - mail messages are RFC822 conformant.  Must be used with
X#                   MAIL above.
X#   SAVEINHOME    - put save files in users HOME instead of LARNHOME (default)
X#   SYSV          - use system III/V (instead of V7) type ioctl calls
X#   TIMECHECK     - incorporates code to disable play during working hours (8-5)
X#   UIDSCORE      - Define to use user id's to manage scoreboard.  Leaving this
X#                   out will cause player id's from the file ".playerids" to
X#                   be used instead.  (.playerids is created upon demand).
X#                   Only one entry per id # is allowed in each scoreboard
X#                   (winning & non-winning).
X#   VT100         - Compile for using vt100 family of terminals.  Omission of
X#                   this define will cause larn to use termcap.
X#   WIZID=xxx     - this is the userid (or playerid) of the wizard.  Default is
X#                   zero (superuser), which disables all wizard functions.
X#                   Players must have this userid (or playerid) in order to
X#                   become the non-scoring wizard player.  Definition of WIZID
X#                   to non-zero will enable the special wizard debugging
X#                   commands.  For root to become wizard, use WIZID= -1.
X#
X############################################################################
X#
X# Configuration options
X#  LARNHOME is the directory where the larn data files will be installed.
X#  BINDIR is the directory where the larn binary will be installed.
X#
XLARNHOME = #    The current directory unless changed in larn.opt
XBINDIR = c:\games
XCC= tcc
XOPTIONS = -DSYSV -DMSDOS -DNOVARARGS
X
X########################################################################
X#
XOBJS= action.obj \
X    bill.obj \
X    config.obj \
X    create.obj \
X    data.obj   \
X    diag.obj   \
X    display.obj \
X    fgetlr.obj  \
X    fortune.obj \
X    global.obj  \
X    help.obj    \
X    iventory.obj\
X    io.obj      \
X    main.obj    \
X    monster.obj \
X    moreobj.obj \
X    movem.obj   \
X    msdos.obj   \
X    nap.obj     \
X    object.obj  \
X    regen.obj   \
X    savelev.obj \
X    scores.obj  \
X    signal.obj  \
X    spheres.obj \
X    spells.obj  \
X    store.obj   \
X    tgetent.obj \
X    tgetstr.obj \
X    tgoto.obj   \
X    tok.obj     \
X    tputs.obj   \
X    vms.obj
X
XDOTFILES= larn.hlp larn.maz larn.ftn # larn.opt
X
X# merge literal strings
X# large memory model
X# include file directory pointer
X# use extended memory during compile
X#
XFLAGS= $(OPTIONS) -d -ml -I\TCPP\INCLUDE -Qx
X
X# case-sensitive link, no map file
X#
Xlarn: larn123.exe
Xlarn123.exe: $(OBJS)
X    tlink \TCPP\LIB\C0L @tlink.rsp, larn123,,\TCPP\LIB\EMU \TCPP\LIB\MATHL \TCPP\LIB\CL /c /x
X
X.c.obj:
X    $(CC) -c $(FLAGS) $<
X
Xaction.obj:   action.c   header.h larndefs.h monsters.h objects.h player.h
Xbill.obj:     bill.c     header.h larndefs.h
Xconfig.obj:   config.c   header.h larndefs.h
Xcreate.obj:   create.c   header.h larndefs.h monsters.h objects.h player.h
Xdata.obj:     data.c     header.h            monsters.h objects.h
Xdiag.obj:     diag.c     header.h larndefs.h monsters.h objects.h player.h
Xdisplay.obj:  display.c  header.h larndefs.h            objects.h player.h
Xfgetlr.obj:   fgetlr.c
Xfortune.obj:  fortune.c  header.h
Xglobal.obj:   global.c   header.h larndefs.h monsters.h objects.h player.h
Xhelp.obj:     help.c     header.h larndefs.h
Xiventory.obj: iventory.c header.h larndefs.h            objects.h player.h
Xio.obj:       io.c       header.h larndefs.h
Xmain.obj:     main.c     header.h larndefs.h monsters.h objects.h player.h patchlev.h
Xmonster.obj:  monster.c  header.h larndefs.h monsters.h objects.h player.h
Xmoreobj.obj:  moreobj.c  header.h larndefs.h monsters.h objects.h player.h
Xmovem.obj:    movem.c    header.h larndefs.h monsters.h objects.h player.h
Xmsdos.obj:    msdos.c    header.h larndefs.h
Xnap.obj:      nap.c
Xobject.obj:   object.c   header.h larndefs.h monsters.h objects.h player.h
Xregen.obj:    regen.c    header.h larndefs.h monsters.h           player.h
Xsavelev.obj:  savelev.c  header.h larndefs.h
Xscores.obj:   scores.c   header.h larndefs.h monsters.h objects.h player.h
Xsignal.obj:   signal.c   header.h larndefs.h
Xspheres.obj:  spheres.c  header.h larndefs.h monsters.h objects.h player.h
Xspells.obj:   spells.c   header.h larndefs.h monsters.h objects.h player.h
Xstore.obj:    store.c    header.h larndefs.h            objects.h player.h
Xtgetent.obj:  tgetent.c
Xtgetstr.obj:  tgetstr.c
Xtgoto.obj:    tgoto.c
Xtok.obj:      tok.c      header.h larndefs.h monsters.h objects.h player.h
Xtputs.obj:    tputs.c
Xvms.obj:      vms.c      header.h larndefs.h
X
Xinstall:
X    exepack larn123.exe $(BINDIR)\larn123.exe
X    exemod $(BINDIR)\larn123.exe /max 1
END_OF_FILE
if test 6666 -ne `wc -c <'makefile.pc'`; then
    echo shar: \"'makefile.pc'\" unpacked with wrong size!
fi
# end of 'makefile.pc'
fi
if test -f 'nansi.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nansi.doc'\"
else
echo shar: Extracting \"'nansi.doc'\" \(6967 characters\)
sed "s/^X//" >'nansi.doc' <<'END_OF_FILE'
XSYNOPSIS
X	Include in \config.sys the line
X		device=nansi.sys
X
XDESCRIPTION
X	Nansi.sys is a console driver which understands ANSI control
X	sequences. It has several advantages over ANSI.SYS (the driver
X	supplied with DOS):
X	1. It supports new escape sequences (see below).
X	2. It provides MUCH faster output under certain conditions.
X	3. It supports the 43-line mode of the EGA.
X	4. The darned bell is now 1/4 second instead of 1/2 second long.
X
X	What a console driver does:
X	When you, for example, type
X		C:> type foo.txt
X	COMMAND.COM opens the file foo.txt, reads it, and writes it to
X	the console driver, which puts it up on the screen.
X
X	Both ansi.sys and nansi.sys use IBM Video BIOS to control the screen.
X	However, nansi.sys bypasses BIOS if the screen is in a text mode; this
X	allows much faster operation under certain conditions.
X
X	While putting text up on the screen, (n)ansi.sys keeps a lookout for
X	the escape character (chr(27), known as ESC); this character signals
X	the start of a terminal control sequence.
X	Terminal control sequences follow the format
X		ESC [ param; param; ...; param cmd
X	where
X		ESC	is the escape character chr$(27).
X		[	is the left bracket character.
X		param	is an ASCII decimal number, or a string in quotes.
X		cmd	is a case-specific letter identifying the command.
X	Usually, zero, one, or two parameters are given.  If parameters
X	are omitted, they usually default to 1; however, some commands
X	(KKR and DKOCT) treat the no-parameter case specially.
X	Spaces are not allowed between parameters.
X
X	For example, both ESC[1;1H and ESC[H send the cursor to the home
X	position (1,1), which is the upper left.
X
X	Either single or double quotes may be used to quote a string.
X	Each character inside a quoted string is equivalent to one numeric
X	parameter.  Quoted strings are normally used only for the Keyboard
X	Key Reassignment command.
X
XControl Sequences
X	The following table lists the sequences understood by nansi.sys.
X	Differences between nansi.sys and the standard ansi.sys are marked
X	with a vertical bar (|).
X
XCursor Positioning
XShort	Long name		Format		Notes
XCUP	cursor position		ESC[y;xH	Sets cursor position.
XHVP	cursor position		ESC[y;xf	Same as CUP; not recommended.
XCUU	cursor up		ESC[nA		n = # of lines to move
XCUD	cursor down		ESC[nB
XCUF	cursor forward		ESC[nC		n = # of columns to move
XCUB	cursor backward		ESC[nD
XDSR	Device Status, Report!	ESC[6n		Find out cursor position.
XCPR	Cursor Position report	ESC[y;xR	Response to DSR, as if typed.
XSCP	Save Cursor Position	ESC[s		Not nestable.
XRCP	Restore Cursor Position ESC[u
X
XEditing
XED	Erase in Display	ESC[2J	Clears screen.
XEL	Erase in Line		ESC[K	Clears to end of line.
XIL  |	Insert Lines		ESC[nL	Inserts n blank lines at cursor line.
XDL  |	Delete Lines		ESC[nM	Deletes n lines including cursor line.
XICH |	Insert Characters	ESC[n@	Inserts n blank chars at cursor.
XDCH |	Delete Characters	ESC[nP	Deletes n chars including cursor char.
X
X
XMode-Setting
XSGR	Set Graphics Rendition	ESC[n;n;...nm	See character attribute table.
XSM	Set Mode		ESC[=nh		See screen mode table.
XRM	Reset Mode		ESC[=nl		See screen mode table.
XIBMKKR	Keyboard Key Reass.	ESC["string"p
X	The first char of the string gives the key to redefine; the rest
X	of the string is the key's new value.
X	To specify unprintable chars, give the ASCII value of the char
X	outside of quotes, as a normal parameter.
X	IBM function keys are two byte strings; see the IBM Basic manual.
X	For instance, ESC[0;";dir a:";13;p redefines function key 1 to
X	have the value "dir a:" followed by the ENTER key.
X      | If no parameters given, all keys are reset to their default values.
X
XDKOCT | Output char translate	ESC[n;ny
X      | When first char is encountered in output request, it is replaced with
X      | the second char.  This might be useful for previewing text before
X      | sending it to a printer with a funny print wheel.
X      | If no parameters are given, all chars are reset to normal.
X
X
XCharacter Attributes
X	The Set Graphics Rendition command is used to select foreground
X	and background colors or attributes.
X	When you use multiple parameters, they are executed in sequence, and
X	the effects are cumulative.
X	   Attrib code		Value
X		0		All attributes off (normal white on black)
X		1		Bold
X		4		Underline
X		5		Blink
X		7		Reverse Video
X		8		Invisible (but why?)
X		30-37		foregnd blk/red/grn/yel/blu/magenta/cyan/white
X		40-47		background
X
XScreen Modes
X	The IBM BIOS supports several video modes; the codes given in the
X	BIOS documentation are used as parameters to the Set Mode command.
X      | (In bitmap modes, the cursor is simulated with a small blob (^V).)
X	    Mode Code		Value
X		0		text 40x25 Black & White
X		1		text 40x25 Color
X		2		text 80x25 Black & White
X		3		text 80x25 Color
X		4		bitmap 320x200 4 bits/pixel
X		5		bitmap 320x200 1 bit/pixel
X		6		bitmap 640x200 1 bit/pixel
X		7		(cursor wrap kludge)
X		13 (EGA)	bitmap 320x200 4 bits/pixel ?
X		14 (EGA)	bitmap 640x200 4 bits/pixel
X		16 (EGA)	bitmap 640x350 4 bits/pixel
X	Mode 7 is an unfortunate kludge; Setting mode 7 tells the cursor
X	to wrap around to the next line when it passes the end of a line;
X	Resetting mode 7 tells the cursor to not wrap, but rather stay put.
X      | If your computer has the Enhanced Graphics Adaptor, modes between
X      | 8 and 15 are also supported; see the EGA BIOS for info.
X      | The EGA also lets you use a shorter character cell in text modes
X      | in order to squeeze 43 lines of text out of the 25-line text modes.
X      | To enter 43 line mode, set the desired 25-line text mode (0 to 3),
X      | then Set Mode 43.  For instance: ESC[=3h ESC[=43h.
X      | To exit 43 line mode, set the desired 25-line text mode again.
X      | Nansi.sys ignores mode 43 unless there is an EGA on your computer.
X
XFaster Output
X      | Any program that sets the console to RAW mode, and buffers its
X      | output properly, can achieve extremely high screen update speeds in
X      | return for giving up the special functions of the keys ^C, ^S, and ^P.
X      | See IOCTL in the MS-DOS 3.x Technical Reference for more info.
X	Also, a small improvement in speed may be noticed with some
X	programs that use the DOS console in normal mode, as this driver
X	efficiently implements the (standard but undocumented) INT 29h
X	most-favored-device putchar used by DOS.
X
XBUGS
X	Insert and delete character do not work in graphics modes.
X	Graphics mode writing is slow.
X	The simulated cursor in graphics mode slows down single-char
X	writes by a factor of 3; it should be disable-able.
X	Does not support erase-to-end-of-screen and other useful functions.
X
XVersion
X	This version, 2.2, created February 1986.  Problems should
X	be reported to Daniel Kegel, 1-60 CIT, Pasadena, CA 91126
X	(or, after June 1986, 2648 169th Ave SE, Bellevue, Wa. 98008).
X	Your suggestions for improvement would be most welcome.
X
XNOTE
X	This program may be distributed for educational and personal use
X	only.  Commercial use is verboten; get in touch with the author.
END_OF_FILE
if test 6967 -ne `wc -c <'nansi.doc'`; then
    echo shar: \"'nansi.doc'\" unpacked with wrong size!
fi
# end of 'nansi.doc'
fi
if test -f 'regen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'regen.c'\"
else
echo shar: Extracting \"'regen.c'\" \(3917 characters\)
sed "s/^X//" >'regen.c' <<'END_OF_FILE'
X/* regen.c */
X#include "header.h"
X#include "larndefs.h"
X#include "monsters.h"
X#include "player.h"
X
X/*
X    regen()
X
X    subroutine to regenerate player hp and spells
X */
Xregen()
X    {
X    register int i,flag;
X    register long *d;
X    d = c;
X#ifdef EXTRA
X    d[MOVESMADE]++;
X#endif
X    if (d[TIMESTOP])  { if(--d[TIMESTOP]<=0) bottomline();  return; }   /* for stop time spell */
X    flag=0;
X
X    if (d[STRENGTH]<3)  { d[STRENGTH]=3; flag=1; }
X    if (d[HP] != d[HPMAX])
X        if (d[REGENCOUNTER]-- <= 0)     /*  regenerate hit points   */
X            {
X            d[REGENCOUNTER] = 22 + (d[HARDGAME]<<1) - d[LEVEL];
X            if ((d[HP] += d[REGEN]) > d[HPMAX])  d[HP] = d[HPMAX];
X            bottomhp();
X            }
X
X    if (d[SPELLS] < d[SPELLMAX])        /*  regenerate spells   */
X        if (d[ECOUNTER]-- <= 0)
X            {
X            d[ECOUNTER] = 100+4*(d[HARDGAME]-d[LEVEL]-d[ENERGY]);
X            d[SPELLS]++;    bottomspell();
X            }
X
X    if (d[HERO])            if (--d[HERO]<=0) { for (i=0; i<6; i++) d[i] -= 10; flag=1; }
X    if (d[ALTPRO])          if (--d[ALTPRO]<=0)         { d[MOREDEFENSES]-=3; flag=1; }
X    if (d[PROTECTIONTIME])  if (--d[PROTECTIONTIME]<=0) { d[MOREDEFENSES]-=2; flag=1; }
X    if (d[DEXCOUNT])        if (--d[DEXCOUNT]<=0)       { d[DEXTERITY]-=3; flag=1; }
X    if (d[STRCOUNT])        if (--d[STRCOUNT]<=0)       { d[STREXTRA]-=3; flag=1; }
X    if (d[BLINDCOUNT])      if (--d[BLINDCOUNT]<=0)     { cursors();  lprcat("\nThe blindness lifts  "); beep(); }
X    if (d[CONFUSE])         if (--d[CONFUSE]<=0) { cursors();  lprcat("\nYou regain your senses"); beep(); }
X    if (d[GIANTSTR])        if (--d[GIANTSTR]<=0) { d[STREXTRA] -= 20; flag=1; }
X    if (d[CHARMCOUNT])      if ((--d[CHARMCOUNT]) <= 0) flag=1;
X    if (d[INVISIBILITY])    if ((--d[INVISIBILITY]) <= 0) flag=1;
X    if (d[CANCELLATION])    if ((--d[CANCELLATION]) <= 0) flag=1;
X    if (d[WTW])             if ((--d[WTW]) <= 0) flag=1;
X    if (d[HASTESELF])       if ((--d[HASTESELF]) <= 0) flag=1;
X    if (d[AGGRAVATE])       --d[AGGRAVATE]; 
X    if (d[SCAREMONST])      if ((--d[SCAREMONST]) <= 0) flag=1; 
X    if (d[STEALTH])         if ((--d[STEALTH]) <= 0) flag=1; 
X    if (d[AWARENESS])       --d[AWARENESS];
X    if (d[HOLDMONST])       if ((--d[HOLDMONST]) <= 0) flag=1;
X    if (d[HASTEMONST])      --d[HASTEMONST];
X    if (d[FIRERESISTANCE])  if ((--d[FIRERESISTANCE]) <= 0) flag=1;
X    if (d[GLOBE])           if (--d[GLOBE]<=0) { d[MOREDEFENSES]-=10; flag=1; }
X    if (d[SPIRITPRO])       if (--d[SPIRITPRO] <= 0) flag=1;
X    if (d[UNDEADPRO])       if (--d[UNDEADPRO] <= 0) flag=1;
X    if (d[HALFDAM])         if (--d[HALFDAM]<=0)  { cursors();  lprcat("\nYou now feel better "); beep(); }
X    if (d[SEEINVISIBLE])
X      if (--d[SEEINVISIBLE]<=0)
X        { monstnamelist[INVISIBLESTALKER] = floorc;
X          if (!d[BLINDCOUNT]) {
X            cursors();
X            lprcat("\nYou feel your vision return to normal");
X            beep();
X          }
X        }
X    if (d[ITCHING])
X        {
X        if (d[ITCHING]>1)
X            if ((d[WEAR]!= -1) || (d[SHIELD]!= -1))
X                if (rnd(100)<50)
X                    {
X                    d[WEAR]=d[SHIELD]= -1; cursors();
X                    lprcat("\nThe hysteria of itching forces you to remove your armor!"); 
X                    beep(); recalc();  bottomline();
X                    }
X        if (--d[ITCHING]<=0) { cursors();  lprcat("\nYou now feel the irritation subside!"); beep(); }
X        }
X    if (d[CLUMSINESS])
X        {
X        if (d[WIELD] != -1)
X            if (d[CLUMSINESS]>1)
X              if (item[playerx][playery]==0)    /* only if nothing there */
X                if (rnd(100)<33) /* drop your weapon due to clumsiness */
X                    drop_object((int)d[WIELD]);
X        if (--d[CLUMSINESS]<=0) { cursors();  lprcat("\nYou now feel less awkward!"); beep(); }
X        }
X    if (flag) bottomline();
X    }
END_OF_FILE
if test 3917 -ne `wc -c <'regen.c'`; then
    echo shar: \"'regen.c'\" unpacked with wrong size!
fi
# end of 'regen.c'
fi
if test -f 'signal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'signal.c'\"
else
echo shar: Extracting \"'signal.c'\" \(5478 characters\)
sed "s/^X//" >'signal.c' <<'END_OF_FILE'
X#include <signal.h>
X#include "header.h"
X#include "larndefs.h"
X
X#define BIT(a) (1<<((a)-1))
X
Xextern char savefilename[],wizard,predostuff,nosignal;
X
Xstatic s2choose()   /* text to be displayed if ^C during intro screen */
X    {
X    cursor(1,24); lprcat("Press "); setbold(); lprcat("return"); resetbold();
X    lprcat(" to continue: ");   lflush();
X    }
X
Xstatic void cntlc()    /* what to do for a ^C */
X    {
X    if (nosignal) return;   /* don't do anything if inhibited */
X# ifndef MSDOS
X    signal(SIGQUIT,SIG_IGN);
X# endif
X    signal(SIGINT,SIG_IGN);
X    quit(); if (predostuff==1) s2choose(); else showplayer();
X    lflush();
X# ifndef MSDOS
X    signal(SIGQUIT,cntlc);
X# endif
X    signal(SIGINT,cntlc);
X    }
X
X#ifndef MSDOS
X/*
X *  subroutine to save the game if a hangup signal
X */
Xstatic sgam()
X    {
X    savegame(savefilename);  wizard=1;  died(-257); /* hangup signal */
X    }
X#endif
X
X#ifdef SIGTSTP
Xstatic tstop() /* control Y */
X    {
X    if (nosignal)   return;  /* nothing if inhibited */
X    lcreat((char*)0);  clearvt100();    lflush();     signal(SIGTSTP,SIG_DFL);
X#ifdef SIGVTALRM
X    /* looks like BSD4.2 or higher - must clr mask for signal to take effect*/
X    sigsetmask(sigblock(0)& ~BIT(SIGTSTP));
X#endif
X    kill(getpid(),SIGTSTP);
X
X    setupvt100();  signal(SIGTSTP,tstop);
X    if (predostuff==1) s2choose(); else drawscreen();
X    showplayer();   lflush();
X    }
X#endif SIGTSTP
X
X/*
X *  subroutine to issue the needed signal traps  called from main()
X */
Xstatic void sigfpe()  { sigpanic(SIGFPE); }
X# ifndef MSDOS
Xstatic sigbus()  { sigpanic(SIGBUS); }
Xstatic sigill()  { sigpanic(SIGILL); }   static sigtrap() { sigpanic(SIGTRAP); }
Xstatic sigiot()  { sigpanic(SIGIOT); }   static sigemt()  { sigpanic(SIGEMT); }
Xstatic sigsegv() { sigpanic(SIGSEGV); }  static sigsys()  { sigpanic(SIGSYS); }
Xstatic sigpipe() { sigpanic(SIGPIPE); }  static sigterm() { sigpanic(SIGTERM); }
X# endif
X
Xsigsetup()
X    {
X    signal(SIGINT,  cntlc);
X    signal(SIGFPE,  sigfpe);
X# ifndef MSDOS
X    signal(SIGBUS,  sigbus);        signal(SIGQUIT, cntlc);
X    signal(SIGKILL, SIG_IGN);       signal(SIGHUP,  sgam);
X    signal(SIGILL,  sigill);        signal(SIGTRAP, sigtrap);
X    signal(SIGIOT,  sigiot);        signal(SIGEMT,  sigemt);
X    signal(SIGSEGV, sigsegv);       signal(SIGSYS,  sigsys);
X    signal(SIGPIPE, sigpipe);       signal(SIGTERM, sigterm);
X#ifdef SIGTSTP
X    signal(SIGTSTP,tstop);      signal(SIGSTOP,tstop);
X#endif SIGTSTP
X# endif
X    }
X
X#ifdef MSDOS
X#define NSIG 9
X#endif
X
X#ifdef VMS
X#define NSIG 16
X#endif
X
X#ifdef BSD  /* for BSD UNIX? */
X
Xstatic char *signame[NSIG] = { "",
X"SIGHUP",  /*   1    hangup */
X"SIGINT",  /*   2    interrupt */
X"SIGQUIT", /*   3    quit */
X"SIGILL",  /*   4    illegal instruction (not reset when caught) */
X"SIGTRAP", /*   5    trace trap (not reset when caught) */
X"SIGIOT",  /*   6    IOT instruction */
X"SIGEMT",  /*   7    EMT instruction */
X"SIGFPE",  /*   8    floating point exception */
X"SIGKILL", /*   9    kill (cannot be caught or ignored) */
X"SIGBUS",  /*   10   bus error */
X"SIGSEGV", /*   11   segmentation violation */
X"SIGSYS",  /*   12   bad argument to system call */
X"SIGPIPE", /*   13   write on a pipe with no one to read it */
X"SIGALRM", /*   14   alarm clock */
X"SIGTERM", /*   15   software termination signal from kill */
X"SIGURG",  /*   16   urgent condition on IO channel */
X"SIGSTOP", /*   17   sendable stop signal not from tty */
X"SIGTSTP", /*   18   stop signal from tty */
X"SIGCONT", /*   19   continue a stopped process */
X"SIGCHLD", /*   20   to parent on child stop or exit */
X"SIGTTIN", /*   21   to readers pgrp upon background tty read */
X"SIGTTOU", /*   22   like TTIN for output if (tp->t_local&LTOSTOP) */
X"SIGIO",   /*   23   input/output possible signal */
X"SIGXCPU", /*   24   exceeded CPU time limit */
X"SIGXFSZ", /*   25   exceeded file size limit */
X"SIGVTALRM",/*  26   virtual time alarm */
X"SIGPROF", /*   27   profiling time alarm */
X"","","","" };
X
X#else BSD   /* for system V? */
X
Xstatic char *signame[NSIG+1] = { "",
X"SIGHUP",  /*   1    hangup */
X"SIGINT",  /*   2    interrupt */
X"SIGQUIT", /*   3    quit */
X"SIGILL",  /*   4    illegal instruction (not reset when caught) */
X"SIGTRAP", /*   5    trace trap (not reset when caught) */
X"SIGIOT",  /*   6    IOT instruction */
X"SIGEMT",  /*   7    EMT instruction */
X# ifdef MSDOS
X"SIGFPE"}; /*   8    floating point exception */
X# else MSDOS
X"SIGFPE",  /*   8    floating point exception */
X"SIGKILL", /*   9    kill (cannot be caught or ignored) */
X"SIGBUS",  /*   10   bus error */
X"SIGSEGV", /*   11   segmentation violation */
X"SIGSYS",  /*   12   bad argument to system call */
X"SIGPIPE", /*   13   write on a pipe with no one to read it */
X"SIGALRM", /*   14   alarm clock */
X# ifdef VMS
X"SIGTERM"}; /*  15   software termination signal from kill */
X# else VMS
X"SIGTERM", /*   15   software termination signal from kill */
X"SIGUSR1",  /*  16   user defines signal 1 */
X"SIGUSR2", /*   17   user defines signal 2 */
X"SIGCLD",  /*   18   child death */
X"SIGPWR" };  /*   19   power fail */
X# endif VMS
X# endif MSDOS
X# endif BSD
X
X/*
X *  routine to process a fatal error signal
X */
Xstatic sigpanic(sig)
Xint sig;
X{
X    char buf[128];
X    signal(sig,SIG_DFL);
X    sprintf(buf,"\nLarn - Panic! Signal %d received [%s]",sig,signame[sig]);
X    write(2,buf,strlen(buf));  sleep(2);
X    sncbr();
X    savegame(savefilename); 
X# ifdef MSDOS
X    exit(1);
X# else
X    kill(getpid(),sig); /* this will terminate us */
X# endif
X}
END_OF_FILE
if test 5478 -ne `wc -c <'signal.c'`; then
    echo shar: \"'signal.c'\" unpacked with wrong size!
fi
# end of 'signal.c'
fi
if test -f 'spheres.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'spheres.c'\"
else
echo shar: Extracting \"'spheres.c'\" \(6636 characters\)
sed "s/^X//" >'spheres.c' <<'END_OF_FILE'
X/*
X  newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
X  rmsphere(x,y)      Function to delete a sphere of annihilation from list
X  sphboom(x,y)       Function to perform the effects of a sphere detonation
X  movsphere()        Function to look for and move spheres of annihilation
X*/
X#include "header.h"
X#include "larndefs.h"
X#include "monsters.h"
X#include "objects.h"
X#include "player.h"
X
X#define min(x,y) (((x)>(y))?(y):(x))
X#define max(x,y) (((x)>(y))?(x):(y))
X
X/*
X *  newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
X *      int x,y,dir,lifetime;
X *
X *  Enter with the coordinates of the sphere in x,y
X *    the direction (0-8 diroffx format) in dir, and the lifespan of the
X *    sphere in lifetime (in turns)
X *  Returns the number of spheres currently in existence
X */
Xnewsphere(x,y,dir,life)
X    int x,y,dir,life;
X    {
X    int m;
X    struct sphere *sp;
X    if (((sp=(struct sphere *)malloc(sizeof(struct sphere)))) == 0)
X        return(c[SPHCAST]); /* can't malloc, therefore failure */
X    if (dir>=9) dir=0;  /* no movement if direction not found */
X    if (level==0) vxy(&x,&y);   /* don't go out of bounds */
X    else
X        {
X        if (x<1) x=1;  if (x>=MAXX-1) x=MAXX-2;
X        if (y<1) y=1;  if (y>=MAXY-1) y=MAXY-2;
X        }
X    if ((m=mitem[x][y]) >= DEMONLORD+4) /* demons dispel spheres */
X        {
X        show1cell(x,y);     /* show the demon (ha ha) */
X        cursors(); lprintf("\nThe %s dispels the sphere!",monster[m].name);
X        beep(); rmsphere(x,y);  /* remove any spheres that are here */
X        return(c[SPHCAST]);
X        }
X    if (m==DISENCHANTRESS) /* disenchantress cancels spheres */
X        {
X        cursors(); lprintf("\nThe %s causes cancellation of the sphere!",monster[m].name); beep();
Xboom:   sphboom(x,y);   /* blow up stuff around sphere */
X        rmsphere(x,y);  /* remove any spheres that are here */
X        return(c[SPHCAST]);
X        }
X    if (c[CANCELLATION]) /* cancellation cancels spheres */
X        {
X        cursors(); lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!"); beep();
X        goto boom;
X        }
X    if (item[x][y]==OANNIHILATION) /* collision of spheres detonates spheres */
X        {
X        cursors(); lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!"); beep();
X        rmsphere(x,y);
X        goto boom;
X        }
X    if (playerx==x && playery==y) /* collision of sphere and player! */
X        {
X        cursors();
X        lprcat("\nYou have been enveloped by the zone of nothingness!\n");
X        beep(); rmsphere(x,y);  /* remove any spheres that are here */
X        nap(4000);  died(258);
X        }
X    item[x][y]=OANNIHILATION;  mitem[x][y]=0;  know[x][y]=1;
X    show1cell(x,y); /* show the new sphere */
X    sp->x=x;  sp->y=y;  sp->lev=level;  sp->dir=dir;  sp->lifetime=life;  sp->p=0;
X    if (spheres==0) spheres=sp; /* if first node in the sphere list */
X    else    /* add sphere to beginning of linked list */
X        {
X        sp->p = spheres;    spheres = sp;
X        }
X    return(++c[SPHCAST]);   /* one more sphere in the world */
X    }
X
X/*
X *  rmsphere(x,y)       Function to delete a sphere of annihilation from list
X *      int x,y;
X *
X *  Enter with the coordinates of the sphere (on current level)
X *  Returns the number of spheres currently in existence
X */
Xrmsphere(x,y)
X    int x,y;
X    {
X    register struct sphere *sp,*sp2=0;
X    for (sp=spheres; sp; sp2=sp,sp=sp->p)
X      if (level==sp->lev)   /* is sphere on this level? */
X        if ((x==sp->x) && (y==sp->y))   /* locate sphere at this location */
X            {
X            item[x][y]=mitem[x][y]=0;  know[x][y]=1;
X            show1cell(x,y); /* show the now missing sphere */
X            --c[SPHCAST];   
X            if (sp==spheres) { sp2=sp; spheres=sp->p; free((char*)sp2); }
X            else
X                { sp2->p = sp->p;  free((char*)sp); }
X            break;
X            }
X    return(c[SPHCAST]); /* return number of spheres in the world */
X    }
X
X/*
X *  sphboom(x,y)    Function to perform the effects of a sphere detonation
X *      int x,y;
X *
X *  Enter with the coordinates of the blast, Returns no value
X */
Xstatic sphboom(x,y)
X    int x,y;
X    {
X    register int i,j;
X    if (c[HOLDMONST]) c[HOLDMONST]=1;
X    if (c[CANCELLATION]) c[CANCELLATION]=1;
X    for (j=max(1,x-2); j<min(x+3,MAXX-1); j++)
X      for (i=max(1,y-2); i<min(y+3,MAXY-1); i++)
X        {
X        item[j][i]=mitem[j][i]=0;
X        show1cell(j,i);
X        if (playerx==j && playery==i)
X            {
X            cursors(); beep();
X            lprcat("\nYou were too close to the sphere!");
X            nap(3000);
X            died(283); /* player killed in explosion */
X            }
X        }
X    }
X
X/*
X *  movsphere()     Function to look for and move spheres of annihilation
X *
X *  This function works on the sphere linked list, first duplicating the list
X *  (the act of moving changes the list), then processing each sphere in order
X *  to move it.  They eat anything in their way, including stairs, volcanic
X *  shafts, potions, etc, except for upper level demons, who can dispel
X *  spheres.
X *  No value is returned.
X */
X#define SPHMAX 20   /* maximum number of spheres movsphere can handle */
Xmovsphere()
X    {
X    register int x,y,dir,len;
X    register struct sphere *sp,*sp2;
X    struct sphere sph[SPHMAX];
X
X    /* first duplicate sphere list */
X    for (sp=0,x=0,sp2=spheres; sp2; sp2=sp2->p) /* look through sphere list */
X      if (sp2->lev == level)    /* only if this level */
X        {
X        sph[x] = *sp2;  sph[x++].p = 0;  /* copy the struct */
X        if (x>1)  sph[x-2].p = &sph[x-1]; /* link pointers */
X        }
X    if (x) sp= sph; /* if any spheres, point to them */
X        else return;    /* no spheres */
X
X    for (sp=sph; sp; sp=sp->p)  /* look through sphere list */
X        {
X        x = sp->x;    y = sp->y;
X        if (item[x][y]!=OANNIHILATION) continue;    /* not really there */
X        if (--(sp->lifetime) < 0)   /* has sphere run out of gas? */
X            {
X            rmsphere(x,y); /* delete sphere */
X            continue;
X            }
X        switch(rnd((int)max(7,c[INTELLIGENCE]>>1))) /* time to move the sphere */
X            {
X            case 1:
X            case 2:     /* change direction to a random one */
X                        sp->dir = rnd(8);
X            default:    /* move in normal direction */
X                        dir = sp->dir;      len = sp->lifetime;
X                        rmsphere(x,y);
X                        newsphere(x+diroffx[dir],y+diroffy[dir],dir,len);
X            };
X        }
X    }
END_OF_FILE
if test 6636 -ne `wc -c <'spheres.c'`; then
    echo shar: \"'spheres.c'\" unpacked with wrong size!
fi
# end of 'spheres.c'
fi
if test -f 'tgetstr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tgetstr.c'\"
else
echo shar: Extracting \"'tgetstr.c'\" \(6825 characters\)
sed "s/^X//" >'tgetstr.c' <<'END_OF_FILE'
X/************************************************************************
X *                                  *
X *          Copyright (c) 1982, Fred Fish           *
X *              All Rights Reserved             *
X *                                  *
X *  This software and/or documentation is released for public   *
X *  distribution for personal, non-commercial use only.     *
X *  Limited rights to use, modify, and redistribute are hereby  *
X *  granted for non-commercial purposes, provided that all      *
X *  copyright notices remain intact and all changes are clearly *
X *  documented.  The author makes no warranty of any kind with  *
X *  respect to this product and explicitly disclaims any implied    *
X *  warranties of merchantability or fitness for any particular *
X *  purpose.                            *
X *                                  *
X ************************************************************************
X */
X
X
X/*
X *  LIBRARY FUNCTION
X *
X *  tgetstr   extract string capability from termcap entry
X *
X *  KEY WORDS
X *
X *  termcap
X *
X *  SYNOPSIS
X *
X *  char *tgetstr(id,area)
X *  char *id;
X *  char **area;
X *
X *  DESCRIPTION
X *
X *  Gets the string capability for <id>, placing it in
X *  the buffer at *area, and advancing *area to point
X *  to next available storage.
X *
X *  For example, if the following capabilities are
X *  in the termcap file:
X *
X *      ZZ=zzzz
X *      YY=yyyyyy
X *      WW=www
X *
X *  then successive calls using YY, ZZ, and WW will
X *  build the following buffer:
X *
X *      yyyyyy0zzzz0www0
X *
X *  The first call will return a pointer to yyyyyy, the
X *  second will return a pointer to zzzz and the third
X *  will return a pointer to www.  Note that each
X *  string is null terminated, as are all C strings.
X *
X *  Characters preceded by the carot character (\136)
X *  are mapped into the corresponding control character.
X *  For example, the two character sequence ^A becomes
X *  a single control-A (\001) character.
X *
X *  The escape character is the normal C backslash and
X *  the normal C escape sequences are recognized, along
X *  with a special sequence for the ASCII escape character
X *  (\033).  The recognized sequences are:
X *
X *      \E   =>  '\033'  (ASCII escape character)
X *      \b   =>  '\010'  (ASCII backspace character)
X *      \f   =>  '\014'  (ASCII form feed character)
X *      \n   =>  '\012'  (ASCII newline/linefeed char)
X *      \r   =>  '\015'  (ASCII carriage return char)
X *      \t   =>  '\011'  (ASCII tab character)
X *      \ddd =>  '\ddd'  (arbitrary ASCII digit)
X *      \x   =>  'x'     (ordinary ASCII character)
X *
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#ifdef VMS
X# define index strchr
X#endif
X#ifdef ULTRIX
X# include <strings.h>
X#endif
X
Xextern char *_tcpbuf;       /* Termcap entry buffer pointer */
X
X#ifdef MSDOS
X    extern char *index();
X#endif
X
X/*
X *  PSEUDO CODE
X *
X *  Begin tgetstr
X *      Initialize pointer to the termcap entry buffer.
X *      While there is a field to process
X *      Skip over the field separator character.
X *      If this is the entry we want then
X *          If the entry is not a string then
X *          Return NULL.
X *          Else
X *          Transfer string and rtn pointer.
X *          End if
X *      End if
X *      End while
X *      Return NULL
X *  End tgetstr
X *
X */
X
Xchar *tgetstr(id,area)
Xchar *id;
Xchar **area;
X{
X    char *bp;
X    char *decode();
X
X    bp = _tcpbuf;
X    while ((bp = index(bp,':')) != NULL) {
X    bp++;
X    if (*bp++ == id[0] && *bp != NULL && *bp++ == id[1]) {
X        if (*bp != NULL && *bp++ != '=') {
X        return(NULL);
X        } else {
X        return(decode(bp,area));
X        }
X    }
X    }
X    return(NULL);
X}
X
X/*
X *  INTERNAL FUNCTION
X *
X *  decode   transfer string capability, decoding escapes
X *
X *  SYNOPSIS
X *
X *  static char *decode(bp,area)
X *  char *bp;
X *  char **area;
X *
X *  DESCRIPTION
X *
X *  Transfers the string capability, up to the next ':'
X *  character, or null, to the buffer pointed to by
X *  the pointer in *area.  Note that the initial
X *  value of *area and *area is updated to point
X *  to the next available location after the null
X *  terminating the transfered string.
X *
X *  BUGS
X *
X *  There is no overflow checking done on the destination
X *  buffer, so it better be large enough to hold
X *  all expected strings.
X *
X */
X
X/*
X *  PSEUDO CODE
X *
X *  Begin decode
X *      Initialize the transfer pointer.
X *      While there is an input character left to process
X *      Switch on input character
X *      Case ESCAPE:
X *          Decode and xfer the escaped sequence.
X *          Break
X *      Case CONTROLIFY:
X *          Controlify and xfer the next character.
X *          Advance the buffer pointer.
X *          Break
X *      Default:
X *          Xfer a normal character.
X *      End switch
X *      End while
X *      Null terminate the output string.
X *      Remember where the output string starts.
X *      Update the output buffer pointer.
X *      Return pointer to the output string.
X *  End decode
X *
X */
X
Xstatic char *decode(bp,area)
Xchar *bp;
Xchar **area;
X{
X    char *cp, *bgn;
X    char *do_esc();
X
X    cp = *area;
X    while (*bp != NULL && *bp != ':') {
X    switch(*bp) {
X    case '\\':
X        bp = do_esc(cp++,++bp);
X        break;
X    case '^':
X        *cp++ = *++bp & 037;
X        bp++;
X        break;
X    default:
X        *cp++ = *bp++;
X        break;
X    }
X    }
X    *cp++ = (char) NULL;
X    bgn = *area;
X    *area = cp;
X    return(bgn);
X}
X
X/*
X *  INTERNAL FUNCTION
X *
X *  do_esc    process an escaped sequence
X *
X *  SYNOPSIS
X *
X *  char *do_esc(out,in);
X *  char *out;
X *  char *in;
X *
X *  DESCRIPTION
X *
X *  Processes an escape sequence pointed to by
X *  in, transfering it to location pointed to
X *  by out, and updating the pointer to in.
X *
X */
X
X/*
X *  PSEUDO CODE
X *
X *  Begin do_esc
X *      If the first character is not a NULL then
X *      If is a digit then
X *          Set value to zero.
X *          For up to 3 digits
X *              Accumulate the sum.
X *          End for
X *          Transfer the sum.
X *          Else if character is in remap list then
X *          Transfer the remapped character.
X *          Advance the input pointer once.
X *          Else
X *          Simply transfer the character.
X *          End if
X *      End if
X *      Return updated input pointer.
X *  End do_esc
X *
X */
X
Xstatic char *maplist = {
X    "E\033b\bf\fn\nr\rt\t"
X};
X
Xchar *do_esc(out,in)
Xchar *out;
Xchar *in;
X{
X    int count;
X    char ch;
X    char *cp;
X
X    if (*in != NULL) {
X    if (isdigit(*in)) {
X        ch = 0;
X        for (count = 0; count < 3 && isdigit(*in); in++) {
X         ch <<= 3;
X         ch |= (*in - '0');
X        }
X        *out++ = ch;
X    } else if ((cp = index(maplist,*in)) != NULL) {
X        *out++ = *++cp;
X        in++;
X    } else {
X        *out++ = *in++;
X    }
X    }
X    return(in);
X}
END_OF_FILE
if test 6825 -ne `wc -c <'tgetstr.c'`; then
    echo shar: \"'tgetstr.c'\" unpacked with wrong size!
fi
# end of 'tgetstr.c'
fi
if test -f 'vms.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vms.c'\"
else
echo shar: Extracting \"'vms.c'\" \(6704 characters\)
sed "s/^X//" >'vms.c' <<'END_OF_FILE'
X#ifdef VMS
X#include "header.h"
X
X#include <file.h>
X#include <stat.h>
X#include <stdio.h>
X#include <stsdef.h>
X#include <ssdef.h>
X#include <descrip.h>
X#include <iodef.h>
X#include <ttdef.h>
X#include <tt2def.h>
X
X/*
X * Read until end of file or until buffer is full.
X * don't let the vms read (which stops once per record)
X * fool the program.
X */
Xvread(fd, buf, size)
Xint fd;
Xchar    *buf;
Xint size;
X{
X    int csize;      /* cumulative size  */
X    int isize;      /* incremental size */
X
X    csize = 0;
X    do {
X        isize = read(fd, buf, size);
X        if (isize > 0) {
X            csize += isize;
X            buf   += isize;
X            size  -= isize;
X        }
X    } while (isize > 0);
X    return (csize);
X}
X
X#else VMS
X
X#ifndef vread       /* if not done as a macro in header.h */
Xvread(fd, buf, size)
Xint fd;
Xchar    *buf;
Xint size;
X{
X    return (read(fd, buf, size));
X}
X#endif vread
X#endif VMS
X
X#ifdef VMS
X/*
X * Run a command in a subjob.  Used for mailing the winners congratulations,
X * tax bills, etc.  Used for the shell escape command (!).  Conditionalized
X * for VMS wherever used (un*x has the right primitives).
X */
Xlong
Xoneliner(cstr)
Xchar    *cstr;
X{
X    struct  dsc$descriptor  cdsc;
X    register long       sts;
X    register long       pstat;
X
X    cdsc.dsc$a_pointer = cstr;
X    cdsc.dsc$w_length  = strlen(cstr);
X    cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
X    cdsc.dsc$b_class   = DSC$K_CLASS_S;
X    sts = LIB$SPAWN(&cdsc, 0, 0, 0, 0, 0, &pstat, 0, 0, 0, 0, 0);
X    if (sts != SS$_NORMAL)
X        return (sts);
X    else
X        return (pstat);
X}
X
X/*
X  Data to convert the escape codes produced by VT style keypad keys to things
X  that LARN will understand.
X*/
X#define MAX_KP_CONV 19
Xstruct 
X    {
X    char *inp_str;
X    char *out_str;
X    } keypad_conv[MAX_KP_CONV] = { { "\x1BOp", "i" },      /* KP0 */
X                                   { "\x1BOq", "b" },      /* KP1 */
X                                   { "\x1BOr", "j" },      /* KP2 */
X                                   { "\x1BOs", "n" },      /* KP3 */
X                                   { "\x1BOt", "h" },      /* KP4 */
X                                   { "\x1BOu", "." },      /* KP5 */
X                                   { "\x1BOv", "l" },      /* KP6 */
X                                   { "\x1BOw", "y" },      /* KP7 */
X                                   { "\x1BOx", "k" },      /* KP8 */
X                                   { "\x1BOy", "u" },      /* KP9 */
X                   { "\x1BOn", "." },      /* KP. */
X                   { "\x1BOl", "," },      /* KP, */
X                   { "\x1B[A", "K" },      /* uparrow */
X                   { "\x1B[B", "J" },      /* downarrow*/
X                   { "\x1B[C", "L" },      /* right arrow */
X                   { "\x1B[D", "H" },      /* left arrow */
X                   { "\x1BOP", "m" },      /* PF1 */
X                   { "\x1BOS", "@" },      /* PF4 */
X                                   { "\x1B[23~", "\x1B" }  /* (ESC) */
X                                 };
X
X/*
X  VMS-specific terminal character read.  Gets a character from the terminal,
X  translating keypad as necessary.  Assumes VT-class terminals.
X*/
Xvms_ttgetch()
X    {
X
X#define BUFFLEN 10
X
X    char           *i;
X    int            j;
X    register int   incount;
X    static char    buffer[BUFFLEN];
X    static char    *bufptr = buffer;
X    static char    *bufend = buffer;
X
X    lflush();       /* be sure output buffer is flushed */
X
X    /* Read the first char from the user
X    */
X    if (bufptr >= bufend) 
X        {
X        bufptr = bufend = buffer;
X        incount = vmsread(buffer, BUFFLEN, 0);
X        while ( incount <= 0 )
X            incount = vmsread(buffer, 1, 2);
X        bufend = &buffer[incount];
X        }
X
X    /* If the first char was an ESCAPE, get the characters from an
X       escape sequence (eg pressing a key that generates such a
X       sequence).  If it was a plain old escape, the vmsread() call
X       will return TIMEOUT.
X    */
X    if (*bufptr == '\x1B' )
X        {
X        incount = vmsread( bufend, (BUFFLEN - 1), 0 );
X        if (incount >= 0)
X        bufend += incount ;
X    }
X
X    /* Make sure the buffer is zero-terminated, since vmsread() 
X       doesn't zero-terminate the characters read.
X    */
X    *bufend = '\0' ;
X
X    /* run through the keypad conversion table to convert keypad
X       keys (escape sequences) and other supported escape sequences
X       to Larn command characters.
X    */
X    for ( j = 0; j < MAX_KP_CONV ; j++ )
X        if (strcmp( &buffer, keypad_conv[j].inp_str ) == 0 )
X            {
X        strcpy( &buffer, keypad_conv[j].out_str );
X        bufend = &buffer[strlen(&buffer)];
X        break;
X        }
X
X    /* If after running through the table the first character is still
X       ESCAPE, then we probably didn't get a match.  Force unsupported
X       keys that generate escape sequences to just return an ESCAPE.
X       Effectively prevents key translations that generate escape
X       sequences.
X    */
X    if (*bufptr == '\x1B' )
X        {
X    bufend = &buffer[1] ;
X    }
X    *bufend = '\0' ;
X
X    if (*bufptr == '\r')
X        *bufptr = '\n';
X
X    return (*bufptr++ & 0xFF);
X    }
X
Xtypedef struct 
X    {
X    short int    status;
X    short int    term_offset;
X    short int    terminator;
X    short int    term_size;
X    } IOSTAB;
X
Xint vmsread(buffer, size, timeout)
Xchar       *buffer;
Xint        size;
Xint        timeout;
X    {
X
X#define TIMEOUT (-2)
X#define ERROR   (-1)
X
X    extern int        iochan;
X
X    register int      status;
X    IOSTAB            iostab;
X    static long       termset[2] = { 0, 0 };      /* No terminator    */
X
X    status = SYS$QIOW( 
X            0,               /* Event flag             */
X            iochan,          /* Input channel        */
X            IO$_READLBLK | IO$M_NOFILTR | IO$M_TIMED,
X                             /* Read, no echo, no translate    */
X            &iostab,         /* I/O status block        */
X            NULL,            /* AST block (none)        */
X            0,               /* AST parameter        */
X            buffer,          /* P1 - input buffer        */
X            size,            /* P2 - buffer length        */
X            timeout,         /* P3 - timeout            */
X            &termset,        /* P4 - terminator set        */
X            NULL,            /* P5 - ignored (prompt buffer)    */
X            0                /* P6 - ignored (prompt size)    */
X            );
X    if (status == SS$_TIMEOUT)
X        return (TIMEOUT);
X    else if (status != SS$_NORMAL)
X        return (ERROR);
X    else 
X        {
X        if ((status = iostab.term_offset + iostab.term_size) > 0)
X            return (status);
X        return (TIMEOUT);
X        }
X    }
X
X#endif VMS
END_OF_FILE
if test 6704 -ne `wc -c <'vms.c'`; then
    echo shar: \"'vms.c'\" unpacked with wrong size!
fi
# end of 'vms.c'
fi
echo shar: End of archive 11 \(of 12\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0