[comp.sources.games] v04i021: spacewar - multiplayer asynchronous space battle game, Part01/06

games@tekred.TEK.COM (06/01/88)

Submitted by: udenva!koala!dir (Dan Rosenblatt)
Comp.sources.games: Volume 4, Issue 21
Archive-name: spacewar/Part01

	[I've compiled this, but haven't had a chance to try it out. -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 6)."
# Contents:  README MANIFEST build.c play.c unplay.c
# Wrapped by billr@saab on Tue May 31 09:54:48 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(1277 characters\)
sed "s/^X//" >README <<'END_OF_README'
XUnfortunately, I have not gotten around to packaging spacewar
Xfor totally automatic installation; so here are some notes:
X
X    spacewar.h	contains various pathnames that must be edited
X		before compilation.  There is also a define for
X		SWMASTER, the player that has special game commands
X		and ship privileges. The special game commands
X		can be found in prvcmd.c.
X
X    Makefile	must define the right symbols during compilation
X		for your system type:
X			VMS	for VMS; certain mailbox privileges
X				are required.
X			BSD	for non System-V.
X		If neither of these are defined, then a System-V
X		environment with named pipes is assumed.
X			VOID	either 'int' or 'void' depending on
X				what your compiler supports.
X			NEEDFMOD if your system doesn't have an fmod
X				function in libc.a or libm.a.
X
X    swobj	should be created by copying swobj.init into it.
X
X    swerr
X    swdb.dir
X    swdb.pag	should be created empty.
X
X    psw.sh	should be edited for pathnames and installed somewhere
X		like /usr/games.
X
X    psw
X    sw		should be setuid to the owner of swobj, swdb.dir, swdb.pag,
X		and swerr. Also, the directory that these files are in
X		must be mode 'rwx' for the same user-id as the setuid cuz
X		various other files are created and exist here only while
X		spacewar is running.
END_OF_README
if test 1277 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(2274 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                  1	This shipping list
X Makefile                  4	
X README                    1	
X aln.h                     6	
X alninit.c                 4	
X bfuncs.c                  6	
X bits.c                    5	
X build.c                   1	
X build.h                   4	
X cmd.c                     2	
X copyright                 6	
X crft.h                    5	
X crftupdate.c              5	
X damage.c                  4	
X dbm.c                     5	
X dbm.h                     6	
X dmpdbm.c                  5	
X doc.ms                    2	
X fixdir.c                  6	
X flds.h                    5	
X globals.c                 6	
X lckmsg.c                  6	
X login.h                   6	
X logoff.c                  5	
X logon.c                   5	
X mail.c                    2	
X mlbx.h                    6	
X mutils.c                  3	
X obj.h                     6	
X objinit.c                 5	
X objupdate.c               5	
X output.c                  5	
X play.c                    1	
X plinit.c                  3	
X plyr.h                    6	
X proctrap.c                3	
X prvcmd.c                  3	
X psw.c                     4	
X psw.sh                    6	
X remove.c                  5	
X rpt.c                     6	
X rsw.c                     6	
X scrn.c                    3	
X see.c                     3	
X shutdown.c                5	
X spacewar.h                5	
X sw.c                      4	
X swobj.init                5	
X sys.h                     6	
X tget.c                    6	
X torp.h                    6	
X tstsz.c                   6	
X ucmd.h                    6	
X uio.h                     6	
X uio2.h                    6	
X universe.h                6	
X unplay.c                  1	
X updaln.c                  3	
X update.c                  2	
X upddbm.c                  4	
X upddmg.c                  4	
X upddsh.c                  5	
X updmov.c                  3	
X updobjs.c                 5	
X updsys.c                  4	
X updtorp.c                 5	
X usrcmd.c                  4	
X vdisp.c                   5	
X vmsdelmbx.c               6	
X vmspsw.c                  4	
X vmsrsw.c                  5	
X who.c                     6	
END_OF_MANIFEST
if test 2274 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f build.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"build.c\"
else
echo shar: Extracting \"build.c\" \(14850 characters\)
sed "s/^X//" >build.c <<'END_OF_build.c'
X/*
X * Spacewar - (re)build a ship
X *
X * Copyright 1984 obo Systems, Inc.
X * Copyright 1984 Dan Rosenblatt
X */
X
X#ifndef VMS
X#include <sys/types.h>
X#include <dbm.h>
X#else /* BSD SYSIII SYSV */
X#include <types.h>
X#include "dbm.h"
X#endif /* VMS */
X#include "spacewar.h"
X#include "universe.h"
X#include "obj.h"
X#include "login.h"
X#include "sys.h"
X#include "crft.h"
X#define BUILD
X#include "build.h"
X
Xstatic struct crftkey getcrkey;
Xstatic struct crft getcrdat;
Xstatic struct syskey getskey;
Xstatic struct sys getsdat;
Xstatic datum dbmkey,dbmdata;
Xstatic struct sysc *getsc;
Xstatic getsys(),getcrft();
Xstatic VOID fixdmg(),putcrft(),putsys(),delsys();
Xextern long atol();
X
XVOID build(plogin)
Xstruct login *plogin;
X{
X	char buf[80+1];
X
X#ifdef DEBUG
X	DBG("build(#%d/%s)\n",plogin-loginlst,plogin->ln_name);
X#endif
X
X	/****************/
X	/* no craft yet */
X	/****************/
X#ifdef DEBUG
X	VDBG("build: #%d/%s doing %s/%d\n",plogin-loginlst,plogin->ln_name,
X	plogin->ln_crft,(int)plogin->ln_substat);
X#endif
X	if (!plogin->ln_crft[0]) {
X
X	    /* nothing - prompt for craft name */
X	    if (!plogin->ln_input[0]) {
X#ifdef DEBUG
X		VDBG("build: prompt for craft name\n");
X#endif
X		output(plogin,'C',0,
X		"A single dot (.) on a line by itself terminates Build.\n\n");
X		output(plogin,'C',0,"What is the name of your ship?");
X		output(plogin,0,0,0);
X#ifdef DEBUG
X		VDBG("build return\n");
X#endif
X		return;
X
X	    /* craft name - store and get or create craft */
X	    } else {
X#ifdef DEBUG
X		VDBG("build: get/create craft '%s'\n",plogin->ln_input);
X#endif
X		plogin->ln_input[sizeof(plogin->ln_crft)-1] = NULL;
X		strcpy(plogin->ln_crft,plogin->ln_input);
X		if (!strcmp(plogin->ln_input,".")) {
X		    plogin->ln_crft[0] = NULL;
X		    plogin->ln_stat = NULL;
X		    plogin->ln_substat = NULL;
X		    output(plogin,'C',0,PROMPT);
X		    output(plogin,0,0,0);
X#ifdef DEBUG
X		    VDBG("build return\n");
X#endif
X		    return;
X		}
X
X		/* exists */
X		if (getcrft(plogin)) {
X#ifdef DEBUG
X		    VDBG("build: craft exists\n");
X#endif
X
X		    /* has a valid hull type */
X		    if (getcrdat.cr_htyp) {
X#ifdef DEBUG
X			VDBG("build: has valid hull %d\n",getcrdat.cr_htyp);
X#endif
X
X			/* must be docked or priviledged */
X			if ((!getcrdat.cr_dock.ip_ofst ||
X			getcrdat.cr_dock.ip_ofst >= MAXOBJ) &&
X			!getcrdat.cr_plvl) {
X#ifdef DEBUG
X			    VDBG("build: docked=%d plvl=%d\n",
X			    getcrdat.cr_dock.ip_ofst,getcrdat.cr_plvl);
X#endif
X			    plogin->ln_crft[0] = NULL;
X			    plogin->ln_stat = NULL;
X			    plogin->ln_substat = NULL;
X			    output(plogin,'C',0,"Must be docked to rebuild.");
X			    output(plogin,'C',0,PROMPT);
X			    output(plogin,0,0,0);
X#ifdef DEBUG
X			    VDBG("build return\n");
X#endif
X			    return;
X
X			/* docked - fix hull damage; set next subsys prompt */
X			} else {
X#ifdef DEBUG
X			    VDBG("build: docked=%d plvl=%d\n",
X			    getcrdat.cr_dock.ip_ofst,getcrdat.cr_plvl);
X#endif
X			    if (!getsys(plogin,HULL)) {
X				perror("build: docked and can't find HULL");
X				plogin->ln_crft[0] = NULL;
X				plogin->ln_stat = NULL;
X				plogin->ln_substat = NULL;
X				output(plogin,'C',0,PROMPT);
X				output(plogin,0,0,0);
X#ifdef DEBUG
X				VDBG("build return\n");
X#endif
X				return;
X			    }
X			    fixdmg();
X			    putsys(plogin);
X			    plogin->ln_substat = (char *)(HULL+1);
X			}
X
X		    /* invalid hull - set up prompting for hull type */
X		    } else {
X#ifdef DEBUG
X			VDBG("build: has invalid hull %d\n",getcrdat.cr_htyp);
X#endif
X			plogin->ln_substat = (char *)(HULL);
X		    }
X
X		/* craft doesn't exist - create it, */
X		/* set up prompting for hull type */
X		} else {
X#ifdef DEBUG
X		    VDBG("build: creating craft\n");
X#endif
X		    binit((char *)&getcrdat,sizeof(getcrdat));
X		    getcrdat.cr_dock.ip_ofst = -1;
X		    dbmdata.dptr = (char *)&getcrdat;
X		    dbmdata.dsize = CRDATSIZ;
X		    if (store(dbmkey,dbmdata)) {
X			output(plogin,'C',0,
X			"(sigh) database collision - try another ship name\n\n\
XWhat is the name of your ship?");
X			output(plogin,0,0,0);
X			plogin->ln_crft[0] = NULL;
X#ifdef DEBUG
X			VDBG("build return\n");
X#endif
X			return;
X		    }
X		    plogin->ln_substat = (char *)(HULL);
X		}
X	    }
X
X	/******************************/
X	/* get craft - error if can't */
X	/******************************/
X	} else if (!getcrft(plogin)) {
X		perror("build: can't find craft\n");
X		plogin->ln_crft[0] = NULL;
X		plogin->ln_stat = NULL;
X		plogin->ln_substat = NULL;
X		output(plogin,'C',0,PROMPT);
X		output(plogin,0,0,0);
X#ifdef DEBUG
X		VDBG("build return\n");
X#endif
X		return;
X
X	/*************************************/
X	/* no hull type - input is hull type */
X	/*************************************/
X	} else if (!getcrdat.cr_htyp) {
X#ifdef DEBUG
X		VDBG("build: craft given hull '%s'\n",plogin->ln_input);
X#endif
X
X		if (!strcmp(plogin->ln_input,".")) {
X		    plogin->ln_crft[0] = NULL;
X		    plogin->ln_stat = NULL;
X		    plogin->ln_substat = NULL;
X		    output(plogin,'C',0,PROMPT);
X		    output(plogin,0,0,0);
X#ifdef DEBUG
X		    VDBG("build return\n");
X#endif
X		    return;
X		}
X
X		/* must be 1, 2, or 3 */
X		if (strcmp("1",plogin->ln_input) &&
X		strcmp("2",plogin->ln_input) &&
X		strcmp("3",plogin->ln_input))
X			output(plogin,'C',0,"Bad hull type\n\n");
X
X		/* update craft */
X		/* create hull subsystem */
X		/* set next subsys prompt */
X		else {
X			getcrdat.cr_htyp = plogin->ln_input[0] - '0';
X			getsc = &config[HULL][getcrdat.cr_htyp];
X			getcrdat.cr_flsp = getsc->sc_bsp;
X			getcrdat.cr_crew = getsc->sc_bcr;
X			putcrft(plogin);
X
X			getsys(plogin,HULL); /* should fail */
X			getsdat.s_pct = getsc->sc_rpct;
X			getsdat.s_edmg = getsc->sc_edmg;
X			getsdat.s_dmg = 0;
X			getsdat.s_lvl = getsc->sc_ilvl;
X			getsdat.s_cap = getsc->sc_cap;
X			putsys(plogin);
X
X			plogin->ln_substat = (char *)(HULL+1);
X		}
X
X	/**********************************************/
X	/* null response - fix damage and leave as is */
X	/**********************************************/
X	} else if (!plogin->ln_input[0]) {
X#ifdef DEBUG
X		VDBG("build: null response for subsys %d\n",
X		(int)plogin->ln_substat);
X#endif
X
X		/* only if system exists */
X		if (getsys(plogin,(int)plogin->ln_substat)) {
X			fixdmg();
X			putsys(plogin);
X		}
X
X		plogin->ln_substat = (char *)((int)plogin->ln_substat + 1);
X
X	/*****************************************************************/
X	/* zero - delete subsystem if at starbase, zero it out otherwise */
X	/*****************************************************************/
X	} else if (!strcmp("0",plogin->ln_input)) {
X#ifdef DEBUG
X	    VDBG("build: zero percent for subsys %d\n",(int)plogin->ln_substat);
X#endif
X
X	    /* only if system exists */
X	    if (getsys(plogin,(int)plogin->ln_substat)) {
X#ifdef DEBUG
X		VDBG("build: subsys exists\n");
X#endif
X		fixdmg();
X
X		/* delete if priviledged or brand new or */
X		/* docked at starbase freeing up space and crew */
X		getsc = &config[getskey.s_type][getcrdat.cr_htyp];
X		if (getcrdat.cr_plvl || getcrdat.cr_dock.ip_ofst < 0 ||
X		(getcrdat.cr_dock.ip_ofst > 0 &&
X		univlst[getcrdat.cr_dock.ip_ofst].uv_pctr == '#')) {
X#ifdef DEBUG
X		    VDBG("build: deleting subsys\n");
X#endif
X		    getcrdat.cr_flsp += getsc->sc_bsp +
X		    (getsc->sc_fsp * getsdat.s_pct) / 100L;
X		    getcrdat.cr_crew += getsc->sc_bcr +
X		    (getsc->sc_fcr * getsdat.s_pct) / 100L;
X		    delsys(plogin);
X
X		/* otherwise set to 0 keeping base space and */
X		/* crew freeing incremental space and crew */
X		} else {
X#ifdef DEBUG
X		    VDBG("build: zero out subsys\n");
X#endif
X		    getcrdat.cr_flsp += (getsc->sc_fsp * getsdat.s_pct) / 100L;
X		    getcrdat.cr_crew += (getsc->sc_fcr * getsdat.s_pct) / 100L;
X		    getsdat.s_pct = 0;
X		    putsys(plogin);
X		}
X		putcrft(plogin);
X	    }
X
X	    plogin->ln_substat = (char *)((int)plogin->ln_substat + 1);
X
X	/************************************************************/
X	/* create/update to new percentage if enough space and crew */
X	/************************************************************/
X	} else {
X	    long pct = atol(plogin->ln_input);
X	    long maxspcpct,maxcrwpct,maxpct;
X	    long fspc = getcrdat.cr_flsp;	/* current free space */
X	    long fcrw = getcrdat.cr_crew;	/* current free crew */
X
X#ifdef DEBUG
X	    VDBG("build: %s%% for subsys %d\n",plogin->ln_input,
X	    (int)plogin->ln_substat);
X#endif
X	    if (!strcmp(plogin->ln_input,".")) {
X		plogin->ln_crft[0] = NULL;
X		plogin->ln_stat = NULL;
X		plogin->ln_substat = NULL;
X		output(plogin,'C',0,PROMPT);
X		output(plogin,0,0,0);
X#ifdef DEBUG
X		VDBG("build return\n");
X#endif
X		return;
X	    }
X
X	    /***************************************/
X	    /* compute maximum percentage possible */
X	    /***************************************/
X	    if (getsys(plogin,(int)plogin->ln_substat)) {
X#ifdef DEBUG
X		VDBG("build: subsys exists with %d%%\n",getsdat.s_pct);
X#endif
X		getsc = &config[getskey.s_type][getcrdat.cr_htyp];
X		fspc += getsc->sc_bsp + (getsc->sc_fsp * getsdat.s_pct) / 100L;
X		fcrw += getsc->sc_bcr + (getsc->sc_fcr * getsdat.s_pct) / 100L;
X	    } else {
X#ifdef DEBUG
X		VDBG("build: subsys doesn't exist\n");
X#endif
X		binit((char *)&getsdat,sizeof(getsdat));
X	    }
X	    maxspcpct = ((fspc - getsc->sc_bsp) * 100L) / getsc->sc_fsp;
X	    maxcrwpct = ((fcrw - getsc->sc_bcr) * 100L) / getsc->sc_fcr;
X	    maxpct = (maxspcpct < maxcrwpct) ? maxspcpct : maxcrwpct;
X	    if (maxpct < 0L)
X		maxpct = 0L;
X	    else if (maxpct > 100L)
X		maxpct = 100L;
X	    
X	    /* check request against limits */
X	    if (pct < 0L || pct > maxpct) {
X#ifdef DEBUG
X		VDBG("build: %ld%% not between %ld and %ld\n",pct,0,maxpct);
X#endif
X		sprintf(buf,
X		"\nPercent of subsystem '%s' must be between 0 and %ld?",
X		subsysnam[(int)plogin->ln_substat],maxpct);
X		output(plogin,'C',0,buf);
X		output(plogin,0,0,0);
X#ifdef DEBUG
X		VDBG("build return\n");
X#endif
X		return;
X
X	    /* create/update subsystem; update craft free space and crew */
X	    } else {
X#ifdef DEBUG
X		VDBG("build: subsys from %d%% to %ld%%\n",getsdat.s_pct,pct);
X#endif
X		getsdat.s_pct = pct;
X		fixdmg();
X		putsys(plogin);
X
X		getsc = &config[getskey.s_type][getcrdat.cr_htyp];
X		getcrdat.cr_flsp = fspc - (getsc->sc_bsp +
X		(getsc->sc_fsp * pct) / 100L);
X		getcrdat.cr_crew = fcrw - (getsc->sc_bcr +
X		(getsc->sc_fcr * pct) / 100L);
X		putcrft(plogin);
X
X		plogin->ln_substat = (char *)((int)plogin->ln_substat + 1);
X	    }
X	}
X
X	/*****************************/
X	/* prompt for next subsystem */
X	/*****************************/
X	if ((int)plogin->ln_substat == HULL) {
X	    output(plogin,'C',0,
X	    "Hull type (1-rocket, 2-sphere, 3-Enterprise)>");
X	    output(plogin,0,0,0);
X	} else if ((int)plogin->ln_substat < MAXSYS) {
X	    getsc = &config[(int)plogin->ln_substat][getcrdat.cr_htyp];
X	    sprintf(buf,"\n\nSubsystem '%s'\n",subsysnam[(int)plogin->ln_substat]);
X	    output(plogin,'C',0,buf);
X	    sprintf(buf,"Your ship has free space of %ld and free crew of %ld\n",
X	    getcrdat.cr_flsp,getcrdat.cr_crew);
X	    output(plogin,'C',0,buf);
X	    if (getsys(plogin,(int)plogin->ln_substat)) {
X		sprintf(buf,"Your ship currently has %d%% of this subsystem\n",
X		getsdat.s_pct);
X		output(plogin,'C',0,buf);
X	    }
X	    sprintf(buf,
X	    "For this subsystem, the base space is %ld and the base crew is %ld\n",
X	    getsc->sc_bsp,getsc->sc_bcr);
X	    output(plogin,'C',0,buf);
X	    sprintf(buf,
X	    "100%% installation uses an additional %ld space and %ld crew\n",
X	    getsc->sc_fsp,getsc->sc_fcr);
X	    output(plogin,'C',0,buf);
X	    output(plogin,'C',0,"What percent do you want?");
X	    output(plogin,0,0,0);
X
X	/* all done */
X	} else {
X	    plogin->ln_crft[0] = NULL;
X	    plogin->ln_stat = NULL;
X	    plogin->ln_substat = NULL;
X	    output(plogin,'C',0,PROMPT);
X	    output(plogin,0,0,0);
X	}
X#ifdef DEBUG
X	VDBG("build return\n");
X#endif
X}
X
Xstatic getcrft(plogin)
Xstruct login *plogin;
X{
X	binit((char *)&getcrkey,sizeof(getcrkey));
X	getcrkey.cr_crftkey = CRAFT;
X	strcpy(getcrkey.cr_plyr,plogin->ln_name);
X	strcpy(getcrkey.cr_name,plogin->ln_crft);
X	dbmkey.dptr = (char *)&getcrkey;
X	dbmkey.dsize = sizeof(getcrkey);
X	dbmdata = fetch(dbmkey);
X#ifdef DEBUG
X	VDBG("getcrft - %s %s\n",(dbmdata.dptr) ? "found" : "couldn't find",
X	getcrkey.cr_name);
X#endif
X	if (!dbmdata.dptr)
X		return(0);
X	bcopy((char *)&getcrdat,dbmdata.dptr,CRDATSIZ);
X	return(1);
X}
X
X/* assumes getcrkey and getcrdat are current */
Xstatic VOID putcrft(plogin)
Xstruct login *plogin;
X{
X#ifdef DEBUG
X	VDBG("putcrft - %s\n",getcrkey.cr_name);
X#endif
X	dbmkey.dptr = (char *)&getcrkey;
X	dbmkey.dsize = sizeof(getcrkey);
X	dbmdata.dptr = (char *)&getcrdat;
X	dbmdata.dsize = CRDATSIZ;
X	if (store(dbmkey,dbmdata)) {
X		perror("putcrft: can't update craft");
X		plogin->ln_crft[0] = NULL;
X		plogin->ln_stat = NULL;
X		plogin->ln_substat = NULL;
X		output(plogin,'C',0,PROMPT);
X		output(plogin,0,0,0);
X	}
X}
X
Xstatic getsys(plogin,styp)
Xstruct login *plogin;
Xint styp;
X{
X	binit((char *)&getskey,sizeof(getskey));
X	getskey.s_syskey = SUBSYS;
X	strcpy(getskey.s_plyr,plogin->ln_name);
X	strcpy(getskey.s_crft,plogin->ln_crft);
X	getskey.s_type = styp;
X	dbmkey.dptr = (char *)&getskey;
X	dbmkey.dsize = sizeof(getskey);
X	dbmdata = fetch(dbmkey);
X#ifdef DEBUG
X	VDBG("getsys - %s %d\n",(dbmdata.dptr) ? "found" : "couldn't find",styp);
X#endif
X	if (!dbmdata.dptr)
X		return(0);
X	bcopy((char *)&getsdat,dbmdata.dptr,sizeof(getsdat));
X	return(1);
X}
X
X/* assumes getskey and getsdat are current */
Xstatic VOID putsys(plogin)
Xstruct login *plogin;
X{
X#ifdef DEBUG
X	VDBG("putsys - %d\n",getskey.s_type);
X#endif
X	dbmkey.dptr = (char *)&getskey;
X	dbmkey.dsize = sizeof(getskey);
X	dbmdata.dptr = (char *)&getsdat;
X	dbmdata.dsize = sizeof(getsdat);
X	if (store(dbmkey,dbmdata)) {
X		perror("putsys: can't update subsystem");
X		plogin->ln_crft[0] = NULL;
X		plogin->ln_stat = NULL;
X		plogin->ln_substat = NULL;
X		output(plogin,'C',0,PROMPT);
X		output(plogin,0,0,0);
X	}
X}
X
X/* assumes getskey is current */
Xstatic VOID delsys(plogin)
Xstruct login *plogin;
X{
X#ifdef DEBUG
X	VDBG("delsys - %d\n",getskey.s_type);
X#endif
X	dbmkey.dptr = (char *)&getskey;
X	dbmkey.dsize = sizeof(getskey);
X	if (delete(dbmkey)) {
X		perror("delsys: can't delete subsystem");
X		plogin->ln_crft[0] = NULL;
X		plogin->ln_stat = NULL;
X		plogin->ln_substat = NULL;
X		output(plogin,'C',0,PROMPT);
X		output(plogin,0,0,0);
X	}
X}
X
X/* assumes getcrdat, getskey, and getsdat are current */
Xstatic VOID fixdmg()
X{
X	/* if priviledged or docked at a starbase, fix all damage */
X	if (getcrdat.cr_plvl ||
X	(getcrdat.cr_dock.ip_ofst > 0 &&
X	univlst[getcrdat.cr_dock.ip_ofst].uv_pctr == '#'))
X		getsdat.s_dmg = 0;
X
X	/* fix temporary damage to 0, permanent damage to 45 */
X	getsdat.s_dmg = (getsdat.s_dmg > 45) ? 45 : 0;
X
X	/* update passive parameters and level */
X	getsc = &config[getskey.s_type][getcrdat.cr_htyp];
X	getsdat.s_edmg = getsc->sc_edmg;
X	getsdat.s_lvl =  getsc->sc_ilvl;
X	getsdat.s_cap =  getsc->sc_cap;
X	if (getskey.s_type == ROCKETS)
X		getsdat.s_lvl = ((long)getsdat.s_lvl * (long)getsdat.s_pct) / 100L;
X	else if (getskey.s_type == TORPS)
X		getsdat.s_lvl = (getsdat.s_cap * getsdat.s_pct) / 100;
X}
END_OF_build.c
if test 14850 -ne `wc -c <build.c`; then
    echo shar: \"build.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f play.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"play.c\"
else
echo shar: Extracting \"play.c\" \(31675 characters\)
sed "s/^X//" >play.c <<'END_OF_play.c'
X/*
X * Spacewar - routine to execute user playing commands
X *
X * Copyright 1985 obo Systems, Inc.
X * Copyright 1985 Dan Rosenblatt
X */
X
X#ifndef VMS
X#include <sys/types.h>
X#include <dbm.h>
X#else /* BSD SYSIII SYSV */
X#include <types.h>
X#include "dbm.h"
X#endif /* VMS */
X#include "spacewar.h"
X#include "universe.h"
X#include "login.h"
X#include "sys.h"
X#include "crft.h"
X#include "flds.h"
X#include "build.h"
X#include "aln.h"
X#include "obj.h"
X#include "torp.h"
X#include "ucmd.h"
X
Xextern VOID fixdir();
Xextern double vdist(),vlen();
Xstatic int okdir();
Xstatic VOID fixaf();
X
Xstatic struct {
X	char	*pc_cmd;
X	char	pc_mincmdl;
X} pcmds[] = {
X/* 0 */	{"erase",1},	{"angle",2},	{"right",2},	{"left",3},
X/* 4 */	{"up",2},	{"down",3},	{"vdist",1},	{"home",1},
X/* 8 */	{"unhome",2},	{"faceforward",2},{"autopilot",2},{"shields",2},
X/* 12 */{"stopthrust",2},{"thrust",2},	{"warp",2},	{"damage",3},
X/* 16 */{"leave",3},	{"dock",3},	{"radio",2},	{"who",2},
X/* 20 */{"report",3},	{"phasers",1},	{"torpedo",2},	{"fix",2},
X/* 24 */{"-",1},	{"sensors",2},	{"lockon",2},	{"redraw",3}
X};
X
XVOID play(plogin)
Xregister struct login *plogin;
X{
X	int i,j;
X	long l,m;
X	register struct crft *pcrft;
X	struct torp *ptorp;
X	register struct universe *puniv;
X	struct login *plgn;
X	char buf[128];
X	double ftmp,tmpvec[3],tmpvec2[3];
X	struct ucmdkey getuckey;
X	datum dbmkey,dbmdata;
X	char ucargs[9][20+1],inuc=0;
X	dsplcmnt tmpdspl;
X
X#ifdef DEBUG
X	DBG("play(#%d/%s)\n",plogin-loginlst,plogin->ln_name);
X#endif
X
X	/* if not yet placed into the universe, try doing so */
X	if (!plogin->ln_play.ip_ptr) {
X	    if (plinit(plogin)) {
X		pcrft = plogin->ln_play.ip_ptr->uv_ptr.uv_crft;
X		sprintf(plogin->ln_input,"Wlcm abrd the %s captain %s",
X		plogin->ln_crft,plogin->ln_name);
X		i = 0; /* force erase, not redraw */
X		goto erase;
X	    }
X#ifdef DEBUG
X	    VDBG("play return\n");
X#endif
X	    return;
X	}
X	pcrft = plogin->ln_play.ip_ptr->uv_ptr.uv_crft;
X
X	/* move last command indicator */
Xdouc:	output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_LSTCMD," ");
X	if (++pcrft->cr_lcmd >= flds[FLD_LSTCMD].f_maxg)
X	    pcrft->cr_lcmd = 0;
X	output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_LSTCMD,"#");
X
X	/* find command */
X	for (i=sizeof(pcmds)/sizeof(pcmds[0]);i-- > 0;)
X	    if (!strncmp(plogin->ln_input,pcmds[i].pc_cmd,pcmds[i].pc_mincmdl))
X		break;
X	if (i < 0) {
Xbadinp:	    sprintf(buf,"??? %s",plogin->ln_input);
Xbadinp2:    output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_COMMAND,buf);
X	    inuc = 0;
X	    goto done;
X	}
X
X
X	switch(i) {
X
X	    /*********/
X	    /* erase */
X	    /*********/
X	    case 0:
Xerase:		/* erase screen, redraw background */
X		output(plogin,'E',0,0);
Xredraw:		background(pcrft);
X
X		/* indicate all fields changed so they get re-displayed */
X		for (j=0;j < sizeof(pcrft->cr_chng);++j)
X		    pcrft->cr_chng[j] = ~0;
X		pcrft->cr_scrn[0][0] = NULL;
X
X		if (i == 0) { /* redraw instead of erase */
X
X		    /* reset last report and command markers */
X		    pcrft->cr_lrpt = 0;
X		    pcrft->cr_lcmd = 0;
X
X		    /* restore last command marker */
X		    output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_LSTCMD,"#");
X		}
X
X		break;
X
X	    /*********/
X	    /* angle */
X	    /*********/
X	    case 1:
X		if (sscanf(plogin->ln_input,"%*s %lf",&ftmp) != 1)
X		    goto badinp;
X
X		/* must be 0<ang<=180 (or 360 if privileged) */
X		if (ftmp <= 0. || SUB(ftmp,360.) > 0. ||
X		(SUB(ftmp,180.) > 0 && !pcrft->cr_plvl))
X		    goto badinp;
X
X		pcrft->cr_vang = MUL(ftmp,DEGTORAD);
X		biton(pcrft->cr_chng,BIT_VANGL);
X
X		/* recompute viewing distance if not privileged */
X		if (!pcrft->cr_plvl) {
X		    pcrft->cr_vdst =
X		    INT(DIV(VANGVDST,SQUARE(pcrft->cr_vang)));
X		    biton(pcrft->cr_chng,BIT_VDIST);
X		}
X		break;
X
X	    /*********/
X	    /* right */
X	    /*********/
X	    case 2:
X		if (!okdir(plogin,pcrft,&ftmp)) goto badinp;
X		pcrft->cr_dir[1] = SUB(pcrft->cr_dir[1],ftmp);
X		biton(pcrft->cr_chng,BIT_DIR1);
X		fixdir(pcrft);
X		fixaf(pcrft);
X		break;
X
X	    /********/
X	    /* left */
X	    /********/
X	    case 3:
X		if (!okdir(plogin,pcrft,&ftmp)) goto badinp;
X		pcrft->cr_dir[1] = ADD(pcrft->cr_dir[1],ftmp);
X		biton(pcrft->cr_chng,BIT_DIR1);
X		fixdir(pcrft);
X		fixaf(pcrft);
X		break;
X
X	    /******/
X	    /* up */
X	    /******/
X	    case 4:
X		if (!okdir(plogin,pcrft,&ftmp)) goto badinp;
X		pcrft->cr_dir[2] = SUB(pcrft->cr_dir[2],ftmp);
X		biton(pcrft->cr_chng,BIT_DIR2);
X		fixdir(pcrft);
X		fixaf(pcrft);
X		break;
X
X	    /********/
X	    /* down */
X	    /********/
X	    case 5:
X		if (!okdir(plogin,pcrft,&ftmp)) goto badinp;
X		pcrft->cr_dir[2] = ADD(pcrft->cr_dir[2],ftmp);
X		biton(pcrft->cr_chng,BIT_DIR2);
X		fixdir(pcrft);
X		fixaf(pcrft);
X		break;
X
X	    /**********************/
X	    /* vdist (privileged) */
X	    /**********************/
X	    case 6:
X		if (!pcrft->cr_plvl)
X		    goto badinp;
X		if (sscanf(plogin->ln_input,"%*s %ld",&pcrft->cr_vdst) != 1)
X		    goto badinp;
X		biton(pcrft->cr_chng,BIT_VDIST);
X		break;
X
X	    /********/
X	    /* home */
X	    /********/
X	    case 7:
X		if (sscanf(plogin->ln_input,"%*s %d",&i) != 1)
X		    goto badinp;
X		if (i < 1 || i > MHOM)
X		    goto badinp;
X		i -= 1;
X
X		/* must be autopiloted on something */
X		if (!pcrft->cr_auto.ip_ptr) {
X		    sprintf(buf,"%.22s - not autopiloted",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		pcrft->cr_hom[i].ip_ptr = pcrft->cr_auto.ip_ptr;
X		/*pcrft->cr_hdst[i] = INT(vdist(pcrft->cr_pstn,
X		pcrft->cr_auto.ip_ptr->uv_pstn));*/
X		tmpdspl = vdisp(pcrft->cr_univ.ip_ptr,pcrft->cr_auto.ip_ptr,'d');
X		pcrft->cr_hdst[i] = INT(tmpdspl.dst);
X		biton(pcrft->cr_chng,BIT_HOMCHAN+i);
X		break;
X
X	    /**********/
X	    /* unhome */
X	    /**********/
X	    case 8:
X		if (sscanf(plogin->ln_input,"%*s %d",&i) != 1)
X		    goto badinp;
X		if (i < 1 || i > MHOM)
X		    goto badinp;
X		i -= 1;
X
X		/* must be homed in */
X		if (!pcrft->cr_hom[i].ip_ptr) {
X		    sprintf(buf,"%.25s - not homed in",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		pcrft->cr_hom[i].ip_ptr = NULL;
X		pcrft->cr_hdst[i] = NULL;
X		biton(pcrft->cr_chng,BIT_HOMCHAN+i);
X		break;
X
X	    /***************/
X	    /* faceforward */
X	    /***************/
X	    case 9:
X		if (vlen(pcrft->cr_vel) == 0.) {
X		    sprintf(buf,"%.27s - not moving",plogin->ln_input);
X		    goto badinp2;
X		}
X		pcrft->cr_ffwd = 1;
X		pcrft->cr_auto.ip_ptr = NULL;
X		rttosp(pcrft->cr_vel,pcrft->cr_dir);
X		biton(pcrft->cr_chng,BIT_AUTOFFWD);
X		biton(pcrft->cr_chng,BIT_DIR1);
X		biton(pcrft->cr_chng,BIT_DIR2);
X		fixdir(pcrft);
X		break;
X
X	    /*************/
X	    /* autopilot */
X	    /*************/
X	    case 10:
X		if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */
X		    i = 0;
X		else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1)
X		    goto badinp;
X
X		/* to a specific homing channel; privileges allow */
X		/* a negative # for absolute universe objects */
X		if (i) {
X		    if (i > MHOM || (i < 1 && !pcrft->cr_plvl))
X			goto badinp;
X		    if (i < 1) {
X			if ((i=(-i-1)) >= MAXUNIVERSE || !univlst[i].uv_type)
X			    goto badinp;
X			else
X			    pcrft->cr_auto.ip_ptr = univlst + i;
X		    } else {
X			i -= 1;
X			if (!pcrft->cr_hom[i].ip_ptr) {
X			    sprintf(buf,"%.25s - not homed in",plogin->ln_input);
X			    goto badinp2;
X			}
X			pcrft->cr_auto.ip_ptr = pcrft->cr_hom[i].ip_ptr;
X		    }
X
X		    /* if docked, shift to docked object (because docking */
X		    /* loses autos, docks, and torps but not homing)      */
X		    puniv = pcrft->cr_auto.ip_ptr;
X		    if (puniv->uv_type == 'P' &&
X		    puniv->uv_ptr.uv_crft->cr_dock.ip_ptr)
X			pcrft->cr_auto.ip_ptr =
X			puniv->uv_ptr.uv_crft->cr_dock.ip_ptr;
X		    /* but not to player's own craft */
X		    if (pcrft->cr_auto.ip_ptr == plogin->ln_play.ip_ptr)
X			pcrft->cr_auto.ip_ptr = NULL;
X
X		/* to closest to center/closest object */
X		} else {
X
Xdoauto:		    /* use viewing distance and smaller of */
X		    /* 5 degrees, half of viewing angle    */
X		    ftmp = MUL(10.,DEGTORAD);
X		    if (SUB(pcrft->cr_vang,ftmp) < 0.)
X			ftmp = pcrft->cr_vang;
X		    ftmp = DIV(ftmp,2.);
X		    l = pcrft->cr_vdst;
X		    pcrft->cr_auto.ip_ptr = NULL;
X
X		    /* select based on closest to center/closest */
X		    for (puniv = univlst+MAXUNIVERSE;puniv-- > univlst;) {
X			if (!puniv->uv_type) continue;
X			if (puniv == plogin->ln_play.ip_ptr) continue;
X			/*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/
X			tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v');
X			vecmul(/*tmpvec*/tmpdspl.vec,pcrft->cr_rmat,tmpvec);
X			rttosp(tmpvec,tmpvec);
X			m = INT(tmpvec[0]);
X			if ((tmpvec[2] == ftmp && m <= l) ||
X			(SUB(tmpvec[2],ftmp) <= 0. && m <= pcrft->cr_vdst)) {
X			    pcrft->cr_auto.ip_ptr = puniv;
X			    ftmp = tmpvec[2];
X			    l = m;
X			}
X		    }
X		}
X
X		biton(pcrft->cr_chng,BIT_AUTOFFWD);
X		if (!pcrft->cr_auto.ip_ptr) {
X		    sprintf(buf,"%.24s - nothing there",plogin->ln_input);
X		    goto badinp2;
X		} else {
X		    pcrft->cr_ffwd = NULL;
X		    /*vdiff(pcrft->cr_auto.ip_ptr->uv_pstn,pcrft->cr_pstn,
X		    pcrft->cr_dir);*/
X		    tmpdspl = vdisp(pcrft->cr_auto.ip_ptr,pcrft->cr_univ.ip_ptr,'v');
X		    rttosp(/*pcrft->cr_dir*/tmpdspl.vec,pcrft->cr_dir);
X		    biton(pcrft->cr_chng,BIT_DIR1);
X		    biton(pcrft->cr_chng,BIT_DIR2);
X		    fixdir(pcrft);
X		}
X		break;
X
X	    /***********/
X	    /* shields */
X	    /***********/
X	    case 11:
X		if (!pcrft->cr_sys[SHIELDS].s_cap) {
X		    sprintf(buf,"%.27s - no shields",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (sscanf(plogin->ln_input,"%*s %d",&i) != 1)
X		    goto badinp;
X
X		/* 0<=arg<=100 */
X		if (i < 0 || i > 100)
X		    goto badinp;
X
X		pcrft->cr_sys[SHIELDS].s_lvl = i;
X		biton(pcrft->cr_chng,BIT_SLEVEL+SHIELDS*flds[FLD_SLEVEL].f_grpw);
X		break;
X
X	    /**************/
X	    /* stopthrust */
X	    /**************/
X	    case 12:
X		if (!pcrft->cr_sys[ROCKETS].s_cap) {
X		    sprintf(buf,"%.27s - no rockets",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (vlen(pcrft->cr_thr) == 0.) {
X		    sprintf(buf,"%.20s - no pending thrust",plogin->ln_input);
X		    goto badinp2;
X		}
X		vinit(pcrft->cr_thr);
X		break;
X
X	    /**********/
X	    /* thrust */
X	    /**********/
X	    case 13:
X		if (!pcrft->cr_sys[ROCKETS].s_cap) {
X		    sprintf(buf,"%.27s - no rockets",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (!pcrft->cr_sys[ROCKETS].s_lvl) {
X		    sprintf(buf,"%.30s - no fuel",plogin->ln_input);
X		    goto badinp2;
X		}
X		vinit(tmpvec);
X		if ((i=sscanf(plogin->ln_input,"%*s %lf %lf %lf %lf%c",&ftmp,
X		tmpvec+0,tmpvec+1,tmpvec+2,&j)) < 1 || i > 4)
X		    goto badinp;
X
X		/* first number is thrust in direction pointed	*/
X		/* others are cartesian components		*/
X		pcrft->cr_dir[0] = ftmp;
X		sptort(pcrft->cr_dir,tmpvec2);
X		for (i=0;i<3;++i)
X		    pcrft->cr_thr[i] =
X		    ADD(pcrft->cr_thr[i],ADD(tmpvec[i],tmpvec2[i]));
X
X		/* turn off docking */
X		if (puniv=pcrft->cr_dock.ip_ptr) {
X
X		    /* fix other player's screen if docked with another craft */
X		    if (puniv->uv_type == 'P')
X			puniv->uv_ptr.uv_crft->cr_scrn[7][15] = '?';
X
X		    /* place craft away from docked object */
X		    /* according to direction of thrust    */
X		    rttosp(pcrft->cr_thr,tmpvec);
X		    tmpvec[0] =  ADD(MUL(FLOAT(puniv->uv_rad+1),2.),1.);
X		    sptort(tmpvec,tmpvec);
X		    for (i=0;i<3;++i)
X			pcrft->cr_pstn[i] = ADD(pcrft->cr_pstn[i],tmpvec[i]);
X		    vchngd(pcrft->cr_univ.ip_ptr);
X		    pcrft->cr_dock.ip_ptr = NULL;
X		    pcrft->cr_scrn[7][15] = '?';
X		}
X
X		break;
X
X	    /********/
X	    /* warp */
X	    /********/
X	    case 14:
X		if (!pcrft->cr_sys[WARP].s_cap) {
X		    sprintf(buf,"%.30s - no warp",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (sscanf(plogin->ln_input,"%*s %lf",&ftmp) != 1 || ftmp == 0.)
X		    goto badinp;
X		ftmp = MUL(ftmp,1000.);
X
X		/* check energy required */
X		l = 500L + 15L * INT(SQRT((ftmp < 0.) ? NEG(ftmp) : ftmp));
X		if (l > pcrft->cr_sys[WARP].s_lvl) {
X		    sprintf(buf,"%.18s - need at least %ld",plogin->ln_input,l);
X		    goto badinp2;
X		}
X
X		/* reduce warp energy level */
X		pcrft->cr_sys[WARP].s_lvl -= l;
X		biton(pcrft->cr_chng,BIT_SLEVEL+WARP*flds[FLD_SLEVEL].f_grpw);
X
X		/* new position; % and %dmg affect accuracy */
X		pcrft->cr_dir[0] = ftmp;
X		sptort(pcrft->cr_dir,tmpvec);
X		ftmp = DIV(MUL(ftmp,FLOAT(100-pcrft->cr_sys[WARP].s_pct+
X		pcrft->cr_sys[WARP].s_dmg)),100.);
X		for (i=0;i<3;++i)
X		    pcrft->cr_pstn[i] = ADD(pcrft->cr_pstn[i],
X		    ADD(tmpvec[i],MUL(ftmp,DIV(FLOAT(RANDOM(200)-100),100.))));
X		vchngd(pcrft->cr_univ.ip_ptr);
X		biton(pcrft->cr_chng,BIT_PN1);
X		biton(pcrft->cr_chng,BIT_PN2);
X		biton(pcrft->cr_chng,BIT_PN3);
X
X		/* turn off auto/dock for this and other crafts on this craft */
X		if (pcrft->cr_dock.ip_ptr) {
X		    pcrft->cr_dock.ip_ptr = NULL;
X		    pcrft->cr_scrn[7][15] = '?';
X		}
X		if (pcrft->cr_auto.ip_ptr) {
X		    pcrft->cr_auto.ip_ptr = NULL;
X		    biton(pcrft->cr_chng,BIT_AUTOFFWD);
X		}
X		for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) {
X		    register struct crft *pcrft2;
X		    if (puniv->uv_type != 'P') continue;
X		    pcrft2 = puniv->uv_ptr.uv_crft;
X		    if (pcrft2->cr_dock.ip_ptr == plogin->ln_play.ip_ptr) {
X			pcrft2->cr_dock.ip_ptr = NULL;
X			pcrft2->cr_scrn[7][15] = '?';
X			pcrft->cr_scrn[7][15] = '?';
X		    }
X		    if (pcrft2->cr_auto.ip_ptr == plogin->ln_play.ip_ptr) {
X			pcrft2->cr_auto.ip_ptr = NULL;
X			biton(pcrft2->cr_chng,BIT_AUTOFFWD);
X		    }
X		}
X
X		break;
X
X	    /***********************/
X	    /* damage (privileged) */
X	    /***********************/
X	    case 15:
X		if (!pcrft->cr_plvl)
X		    goto badinp;
X		if (sscanf(plogin->ln_input,"%*s %d %d",&i,&j) != 2)
X		    goto badinp;
X
X		/* must be a valid, existing system */
X		if (i < 0 || i >= MSYS || !pcrft->cr_sys[i].s_cap)
X		    goto badinp;
X
X		/* 0<=%dmg<=100 */
X		if (j < 0 || j > 100)
X		    goto badinp;
X
X		pcrft->cr_sys[i].s_dmg = j;
X		if (i == HULL)
X		    plogin->ln_play.ip_ptr->uv_mass = j;
X		biton(pcrft->cr_chng,BIT_SDMG+i*flds[FLD_SDMG].f_grpw);
X		break;
X
X	    /*********/
X	    /* leave */
X	    /*********/
X	    case 16:
X		/* only if privileged or nothing bad */
X		/* nearby or docked with an object */
X		if (pcrft->cr_plvl || pcrft->cr_sens[1] == 0 ||
X		((puniv=pcrft->cr_dock.ip_ptr) && puniv->uv_type == 'O')) {
X		    output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_COMMAND,
X		    plogin->ln_input);
X		    unplay(plogin);
X		    output(plogin,'E',0,0);
X		    output(plogin,'C',0,PROMPT);
X		    output(plogin,0,0,0);
X		    return;
X		}
X		sprintf(buf,"%.14s - not docked and BAD != 0",plogin->ln_input);
X		goto badinp2;
X
X	    /********/
X	    /* dock */
X	    /********/
X	    case 17:
X		/* find the closest, dock'able object */
X		l = 10000L;
X		pcrft->cr_dock.ip_ptr = NULL;
X		for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) {
X		    double *pvel;
X		    switch(puniv->uv_type) {
X			case 0: continue;
X			case 'P':
X			    if (puniv == plogin->ln_play.ip_ptr)
X				continue;
X			    if (puniv->uv_ptr.uv_crft->cr_dock.ip_ptr)
X				continue;
X			    pvel = puniv->uv_ptr.uv_crft->cr_vel;
X			    break;
X			case 'T':
X			    pvel = puniv->uv_ptr.uv_torp->tp_vel;
X			    break;
X			case 'A':
X			    pvel = puniv->uv_ptr.uv_aln->al_vel;
X			    break;
X			case 'O':
X			    if (puniv->uv_pctr == ' ' || puniv->uv_pctr == '*')
X				continue;
X			    pvel = puniv->uv_ptr.uv_obj->oj_vel;
X			    break;
X		    }
X		    /*m = INT(vdist(pcrft->cr_pstn,puniv->uv_pstn));*/
X		    tmpdspl = vdisp(pcrft->cr_univ.ip_ptr,puniv,'d');
X		    m = INT(tmpdspl.dst);
X		    if (m < l && m <= 5*(puniv->uv_rad+1)) {
X			pcrft->cr_dock.ip_ptr = puniv;
X			l = m;
X			vcopy(tmpvec,pvel);
X		    }
X		}
X		if (!pcrft->cr_dock.ip_ptr) {
X		    sprintf(buf,"%.25s - too far away",plogin->ln_input);
X		    goto badinp2;
X		}
X		puniv = pcrft->cr_dock.ip_ptr;
X
X		/* must also be within range next movement iteration */
X		for (i=0;i<3;++i)
X		    tmpvec[i] = SUB(ADD(puniv->uv_pstn[i],tmpvec[i]),
X		    ADD(pcrft->cr_pstn[i],pcrft->cr_vel[i]));
X		if (INT(vlen(tmpvec)) > 5*(puniv->uv_rad+1)) {
X		    sprintf(buf,"%.22s - moving too fast",plogin->ln_input);
X		    pcrft->cr_dock.ip_ptr = NULL;
X		    goto badinp2;
X		}
X
X		/* dock */
X		pcrft->cr_scrn[7][15] = '?';
X		vinit(pcrft->cr_thr);
X		vcopy(pcrft->cr_pstn,puniv->uv_pstn);
X		vchngd(pcrft->cr_univ.ip_ptr);
X		biton(pcrft->cr_chng,BIT_PN1);
X		biton(pcrft->cr_chng,BIT_PN2);
X		biton(pcrft->cr_chng,BIT_PN3);
X		output(plogin,0,0,0);
X
X		/* fix autopilots, docks, torp aim, alien attack */
X		for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) {
X		    register struct crft *pcrft2;
X		    struct aln *paln;
X		    switch(puniv->uv_type) {
X			case 0: continue;
X			case 'P':
X			    pcrft2 = puniv->uv_ptr.uv_crft;
X			    if (pcrft2->cr_auto.ip_ptr ==
X			    plogin->ln_play.ip_ptr) {
X
X				/* shift autopilot to item docked with */
X				/* if its not an object and not itself */
X				if (pcrft->cr_dock.ip_ptr->uv_type != 'O' &&
X				pcrft->cr_dock.ip_ptr != puniv)
X				    pcrft2->cr_auto.ip_ptr =
X				    pcrft->cr_dock.ip_ptr;
X
X				/* its an object or itself - lose autopilot */
X				else
X				    pcrft2->cr_auto.ip_ptr = NULL;
X				biton(pcrft2->cr_chng,BIT_AUTOFFWD);
X				pcrft2->cr_scrn[7][15] = '?';
X			    }
X
X			    if (pcrft2->cr_dock.ip_ptr ==
X			    plogin->ln_play.ip_ptr) {
X
X				/* shift dock to item docked */
X				/* with if its an object  */
X				if (pcrft->cr_dock.ip_ptr->uv_type == 'O')
X				    pcrft2->cr_dock.ip_ptr =
X				    pcrft->cr_dock.ip_ptr;
X				else
X				    pcrft2->cr_dock.ip_ptr = NULL;
X				pcrft2->cr_scrn[7][15] = '?';
X			    }
X
X			    break;
X			case 'T':
X			    ptorp = puniv->uv_ptr.uv_torp;
X			    if (ptorp->tp_aim.ip_ptr ==
X			    plogin->ln_play.ip_ptr &&
X			    pcrft->cr_dock.ip_ptr->uv_type == 'O' &&
X			    ptorp->tp_fby.ip_ptr &&
X			    ptorp->tp_fby.ip_ptr->uv_type == 'P') {
X				pcrft2 = ptorp->tp_fby.ip_ptr->uv_ptr.uv_crft;
X				output(pcrft2->cr_lgn,'B',0,0);
X				setrpt(pcrft2);
X				rpt(pcrft2,"Torpedo missed - target docked");
X				fnshrpt(pcrft2,1);
X				remove(ptorp->tp_univ);
X			    }
X			    break;
X			case 'A':
X			    paln = puniv->uv_ptr.uv_aln;
X			    if (paln->al_atck.ip_ptr == plogin->ln_play.ip_ptr
X			    && (pcrft->cr_dock.ip_ptr->uv_type == 'O' ||
X			    pcrft->cr_dock.ip_ptr == puniv)) {
X				paln->al_atck.ip_ptr = NULL;
X			    }
X			    break;
X		    }
X		}
X		break;
X
X	    /*********/
X	    /* radio */
X	    /*********/
X	    case 18:
X		if (sscanf(plogin->ln_input,"%*s %[^\n]",buf) != 1)
X		    goto badinp;
X
X		output(pcrft->cr_lgn,0,0,0);
X
X		/* similar to autopilot */
X		ftmp = MUL(10.,DEGTORAD);
X		if (SUB(pcrft->cr_vang,ftmp) < 0.)
X		    ftmp = pcrft->cr_vang;
X		ftmp = DIV(ftmp,2.);
X		for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) {
X		    if (puniv->uv_type != 'P') continue;
X		    if (puniv->uv_ptr.uv_crft == pcrft) continue;
X		    /*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/
X		    tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v');
X		    vecmul(/*tmpvec*/tmpdspl.vec,pcrft->cr_rmat,tmpvec);
X		    rttosp(tmpvec,tmpvec);
X		    if (SUB(tmpvec[2],ftmp) <= 0.) {
X			char buf2[40+1];
X			plgn = puniv->uv_ptr.uv_crft->cr_lgn;
X			output(plgn,'B',0,0);
X			output(plgn,'H',FLD_RADIO,buf);
X			/*vdiff(pcrft->cr_pstn,puniv->uv_pstn,tmpvec);*/
X			tmpdspl = vdisp(pcrft->cr_univ.ip_ptr,puniv,'v');
X			rttosp(/*tmpvec*/tmpdspl.vec,tmpvec);
X			setrpt(puniv->uv_ptr.uv_crft);
X			sprintf(buf2,"Radio @%ld %.1f %.1f",INT(tmpvec[0]),
X			DIV(tmpvec[1],DEGTORAD),DIV(tmpvec[2],DEGTORAD));
X			rpt(puniv->uv_ptr.uv_crft,buf2);
X			fnshrpt(puniv->uv_ptr.uv_crft,1);
X		    }
X		}
X		break;
X
X	    /*******/
X	    /* who */
X	    /*******/
X	    case 19:
X		if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */
X		    i = 0;
X		else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1 || i < 0)
X		    goto badinp;
X		i *= flds[FLD_REPORT].f_maxg; /* skip display group count */
X
X		setrpt(pcrft);
X		*buf = NULL;
X		for (plgn=loginlst+MAXLOGIN;plgn-- > loginlst;) {
X		    if (!plgn->ln_play.ip_ptr) continue;
X		    if (i-- > 0) continue;
X		    if (strlen(buf) + strlen(plgn->ln_name) +
X		    strlen(plgn->ln_crft) + 5 > flds[FLD_REPORT].f_len) {
X			rpt(pcrft,buf);
X			*buf = NULL;
X		    }
X		    sprintf(buf+strlen(buf),"%s/%s(%c) ",plgn->ln_name,
X		    plgn->ln_crft,plgn->ln_play.ip_ptr->uv_pctr);
X		}
X		rpt(pcrft,buf);
X		fnshrpt(pcrft,0);
X		break;
X
X	    /**********/
X	    /* report */
X	    /**********/
X	    case 20:
X		if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */
X		    i = 0;
X		else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1 || i < 0)
X		    goto badinp;
X		i *= flds[FLD_REPORT].f_maxg; /* skip display group count */
X
X		setrpt(pcrft);
X
X		/* almost identical to view() */
X		for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) {
X		    if (!puniv->uv_type) continue;
X		    if (puniv->uv_ptr.uv_crft == pcrft) continue;
X		    /*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/
X		    tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v');
X		    vecmul(/*tmpvec*/tmpdspl.vec,pcrft->cr_rmat,tmpvec);
X		    rttosp(tmpvec,tmpvec);
X		    ftmp = DIV(pcrft->cr_vang,2.);
X		    if (SUB(ftmp,tmpvec[2]) >= 0. &&
X		    (l=INT(tmpvec[0])) <= pcrft->cr_vdst) {
X			if (i-- > 0) continue;
X			tmpvec[0] = DIV(tmpvec[2],ftmp);
X			tmpvec[2] = DIV(PI,2.);
X			sptort(tmpvec,tmpvec);
X
X			/* common characteristics */
X			sprintf(buf,"%ld,%ld(%c)@%ld",-INT(MUL(tmpvec[1],7.)),
X			INT(MUL(tmpvec[0],15.)),puniv->uv_pctr,l);
X
X			/* individual characteristics */
X			switch(puniv->uv_type) {
X			    case 'O':
X				sprintf(buf+strlen(buf)," r=%d m=%ld",
X				puniv->uv_rad,puniv->uv_mass);
X				break;
X			    case 'P':
X				plgn = puniv->uv_ptr.uv_crft->cr_lgn;
X				sprintf(buf+strlen(buf)," %s/%s h%ld s%d",
X				plgn->ln_name,plgn->ln_crft,puniv->uv_mass,
X				puniv->uv_ptr.uv_crft->cr_sys[SHIELDS].s_lvl);
X				break;
X			    case 'T':
X				sprintf(buf+strlen(buf)," h%ld",puniv->uv_mass);
X				break;
X			    case 'A':
X				sprintf(buf+strlen(buf)," h%ld s%d",
X				puniv->uv_mass,
X				puniv->uv_ptr.uv_aln->al_sys[SHIELDS].s_lvl);
X				break;
X			}
X
X			/* indicate auto'd, dock'd, or home'd */
X			l = 0;
X			if (pcrft->cr_auto.ip_ptr == puniv) {
X			    if (!l) strcat(buf," (");
X			    l = 1;
X			    strcat(buf,"A");
X			}
X			if (pcrft->cr_dock.ip_ptr == puniv) {
X			    if (!l) strcat(buf," (");
X			    l = 1;
X			    strcat(buf,"D");
X			}
X			for (j=0;j<MHOM;++j)
X			    if (pcrft->cr_hom[j].ip_ptr == puniv) {
X				if (!l) strcat(buf," (");
X				l = 1;
X				sprintf(buf+strlen(buf),"%d",j+1);
X			    }
X			if (l) strcat(buf,")");
X
X			rpt(pcrft,buf);
X		    }
X		}
X		fnshrpt(pcrft,0);
X		break;
X
X	    /***********/
X	    /* phasers */
X	    /***********/
X	    case 21:
X		if (!pcrft->cr_sys[PHASERS].s_cap) {
X		    sprintf(buf,"%.27s - no phasers",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (sscanf(plogin->ln_input,"%*s %d",&i) != 1)
X		    goto badinp;
X		
X		/* 1<=arg<=1000 */
X		if (i < 1 || i > 1000)
X		    goto badinp;
X
X		/* check if conditions allow phasers */
X		if (pcrft->cr_dock.ip_ptr) {
X		    sprintf(buf,"%.21s - not while docked",plogin->ln_input);
X		    goto badinp2;
X		}
X		puniv = pcrft->cr_auto.ip_ptr;
X		if (!puniv || puniv->uv_type == 'O') {
X		    sprintf(buf,"%.19s - nothing to fire at",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (inuc) {
X		    sprintf(buf,"%.24s - not in '-cmd'",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		/* must have enough energy for phaser blast */
X		if (!pcrft->cr_sys[DILITH].s_cap ||
X		pcrft->cr_sys[DILITH].s_lvl < i) {
X		    sprintf(buf,"%.20s - not enough energy",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		/* phasers must not be damaged too much */
X		if (pcrft->cr_sys[PHASERS].s_dmg >= 60) {
X		    sprintf(buf,"%.22s - too much damage",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		/* use the requested energy */
X		pcrft->cr_sys[DILITH].s_lvl -= i;
X		biton(pcrft->cr_chng,BIT_SLEVEL+DILITH*flds[FLD_SLEVEL].f_grpw);
X
X		/* compute damage */
X		l = i;
X		l *= pcrft->cr_sys[PHASERS].s_pct;
X		l /= 100;
X		l *= (100-pcrft->cr_sys[PHASERS].s_dmg);
X		l /= 100;
X		l *= pcrft->cr_sys[PHASERS].s_cap;
X		l /= 100;
X
X		/* finally, do it */
X		output(pcrft->cr_lgn,0,0,0); /* flush buffering */
X		damage(plogin->ln_play.ip_ptr,puniv,1.,FLOAT(l),
X		"Phaser attack");
X
X		break;
X
X	    /***********/
X	    /* torpedo */
X	    /***********/
X	    case 22:
X		if (!pcrft->cr_sys[TORPS].s_cap ||
X		pcrft->cr_sys[TORPS].s_lvl < 1) {
X		    sprintf(buf,"%.25s - no torpedoes",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		/* check if conditions allow torpedoes */
X		if (pcrft->cr_dock.ip_ptr) {
X		    sprintf(buf,"%.21s - not while docked",plogin->ln_input);
X		    goto badinp2;
X		}
X		puniv = pcrft->cr_auto.ip_ptr;
X		if (!puniv || puniv->uv_type == 'O') {
X		    sprintf(buf,"%.19s - nothing to fire at",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (inuc) {
X		    sprintf(buf,"%.24s - not in '-cmd'",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		/* torpedo tubes must not be damaged too much */
X		if (pcrft->cr_sys[TORPS].s_dmg >= 60) {
X		    sprintf(buf,"%.22s - too much damage",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		/* search for an open slot */
X		for (ptorp=torplst+MAXTORP;ptorp-- > torplst;)
X		    if (!ptorp->tp_aim.ip_ptr)
X			break;
X		if (ptorp < torplst) {
X		    sprintf(buf,"%.17s - sorry, universe full",plogin->ln_input);
X		    goto badinp2;
X		}
X		for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;)
X		    if (!puniv->uv_type)
X			break;
X		if (puniv < univlst) {
X		    perror("play: ptorp but no puniv");
X		    goto badinp;
X		}
X
X		/* reduce torpedo count */
X		pcrft->cr_sys[TORPS].s_lvl -= 1;
X		biton(pcrft->cr_chng,BIT_SLEVEL+TORPS*flds[FLD_SLEVEL].f_grpw);
X
X		/* put torpedo into the universe */
X		pcrft->cr_dir[0] = 1.0;
X		sptort(pcrft->cr_dir,tmpvec);
X		for (i=0;i<3;++i) {
X		    ptorp->tp_pstn[i] = ADD(pcrft->cr_pstn[i],
X		    ptorp->tp_thr[i]=MUL(tmpvec[i],50.));
X		    ptorp->tp_vel[i] = ADD(pcrft->cr_vel[i],MUL(tmpvec[i],10.));
X		}
X		ptorp->tp_aim.ip_ptr = pcrft->cr_auto.ip_ptr;
X		ptorp->tp_fby.ip_ptr = plogin->ln_play.ip_ptr;
X		ptorp->tp_dist = INT(vdist(ptorp->tp_pstn,
X		ptorp->tp_aim.ip_ptr->uv_pstn));
X		ptorp->tp_dmg = 0;
X		ptorp->tp_lhit.ip_ptr = NULL;
X		puniv->uv_type = 'T';
X		puniv->uv_pctr = '+';
X		puniv->uv_pstn = ptorp->tp_pstn;
X		puniv->uv_mass = ptorp->tp_dmg;
X		puniv->uv_rad = 1;
X		puniv->uv_ptr.uv_torp = ptorp;
X		ptorp->tp_univ.ip_ptr = puniv;
X
X		break;
X
X	    /*******/
X	    /* fix */
X	    /*******/
X	    case 23:
X		if (!pcrft->cr_sys[DMGCON].s_cap) {
X		    sprintf(buf,"%.20s - no damage control",plogin->ln_input);
X		    goto badinp2;
X		}
X		if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */
X		    i = 0;
X		else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1)
X		    goto badinp;
X
X		/* 0<=arg<=MSYS */
X		if (i < 0 || i > MSYS)
X		    goto badinp;
X
X		/* subsystem must be present */
X		if (i > 0 && !pcrft->cr_sys[i-1].s_cap) {
X		    sprintf(buf,"%.20s - no such subsystem",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		pcrft->cr_sys[DMGCON].s_lvl = i;
X		biton(pcrft->cr_chng,BIT_SLEVEL+DMGCON*flds[FLD_SLEVEL].f_grpw);
X		break;
X
X	    /***************/
X	    /* - (ucmd)    */
X	    /***************/
X	    case 24:
X		if (inuc) {
X		    sprintf(buf,"%.24s - nested '-cmd'",plogin->ln_input);
X		    goto badinp2;
X		}
X		for (i=0;i<9;ucargs[i++][0] = NULL) ;
X		if ((i=sscanf(plogin->ln_input,
X		"-%s %20s %20s %20s %20s %20s %20s %20s %20s %20s%c",
X		buf,ucargs[0],ucargs[1],ucargs[2],ucargs[3],ucargs[4],
X		ucargs[5],ucargs[6],ucargs[7],ucargs[8],&j)) < 1 || i > 10)
X		    goto badinp;
X		buf[sizeof(getuckey.uc_name)-1] = NULL;
X
X		/* set up data structure to get first line of ucmd */
X		binit((char *)&getuckey,sizeof(getuckey));
X		getuckey.uc_ucmdkey = UCMD;
X		strcpy(getuckey.uc_plyr,plogin->ln_name);
X		strcpy(getuckey.uc_name,buf);
X		getuckey.uc_ucmd = 1;
X
X		/* verify that ucmd exists */
X		dbmkey.dptr = (char *)&getuckey;
X		dbmkey.dsize = sizeof(getuckey);
X		dbmdata = fetch(dbmkey);
X		if (!dbmdata.dptr) {
X		    sprintf(buf,"%.23s - no such '-cmd'",plogin->ln_input);
X		    goto badinp2;
X		}
X		inuc = 1;
X		break;
X
X	    /***********/
X	    /* sensors */
X	    /***********/
X	    case 25:
X		if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */
X		    i = 0;
X		else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1 || i < 0)
X		    goto badinp;
X		i *= flds[FLD_REPORT].f_maxg; /* skip display group count */
X
X		setrpt(pcrft);
X
X		/* stolen from report and modified */
X		for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) {
X		    if (!puniv->uv_type) continue;
X		    if (puniv->uv_ptr.uv_crft == pcrft) continue;
X		    /*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/
X		    tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v');
X		    vcopy(tmpvec,tmpdspl.vec);
X		    vcopy(tmpvec2,tmpvec);
X		    rttosp(tmpvec,tmpvec);
X		    l = INT(tmpvec[0]);
X		    if (l <= 5000L) {
X			if (i-- > 0) continue;
X
X			/* is it on viewscreen? */
X			vecmul(tmpvec2,pcrft->cr_rmat,tmpvec2);
X			rttosp(tmpvec2,tmpvec2);
X			ftmp = DIV(pcrft->cr_vang,2.);
X			*buf = NULL;
X			if (SUB(ftmp,tmpvec2[2]) >= 0.) {
X			    tmpvec2[0] = DIV(tmpvec2[2],ftmp);
X			    tmpvec2[2] = DIV(PI,2.);
X			    sptort(tmpvec2,tmpvec2);
X			    sprintf(buf,"%ld,%ld",-INT(MUL(tmpvec2[1],7.)),
X			    INT(MUL(tmpvec2[0],15.)));
X			}
X
X
X			/* common characteristics */
X			sprintf(buf+strlen(buf),"(%c)@%ld %.1f %.1f",
X			puniv->uv_pctr,l,DIV(tmpvec[1],DEGTORAD),
X			DIV(tmpvec[2],DEGTORAD));
X
X			/* indicate auto'd, dock'd, or home'd */
X			l = 0;
X			if (pcrft->cr_auto.ip_ptr == puniv) {
X			    if (!l) strcat(buf," (");
X			    l = 1;
X			    strcat(buf,"A");
X			}
X			if (pcrft->cr_dock.ip_ptr == puniv) {
X			    if (!l) strcat(buf," (");
X			    l = 1;
X			    strcat(buf,"D");
X			}
X			for (j=0;j<MHOM;++j)
X			    if (pcrft->cr_hom[j].ip_ptr == puniv) {
X				if (!l) strcat(buf," (");
X				l = 1;
X				sprintf(buf+strlen(buf),"%d",j+1);
X			    }
X			if (l) strcat(buf,")");
X
X			rpt(pcrft,buf);
X		    }
X		}
X		fnshrpt(pcrft,0);
X		break;
X
X	    /**********/
X	    /* lockon */
X	    /**********/
X	    case 26:
X		if (!pcrft->cr_lhit.ip_ptr) {
X		    sprintf(buf,"%.26s - no attacker",plogin->ln_input);
X		    goto badinp2;
X		}
X
X		/* undo FFWD/AUTO; point in direction of last hit position */
X		fixaf(pcrft);
X		vdiff(pcrft->cr_lhpstn,pcrft->cr_pstn,pcrft->cr_dir);
X		rttosp(pcrft->cr_dir,pcrft->cr_dir);
X		biton(pcrft->cr_chng,BIT_DIR1);
X		biton(pcrft->cr_chng,BIT_DIR2);
X		fixdir(pcrft);
X
X		/* try autopiloting (gross!) */
X		goto doauto;
X
X	    /**********/
X	    /* redraw */
X	    /**********/
X	    case 27:
X		goto redraw;
X
X	    default:
X		perror("play: impossible cmd");
X		goto badinp;
X	}
X
X	/* display last command */
X	output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_COMMAND,plogin->ln_input);
X
X	/* process ucmd */
Xdone:	if (inuc) {
X	    char *ip,*op;
X
X	    /* get ucmd text; setup for next one */
X	    dbmdata = fetch(dbmkey);
X	    if (!dbmdata.dptr) goto done2;
X	    getuckey.uc_ucmd += 1;
X
X	    /* substitute arguments */
X	    for (ip=dbmdata.dptr,op=plogin->ln_input;
X	    *ip && op < plogin->ln_input + sizeof(plogin->ln_input)-1;) {
X		if (*ip == '$' && ip[1] >= '1' && ip[1] <= '9') {
X		    char *ap=ucargs[ip[1]-'1'];
X		    while (*ap &&
X		    op < plogin->ln_input + sizeof(plogin->ln_input)-1)
X			*op++ = *ap++;
X		    ip += 2;
X		} else
X		    *op++ = *ip++;
X	    }
X	    *op = NULL;
X
X	    goto douc;
X	}
X
X	/* update screen, reposition cursor, and clear command line if present */
Xdone2:	nums(pcrft);
X	view(pcrft);
X	if (plogin->ln_input[0]) {
X	    output(plogin,'D',0,0);
X	    plogin->ln_input[0] = NULL;
X	}
X	output(plogin,0,0,0);
X
X#ifdef DEBUG
X	VDBG("play return\n");
X#endif
X	return;
X}
X
Xstatic int okdir(plogin,pcrft,pftmp)
Xregister struct login *plogin;
Xregister struct crft *pcrft;
Xdouble *pftmp;
X{
X	char c;
X
X	/* no argument, use half viewing angle */
X	if (sscanf(plogin->ln_input,"%*s%c",&c) != 1) {
X	    *pftmp = DIV(pcrft->cr_vang,2.);
X	    return(1);
X	}
X
X	/* 0<arg<360 */
X	if (sscanf(plogin->ln_input,"%*s %lf",pftmp) != 1)
X	    return(0);
X	if (SUB(*pftmp,360.) >= 0. || *pftmp <= 0.)
X	    return(0);
X	*pftmp = MUL(*pftmp,DEGTORAD);
X	return(1);
X}
X
Xstatic VOID fixaf(pcrft)
Xregister struct crft *pcrft;
X{
X	if (pcrft->cr_ffwd) {
X	    pcrft->cr_ffwd = NULL;
X	    biton(pcrft->cr_chng,BIT_AUTOFFWD);
X	} else if (pcrft->cr_auto.ip_ptr) {
X	    pcrft->cr_auto.ip_ptr = NULL;
X	    biton(pcrft->cr_chng,BIT_AUTOFFWD);
X	}
X}
END_OF_play.c
if test 31675 -ne `wc -c <play.c`; then
    echo shar: \"play.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f unplay.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"unplay.c\"
else
echo shar: Extracting \"unplay.c\" \(3248 characters\)
sed "s/^X//" >unplay.c <<'END_OF_unplay.c'
X/*
X * Spacewar - remove a player from the universe
X *	      update/destroy the ship
X *
X * Copyright 1985 obo Systems, Inc.
X * Copyright 1985 Dan Rosenblatt
X */
X
X#ifndef VMS
X#include <sys/types.h>
X#include <dbm.h>
X#else /* BSD SYSIII SYSV */
X#include <types.h>
X#include "dbm.h"
X#endif /* VMS */
X#include "spacewar.h"
X#include "universe.h"
X#include "plyr.h"
X#include "login.h"
X#include "sys.h"
X#include "crft.h"
X
XVOID unplay(plogin)
Xregister struct login *plogin;
X{
X	register struct crft *pcrft;
X	struct crft *pcrft2;
X	struct sys *psys;
X	struct crftkey getcrkey;
X	struct syskey getskey;
X	struct plyrkey getplkey;
X	struct plyr getpldat;
X	datum dbmkey,dbmdata;
X	int i;
X	extern int numpling;
X
X#ifdef DEBUG
X	DBG("unplay(#%d/%s)\n",plogin-loginlst,plogin->ln_name);
X#endif
X
X	/* privileged or docked with an object or nothing bad nearby */
X	pcrft = plogin->ln_play.ip_ptr->uv_ptr.uv_crft;
X	if (pcrft->cr_plvl || (pcrft->cr_dock.ip_ptr &&
X	pcrft->cr_dock.ip_ptr->uv_type == 'O') || pcrft->cr_sens[1] == 0)
X	    crftupdate(plogin);
X
X	/* destroy; report and give credit if due to another player */
X	else {
X
X	    /* delete craft and subsystems from database */
X	    binit((char *)&getcrkey,sizeof(getcrkey));
X	    getcrkey.cr_crftkey = CRAFT;
X	    strcpy(getcrkey.cr_plyr,plogin->ln_name);
X	    strcpy(getcrkey.cr_name,plogin->ln_crft);
X	    dbmkey.dptr = (char *)&getcrkey;
X	    dbmkey.dsize = sizeof(getcrkey);
X	    if (delete(dbmkey))
X		perror("unplay: can't delete crft");
X	    binit((char *)&getskey,sizeof(getskey));
X	    getskey.s_syskey = SUBSYS;
X	    strcpy(getskey.s_plyr,plogin->ln_name);
X	    strcpy(getskey.s_crft,plogin->ln_crft);
X	    dbmkey.dptr = (char *)&getskey;
X	    dbmkey.dsize = sizeof(getskey);
X	    for (psys=pcrft->cr_sys,i=0;i < MSYS;++psys,++i) {
X		if (!psys->s_cap) continue;  /* not in this craft */
X		getskey.s_type = i;
X		if (delete(dbmkey))
X		    perror("unplay: can't delete sys");
X	    }
X
X	    /* update player losing craft */
X	    binit((char *)&getplkey,sizeof(getplkey));
X	    getplkey.pl_plyrkey = PLYR;
X	    strcpy(getplkey.pl_name,plogin->ln_name);
X	    dbmkey.dptr = (char *)&getplkey;
X	    dbmkey.dsize = sizeof(getplkey);
X	    dbmdata = fetch(dbmkey);
X	    if (dbmdata.dptr) {
X		bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
X		getpldat.pl_slst += 1;
X		getpldat.pl_klst += pcrft->cr_kill;
X		getpldat.pl_plst += pcrft->cr_pnts;
X		getpldat.pl_tlst += pcrft->cr_time;
X		dbmdata.dptr = (char *)&getpldat;
X		dbmdata.dsize = sizeof(getpldat);
X		if (store(dbmkey,dbmdata))
X		    perror("unplay: can't update plyr");
X	    } else
X		perror("unplay: can't fetch plyr");
X
X	    /* report destruction and credit destroyer */
X	    if (pcrft->cr_lhit.ip_ptr && pcrft->cr_lhit.ip_ptr->uv_type == 'P') {
X		pcrft2 = pcrft->cr_lhit.ip_ptr->uv_ptr.uv_crft;
X		pcrft2->cr_kill += 1;
X		output(pcrft2->cr_lgn,'B',0,0);
X		setrpt(pcrft2);
X		rpt(pcrft2,"Ship destroyed by you");
X		fnshrpt(pcrft2,1);
X	    }
X	}
X
X	/* remove craft from universe */
X	remove(plogin->ln_play);
X	if (--numpling < 0) numpling = 0;
X
X	/* put player back to command mode */
X	plogin->ln_iomode = NULL;
X	plogin->ln_crft[0] = NULL;
X	plogin->ln_play.ip_ptr = NULL;
X	plogin->ln_stat = NULL;
X	plogin->ln_substat = NULL;
X
X#ifdef DEBUG
X	VDBG("unplay return\n");
X#endif
X}
END_OF_unplay.c
if test 3248 -ne `wc -c <unplay.c`; then
    echo shar: \"unplay.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 6\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0