root/games/larn/tok.c
/*      $NetBSD: tok.c,v 1.11 2012/06/19 05:30:44 dholland Exp $        */

/* tok.c                Larn is copyrighted 1986 by Noah Morgan. */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: tok.c,v 1.11 2012/06/19 05:30:44 dholland Exp $");
#endif                          /* not lint */

#include <sys/types.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <ctype.h>
#include "header.h"
#include "extern.h"

/* Keystrokes (roughly) between checkpoints */
#define CHECKPOINT_INTERVAL     400

static char     lastok = 0;
int             yrepcount = 0;
#ifndef FLUSHNO
#define FLUSHNO 5
#endif  /* FLUSHNO */
static int      flushno = FLUSHNO;      /* input queue flushing threshold */
#define MAXUM 52                /* maximum number of user re-named monsters */
#define MAXMNAME 40             /* max length of a monster re-name */
static char     usermonster[MAXUM][MAXMNAME];   /* the user named monster
                                                 * name goes here */
static u_char     usermpoint = 0;       /* the user monster pointer */

/*
        lexical analyzer for larn
 */
int
yylex(void)
{
        char            cc;
        int             ic;
        if (hit2flag) {
                hit2flag = 0;
                yrepcount = 0;
                return (' ');
        }
        if (yrepcount > 0) {
                --yrepcount;
                return (lastok);
        } else
                yrepcount = 0;
        if (yrepcount == 0) {
                bottomdo();
                showplayer();
        }                       /* show where the player is      */
        lflush();
        while (1) {
                c[BYTESIN]++;
                /* check for periodic checkpointing */
                if (ckpflag)
                        if ((c[BYTESIN] % CHECKPOINT_INTERVAL) == 0) {
#ifndef DOCHECKPOINTS
                                savegame(ckpfile);
#else
                                wait(0);        /* wait for other forks to
                                                 * finish */
                                if (fork() == 0) {
                                        savegame(ckpfile);
                                        exit();
                                }
#endif
                        }
                do {            /* if keyboard input buffer is too big, flush
                                 * some of it */
                        ioctl(0, FIONREAD, &ic);
                        if (ic > flushno)
                                read(0, &cc, 1);
                }
                while (ic > flushno);

                if (read(0, &cc, 1) != 1)
                        return (lastok = -1);

                if (cc == 'Y' - 64) {   /* control Y -- shell escape */
                        resetscroll();
                        clear();/* scrolling region, home, clear, no
                                 * attributes */
                        if ((ic = fork()) == 0) {       /* child */
                                execl("/bin/csh", "/bin/csh", NULL);
                                exit(1);
                        }
                        wait(0);
                        if (ic < 0) {   /* error */
                                write(2, "Can't fork off a shell!\n", 25);
                                sleep(2);
                        }
                        setscroll();
                        return (lastok = 'L' - 64);     /* redisplay screen */
                }
                if ((cc <= '9') && (cc >= '0')) {
                        yrepcount = yrepcount * 10 + cc - '0';
                } else {
                        if (yrepcount > 0)
                                --yrepcount;
                        return (lastok = cc);
                }
        }
}

/*
 *      flushall()              Function to flush all type-ahead in the input buffer
 */
void
flushall(void)
{
        char            cc;
        int             ic;
        for (;;) {              /* if keyboard input buffer is too big, flush
                                 * some of it */
                ioctl(0, FIONREAD, &ic);
                if (ic <= 0)
                        return;
                while (ic > 0) {
                        read(0, &cc, 1);
                        --ic;
                }               /* gobble up the byte */
        }
}

/*
        function to set the desired hardness
        enter with hard= -1 for default hardness, else any desired hardness
 */
void
sethard(int hard)
{
        int    j, k, i;
        struct monst *mp;

        j = c[HARDGAME];
        hashewon();
        if (restorflag == 0) {  /* don't set c[HARDGAME] if restoring game */
                if (hard >= 0)
                        c[HARDGAME] = hard;
        } else
                c[HARDGAME] = j;/* set c[HARDGAME] to proper value if
                                 * restoring game */

        if ((k = c[HARDGAME]) != 0)
                for (j = 0; j <= MAXMONST + 8; j++) {
                        mp = &monster[j];
                        i = ((6 + k) * mp->hitpoints + 1) / 6;
                        mp->hitpoints = (i < 0) ? 32767 : i;
                        i = ((6 + k) * mp->damage + 1) / 5;
                        mp->damage = (i > 127) ? 127 : i;
                        i = (10 * mp->gold) / (10 + k);
                        mp->gold = (i > 32767) ? 32767 : i;
                        i = mp->armorclass - k;
                        mp->armorclass = (i < -127) ? -127 : i;
                        i = (7 * mp->experience) / (7 + k) + 1;
                        mp->experience = (i <= 0) ? 1 : i;
                }
}

/*
        function to read and process the larn options file
 */
void
readopts(void)
{
        const char  *i;
        int    j, k;
        int             flag;

        flag = 1;               /* set to 0 if a name is specified */

        if (lopen(optsfile) < 0) {
                strcpy(logname, loginname);
                return;         /* user name if no character name */
        }
        i = " ";
        while (*i) {
                if ((i = lgetw()) == NULL)
                        break;  /* check for EOF */
                while ((*i == ' ') || (*i == '\t'))
                        i++;    /* eat leading whitespace */

                if (strcmp(i, "bold-objects") == 0)
                        boldon = 1;
                else if (strcmp(i, "enable-checkpointing") == 0)
                        ckpflag = 1;
                else if (strcmp(i, "inverse-objects") == 0)
                        boldon = 0;
                else if (strcmp(i, "female") == 0)
                        sex = 0;        /* male or female */
                else if (strcmp(i, "monster:") == 0) {  /* name favorite monster */
                        if ((i = lgetw()) == 0)
                                break;
                        strlcpy(usermonster[usermpoint], i, MAXMNAME);
                        if (usermpoint >= MAXUM)
                                continue;       /* defined all of em */
                        if (isalpha(j = usermonster[usermpoint][0])) {
                                for (k = 1; k < MAXMONST + 8; k++)      /* find monster */
                                        if (monstnamelist[k] == j) {
                                                monster[k].name = &usermonster[usermpoint++][0];
                                                break;
                                        }
                        }
                } else if (strcmp(i, "male") == 0)
                        sex = 1;
                else if (strcmp(i, "name:") == 0) {     /* defining players name */
                        if ((i = lgetw()) == 0)
                                break;
                        strlcpy(logname, i, LOGNAMESIZE);
                        flag = 0;
                } else if (strcmp(i, "no-introduction") == 0)
                        nowelcome = 1;
                else if (strcmp(i, "no-beep") == 0)
                        nobeep = 1;
                else if (strcmp(i, "process-name:") == 0) {
                        if ((i = lgetw()) == 0)
                                break;
                        strlcpy(psname, i, PSNAMESIZE);
                } else if (strcmp(i, "play-day-play") == 0) {
                        /* bypass time restrictions: ignored */
                } else if (strcmp(i, "savefile:") == 0) {       /* defining savefilename */
                        if ((i = lgetw()) == 0)
                                break;
                        strcpy(savefilename, i);
                        flag = 0;
                }
        }
        if (flag)
                strcpy(logname, loginname);
}