term.c revision 1.1
11.1Skamil/* $Header: /tank/opengrok/rsync2/NetBSD/src/games/warp/term.c,v 1.1 2020/11/09 23:37:05 kamil Exp $ */
21.1Skamil
31.1Skamil/* $Log: term.c,v $
41.1Skamil/* Revision 1.1  2020/11/09 23:37:05  kamil
51.1Skamil/* Add Warp Kit, Version 7.0 by Larry Wall
61.1Skamil/*
71.1Skamil/* Warp is a real-time space war game that doesn't get boring very quickly.
81.1Skamil/* Read warp.doc and the manual page for more information.
91.1Skamil/*
101.1Skamil/* games/warp originally distributed with 4.3BSD-Reno, is back to the BSD
111.1Skamil/* world via NetBSD. Its remnants were still mentioned in games/Makefile.
121.1Skamil/*
131.1Skamil/* Larry Wall, the original author and the copyright holder, generously
141.1Skamil/* donated the game and copyright to The NetBSD Foundation, Inc.
151.1Skamil/*
161.1Skamil/* Import the game sources as-is from 4.3BSD-Reno, with the cession
171.1Skamil/* of the copyright and license to BSD-2-clause NetBSD-style.
181.1Skamil/*
191.1Skamil/* Signed-off-by: Larry Wall <larry@wall.org>
201.1Skamil/* Signed-off-by: Kamil Rytarowski <kamil@netbsd.org>
211.1Skamil/*
221.1Skamil * Revision 7.0.1.2  86/12/12  17:04:09  lwall
231.1Skamil * Baseline for net release.
241.1Skamil *
251.1Skamil * Revision 7.0.1.1  86/10/16  10:53:20  lwall
261.1Skamil * Added Damage.  Fixed random bugs.
271.1Skamil *
281.1Skamil * Revision 7.0  86/10/08  15:14:02  lwall
291.1Skamil * Split into separate files.  Added amoebas and pirates.
301.1Skamil *
311.1Skamil */
321.1Skamil
331.1Skamil#include "EXTERN.h"
341.1Skamil#include "warp.h"
351.1Skamil#include "bang.h"
361.1Skamil#include "intrp.h"
371.1Skamil#include "object.h"
381.1Skamil#include "play.h"
391.1Skamil#include "score.h"
401.1Skamil#include "sig.h"
411.1Skamil#include "us.h"
421.1Skamil#include "util.h"
431.1Skamil#include "weapon.h"
441.1Skamil#include "INTERN.h"
451.1Skamil#include "term.h"
461.1Skamil
471.1Skamilint typeahead = FALSE;
481.1Skamil
491.1Skamilchar tcarea[TCSIZE];	/* area for "compiled" termcap strings */
501.1Skamil
511.1Skamil/* guarantee capability pointer != Nullch */
521.1Skamil/* (I believe terminfo will ignore the &tmpaddr argument.) */
531.1Skamil
541.1Skamil#define Tgetstr(key) ((tstr = tgetstr(key,&tmpaddr)) ? tstr : nullstr)
551.1Skamil
561.1Skamil#ifdef PUSHBACK
571.1Skamilstruct keymap {
581.1Skamil    char km_type[128];
591.1Skamil    union km_union {
601.1Skamil	struct keymap *km_km;
611.1Skamil	char *km_str;
621.1Skamil    } km_ptr[128];
631.1Skamil};
641.1Skamil
651.1Skamil#define KM_NOTHIN 0
661.1Skamil#define KM_STRING 1
671.1Skamil#define KM_KEYMAP 2
681.1Skamil#define KM_BOGUS 3
691.1Skamil
701.1Skamil#define KM_TMASK 3
711.1Skamil#define KM_GSHIFT 4
721.1Skamil#define KM_GMASK 7
731.1Skamil
741.1Skamiltypedef struct keymap KEYMAP;
751.1Skamil
761.1SkamilKEYMAP *topmap INIT(Null(KEYMAP*));
771.1Skamil
781.1Skamilvoid mac_init();
791.1SkamilKEYMAP *newkeymap();
801.1Skamilvoid pushstring();
811.1Skamil#endif
821.1Skamil
831.1Skamil/* terminal initialization */
841.1Skamil
851.1Skamilvoid
861.1Skamilterm_init()
871.1Skamil{
881.1Skamil    savetty();				/* remember current tty state */
891.1Skamil
901.1Skamil#ifdef TERMIO
911.1Skamil    ospeed = _tty.c_cflag & CBAUD;	/* for tputs() */
921.1Skamil    ERASECH = _tty.c_cc[VERASE];	/* for finish_command() */
931.1Skamil    KILLCH = _tty.c_cc[VKILL];		/* for finish_command() */
941.1Skamil#else
951.1Skamil    ospeed = _tty.sg_ospeed;		/* for tputs() */
961.1Skamil    ERASECH = _tty.sg_erase;		/* for finish_command() */
971.1Skamil    KILLCH = _tty.sg_kill;		/* for finish_command() */
981.1Skamil#endif
991.1Skamil
1001.1Skamil    /* The following could be a table but I can't be sure that there isn't */
1011.1Skamil    /* some degree of sparsity out there in the world. */
1021.1Skamil
1031.1Skamil    switch (ospeed) {			/* 1 second of padding */
1041.1Skamil#ifdef BEXTA
1051.1Skamil        case BEXTA:  just_a_sec = 1920; break;
1061.1Skamil#else
1071.1Skamil#ifdef B19200
1081.1Skamil        case B19200: just_a_sec = 1920; break;
1091.1Skamil#endif
1101.1Skamil#endif
1111.1Skamil        case B9600:  just_a_sec =  960; break;
1121.1Skamil        case B4800:  just_a_sec =  480; break;
1131.1Skamil        case B2400:  just_a_sec =  240; break;
1141.1Skamil        case B1800:  just_a_sec =  180; break;
1151.1Skamil        case B1200:  just_a_sec =  120; break;
1161.1Skamil        case B600:   just_a_sec =   60; break;
1171.1Skamil	case B300:   just_a_sec =   30; break;
1181.1Skamil	/* do I really have to type the rest of this??? */
1191.1Skamil        case B200:   just_a_sec =   20; break;
1201.1Skamil        case B150:   just_a_sec =   15; break;
1211.1Skamil        case B134:   just_a_sec =   13; break;
1221.1Skamil        case B110:   just_a_sec =   11; break;
1231.1Skamil        case B75:    just_a_sec =    8; break;
1241.1Skamil        case B50:    just_a_sec =    5; break;
1251.1Skamil        default:     just_a_sec =  960; break;
1261.1Skamil					/* if we are running detached I */
1271.1Skamil    }					/*  don't want to know about it! */
1281.1Skamil}
1291.1Skamil
1301.1Skamil/* set terminal characteristics */
1311.1Skamil
1321.1Skamilvoid
1331.1Skamilterm_set(tcbuf)
1341.1Skamilchar *tcbuf;		/* temp area for "uncompiled" termcap entry */
1351.1Skamil{
1361.1Skamil    char *tmpaddr;			/* must not be register */
1371.1Skamil    Reg1 char *tstr;
1381.1Skamil    char *tgetstr();
1391.1Skamil    char *s;
1401.1Skamil    int retval;
1411.1Skamil
1421.1Skamil#ifdef PENDING
1431.1Skamil#ifndef FIONREAD
1441.1Skamil#ifndef RDCHK
1451.1Skamil    /* do no delay reads on something that always gets closed on exit */
1461.1Skamil
1471.1Skamil    devtty = open("/dev/tty",0);
1481.1Skamil    if (devtty < 0) {
1491.1Skamil	printf(cantopen,"/dev/tty");
1501.1Skamil	finalize(1);
1511.1Skamil    }
1521.1Skamil    fcntl(devtty,F_SETFL,O_NDELAY);
1531.1Skamil#endif
1541.1Skamil#endif
1551.1Skamil#endif
1561.1Skamil
1571.1Skamil    /* get all that good termcap stuff */
1581.1Skamil
1591.1Skamil    retval = tgetent(tcbuf,getenv("TERM"));	/* get termcap entry */
1601.1Skamil    if (retval < 1) {
1611.1Skamil#ifdef VERBOSE
1621.1Skamil	printf("No termcap %s found.\n", retval ? "file" : "entry");
1631.1Skamil#else
1641.1Skamil	fputs("Termcap botch\n",stdout);
1651.1Skamil#endif
1661.1Skamil	finalize(1);
1671.1Skamil    }
1681.1Skamil    tmpaddr = tcarea;			/* set up strange tgetstr pointer */
1691.1Skamil    s = Tgetstr("pc");			/* get pad character */
1701.1Skamil    PC = *s;				/* get it where tputs wants it */
1711.1Skamil    if (!tgetflag("bs")) {		/* is backspace not used? */
1721.1Skamil	BC = Tgetstr("bc");		/* find out what is */
1731.1Skamil	if (BC == nullstr) 		/* terminfo grok's 'bs' but not 'bc' */
1741.1Skamil	    BC = Tgetstr("le");
1751.1Skamil    } else
1761.1Skamil	BC = "\b";			/* make a backspace handy */
1771.1Skamil    UP = Tgetstr("up");			/* move up a line */
1781.1Skamil    ND = Tgetstr("nd");			/* non-destructive move cursor right */
1791.1Skamil    DO = Tgetstr("do");			/* move cursor down */
1801.1Skamil    if (!*DO)
1811.1Skamil	DO = Tgetstr("nl");
1821.1Skamil    CL = Tgetstr("cl");			/* get clear string */
1831.1Skamil    CE = Tgetstr("ce");			/* clear to end of line string */
1841.1Skamil    CM = Tgetstr("cm");			/* cursor motion - PWP */
1851.1Skamil    HO = Tgetstr("ho");			/* home cursor if no CM - PWP */
1861.1Skamil    CD = Tgetstr("cd");			/* clear to end of display - PWP */
1871.1Skamil    SO = Tgetstr("so");			/* begin standout */
1881.1Skamil    SE = Tgetstr("se");			/* end standout */
1891.1Skamil    if ((SG = tgetnum("sg"))<0)
1901.1Skamil	SG = 0;				/* blanks left by SG, SE */
1911.1Skamil    US = Tgetstr("us");			/* start underline */
1921.1Skamil    UE = Tgetstr("ue");			/* end underline */
1931.1Skamil    if ((UG = tgetnum("ug"))<0)
1941.1Skamil	UG = 0;				/* blanks left by US, UE */
1951.1Skamil    if (*US)
1961.1Skamil	UC = nullstr;			/* UC must not be NULL */
1971.1Skamil    else
1981.1Skamil	UC = Tgetstr("uc");		/* underline a character */
1991.1Skamil    if (!*US && !*UC) {			/* no underline mode? */
2001.1Skamil	US = SO;			/* substitute standout mode */
2011.1Skamil	UE = SE;
2021.1Skamil	UG = SG;
2031.1Skamil    }
2041.1Skamil    LINES = tgetnum("li");		/* lines per page */
2051.1Skamil    COLS = tgetnum("co");		/* columns on page */
2061.1Skamil    AM = tgetflag("am");		/* terminal wraps automatically? */
2071.1Skamil    XN = tgetflag("xn");		/* then eats next newline? */
2081.1Skamil    VB = Tgetstr("vb");
2091.1Skamil    if (!*VB)
2101.1Skamil	VB = "\007";
2111.1Skamil    CR = Tgetstr("cr");
2121.1Skamil    if (!*CR) {
2131.1Skamil	if (tgetflag("nc") && *UP) {
2141.1Skamil	    CR = safemalloc((MEM_SIZE)strlen(UP)+2);
2151.1Skamil	    Sprintf(CR,"%s\r",UP);
2161.1Skamil	}
2171.1Skamil	else
2181.1Skamil	    CR = "\r";
2191.1Skamil    }
2201.1Skamil    if (LINES <= 0)
2211.1Skamil	LINES = 24;
2221.1Skamil    if (COLS <= 0)
2231.1Skamil	COLS = 80;
2241.1Skamil
2251.1Skamil    BCsize = comp_tc(bsptr,BC,1);
2261.1Skamil    BC = bsptr;
2271.1Skamil
2281.1Skamil    if (!*ND)				/* not defined? */
2291.1Skamil	NDsize = 1000;			/* force cursor addressing */
2301.1Skamil    else {
2311.1Skamil	NDsize = comp_tc(cmbuffer,ND,1);
2321.1Skamil	myND = malloc((unsigned)NDsize);
2331.1Skamil	movc3(NDsize,cmbuffer,myND);
2341.1Skamil	if (debugging) {
2351.1Skamil	    int scr;
2361.1Skamil
2371.1Skamil	    printf("ND");
2381.1Skamil	    for (scr=0; scr<NDsize; scr++)
2391.1Skamil		printf(" %d",myND[scr]);
2401.1Skamil	    printf("\n");
2411.1Skamil	}
2421.1Skamil    }
2431.1Skamil
2441.1Skamil    if (!*UP)				/* not defined? */
2451.1Skamil	UPsize = 1000;			/* force cursor addressing */
2461.1Skamil    else {
2471.1Skamil	UPsize = comp_tc(cmbuffer,UP,1);
2481.1Skamil	myUP = malloc((unsigned)UPsize);
2491.1Skamil	movc3(UPsize,cmbuffer,myUP);
2501.1Skamil	if (debugging) {
2511.1Skamil	    int scr;
2521.1Skamil
2531.1Skamil	    printf("UP");
2541.1Skamil	    for (scr=0; scr<UPsize; scr++)
2551.1Skamil		printf(" %d",myUP[scr]);
2561.1Skamil	    printf("\n");
2571.1Skamil	}
2581.1Skamil    }
2591.1Skamil
2601.1Skamil    if (!*DO) {				/* not defined? */
2611.1Skamil	myDO = DO = "\n";		/* assume a newline */
2621.1Skamil	DOsize = 1;
2631.1Skamil    }
2641.1Skamil    else {
2651.1Skamil	DOsize = comp_tc(cmbuffer,DO,1);
2661.1Skamil	myDO = malloc((unsigned)DOsize);
2671.1Skamil	movc3(DOsize,cmbuffer,myDO);
2681.1Skamil	if (debugging) {
2691.1Skamil	    int scr;
2701.1Skamil
2711.1Skamil	    printf("DO");
2721.1Skamil	    for (scr=0; scr<DOsize; scr++)
2731.1Skamil		printf(" %d",myDO[scr]);
2741.1Skamil	    printf("\n");
2751.1Skamil	}
2761.1Skamil    }
2771.1Skamil    if (debugging)
2781.1Skamil	Fgets(cmbuffer,(sizeof cmbuffer),stdin);
2791.1Skamil
2801.1Skamil    CMsize = comp_tc(cmbuffer,tgoto(CM,20,20),0);
2811.1Skamil    if (PC != '\0') {
2821.1Skamil	char *p;
2831.1Skamil
2841.1Skamil	for (p=filler+(sizeof filler)-1;!*p;--p)
2851.1Skamil	    *p = PC;
2861.1Skamil    }
2871.1Skamil    charsperhalfsec = ospeed >= B9600 ? 480 :
2881.1Skamil		      ospeed == B4800 ? 240 :
2891.1Skamil		      ospeed == B2400 ? 120 :
2901.1Skamil		      ospeed == B1200 ? 60 :
2911.1Skamil		      ospeed == B600 ? 30 :
2921.1Skamil	      /* speed is 300 (?) */   15;
2931.1Skamil
2941.1Skamil    gfillen = ospeed >= B9600 ? (sizeof filler) :
2951.1Skamil	      ospeed == B4800 ? 13 :
2961.1Skamil	      ospeed == B2400 ? 7 :
2971.1Skamil	      ospeed == B1200 ? 4 :
2981.1Skamil				1+BCsize;
2991.1Skamil    if (ospeed < B2400)
3001.1Skamil	lowspeed = TRUE;
3011.1Skamil
3021.1Skamil    strcpy(term,ttyname(2));
3031.1Skamil
3041.1Skamil    if (!*CM || !BCsize)
3051.1Skamil	no_can_do("dumb");
3061.1Skamil    if (!scorespec && (LINES < 24 || COLS < 80))
3071.1Skamil	no_can_do("puny");
3081.1Skamil
3091.1Skamil    crmode();
3101.1Skamil    raw();
3111.1Skamil    noecho();				/* turn off echo */
3121.1Skamil    nonl();
3131.1Skamil
3141.1Skamil#ifdef PUSHBACK
3151.1Skamil    mac_init(tcbuf);
3161.1Skamil#endif
3171.1Skamil}
3181.1Skamil
3191.1Skamil#ifdef PUSHBACK
3201.1Skamilvoid
3211.1Skamilmac_init(tcbuf)
3221.1Skamilchar *tcbuf;
3231.1Skamil{
3241.1Skamil    char tmpbuf[1024];
3251.1Skamil
3261.1Skamil    tmpfp = fopen(filexp(getval("WARPMACRO",WARPMACRO)),"r");
3271.1Skamil    if (tmpfp != Nullfp) {
3281.1Skamil	while (fgets(tcbuf,1024,tmpfp) != Nullch) {
3291.1Skamil	    mac_line(tcbuf,tmpbuf,(sizeof tmpbuf));
3301.1Skamil	}
3311.1Skamil	Fclose(tmpfp);
3321.1Skamil    }
3331.1Skamil}
3341.1Skamil
3351.1Skamilvoid
3361.1Skamilmac_line(line,tmpbuf,tbsize)
3371.1Skamilchar *line;
3381.1Skamilchar *tmpbuf;
3391.1Skamilint tbsize;
3401.1Skamil{
3411.1Skamil    Reg1 char *s;
3421.1Skamil    Reg2 char *m;
3431.1Skamil    Reg3 KEYMAP *curmap;
3441.1Skamil    Reg4 int ch;
3451.1Skamil    Reg5 int garbage = 0;
3461.1Skamil    static char override[] = "\r\nkeymap overrides string\r\n";
3471.1Skamil
3481.1Skamil    if (topmap == Null(KEYMAP*))
3491.1Skamil	topmap = newkeymap();
3501.1Skamil    if (*line == '#' || *line == '\n')
3511.1Skamil	return;
3521.1Skamil    if (line[ch = strlen(line)-1] == '\n')
3531.1Skamil	line[ch] = '\0';
3541.1Skamil    m = dointerp(tmpbuf,tbsize,line," \t");
3551.1Skamil    if (!*m)
3561.1Skamil	return;
3571.1Skamil    while (*m == ' ' || *m == '\t') m++;
3581.1Skamil    for (s=tmpbuf,curmap=topmap; *s; s++) {
3591.1Skamil	ch = *s & 0177;
3601.1Skamil	if (s[1] == '+' && isdigit(s[2])) {
3611.1Skamil	    s += 2;
3621.1Skamil	    garbage = (*s & KM_GMASK) << KM_GSHIFT;
3631.1Skamil	}
3641.1Skamil	else
3651.1Skamil	    garbage = 0;
3661.1Skamil	if (s[1]) {
3671.1Skamil	    if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) {
3681.1Skamil		puts(override);
3691.1Skamil		free(curmap->km_ptr[ch].km_str);
3701.1Skamil		curmap->km_ptr[ch].km_str = Nullch;
3711.1Skamil	    }
3721.1Skamil	    curmap->km_type[ch] = KM_KEYMAP + garbage;
3731.1Skamil	    if (curmap->km_ptr[ch].km_km == Null(KEYMAP*))
3741.1Skamil		curmap->km_ptr[ch].km_km = newkeymap();
3751.1Skamil	    curmap = curmap->km_ptr[ch].km_km;
3761.1Skamil	}
3771.1Skamil	else {
3781.1Skamil	    if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP)
3791.1Skamil		puts(override);
3801.1Skamil	    else {
3811.1Skamil		curmap->km_type[ch] = KM_STRING + garbage;
3821.1Skamil		curmap->km_ptr[ch].km_str = savestr(m);
3831.1Skamil	    }
3841.1Skamil	}
3851.1Skamil    }
3861.1Skamil}
3871.1Skamil
3881.1SkamilKEYMAP*
3891.1Skamilnewkeymap()
3901.1Skamil{
3911.1Skamil    Reg1 int i;
3921.1Skamil    Reg2 KEYMAP *map;
3931.1Skamil
3941.1Skamil#ifndef lint
3951.1Skamil    map = (KEYMAP*)safemalloc(sizeof(KEYMAP));
3961.1Skamil#else
3971.1Skamil    map = Null(KEYMAP*);
3981.1Skamil#endif /* lint */
3991.1Skamil    for (i=127; i>=0; --i) {
4001.1Skamil	map->km_ptr[i].km_km = Null(KEYMAP*);
4011.1Skamil	map->km_type[i] = KM_NOTHIN;
4021.1Skamil    }
4031.1Skamil    return map;
4041.1Skamil}
4051.1Skamil
4061.1Skamil#endif
4071.1Skamil
4081.1Skamil/* print out a file, stopping at form feeds */
4091.1Skamil
4101.1Skamilvoid
4111.1Skamilpage(filename,num)
4121.1Skamilchar *filename;
4131.1Skamilbool num;
4141.1Skamil{
4151.1Skamil    int linenum = 1;
4161.1Skamil
4171.1Skamil    tmpfp = fopen(filename,"r");
4181.1Skamil    if (tmpfp != NULL) {
4191.1Skamil	while (fgets(spbuf,(sizeof spbuf),tmpfp) != NULL) {
4201.1Skamil	    if (*spbuf == '\f') {
4211.1Skamil		printf("[Type anything to continue] ");
4221.1Skamil		Fflush(stdout);
4231.1Skamil		getcmd(spbuf);
4241.1Skamil		printf("\r\n");
4251.1Skamil		if (*spbuf == INTRCH)
4261.1Skamil		    finalize(0);
4271.1Skamil		if (*spbuf == 'q' || *spbuf == 'Q')
4281.1Skamil		    break;
4291.1Skamil	    }
4301.1Skamil	    else {
4311.1Skamil		if (num)
4321.1Skamil		    printf("%3d   %s\r",linenum++,spbuf);
4331.1Skamil		else
4341.1Skamil		    printf("%s\r",spbuf);
4351.1Skamil	    }
4361.1Skamil	}
4371.1Skamil	Fclose(tmpfp);
4381.1Skamil    }
4391.1Skamil}
4401.1Skamil
4411.1Skamilvoid
4421.1Skamilmove(y, x, chadd)
4431.1Skamilint y, x;
4441.1Skamilint chadd;
4451.1Skamil{
4461.1Skamil    Reg1 int ydist;
4471.1Skamil    Reg2 int xdist;
4481.1Skamil    Reg3 int i;
4491.1Skamil    Reg4 char *s;
4501.1Skamil
4511.1Skamil    ydist = y - real_y;
4521.1Skamil    xdist = x - real_x;
4531.1Skamil    i = ydist * (ydist < 0 ? -UPsize : DOsize) +
4541.1Skamil        xdist * (xdist < 0 ? -BCsize : NDsize);
4551.1Skamil    beg_qwrite();
4561.1Skamil    if (i <= CMsize) {
4571.1Skamil	if (ydist < 0)
4581.1Skamil	    for (; ydist; ydist++)
4591.1Skamil		for (i=UPsize,s=myUP; i; i--)
4601.1Skamil		    qaddch(*s++);
4611.1Skamil	else
4621.1Skamil	    for (; ydist; ydist--)
4631.1Skamil		for (i=DOsize,s=myDO; i; i--)
4641.1Skamil		    qaddch(*s++);
4651.1Skamil	if (xdist < 0)
4661.1Skamil	    for (; xdist; xdist++)
4671.1Skamil		for (i=BCsize,s=BC; i; i--)
4681.1Skamil		    qaddch(*s++);
4691.1Skamil	else
4701.1Skamil	    for (; xdist; xdist--)
4711.1Skamil		for (i=NDsize,s=myND; i; i--)
4721.1Skamil		    qaddch(*s++);
4731.1Skamil    }
4741.1Skamil    else {
4751.1Skamil	tputs(tgoto(CM,x,y),0,cmstore);
4761.1Skamil    }
4771.1Skamil    real_y = y;
4781.1Skamil    real_x = x;
4791.1Skamil    if (chadd) {
4801.1Skamil	qaddch(chadd);
4811.1Skamil    }
4821.1Skamil    if (maxcmstring != cmbuffer)
4831.1Skamil	end_qwrite();
4841.1Skamil}
4851.1Skamil
4861.1Skamilvoid
4871.1Skamildo_tc(s,l)
4881.1Skamilchar *s;
4891.1Skamilint l;
4901.1Skamil{
4911.1Skamil    beg_qwrite();
4921.1Skamil    tputs(s,l,cmstore);
4931.1Skamil    end_qwrite();
4941.1Skamil}
4951.1Skamil
4961.1Skamilint
4971.1Skamilcomp_tc(dest,s,l)
4981.1Skamilchar *dest;
4991.1Skamilchar *s;
5001.1Skamilint l;
5011.1Skamil{
5021.1Skamil    maxcmstring = dest;
5031.1Skamil    tputs(s,l,cmstore);
5041.1Skamil    return(maxcmstring-dest);
5051.1Skamil}
5061.1Skamil
5071.1Skamilvoid
5081.1Skamilhelper()
5091.1Skamil{
5101.1Skamil    clear();
5111.1Skamil    mvaddstr(0,4,"h or 4          left");
5121.1Skamil    mvaddstr(1,4,"j or 2          down                Use with SHIFT to fire torpedoes.");
5131.1Skamil    mvaddstr(2,4,"k or 8          up                  Use with CTRL or FUNCT to fire");
5141.1Skamil    mvaddstr(3,4,"l or 6          right                   phasers or turbolasers.");
5151.1Skamil    mvaddstr(4,4,"b or 1          down and left       Use preceded by 'a' or 'r' for");
5161.1Skamil    mvaddstr(5,4,"n or 3          down and right          attractors or repulsors.");
5171.1Skamil    mvaddstr(6,4,"y or 7          up and left         Use normally for E or B motion.");
5181.1Skamil    mvaddstr(7,4,"u or 9          up and right");
5191.1Skamil    mvaddstr(8,4,"");
5201.1Skamil    mvaddstr(9,4,"del or %        fire photon torpedoes in every (reasonable) direction.");
5211.1Skamil    mvaddstr(10,4,"s               stop all torpedoes.");
5221.1Skamil    mvaddstr(11,4,"S or 0          stop the Enterprise when in warp mode.");
5231.1Skamil    mvaddstr(12,4,"d/D             destruct all torpedoes/current vessel.");
5241.1Skamil    mvaddstr(13,4,"i/w             switch to Enterprise & put into impulse/warp mode.");
5251.1Skamil    mvaddstr(14,4,"c/v             switch to Enterprise & make cloaked/visible.");
5261.1Skamil    mvaddstr(15,4,"p               switch to Base.");
5271.1Skamil    mvaddstr(16,4,"o               toggle to other vessel (from E to B, or vice versa.)");
5281.1Skamil    mvaddstr(17,4,"z               zap (suppress) blasts near Enterprise next cycle");
5291.1Skamil    mvaddstr(18,4,"");
5301.1Skamil    mvaddstr(19,4,"^R      refresh the screen.              ^Z      suspend the game.");
5311.1Skamil    mvaddstr(20,4,"q       exit this round (if you haven't typed q within 10 cycles).");
5321.1Skamil    mvaddstr(21,4,"Q       exit this game.");
5331.1Skamil    mvaddstr(22,4,"");
5341.1Skamil    mvaddstr(23,4,"                   [Hit space to continue]");
5351.1Skamil    Fflush(stdout);
5361.1Skamil    do {
5371.1Skamil	getcmd(spbuf);
5381.1Skamil    } while (*spbuf != ' ');
5391.1Skamil    rewrite();
5401.1Skamil
5411.1Skamil}
5421.1Skamil
5431.1Skamilvoid
5441.1Skamilrewrite()
5451.1Skamil{
5461.1Skamil    Reg1 int x;
5471.1Skamil    Reg2 int y;
5481.1Skamil    Reg3 OBJECT *obj;
5491.1Skamil
5501.1Skamil    clear();
5511.1Skamil    for (y=0; y<YSIZE; y++) {
5521.1Skamil	for (x=0; x<XSIZE; x++) {
5531.1Skamil	    if (numamoebas && amb[y][x] != ' ')
5541.1Skamil		mvaddc(y+1,x*2,amb[y][x]);
5551.1Skamil	    if (obj=occupant[y][x]) {
5561.1Skamil		if (obj->image != ' ')
5571.1Skamil		    mvaddc(y+1,x*2,obj->image);
5581.1Skamil	    }
5591.1Skamil	}
5601.1Skamil    }
5611.1Skamil    Sprintf(spbuf,
5621.1Skamil    "%-4s E: %4d %2d B: %5d %3d Enemies: %-3d Stars: %-3d Stardate%5d.%1d %9ld",
5631.1Skamil	"   ", 0, 0, 0, 0, 0, 0, timer/10+smarts*100, timer%10, 0L);
5641.1Skamil    mvaddstr(0,0,spbuf);
5651.1Skamil    oldeenergy = oldbenergy = oldcurscore =
5661.1Skamil    oldstatus = oldetorp = oldbtorp = oldstrs = oldenemies = -1;
5671.1Skamil					/* force everything to fill in */
5681.1Skamil    if (damage)
5691.1Skamil	olddamage = 0;
5701.1Skamil    if (!ent)
5711.1Skamil	etorp = 0;
5721.1Skamil    if (!base)
5731.1Skamil	btorp = 0;
5741.1Skamil    display_status();
5751.1Skamil}
5761.1Skamil
5771.1Skamilchar
5781.1Skamilcmstore(ch)
5791.1SkamilReg1 char ch;
5801.1Skamil{
5811.1Skamil    *maxcmstring++ = ch;
5821.1Skamil}
5831.1Skamil
5841.1Skamil/* discard any characters typed ahead */
5851.1Skamil
5861.1Skamilvoid
5871.1Skamileat_typeahead()
5881.1Skamil{
5891.1Skamil#ifdef PUSHBACK
5901.1Skamil    if (!typeahead && nextin==nextout)	/* cancel only keyboard stuff */
5911.1Skamil#else
5921.1Skamil    if (!typeahead)
5931.1Skamil#endif
5941.1Skamil    {
5951.1Skamil#ifdef PENDING
5961.1Skamil	while (input_pending())
5971.1Skamil	    Read_tty(buf,sizeof(buf));
5981.1Skamil#else /* this is probably v7, with no rdchk() */
5991.1Skamil	ioctl(_tty_ch,TIOCSETP,&_tty);
6001.1Skamil#endif
6011.1Skamil    }
6021.1Skamil}
6031.1Skamil
6041.1Skamilvoid
6051.1Skamilsettle_down()
6061.1Skamil{
6071.1Skamil    dingaling();
6081.1Skamil    Fflush(stdout);
6091.1Skamil    sleep(1);
6101.1Skamil#ifdef PUSHBACK
6111.1Skamil    nextout = nextin;			/* empty circlebuf */
6121.1Skamil#endif
6131.1Skamil    eat_typeahead();
6141.1Skamil}
6151.1Skamil
6161.1Skamil#ifdef PUSHBACK
6171.1Skamil/* read a character from the terminal, with multi-character pushback */
6181.1Skamil
6191.1Skamilint
6201.1Skamilread_tty(addr,size)
6211.1Skamilchar *addr;
6221.1Skamilint size;	/* ignored for now */
6231.1Skamil{
6241.1Skamil#ifdef lint
6251.1Skamil    size = size;
6261.1Skamil#endif
6271.1Skamil    if (nextout != nextin) {
6281.1Skamil	*addr = circlebuf[nextout++];
6291.1Skamil	nextout %= PUSHSIZE;
6301.1Skamil	return 1;
6311.1Skamil    }
6321.1Skamil    else {
6331.1Skamil	size = read(0,addr,1);
6341.1Skamil	if (size < 0)
6351.1Skamil	    sig_catcher(SIGHUP);
6361.1Skamil	if (metakey) {
6371.1Skamil	    if (*addr & 0200) {
6381.1Skamil		pushchar(*addr & 0177);
6391.1Skamil		*addr = '\001';
6401.1Skamil	    }
6411.1Skamil	}
6421.1Skamil	else
6431.1Skamil	    *addr &= 0177;
6441.1Skamil	return 1;
6451.1Skamil    }
6461.1Skamil}
6471.1Skamil
6481.1Skamil#ifdef PENDING
6491.1Skamil#ifndef FIONREAD
6501.1Skamil#ifndef RDCHK
6511.1Skamilint
6521.1Skamilcircfill()
6531.1Skamil{
6541.1Skamil    Reg1 int howmany;
6551.1Skamil    Reg2 int i;
6561.1Skamil
6571.1Skamil    assert (nextin == nextout);
6581.1Skamil    howmany = read(devtty,circlebuf+nextin,metakey?1:PUSHSIZE-nextin);
6591.1Skamil    if (howmany > 0) {
6601.1Skamil	if (metakey) {
6611.1Skamil	    if (circlebuf[nextin] & 0200) {
6621.1Skamil		circlebuf[nextin] &= 0177;
6631.1Skamil		pushchar('\001');
6641.1Skamil	    }
6651.1Skamil	}
6661.1Skamil	else
6671.1Skamil	    for (i = howmany+nextin-1; i >= nextin; i--)
6681.1Skamil		circlebuf[i] &= 0177;
6691.1Skamil	nextin += howmany;
6701.1Skamil	nextin %= PUSHSIZE;	/* may end up 1 if metakey */
6711.1Skamil    }
6721.1Skamil    return howmany;
6731.1Skamil}
6741.1Skamil#endif /* RDCHK */
6751.1Skamil#endif /* FIONREAD */
6761.1Skamil#endif /* PENDING */
6771.1Skamil
6781.1Skamilvoid
6791.1Skamilpushchar(ch)
6801.1Skamilchar ch;
6811.1Skamil{
6821.1Skamil    nextout--;
6831.1Skamil    if (nextout < 0)
6841.1Skamil	nextout = PUSHSIZE - 1;
6851.1Skamil    if (nextout == nextin) {
6861.1Skamil	fputs("\r\npushback buffer overflow\r\n",stdout);
6871.1Skamil	sig_catcher(0);
6881.1Skamil    }
6891.1Skamil    circlebuf[nextout] = ch;
6901.1Skamil}
6911.1Skamil
6921.1Skamil#else /* PUSHBACK */
6931.1Skamil#ifndef read_tty
6941.1Skamil/* read a character from the terminal, with hacks for O_NDELAY reads */
6951.1Skamil
6961.1Skamilint
6971.1Skamilread_tty(addr,size)
6981.1Skamilchar *addr;
6991.1Skamilint size;
7001.1Skamil{
7011.1Skamil    if (is_input) {
7021.1Skamil	*addr = pending_ch;
7031.1Skamil	is_input = FALSE;
7041.1Skamil	return 1;
7051.1Skamil    }
7061.1Skamil    else {
7071.1Skamil	size = read(0,addr,size);
7081.1Skamil	if (size < 0)
7091.1Skamil	    sig_catcher(SIGHUP);
7101.1Skamil	if (metakey) {
7111.1Skamil	    if (*addr & 0200) {
7121.1Skamil		pending_ch = *addr & 0177;
7131.1Skamil		is_input = TRUE;
7141.1Skamil		*addr = '\001';
7151.1Skamil	    }
7161.1Skamil	}
7171.1Skamil	else
7181.1Skamil	    *addr &= 0177;
7191.1Skamil	return size;
7201.1Skamil    }
7211.1Skamil}
7221.1Skamil#endif /* read_tty */
7231.1Skamil#endif /* PUSHBACK */
7241.1Skamil
7251.1Skamilint
7261.1Skamilread_nd(buff, siz)
7271.1Skamilchar *buff;
7281.1Skamilint siz;
7291.1Skamil{
7301.1Skamil    if (!input_pending())
7311.1Skamil	return 0;
7321.1Skamil
7331.1Skamil    getcmd(buff);
7341.1Skamil    return 1;
7351.1Skamil}
7361.1Skamil
7371.1Skamil/* get a character into a buffer */
7381.1Skamil
7391.1Skamilvoid
7401.1Skamilgetcmd(whatbuf)
7411.1SkamilReg3 char *whatbuf;
7421.1Skamil{
7431.1Skamil#ifdef PUSHBACK
7441.1Skamil    Reg1 KEYMAP *curmap;
7451.1Skamil    Reg2 int i;
7461.1Skamil    bool no_macros;
7471.1Skamil    int times = 0;			/* loop detector */
7481.1Skamil    char scrchar;
7491.1Skamil
7501.1Skamiltryagain:
7511.1Skamil    curmap = topmap;
7521.1Skamil/*    no_macros = (whatbuf != buf && nextin == nextout);  */
7531.1Skamil    no_macros = FALSE;
7541.1Skamil#endif
7551.1Skamil    for (;;) {
7561.1Skamil	errno = 0;
7571.1Skamil	if (read_tty(whatbuf,1) < 0 && !errno)
7581.1Skamil	    errno = EINTR;
7591.1Skamil#ifdef read_tty
7601.1Skamil	if (metakey) {
7611.1Skamil	    if (*whatbuf & 0200) {
7621.1Skamil		*what_buf &= 037;	/* punt and hope they don't notice */
7631.1Skamil	    }
7641.1Skamil	}
7651.1Skamil	else
7661.1Skamil	    *whatbuf &= 0177;
7671.1Skamil#endif /* read_tty */
7681.1Skamil	if (errno && errno != EINTR) {
7691.1Skamil	    perror(readerr);
7701.1Skamil	    sig_catcher(0);
7711.1Skamil	}
7721.1Skamil#ifdef PUSHBACK
7731.1Skamil	if (*whatbuf & 0200 || no_macros) {
7741.1Skamil	    *whatbuf &= 0177;
7751.1Skamil	    goto got_canonical;
7761.1Skamil	}
7771.1Skamil	if (curmap == Null(KEYMAP*))
7781.1Skamil	    goto got_canonical;
7791.1Skamil	for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){
7801.1Skamil	    Read_tty(&scrchar,1);
7811.1Skamil	}
7821.1Skamil	switch (curmap->km_type[*whatbuf] & KM_TMASK) {
7831.1Skamil	case KM_NOTHIN:			/* no entry? */
7841.1Skamil	    if (curmap == topmap)	/* unmapped canonical */
7851.1Skamil		goto got_canonical;
7861.1Skamil	    settle_down();
7871.1Skamil	    goto tryagain;
7881.1Skamil	case KM_KEYMAP:			/* another keymap? */
7891.1Skamil	    curmap = curmap->km_ptr[*whatbuf].km_km;
7901.1Skamil	    assert(curmap != Null(KEYMAP*));
7911.1Skamil	    break;
7921.1Skamil	case KM_STRING:			/* a string? */
7931.1Skamil	    pushstring(curmap->km_ptr[*whatbuf].km_str);
7941.1Skamil	    if (++times > 20) {		/* loop? */
7951.1Skamil		fputs("\r\nmacro loop?\r\n",stdout);
7961.1Skamil		settle_down();
7971.1Skamil	    }
7981.1Skamil	    no_macros = FALSE;
7991.1Skamil	    goto tryagain;
8001.1Skamil	}
8011.1Skamil#else
8021.1Skamil	*whatbuf &= 0177;
8031.1Skamil	break;
8041.1Skamil#endif
8051.1Skamil    }
8061.1Skamil
8071.1Skamilgot_canonical:
8081.1Skamil#ifndef TERMIO
8091.1Skamil    if (*whatbuf == '\r')
8101.1Skamil	*whatbuf = '\n';
8111.1Skamil#endif
8121.1Skamil    if (whatbuf == buf)
8131.1Skamil	whatbuf[1] = FINISHCMD;		/* tell finish_command to work */
8141.1Skamil}
815
816#ifdef PUSHBACK
817void
818pushstring(str)
819char *str;
820{
821    Reg1 int i;
822    char tmpbuf[PUSHSIZE];
823    Reg2 char *s = tmpbuf;
824
825    assert(str != Nullch);
826    interp(s,PUSHSIZE,str);
827    for (i = strlen(s)-1; i >= 0; --i) {
828	s[i] ^= 0200;
829	pushchar(s[i]);
830    }
831}
832#endif
833