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

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

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



#! /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 2 (of 6)."
# Contents:  cmd.c doc.ms mail.c update.c
# Wrapped by billr@saab on Tue May 31 09:54:49 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f cmd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cmd.c\"
else
echo shar: Extracting \"cmd.c\" \(11449 characters\)
sed "s/^X//" >cmd.c <<'END_OF_cmd.c'
X/*
X * Spacewar - get and process player commands doing character/line editing
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 <errno.h>
X#include "spacewar.h"
X#include "universe.h"
X#include "login.h"
X#include "uio.h"
X#include "plyr.h"
X#include "mlbx.h"
X#ifdef VMS
X#	include <iodef.h>
X#	include <ssdef.h>
X	short inmlbx;
X#endif /* VMS */
X
Xint doproctrap,doupdate;
Xstatic struct login *getinp();
Xstatic VOID cmd2();
Xextern VOID prvcmd();
X
XVOID cmd()
X{
X	register struct login *plogin;
X
X#ifdef DEBUG
X	DBG("cmd()\n");
X#endif
X
X	/* get and process a command */
X	if (!(plogin = getinp())) {
X#ifdef DEBUG
X		VDBG("cmd return\n");
X#endif
X		return;
X	}
X
X	/* based on current major command */
X#ifdef DEBUG
X	VDBG("cmd: stat #%d '%c'\n",plogin-loginlst,plogin->ln_stat);
X#endif
X	switch(plogin->ln_stat) {
X
X		case 'M':	/* Mail (Complain) */
X			doupdate = 0;
X			mail(plogin);
X			if (doupdate == 0) doupdate = 1;
X			break;
X
X		case 'B':	/* reBuild */
X			doupdate = 0;
X			build(plogin);
X			if (doupdate == 0) doupdate = 1;
X			break;
X
X		case 'S':	/* See */
X			doupdate = 0;
X			see(plogin);
X			if (doupdate == 0) doupdate = 1;
X			break;
X
X		case 'U':	/* Usercmd */
X			doupdate = 0;
X			usrcmd(plogin);
X			if (doupdate == 0) doupdate = 1;
X			break;
X
X		case 'W':	/* Who */
X			doupdate = 0;
X			who(plogin);
X			if (doupdate == 0) doupdate = 1;
X			break;
X
X		case 'P':	/* Play */
X			doupdate = 0;
X			play(plogin);
X			if (doupdate == 0) doupdate = 1;
X			break;
X
X		default:	/* not doing anything yet */
X			doupdate = 0;
X			cmd2(plogin);
X			if (doupdate == 0) doupdate = 1;
X			break;
X	}
X
X	plogin->ln_input[0] = NULL;
X#ifdef DEBUG
X	VDBG("cmd return\n");
X#endif
X}
X
Xstatic VOID cmd2(plogin)
Xregister struct login *plogin;
X{
X	int inplen=strlen(plogin->ln_input);
X	struct plyrkey getplkey;
X	struct plyr getpldat;
X	datum dbmkey,dbmdata;
X
X#ifdef DEBUG
X	DBG("cmd2()\n");
X#endif
X
X	/********************/
X	/* response is name */
X	/********************/
X	if (!plogin->ln_name[0]) { /* no name */
X
X#ifdef DEBUG
X		VDBG("cmd2: #%d response is name\n",plogin-loginlst);
X#endif
X
X		/* do again if too short or long */
X		if (inplen < 2 || inplen >= sizeof(plogin->ln_name)) {
X			output(plogin,'C',0,
X			"Name must be 2 to 8 characters\n\nWhat is your name?");
X			output(plogin,0,0,0);
X#ifdef DEBUG
X			VDBG("cmd2 return\n");
X#endif
X			return;
X		}
X
X		/* insure no players playing more than once */
X		{
X			int i;
X			struct login *plgn;
X
X#ifdef DEBUG
X			VDBG("cmd2: #%d checking for dup login (%s)\n",
X			plogin-loginlst,plogin->ln_input);
X#endif
X			for (i=MAXLOGIN,plgn=loginlst;i-- > 0;++plgn) {
X				if (!strcmp(plogin->ln_input,plgn->ln_name)) {
X				    output(plogin,'C',0,
X				    "Someone is already playing that name.\n\n\
XHow about another name?");
X				    output(plogin,0,0,0);
X#ifdef DEBUG
X				    VDBG("cmd2 return\n");
X#endif
X				    return;
X				}
X			}
X		}
X
X		/* store name and prompt for password */
X		strcpy(plogin->ln_name,plogin->ln_input);
X		output(plogin,'C',0,"Password:");
X		output(plogin,0,0,0);
X
X		/* set up password state */
X		plogin->ln_stat = 'p';
X		plogin->ln_iomode = 'p'; /* no echo */
X
X	/************************/
X	/* response is password */
X	/************************/
X	} else if (plogin->ln_stat == 'p') { /* password state */
X
X#ifdef DEBUG
X		VDBG("cmd2: #%d (%s) response is password\n",
X		plogin-loginlst,plogin->ln_name);
X#endif
X
X		/* get player */
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
X		/* found; check password */
X		dbmdata = fetch(dbmkey);
X		if (dbmdata.dptr) {
X
X#ifdef DEBUG
X			VDBG("cmd2: #%d (%s) found, checking password\n",
X			plogin-loginlst,plogin->ln_name);
X#endif
X
X			bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
X
X			/* bad password */
X			if (strcmp(plogin->ln_input,getpldat.pl_passwd)) {
X				output(plogin,'C',0,"Incorrect.\n\nPassword:");
X				output(plogin,0,0,0);
X
X			/* good password; check for mail and give prompt */
X			} else {
X				output(plogin,'C',0,"\n\n");
X				if (getpldat.pl_seenml < getpldat.pl_lstml)
X				output(plogin,'C',0,"You have new mail\n");
X
X				output(plogin,'C',0,PROMPT);
X				output(plogin,0,0,0);
X				plogin->ln_stat = NULL;
X				plogin->ln_iomode = NULL;
X
X				/* update login info */
X				++getpldat.pl_numlgn;
X				time(&getpldat.pl_lstlgn);
X				dbmdata.dptr = (char *)&getpldat;
X				dbmdata.dsize = sizeof(getpldat);
X				if (store(dbmkey,dbmdata))
X					perror("cmd2: can't update plyr");
X			}
X
X		/* not found; insert new player */
X		} else {
X
X#ifdef DEBUG
X			VDBG("cmd2: #%d (%s) not found, inserting\n",
X			plogin-loginlst,plogin->ln_name);
X#endif
X
X			/* do again if too short or long */
X			if (inplen < 2 || inplen >= sizeof(getpldat.pl_passwd)) {
X			    output(plogin,'C',0,
X			    "Password must be 2 to 8 characters\n\nPassword:");
X			    output(plogin,0,0,0);
X#ifdef DEBUG
X			    VDBG("cmd2 return\n");
X#endif
X			    return;
X			}
X
X			/* initialize new player login */
X			binit((char *)&getpldat,sizeof(getpldat));
X			strcpy(getpldat.pl_passwd,plogin->ln_input);
X			getpldat.pl_numlgn = 1;
X			time(&getpldat.pl_lstlgn);
X			getpldat.pl_frstml = 1;
X
X			/* insert new player */
X			dbmdata.dptr = (char *)&getpldat;
X			dbmdata.dsize = sizeof(getpldat);
X			if (store(dbmkey,dbmdata)) {
X				output(plogin,'C',0,
X				"(sigh) database collision - try another name\
X\n\nWhat is your name?");
X				output(plogin,0,0,0);
X				plogin->ln_name[0] = NULL;
X
X			/* give prompt */
X			} else {
X				output(plogin,'C',0,"\n\n");
X				output(plogin,'C',0,PROMPT);
X				output(plogin,0,0,0);
X			}
X			plogin->ln_stat = NULL;
X			plogin->ln_iomode = NULL;
X		}
X
X	/***********************/
X	/* response is command */
X	/***********************/
X	} else switch(plogin->ln_input[0]) {
X
X		case 'L': case 'l':	/* Logoff */
X			logoff(plogin);
X			break;
X
X		case 'B': case 'b':	/* reBuild */
X			plogin->ln_stat = 'B';
X			plogin->ln_crft[0] = NULL;
X			plogin->ln_substat = NULL;
X			plogin->ln_input[0] = NULL;
X			build(plogin);
X			break;
X
X		case 'I': case 'i':	/* Information */
X			output(plogin,'C',0,
X			"\nGet hold of and read the spacewar documentation\n");
X			output(plogin,'C',0,PROMPT);
X			output(plogin,0,0,0);
X			break;
X
X		case 'C': case 'c':	/* Complain -> Mail to Dan */
X			plogin->ln_stat = 'M';
X			plogin->ln_substat = NULL;
X			strcpy(plogin->ln_input,SWMASTER);
X			mail(plogin);
X			break;
X
X		case 'M': case 'm':	/* Mail */
X			plogin->ln_stat = 'M';
X			plogin->ln_substat = NULL;
X			plogin->ln_input[0] = NULL;
X			mail(plogin);
X			break;
X
X		case 'U': case 'u':	/* Usercmd */
X			plogin->ln_stat = 'U';
X			plogin->ln_substat = NULL;
X			plogin->ln_input[0] = NULL;
X			usrcmd(plogin);
X			break;
X
X		case 'S': case 's':	/* See */
X			plogin->ln_stat = 'S';
X			plogin->ln_substat = NULL;
X			plogin->ln_input[0] = NULL;
X			see(plogin);
X			break;
X
X		case 'W': case 'w':	/* Who */
X			plogin->ln_stat = 'W';
X			plogin->ln_substat = NULL;
X			plogin->ln_input[0] = NULL;
X			who(plogin);
X			break;
X
X		case 'P': case 'p':	/* Play */
X			plogin->ln_stat = 'P';
X			plogin->ln_crft[0] = NULL;
X			plogin->ln_substat = NULL;
X			plogin->ln_input[0] = NULL;
X			play(plogin);
X			break;
X
X		default:
X			prvcmd(plogin);
X			output(plogin,'C',0,PROMPT);
X			output(plogin,0,0,0);
X			break;
X	}
X
X#ifdef DEBUG
X	VDBG("cmd2 return\n");
X#endif
X}
X
X/* get input; return a ptr to where a full command is */
Xstatic struct login *getinp()
X{
X	struct uio inp;
X	int i;
X	register char *p;
X	register char *input;
X	extern int errno;
X#ifndef BSD
X#ifndef VMS
X#	include "uio2.h"
X	struct uio2 inp2;
X#endif /* VMS */
X#endif /* BSD */
X
X#ifdef DEBUG
X	DBG("getinp()\n");
X#endif /* DEBUG */
X
X	/* get player input allowing asynchronous  */
X	/* trap processing; do echo and edit magic */
X	/* do all this until there is a full cmd   */
X	for (;;) {
X
X		/* get the uio header allowing asynch trap processing */
X		if (doproctrap < 0 || doupdate < 0) {
X#ifdef DEBUG
X			VDBG("getinp return\n");
X#endif
X			return(NULL);
X		}
X		doproctrap = 1;
X#ifdef VMS
X		inp.uio_lgn = (struct login *)-1;
X		if ((i=sys$qiow(0,inmlbx,IO$_READVBLK,0,0,0,&inp,sizeof(inp),
X		0,0,0,0)) != SS$_NORMAL)  {
X#ifdef DEBUG
X		    VDBG("getinp qiow(READVBLK)=%d errno=%d\n",i,errno);
X#endif
X		    if (errno != EINTR)
X			perror("read mlbx uio");
X		    continue;
X		}
X		if (inp.uio_lgn == (struct login *)-1) continue;
X#else /* BSD SYSIII SYSV */
X		if (read(0,&inp,sizeof(inp)) != sizeof(inp)) {
X			if (errno != EINTR)
X				perror("read uio");
X			continue;
X		}
X#endif /* VMS BSD SYSIII SYSV */
X		doproctrap = 0;
X#ifdef DEBUG
X#ifndef BSD
X		if (((int)inp.uio_lgn) >= 0 &&((int)inp.uio_lgn) <= 20) {
X#ifdef VMS
X			VDBG("getinp: uio sig %d %s\n",(int)inp.uio_lgn,
X			inp.uio_chrs);
X#else /* SYSIII SYSV */
X			bcopy((char *)&inp2,(char *)&inp,sizeof(inp2));
X			VDBG("getinp: uio sig %d %d %s\n",inp2.uio2sig,
X			inp2.uio2pid,inp2.uio2tty);
X#endif /* VMS SYSIII SYSV */
X		} else
X#endif /* BSD */
X		{
X			VDBG("getinp: uio #%d '",inp.uio_lgn-loginlst);
X			for (p=inp.uio_chrs;*p;++p)
X			    VDBG((*p < ' ' || *p > '~') ? "\\%03o" : "%c",*p);
X			VDBG("'\n");
X		}
X#endif /* DEBUG */
X
X		/* validate login pointer */
X#ifndef BSD
X		if (((int)inp.uio_lgn) >= 0 &&((int)inp.uio_lgn) <= 20) {
X#ifdef VMS
X			proctrap(inp);
X#else /* SYSIII SYSV */
X			bcopy((char *)&inp2,(char *)&inp,sizeof(inp2));
X			proctrap(inp2);
X#endif /* VMS SYSIII SYSV */
X			continue;
X		}
X#endif /* BSD */
X		if (inp.uio_lgn < loginlst ||
X		inp.uio_lgn >= loginlst+MAXLOGIN) {
X			perror("uio_lgn out of range");
X			continue;
X		}
X
X		/* echo (based on iomode) and edit magic */
X		input = inp.uio_lgn->ln_input;
X		input += strlen(input);
X		for (p=inp.uio_chrs;*p;++p) {
X		    switch(*p) {
X			case '\n':
X			case '\r':
X			    *input = NULL;
X
X			    /* strip trailing blanks */
X			    for (p=inp.uio_lgn->ln_input;--input >= p &&
X			    *input == ' ';)
X				*input = NULL;
X
X			    if (inp.uio_lgn->ln_iomode == 'm' ||
X			    inp.uio_lgn->ln_iomode == 's')
X				output(inp.uio_lgn,'C',0,"\r");
X			    else
X				output(inp.uio_lgn,'C',0,"\n");
X			    output(inp.uio_lgn,0,0,0);
X#ifdef DEBUG
X			    VDBG("getinp return\n");
X#endif /* DEBUG */
X			    return(inp.uio_lgn);
X
X			case '\025':	/* control-U */
X			    if (inp.uio_lgn->ln_iomode == 's') {
X				output(inp.uio_lgn,'D',0,0);
X				input = inp.uio_lgn->ln_input;
X			    } else {
X				for (i=strlen(inp.uio_lgn->ln_input);i-- > 0;) {
X				    --input;
X				    output(inp.uio_lgn,'C',0,"\b \b");
X				}
X			    }
X			    break;
X
X			case '\b':
X			    if (input > inp.uio_lgn->ln_input) {
X				--input;
X				output(inp.uio_lgn,'C',0,"\b \b");
X			    }
X			    break;
X		    }
X
X		    /* ignore all non-printing chars */
X		    if (*p < ' ' || *p > '~') continue;
X
X		    /* make sure buffer can't overflow */
X		    if (input >= inp.uio_lgn->ln_input +
X		    sizeof(inp.uio_lgn->ln_input) - 1) {
X			*input = NULL;
X			if (inp.uio_lgn->ln_iomode == 'm' ||
X			inp.uio_lgn->ln_iomode == 's')
X			    output(inp.uio_lgn,'C',0,"\r");
X			else
X			    output(inp.uio_lgn,'C',0,"\n");
X			output(inp.uio_lgn,0,0,0);
X#ifdef DEBUG
X			VDBG("getinp return\n");
X#endif /* DEBUG */
X			return(inp.uio_lgn);
X		    }
X
X		    input[1] = NULL;
X		    *input = *p;
X		    output(inp.uio_lgn,'C',0,(inp.uio_lgn->ln_iomode == 'p') ?
X		    " " : input); /* space if password state, char otherwise */
X		    ++input;
X		}
X		*input = NULL;
X		output(inp.uio_lgn,0,0,0);
X	}
X}
END_OF_cmd.c
if test 11449 -ne `wc -c <cmd.c`; then
    echo shar: \"cmd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f doc.ms -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"doc.ms\"
else
echo shar: Extracting \"doc.ms\" \(26603 characters\)
sed "s/^X//" >doc.ms <<'END_OF_doc.ms'
X.RP
X.TL
XSPACEWAR
X.AU
XDan Rosenblatt
X.AI
XSystems
XSigma Design, Inc.
X.AB
XSPACEWAR is a multi-user, asynchronous, space battle game in a
X3-dimensional universe.
XYou play with/against other players while the computer controls
Xthe aliens (which are always against you).
XThe game does not wait for you to 'take your turn'.
XThe 3-dimensional universe is infinite, and it gets a bit
Xcomplicated (and frustrating) figuring out where you are, where you
Xwant to go, and how to get there.
XBesides all this, you even have to build (configure) your own ship,
Xand how well you do that will greatly affect how you fare in battle.
X.PP
XChanges to the game/documentation from the previous version (Jan 17'86)
Xare marked with '|' in the right margin.
X.AE
X.NH 1
XINTRODUCTION
X.PP
XThis game is based on a previous version written in F77 that ran on the
XMark III*
X.FS
X*Mark III is a trademark of GEISCO
X.FE
Xtimesharing system, which was unsuccessfully transported to DTSS at CSS
X(oh well), which was based on David Fotland's version on the UNIX*
X.FS
X*UNIX is a trademark of Bell Laboratories
X.FE
Xsystem, which is loosely based on Nat Howard's star trek game, which is
Xloosely based on a game written by Peter Langston at Harvard.
X(whew!)
X.PP
XIt is a multi-player game; up to 30*
X.FS
X*the actual number depends on the particular machine
X.FE
Xpeople can play simultaneously.
XAll players are in the same 3-dimensional universe at the same time
Xand can battle, aid, or ignore each other as they wish.
X.PP
XIt is an ongoing game, with the universe and your ship returning to
Xthe appropriate spots each time you re-enter the game.
X.PP
XInput is asynchronous.
XThe game doesn't stop and wait for you to give it a command.
XIf you do nothing, the game goes on around you and you may be
Xattacked, or fall into an object (crash), etc.
XWhenever you give a command, it is acted upon.
X.NH 1
XENTERING THE GAME
X.PP
XFor the moment, the game is available on wombat, and to play it
Xyou must have a login on that machine.
XThen run 'psw' (play spacewar).
XIf there is spacewar news, it will be displayed first.
XIf the game isn't running, you'll get a message to wait
Xa few moments while the universe is initialized.
X.PP
XYou will be asked for your name.
XIt can be up to eight (8) characters upper and lower case, including
Xblanks.
XYou will be asked for your password.
XIt also can be up to eight (8) characters upper and lower case,
Xincluding blanks.
XYour name and password as given to and used by SPACEWAR has nothing
Xto do with your UNIX login name and password.
XIf you are prompted with:
X.sp
X.ce 1
XPlay/See/Info/Complain/Mail/reBuild/Usercmd/Logoff/Who>
X.sp
Xthen you are ready to play SPACEWAR.
XRespond to this command prompt with at least 1 letter, upper or
Xlower case, and a carriage-return.
X.PP
XThere are four (4) special characters for editing/signalling.
XThe backspace (^H) key is the character erase.
XIt removes the character just to the left of the cursor and backs the
Xcursor up one (1) position.
XIf there are no more user-entered characters, nothing happens.
XThe cancel (^U) key is the line erase.
XIt erases the entire line of user-entered characters and backs the
Xcursor up to the beginning of the user-entry area.
XThe interrupt (usually ^C) key is the attention/restart
Xsignal.
XIt works anytime except when you are actually playing (in your ship
Xin the universe).
XIf you think the game daemon is broken, hung, ..., try this key; it can't
Xhurt.
XThe quit (usually ^^) key is the panic/escape signal.
XIt works anytime AND when you are actually playing, will get you
Xout of the universe (and your ship), sometimes destroying your ship.
X.NH 1
XLEAVING THE GAME
X.PP
XTo leave the game in an orderly fashion, type an 'l' (L) upper or
Xlower case to the command prompt.
XYou can also type the quit key (panic/escape signal).
XYou can also just break the phone/network connection which will have
Xthe same effect as typing the quit key.
X.PP
XTo leave the universe when you are actually playing 'in your ship',
Xyou must be docked with an object (planet, moon, asteroid,
Xstarbase) OR nothing bad must be near you (the BAD sensor must be 0).
XIf you force a logoff/disconnect by quitting or breaking the
Xphone/network connection without being docked at an object
XAND something bad is near you, YOUR SHIP WILL BE DESTROYED.
X.PP
XIf the game daemon dies, the most that can be lost is the last 59
Xgame cycles and no ships will be destroyed.
X.NH 1
XTHE COMMANDS
X.PP
XThe Play command is discussed later.
X.PP
XThe See command is for seeing players/ships standings.
XThe first section shows (not in any particular order) each player's name,
Xthe craft name, the craft points, time, and kills.
XThe second section shows (by player) two lines per player.
XThe first line has the player's name, total number of active ships,
Xthen average/maximum/ranking for points, time, and kills.
XThe ranking is based on maximums.
XThe second line has number of ships lost, points lost, time lost,
Xand kills lost.
X.PP
XComplain is just mail to the keeper of the SPACEWAR game.
X.PP
XMail is for handling and sending mail.
XWhen you first login to the game, you will be told if you have new
Xmail.
XYour mail is separated into 2 groups, old and new.
XWhen you say delete, only old mail is deleted.
XWhen you say new, new mail is shown to you and then becomes old
Xmail.
XWhen you say old, old mail is shown to you and retained.
X.PP
XThe Usercmd is for building user-defined commands to be used during
Xplaying.
XThe command name can be 1 to 8 characters upper and lower case with
Xno embedded blanks.
XAny basic playing command can appear in a user-defined command
Xexcept for phaser, torpedo, and another user-defined command (no recursion).
XArgument substitution is accomplished via $1, $2, ..., $9 appearing
Xin the user-defined command with actual values being substituted
Xfrom the original command arguments.
XSee the example at the end of 'hopefully helpful hints'.
X.NH 1
XTHE SHIPS
X.PP
XBefore you can play, you must build your ship.
XThere is no limit to the number of ships you can build.
XYou must choose a ship name (up to 12 characters upper and lower
Xcase including blanks) and from 3 hull types.
XType 1 is rocket shaped and has the expected capabilities, i.e. good
Xrockets.
XType 2 is spherical with lots of floor space and good shields.
XType 3 is like the starship Enterprise and is designed around huge
Xwarp engines, so thats what its best at along with good phasers.
XType 3 ships are good at smash and run-away battles, while type 2
Xships are best at sit and slug-it-out battles.
X.PP
XEach ship is comprised of up to ten subsystems;
XSolar energy, Antimatter energy, Warp drive, Rockets, Dilithium,
XPhasers, Shields, Torpedoes, Damage control, and Security.
XThere are other yet to be implemented weapons but to get them you
Xmust pillage another ship that has them (such as aliens).
X.PP
XEach subsystem, if you choose to have any of it, uses up a certain
Xbase amount of floor space and crew.
XThe more you ask for of the subsystem, the more floor
Xspace and crew you use up.
X.PP
XYour shields and phasers run off of energy which is generated by the
Xsolar and antimatter energy sources, and stored in your dilithium
Xcrystals.
XAntimatter energy is delivered at a fixed rate dependent on ship
Xtype and percent of subsystem.
XSolar energy is delivered at a rate dependent on ship type, percent
Xof subsystem, and how far away from the suns you are.
X.PP
XWarp drive takes you from here to there instantly, without any
Xchange in velocity.
XWarp drive runs off its own energy supply, completely separate from
Xyour shields, phasers, dilithium crystals, solar, and antimatter.
XWarps of the same distance will always cost the same amount of warp
Xenergy, but the recharge rate depends on ship type and percent of
Xsubsystem.
XIn addition, the warp drive is not perfectly accurate.
XThe more of it you have, however, the more accurate it is.
X.PP
XThe base floor space and crew for rockets covers the engines, and
Xthe additional floor space and crew covers fuel.
XThe maximum thrust of the rockets is determined by your hull type
X(most for type 1, least for type 3).
X.PP
XThe percentage of the torpedo subsystem determines the number of
Xhoming torpedoes you can carry.
XTheir maximum thrust is 50.
X.PP
XThe more damage control you have, the faster your ship will repair
Xitself when it gets damaged in battle.
XThere are two types of damage: temporary and permanent (lack of spare
Xparts).
XPermanent damage can only be fixed at a starbase.
X.PP
XSecurity is useful to protect yourself against being pillaged by an
Xenemy ship.
XCurrently, there is no pillage command.
X.NH 1
XDAMAGE
X.PP
XThere are two types of damage: temporary and permanent.
XTemporary damage can be fixed by your damage control personnel,
Xbut permanent damage can only be fixed at a starbase.
XYou can be damaged by enemy phasers or torpedoes.
XIf your hull is damaged enough, it causes more damage to your whole
Xship (radiation leakage, atmosphere loss, heat loss, ...).
XDamage to any subsystem over 45% becomes permanent and damage
Xcontrol can only repair it back down to 45%.
XIf you are docked and are damaged or need supplies, the reBuild
Xcommand will replenish supplies and fix damage, though permanent
Xdamage can only be fixed at a starbase.
X.PP
XIf your ship's solar or antimatter energy subsystems are damaged,
Xyou simply generate that much less energy to be stored in your
Xdilithium crystals.
XDamage to the dilithium crystals affects the amount of energy that
Xcan be stored.
XIf your warp drive is damaged, you still warp the same distance, but
Xthe accuracy is decreased (to 0 if there is enough damage).
XDamage to your rockets affects maximum acceleration.
XDamage to your phasers reduces the amout of damage they can inflict
X(they can't even be fired if there is too much damage).
XIf your shields are damaged, they will valiantly retain the same
Xstrength, but the amount of energy required to do so increases.
XIf your torpedo tubes are too damaged, you won't be able to fire any
Xtorpedoes; otherwise they work fine.
XIf damage control is damaged, it can't fix damage very well.
X.PP
XSome subsystems are easier to damage than others.
XYou will notice after a few battles that the same subsystems always
Xseem to be hurt the most.
XFor example, the solar energy collectors are on the outside of the
Xship, so they are very vulnerable.
X.NH 1
XTHE UNIVERSE
X.PP
XThe universe is infinite and unbounded.
XIt is populated by two stars, many planets, moons, and asteroids.
XThere are also a couple of starbases, aliens, maybe a black hole,
Xand of course other (enemy?) ships.
XGravity exists, and works as expected with a constant of 1 (f=m1m2/(r*r)).
XIt is considered bad form to collide with a solid object (you crash
Xand your ship is destroyed).
XThe first time you enter the game with a new ship, you will be near
Xan object and facing that object.
XIf you leave the game after docking with an object, the next time
Xyou return you will still be docked.
XIf the game daemon dies for some reason, you will return to within
X59 game cycles of where you were when it died.
X.PP
XThe distance between the two stars is about 200,000.
XThe planets are between 1000 and 50,000 from the suns.
XThe basic coordinate system is cartesian (rectangular, x/y/z), and
Xhelio-centric.
XThe x and y axes are in the plane of the ecliptic.
XThe z axis is perpendicular to them.
XThe order of output is always x,y,z.
XSome of the screen readouts are in spherical (polar) notation;
Xr (distance from center), theta (ccw from positive x axis), and phi
X(down from positive z axis).
X.NH 1
XTHE SCREEN
X.PP
XThe screen in front of you during the game contains a vast amount of
Xinformation.
XIn the top center is your viewscreen, your window into space, creating
Xa cone of vision.
XThis shows a picture of the space in front of you that depends on
Xyour direction and viewing angle which in turn determines your
Xmaximum viewing distance.
XThe center of the cross-hairs is straight ahead.
XObjects are represented symbolically on the screen.
XObjects that are further than you can view but still within 5000 are
Xshown as unidentified.
XObjects that you are docked with or that are docked with you are
Xshown in the center of your viewscreen in background intensity.
X.DS B 8
XItem		Symbolic display
X------------	----------------
XStars		*
XPlanets		O
XMoons		o
XAsteroids	o
XStarbases	#
XHuman ships	1 2 3
XAlien ships	4 5 6 7 8 9
XTorpedoes	+
XUnidentified	.
X.DE
X.PP
XAround the sides of the screen are status displays.
XDown the left side are the direction you are pointed (polar) and
Xpossibly AUTO or FFWD, position (rectangular), velocity
X(rectangular), angle of view and viewing distance, how many objects
Xyou can see within the given viewing distance, and how many bad
Xobjects (that can hurt you) are within 5000.
XBelow these are the homing channels, six of them, showing
Xdistance.
X.PP
XDown the right side of the screen are your subsystems, what level
Xthey are at and how much damage each has.
X.DS B 8
XSystem     Meaning of level
X--------   ------------------------------
XHull       Current acceleration
XSolar E.   Energy being produced
XAntm. E.   Energy being produced
XWarp       Warp energy stored
XRockets    Rocket fuel stored
XDilith.    Phaser+shield energy stored
XPhasers
XShields    Shield protection
XTorps.     Number of torpedoes stored
XDmg.Con.   Current subsystem being fixed
XSecurity
X.DE
X.PP
XAt the bottom right corner of the viewscreen is game time.
XThe bottom of your screen is divided into two halves.
XThe left half shows your last 7 commands (command history)
Xand the most recent command
X(indicated with a # just to the left of the command).
XThe right half is for various reports and asynchronous events, like
Xreporting attack damage and torpedo actions.
XJust above the command history area is a line for radio messages.
XLine 24, just below the command history area, is where your keyboard
Xbuffer is displayed.
X.NH 1
XPOINTS
X.PP
XA score of points, game time, and kills is kept by ship.
XLosses of points, game time, and kills is kept by player
X(which happens when a ship is destroyed).
XYou get points for inflicting damage (1/10 of the damage inflicted).
XIn a multi-player battle, the player credited with the destruction
Xof a ship is the player who fired the last shot at that ship
X(including torpedo hits).
XIf a ship self-destructs, the player who fired the last shot is
Xstill credited with the destruction.
XYou must be in the universe when a ship is destroyed to be credited
Xwith its destruction.
X.NH 1
XPLAYING
X.PP
XWhen you enter the Play command, you will be asked for your terminal
Xtype.
XSPACEWAR on UNIX uses termcap, so enter the termcap name for your
Xterminal.
XThere is the ability to change which background/foreground mode is
Xused and also to reverse the orientation
X(typically they are either reverse video or half intensity).
XThis is done by preceeding the terminal name with a period, comma,
Xor semicolon (.,;).
XPeriod reverses the orientation of the standard so/se (standout).
XComma uses us/ue (underscore).
XSemicolon reverses the orientation of us/ue.
X.PP
XMany of the play commands take some sort of argument, which comes
Xafter the command.
XCommands may be in upper or lower case, and you must type enough of
Xthe command so that it is uniquely identified (minimum length is
Xshown in parenthesis after the command).
XIf the command cannot be identified or the argument is bad
X(non-numeric, out of range, ...), the command is prepended with '???'
Xwhen it is copied to the command history area.
XIf the command cannot be carried out, a message of why is appended
Xto the command when it is copied.
X
X
X.SH
XERASE (1)
X.IP
XErases and redraws the screen.
X.SH
XANGLE (2)
X.IP
XChanges your viewscreen viewing angle.
XValid argument range is 0.0<n<=180.0.
XYour viewing distance is related to viewing angle
Xby an inverse square rule (1/a*a).
XInitially set to 45.0 with a viewing distance of 5000.
X.SH
XRIGHT (2)
X.IP
XChanges your viewing direction to the right (objects on the
Xscreen move to the left).
XValid argument range is 0.0<n<=360.0.
XIf no argument is given, the change in direction is 1/2 your current
Xviewing angle.
XIf you are autopiloted or facing forward, it is turned off.
X.SH
XLEFT (3)
X.IP
XSee RIGHT.
X.SH
XUP (2)
X.IP
XSee RIGHT.
X.SH
XDOWN (3)
X.IP
XSee RIGHT.
X.SH
XHOME (1)
X.IP
XLocks the homing channel given as the argument onto what you are
Xautopiloted on (you must be autopiloted on something).
XValid argument range is 1<=n<=6.
XHoming will not lose an object just because you or it warps
X(autopilot will).
XThe homing channel will lose what it is locked onto if you tell it to
Xlock onto something else, or if what it is locked onto leaves the
Xuniverse, or if you leave the universe and it is not an object.
X.SH
XUNHOME (2)
X.IP
XAnother way to make a homing channel lose what it is locked onto.
XValid argument range is 1<=n<=6.
X.SH
XFACEFOWARD (2)
X.IP
XThis command will point you and keep you pointed in the direction
Xthat you are moving (velocity).
XYou will get a complaint if you are not moving.
XIf you are autopiloted, the autopilot is turned off.
X.SH
XAUTOPILOT (2)
X.IP
XThis crucial battle command locks you onto the thing that is
Xclosest to center of your viewscreen and closest to you so that the
Xthing is always in the center of your viewscreen.
XYou cannot fire any weapons at something unless you are autopiloted
Xon it.
XIt will lock onto the closest to center/closest to you thing that is
Xwithin 5 degrees of center or half your viewing angle, whichever is
Xsmaller.
XIf given an argument in the range 1<=n<=6, it will lock onto the
Xthing that is on the given homing channel.
XIf the thing that you lock onto is docked, you will be locked onto
Xthe thing it is docked with (except your own ship).
XIf the thing that you are autopiloted on docks, the autopilot will
Xshift if the thing docks with another ship, and it will be lost if
Xthe thing docks with you or an object.
XIf you are facing forward, faceforward is turned off.
X.SH
XSHIELDS (2)
X.IP
XTakes an argument in the range 0<=n<=100 and sets your shield
Xprotection to that percent.
XIf you use up all your stored dilithium energy, the shield
Xprotection drops to where it uses up all the energy your solar and
Xantimatter energy sources produce.
X.SH
XTHRUST (2)
X.IP
XThrust with the rockets.
XFuel is expended as you accelerate or decelerate.
XIf you specify a thrust greater than your maximum acceleration,
Xthrust is applied over several iterations.
XThis command takes up to 4 arguments.
XThe first is how much thrust to apply in the forward direction (the
Xdirection you are pointing).
XIt can be negative to slow you down (assuming you are facing
Xforward).
XThe other three arguments are thrust in the x, y, and z directions
Xand can also be negative.
XIf you are docked, you will no longer be docked.
XMultiple arguments must be space separated.
X.SH
XSTOPTHRUST (2)
X.IP
XCancels any pending thrust.
X.SH
XWARP (2)
X.IP
XThe other way to get around the universe.
XMoves you forward (direction you are pointing) instantaneously.
XGive it an argument of the distance you wish to move in thousands
Xof units (can be negative to move you backwards).
XIf you are docked or autopiloted, you no longer will be.
XOthers that are docked or autopiloted with/on you have theirs turned
Xoff also.
XAny warp takes at least 500 units of warp energy.
X.SH
XLEAVE (3)
X.IP
XEjects you from the universe in an orderly fashion, but only if you
Xare docked with an object (planet, moon, asteroid, starbase) or if
Xnothing bad is near you.
XOtherwise you remain in the universe.
XAny torpedoes that you have fired keep going but no credit is
Xgiven to you when they inflict damage or kill.
X.SH
XDOCK (3)
X.IP
XDocks you with the nearest thing (except stars or black holes).
XYou must be within 5*(thing radius + 1) to dock; be forwarned that
Xcrashing distance is 2*(thing radius + 1).
XYou must also be moving slow enough to be within docking distance
Xfor at least 2 game cycles.
XYou cannot be directly attacked once you dock, though if you dock
Xwith another ship that is attacked you will sustain damage by being
Xclose to it.
XAny autopilots, docks, or torpedoes on you are transfered to the
Xthing you dock with or are lost depending on the type of thing you
Xdock with.
XThe thing you dock with will be shown in the center of your
Xviewscreen in background mode.
X.SH
XRADIO (2)
X.IP
XSends a radio message (starting with the first non-blank character
Xafter the command) in the direction you are pointing in a cone that
Xis within 5 degrees of center or half your viewing angle, whichever
Xis smaller.
X.SH
XWHO (2)
X.IP
XTells (in the report area) who is currently playing and their ship
Xname.
XSince more players can be playing than can be reported on,
Xwho takes an optional argument of how many output screens to
Xskip before putting out to the report area.
X.SH
XREPORT (3)
X.IP
XReports (in the report area) on all the objects that you can see on
Xyour viewscreen.
XEach line includes the x,y viewscreen coordinates of the thing, the
Xsymbolic picture, and the distance to the thing.
XFor objects, the radius and mass are shown.
XFor ships, the player's and ship's name, hull damage, and shield protection.
XFor torpedoes, the hull damage.
XFor aliens, hull damage and shield protection.
XAfter all this follows optional information in parenthesis telling
Xyou if you are autopiloted (A), docked (D), or homed (1/2/3/4/5/6)
Xon the thing described.
XSince more things can be on your viewscreen than can be reported on,
Xreport takes an optional argument of how many output screens to
Xskip before putting out to the report area.
X.SH
XPHASERS (1)
X.IP
XYou must be autopiloted and not docked.
XGive it an argument of how much energy to apply, 1<=n<=1000.
XThe amount of damage inflicted depends on how much phasers you have,
Xhow much energy you apply, how far away the target is, and how much
Xshielding the target has.
X.SH
XTORPEDO (2)
X.IP
XLaunches a torpedo at what you are autopiloted on.
XYou will be informed in the report area when the torpedo blows up,
Xcrashes, is destroyed, or misses.
X.SH
XFIX (2)
X.IP
XThis command directs your damage control to fix the subsystem given
Xas argument, 0<=n<=11.
XIf no argument (or 0) is given, it goes back to fixing all
Xsubsystems.
XOnce a particular subsystem is fixed (remember that permanent
Xdamage, >45%, cannot be fixed), it goes back to fixing all
Xsubsystems.
XDue to the law of diminishing returns, damage control is not as
Xefficient when fixing one particular subsystem.
X.SH
XSENSORS (2)
X.IP
XReports (in the report area) on all the objects that are within 5000 units
Xof your ship.
XEach line includes the x,y viewscreen coordinates of the thing
Xif it is visible on your viewscreen, the
Xsymbolic picture, the distance to the thing,
Xand the direction vector to the thing.
XAfter this follows optional information in parenthesis telling
Xyou if you are autopiloted (A), docked (D), or homed (1/2/3/4/5/6)
Xon the thing described.
XSince more things can be within 5000 units than can be reported on,
Xsensors takes an optional argument of how many output screens to
Xskip before putting out to the report area.
X.SH
XLOCKON (2)
X.IP
XPoints you in the direction of where the last attack came from and
Xtries to 'autopilot' on anything in that direction/location.
XSince aliens and other players can move after they attack you,
Xthe 'autopilot' may not be effective.
X.SH
XREDRAW (3)
X.IP
XRedraws the screen just like 'erase' but without first
Xblanking out the screen.
X.SH
X-cmd
X.IP
XExecute a user-defined command with argument substitution.
XArguments must be space separated.
X.NH 1
XHOPEFULLY HELPFUL HINTS
X
XThe reBuild command:
X.PP
XWhen reBuilding your ship, you can give a null response (just
Xcarriage-return) to the percent of subsystem prompt and it will
Xleave you with whatever percent you already have.
XYou must cycle through all your subsystems to replenish supplies and
Xfix damage.
X
XPlaying your ship in the universe:
X.PP
XDon't forget that if you force a logoff when you aren't docked with
Xan object and something bad is near you, your ship will be destroyed.
XThis is to deter players from avoiding battle by escaping from the
Xuniverse in an unfair way.
X.PP
XThe direction indicators in the upper left of your screen show the
Xdirection your ship is pointed (determining what you can see on your
Xviewscreen), which is not necessarily the direction you are moving.
XThe direction your ship is pointed is affected by the commands LEFT,
XRIGHT, UP, DOWN, FACEFORWARD, and AUTOPILOT.
XThe last two commands continuously adjust the direction your ship is
Xpointed until something turns the command off.
XThese two states are indicated with 'AUTO' or 'FFWD' just after your
Xdirection indicators.
X.PP
XThe direction and reports of radio and attack direction are all in
Xpolar coordinates.
XPosition and velocity are in rectangular and don't relate very well
X(for humans) to those in polar coordinates.
XTo see a radio broadcaster or an attacker, adjust your direction to
Xbe the same as what was shown in the report area.
X.PP
XIf you can't see an object you're pointed at, its probably because
Xits further than your viewing distance.
XIncrease your viewing distance by decreasing your viewing angle, but
Xdon't leave it that way for too long because someone could more
Xeasily sneak up on you.
XDon't forget to watch the 'BAD' indicator and to use the SENSORS cmd
Xto see how many potentially dangerous things are within 5000 units of you.
X.PP
XSince enough hull damage (>59%) will cause more damage to your ship,
Xdon't let it go too long when you're in battle (use the FIX
Xcommand).
X.PP
XIf your velocity starts changing for some unexplained reason, you
Xprobably are being pulled toward an object by its gravity.
XI other words, you are in danger of crashing, though not for a
Xlittle while.
XSometimes you won't crash, but will be flung off into space at a
Xhigh velocity.
XLotsa luck finding your way back.
X.PP
XIts strongly suggested, since docking is one of the most difficult
Xthings to do and the only way to fix a damaged ship (at a starbase), to
Xcreate a user-defined command something like this:
X.DS B 8
XPlay/See/.../Who>U
X
Xcommand/L(ist)/.(quit)>fixvel
X
XThe currently defined command (if any) will be displayed.
XA single dot (.) at the first prompt will retain it.
X
X>fac
X>thr -$2
X>aut $1
X>thr $2
X>fac
X>.
X.DE
XWhen playing, assuming the object you're trying to dock with is on
Xhoming channel 4 and you're thrusting toward it at say 25, the playing
Xcommand:
X.sp
X.ce 1
X-fixvel 4 25
X.sp
Xwould correct your thrust to keep you heading toward the object.
XDon't forget that all objects orbit in a circular path.
XThe best chance for docking is if you follow the object and 'creep'
Xup on it from behind.
XThe 'faceforward' command will show you how often you need to
Xcorrect your course by displaying the object you're following creep away
Xfrom the center of your viewscreen.
END_OF_doc.ms
if test 26603 -ne `wc -c <doc.ms`; then
    echo shar: \"doc.ms\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mail.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mail.c\"
else
echo shar: Extracting \"mail.c\" \(11978 characters\)
sed "s/^X//" >mail.c <<'END_OF_mail.c'
X/*
X * Spacewar - mail subsystem
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 <time.h>
X#include "spacewar.h"
X#include "universe.h"
X#include "login.h"
X#include "mlbx.h"
X#include "plyr.h"
X
X#define MAILPROMPT	"player/O(ld)/N(ew)/D(elete)/.(quit)>"
X
Xstruct mstat {
X	char	ms_stat;	/* D(isplay) or S(end) */
X	short	ms_bgn;		/* display begin */
X	short	ms_cur;		/* display current */
X	short	ms_end;		/* display end */
X	char	ms_towho[8+1];	/* send to player */
X	struct mlst *ms_frst;	/* send first line */
X	struct mlst *ms_lst;	/* send last line */
X};
Xstruct mlst {
X	struct mlst *ml_nxt;	/* next mail */
X	char	*ml_lin;	/* line of mail */
X};
X
Xstatic VOID sndmail(),dspmail();
Xextern char *malloc();
X
Xmail(plogin)
Xregister struct login *plogin;
X{
X	register struct mstat *pmstat;
X	struct mlbxkey getmbkey;
X	struct plyrkey getplkey;
X	struct plyr getpldat;
X	datum dbmkey,dbmdata;
X	int i;
X	char buf[80+1],c;
X
X#ifdef DEBUG
X	DBG("mail(#%d/%s)\n",plogin-loginlst,plogin->ln_name);
X#endif
X
X	/********************************/
X	/* call subtask based on status */
X	/********************************/
X	if (pmstat = (struct mstat *)plogin->ln_substat)
X	    switch(pmstat->ms_stat) {
X		case 'D':
X		    dspmail(plogin,pmstat);
X		    break;
X		case 'S':
X		    sndmail(plogin,pmstat);
X		    break;
X		default:
X		    perror("mail: unknown ms_stat");
X		    plogin->ln_stat = NULL;
X		    plogin->ln_substat = NULL;
X		    output(plogin,'C',0,PROMPT);
X		    output(plogin,0,0,0);
X		    break;
X	    }
X
X	/*******************************************/
X	/* no status. figure based on input buffer */
X	/*******************************************/
X
X	/* nothing - send counts & subtask prompt */
X	else if (!plogin->ln_input[0]) {
X		/* get player */
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) {	/* not found? */
X		    perror("mail: can't find plyr");
X		    plogin->ln_stat = NULL;
X		    plogin->ln_substat = NULL;
X		    output(plogin,'C',0,PROMPT);
X#ifdef DEBUG
X		    VDBG("mail return\n");
X#endif
X		    return;
X		}
X		bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
X
X		sprintf(buf,
X		"\nYou have %d line(s) of old mail, %d line(s) of new mail.\n",
X		getpldat.pl_seenml - getpldat.pl_frstml + 1,
X		getpldat.pl_lstml - getpldat.pl_seenml);
X		output(plogin,'C',0,buf);
X		output(plogin,'C',0,MAILPROMPT);
X		output(plogin,0,0,0);
X
X	/* one character - command */
X	} else if (!plogin->ln_input[1]) {
X
X	    /* get player */
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) {	/* not found? */
X		perror("mail: can't find plyr");
X		plogin->ln_stat = NULL;
X		plogin->ln_substat = NULL;
X		output(plogin,'C',0,PROMPT);
X#ifdef DEBUG
X		VDBG("mail return\n");
X#endif
X		return;
X	    }
X	    bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
X
X	    switch(c=plogin->ln_input[0]) {
X
X		case 'D':	/* delete all seen mail */
X		case 'd':
X		    binit((char *)&getmbkey,sizeof(getmbkey));
X		    getmbkey.mb_mlbxkey = MLBX;
X		    strcpy(getmbkey.mb_plyr,plogin->ln_name);
X		    dbmkey.dptr = (char *)&getmbkey;
X		    dbmkey.dsize = sizeof(getmbkey);
X		    i = 0;
X		    while (getpldat.pl_frstml <= getpldat.pl_seenml) {
X			getmbkey.mb_mlbx = getpldat.pl_frstml++;
X			if (delete(dbmkey))
X			    perror("mail: can't delete mlbx");
X			else
X			    ++i;
X		    }
X		    sprintf(buf,"\nDeleted %d line(s) of mail\n",i);
X		    output(plogin,'C',0,buf);
X
X		    /* update plyr */
X		    dbmkey.dptr = (char *)&getplkey;
X		    dbmkey.dsize = sizeof(getplkey);
X		    dbmdata.dptr = (char *)&getpldat;
X		    dbmdata.dsize = sizeof(getpldat);
X		    if (store(dbmkey,dbmdata))
X			perror("mail: can't update plyr");
X
X		    /* back to command prompt */
X		case '.':	/* quit mail */
X		    plogin->ln_stat = NULL;
X		    output(plogin,'C',0,PROMPT);
X		    output(plogin,0,0,0);
X		    break;
X
X		case 'O':	/* display old mail */
X		case 'o':
X		case 'N':	/* display new mail */
X		case 'n':
X		    /* allocate subtask status structure */
X		    if (!(pmstat = (struct mstat *)
X		    malloc(sizeof(struct mstat)))) {
X			perror("mail: out of memory for mstat");
X			plogin->ln_stat = NULL;
X			output(plogin,'C',0,PROMPT);
X			output(plogin,0,0,0);
X			break;
X		    }
X
X		    /* initialize subtask status structure */
X		    pmstat->ms_stat = 'D';
X		    if (c == 'O' || c == 'o') {
X			pmstat->ms_bgn = getpldat.pl_frstml;
X			pmstat->ms_end = getpldat.pl_seenml;
X		    } else {
X			pmstat->ms_bgn = getpldat.pl_seenml + 1;
X			pmstat->ms_end = getpldat.pl_lstml;
X		    }
X		    pmstat->ms_cur = pmstat->ms_bgn - 1;
X
X		    /* save subtask status structure and start subtask */
X		    plogin->ln_substat = (char *) pmstat;
X		    dspmail(plogin,pmstat);
X		    break;
X
X		default:
X		    output(plogin,'C',0,MAILPROMPT);
X		    output(plogin,0,0,0);
X		    break;
X	    }
X
X	/* send to player */
X	} else {
X		/* allocate/initialize subtask status structure */
X		if (!(pmstat = (struct mstat *) malloc(sizeof(struct mstat)))) {
X			perror("mail: out of memory for mstat");
X			plogin->ln_stat = NULL;
X			output(plogin,'C',0,PROMPT);
X			output(plogin,0,0,0);
X		} else {
X			pmstat->ms_stat = 'S';
X			plogin->ln_input[sizeof(pmstat->ms_towho)-1] = NULL;
X			strcpy(pmstat->ms_towho,plogin->ln_input);
X			pmstat->ms_frst = pmstat->ms_lst = NULL;
X			plogin->ln_substat = (char *) pmstat;
X			sndmail(plogin,pmstat);
X		}
X	}
X
X#ifdef DEBUG
X	VDBG("mail return\n");
X#endif
X}
X
Xstatic VOID dspmail(plogin,pmstat)
Xregister struct login *plogin;
Xregister struct mstat *pmstat;
X{
X	struct mlbxkey getmbkey;
X	struct plyrkey getplkey;
X	struct plyr getpldat;
X	datum dbmkey,dbmdata;
X	char buf[80+1];
X	int nlines=6;
X
X#ifdef DEBUG
X	DBG("dspmail(#%d/%s,{%d,%d,%d})\n",plogin-loginlst,plogin->ln_name,
X	pmstat->ms_bgn,pmstat->ms_cur,pmstat->ms_end);
X#endif
X
X	/* first time */
X	if (pmstat->ms_cur < pmstat->ms_bgn) {
X
X		sprintf(buf,"\nThere are %d line(s) of mail\n",
X		pmstat->ms_end - pmstat->ms_bgn + 1);
X		output(plogin,'C',0,buf);
X
X		if (pmstat->ms_end >= pmstat->ms_bgn) {
X		    sprintf(buf,"Output is in groups of %d lines. ",nlines);
X		    output(plogin,'C',0,buf);
X		    output(plogin,'C',0,"Hit return when ready for more.\n");
X		    output(plogin,'C',0,
X		    "A single dot (.) on a line by itself terminates Mail.\n\n");
X		    plogin->ln_iomode = 'm';
X		}
X	}
X
X	/* display a group of lines */
X	binit((char *)&getmbkey,sizeof(getmbkey));
X	getmbkey.mb_mlbxkey = MLBX;
X	strcpy(getmbkey.mb_plyr,plogin->ln_name);
X	dbmkey.dptr = (char *)&getmbkey;
X	dbmkey.dsize = sizeof(getmbkey);
X	while (nlines-- > 0) {
X
X		/* terminate or no more - update plyr */
X		/* and go back to command level */
X		if (!strcmp(plogin->ln_input,".") ||
X		++pmstat->ms_cur > pmstat->ms_end) {
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)	/* not found? */
X				perror("dspmail: can't find plyr");
X			else {
X				bcopy((char *)&getpldat,dbmdata.dptr,
X				sizeof(getpldat));
X				getpldat.pl_seenml =
X				    (pmstat->ms_cur < pmstat->ms_end) ?
X				    pmstat->ms_cur : pmstat->ms_end;
X				dbmdata.dptr = (char *)&getpldat;
X				dbmdata.dsize = sizeof(getpldat);
X				if (store(dbmkey,dbmdata))
X					perror("dspmail: can't update plyr");
X			}
X
X			free((char *)pmstat);
X			plogin->ln_iomode = NULL;
X			plogin->ln_stat = NULL;
X			plogin->ln_substat = NULL;
X			output(plogin,'C',0,PROMPT);
X			break;
X
X		/* get and put out the line of mail */
X		} else {
X			getmbkey.mb_mlbx = pmstat->ms_cur;
X			dbmdata = fetch(dbmkey);
X			if (!dbmdata.dptr)	/* not found? */
X				perror("dspmail: can't find mlbx");
X			else {
X				output(plogin,'C',0,dbmdata.dptr);
X				output(plogin,'C',0,"\n");
X			}
X		}
X	}
X
X	output(plogin,0,0,0);
X#ifdef DEBUG
X	VDBG("dspmail return\n");
X#endif
X}
X
Xstatic VOID sndmail(plogin,pmstat)
Xregister struct login *plogin;
Xregister struct mstat *pmstat;
X{
X	time_t clock;
X	struct mlst *pmlst,*nxtmlst;
X	struct plyrkey getplkey;
X	struct plyr getpldat;
X	struct mlbxkey getmbkey;
X	datum dbmkey,dbmdata;
X	int mlost=0,nlines;
X	struct tm *localtime();
X	char *asctime(),*ctime(),buf[80+1];
X
X#ifdef DEBUG
X	DBG("sndmail(#%d/%s,%s)\n",plogin-loginlst,plogin->ln_name,
X	pmstat->ms_towho);
X#endif
X
X	/* first time or terminate */
X	if (!pmstat->ms_frst || !strcmp(plogin->ln_input,".")) {
X
X	    /* verify existence of recipient */
X	    binit((char *)&getplkey,sizeof(getplkey));
X	    getplkey.pl_plyrkey = PLYR;
X	    strcpy(getplkey.pl_name,pmstat->ms_towho);
X	    dbmkey.dptr = (char *)&getplkey;
X	    dbmkey.dsize = sizeof(getplkey);
X	    dbmdata = fetch(dbmkey);
X	    if (!dbmdata.dptr) {	/* doesn't exist */
X		output(plogin,'C',0,pmstat->ms_towho);
X		output(plogin,'C',0," - no such player\n");
X		goto terminate;	/* horrendous */
X
X	    } else if (!pmstat->ms_frst) {	/* first time */
X		time(&clock);
X		sprintf(plogin->ln_input,"From '%s' on %.24s",plogin->ln_name,
X#ifdef VMS
X		ctime(&clock));
X#else /* BSD SYSIII SYSV */
X		asctime(localtime(&clock)));
X#endif /* VMS BSD SYSIII SYSV */
X		output(plogin,'C',0,
X		"Terminate your mail with a single dot (.) on a line by itself.\n\n");
X		output(plogin,0,0,0);
X
X	    } else {	/* terminate */
X
X		/* insert mlbx lines */
X		bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
X		binit((char *)&getmbkey,sizeof(getmbkey));
X		getmbkey.mb_mlbxkey = MLBX;
X		strcpy(getmbkey.mb_plyr,pmstat->ms_towho);
X		dbmkey.dptr = (char *)&getmbkey;
X		dbmkey.dsize = sizeof(getmbkey);
X		for (nlines=(-1),nxtmlst=pmlst=pmstat->ms_frst;pmlst;
X		++nlines,pmlst=nxtmlst) {
X		    nxtmlst = nxtmlst->ml_nxt;
X		    getmbkey.mb_mlbx = ++getpldat.pl_lstml;
X		    dbmdata.dsize = strlen(dbmdata.dptr=pmlst->ml_lin) + 1;
X		    if (!mlost && store(dbmkey,dbmdata)) {
X			++mlost;
X			output(plogin,'C',0,
X			"(sigh) database collision, your mail was lost\n");
X		    }
X		    free(pmlst->ml_lin);
X		    free((char *)pmlst);
X		}
X
X		/* insert trailer, update recipient */
X		if (!mlost) {
X		    getmbkey.mb_mlbx = ++getpldat.pl_lstml;
X		    dbmdata.dsize = strlen(dbmdata.dptr=".") + 1;
X		    if (store(dbmkey,dbmdata)) --getpldat.pl_lstml;
X
X		    dbmkey.dptr = (char *)&getplkey;
X		    dbmkey.dsize = sizeof(getplkey);
X		    dbmdata.dptr = (char *)&getpldat;
X		    dbmdata.dsize = sizeof(getpldat);
X		    if (store(dbmkey,dbmdata)) {
X			perror("sndmail: can't update plyr");
X			output(plogin,'C',0,
X			"(sigh) database error, your mail was lost\n");
X		    } else {
X			sprintf(buf,"Sent %d+2 line(s) of mail\n",nlines);
X			output(plogin,'C',0,buf);
X		    }
X		}
X
X		/* back to command prompt */
Xterminate:
X		free((char *)pmstat);
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("sndmail return\n");
X#endif
X		return;
X	    }
X	}
X
X	/*************************/
X	/* save the line of mail */
X	/*************************/
X
X	/* terminate early if no memory */
X	if (!(pmlst = (struct mlst *) malloc((unsigned)sizeof(struct mlst))))
X		perror("sndmail: out of memory for mlst");
X	if (!pmlst || !(pmlst->ml_lin = malloc(strlen(plogin->ln_input)+1))) {
X		if (pmlst) perror("sndmail: out of memory for ml_lin");
X		strcpy(plogin->ln_input,".");
X		sndmail(plogin,pmstat);
X
X	/* save text and link in to list */
X	} else {
X		pmlst->ml_nxt = NULL;
X		strcpy(pmlst->ml_lin,plogin->ln_input);
X		if (pmstat->ms_frst)
X			pmstat->ms_lst->ml_nxt = pmlst;
X		else
X			pmstat->ms_frst = pmlst;
X		pmstat->ms_lst = pmlst;
X		output(plogin,'C',0,">");
X		output(plogin,0,0,0);
X	}
X
X#ifdef DEBUG
X	VDBG("sndmail return\n");
X#endif
X}
END_OF_mail.c
if test 11978 -ne `wc -c <mail.c`; then
    echo shar: \"mail.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f update.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"update.c\"
else
echo shar: Extracting \"update.c\" \(1826 characters\)
sed "s/^X//" >update.c <<'END_OF_update.c'
X/*
X * Spacewar - update the universe
X *
X * Copyright 1985 obo Systems, Inc.
X * Copyright 1985 Dan Rosenblatt
X */
X
X#include "spacewar.h"
X#ifndef VMS
X#include <sys/types.h>
X#else /* BSD SYSIII SYSV */
X#include <types.h>
X#endif
X#include "universe.h"
X#include "login.h"
X#include "sys.h"
X#include "aln.h"
X#include "build.h"
X#include "flds.h"
X#include "torp.h"
X#include "crft.h"
X
Xlong gametime;
X
XVOID update()
X{
X	struct universe *puniv;
X	register struct login *plogin;
X	struct crft *pcrft;
X	char *s,*lckmsg();
X	extern int numpling;
X
X#ifdef DEBUG
X	DBG("update()\n");
X#endif
X
X	/* periodic sync and lockout check */
X	if (++gametime%60L == 0) {
X	    objupdate();
X	    crftupdate((struct login *)0);
X	    if (s=lckmsg()) {
X		numpling = 0;
X		for (plogin=loginlst+MAXLOGIN;plogin-- > loginlst;) {
X		    if (plogin->ln_tty && plogin->ln_play.ip_ptr) {
X			remove(plogin->ln_play);
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			output(plogin,'E',0,0);
X			output(plogin,'B',0,0);
X			output(plogin,'C',0,"\n\n");
X			output(plogin,'C',0,s);
X			output(plogin,'C',0,"\n");
X			output(plogin,'C',0,PROMPT);
X			output(plogin,0,0,0);
X		    }
X		}
X	    }
X	}
X
X	/* movement of objects */
X	updobjs();
X	updmov();
X
X	/* movement of intelligent nasties */
X	updtorp();
X	updaln();
X
X	/* damage/destruction from hull damage, damage control */
X	upddmg();
X
X	/* energy subsystems */
X	updsys();
X
X	/* direction, sensors, homing */
X	upddsh();
X
X	/* player's screens */
X	for (plogin=loginlst;plogin < loginlst+MAXLOGIN;++plogin) {
X	    if (!plogin->ln_tty || !(puniv=plogin->ln_play.ip_ptr)) continue;
X	    nums(pcrft=puniv->uv_ptr.uv_crft);
X	    view(pcrft);
X	    output(plogin,0,0,0);
X	    pcrft->cr_time += 1;
X	}
X
X#ifdef DEBUG
X	VDBG("update return\n");
X#endif
X}
END_OF_update.c
if test 1826 -ne `wc -c <update.c`; then
    echo shar: \"update.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 6\).
cp /dev/null ark2isdone
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