[comp.sources.games] v12i054: 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 54
Archive-name: larn2/Part01
Supersedes: larn: Volume 11, Issue 84-94
Environment: Unix, VMS, MS-DOS, OS/2, termcap

	[This is an update of the larn game posted earlier. This
	includes patches, enhancements and additional support for
	OS/2.  -br]

#! /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 1 (of 12)."
# Contents:  README MANIFEST main.c tgoto.c
# Wrapped by billr@saab on Tue Apr 23 13:50:27 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1841 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
XHere is the source to Larn V12.3.  I had made a number of changes without
Xchanging the save file format, so I decided to make another distribution
Xbefore making the big leap to V14.0.
X
XThis distribution incorporates all the changes distributed as Patches to V12.2,
Xa few others that were suggested but not sent out as patches, plus my own
Xdevelopment.  See LARN123.FIX for a partial list.
X
XThe source correctly compiles and executes under DEC Ultrix (BSD), using the cc
Xcompiler.  The enclosed makefile.unix is for U*ix systems (rename to Makefile).
XI've endevoured to make Larn buildable under SYSV, and it builds/runs correctly
Xwith Ultrix V3.1's SYSTEM_FIVE environment, so I expect its fairly close to
Xbeing usable under SYSV as well.
X
XThe source correctly compiles and executes under VAX/VMS, using the VAX C V3.x
Xcompiler.  The enclosed descrip.mms is a MMS file for building under VAX/VMS.
XSee the VMSREADME.TXT for some more VMS-related information.
X
XThe source correctly compiles and executes under MS-DOS, using Turbo C++ V1.0.
XI am no longer able to verify that it compiles using Turbo C V2.0.  The
Xmakefile.pc and tlink.rsp are for building the MS-DOS Larn.  
X
XThe source correctly compiles and executes under OS/2, using Microsoft C.
XThe makefile.os2, os2larn.def and os2larn.lnk are for building the OS/2 Larn.  
X
XI am interested in receiving source changes that allow Larn to be ported or
Xbuilt correctly on other architectures or operating systems.  I am also 
Xinterested in constructive changes or additions to improve the game.  
X
XBug fixes, bug reports, and requests welcome.
X
XI am reachable at tle.enet.dec.com!routley or routley@tle.enet.dec.com.
XBecause I cannot provide a stable mail address, all USmail should be sent to:
X
XKevin Routley
XDigital Equipment Corporation
XZKO2-3/N30
X110 Spitbrook Road
XNashua, NH  03060
X
END_OF_FILE
if test 1841 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(2692 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X Makefile.unix              2	Makefile for U*ix.
X README                     1	General readme
X action.c                   9	
X bill.c                     8	
X config.c                  12	
X create.c                   8	
X data.c                     4	
X descrip.mms               12	MMS build file for VAX/VMS
X diag.c                     9	
X display.c                  5	
X fgetlr.c                  12	Termcap support for VMS/MS-DOS.
X fortune.c                 10	
X global.c                   2	
X header.h                  12	
X help.c                    12	
X io.c                       3	
X iventory.c                10	
X larn.ftn                  12	Fortune File
X larn.maz                   7	Maze file
X larn.opt                  12	Sample options file.  Rename to .larnopts for U*ix.
X larn123.doc                7	Documentation for Larn V12.3
X larn123.fix               11	List of changes since Larn V12.0
X larndefs.h                12	
X larnhlp.txt                9	Help file without ansi escape sequences
X larnhlp.uue               10	Uuencoded help file with ansi escape sequences
X main.c                     1	
X makefile.os2              12	OS/2-Microsoft C Makefile
X makefile.pc               11	MS-DOS, Turbo C++ Makefile
X monster.c                  6	
X monsters.h                 9	
X moreobj.c                  3	
X movem.c                    4	
X msdos.c                   10	MS-DOS Specific code.
X nansi.doc                 11	Docs for NANSI.SYS, a MS-DOS ANSI.SYS replacement
X nansisys.uue              12	UUENCODED NANSI.SYS
X nap.c                     12	
X object.c                   2	
X objects.h                 12	
X os2larn.def                5	OS/2 Build support
X os2larn.lnk                4	OS/2 Build support
X patchlev.h                 3	
X player.h                  12	
X regen.c                   11	
X savelev.c                 12	
X scores.c                   8	
X signal.c                  11	
X spells.c                   6	
X spheres.c                 11	
X store.c                    5	
X termcap.pc                 5	Termcap file for MS-DOS.
X termcap.vms               12	Termcap file for VMS.
X tgetent.c                 10	Termcap support for VMS/MS-DOS.
X tgetstr.c                 11	Termcap support for VMS/MS-DOS.
X tgoto.c                    1	Termcap support for VMS/MS-DOS.
X tlink.rsp                  4	Turbo C++ MS-DOS Build support
X tok.c                      9	
X tputs.c                    7	Termcap support for VMS/MS-DOS.
X vms.c                     11	VMS Specific code.
X vmsreadme.txt              6	VMS Specific Readme
END_OF_FILE
if test 2692 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(40768 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/* main.c */
X
X#ifdef MSDOS
X#include "errno.h"
X#include "setjmp.h"
X#include "stdlib.h"
X#endif
X
X#include "header.h"
X#include "larndefs.h"
X#include "monsters.h"
X#include "objects.h"
X#include "player.h"
X#include "patchlev.h"
X
X#ifndef MSDOS
X# ifndef VMS
X#  include <pwd.h>
X# endif VMS
X#endif MSDOS
X
Xextern char move_no_pickup;
Xint dropflag=0; /* if 1 then don't lookforobject() next round */
Xint rmst=80;    /*  random monster creation counter     */
Xint userid;     /* the players login user id number */
Xchar nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a
X                              move */
Xstatic char viewflag=0;    /* if viewflag then we have done a 99 stay here
X                              and don't showcell in the main loop */
Xchar restorflag=0;         /* 1 means restore has been done    */
Xchar prompt_mode = 0;         /* 1 if prompting for actions */
X
X#ifdef MSDOS
X
Xstatic char cmdhelp[] = "\
XCmd line format: larn [-slicnhp] [-o<optsfile>] [-##] [++]\n\
X  -s   show the scoreboard\n\
X  -l   show the logfile (wizard id only)\n\
X  -i   show scoreboard with inventories of dead characters\n\
X  -c   create new scoreboard (wizard id only)\n\
X  -n   suppress welcome message on starting game\n\
X  -##  specify level of difficulty (example: -5)\n\
X  -h   print this help text\n\
X  -p   prompt for actions on objects\n\
X  ++   restore game from checkpoint file\n\
X  -o<optsfile>   specify larnopts filename to be used instead of \"larn.opt\"\n\
X";
X
X# else
X
Xstatic char cmdhelp[] = "\
XCmd line format: larn [-slicnhp] [-o<optsfile>] [-##] [++]\n\
X  -s   show the scoreboard\n\
X  -l   show the logfile (wizard id only)\n\
X  -i   show scoreboard with inventories of dead characters\n\
X  -c   create new scoreboard (wizard id only)\n\
X  -n   suppress welcome message on starting game\n\
X  -##  specify level of difficulty (example: -5)\n\
X  -h   print this help text\n\
X  -p   prompt for actions on objects\n\
X  ++   restore game from checkpoint file\n\
X  -o<optsfile>   specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
X";
X
X# endif
X
X#ifdef MSDOS
Xint save_mode = 0;      /* 1 if doing a save game */
Xjmp_buf save_jbuf;      /* To recover from disk full errors */
X#endif
X
X#ifdef VT100
Xstatic char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
X    "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
X    "vt341"  };
X#endif
X
X#ifdef VMS
X# define EXIT_FAILURE
X# define EXIT_SUCCESS 1
X#else
X# define EXIT_FAILURE 1
X# define EXIT_SUCCESS 0
X#endif
X
X/*
X    ************
X    MAIN PROGRAM
X    ************
X*/
Xmain(argc,argv)
X    int argc;
X    char **argv;
X    {
X    register int i,j;
X    int hard = -1;
X    char *ptr=0;
X#ifdef VT100
X    char *ttype;
X#endif
X#ifndef MSDOS
X    struct passwd *pwe,*getpwuid();
X#endif
X
X/*
X *  first task is to identify the player
X */
X#ifndef VT100
X    init_term();    /* setup the terminal (find out what type) for termcap */
X#endif
X#ifdef MSDOS
X    ptr = "PLAYER";
X#else
X#ifdef VMS
X    ptr = getenv("USER");
X#else
X    if (((ptr = getlogin()) == 0) || (*ptr==0)) /* try to get login name */
X      if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
X        ptr = pwe->pw_name;
X      else
X      if ((ptr = getenv("USER")) == 0)
X        if ((ptr = getenv("LOGNAME")) == 0)
X          {
X          noone: write(2, "Can't find your logname.  Who Are You?\n",39);
X                 exit();
X          }
X    if (ptr==0) goto noone;
X    if (strlen(ptr)==0) goto noone;
X#endif
X#endif
X
X/*
X *  second task is to prepare the pathnames the player will need
X */
X    strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
X    strcpy(logname,ptr);    /* this will be overwritten with the players name */
X
X/* Set up the input and output buffers.
X */
X    lpbuf    = (char *)malloc((5* BUFBIG)>>2);  /* output buffer */
X    inbuffer = (char *)malloc((5*MAXIBUF)>>2);  /* output buffer */
X    if ((lpbuf==0) || (inbuffer==0)) 
X        died(-285); /* malloc() failure */
X
X# ifdef MSDOS
X    /* LARNHOME now comes from the options file, so it must be read in
X     * before constructing the other file names.  Unfortunately we have
X     * to look for the -o option now.
X     */
X    strcpy(optsfile, LARNOPTS);
X    for (i = 1; i < argc; i++)
X        if (strncmp(argv[i], "-o", 2) == 0) 
X            {
X            argv[i][0] = 0;         /* remove this argv */
X            if (argv[i][2] != '\0')
X                strncpy(optsfile, &argv[i][2], PATHLEN);
X            else
X                {
X                strncpy(optsfile, argv[i + 1], PATHLEN);
X                argv[i + 1][0] = 0; /* and this argv */
X                }
X            optsfile[PATHLEN - 1] = 0;
X            break;
X            }
X    readopts();
X    append_slash(larndir);
X
X    /* Savefile and swapfile can be given explicitly as options
X     */
X    if (!savefilename[0]) 
X        {
X        strcpy(savefilename, larndir);
X        strcat(savefilename, SAVEFILE);
X        }
X    if (!swapfile[0]) 
X        {
X        strcpy(swapfile, larndir);
X        strcat(swapfile, SWAPFILE);
X        }
X    strcpy(scorefile, larndir);
X    strcpy(logfile, larndir);
X    strcpy(helpfile, larndir);
X    strcpy(larnlevels, larndir);
X    strcpy(fortfile, larndir);
X    strcpy(playerids, larndir);
X    strcpy(ckpfile, larndir);
X
X# else /* MSDOS */
X
X    if ((ptr = getenv("HOME")) == 0) 
X        ptr = ".";
X#ifdef SAVEINHOME
X    /* save file name in home directory */
X# ifdef VMS
X    sprintf(savefilename, "%s%s",ptr, SAVEFILE);
X# else
X    sprintf(savefilename, "%s/%s",ptr, SAVEFILE);
X# endif VMS
X#else
X    strcat(savefilename,logname);   /* prepare savefile name */
X    strcat(savefilename,".sav");    /* prepare savefile name */
X#endif
X#ifdef VMS
X    sprintf(optsfile, "%s%s",ptr, LARNOPTS);   /* the options filename */
X#else
X    sprintf(optsfile, "%s/%s",ptr, LARNOPTS);   /* the options filename */
X#endif VMS
X
X# endif /* MSDOS */
X
X    strcat(scorefile, SCORENAME);   /* the larn scoreboard filename */
X    strcat(logfile, LOGFNAME);      /* larn activity logging filename */
X    strcat(helpfile, HELPNAME);     /* the larn on-line help file */
X    strcat(larnlevels, LEVELSNAME); /* the pre-made cave level data file */
X    strcat(fortfile, FORTSNAME);    /* the fortune data file name */
X    strcat(playerids, PLAYERIDS);   /* the playerid data file name */
X    strcat(ckpfile, CKPFILE);
X
X# ifdef TIMECHECK
X    strcat(holifile, HOLIFILE);     /* the holiday data file name */
X# endif
X
X#ifdef VT100
X/*
X *  check terminal type to avoid users who have not vt100 type terminals
X */
X    ttype = getenv("TERM");
X    for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
X        if (strcmp(ttype,termtypes[i]) == 0) { j=0;  break; }
X    if (j)
X        {
X        lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
X        exit(EXIT_FAILURE);
X        }
X#endif
X
X/*
X *  now make scoreboard if it is not there (don't clear) 
X */
X    if (access(scorefile,0) == -1) /* not there */
X        makeboard();
X
X/*
X *  now process the command line arguments 
X */
X    for (i=1; i<argc; i++)
X        {
X        if (argv[i][0] == '-')
X          switch(argv[i][1])
X            {
X            case 's':          /* show scoreboard   */
X                showscores();
X                exit(EXIT_SUCCESS);
X
X            case 'l':          /* show log file     */
X                diedlog();
X                exit(EXIT_SUCCESS);
X
X            case 'i':          /* show all scoreboard */
X                showallscores();
X                exit(EXIT_SUCCESS);
X
X            case 'c':          /* anyone with password can create scoreboard */
X                lprcat("Preparing to initialize the scoreboard.\n");
X                if (getpassword() != 0)  /*make new scoreboard*/
X                    {
X                    makeboard();
X                    lprc('\n');
X                    showscores();
X                    }
X                exit(EXIT_SUCCESS);
X
X            case 'n':          /* no welcome msg   */
X                nowelcome=1;
X                argv[i][0]=0;
X                break;
X
X            case '0': case '1': case '2': case '3': case '4': case '5':
X            case '6': case '7': case '8': case '9': /* for hardness */
X                hard = atoi(&argv[i][1]);
X                break;
X
X            case 'h':          /* print out command line arguments */
X            case '?':
X                write(1,cmdhelp,sizeof(cmdhelp));
X                exit(EXIT_SUCCESS);
X
X            case 'o':          /* specify a .larnopts filename */
X                if (argv[i]+2 != '\0')
X                    strncpy(optsfile,argv[i]+2,127);
X                else
X                    {
X                    strncpy( optsfile, argv[i+1][0], 127 );
X                    argv[i+1][0] = '\0';
X                    }
X                break;
X
X            case 'p':          /* set 'prompt_mode' flag */
X                prompt_mode = 1 ;
X                break ;
X
X            default:
X                printf("Unknown option <%s>\n",argv[i]);
X                write(1,cmdhelp,sizeof(cmdhelp));
X                exit(EXIT_SUCCESS);
X            };
X
X        if (strcmp(argv[i], "++") == 0)
X            restorflag = 1;
X    }
X
X#ifndef MSDOS
X    readopts();     /* read the options file if there is one */
X#endif
X
X#ifdef TIMECHECK
X/*
X *  this section of code checks to see if larn is allowed during working hours
X */
X    if (dayplay==0) /* check for not-during-daytime-hours */
X      if (playable())
X        {
X        write(2,"Sorry, Larn can not be played during working hours.\n",52);
X        exit(EXIT_SUCCESS);
X        }
X#endif TIMECHECK
X
X#ifdef UIDSCORE
X    userid = geteuid(); /* obtain the user's effective id number */
X#else UIDSCORE
X    userid = getplid(logname);  /* obtain the players id number */
X#endif UIDSCORE
X#ifdef VMS
X    wisid = userid;
X#endif
X    if (userid < 0) 
X        { 
X        write(2,"Can't obtain playerid\n",22);
X        exit(EXIT_SUCCESS);
X        }
X
X#ifdef HIDEBYLINK
X/*
X *  this section of code causes the program to look like something else to ps
X */
X    if (strcmp(psname,argv[0])) /* if a different process name only */
X        {
X        if ((i=access(psname,1)) < 0)
X            {       /* link not there */
X            if (link(argv[0],psname)>=0)
X                {
X                argv[0] = psname;   execv(psname,argv);
X                }
X            }
X        else
X            unlink(psname);
X        }
X
X    for (i=1; i<argc; i++)
X        {
X        szero(argv[i]); /* zero the argument to avoid ps snooping */
X        }
X#endif HIDEBYLINK
X
X/*
X *  He really wants to play, so malloc the memory for the dungeon.
X */
X# ifdef MSDOS
X    allocate_memory();
X# else
X    cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
X    if (cell == 0) died(-285);  /* malloc failure */
X# endif
X    lcreat((char*)0);   
X    newgame();      /*  set the initial clock  */
X
X    if (restorflag == 1)           /* restore checkpoint file */
X        {
X        clear();
X        hitflag = 1;
X        restoregame(ckpfile);
X        }
X    else if (access(savefilename,0)==0)   /* restore game if need to */
X        {
X        clear();    
X        restorflag = 1;
X        hitflag=1;  
X        restoregame(savefilename);  /* restore last game    */
X        }
X    sigsetup();     /* trap all needed signals  */
X    setupvt100();   /*  setup the terminal special mode             */
X    sethard(hard);  /* set up the desired difficulty                */
X    if (c[HP]==0)   /* create new game */
X        {
X        makeplayer();   /*  make the character that will play           */
X        newcavelevel(0);/*  make the dungeon                            */
X        predostuff = 1; /* tell signals that we are in the welcome screen */
X        if (nowelcome==0)
X            welcome();     /* welcome the player to the game */
X# ifdef MSDOS
X        /* Display their mail if they've just won the previous game
X         */
X        checkmail();
X# endif
X        }
X
X    lprc(T_INIT);   /* Reinit the screen because of welcome and check mail
X                     * having embedded escape sequences.*/
X    drawscreen();   /*  show the initial dungeon                    */
X    predostuff = 2; /* tell the trap functions that they must do a showplayer()
X               from here on */
X    /* nice(1); /* games should be run niced */
X    yrepcount = hit2flag = 0;
X    /* init previous player position to be current position, so we don't
X       reveal any stuff on the screen prematurely.
X    */
X    oldx = playerx ;
X    oldy = playery;
X    gtime = -1;
X
X    /* MAINLOOP
X       find objects, move stuff, get commands, regenerate
X    */
X    while (1)
X        {
X        if (dropflag==0)
X            /* see if there is an object here.
X
X               If in prompt mode, identify and prompt; else
X               identify, pickup if ( auto pickup and not move-no-pickup ),
X               never prompt.
X            */
X            if (prompt_mode)
X                lookforobject( TRUE, FALSE, TRUE );
X            else
X                lookforobject( TRUE, ( auto_pickup && !move_no_pickup ), FALSE );
X            else
X                dropflag=0; /* don't show it just dropped an item */
X
X        /* handle global activity
X           update game time, move spheres, move walls, move monsters
X           all the stuff affected by TIMESTOP and HASTESELF
X        */
X        if (c[TIMESTOP] <= 0)
X            if (c[HASTESELF] == 0 ||
X               (c[HASTESELF] & 1) == 0)
X                {
X                gtime++;
X                movsphere();
X
X                if (hitflag==0)
X                    {
X                    if (c[HASTEMONST])
X                        movemonst();
X                    movemonst();
X                    }
X                }
X
X        /* show stuff around the player
X        */
X        if (viewflag==0)
X            showcell(playerx,playery);
X        else
X            viewflag=0;
X
X        if (hit3flag)
X            lflushall();
X        hitflag=hit3flag=0;
X        bot_linex();    /* update bottom line */
X
X        /* get commands and make moves
X        */
X        nomove=1;
X        while (nomove)
X            {
X            if (hit3flag)
X                lflushall();
X            nomove=0;
X            parse();
X            }
X        regen();            /*  regenerate hp and spells            */
X        if (c[TIMESTOP]==0)
X            if (--rmst <= 0)
X                {
X                rmst = 120-(level<<2);
X                fillmonst(makemonst(level));
X                }
X        }
X    }
X
X/*
X    subroutine to randomly create monsters if needed
X */
Xstatic randmonst()
X    {
X    if (c[TIMESTOP]) return;    /*  don't make monsters if time is stopped  */
X    if (--rmst <= 0)
X        {
X        rmst = 120 - (level<<2);  fillmonst(makemonst(level));
X        }
X    }
X
X
X/*
X    parse()
X
X    get and execute a command
X */
Xstatic parse()
X    {
X    register int i,j,k,flag;
X    extern showeat(),showquaff(),showread();
X
X    while   (1)
X        {
X        k = yylex();
X        switch(k)   /*  get the token from the input and switch on it   */
X            {
X            case 'h':   moveplayer(4);  return;     /*  west        */
X            case 'H':   run(4);         return;     /*  west        */
X            case 'l':   moveplayer(2);  return;     /*  east        */
X            case 'L':   run(2);         return;     /*  east        */
X            case 'j':   moveplayer(1);  return;     /*  south       */
X            case 'J':   run(1);         return;     /*  south       */
X            case 'k':   moveplayer(3);  return;     /*  north       */
X            case 'K':   run(3);         return;     /*  north       */
X            case 'u':   moveplayer(5);  return;     /*  northeast   */
X            case 'U':   run(5);         return;     /*  northeast   */
X            case 'y':   moveplayer(6);  return;     /*  northwest   */
X            case 'Y':   run(6);         return;     /*  northwest   */
X            case 'n':   moveplayer(7);  return;     /*  southeast   */
X            case 'N':   run(7);         return;     /*  southeast   */
X            case 'b':   moveplayer(8);  return;     /*  southwest   */
X            case 'B':   run(8);         return;     /*  southwest   */
X
X            case '.':                               /*  stay here       */
X                if (yrepcount) 
X                    viewflag=1;
X                return;
X
X            case 'c':
X                yrepcount=0;
X                cast();
X                return;     /*  cast a spell    */
X
X            case 'd':
X                yrepcount=0;
X                if (c[TIMESTOP]==0)
X                    dropobj();
X                return; /*  to drop an object   */
X
X            case 'e':
X                yrepcount=0;
X                if (c[TIMESTOP]==0)
X                    if (!floor_consume( OCOOKIE, "eat" ))
X                        consume( OCOOKIE, "eat", showeat );
X                return; /*  to eat a fortune cookie */
X
X            case 'g':   
X                yrepcount = 0 ;
X                cursors();
X                lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
X                break ;
X
X            case 'i':       /* inventory */
X                yrepcount=0;
X                nomove=1;
X                showstr(FALSE);
X                return;
X
X            case 'p':           /* pray at an altar */
X                yrepcount = 0;
X                if (!prompt_mode)
X                    pray_at_altar();
X                else
X                    nomove = 1;
X                return;
X
X            case 'q':           /* quaff a potion */
X                yrepcount=0;
X                if (c[TIMESTOP]==0)
X                    if (!floor_consume( OPOTION, "quaff"))
X                        consume( OPOTION, "quaff", showquaff );
X                return;
X
X            case 'r':
X                yrepcount=0;
X                if (c[BLINDCOUNT])
X                    {
X                    cursors();
X                    lprcat("\nYou can't read anything when you're blind!");
X                    }
X                else if (c[TIMESTOP]==0)
X                    if (!floor_consume( OSCROLL, "read" ))
X                        if (!floor_consume( OBOOK, "read" ))
X                            consume( OSCROLL, "read", showread );
X                return;     /*  to read a scroll    */
X
X            case 's':
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    sit_on_throne();
X                else
X                    nomove = 1;
X                return ;
X
X            case 't':                       /* Tidy up at fountain */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    wash_fountain() ;
X                else
X                    nomove = 1;
X                return ;
X
X            case 'v':
X                yrepcount=0;
X                nomove = 1;
X                cursors();
X                lprintf("\nCaverns of Larn, Version %d.%d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)PATCHLEVEL,(long)c[HARDGAME]);
X                if (wizard)
X                    lprcat(" Wizard");
X                if (cheat) 
X                    lprcat(" Cheater");
X                lprcat("\nThis version of Larn by Kevin Routley");
X                return;
X
X            case 'w':                       /*  wield a weapon */
X                yrepcount=0;
X                wield();
X                return;
X
X            case 'A':
X                yrepcount = 0;
X                if (!prompt_mode)
X                    desecrate_altar();
X                else
X                    nomove = 1;
X                return;
X
X            case 'C':                       /* Close something */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    close_something();
X                else
X                    nomove = 1;
X                return;
X
X            case 'D':                       /* Drink at fountain */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    drink_fountain() ;
X                else
X                    nomove = 1;
X                return ;
X
X            case 'E':               /* Enter a building */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    enter() ;
X                else
X                    nomove = 1;
X                break ;
X
X            case 'I':              /*  list spells and scrolls */
X                yrepcount=0;
X                seemagic(0);
X                nomove=1;
X                return;
X
X            case 'O':               /* Open something */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    open_something();
X                else
X                    nomove = 1;
X                return;
X
X            case 'P':
X                cursors();
X                yrepcount = 0;
X                nomove = 1;
X                if (outstanding_taxes>0)
X                    lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
X                else
X                    lprcat("\nYou do not owe any taxes.");
X                return;
X
X            case 'Q':    /*  quit        */
X                yrepcount=0;
X                quit();
X                nomove=1;
X                return;
X
X            case 'R' :          /* remove gems from a throne */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    remove_gems( );
X                else
X                    nomove = 1;
X                return ;
X
X# ifdef MSDOS
X            case 'S':
X                /* Set up error recovery
X                 */
X                if (setjmp(save_jbuf) != 0) {
X
X                    /* can't use lwclose!
X                     */
X                    if (lfd > 2)
X                        close(lfd);
X                    lcreat(NULL);
X                    setscroll();
X                    cursors();
X                    lprcat("\nSave failed !\n");
X                    if (errno == ENOSPC)
X                        lprcat("Disk is full !\n");
X                    beep();
X                    (void) unlink(savefilename);
X                    save_mode = 0;
X                    yrepcount = 0;
X                    nomove = 1;
X                    break;
X                }
X
X                /* And do the save.
X                 */
X                cursors();
X                lprintf("\nSaving to `%s' . . . ", savefilename);
X                lflush();
X                save_mode = 1;
X                savegame(savefilename);
X                clear();
X                lflush();
X                wizard=1;
X                died(-257); /* doesn't return */
X                break;
X# else
X            case 'S':   clear();  lprcat("Saving . . ."); lflush();  
X                        savegame(savefilename); wizard=1; died(-257);   /*  save the game - doesn't return  */
X# endif MSDOS
X
X            case 'T':   yrepcount=0;    cursors();  if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
X                                        if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
X                        else lprcat("\nYou aren't wearing anything");
X                        return;
X
X            case 'W':
X                yrepcount=0;
X                wear();
X                return; /*  wear armor  */
X
X            case 'Z':
X                yrepcount=0;
X                if (c[LEVEL]>9) 
X                    { 
X                    oteleport(1);
X                    return; 
X                    }
X                cursors(); 
X                lprcat("\nAs yet, you don't have enough experience to use teleportation");
X                return; /*  teleport yourself   */
X
X            case ' ':   yrepcount=0;    nomove=1;  return;
X
X# ifdef MSDOS
X            case 'D'-64:
X                yrepcount = 0;
X                nomove = 1;
X                levelinfo();
X                return;
X# endif
X
X            case 'L'-64:  yrepcount=0;  drawscreen();  nomove=1; return;    /*  look        */
X
X#if WIZID
X#ifdef EXTRA
X            case 'A'-64:    yrepcount=0;    nomove=1; if (wizard) { diag(); return; }  /*   create diagnostic file */
X                        return;
X#endif
X#endif
X            case '<':                       /* Go up stairs or vol shaft */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    up_stairs();
X        else
X            nomove = 1;
X                return ;
X
X            case '>':                       /* Go down stairs or vol shaft*/
X                yrepcount = 0 ;
X                if (!prompt_mode)
X                    down_stairs();
X        else
X            nomove = 1;
X                return ;
X
X            case '?':                       /* give the help screen */
X                yrepcount=0;
X                help();
X                nomove=1;
X                return; 
X
X        case ',':                       /* pick up an item */
X            yrepcount = 0 ;
X            if (!prompt_mode)
X            /* pickup, don't identify or prompt for action */
X            lookforobject( FALSE, TRUE, FALSE );
X        else
X            nomove = 1;
X        return;
X
X            case ':':                       /* look at object */
X                yrepcount = 0 ;
X                if (!prompt_mode)
X            /* identify, don't pick up or prompt for action */
X                    lookforobject( TRUE, FALSE, FALSE );
X                nomove = 1;  /* assumes look takes no time */
X                return;
X
X        case '@':       /* toggle auto-pickup */
X            yrepcount = 0 ;
X            nomove = 1;
X            cursors();
X            lprcat("\nAuto pickup: ");
X            auto_pickup = !auto_pickup;
X            if (auto_pickup)
X                lprcat("On.");
X            else
X                lprcat("Off.");
X            return;
X
X        case '/':        /* identify object/monster */
X            specify_object();
X            nomove = 1 ;
X            yrepcount = 0 ;
X            return;
X
X        case '^':                       /* identify traps */
X                flag = yrepcount = 0;
X                cursors();
X                lprc('\n');
X                for (j=playery-1; j<playery+2; j++)
X                    {
X                    if (j < 0)
X                        j=0;
X                    if (j >= MAXY)
X                        break;
X                    for (i=playerx-1; i<playerx+2; i++)
X                        {
X                        if (i < 0) 
X                            i=0;
X                        if (i >= MAXX) 
X                            break;
X                        switch(item[i][j])
X                            {
X                            case OTRAPDOOR:     case ODARTRAP:
X                            case OTRAPARROW:    case OTELEPORTER:
X                            case OPIT:
X                                lprcat("\nIts ");
X                                lprcat(objectname[item[i][j]]);
X                                flag++;
X                            };
X                        }
X                    }
X                if (flag==0) 
X                    lprcat("\nNo traps are visible");
X                return;
X
X#if WIZID
X            case '_':   /*  this is the fudge player password for wizard mode*/
X                        yrepcount=0;    cursors(); nomove=1;
X# ifndef MSDOS
X                        if (userid!=wisid)
X                            {
X                            lprcat("Sorry, you are not empowered to be a wizard.\n");
X                            scbr(); /* system("stty -echo cbreak"); */
X                            lflush();  return;
X                            }
X# endif
X                        if (getpassword()==0)
X                            {
X                            scbr(); /* system("stty -echo cbreak"); */ return;
X                            }
X                        wizard=1;  scbr(); /* system("stty -echo cbreak"); */
X                        for (i=0; i<6; i++)  c[i]=70;  iven[0]=iven[1]=0;
X                        take(OPROTRING,50);   take(OLANCE,25);  c[WIELD]=1;
X                        c[LANCEDEATH]=1;   c[WEAR] = c[SHIELD] = -1;
X                        raiseexperience(6000000L);  c[AWARENESS] += 25000;
X                        {
X                        register int i,j;
X                        for (i=0; i<MAXY; i++)
X                            for (j=0; j<MAXX; j++)  know[j][i]=KNOWALL;
X                        for (i=0; i<SPNUM; i++) spelknow[i]=1;
X                        for (i=0; i<MAXSCROLL; i++)  scrollname[i][0]=' ';
X                        for (i=0; i<MAXPOTION; i++)  potionname[i][0]=' ';
X                        }
X                        for (i=0; i<MAXSCROLL; i++)
X                          if (strlen(scrollname[i])>2) /* no null items */
X                            { item[i][0]=OSCROLL; iarg[i][0]=i; }
X                        for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
X                          if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
X                            { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
X                        for (i=1; i<MAXY; i++)
X                            { item[0][i]=i; iarg[0][i]=0; }
X                        for (i=MAXY; i<MAXY+MAXX; i++)
X                            { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
X            for (i=MAXX+MAXY; i<MAXOBJECT; i++)
X                {
X                item[MAXX-1][i-MAXX-MAXY]=i;
X                iarg[MAXX-1][i-MAXX-MAXY]=0;
X                }
X                        c[GOLD]+=250000;    drawscreen();   return;
X#endif
X
X            };
X        }
X    }
X
Xparse2()
X    {
X    if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters       */
X    randmonst();    regen();
X    }
X
Xstatic run(dir)
X    int dir;
X    {
X    register int i;
X    i=1; while (i)
X        {
X        i=moveplayer(dir);
X        if (i>0) {  if (c[HASTEMONST]) movemonst();  movemonst(); randmonst(); regen(); }
X        if (hitflag) i=0;
X        if (i!=0)  showcell(playerx,playery);
X        }
X    }
X
X/*
X    function to wield a weapon
X */
Xstatic wield()
X    {
X    register int i;
X    while (1)
X        {
X        if ((i = whatitem("wield (- for nothing)")) == '\33')
X        return;
X        if (i != '.')
X            {
X            if (i=='*')
X                {
X                i = showwield();
X                cursors();
X                }
X            if ( i == '-' )
X                {
X                c[WIELD] = -1 ;
X                bottomline();
X                return;
X                }
X            if (i && i != '.')
X                if (iven[i-'a']==0)
X                    { ydhi(i); return; }
X                else if (iven[i-'a']==OPOTION)
X                    { ycwi(i); return; }
X            else if (iven[i-'a']==OSCROLL)
X                    { ycwi(i); return; }
X            else if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD))
X                    { lprcat("\nBut one arm is busy with your shield!");
X                      return; }
X            else
X                {
X                c[WIELD]=i-'a';
X                if (iven[i-'a'] == OLANCE)
X                    c[LANCEDEATH]=1;
X                else c[LANCEDEATH]=0;
X                bottomline();
X                return;
X                }
X            }
X        }
X    }
X
X/*
X    common routine to say you don't have an item
X */
Xstatic ydhi(x)
X    int x;
X    { cursors();  lprintf("\nYou don't have item %c!",x); }
Xstatic ycwi(x)
X    int x;
X    { cursors();  lprintf("\nYou can't wield item %c!",x); }
X
X/*
X    function to wear armor
X */
Xstatic wear()
X    {
X    register int i;
X    while (1)
X        {
X        if ((i = whatitem("wear"))=='\33')
X            return;
X        if (i != '.' && i != '-')
X            {
X            if (i=='*')
X                {
X                i = showwear();
X                cursors();
X                }
X            if (i && i != '.')
X                switch(iven[i-'a'])
X                    {
X                    case 0:
X                        ydhi(i);
X                        return;
X                    case OLEATHER:  case OCHAIN:  case OPLATE:
X                    case ORING:     case OSPLINT: case OPLATEARMOR:
X                    case OSTUDLEATHER:            case OSSPLATE:
X                        if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
X                            c[WEAR]=i-'a';  bottomline(); return;
X                    case OSHIELD:   if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
X                                if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
X                                c[SHIELD] = i-'a';  bottomline(); return;
X                    default:    lprcat("\nYou can't wear that!");
X                    };
X            }
X        }
X    }
X
X/*
X    function to drop an object
X */
Xstatic dropobj()
X    {
X    register int i;
X    register char *p;
X    long amt;
X
X    p = &item[playerx][playery];
X    while (1)
X        {
X        if ((i = whatitem("drop"))=='\33')  
X        return;
X    if (i=='*') 
X        {
X        i = showstr(TRUE);
X        cursors();
X        }
X    if ( i != '-' )
X            {
X            if (i=='.') /* drop some gold */
X                {
X                if (*p) { lprcat("\nThere's something here already!"); return; }
X                lprcat("\n\n");
X                cl_dn(1,23);
X                lprcat("How much gold do you drop? ");
X                if ((amt=readnum((long)c[GOLD])) == 0) return;
X                if (amt>c[GOLD])
X                    {
X#ifndef MSDOS
X            lprcat("\n");
X#endif MSDOS
X            lprcat("You don't have that much!");
X            return; }
X                if (amt<=32767)
X                    { *p=OGOLDPILE; i=amt; }
X                else if (amt<=327670L)
X                    { *p=ODGOLD; i=amt/10; amt = 10L*i; }
X                else if (amt<=3276700L)
X                    { *p=OMAXGOLD; i=amt/100; amt = 100L*i; }
X                else if (amt<=32767000L)
X                    { *p=OKGOLD; i=amt/1000; amt = 1000L*i; }
X                else
X                    { *p=OKGOLD; i=32767; amt = 32767000L; }
X                c[GOLD] -= amt;
X#ifndef MSDOS
X                lprintf("You drop %d gold pieces",(long)amt);
X#else
X                lprintf("\nYou drop %d gold pieces",(long)amt);
X#endif MSDOS
X                iarg[playerx][playery]=i; bottomgold();
X                know[playerx][playery]=0; dropflag=1;  return;
X                }
X        if (i)
X        {
X        drop_object(i-'a');
X        return;
X        }
X            }
X        }
X    }
X
Xstatic int floor_consume( search_item, cons_verb )
Xint search_item;
Xchar *cons_verb;
X    {
X    register int i;
X    char tempc;
X
X    cursors();
X    i = item[playerx][playery];
X
X    /* item not there, quit
X    */
X    if (i != search_item)
X        return( 0 );
X
X    /* item there.  does the player want to consume it?
X    */
X    lprintf("\nThere is %s", objectname[i] );
X    if (i==OSCROLL)
X        if (scrollname[iarg[playerx][playery]][0])
X            lprintf(" of%s", scrollname[iarg[playerx][playery]]);
X    if (i==OPOTION)
X        if (potionname[iarg[playerx][playery]][0])
X            lprintf(" of%s", potionname[iarg[playerx][playery]]);
X    lprintf(" here.  Do you want to %s it?", cons_verb );
X
X    if ((tempc = getyn()) == 'n' )
X        return( 0 );                /* item there, not consumed */
X    else if (tempc != 'y')
X        {
X        lprcat(" aborted");
X        return( -1 );               /* abort */
X        }
X
X    /* consume the item.
X    */
X    switch( i )
X        {
X        case OCOOKIE:
X            outfortune();
X            forget();
X            break;
X        case OBOOK:
X            readbook( iarg[playerx][playery] );
X            forget();
X            break;
X        case OPOTION:
X            quaffpotion( iarg[playerx][playery] );
X            forget();
X            break;
X        case OSCROLL:
X            /* scrolls are tricky because of teleport.
X            */
X            i = iarg[playerx][playery];
X            know[playerx][playery] = 0;
X            item[playerx][playery] = iarg[playerx][playery] = 0 ;
X            read_scroll( i );
X            break;
X        }
X    return( 1 );
X    }
X
Xstatic int consume( search_item, prompt, showfunc )
Xint search_item ;
Xchar *prompt;
Xint (*showfunc)();
X    {
X    register int i;
X
X    while (1)
X        {
X        if ((i = whatitem( prompt )) == '\33')
X            return;
X        if (i != '.' && i != '-')
X            {
X            if (i == '*')
X                {
X                i = showfunc();
X                cursors();
X                }
X            if (i && i != '.')
X                {
X                switch (iven[i-'a'])
X                    {
X                    case OSCROLL:
X                        if ( search_item != OSCROLL )
X                            {
X                            lprintf("\nYou can't %s that.", prompt );
X                            return;
X                            }
X                        read_scroll( ivenarg[i-'a'] );
X                        break;
X                    case OBOOK:
X                        if ( search_item != OSCROLL )
X                            {
X                            lprintf("\nYou can't %s that.", prompt );
X                            return;
X                            }
X                        readbook( ivenarg[i-'a'] );
X                        break;
X                    case OCOOKIE:
X                        if ( search_item != OCOOKIE )
X                            {
X                            lprintf("\nYou can't %s that.", prompt );
X                            return;
X                            }
X                        outfortune();
X                        break;
X                    case OPOTION:
X                        if ( search_item != OPOTION )
X                            {
X                            lprintf("\nYou can't %s that.", prompt );
X                            return;
X                            }
X                        quaffpotion( ivenarg[i-'a'], TRUE );
X                        break;
X                    case 0:
X                        ydhi(i);
X                        return;
X                    default:
X                        lprintf("\nYou can't %s that.", prompt );
X                        return;
X                    }
X                iven[i-'a'] = 0;
X                return;
X                }
X            }
X        }
X    }
X
X/*
X    function to ask what player wants to do
X */
Xstatic whatitem(str)
X    char *str;
X    {
X    int i=0;
X    cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
X    while (i>'z' || (i<'a' && i!='-' && i!='*' && i!='\33' && i!='.'))
X        i=ttgetch();
X    if (i=='\33')
X        lprcat(" aborted");
X    return(i);
X    }
X
X/*
X    subroutine to get a number from the player
X    and allow * to mean return amt, else return the number entered
X */
Xunsigned long readnum(mx)
X    long mx;
X    {
X    register int i;
X    register unsigned long amt=0;
X
X    sncbr();
X    /* allow him to say * for all gold 
X    */
X    if ((i=ttgetch()) == '*')
X        amt = mx;
X    else
X        /* read chars into buffer, deleting when requested */
X    while (i != '\n')
X        {
X        if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
X        if ((i <= '9') && (i >= '0') && (amt<999999999))
X            amt = amt*10+i-'0';
X        if ((i=='\010') || (i=='\177'))
X            amt = (long)(amt / 10) ;
X        i = ttgetch();
X        }
X    scbr();
X    return(amt);
X    }
X
X#ifdef HIDEBYLINK
X/*
X *  routine to zero every byte in a string
X */
Xszero(str)
X    register char *str;
X    {
X    while (*str)
X        *str++ = 0;
X    }
X#endif HIDEBYLINK
X
X#ifdef TIMECHECK
X/*
X *  routine to check the time of day and return 1 if its during work hours
X *  checks the file ".holidays" for forms like "mmm dd comment..."
X */
Xint playable()
X    {
X    long g_time,time();
X    int hour,day,year;
X    char *date,*month,*p;
X
X    time(&g_time);  /* get the time and date */
X    date = ctime(&g_time); /* format: Fri Jul  4 00:27:56 EDT 1986 */
X    year = atoi(date+20);
X    hour = (date[11]-'0')*10 + date[12]-'0';
X    day  = (date[8]!=' ') ? ((date[8]-'0')*10 + date[9]-'0') : (date[9]-'0');
X    month = date+4;  date[7]=0; /* point to and NULL terminate month */
X
X    if (((hour>=8 && hour<17)) /* 8AM - 5PM */
X        && strncmp("Sat",date,3)!=0     /* not a Saturday */
X        && strncmp("Sun",date,3)!=0)    /* not a Sunday */
X            {
X        /* now check for a .holidays datafile */
X            lflush();
X            if (lopen(holifile) >= 0)
X                for ( ; ; )
X                    {
X                    if ((p=lgetw())==0) break;
X                    if (strlen(p)<6) continue;
X                    if ((strncmp(p,month,3)==0) && (day==atoi(p+4)) && (year==atoi(p+7)))
X                        return(0); /* a holiday */
X                    }
X            lrclose();  lcreat((char*)0);
X            return(1);
X            }
X    return(0);
X    }
X#endif TIMECHECK
END_OF_FILE
if test 40768 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'tgoto.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tgoto.c'\"
else
echo shar: Extracting \"'tgoto.c'\" \(6360 characters\)
sed "s/^X//" >'tgoto.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 *  tgoto   expand cursor addressing string from cm capability
X *
X *  KEY WORDS
X *
X *  termcap
X *
X *  SYNOPSIS
X *
X *  char *tgoto(cm,destcol,destline)
X *  char *cm;
X *  int destcol;
X *  int destline;
X *
X *  DESCRIPTION
X *
X *  Returns cursor addressing string, decoded from the cm
X *  capability string, to move cursor to column destcol on
X *  line destline.
X *
X *  The following sequences uses one input argument, either
X *  line or column, and place the appropriate substitution
X *  in the output string:
X *
X *      %d  substitute decimal value (in ASCII)
X *      %2  like %d but forces field width to 2
X *      %3  like %d but forces field width to 3
X *      %.  like %c
X *      %+x like %c but adds ASCII value of x
X *
X *  The following sequences cause processing modifications
X *  but do not "use up" one of the arguments.  If they
X *  act on an argument they act on the next one to
X *  be converted.
X *
X *      %>xy    if next value to be converted is
X *          greater than value of ASCII char x
X *          then add value of ASCII char y.
X *      %r  reverse substitution of line
X *          and column (line is substituted
X *          first by default).
X *      %i  causes input values destcol and
X *          destline to be incremented.
X *      %%  gives single % character in output.
X *
X *  BUGS
X *
X *  Does not implement some of the more arcane sequences for
X *  radically weird terminals (specifically %n, %B, & %D).
X *  If you have one of these you deserve whatever happens.
X *
X */
X
X/*
X *  Miscellaneous stuff
X */
X
X#include <stdio.h>
X
X#define MAXARGS 2
X
Xstatic char *in;        /* Internal copy of input string pointer */
Xstatic char *out;       /* Pointer to output array */
Xstatic int args[MAXARGS];   /* Maximum number of args to convert */
Xstatic int pcount;      /* Count of args processed */
Xstatic char output[64];     /* Converted string */
X
X
X/*
X *  PSEUDO CODE
X *
X *  Begin tgoto
X *      If no string to process then
X *      Return pointer to error string.
X *      Else
X *      Initialize pointer to input string.
X *      Initialize pointer to result string.
X *      First arg is line number by default.
X *      Second arg is col number by default.
X *      No arguments processed yet.
X *      While there is another character to process
X *          If character is a not a % character then
X *          Simply copy to output.
X *          Else
X *          Process the control sequence.
X *          End if
X *      End while
X *      TERMINATE STRING!  (rde)
X *      Return pointer to static output string.
X *      End if
X *  End tgoto
X *
X */
X
Xchar *tgoto(cm,destcol,destline)
Xchar *cm;
Xint destcol;
Xint destline;
X{
X    if (cm == NULL) {
X    return("OOPS");
X    } else {
X    in = cm;
X    out = output;
X    args[0] = destline;
X    args[1] = destcol;
X    pcount = 0;
X    while (*in != NULL) {
X        if (*in != '%') {
X        *out++ = *in++;
X        } else {
X        process();
X        }
X    }
X    *out = '\0';    /* rde 18-DEC-86: don't assume out was all zeros */
X    return(output);
X    }
X}
X
X/*
X *  INTERNAL FUNCTION
X *
X *  process   process the conversion/command sequence
X *
X *  SYNOPSIS
X *
X *  static process()
X *
X *  DESCRIPTION
X *
X *  Processes the sequence beginning with the % character.
X *  Directly manipulates the input string pointer, the
X *  output string pointer, and the arguments.  Leaves
X *  the input string pointer pointing to the next character
X *  to be processed, and the output string pointer pointing
X *  to the next output location.  If conversion of
X *  one of the numeric arguments occurs, then the pcount
X *  is incremented.
X *
X */
X
X/*
X *  PSEUDO CODE
X *
X *  Begin process
X *      Skip over the % character.
X *      Switch on next character after %
X *      Case 'd':
X *      Process %d type conversion (variable width).
X *      Reinitialize output pointer.
X *      Break;
X *      Case '2':
X *      Process %d type conversion (width 2).
X *      Reinitialize output pointer.
X *      Break;
X *      Case '3':
X *      Process %d type conversion (width 3).
X *      Reinitialize output pointer.
X *      Break;
X *      Case '.'
X *      Process %c type conversion.
X *      Break;
X *      Case '+':
X *      Process %c type conversion with offset.
X *      Break;
X *      Case '>':
X *      Process argument modification.
X *      Break;
X *      Case 'r':
X *      Process argument reversal.
X *      Break;
X *      Case 'i':
X *      Increment argument values.
X *      Break;
X *      Case '%':
X *      Copy to output, incrementing pointers.
X *      Break;
X *      End switch
X *  End process
X *
X */
X
X
Xstatic process()
X{
X    int temp;
X
X    in++;
X    switch(*in++) {
X    case 'd':
X    sprintf(out,"%d",args[pcount++]);
X    out = &output[strlen(output)];  
X    break;
X    case '2':
X    sprintf(out,"%02d",args[pcount++]);
X    out += 2 ;
X/*
X    out = &output[strlen(output)];
X*/
X    break;
X    case '3':
X    sprintf(out,"%03d",args[pcount++]);
X    out = &output[strlen(output)];
X    break;
X    case '.':
X    *out++ = args[pcount++];
X    break;
X    case '+':
X    *out++ = args[pcount++] + *in++;
X    break;
X    case '>':
X    if (args[pcount] > *in++) {
X        args[pcount] += *in++;
X    } else {
X        in++;
X    }
X    break;
X    case 'r':
X    temp = args[pcount];
X    args[pcount] = args[pcount+1];
X    args[pcount+1] = temp;
X    break;
X    case 'i':
X    args[pcount]++;
X    args[pcount+1]++;
X    break;
X    case '%':
X    *out++ = '%';
X    break;
X    }
X}
END_OF_FILE
if test 6360 -ne `wc -c <'tgoto.c'`; then
    echo shar: \"'tgoto.c'\" unpacked with wrong size!
fi
# end of 'tgoto.c'
fi
echo shar: End of archive 1 \(of 12\).
cp /dev/null ark1isdone
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