Path: utzoo!attcan!uunet!husc6!bloom-beacon!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games
From: games@tekred.TEK.COM
Newsgroups: comp.sources.games
Subject: v04i021: spacewar - multiplayer asynchronous space battle game, Part01/06
Message-ID: <2583@tekred.TEK.COM>
Date: 31 May 88 17:13:16 GMT
Sender: billr@tekred.TEK.COM
Lines: 2049
Approved: billr@saab.CNA.TEK.COM
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 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 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 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
X#include
X#else /* BSD SYSIII SYSV */
X#include
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 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
X#include
X#else /* BSD SYSIII SYSV */
X#include
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 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;jcr_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;jcr_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 /* 0ln_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 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
X#include
X#else /* BSD SYSIII SYSV */
X#include
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