[alt.sources] COSMOS Game

karl@ddsw1.MCS.COM (Karl Denninger) (11/18/88)

This is the first of three archives containing COSMOS, a multiuser space
game for Xenix machines.

Note that this code is SPECIFIC to Xenix V/386.  It MIGHT run on System V
80386 machines, the further you get away from this the less likely you are
to have success.  In particular, you absolutely must have:

o SVID-compliant shared memory and semaphores.
o A large segment size (500K or so), or a completely flat address space.
o Paging would be nice :-)
o A working curses.

o A 'nap' call is highly recommended (short sleep).

FORGET EVEN TRYING to run this on a '286 -- it won't work.  On Microport, 
it won't even compile without severely crippling the size of the grid.


NOTE:  This is shareware, but not crippleware.  If you don't want it, 
       then don't keep it.  Flames to /dev/null.


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  Makefile Manifest README buildbase.c dispstatus.c
#   getship.c givedamage.c makechoice.c mines.c modgame.c phasers.c
#   players.c rmseg.c scan.c
# Wrapped by karl@ddsw1 on Thu Nov 17 23:53:03 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1538 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# Makefile for Space - a multiuser game
X#
X# Copyright 1988 Macro Computer Solutions, Inc and Karl Denninger.
X#
X# All rights reserved.
X#
X# Unauthorized duplication, distribution, or modification is
X# prohibited by Federal and State law and will be prosecuted under
X# civil and criminal law.
X
CC=cc
X#
X# First CFLAGS line is for terminfo, others for termcap 
X#
CFLAGS= -s -DM_TERMINFO -Ox -DVERSION=\"0.9.9B\" -DSYSID=\"386\" -DSYSV 
X#CFLAGS= -s -DM_TERMCAP -Ox -Dcbreak=crmode -DVERSION=\"0.9.9B\" -DSYSID=\"386\" -DSYSV 
LDFLAGS= -s -o
X#
X# Now we have two library call lines, first for terminfo, then termcap
X#
LIBS= -lcurses -lx -lm
X#LIBS= -ltcap -ltermcap -lx -lm
X#
X# Then the rest of the stuff
X#
INC_DEP=/usr/include/stdio.h\
X	/usr/include/sys/types.h\
X	/usr/include/fcntl.h\
X	/usr/include/signal.h\
X	/usr/include/setjmp.h\
X	/usr/include/pwd.h\
X	/usr/include/termio.h\
X	/usr/include/sys/file.h\
X	/usr/include/memory.h\
X	cosmos.h
XFILES=	cosmos.o\
X	funcs.o\
X	dispstatus.o\
X	getship.o\
X	buildbase.o\
X	phasers.o\
X	givedamage.o\
X	mines.o\
X	scan.o\
X	modgame.o\
X	torpedoes.o\
X	players.o
X
all: cosmos rmseg drone
X
cosmos: $(INC_DEP) $(FILES)
X	$(CC) $(LDFLAGS) cosmos $(FILES) $(LIBS)
X
rmseg: $(INC_DEP) rmseg.o
X	$(CC) $(LDFLAGS) rmseg rmseg.o
X
drone: $(INC_DEP) drone.o funcs.o givedamage.o getship.o dispstatus.o \
X	buildbase.o phasers.o makechoice.o torpedoes.o
X	$(CC) $(LDFLAGS) drone drone.o funcs.o givedamage.o getship.o \
X	dispstatus.o buildbase.o phasers.o makechoice.o torpedoes.o -lcurses -lx -lm
X
clean:
X	rm drone cosmos rmseg *.o
END_OF_FILE
if test 1538 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'Manifest' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Manifest'\"
else
echo shar: Extracting \"'Manifest'\" \(734 characters\)
sed "s/^X//" >'Manifest' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X Help                       2	
X Makefile                   1	
X Manifest                   1	This shipping list
X README                     1	
X buildbase.c                1	
X cosmos.c                   3	
X cosmos.h                   2	
X dispstatus.c               1	
X drone.c                    2	
X funcs.c                    3	
X getship.c                  1	
X givedamage.c               1	
X makechoice.c               1	
X mines.c                    1	
X modgame.c                  1	
X phasers.c                  1	
X players.c                  1	
X rmseg.c                    1	
X scan.c                     1	
X torpedoes.c                2	
END_OF_FILE
if test 734 -ne `wc -c <'Manifest'`; then
    echo shar: \"'Manifest'\" unpacked with wrong size!
fi
# end of 'Manifest'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(6745 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Welcome to COSMOS!
X
This is the first public release of the COSMOS game for Xenix and some Unix
machines.  We hope you will find it to be a fun diversion from your normal
routine -- but be careful not to become addicted to it!
X
X
The following is our statement of policy with regards to the COSMOS package
and it's copyright, as well as general information on porting and
compatibility.
X
XFirst, the dry stuff we have to dispense with:
X
COSMOS is Copyright 1988 by MCS, Inc. and Karl Denninger
All component files in this 'shar' archive are considered covered by this
copyright, both individually and as a compilation.
All rights reserved.
X
Limited distribution rights are granted to the public as follows:
X
o Non-profit distribution of this SHAR file, in it's entirety, is permitted
X  freely.  If modifications are made, the unmodified files MUST be provided in
X  any and all derivitive works.
X
o Non-profit and personal use of this software is permitted on an 
X  unrestricted basis.  
X
o No derivitive or direct product of this work, whether composed of this
X  package in whole or part, may be sold or used for profit without the express 
X  written consent of MCS, Inc. and Karl Denninger.  "Profit" shall be defined
X  as monetary compensation in excess of direct costs for the transfer of code 
X  or documentation contained in COSMOS, or compensation paid to secure the
X  right to execute COSMOS on a host CPU.  (If in doubt, ask.  In general,
X  having COSMOS available on a pay-for system is ok, as long as you don't
X  charge specifically for COSMOS' use).
X
o Copyright notices and any other legends or trademarks must not be removed
X  from the software and any accompanying documentation.
X
X
COSMOS is SHAREWARE.  We request a $25.00 donation for each executing CPU.
In return, you'll be placed on our mailing list and alerted to new versions
of COSMOS, as well as receiving a nicely-printed users manual.  It is
expected that after evaluating the game, you will either remove it from use
or register the package.
X
Please send checks to:
X
Macro Computer Solutions, Inc.
X415 S.E. Garfield
Mundelein, IL  60060
Attn: COSMOS Shareware
X
X
X
DISCLAIMER OF WARRANTY AND LIABILITY.
X
MCS and Karl Denninger hereby disclaim any and all warranties and
liabilities with regards to this package.  COSMOS is provided "as is", and
the user is warned that there is no guarantee of completeness or
correctness, nor of fitness for any purpose whatsoever.  The user is wholly
responsible for the results of compiling and using COSMOS, without
limitation.  
X
X
Installation:
X
COSMOS is designed to execute on a SCO Xenix V/386 installation.  As such,
it should compile without changes in it's supplied form.  Other operating
systems may require SUBSTANTIAL modifications.  To be able to support
COSMOS, you require at a minimum:
X
o Shared memory support per SVID (SVR2 or better)
o Semaphore support, per SVID. 
o A segment size limitation (if any) in excess of 500K.  Linear address
X  spaces are highly preferred.  This package WILL NOT run on a 80286.  Don't
X  even bother trying.
X
o A working CURSES implementation.
X
X
Highly recommended:
o A 'nap()' system call (short sleep).
X
X
If you have all the items noted above, you can probably build COSMOS.  If
you're on a Xenix V/386 machine, you'll certainly be able to do so (in fact,
it should build without modifications).
X
Do all the usual things, peek in the Makefile and cosmos.h to make sure
things look reasonable to you, and type 'make'.
X
Place the binary files (cosmos and drone) in a publically-locatable directory.  The executable 'rmseg' is provided to clean up after the COSMOS game; it
removes the shared segment and semaphore identifiers if needed.
X
X
To install:
X
Make a directory, and place the Help and Hello files in it.  Make these
world readable.  SGID cosmos, in a binary directory, to your games group
X(which should also own the directory you have the Help in).
X
Create /etc/cosmos, in the form:
X
X/pub/games/lib/cosmos/ 100 101 6 120 120 480
X
XFields:
X
X1. Base directory: where to find the Help and Hello files, as well as the
X   place you want COMSOS to keep it's scorefile.  Should NOT be publically
X   accessible (660 is a good mode).
X
X2. First "god user" UID.
X3. Second "god user" UID.
X
X	Both of these users can use the ^X, ^W and ^P functions.
X
X4. The number of drone ships you will allow to be in the game.
X   WARNING: If this is too large, you'll have a VERY slow system! :-)  6 is
X   reasonable for most 80386 machines.
X
X5. Time limit values for captive users.  Currently incomplete, these values
X   are used if ACCOUNTING is #defined in cosmos.h  You may put any values
X   you wish in here at present, but they MUST be present.
X
XExit the editor and make sure this file is readable by the COSMOS group.
X
Once this has been done, you are ready to play.  Type 'cosmos' to start.
All documentation is online.
X
X
X
THEORY OF OPERATION
X
COSMOS is a shared-memory real-time space adventure.  It is designed around
a single semaphore for locking, and a large shared memory segment for data
storage.  All information that is considered globally "accurate" is
contained in this shared segment, which is created by the first player
entering the game.
X
The game system meters out time in discrete "chunks", the size of which are
under the control of the system installer.  Drone ships operate using the
same rules and strategy as the human players, but are penalized slightly to
allow the humans some semblance of a chance in combat.  
X
COSMOS is designed to decommission drones when there are no human players in
the game.  After a few turns, the drones will put themselves to sleep until
one or more players reenter the game.
X
X
RESOURCE CONSUMPTION
X
COSMOS requires about 500K of shared memory in it's default configuration.
When the game is in play, this is mapped into each players virtual process
space, and thus consumes physical memory.  During quiescent times of no
playing, the operating system should page this segment out to disk.
X
Drones are likewise stopped, but the process(es) in question continue to
remain alive on the system, albiet in suspended animation. 
X
If this is a concen, you may modify the drone code to exit when they detect
a lack of human players.  Similarly, it would be simple to add the required
support to delete the shared segment and semaphore when the last process
exits, although this is not currently done (not doing so keeps the game grid
around for the next player).
X
Of course, system reboots and crashes will cause the segment to be removed :-)
X
X
XEnjoy -- and watch that load average!
X
X--
Karl Denninger (karl@ddsw1.MCS.COM, ddsw1!karl)
Data: [+1 312 566-8912], Voice: [+1 312 566-8910]
Macro Computer Solutions, Inc.    	"Quality solutions at a fair price"
END_OF_FILE
if test 6745 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'buildbase.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'buildbase.c'\"
else
echo shar: Extracting \"'buildbase.c'\" \(3900 characters\)
sed "s/^X//" >'buildbase.c' <<'END_OF_FILE'
X/*	Base Building routines
X	Contains routines for both player and computer people.... */
X
X/*	Copyright 1988 Karl Denninger  & MCS, Inc.  
X	All rights reserved					*/
X
X
X#include 	"cosmos.h"
X
extern	char	*buffer;
extern	int	drone;
extern	struct	nameblock	*ship;
X
cbuildbase(semid, x, y, window)
int	semid;
int	x, y;
int	window;
X
X{
X
X	int	kb;
X	int	xx, yy;
X	int	dist;
X	struct	grid	onegrid;
X	struct	grid	anothergrid;
X	char	tmp[80];
X
X	release(semid);
X	xx = x; yy = y;
X	kb = findobj(&xx, &yy, &dist, PLANET, PLANET, window);
X	acquire(semid);
X	xx = 0; yy = 0;
X	switch(kb) {
X		case '8':
X			xx = 0; yy = 1;
X			break;
X		case '9':
X			xx = 1; yy = 1;
X			break;
X		case '6':
X			yy = 0; xx = 1;
X			break;
X		case '3':
X			yy = -1; xx = 1;
X			break;
X		case '2':
X			xx = 0; yy = -1;
X			break;
X		case '1':
X			xx = -1; yy = -1;
X			break;
X		case '4':
X			xx = -1; yy = 0;
X			break;
X		case '7':
X			xx = -1; yy = 1;
X			break;
X	}
X	xx += x;
X	yy += y;
X	readgrid(xx, yy, &onegrid);
X	if (onegrid.type == PLANET)  {		/* If now a planet */
X		onegrid.shield += 10;		/* Add one shield level */
X		printf("Build %d\n", (onegrid.shield/10));
X		fflush(stdout);
X		ship->energy -= BUILDCOST;	/* It's expensive! */
X		ship->points += 50;		/* One point for a build */
X		readgrid(x, y, &anothergrid);
X		anothergrid.energy = ship->energy;
X		storegrid(x, y, anothergrid);
X	} else {				/* Can't build anything else */
X		return(0);
X	}
X	if (onegrid.shield >= 100) {		/* If we have a base.. */
X		if (roll(200) < 2)
X			onegrid.type = NEGBASE;	/* Change it to a neg. base */
X		else
X			onegrid.type = BASE;	/* Change it to a base */
X		onegrid.align = ship->align;	/* It's yours, or neutral */
X		sprintf(tmp, "A new base appears at %d %d", xx, yy);
X		putmsg(tmp);
X		ship->points += 200;		/* 200 for a base... */
X	}
X	storegrid(xx, yy, onegrid);
X	release(semid);
X	sleep(BUILDTIME);			/* Sleep for BUILDTIME secs */
X	acquire(semid);
X	return(0);
X}
X
X
X
buildbase(semid, x, y)
int	semid;
int	x, y;
X
X{
X
X	int	kb;
X	int	xx, yy;
X	struct	grid	onegrid;
X	struct	grid	anothergrid;
X	char	tmp[80];
X
X	release(semid);
X	mvaddstr(22,20,"Build -> ");
X	clrtoeol();
X	refresh();
X	kb = getchx();
X	acquire(semid);
X	if (ship->wstatus & SHIELD_UP) {
X		mvaddstr(23,20,"Captain!  We can't deploy troops through the shields!");
X		clrtoeol();
X		return(0);
X	}
X	xx = 0; yy = 0;
X	switch(kb) {
X		case '8':
X			xx = 0; yy = 1;
X			break;
X		case '9':
X			xx = 1; yy = 1;
X			break;
X		case '6':
X			yy = 0; xx = 1;
X			break;
X		case '3':
X			yy = -1; xx = 1;
X			break;
X		case '2':
X			xx = 0; yy = -1;
X			break;
X		case '1':
X			xx = -1; yy = -1;
X			break;
X		case '4':
X			xx = -1; yy = 0;
X			break;
X		case '7':
X			xx = -1; yy = 1;
X			break;
X	}
X	xx += x;
X	yy += y;
X	if ((xx < 0) || (xx >= SIZE) || (yy < 0) || (yy >= SIZE)) {
X		mvaddstr(23,20,"Can't build there");
X		clrtoeol();
X		return(0);
X	}
X	readgrid(xx, yy, &onegrid);
X	if (onegrid.type == PLANET)  {		/* If now a planet */
X		onegrid.shield += 10;		/* Add one shield level */
X		move(23,20);
X		printw("Build %d", (onegrid.shield/10));
X		release(semid);
X		refresh();
X		acquire(semid);
X		ship->energy -= BUILDCOST;	/* It's expensive! */
X		ship->points += 50;		/* One point for a build */
X		readgrid(x, y, &anothergrid);
X		anothergrid.energy = ship->energy;
X		storegrid(x, y, anothergrid);
X	} else {				/* Can't build anything else */
X		mvaddstr(23,20,"Nothing there to build!");
X		clrtoeol();
X		return(0);
X	}
X	if (onegrid.shield >= 100) {		/* If we have a base.. */
X		if (roll(200) < 2)
X			onegrid.type = NEGBASE;	/* Change it to a neg. base */
X		else
X			onegrid.type = BASE;	/* Change it to a base */
X		onegrid.align = ship->align;	/* It's yours, or neutral */
X		sprintf(tmp, "A new base appears at %d %d", xx, yy);
X		putmsg(tmp);
X		mvaddstr(23,20,"You have built a BASE!");
X		ship->points += 200;		/* 200 for a base... */
X	}
X	storegrid(xx, yy, onegrid);
X	release(semid);
X	sleep(BUILDTIME);			/* Sleep for BUILDTIME secs */
X	acquire(semid);
X	return(0);
X}
X
END_OF_FILE
if test 3900 -ne `wc -c <'buildbase.c'`; then
    echo shar: \"'buildbase.c'\" unpacked with wrong size!
fi
# end of 'buildbase.c'
fi
if test -f 'dispstatus.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dispstatus.c'\"
else
echo shar: Extracting \"'dispstatus.c'\" \(6141 characters\)
sed "s/^X//" >'dispstatus.c' <<'END_OF_FILE'
X/*	Dispstatus.c		*/
X
X#include	"cosmos.h"
X
extern	char	*buffer;
extern	int	drone;
extern	struct	nameblock	*ship;
X
calcstatus(x, y, window, docked)		/* Calc green/red, no display */
int	x, y;
int	window;
int	docked;
X
X{
X	int	scanx, scany;		/* Scanner variables */
X	struct	grid	onegrid;	/* One grid entry */
X	int	scx, scy, tempint, tempx;
X	int	othership = 0;
X	int	ally =0;
X	int	enemy = 0;
X	long	oldenergy;
X	int	xx = 0, yx = 0;
X	static	int	retval;
X
X	readgrid(x, y, &onegrid);	/* Get present situation */
X	ship->shield = onegrid.shield;	/* Update */
X	oldenergy = ship->energy;
X	if (onegrid.energy < ship->energy)
X		ship->energy = onegrid.energy;
X	scanx = x - (window / 2);	/* Start here on each axis */ 
X	scany = y - (window / 2);
X	scx = 0;
X	scy = window;
X	othership = 0;
X	tempint = scanx;
X	while (scany <= (y + (window / 2))) {
X		scx = 0;
X		scanx = tempint;
X		while (scanx <= (x + (window / 2))) {
X			if ((scanx < 0) || (scany < 0) || (scanx >= SIZE) || (scany >= SIZE))
X				;
X			else {
X				readgrid(scanx, scany, &onegrid);
X				if (onegrid.hit) { 
X					if ((scx != x) && (scy != y)) {
X						if ((onegrid.type < 'A') || (onegrid.type > 'Z')) {
X							onegrid.hit = 0;
X							storegrid(scanx, scany, onegrid);
X						}
X					}
X				}
X				if ((onegrid.type >= 'A') && (onegrid.type <= 'Z')) {
X					if (onegrid.align == ship->align) {
X						othership++;
X						ally++;
X					} else {
X						othership++;
X						enemy++;
X					}
X				}
X
X			}
X			scx++;
X			scanx++;
X		}
X		scany++;
X		scy--;
X	}
X	othership--;				/* We'll always be there */
X	if (othership == 0) {
X		retval = 0;
X	} else {
X		retval = 1;
X	}
X	return(retval);
X}
X
dispstatus(x, y, window, docked)
int	x, y;
int	window;
int	docked;
X
X{
X	int	scanx, scany;		/* Scanner variables */
X	struct	grid	onegrid;	/* One grid entry */
X	int	scx, scy, tempint, tempx;
X	int	othership = 0;
X	int	ally =0;
X	int	enemy = 0;
X	long	oldenergy;
X	int	xx = 0, yx = 0;
X	int	lastfound;
X	int	dx, dy;
X	static	int	retval;
X
X	
X	for (xx = 0; xx <= (window + 1); xx++) {
X		mvaddstr(xx,0,"|");
X		mvaddstr(xx,(window * 2)+2,"|");
X	}
X	readgrid(x, y, &onegrid);	/* Get present situation */
X	ship->shield = onegrid.shield;	/* Update */
X	oldenergy = ship->energy;
X	if (onegrid.energy < ship->energy)
X		ship->energy = onegrid.energy;
X	scanx = x - (window / 2);	/* Start here on each axis */ 
X	scany = y - (window / 2);
X	scx = 0;
X	scy = window;
X	move(scy + 1, 1);
X	for (xx = 0;xx <= (window * 2); xx++)
X		addstr("=");
X	lastfound = ((window / 2) + 1);
X	move(scy + 1, (window - (strlen(">Scanner<") / 2)+1));
X	addstr(">Scanner<");
X	othership = 0;
X	tempint = scanx;
X	while (scany <= (y + (window / 2))) {
X		scx = 0;
X		scanx = tempint;
X		while (scanx <= (x + (window / 2))) {
X			dx = (scanx - x) * (scanx - x);
X			dy = (scany - y) * (scany - y); 
X			if ((scanx < 0) || (scany < 0) || 
X				(scanx >= SIZE) || (scany >= SIZE) 
X#ifdef	FASTMATH
X				|| ((int) sqr(dx + dy) >= lastfound)
X#endif
X				)
X				mvaddch(scy, (scx * 2)+1, 32);
X			else {
X				readgrid(scanx, scany, &onegrid);
X				if (onegrid.hit) 
X					standout();
X				if (docked == -1)
X					mvaddch(scy, (scx * 2)+1, onegrid.type);
X				else {
X					if (onegrid.type == NEGBASE) {
X						mvaddch(scy, (scx * 2)+1, BASE);
X					} else {
X						mvaddch(scy, (scx * 2)+1, onegrid.type);
X					}
X				}
X				if (onegrid.hit) { 
X					standend();
X					if ((scx != x) && (scy != y)) {
X						if ((onegrid.type < 'A') || (onegrid.type > 'Z')) {
X							onegrid.hit = 0;
X							storegrid(scanx, scany, onegrid);
X						}
X					}
X				}
X				if ((onegrid.type >= 'A') && (onegrid.type <= 'Z')) {
X					if (onegrid.align == ship->align) {
X						othership++;
X						ally++;
X					} else {
X						othership++;
X						enemy++;
X					}
X				}
X
X			}
X			scx++;
X			scanx++;
X		}
X		scany++;
X		scy--;
X	}
X	move(0,44);
X	printw(">> The S.S. %s <<", ship->name);
X	clrtoeol();
X	move(2,59);
X	printw("Energy... %ld", ship->energy);
X	clrtoeol();
X	move(3,59);
X	printw("Engines.. %d", ship->engines);
X	clrtoeol();
X	move(4,59);
X	printw("Lasers... %d", ship->lasers);
X	clrtoeol();
X	move(5,59);
X	if ((ship->wstatus & MINE_DEAD) == 0)
X		printw("Mine Lch. %d", ship->mines);
X	clrtoeol();
X	move(6,59);
X	if ((ship->wstatus & TORPEDO_DEAD) == 0)
X		printw("Torp Lch. %d", ship->torps);
X	clrtoeol();
X	move(7,59);
X	printw("Shield... %d", ship->shield);
X	clrtoeol();
X	move(8,59);
X	printw("Crew Lvl. %d", ship->crew);
X	clrtoeol();
X	move(9,59);
X	printw("Life Supt %d", ship->life);
X	clrtoeol();
X	move(10,59);
X	printw("Hull..... %d", ship->hull);
X	clrtoeol();
X	move(11,59);
X	if (docked)
X		addstr("Ship..... DOCKED");
X	clrtoeol();
X	move(12,59);
X	othership--;				/* We'll always be there */
X	if (othership == 0) {
X		printw("Status... GREEN");
X		retval = 0;
X	} else {
X		retval = 1;
X		if (ship->wstatus & SHIELD_UP)
X			printw("Status... YELLOW");
X		else
X			printw("Status... RED");
X	}
X	clrtoeol();
X	move(13,59);
X	if (ship->wstatus & SHIELD_DEAD)
X		addstr("Shield... INOPERABLE");
X	else {
X		if (ship->wstatus & SHIELD_UP)
X			addstr("Shield... UP");
X		else
X			addstr("Shield... DOWN");
X	}
X	clrtoeol();
X	move(14,59);
X	if (ship->wstatus & LASERS_DEAD)
X		addstr("Lasers... INOPERABLE");
X	else {
X		if (ship->wstatus & LASERS_LOCK)
X			addstr("Lasers... LOCKED");
X		else
X			addstr("Lasers... STBY");
X	}
X	clrtoeol();
X	move(15,59);
X	if (ship->wstatus & MINE_DEAD)
X		clrtoeol();
X	else {
X		if (ship->wstatus & MINE_LOCK)
X			addstr("Mines.... LOCKED");
X		else
X			addstr("Mines.... STBY");
X		printw(" /%d", ship->nummines);
X	}
X	clrtoeol();
X	move(16,59);
X	if (ship->wstatus & TORPEDO_DEAD)
X		clrtoeol();
X	else {
X		if (ship->wstatus & TORPEDO_LOCK)
X			addstr("Torps.... LOCKED");
X		else
X			addstr("Torps.... STBY");
X		printw(" /%d", ship->numtorps);
X	}
X	clrtoeol();
X	mvaddstr(17,43,"------------------------------------");
X	dspmsg();				/* Show any messages */
X	mvaddstr(22,0,"Current Position");
X	move(23,0);
X	printw("X = %3d, Y = %3d", x, y);
X	if (oldenergy > ship->energy) {
X		mvaddstr(23,20,"You've been HIT!");
X		clrtoeol();
X		beep();
X	}
X	if (ship->gods) {
X/*		mvaddstr(23,20,"You feel a supernatural force nearby");
X		clrtoeol();	*/
X		ship->gods = 0;
X	}
X	if (oldenergy < ship->energy) {
X		mvaddstr(23,20,"Energy transfer to you in progress");
X		clrtoeol();
X	}
X	return(retval);
X}
X
END_OF_FILE
if test 6141 -ne `wc -c <'dispstatus.c'`; then
    echo shar: \"'dispstatus.c'\" unpacked with wrong size!
fi
# end of 'dispstatus.c'
fi
if test -f 'getship.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getship.c'\"
else
echo shar: Extracting \"'getship.c'\" \(5450 characters\)
sed "s/^X//" >'getship.c' <<'END_OF_FILE'
X/*	Getship.c	- get a new ship type */
X
X#include	"cosmos.h"
X
X#define	MAXCPNAMES	21		/* Number of names defined below */
static	char	*cpname[MAXCPNAMES] = {
X	"Andrus", "Nomad", "Colossus", "W.O.P.R.", "Joshua",
X	"James", "Zoonix", "Regula", "Andromeda", "Eteries",
X	"Freightliner", "Unreliable", "Pegasus", "Sturgeon", "Challenger",
X	"Enterprise", "Relient", "Excalibur", "Botany Bay", "Columbia",
X	"Yugo" };
X
X
extern	char	*buffer;
extern	char	home[128];
extern	int	drone;
extern	struct	nameblock	*ship;
X
X
X
char	*getcship(semid, xx, yy)
int	semid;
int	*xx, *yy;
X
X{
X	
X	static	struct	nameblock	shipx;
X
X	struct	shiprecord	record;
X	struct	passwd		*psw;
X	struct	nameblock	entry;
X	int	uid;
X	int	fid;
X	int	index;
X	char	fname[80], tmp[80];
X	int	count;
X	int	quit = 0;
X	long	temp;
X	int	key;
X	int	x;
X	
X	strcpy(shipx.name, "_Computer");
X	shipx.type = roll(11);			/* Select a ship type */
X	if (shipx.type == 0)
X		shipx.type++;
X	shipx.name[MAXNAME-1] = 0;
X#ifdef	DEBUG
X	*xx = 1;
X	*yy = 1;
X#else
X	*xx = roll(SIZE - 1);
X	*yy = roll(SIZE - 1);
X#endif
X	shipx.energy = (long) e_require[shipx.type];	/* Get max energy */
X	shipx.points = (long) pts[shipx.type - 1];	/* Points to start */
X	shipx.shield = 100;
X	shipx.crew = 100;
X	shipx.life = 100;
X	shipx.engines = 100;
X	shipx.hull = 100;
X	shipx.lasers = 100;
X	shipx.torps = 100;
X	shipx.mines = 100;
X	shipx.numtorps = num_torps[shipx.type];	/* Copy over config values */
X	shipx.nummines = num_mines[shipx.type];
X	shipx.wstatus = weapons[shipx.type];
X	printf("Computer ship is called the %s, a %s with %ld pts.\n", shipx.name, shiptypes[shipx.type], shipx.points);
X	fflush(stdout);
X	quit = 0;
X	key = 'A';
X	while (quit == 0) {
X		entry.token = key;
X		if ((index = locship(&entry, 1)) < 0)
X			quit++;
X		else
X			key++;
X	}
X	shipx.token = key;
X	entry.token = 0;
X	x = locship(&entry, 1);		/* Find open slot */
X	if (x == -1) {
X		puts("Too many players!");
X		release(semid);
X		exit(0);
X	}
X	sprintf(tmp, "%s %d", cpname[roll(MAXCPNAMES)], (x + 1));
X	strcpy(shipx.name, tmp);
X	storename(x, shipx);
X	return((char *) buffer + sizeof(ccount) + (sizeof(shipx) * x) );
X}
X
X
char	*getship(cx, ptr, semid, xx, yy)
int	cx;
char	*ptr;
int	semid;
int	*xx, *yy;
X
X{
X	
X	static	struct	nameblock	shipx;
X
X	int	cxx;
X	struct	shiprecord	record;
X	struct	passwd		*psw;
X	struct	nameblock	entry;
X	int	uid;
X	int	fid;
X	int	index;
X	char	fname[80];
X	int	count;
X	int	quit = 0;
X	long	temp;
X	int	key;
X	int	x;
X	
X	cxx = cx;
X	mvaddstr(1,20,"Ship Assignment - The Admiral's Quarters");
X	mvaddstr(3,0,"Tkn    Ship Name              Class            Points");
X	x = 4;
X	count = 0;
X	while (count < MAXSHIPS) {
X		readname(count, &entry);
X		if (entry.token) {
X			entry.name[MAXNAME-1] = 0;	/* Just in case */
X			mvaddch(x,0,entry.token);
X			mvaddstr(x,5,entry.name);
X			move(x,30);
X			addstr(shiptypes[entry.type]);
X			move(x,47);
X			printw("%ld", entry.points);	/* User's points */
X			x++;
X		}
X		count++;
X	}
X	refresh();
X	uid = getuid();			/* Who are we (really) */
X	sprintf(fname, "%s/space.scorefile", HOMEDIR);
X	if ((fid = open(fname, O_RDWR|O_CREAT, 0660)) < 0) {
X		perror(fname);
X		endwin();
X		return((char *) NULL);
X	}
X	count = 0;
X	while (read(fid, &record, sizeof(record)) == sizeof(record)) {
X		if (record.uid == uid)  {
X			count++;		/* Found record */		
X			lseek(fid, 0L - (sizeof(record)), 1);
X			break;
X		}
X	}
X	if (count == 0)  {
X		release(semid);
X		mvaddstr(18,0, "Please name your vessel: ");
X		refresh();
X		get_str(shipx.name);
X		acquire(semid);
X		strcpy(record.shipname, shipx.name);
X		shipx.type = 2;
X		shipx.points = pts[(shipx.type - 1)];
X		record.uid = getuid();
X		record.type = 1;
X		record.points = 0L;
X		record.energy = e_require[shipx.type];
X		write(fid, &record, sizeof(record));
X	} else {
X		shipx.type = record.type;
X		shipx.points = record.points;
X		shipx.energy = record.energy;
X		strncpy(shipx.name, record.shipname, MAXNAME);
X		shipx.name[MAXNAME-1] = 0;
X		*xx = record.x;
X		*yy = record.y;
X	}
X	close(fid);
X	while (shipx.points > pts[shipx.type]) {
X		shipx.type++;
X		move(20,0);
X		standout();
X		shipx.energy = 0;	/* Make sure you get full tanks */
X		printw("Congratuations!  You have been promoted to captain of a %s", shiptypes[shipx.type]);
X		standend();
X		clrtoeol();
X	}
X	if (!shipx.energy)
X		shipx.energy = (long) e_require[shipx.type];/* Max energy */
X	shipx.shield = 100;
X	shipx.crew = 100;
X	shipx.life = 100;
X	shipx.engines = 100;
X	shipx.hull = 100;
X	shipx.lasers = 100;
X	shipx.torps = 100;
X	shipx.mines = 100;
X	shipx.numtorps = num_torps[shipx.type];	/* Copy over config values */
X	shipx.nummines = num_mines[shipx.type];
X	shipx.wstatus = weapons[shipx.type];
X	while (quit == 0) {
X		release(semid);
X		move(21,0);
X		printw("Your ship is called the %s, a %s with %ld pts.", shipx.name, shiptypes[shipx.type], shipx.points);
X		clrtoeol();
X		mvaddstr(22,0,"Enter desired ship token: ");
X		refresh();
X		if (cxx > 1) {
X			key = *ptr;
X			cxx = 1;
X		} else 
X			key = getchx();
X		if ((key >= 'a') && (key <= 'z')) 
X			key = key - 32;
X		if ((key < 'A') || (key > 'Z'))
X			continue;
X		addch(key);
X		refresh();
X		entry.token = key;
X		acquire(semid);
X		if ((index = locship(&entry, 1)) >= 0)
X			mvaddstr(23,0, "In use, try again");
X		else
X			quit++;
X	}
X	shipx.token = key;
X	shipx.uid = getuid();
X	entry.token = 0;
X	x = locship(&entry, 1);		/* Find open slot */
X	if (x == -1) {
X		endwin();
X		puts("Too many players!");
X		release(semid);
X		return((char *) NULL);
X	}
X	storename(x, shipx);
X	return((char *) buffer + sizeof(ccount) + (sizeof(shipx) * x)); 
X}
END_OF_FILE
if test 5450 -ne `wc -c <'getship.c'`; then
    echo shar: \"'getship.c'\" unpacked with wrong size!
fi
# end of 'getship.c'
fi
if test -f 'givedamage.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'givedamage.c'\"
else
echo shar: Extracting \"'givedamage.c'\" \(4738 characters\)
sed "s/^X//" >'givedamage.c' <<'END_OF_FILE'
X/*	Give Damage to another object	*/
X
X#include	"cosmos.h"
X
extern	int	drone;
extern	struct	nameblock	*shp;
X
void givedamage(x, y, edmg, shp, explosion)
int	x, y;
int	edmg;
struct	nameblock	*shp;
int	explosion;
X{
X	int	shiedmg;
X	char	tmp[80];
X	int	xx, hitperson;
X	struct	grid	ogrid;
X	struct	nameblock	oname;
X
X	shiedmg = edmg / EPERSHIELD;
X	if (shp != NULL)
X		shp->points += (edmg / 200);	/* Give the hitter points */
X	readgrid(x, y, &ogrid);
X	ogrid.hit++;				/* Make it light up */
X	if ((ogrid.type == EMPTY) || (ogrid.type == VOID)) {/* Nothing? */
X		storegrid(x, y, ogrid);		/* Save it back */
X		return;				/* Get the heck out */
X	}
X	if ((ogrid.type == BASE) || (ogrid.type == NEGBASE)) {
X		if (ogrid.shield == 100) {
X			sprintf(tmp, "Base under attack at %d %d", x, y); 
X			putmsg(tmp);
X		}
X		if (ogrid.shield > shiedmg) {
X			ogrid.shield -= shiedmg;
X			edmg = 0;
X		} else {
X			ogrid.shield = 0;
X		}
X		ogrid.energy -= edmg;
X	}
X	if (shp != NULL)
X		if (drone == 0) {
X			move(23,20);
X		}
X	if ((ogrid.shield <= 0) && ((ogrid.type == BASE) || (ogrid.type == NEGBASE))) {
X		if (shp != NULL) {
X			if (ogrid.align != shp->align)
X				shp->points += 1000;	/* Pts iff not yours */
X		}
X		ogrid.type = PLANET;
X		ogrid.shield = 0;
X		storegrid(x, y, ogrid);
X		if (shp != NULL)
X			if (drone == 0) {
X				printw("FLASH!  The base is DESTROYED!");
X			}
X		explode(x, y, (BASE_DEATH * EXPLOSION), BASE_DEATH);
X	} else {
X		if (shp != NULL) {
X			if (drone == 0) {
X				printw("Scored hit on '%c'", ogrid.type);
X			}
X			clrtoeol();
X		}
X	}
X	if ((ogrid.type >= 'A') && (ogrid.type <= 'Z')) {	/* A shp? */
X		xx = 0;
X		hitperson = -1;
X		while (hitperson == -1) {
X			readname(xx, &oname);
X			if (oname.token == ogrid.type)
X				hitperson = xx;
X			xx++;
X		}
X		if (hitperson >= 0)		/* Big shp has better shield */
X			shiedmg = shiedmg / ((oname.type / 2) + 2);
X		if (oname.wstatus & SHIELD_UP) {
X			if (ogrid.shield > shiedmg) {
X				ogrid.shield -= shiedmg;
X				edmg = 0;
X			} else {
X				edmg -= ((ogrid.shield * ((oname.type / 2) + 2)) * EPERSHIELD);
X				ogrid.shield = 0;
X			}
X		}
X		ogrid.energy -= edmg;		/* No diff for raw E hits */
X		if (hitperson >= 0) {		/* Systems are less fragile */
X			edmg = edmg / oname.type;/* Divide by type */
X			if (!explosion) {	/* If not an explosion */
X				xx = roll(8);
X				switch(xx) {
X					case 0:
X						oname.engines -= edmg/100;
X						break;
X					case 1:
X						oname.life -= edmg/150;
X						break;
X					case 2:
X						oname.crew -= edmg/200;
X						break;
X					case 3:
X						oname.shield -= edmg/75;
X						break;
X					case 4:
X						oname.hull -= edmg/300;
X						break;
X					case 5:
X						oname.lasers -= edmg/500;
X						break;
X					case 6:
X						oname.torps -= edmg/200;
X						break;
X					case 7:
X						oname.mines -= edmg/50;
X						break;
X				}
X			} else {	/* Explosion hurts everything */
X				oname.engines -= edmg/(75 + roll(50));
X				oname.life -= edmg/(100 + roll(100));
X				oname.crew -= edmg/(150 + roll(100));
X				oname.shield -= edmg/(50 + roll(50));
X				oname.hull -= edmg/(200 + roll(200));
X				oname.lasers -= edmg/(400 + roll(200));
X				oname.torps -= edmg/(150 + roll(100));
X				oname.mines -= edmg/(25 + roll(50));
X			}
X		}
X		storename(hitperson, oname);
X		if (ogrid.energy < 0) {	/* If a shp blows up */
X			if (shp != NULL)
X				shp->points += (oname.points / 5);
X		}
X	} else {
X		if (ogrid.type != VOID) {
X			if (ogrid.shield > 0)
X				ogrid.shield -= (edmg/100);
X			if (ogrid.shield <= 0) {
X				ogrid.shield = 0;
X				ogrid.energy -= edmg;
X			}
X		}
X	}
X	if (ogrid.energy < 0) {
X		if (drone == 0)
X			mvaddstr(23,20,"FLASH! There is an explosion!");
X		if ((ogrid.type < 'A') || (ogrid.type > 'Z')) {
X			if ((ogrid.type == MINE) || (ogrid.type == TORPEDO)) {
X				if (shp != NULL)
X					shp->points += 25;
X				ogrid.type = EMPTY;
X				storegrid(x, y, ogrid);
X				if (roll(NUKECHANCE) < 2)	/* Nuke? */
X					explode(x, y, (NUKE_MINE * EXPLOSION), 
X						NUKE_MINE);/* Nuclear mine */
X				else
X					explode(x, y, (MINE_BOOM * EXPLOSION), 
X						MINE_BOOM);/* Normal Mine */
X			}
X			if (ogrid.type == PLANET) {
X				if (shp != NULL)
X					shp->points += 3000;
X				ogrid.type = EMPTY;
X				storegrid(x, y, ogrid);
X				explode(x, y, (BIG_BOOM * EXPLOSION), BIG_BOOM);	/* Oh oh ! */
X				sprintf(tmp, "Planet destroyed at %d %d", x, y);
X				putmsg(tmp);
X			}
X			if (ogrid.type == STAR) {
X				if (shp != NULL)
X					shp->points += 8000;
X				ogrid.type = VOID;
X				ogrid.energy = roll(SIZE);
X				ogrid.shield = roll(SIZE);
X				storegrid(x, y, ogrid);
X				explode(x, y, (NOVA * (EXPLOSION * 2)), NOVA);		/* Ouch! */
X				sprintf(tmp, "NOVA at %d %d!", x, y);
X				putmsg(tmp);
X			}
X		} else {
X			ogrid.type = EMPTY;
X			storegrid(x, y, ogrid);
X			explode(x, y, (SHIP_DEATH * EXPLOSION), SHIP_DEATH);
X		}
X	}
X	storegrid(x, y, ogrid);
X	return;
X}
END_OF_FILE
if test 4738 -ne `wc -c <'givedamage.c'`; then
    echo shar: \"'givedamage.c'\" unpacked with wrong size!
fi
# end of 'givedamage.c'
fi
if test -f 'makechoice.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makechoice.c'\"
else
echo shar: Extracting \"'makechoice.c'\" \(4177 characters\)
sed "s/^X//" >'makechoice.c' <<'END_OF_FILE'
X/*	Space module	 MAKECHOICE	- run the drone ship	*/
X
X#include	"cosmos.h"
extern	char	*buffer;
extern	struct	nameblock	*ship;
X
checkchoice(x, y, key, lastret)			/* Is this a wise choice? */
int	x, y;
int	key;
int	*lastret;
X
X{
X	static	int	keyvec[10] = {'1', '4', '7', '8', '9', '6', '3', '2', 0};
X	int	retval;
X	int	xx, yy;
X	struct	grid	ourgrid;
X	int	quit = 0;
X	int	infloop = 0;
X
X	retval = key;
X	if (key == 0) {
X		if (roll(10) > 8) {
X			retval = keyvec[roll(7)];
X		} else {
X			retval = *lastret;
X		}
X	}
X	quit = 0;
X	while (quit == 0) {
X		infloop++;			/* Infinite loop detector */
X		xx = x; yy = y;
X		switch(retval) {
X			case '8':
X				yy = y + 1;
X				break;
X			case '7':
X				yy = y + 1;
X				xx = x - 1;
X				break;
X			case '1':
X				yy = y - 1;
X				xx = x - 1;
X				break;
X			case '9':
X				xx = x + 1;
X				yy = y + 1;
X				break;
X			case '3':
X				yy = y - 1;
X				xx = x + 1;
X				break;
X			case '2':
X				yy = y - 1;
X				break;
X			case '4':
X				xx = x - 1;
X				break;
X			case '6':
X				xx = x + 1;
X				break;
X		}
X		if ((xx >= 0) && (yy >= 0) && (xx < SIZE) && (yy < SIZE)) {
X			readgrid(xx, yy, &ourgrid);
X			if (ourgrid.type == EMPTY) {	/* Found an out */
X				quit++;
X				*lastret = retval;
X				return(retval);
X			}
X		}
X		retval = keyvec[roll(8)];
X		if (infloop > 15) {		/* Can't find a way out */
X			retval = 0;		/* So don't move anywhere */
X			quit++;
X			printf("Can't find path; sit\n");
X			fflush(stdout);
X		}
X	}
X	*lastret = retval;
X	return(retval);
X}
X
makechoice(x, y, window, lastkey)
int	x, y;
int	window;
int	*lastkey;
X{
X	int	xx, yy;			/* Temp storage */
X	int	threat;			/* If there is a threat... */
X	int	dist;			/* Distance from 'mark' */
X	int	key;			/* Code to be returned */
X	static	int	list[10] = {'1','4','7','8','9','6','3','2',0 };
X	static	int	conv[10] = {'9','6','3','2','1','4','7','8',0 };
X
X		/* See if it's ok to hunt bases, energy must be full */
X
X	if (ship->energy > (e_require[ship->type] - (e_require[ship->type]/5))) { /* Full? */
X		xx = x; yy = y;
X		key = findobj(&xx, &yy, &dist, BASE, BASE, window);
X		if (key) {		/* Oh boy!  I see a base! */
X			if (dist < 3) {
X				for (xx = 0; xx < 9; xx++) {	/* Back off! */
X					if (list[xx] == key) {
X						*lastkey = conv[xx];
X						return(conv[xx]);
X					}
X				}
X			} else {
X				if (dist > 6) {			/* Move in */
X					*lastkey = key;
X					return(key);	/* Return move code */
X				}
X				*lastkey = 'L';		/* Shoot it! */
X				return('L');		/* And out */
X			}
X		}
X	}
X	xx = x; yy = y;
X	key = findobj(&xx, &yy, &dist, 'A', 'Z', window);
X	if (!key) {				/* There is a ship in range */
X		if (ship->wstatus & SHIELD_UP)
X			return('s');		/* Drop shields */
X	} else {
X		if (!(ship->wstatus & SHIELD_UP)) {
X			if (dist > 4) {		/* If a good distance */
X				if ((ship->energy > (e_require[ship->type] / 5)) &&
X				(ship->numtorps) && (ship->torps) &&
X				(roll(dist - 4) > 1))
X					return('t');	/* Fire torpedoes at ship */
X			}
X			if (!(ship->wstatus & SHIELD_DEAD)) {	/* Not dead */
X				return('s');		/* Raise shields! */
X			}
X		}
X		if (ship->energy > (e_require[ship->type] / 5)) {/* Attack! */
X			if (roll(dist) > 2) {	/* If we outroll it */
X				*lastkey = key;
X				return(key);	/* Move in */
X			} else {
X				*lastkey = 'l';
X				return('l');	/* Else shoot! */
X			}
X		} else {
X			for (xx = 0; xx < 9; xx++) {
X				if (list[xx] == key) {
X					*lastkey = conv[xx];
X					return(conv[xx]);
X				}
X			}
X		}
X	} 	/* There is no ship in range to attack or run from */
X	if (ship->energy < (e_require[ship->type] / 5)) {/* If low on power */
X		xx = x; yy = y;
X		key = findobj(&xx, &yy, &dist, BASE, BASE, window);
X		if (key) {
X			if (dist == 1) {
X				*lastkey = 'D';
X				return('D');		/* Dock */
X			} else
X				return(key);		/* Go to the base */
X		}
X	}
X	if (ship->energy < (e_require[ship->type] / 5) 	/* Need to build here */
X		xx = x; yy = y;
X		key = findobj(&xx, &yy, &dist, PLANET, PLANET, window);
X		if (key) {
X			if (dist == 1)
X				return('B');		/* Build */
X			else
X				return(key);		/* Go to the planet */
X		}
X	}		/* Otherwise power is ok */
X	if (*lastkey == 'D') {	/* If docked... */
X		if (ship->energy != e_require[ship->type])
X			return('D');	/* Continue if not full */
X		else {
X			*lastkey = 0;
X			return(0);
X		}
X	}
X	return(*lastkey);
X}
END_OF_FILE
if test 4177 -ne `wc -c <'makechoice.c'`; then
    echo shar: \"'makechoice.c'\" unpacked with wrong size!
fi
# end of 'makechoice.c'
fi
if test -f 'mines.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mines.c'\"
else
echo shar: Extracting \"'mines.c'\" \(1503 characters\)
sed "s/^X//" >'mines.c' <<'END_OF_FILE'
X/*	Put a mine in someone's way :-)   */
X
X#include	"cosmos.h"
extern	char	*buffer;
extern	int	drone;
extern	struct	nameblock	*ship;
X
extern	int	window;
extern	void	givedamage();
X
mines(semid, x, y)
int	semid;
int	x, y;
X{
X
X	
X	struct	grid	ourgrid;
X	int	xx = 0, yy = 0;
X	int	key = 0;
X
X	if ((ship->mines < 30) || (ship->wstatus & MINE_DEAD))
X		return(0);			/* Weapon is dead */
X	if (ship->nummines <= 0) {
X		mvaddstr(23,20,"No more mines on board!");
X		clrtoeol();
X		return(0);
X	}
X	mvaddstr(15,59,"Mines.... ARMED");
X	clrtoeol();
X	mvaddstr(22,20,"Mines (1) -> ");
X	clrtoeol();
X	release(semid);
X	refresh();
X	key = getchx();
X	acquire(semid);
X	switch(key) {
X		case '8':
X			xx = 0;
X			yy = 1;
X			break;
X		case '9':
X			xx = 1;
X			yy = 1;
X			break;
X		case '6':
X			xx = 1;
X			yy = 0;
X			break;
X		case '3':
X			xx = 1;
X			yy = -1;
X			break;
X		case '2':
X			xx = 0;
X			yy = -1;
X			break;
X		case '1':
X			xx = -1;
X			yy = -1;
X			break;
X		case '4':
X			xx = -1;
X			yy = 0;
X			break;
X		case '7':
X			xx = -1;
X			yy = 1;
X			break;
X	}
X	if ( ((x + xx) >= SIZE) || ((x + xx) < 0) || ((y + yy) >= SIZE) || ((y + yy) < 0))
X		return(0);
X	readgrid((x + xx), (y + yy), &ourgrid);
X	if (ourgrid.type != EMPTY) {
X		mvaddstr(23,20,"EMERGENCY OVERRIDE!  That space is not empty!");
X		clrtoeol();
X		return(0);
X	}
X	ourgrid.type = MINE;
X	ourgrid.energy = MINE_ENERGY;		/* Low value deliberately */
X	ourgrid.shield = 0;
X	ourgrid.hit = 0;
X	storegrid((x + xx), (y + yy), ourgrid);	/* Save it */
X	ship->nummines--;			/* Laid one */
X	return(0);
X}
END_OF_FILE
if test 1503 -ne `wc -c <'mines.c'`; then
    echo shar: \"'mines.c'\" unpacked with wrong size!
fi
# end of 'mines.c'
fi
if test -f 'modgame.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'modgame.c'\"
else
echo shar: Extracting \"'modgame.c'\" \(4582 characters\)
sed "s/^X//" >'modgame.c' <<'END_OF_FILE'
X/*	Modgame - change game parameters */
X
X#include	"cosmos.h"
X
extern	int	extx, exty;
X
modgame(semid)
int	semid;
X{
X
X	struct	grid	ourgrid;
X	struct	nameblock	ourname;
X	int	key;
X	char	tmp[80];
X	int	xx, yy, x, y;
X
X	release(semid);
X	mvaddstr(23,20,"Modify <G>rid, <S>hip, <F>ind or <T>eleport > ");
X	clrtoeol();
X	refresh();
X	key = toupper(getchx());
X	switch (key) {
X		case 'T':
X			mvaddstr(23,20,"Teleport to -> ");
X			clrtoeol();
X			refresh();
X			echo();
X			get_str(tmp);
X			noecho();
X			if (!tmp[0]) {
X				acquire(semid);
X				return;
X			}
X			if (sscanf(tmp, "%d %d", &xx, &yy) != 2) {
X				acquire(semid);
X				return;
X			}
X			acquire(semid);
X			readgrid(xx, yy, &onegrid);
X			if (onegrid.type != EMPTY) {
X				mvaddstr(23,20,"Space not empty");
X				clrtoeol();
X				refresh();
X				sleep(2);
X				return;
X			}
X			readgrid(extx, exty, &onegrid);
X			storegrid(xx, yy, onegrid);
X			onegrid.type = EMPTY;
X			onegrid.energy = 0;
X			onegrid.shield = 0;
X			storegrid(extx, exty, onegrid);
X			extx = xx;
X			exty = yy;
X			break;
X		case 'F':
X			mvaddstr(23,20,"Find what -> ");
X			clrtoeol();
X			refresh();
X			key = toupper(getchx());
X			if (!key) {
X				acquire(semid);
X				return;
X			}
X			move(23,40);
X			printw("Find %c", key);
X			refresh();
X			for (x = 0; x < SIZE; x++) {
X				for (y = 0; y < SIZE; y++) {
X					readgrid(x, y, &ourgrid);
X					if (ourgrid.type == key) {
X						move(23,40);
X						printw("Found at %d %d", x, y);
X						clrtoeol();
X						refresh();
X						sleep(5);
X						break;
X					}
X				}
X			}
X			acquire(semid);
X			break;
X		case 'G':
X			mvaddstr(23,20,"X Y coordinates > ");
X			clrtoeol();
X			refresh();
X			get_str(tmp);
X			if (tmp[0] == 0) {
X				acquire(semid);
X				return;
X			}
X			if (sscanf(tmp, "%d %d", &x, &y) != 2) {
X				mvaddstr(23,20,"Invalid coordinates");
X				clrtoeol();
X				acquire(semid);
X				return;
X			}
X			if ((x < 0) || (y < 0) || (x >= SIZE) || (y >= SIZE)) {
X				mvaddstr(23,20,"Invalid coordinates");
X				clrtoeol();
X				acquire(semid);
X				return;
X			}
X			readgrid(x, y, &ourgrid);
X			move(22,20);
X			printw("Type = %d, E = %d, Shield = %d", ourgrid.type, ourgrid.energy, ourgrid.shield);
X			clrtoeol();
X			mvaddstr(23,20,"New type (`.,@*+) > ");
X			clrtoeol();
X			refresh();
X			key = getchx();
X			acquire(semid);
X			ourgrid.type = EMPTY;
X			switch(key) {
X				case '.':
X				case ' ':
X					ourgrid.type = EMPTY;
X					ourgrid.shield = 0;
X					ourgrid.energy = 0;
X					break;
X				case '@':
X					ourgrid.type = PLANET;
X					ourgrid.shield = 0;
X					ourgrid.energy = 10000000L;
X					break;
X				case '*':
X					ourgrid.type = STAR;
X					ourgrid.shield = 0;
X					ourgrid.energy = 20000000L;
X					break;
X				case ',':
X					ourgrid.type = MINE;
X					ourgrid.energy = 5L;
X					ourgrid.shield = 0;
X					break;
X				case '`':
X					ourgrid.type = ASTEROID;
X					ourgrid.energy = 500000L;
X					ourgrid.shield = 20;
X					break;
X				case '+':
X					ourgrid.type = BASE;
X					ourgrid.energy = 10000000L;
X					ourgrid.shield = 100;
X					break;
X			}
X			move(22,20);
X			printw("Type = %d, E = %d, Shield = %d", ourgrid.type, ourgrid.energy, ourgrid.shield);
X			mvaddstr(23,20,"Energy = ");
X			clrtoeol();
X			refresh();
X			get_str(tmp);
X			sscanf(tmp, "%d", &ourgrid.energy);
X			mvaddstr(23,20,"Shield = ");
X			clrtoeol();
X			refresh();
X			get_str(tmp);
X			sscanf(tmp, "%d", &ourgrid.shield);
X			storegrid(x, y, ourgrid);
X			break;
X		case 'S':
X			mvaddstr(23,20,"Ship letter> ");
X			clrtoeol();
X			refresh();
X			key = getchx();
X			for (x = 0; x < MAXSHIPS; x++) {
X				readname(x, &ourname);
X				if (ourname.token == key) {
X					move(23,20);
X					printw("Type = %d, E = %d, Sh = %d, Pts = %d", ourname.type, ourname.energy, ourname.shield, ourname.points);
X					clrtoeol();
X					mvaddstr(22,20,"New Type = ");
X					clrtoeol();
X					refresh();
X					get_str(tmp);
X					sscanf(tmp, "%d", &ourname.type); 
X					mvaddstr(22,20,"New E = ");
X					clrtoeol();
X					refresh();
X					get_str(tmp);
X					sscanf(tmp, "%d", &ourname.energy);
X					mvaddstr(22,20,"New Shield = ");
X					clrtoeol();
X					refresh();
X					get_str(tmp);
X					sscanf(tmp, "%d", &ourname.shield);
X					mvaddstr(22,20,"New Points = ");
X					clrtoeol();
X					refresh();
X					get_str(tmp);
X					sscanf(tmp, "%d", &ourname.points);
X					acquire(semid);
X					ourname.gods++;
X					storename(x, ourname);
X					for (x = 0; x < SIZE; x++) {
X						for (y = 0; y < SIZE; y++) {
X							readgrid(x, y, &ourgrid);
X							if (ourgrid.type == ourname.token) {
X
X								ourgrid.energy = ourname.energy;
X								ourgrid.shield = ourname.shield;
X								storegrid(x, y, ourgrid);
X							}
X						}
X					}
X					return(0);
X				}
X		}
X	}
X	return;
X}
END_OF_FILE
if test 4582 -ne `wc -c <'modgame.c'`; then
    echo shar: \"'modgame.c'\" unpacked with wrong size!
fi
# end of 'modgame.c'
fi
if test -f 'phasers.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'phasers.c'\"
else
echo shar: Extracting \"'phasers.c'\" \(2943 characters\)
sed "s/^X//" >'phasers.c' <<'END_OF_FILE'
X/*	Phaser/laser fire	- Part of the COSMOS universe
X
X	Copyright 1988 Karl Denninger & MCS, Inc.
X	All rights reserved
X
X*/
X
X#include	"cosmos.h"
X
extern	char	*buffer;
extern	int	drone;
extern	struct	nameblock	*ship;
X
extern	int	window;
extern	void	givedamage();
X
phasers(semid, x, y)
int	semid;
int	x, y;
X{
X
X	static	int	xx, yy;
X	static	int	x1, y1;
X	static	char	tmp[80];
X	static	char	tmp2[80];
X	
X	struct	grid	onegrid;
X	struct	grid	ourgrid;
X	char	args[40];
X	char	*arg[3];
X	long	edmg;
X	long	shiedmg;
X	int	hitperson;
X	struct	nameblock	onename;
X	int	dist;
X
X	if (ship->wstatus & LASERS_DEAD)
X		return(0);			/* Weapon is dead */
X	mvaddstr(14,59,"Lasers... ARMED");
X	clrtoeol();
X	mvaddstr(22,20,"Lasers -> ");
X	clrtoeol();
X	release(semid);
X	refresh();
X	get_str(args);
X	acquire(semid);
X	if (args[0]) 
X		strcpy(tmp2, args);
X	strcpy(tmp, tmp2);
X	if ((!isdigit(tmp[0])) && (tmp[0] != '-')) {
X		if (ship->type < 3) {	/* Small doesn't have lock */
X			mvaddstr(23,20,"We don't have weapons locking!");
X			clrtoeol();
X			return(0);
X		}
X		xx = x;
X		yy = y;
X		if (!findobj(&xx, &yy, &dist, toupper(tmp[0]), toupper(tmp[0]), window)) {	
X			mvaddstr(23,20,"Target not found");
X			clrtoeol();
X			return(0);
X		} else {
X			x1 = (xx - x);
X			y1 = (yy - y);
X		}
X	} else {
X		if ((arg[0] = strtok(tmp, ":, ")) == NULL) {
X			mvaddstr(23,20,"Requires two parameters");
X			clrtoeol();
X			return(0);
X		} else
X			x1 = atoi(arg[0]);
X		if ((arg[1] = strtok((char *) NULL, ":, ")) == NULL) {
X			mvaddstr(23,20,"Requires two parameters");
X			clrtoeol();
X			return(0);
X		} else
X			y1 = atoi(arg[1]);
X	}
X	if (((x + x1) < 0) || ((x + x1) >= SIZE) 
X		|| ((y + y1) < 0) || ((y + y1) >= SIZE)) {
X		mvaddstr(23,20,"Invalid coordinates");
X		clrtoeol();
X		return(0);
X	}
X	if ((x1 == 0) && (y1 == 0)) {
X		mvaddstr(23,20,"Silly -- you can't shoot yourself!");
X		clrtoeol();
X		return(0);
X	}
X	edmg = (int) ((800 + roll(700)) * ship->type) / sqr((x1 * x1) + (y1 * y1) + 1);
X	readgrid((x + x1), (y + y1), &ourgrid);		/* Anything there? */
X	if ((ourgrid.type != EMPTY) && (ourgrid.type != VOID)) {
X		readgrid(x, y, &ourgrid);
X		ship->energy -= (200 * ship->type);
X		ourgrid.energy -= (200 * ship->type);
X		storegrid(x, y, ourgrid);
X		givedamage((x + x1), (y + y1), edmg, ship, 0);	/* Give it damage */
X	}
X	return(0);
X}
X
cphasers(x, y, startobj, endobj)
int	x, y;
int	startobj, endobj;
X{
X
X	int	xx, yy;
X	int	dist;
X	int	go;
X	int	tmpx, dir;
X	int	edmg;
X	struct	grid	ourgrid;
X
X	if (ship->lasers < 30) {
X		if (roll(200) > ship->lasers)
X			return(0);
X	}
X	xx = x; yy = y;
X	dir = findobj(&xx, &yy, &dist, startobj, endobj, window);
X	if (dir == 0)
X		return(0);				/* No target in range */
X	if (dir) {
X		edmg = ((1000 + roll(700)) * ship->type) / sqr(((xx - x) * (xx - x)) + ((yy - y) * (yy - y)) + 1);
X		readgrid(x, y, &ourgrid);
X		ship->energy -= (200 * ship->type);
X		ourgrid.energy -= (200 * ship->type);
X		storegrid(x, y, ourgrid);
X		givedamage(xx, yy, edmg, ship, 0);	/* Give it damage */
X	}
X	return(1);
X}
END_OF_FILE
if test 2943 -ne `wc -c <'phasers.c'`; then
    echo shar: \"'phasers.c'\" unpacked with wrong size!
fi
# end of 'phasers.c'
fi
if test -f 'players.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'players.c'\"
else
echo shar: Extracting \"'players.c'\" \(348 characters\)
sed "s/^X//" >'players.c' <<'END_OF_FILE'
int addplayer(limited, timed, ac, av)
int	*limited;		/* Return, NZ = limited player */
int	*timed;			/* Return, NZ = timed player */
int	ac;			/* Count of arguments */
char	*av;			/* Second argument */
X{
X
X}
X
void delplayer(ac, av, start)
int	ac;			/* Count of arguments */
char	*av;			/* Second argument */
long	start;			/* Game start time */
X{
X
X}
END_OF_FILE
if test 348 -ne `wc -c <'players.c'`; then
    echo shar: \"'players.c'\" unpacked with wrong size!
fi
# end of 'players.c'
fi
if test -f 'rmseg.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rmseg.c'\"
else
echo shar: Extracting \"'rmseg.c'\" \(1430 characters\)
sed "s/^X//" >'rmseg.c' <<'END_OF_FILE'
X/*	Spacewar	- The final frontier
X
X	This package is Copyright 1988 Karl Denninger.  All rights reserved.
X	
X	All unauthorized mutants shall be destroyed, fed to vermin, and the
X	remains from this process will be prosecuted.
X
X*/
X
X/*	Definitions go below - Make sure you have these in front of include
X	files as these definitions should override the include files	*/
X
X
X#include	"cosmos.h"
X
struct	nameblock	name;
struct	grid		onegrid;
X
main()
X{
X	int	seg;			/* Shared segment number */
X	char	*buffer;		/* Buffer pointer */
X
X	int	size;
X	int	x, y;			/* X & Y coordinates of ship */
X	int	key;
X	int	quit = 0;		/* Halt variable */
X	int	tempint;
X	
X	struct	nameblock	namebuf;
X	long	game = (sizeof(onename) * MAXSHIPS) + sizeof(ccount) + 
X		(sizeof(onegrid) * MAXGRID) + (sizeof(onemsg) * MAXMSG);
X	size = (game);			/* Get size of game module */
X
X	printf("COSMOS Maintenance cleanup\n");
X	printf("Remove segment %s\n",VERSION);
X	if ((seg = shmget(122L, size, IPC_CREAT|0660)) == -1) {
X		perror("create");
X		puts("Cannot execute due to shared-segment create fault");
X		exit(1);
X	}
X	if (shmctl(seg, IPC_RMID, 0))  {
X		perror("destroy");
X		puts("Cannot delete segment");
X		exit(1);
X	}
X	if ((seg = semget(122L, 1, IPC_CREAT|0660)) == -1) {
X		perror("create");
X		puts("Cannot execute due to semaphore create fault");
X		exit(1);
X	}
X	if (semctl(seg, IPC_RMID, 0))  {
X		perror("destroy");
X		puts("Cannot delete semaphore");
X		exit(1);
X	}
X
X	exit(0);
X}
END_OF_FILE
if test 1430 -ne `wc -c <'rmseg.c'`; then
    echo shar: \"'rmseg.c'\" unpacked with wrong size!
fi
# end of 'rmseg.c'
fi
if test -f 'scan.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scan.c'\"
else
echo shar: Extracting \"'scan.c'\" \(2693 characters\)
sed "s/^X//" >'scan.c' <<'END_OF_FILE'
X/*	Cosmos	- A game of the cosmos		*/
X
X#include	"cosmos.h"
extern	char	*buffer;
extern	struct	nameblock	*ship;
X
scan(semid, x, y, window)
int	semid, x, y;
int	window;
X{
X
X	int	xx, yy;
X	int	z = 0, zx;
X	int	dist;
X	int	key;
X	struct	grid	ourgrid;
X	struct	nameblock	name;
X	int	vector;
X
X	release(semid);
X	mvaddstr(22,20,"Scan object -> ");
X	refresh();
X	key = getchx();
X	acquire(semid);
X	if ((key == 10) || (key == 13) || (key == 0))
X		return(0);
X	else {
X		xx = x; yy = y;
X		vector = findobj(&xx, &yy, &dist, key, key, window_size[ship->type]);
X		if (vector == 0) {
X			mvaddstr(23,20,"No object found");
X			clrtoeol();
X			return(0);		/* Nothing to scan */
X		}
X		readgrid(xx, yy, &ourgrid);
X		for (zx = 1; zx < 17; zx++) {
X			mvaddstr(zx, 44, "                ");
X		}
X		if ((ourgrid.type >= 'A') && (ourgrid.type <= 'Z')) {
X			name.token = key;
X			z = locship(&name, 1);
X			readname(z, &name);
X			name.scanned++;
X			storename(z, name);
X			move(1,44);
X			printw("'%c', a %s", name.token, shiptypes[name.type]);
X			clrtoeol();
X			move(2,49);
X			z = name.energy;
X			printw("%9ld", z);
X			move(3,49);
X			printw("%9d", (name.engines + roll(20) - 10));
X			move(4,49);
X			printw("%9d", (name.lasers + roll(20) - 10));
X			move(5,49);
X			if ((ship->wstatus & MINE_DEAD) == 0)
X				printw("%9d", (name.mines + roll(20) - 10));
X			else
X				addstr("         ");
X			move(6,49);
X			if ((ship->wstatus & TORPEDO_DEAD) == 0)
X				printw("%9d", (name.torps + roll(20) - 10));
X			else
X				addstr("         ");
X			move(7,49);
X			printw("%9d", (ourgrid.shield + roll(20) - 10));
X			move(8,49);
X			printw("%9d", (name.crew + roll(20) - 10));
X			move(9,49);
X			printw("%9d", (name.life + roll(20) - 10));
X			move(10,49);
X			printw("%9d", (name.hull + roll(20) - 10));
X			move(13,49);
X			if (name.wstatus & SHIELD_DEAD)
X				addstr("INOPER.");
X			else {
X				if (name.wstatus & SHIELD_UP)
X					addstr("UP       ");
X				else
X					addstr("DOWN     ");
X			}
X			clrtoeol();
X			move(14,49);
X			if (name.wstatus & LASERS_DEAD)
X				addstr("INOPER.");
X			else {
X				if (name.wstatus & LASERS_LOCK)
X					addstr("LOCKED     ");
X				else
X					addstr("STBY       ");
X			}
X			move(15,49);
X			if (name.wstatus & MINE_DEAD)
X				addstr("          ");
X			else {
X				if (name.wstatus & MINE_LOCK) 
X					addstr("LOCK");
X				else
X					addstr("STBY");
X				printw("/%d", name.nummines);
X			}
X			move(16,49);
X			if (ship->wstatus & TORPEDO_DEAD)
X				addstr("          ");
X			else {
X				if (ship->wstatus & TORPEDO_LOCK)
X					addstr("LOCK");
X				else
X					addstr("STBY");
X				printw("/%d", name.numtorps);
X			}
X		} else {
X			move(2,49);
X			z = ourgrid.energy; 
X			printw("%9ld", z);
X			move(7,49);
X			printw("%9d", ourgrid.shield);
X		}
X	}
X	return(1);
X}
X
END_OF_FILE
if test 2693 -ne `wc -c <'scan.c'`; then
    echo shar: \"'scan.c'\" unpacked with wrong size!
fi
# end of 'scan.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 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

--
Karl Denninger (karl@ddsw1.MCS.COM, ddsw1!karl)
Data: [+1 312 566-8912], Voice: [+1 312 566-8910]
Macro Computer Solutions, Inc.    	"Quality solutions at a fair price"

karl@ddsw1.MCS.COM (Karl Denninger) (11/18/88)

Part 2 of 3, see part 1 for details.

#! /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 3)."
# Contents:  Help cosmos.h drone.c torpedoes.c
# Wrapped by karl@ddsw1 on Thu Nov 17 23:53:07 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Help' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Help'\"
else
echo shar: Extracting \"'Help'\" \(13308 characters\)
sed "s/^X//" >'Help' <<'END_OF_FILE'
X************************ COSMOS On-Line Assistance **************************
X
Note: If your screen is "screwed up" your terminal type is set incorrectly.
X
X       Numeric				    Celestial Objects on Grid
X	-Pad-				
X					@ - Planet	A-Z - Spaceship 
X	7 8 9				* - A Star	      (Computer or Man)
X	4 5 6   <<< Move in 		` - A Asteroid  +   - StarBase
X	1 2 3       direction		, - A Mine      .   - Empty Space
X						A Void is a "space"
b - Broadcast message 
l - Fire Lasers
m - Lay a Mine 
t - Fire a Torpedo			+ - Add another enemy ship to game
s - Raise/lower (toggle) shields
X
A - Set your alliance (unimpl.)		M - Move on autopilot to coordinates 
B - Build a base on a planet 		N - Change ship's name (if docked)
C - Capture an object (unimplemented)	P - Players in game (docked) or status
D - Dock with a starbase		Q - Quit (save if GREEN status)
R - Disable/Enable Ramming protection	S - Scan an object in view
X
X
Movement:
X
X	Basic Movement is done with the numeric keypad.  Some ships can "home" 
X	in on a given coordinate using the "M" command.  This command will 
X	only function in ships which include it as part of their navigation 
X	subsystem (first available on the Frigate).
X
X	The coordinate grid is layed out in x, y, with the 'x' axis being
X	the horizontal.  Your current position is always displayed in the
X	lower left corner of the playscreen.
X
X	The "M" (capital 'm') command will take you to a destination at
X	best-rate-of-travel speed if your ship is equipped with an autopilot
X	(small ships lack the machinery).  The autopilot is intelligent
X	enough to stop the ship if there is an obstruction you would
X	otherwise impact with, but not intelligent to steer around it
X	automatically.  Enter the destination coordinates when you use the
X	"M" command with a single space or tab between them, "X" first.
X
X	A "M" command entered without coordinates will use the last stored 
X	destination position.
X
X
Shields:
X	
X	These consume energy when in use.  When your shields are up,
X	the shields will take the damage (in percent operability) before
X	your main energy stores and the remainder of the ship are affected.
X	If your shield level drops to zero or below, your shields will
X	be "blown down" and you will suffer damage from this as well as the
X	hit which causes the shields to drop (as they are no longer functional).
X
X	Shields provide some protection against collisions.
X
X	You may not be able raise your shields if they are below 30% efficiency.
X
X
XEnergy:
X
X	If you run out you're dead.  Don't allow this to happen.  The best
X	way to get more energy is to dock with a starbase.  See "building
X	bases" for information on this.
X
X	Some energy is used to maintain the ships' functions.  An additional
X	amount if required whenever you move, when you use shields or weapons,
X	or when you build upon a planet.
X
X
Building Bases:
X
X	To build a base, a player moves next to a planet and uses the "B"
X	command.  You will be asked for a direction, enter the key on the
X	keypad (numeric) corresponding to the direction of the planet you
X	wish to build upon.
X
X	10 Builds are required to create a base, and each one requires 500
X	Energy units from your ship.
X
X
Lasers:
X	
X	Lasers are fired with the 'l' key.  You must aim these weapons at
X	the position you wish to hit _relative_ to your current location, or
X	in ships which have targeting (anything larger than a courier) you
X	may aim by ship name.  Thus, to hit an object at 102, 100 if you 
X	are at 100, 100 would require a "laser" coordinate entry of "2 0".
X
X	Larger ships have more powerful lasers.
X
X	Note that either an object's letter (case is irrelavent) or the
X	relative coordinates must be entered at the prompt, followed by
X	<return>.  A null (ie: return only) entry will use the last entered
X	coordinates or ship to target on.
X
X
Projectiles:
X
X	Torpedoes move at a reasonable rate -- you may be able to outrun
X	them.  Torpedoes also have a definite range dependant on the 
X	launcher's guidance capabilities, at which point they automatically 
X	detonate regardless of whether they are in range of a target.
X
X	Torpedoes explode on impact with any other object in the game.  
X	
X	All torpedoes are guided by the "parent" ship which fires it.  As a
X	result, if the parent ship should die, the torpedo will cease
X	activity (effectively be "dead).  The torpedo does carry limited
X	detection facilities in it's nose, as will "track" or home in on a
X	target if it is not specified in absolute terms.  Small ships have 
X	an "in flight" torpedo limit due to their limited computer resources 
X	for guidance.
X	
X	To fire a torpedo, enter either the ship's letter or the relative
X	coordinates to fire upon, as with lasers.  As with lasers, a
X	<return> signifies to repetitively fire at the same target.
X
X	Scout ships do not possess torpedoes.
X
X
Mines:
X	
X	Intersteller mines are extremely dangerous.  They are difficult to 
X	spot and impossible to trace, and they will explode if they take any
X	damage at all (ie: if you shoot it).  Clusters of mines will 
X	chain-detonate; this will produce a very spectacular explosion (not 
X	to mention killing nearly any ship nearby).  Mines are not detected
X	by one's "collision avoidance" system, and as a result you can
X	easily run into one or more without warning.
X
X	Note that once in a while a mine will be in your "kit" that has much
X	more explosive power than normal.  These are termed "nuclear" mines;
X	you cannot detect a difference until they are detonated.
X
X	Mines are first available to Frigates.
X
X
Ramming objects:
X
X	Your computer will not allow you to run into solid objects unless
X	you specifically override this safety feature.  To turn on the
X	override, and permit ramming, press <R>.  You may press this key
X	again to disable the override when you are done with it.
X
X	This is intended to permit intentional ramming operations, but
X	prevent accidental death due to collisions with solid objects.
X
X	Note that the override on your movement expends some energy stopping
X	your ship before it impacts with the object you would otherwise ram.
X
X
Special weaponry:
X
X	There may be special functions only available to the largest class
X	ships.  The use of these functions is not documented, but there are
X	rumors that one of them is a planet-destroying weapon.
X
X	Hints will be given to you if you are fortunate when completing a base.
X
X
XExplosions:
X	
X	Expect to take *HEAVY* damage from things that explode near you.  If
X	you are unfortunate enough to be next to an object that is destroyed,
X	you will suffer the equivalent damage of several large laser (or 
X	multiple) torpedo hits.  Many ships will be destroyed by these 
X	occurances.  Bases, planets, stars, and large ships will do damage 
X	beyond the immediate neighbor sectors when they detonate.
X
X	Be especially careful if you are near multiple sources of explosion
X	-- it is possible to have a chain-reaction established and suffer
X	multiple hits in this case.  Such occurrances are nearly always fatal.
X
X	Your shields are effective against explosion forces up to a point.
X
X
Combat:
X	
X	You will be informed via a "beep" and a message on the bottom line
X	of your screen, as well as your token "flashing", whenever you
X	suffer an attack.  The source of the attack is not necessarially
X	known to you, although you can probably take a good guess from the
X	magnitude of the hit.
X
X	The first time you fire on a base it will send a distress message.
X	Bases will also use their very last dying gasps to tell the universe
X	you have blown them to smithereens, so you can expect a message when
X	this occurs as well.
X
X	Weapons fire is "sticky"; that is, once you enter a coordinate to
X	shoot at you may just press <return> at the coordinate prompt to
X	fire at the same relative location.  This "sticky" power is retained
X	even if you move the vessel.  NOTE THAT COORDINATES ENTERED FOR
X	WEAPONS MUST - MUST - MUST BE RELATIVE TO YOUR CURRENT LOCATION.
X
X	Any item which explodes will be detected by your ships' sensor, and
X	the coordinates of the explosion will be displayed on the message
X	screen.  Novas and planetary destruction are so spectacular as to be
X	unmistakable for other explosions, and are so noted.
X
X
Black Holes:
X	
X	Occasionally you may see an "empty" space on the game grid.  These
X	are "black holes".  There are a few found at random locations
X	throughout the galaxy, and exploding stars will also create these
X	anomolies.
X
X	Moving into a sector containing a black hole will cause your ship to
X	be instantly transported to another location on the game grid.  The
X	"white hole" on the other side is always consistantly placed once
X	the black hole has been created.
X
X
General Weaponry & Player Notes:
X
X	When you shoot something, or it explodes, you will see the area
X	affected by the act light up in reverse video (providing your
X	terminal supports this option).  
X
X	Note that the computer may be playing and number of ships while you
X	are in the game.  These are indistinguishable from human players,
X	and they play be the same rules you do.  Pay particular attention 
X	to a ships' size, as these ships come in all sizes and dispositions.
X	The admininistrator can set the maximum number of computer players 
X	which can be in the game as well as their rate of replenishment.  
X	It is completely possible for the computer ships to gang up on the 
X	human player(s). (Hint: Computer ships operate on energy just as you 
X	do, and must dock as well).
X
X	The message area (the 4 lines on the bottom right side of the screen) 
X	is a "windowed radio" of sorts.  Operating on sub-light frequencies, 
X	it is a limited-bandwidth device, that is to say, rapid events may 
X	overload it's reception and display capacity.  If this occurs the 
X	message(s) which overload the capacity of the internal buffering are 
X	lost without a trace.
X	
X	All other things being equal, a small ship is faster than a large
X	one due to inertia.  The game enforces this by parceling out movement
X	windows differently for the different classes of ships.
X
X
X
Combat Hints:
X
To Survive Combat (victoriously, of course):
X
X1) Use the power of items near you, yet be wary of it.  Be aware that a ship
X   or other object which detonates near you will likely damage you heavily.
X   Large ships', planets, and stars' detonations will be _fatal_ if you are 
X   too close to the object when it explodes.
X2) Put up your shields when hostilities are imminent.  They only help you if
X   they are raised.  However, do not leave them up unnecessarially, as
X   shields are a heavy drain on your energy resources.  Computer ships will
X   _always_ raise their shields when in your company if they are operational.
X   Note that if your shields get to below 30% efficiency, your control
X   circuits may malfunction, making it impossible to lower _or_ raise shields.
X   To avoid this drop your shields before you go below 30% shield efficiency.
X3) Make use of the explosive potential in starbases if you surprise a enemy 
X   ship and it is docked with one.  Undock and move away IMMEDIATELY if you 
X   are attacked while docked, or if the base you are docked with is attacked 
X   by hostile fire.
X4) Be aware that different class ships have different scanner sensitivities,
X   and that you may be seen before you can see your opponent and vice-versa.
X   As a correlary of this, if you can't see what's firing on you, it's
X   almost certainly larger than you are.
X5) Keep an eye on your secondary resources (percentage damage display), as
X   well as energy.  Abort your combat if any of your critical parameters is
X   near the failing level.  Shields are especially important, as they absorb 
X   hits that would otherwise damage your ship's other components.
X6) Learn to fire bursts of weapons.  This is done by moving to position,
X   keying the initial fire command with appropriate parameters, then
X   re-keying only the command portion to fire again at the same location.
X   Use EXTREME caution when doing this with lasers to prevent running out 
X   of energy!
X7) Use the scanners to determine whether a ship you are attacking is weaker
X   than you are, comparable, or much stronger.  Don't be afraid to run from
X   attacks from ships of unknown strength!
X8) Be wary of allowing your "operability percentages" to drop below 30
X   percent.   Your controls may malfunction in this circumstance; you may be
X   unable to raise (or lower!) your shields, fire weapons, or even move! 
X
Note that you only get points for what you actively damage.  Forcing someone
into a planet will not gain you any Captains' points, while causing their
ship to explode from laser or torpedo fire certainly will.
X
Most damage which does not disable a resource (percent < 0) will be repaired
with time, even if you do not dock at a starbase.  Damage which results in an
item going below "0" will not be repaired until you dock, and the item
affected cannot be used.  Nearly all items which sustain damage leaving less
than 30 percent operability will have serious problems.  The following 
X"secondary" items are *ESSENTIAL* to operation of the ship; loss of any of 
these (below 0) will cost you your vessel.
X
X	Life support	- This one should be obvious (oxygen anyone?)
X	Crew		- Also obvious.  You're one of them :-)
X	Hull		- If it's zero, there isn't one.  In other words,
X			  your vessel is blown into a few thousand pieces.
X
X<Return> to continue
END_OF_FILE
if test 13308 -ne `wc -c <'Help'`; then
    echo shar: \"'Help'\" unpacked with wrong size!
fi
# end of 'Help'
fi
if test -f 'cosmos.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cosmos.h'\"
else
echo shar: Extracting \"'cosmos.h'\" \(7901 characters\)
sed "s/^X//" >'cosmos.h' <<'END_OF_FILE'
X/*	Cosmos		- The final frontier
X
X	This package is Copyright 1988 Karl Denninger.  All rights reserved.
X	
X	All unauthorized mutants shall be destroyed, fed to vermin, and the
X	remains from this process will be prosecuted.
X
X*/
X
X/*	Definitions go below - Make sure you have these in front of include
X	files as these definitions should override the include files	*/
X
X#include	<values.h>	/* Gots to have this */
X
X#undef	NO_RDCHK			/* Define if not Xenix or if
X					   you have problems with input 
X					   disappearing when typed ahead */
X
X#define	MAXSHIPS	20		/* Max players */
X#define	HOMEDIR		home		/* Home directory */
X#define	HOME		"/etc/cosmos/"	/* Home pointer file */
X#define	SIZE		200		/* Grid size (each) */
X#define	MAXNAME		20		/* Ship name max length */
X#define MAXFTORPS	10		/* Max free torps per ship */
X#define	TIME_PER_EUNIT	20		/* Time per energy in turns at rest */
X#define	TIME_PER_MSG	100		/* Time for message expiration */
X#define	MINE_ENERGY	5L		/* Energy for a mine */
X#define	EPERSHIELD	100		/* Energy per shield point */
X#undef	ACCOUNTING			/* Accounting features enabled? */
X
X#undef	RETIRE_MSGS			/* Don't kill msgs */
X#undef	FASTMATH			/* We have a fast sqrt routine */
X
X/* All of these constants are per ship type, which means they get multiplied
X   when used.  This is especially important with energy adjustments; be fair! */
X
X#define	E_PER_MOVE	30		/* Energy per move square */
X#define	E_RAND_PER_MOVE	5		/* Random influence per move */
X#define	EADD		75		/* Number always added w/docked */
X#define	RANDADD		80		/* Random number added w/docked */
X#define	NUKECHANCE	200		/* One in 200 mines is a nuke */
X
X/*	Having a thing explode counts as EXPLOSION * HIT TYPE points of
X	explosive energy which must be dissipated.  Some, of course, by
X	the person impacted.... :-)
X*/
X
X#define	EXPLOSION	10000		/* Base explosion energy dissipated */
X#define	TORP_EREL	800		/* Base torpedo energy released */
X
X#define	SHIP_DEATH	1		/* Ship explosion ( X type) */
X#define	MINE_BOOM	2		/* Mine explosion */
X#define	BASE_DEATH	4		/* This is not good :-) */
X#define	NUKE_MINE	12		/* Nuclear mine blast */
X#define	BIG_BOOM	18		/* A planet blowing up! */
X#define	NOVA		40		/* Uh, don't ask */
X
X#define	NAP				/* System has short sleep if defined */
X#define	NAPTIME		250		/* Time in ms for sleep ifdef NAP */
X#define	SLEEPTIME	1		/* Time in sec for sleep ifndef NAP */
X
X/* Some constants below, tune these for personal preference */
X  
X#define	SHIELD_COST	4		/* Cost per turn per ship/shield type */
X#define BUILDCOST	500		/* Cost of a BUILD command */
X#define	BUILDTIME	2		/* Time in Seconds to execute a build */
X
X/* For inter-ship messages */
X
X#define	MAXMSG		6		/* Maximum messages in queue at once */
X#define	MSGLEN		40		/* Maximum length of each msg */
X
X/* The following are the definitions for the inanimate objects */
X
X#define	EMPTY		'.'				/* Empty place */
X#define	PLANET		'@'				/* Planetary body */
X#define	STAR		'*'				/* A star */
X#define	BASE		'+'				/* A Starbase planet */
X#define	NEGBASE		'-'				/* A negbase planet */
X#define	MINE		','				/* A Mine */
X#define	TORPEDO		'^'				/* A Torpedo */
X
X#define	VOID		' '				/* A void */
X#define	ASTEROID	'`'				/* Asteroid :-) */
X
X/*	END OF CONFIGURABLE SECTION -- DO NOT CHANGE BELOW HERE		*/
X
X
static	char	*shiptypes[20] = {		/* Names of ships */
X			"", "Scout", "Courier", "Frigate", "Miner", "Destroyer",
X			"Cruiser", "Battlestar", "Death Star", "Dreadnought",
X			"Marauder", "Flagship"
X		};
X
static	int	e_require[20] = {	/* Energy requirements/capacity */
X		0, 20000, 30000, 40000, 55000, 70000, 85000, 100000,
X		120000, 135000, 150000, 200000
X		};
X
static	int	pts[20] = {		/* Pts for Advancement */
X		0, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 
X		2560000, 5120000, 10240000, MAXINT
X		};
X
static	int	num_torps[20] = {		/* Number of torpedoes */
X		0, 0, 2, 5, 2, 5, 10, 15, 17, 20, 30, 35
X		};
X
static	int	num_ftorps[20] = {		/* Guidance control capacity */
X		0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
X		};
X
static 	int	num_mines[20] = {		/* Number of mines */
X		0, 0, 0, 2, 15, 5, 5, 15, 20, 25, 30, 40
X		};
X
static	int	window_size[20] = {		/* Screen window sizes */
X		10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20
X		};
X
X					/* Bit mask values for weapons */
X					/* THESE SHOULD NOT BE CHANGED */
X#define	SHIELD_UP	1		
X#define	SHIELD_DEAD	2		/* NOTE: Requires, due to entries, */
X#define	LASERS_LOCK	4		/*       32-bit integers to run    */
X#define	LASERS_DEAD	8
X#define	TORPEDO_LOCK	16
X#define	TORPEDO_DEAD	32
X#define	MINE_LOCK	64
X#define	MINE_DEAD	128
X#define	PLANET_KILLER	256		/* You have a planet killer */
X#define	CREATE_WORLDS	512		/* You can create planets */
X
static	int	weapons[20] = {		/* Weapons mask; must be here */
X		0,
X		MINE_DEAD,
X		MINE_DEAD,
X		0,
X		0,
X		MINE_DEAD,
X		MINE_DEAD,
X		0,			/* All normal weapons here */
X		0,
X		0,
X		PLANET_KILLER,
X		PLANET_KILLER|CREATE_WORLDS
X		};
X
X
X/* Standard include files */
X
X#include	<stdio.h>
X#include	<fcntl.h>
X#include	<errno.h>
X#include	<sys/types.h>
X#include	<sys/file.h>
X#include	<sys/ipc.h>
X#include	<sys/shm.h>
X#include	<curses.h>
X#include	<signal.h>
X#include	<string.h>
X#include	<math.h>
X#include	<ctype.h>
X#include	<pwd.h>
X
extern	struct	passwd	*getpwuid();
extern	char	*memcpy();
X
X#define	MAXGRID		SIZE * SIZE	/* DO NOT CHANGE */
X
struct torps {
X	char	inuse;		/* Torpedo in "use" */
X	int	level;		/* Torpedo 'level' for explosion */
X	int	x;		/* Torpedo 'x' coordinate */
X	int	y;		/* Torpedo 'y' coordinate */
X	int	destx;		/* Destination 'x' */
X	int	desty;		/* Destination 'y' */
X	int	homeship;	/* Home in on ship indicated if NZ */
X	int	travelled;	/* Sectors travelled */
X	int	life;		/* Life (in sectors) of torpedo w/o impact */
X	int	lastkey;	/* Last homing beacon direction */
X};
X
struct grid {			/* The play grid */
X	char	type;		/* Thing 'living' there */
X	short	shield;		/* Shield percentage at location */
X	int	energy;		/* Energy at location */
X	char	align;		/* Alignment */
X	char	hit;		/* Hit by fire flag */
X};
X	
X/*	Additional attributes
X	Ship type (1 char)
X	Weapon status (each weapon - bit mask inoperable/locked/standby)
X		Shields
X		Lasers
X		Torpedoes
X		Mines
X	Life support status (percentage)
X	Crew status (percentage)
X	Engines (percentage)
X	Hull (percentage)
X	Shields				
X*/
struct	nameblock {
X	char	name[MAXNAME];		/* Ships' christened name */
X	char	token;			/* Game token */
X	int	type;			/* Ship type */
X	int	wstatus;		/* Bit mask -- be careful! */
X	int	lasers;			/* Laser status */
X	int	torps;			/* Torpedo launchers */
X	int	mines;			/* Mine launchers */
X	int	life;			/* Life support */
X	int	crew;			/* Crew status */
X	int	engines;		/* Engine status */
X	int	hull;			/* Hull status */
X	int	shield;			/* Shield status */
X	long	energy;			/* Energy amount */
X	long	points;			/* Points awarded to date */
X	char	align;			/* Current alignment */
X	int	locked;			/* What you have locked on */
X	int	lockx;			/* 'X' coordinate of lock */
X	int	locky;			/* "Y" coordinate of lock */
X	int	numtorps;		/* Number of torpedoes */
X	int	nummines;		/* Number of mines */
X	int	scanned;		/* Have we been scanned? */
X	int	human;			/* Non-zero if a human player */
X	int	gods;			/* The gods have intervened */
X	int	uid;			/* The users' UID */
X};
X
struct	msgblock {
X	int	curmsg;			/* Current message number */
X	char	msgtext[MSGLEN*MAXMSG];	/* Message texts */
X};
X
X
struct gameseg 	{
X	int	ccount;					/* # of computers */
X	struct	nameblock	names[MAXSHIPS];	/* Name/ship blocks */
X	struct	grid		play[MAXGRID];		/* Play grid */
X	struct	msgblock	messages[MAXMSG];	/* Messages */
X};
X
X
struct	shiprecord	{
X	char	shipname[20];
X	int	type;
X	long	points;			/* Points */
X	int	uid;			/* User's UID entry */
X	int	x;			/* X & Y Coordinates Last time */
X	int	y;
X	long	energy;			/* Energy last saved */
X	int	notused1;		/* We will save 2 ints for later */
X	int	notused2;
X	int	notused3;
X	int	notused4;
X};
X
struct	nameblock	onename;
struct	grid		onegrid;
struct	msgblock	onemsg;
X
int	ccount;
X
END_OF_FILE
if test 7901 -ne `wc -c <'cosmos.h'`; then
    echo shar: \"'cosmos.h'\" unpacked with wrong size!
fi
# end of 'cosmos.h'
fi
if test -f 'drone.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'drone.c'\"
else
echo shar: Extracting \"'drone.c'\" \(13370 characters\)
sed "s/^X//" >'drone.c' <<'END_OF_FILE'
X/*	Spacewar	- The final frontier
X
X	This package is Copyright 1988 Karl Denninger.  All rights reserved.
X	
X	All unauthorized mutants shall be destroyed, fed to vermin, and the
X	remains from this process will be prosecuted.
X
X*/
X
X/*	Definitions go below - Make sure you have these in front of include
X	files as these definitions should override the include files	*/
X
X
X
X/*	This is the drone module -- it's a computer "player" */
X
X
X
X#include	"cosmos.h"
X
X
int	extx, exty;
char	*buffer;				/* Buffer pointer */
int	*intbfr;
int	numcomp;
char	home[128];				/* Home directory */
int	superuser, su2;				/* Uid of the superuser */
int	window;					/* Window size, must be < 20 */
int	foundchar = 0;				/* Found character? */
int	oldchar;				/* Old character if one */
struct	nameblock	*ship;			/* Pointer to ship's data */
struct	nameblock	name[MAXSHIPS];
struct	grid		onegrid;
struct	grid		oldgrid;
int	quit;					/* Halt variable */
X
int	squares[SIZE];
X
int	drone = -1;				/* This is a drone ship */
X
main(argc, argv)
int	argc;
char	*argv[];
X{
X
X	static	long	points;		/* Points accumulated */
X	static	int	type;		/* Class of ship */
X	char	shipname[40];
X	
X	int	shipcount = 0;
X	int	bypass;
X	int	slept = 0;		/* Was I sleeping a minute ago? */
X	int	humans = 0;		/* Number of human players */
X	int	humancount = 0;		/* Human count (turns) */
X	int	ntfree = 0;		/* Number of torpedoes free */
X	int	docked = 0;
X	int	tmpint;			/* Temp integer */
X
X	int	seg;			/* Shared segment number */
X	
X	int	status;			/* Status (ok/not ok) */
X	int	qcount = 0;		/* Quit counter */
X	int	energy_count = 0;	/* Temporary iterative counter */
X	int	stale_msg = TIME_PER_MSG;/* Stale message count */
X	int	tempenergy;
X	long	size;
X	int	x, y;			/* X & Y coordinates of ship */
X	int	oldx, oldy;
X	int	key;
X	int	tempint = 0;
X	double	dist;			/* Distance between two points */
X
X	static	int	delta_x	= 0;	/* Initial delta 'x' */
X	static	int	delta_y = 0;	/* Initial delta 'y' */
X
X	int	semid;
X	int	flags;
X	char	tempstr[80];		/* 80 Character string */
X	char	tempstr2[80];		/* 80 Character string */
X	char	tmp[80];
X	FILE	*fid;
X	int		lastkey = 0;
X
X	struct	nameblock	namebuf;
X	struct	torps	torparray[MAXFTORPS];
X					/* Array of torpedo coords */
X
X	long	game = sizeof(ccount) + (sizeof(onename) * MAXSHIPS) + 
X			(sizeof(onegrid) * MAXGRID) + (sizeof(onemsg) * MAXMSG);
X
X	size = (game);			/* Get size of game module */
X
X	printf("Cosmos DRONE V%s\n", VERSION);
X	printf("Copyright 1988 MCS Inc. & Karl Denninger\n");
X	fflush(stdout);
X	for (x = 0; x < SIZE; x++)
X		squares[x] = (x * x);
X	sprintf(tmp, "%s", HOME);
X	if ((fid = fopen(tmp, "r")) != NULL) {
X		fscanf(fid, "%s %d %d %d", home, &superuser, &su2, &numcomp);
X		fclose(fid);
X	}
X	if ((seg = shmget(122L, size, 0660)) == -1) {
X		perror("create");
X		puts("Cannot execute due to shared-segment create fault");
X		exit(1);
X	}
X	if ((buffer = shmat(seg, (char *) NULL, 0)) == (char *) -1) {
X		perror("attach");
X		puts("Cannot execute due to shared-segment attach fault");
X		exit(1);
X	}
X	if ((semid = semget(122L, 1, 0660)) == -1) {
X		if ((semid = semget(122L, 1, 0660)) == -1) {
X			perror("semaphone create");
X			exit(1);
X		}
X	} else {
X		acquire(semid);
X	}
X	signal(SIGINT, SIG_IGN);		/* Ignore ^C */
X	readgrid(0, 0, &onegrid);
X	if (onegrid.type == 0) {
X		puts("No grid, exiting....\n");
X		release(semid);
X		exit(1);
X	}
X	intbfr = (int *) buffer;
X	srand((unsigned) time ((long *) 0L));
X	if (((int) *intbfr ) >= numcomp) {
X		puts("All computer players in, exiting");
X		release(semid);
X		exit(1);
X	}
X	*intbfr += 1;				/* Increment one */
X	ship = (struct nameblock *) getcship(semid, &x, &y);/* Get token */
X	if ((x == 0) && (y == 0)) {
X		x = roll(SIZE); 
X		y = roll(SIZE);
X	}
X	window = window_size[ship->type];
X	sprintf(tmp, "Welcome %s (%c)", ship->name, ship->token);
X	putmsg(tmp);
X
X/*	Now place the computer's ship in the game.  	*/
X	
X	quit = 0;
X	tempint = 0;
X	while (quit == 0) {
X		readgrid(x, y, &onegrid);
X		if (onegrid.type == EMPTY) 
X			quit++;
X		else {
X			x = roll(SIZE); y = roll(SIZE);
X			tempint++;
X			if (tempint >= 200) {
X				release(semid);
X				puts("Cannot place ship!");
X			}
X		}
X	}
X	onegrid.type = ship->token;
X	onegrid.shield = ship->shield;
X	onegrid.energy = ship->energy;
X	onegrid.align = 0;			/* Neutral alignment */
X	ship->human = 0;			/* Android player */
X	storegrid(x, y, onegrid);
X	quit = 0;
X	while (quit == 0) {
X
X/* Move torpedoes */
X		movetorps(torparray, &ntfree);
X		readgrid(x, y, &onegrid);
X		if (onegrid.type == EMPTY) 	/* If we got killed */
X			quit++;			/* Exit at end of pass */
X
X/* Insert here any routines which should be performed after each turn --
X   specifically, those things which take energy when engaged such as shields */
X		
X		energy_count--;
X		if (energy_count < 0) {
X			energy_count = TIME_PER_EUNIT;
X			onegrid.energy += 500;
X			ship->energy += 500;
X		}
X#ifdef	RETIRE_MSGS
X		if (stale_msg-- <= 0) {
X			putmsg("");
X			stale_msg = TIME_PER_MSG;
X		}
X#endif
X		if (ship->wstatus & SHIELD_UP) {
X			onegrid.energy -= (ship->type * SHIELD_COST);
X			docked = 0;		/* Undock the craft */
X		}
X		if (ship->energy > onegrid.energy)
X			ship->energy = onegrid.energy;
X		if (ship->shield > onegrid.shield)
X			ship->shield = onegrid.shield;
X		if (ship->shield <= 30) {
X			ship->wstatus &= ~(SHIELD_UP);
X			ship->wstatus |= SHIELD_DEAD;
X		} else 
X			ship->wstatus &= ~(SHIELD_DEAD);
X		if (ship->torps <= 30) {
X			ship->wstatus &= ~(TORPEDO_LOCK);
X			ship->wstatus |= TORPEDO_DEAD;
X			if (ship->torps < 0)
X				ship->numtorps = 0;	/* Blown off */
X		} else 
X			if (num_torps[ship->type] > 0)
X				ship->wstatus &= ~(TORPEDO_DEAD);
X		if (ship->mines <= 30) {
X			ship->wstatus &= ~(MINE_LOCK);
X			ship->wstatus |= MINE_DEAD;
X			if (ship->mines < 0)
X				ship->nummines = 0;	/* Blown off */
X		} else 
X			if (num_mines[ship->type] > 0)
X				ship->wstatus &= ~(MINE_DEAD);
X		ship->align = onegrid.align;		/* Alignment */
X		if (onegrid.hit) {
X			printf("Computer hit %d times\n", onegrid.hit);
X			onegrid.hit = 0;
X		}
X		storegrid(x, y, onegrid);
X		if ((ship->energy < 0) || (ship->life < 0) || (ship->hull < 0) || (ship->crew < 0)) {
X			sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token);
X			putmsg(tmp);
X			explode(x, y, (ship->type * EXPLOSION), ship->type);
X			ship->token = 0;	/* Delete from grid */
X			ship->name[0] = 0;
X			onegrid.type = EMPTY;
X			onegrid.shield = 0;
X			onegrid.energy = 0;
X			onegrid.align = 0;
X			storegrid(x, y, onegrid);
X			release(semid);		/* Release locks */
X			puts("Computer ship disintegrated!");
X			*intbfr -= 1;
X			exit(0);
X		}
X		status = calcstatus(x, y, window, docked);
X		release(semid);		/* Release lock */
X		oldx = x;
X		oldy = y;
X/*
X	The purpose of this section of code is to insure that there is
X	something to do before going off and reading input.  If there is
X	nothing to do, wait a second, then go update the display and try
X	again.  In addition, if a drone, we only move with any real speed if
X	there are humans in the game (to reduce CPU load).
X*/
X		humans = 0;			/* No humans */
X		for (key = 0; key < MAXSHIPS; key++) {
X			readname(key, &onename);
X			if (onename.type) {	
X				if (onename.human) 	/* A human! */
X					humans++;
X			}
X		}
X		if (!humans) {			/* If there are no humans */
X			if (humancount < 100)	/* Do we sleep? */
X				humancount++;	/* Increase human check */
X			else {
X				slept++;
X				sleep(60);	/* sleep 60 seconds */
X			}
X		} else {
X			humancount = 0;		/* Clear count iff humans */
X			if (slept) {
X				slept = 0;	/* Clear it */
X				sprintf(tmp, "%s awakens", ship->name);
X				putmsg(tmp);
X			}
X		}
X		key = 0;
X		nap(NAPTIME + 350);
X#ifdef	SLOWDOWN
X		if ((ship->type >= 10) && (shipcount < 5))/* Marauder... */
X			shipcount = 5;		/* Nearly always can move... */
X		if (shipcount++ <= (ship->type / 3)) {/* If delay not expired */
X			key = 0;		/* No input allowed */
X			bypass++;		/* Bypass check */
X		} else {			/* Otherwise... */
X#endif
X			shipcount = 0;		/* Reset counter to zero */
X			key = makechoice(x, y, window, &lastkey);
X			bypass = 0;		/* Evaluate keypress */
X#ifdef	SLOWDOWN
X		}
X#endif
X		acquire(semid);			/* Regain lock on segment */
X		if (status == 0)		/* If green */
X			qcount = 0;		/* Then reset exit marker */
X		if (!bypass) {
X			if ((key == 0) || ((key >= '0') && (key <= '9')))
X				key = checkchoice(x, y, key, &lastkey);
X		}
X		switch (key) {
X			case 0:
X				break;	
X			case '8':
X				y = y + 1;
X				break;
X			case '7':
X				y = y + 1;
X				x = x - 1;
X				break;
X			case '1':
X				y = y - 1;
X				x = x - 1;
X				break;
X			case '9':
X				x = x + 1;
X				y = y + 1;
X				break;
X			case '3':
X				y = y - 1;
X				x = x + 1;
X				break;
X			case '2':
X				y = y - 1;
X				break;
X			case '4':
X				x = x - 1;
X				break;
X			case '6':
X				x = x + 1;
X				break;
X			case 'D':
X				docked = cdock(x, y, &window);
X				break;
X			case 'B':
X				cbuildbase(semid, x, y, window);
X				break;
X			case 'l':
X				if (cphasers(x, y, 'A', 'Z') == 0)
X					lastkey = 0;
X				break;
X			case 'L':
X				if (cphasers(x, y, BASE, BASE) == 0)
X					lastkey = 0;
X				break;
X/*
X			case 'm':
X				cmines(semid, x, y);
X				break;
X*/
X			case 't':
X				if (!cftorps(x, y, torparray, &ntfree, window))
X					lastkey = 0;
X				break;
X			case 's':
X			case 'S':
X				if ((ship->wstatus & SHIELD_DEAD) == 0)
X					ship->wstatus = ship->wstatus ^ SHIELD_UP;
X				break;
X		}
X		if (x < 0)
X			x = 0;
X		if (y < 0)
X			y = 0;
X		if (x >= SIZE)
X			x = SIZE - 1;
X		if (y >= SIZE)
X			y = SIZE - 1;
X
X/* Now check to see if the engines are working... */
X		
X		if (ship->engines < 30) {
X			if (roll(200) > ship->engines) {
X				x = oldx;	/* If not, no movement! */
X				y = oldy;
X			}
X		}
X
X/* End Engine check */
X
X		if ((x != oldx) || (y != oldy)) {
X			printf("Position %d %d\n", x, y);
X			docked = 0;			/* Undock craft */
X			readgrid(x, y, &oldgrid);
X			if (oldgrid.type == VOID) {
X				x = oldgrid.energy;
X				y = oldgrid.shield;
X				readgrid(x, y, &oldgrid);
X			}
X			if (oldgrid.type != EMPTY) {	/* Collision! */
X				tempenergy = oldgrid.energy;
X				readgrid(oldx, oldy, &onegrid);
X				oldgrid.energy -= ((onegrid.energy / 2) + 1000);
X				if (oldgrid.energy < 0) {
X					if ((oldgrid.type >= 'A') && (oldgrid.type <= 'Z')) {
X						namebuf.token = oldgrid.type;
X						tempint = locship(&namebuf, 1);
X						namebuf.token = 0;
X						namebuf.name[0] = 0;
X						storename(tempint, namebuf);
X					}
X					if (oldgrid.type == MINE) {
X						explode(x, y, (MINE_BOOM * EXPLOSION), MINE_BOOM);
X					}
X					oldgrid.type = EMPTY;
X				}
X				storegrid(x, y, oldgrid);
X				x = oldx;		/* Go backwards */
X				y = oldy;
X				if (tempenergy < 0)
X					tempenergy = 0 - tempenergy;
X				onegrid.energy -= ((tempenergy / 2) + 1000);
X				storegrid(x, y, onegrid);
X			} else {
X				readgrid(oldx, oldy, &onegrid);
X				
X				onegrid.energy -= sqr(((x - oldx) * (x - oldx)) + ((y - oldy) * (y - oldy))) * (roll(E_RAND_PER_MOVE) + E_PER_MOVE);
X				storegrid(x, y, onegrid);
X				onegrid.type = EMPTY;
X				onegrid.energy = 0L;
X				onegrid.shield = 0L;
X				onegrid.align = (char) 0;
X				storegrid(oldx, oldy, onegrid);
X			}
X		}
X		readgrid(x, y, &onegrid);
X		if (onegrid.hit) 		/* If we have been hit */
X			docked = 0;		/* Undock craft for sure */
X		if (docked)  {	/* If docked with the base */
X			tmpint = (roll(RANDADD)+EADD) * ship->type;
X			onegrid.energy += tmpint;
X			ship->energy += tmpint;
X			if (onegrid.energy > e_require[ship->type]) {
X				onegrid.energy = e_require[ship->type];
X				ship->energy = e_require[ship->type];
X			}
X			if (ship->shield < 100) {
X				ship->shield++;
X				onegrid.shield++;
X			}
X			if (ship->engines < 100)
X				ship->engines += 1;
X			if (ship->life < 100)
X				ship->life += 1;
X			if (ship->crew < 100)
X				ship->crew += 1;
X			if (ship->hull < 100)
X				ship->hull += 1;
X			if (ship->lasers < 100)
X				ship->lasers += 1;
X			if (ship->mines < 100)
X				ship->mines += 1;
X			if (ship->torps < 100)
X				ship->torps += 1;
X			ship->numtorps++;
X			ship->nummines++;
X		}
X		if (energy_count == 0) {	/* If it's time */
X			if ((ship->shield < 100) && (ship->shield > 0)) {
X				ship->shield++;
X				onegrid.shield++;
X			}
X			if ((ship->engines < 100) && (ship->engines > 0))
X				ship->engines += 1;
X			if ((ship->life < 100) && (ship->life > 0))
X				ship->life += 1;
X			if ((ship->crew < 100) && (ship->crew > 0))
X				ship->crew += 1;
X			if ((ship->hull < 100) && (ship->hull > 0))
X				ship->hull += 1;
X			if ((ship->lasers < 100) && (ship->lasers > 0))
X				ship->lasers += 1;
X			if ((ship->torps< 100) && (ship->torps> 0))
X				ship->torps += 1;
X			if ((ship->mines < 100) && (ship->mines> 0))
X				ship->mines += 1;
X		}
X		if (ship->shield > 100) {
X			ship->shield = 100;
X			onegrid.shield = 100;
X		}
X		if (ship->engines > 100)
X			ship->engines = 100;
X		if (ship->life > 100)
X			ship->life = 100;
X		if (ship->crew > 100)
X			ship->crew = 100;
X		if (ship->hull > 100)
X			ship->hull = 100;
X		if (ship->torps > 100)
X			ship->torps = 100;
X		if (ship->lasers > 100)
X			ship->lasers = 100;
X		if (ship->mines > 100)
X			ship->mines = 100;
X		if (ship->numtorps > num_torps[ship->type])
X			ship->numtorps = num_torps[ship->type];
X		if (ship->nummines > num_mines[ship->type])
X			ship->nummines = num_mines[ship->type];
X		storegrid(x, y, onegrid);
X	}
X	readgrid(x, y, &onegrid);			/* Delete ship */
X	onegrid.type = EMPTY;
X	storegrid(x, y, onegrid);
X	namebuf.token = ship->token;
X	tempint = locship(&namebuf, 1);
X	namebuf.token = 0;
X	namebuf.name[0] = 0;
X	storename(tempint, namebuf);
X	release(semid);
X	puts("Good bye!");
X	*intbfr -= 1;
X	shmdt(buffer);				/* Detach shared segment */
X	exit(0);
X}
END_OF_FILE
if test 13370 -ne `wc -c <'drone.c'`; then
    echo shar: \"'drone.c'\" unpacked with wrong size!
fi
# end of 'drone.c'
fi
if test -f 'torpedoes.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'torpedoes.c'\"
else
echo shar: Extracting \"'torpedoes.c'\" \(7558 characters\)
sed "s/^X//" >'torpedoes.c' <<'END_OF_FILE'
X/*	Part of the COSMOS package
X	Copyright 1988 Karl Denninger & MCS, Inc.
X	All Rights Reserved
X*/
X
X
X#include	"cosmos.h"
X
extern	struct	nameblock	*ship;
X
movetorps(ta, ntfree)
struct	torps	ta[];
int	*ntfree;
X{
X	int	tcount;
X	struct	grid	ourgrid;
X	int	key;
X	int	xx, yy;
X	int	dist;
X	int	x1, y1, xv, yv, count;
X
X	if (! *ntfree)
X		return(0);		/* Exit -- no torpedoes to move */
X	for (tcount = 0; tcount < MAXFTORPS; tcount++) {
X		if (ta[tcount].inuse) {		/* Process this entry */
X			readgrid(ta[tcount].x, ta[tcount].y, &ourgrid);
X			if (ourgrid.type != TORPEDO) {
X				ta[tcount].inuse = 0;	/* Free slot */
X				(*ntfree)--;	/* Free torpedo in flight */
X			} else {
X				ourgrid.type = EMPTY;
X				ourgrid.energy = 0;
X				ourgrid.shield = 0;
X				storegrid(ta[tcount].x, ta[tcount].y, ourgrid);
X				if ((ta[tcount].destx == -1) && (ta[tcount].desty == -1)) {
X					if (ta[tcount].homeship) {
X						xx = ta[tcount].x;
X						yy = ta[tcount].y;
X						key = findobj(&xx, &yy, &dist, 
X						ta[tcount].homeship,
X						ta[tcount].homeship,
X						window_size[ship->type]);
X						if (!key)
X							key = ta[tcount].lastkey;
X						else
X							ta[tcount].lastkey = key;
X					}
X				} else 
X					key = give_dir(ta[tcount].x,
X						ta[tcount].y,
X						ta[tcount].destx,
X						ta[tcount].desty);
X				xx = ta[tcount].x;
X				yy = ta[tcount].y;
X				switch(key) {
X					case 0:
X						break;	
X					case '8':
X						yy = yy + 1;
X						break;
X					case '7':
X						yy= yy + 1;
X						xx = xx - 1;
X						break;
X					case '1':
X						yy = yy - 1;
X						xx = xx - 1;
X						break;
X					case '9':
X						xx = xx + 1;
X						yy = yy + 1;
X						break;
X					case '3':
X						yy = yy - 1;
X						xx = xx + 1;
X						break;
X					case '2':
X						yy = yy - 1;
X						break;
X					case '4':
X						xx = xx - 1;
X						break;
X					case '6':
X						xx = xx + 1;
X						break;
X				}
X				if ((xx < 0) || (yy < 0) || (xx >= SIZE) || (yy >= SIZE)) {
X					(*ntfree)--;
X					ta[tcount].inuse = 0;	/* Delete */
X				} else {
X					readgrid(xx, yy, &ourgrid);
X					if (ourgrid.type == VOID) {	/* Warp */
X						xx = ourgrid.energy;	/* Get x */
X						yy = ourgrid.shield;	/* And Y */
X						readgrid(xx, yy, &ourgrid);
X					}
X					if (ourgrid.type != EMPTY) {
X						ta[tcount].inuse = 0;	/* Boom! */
X						if ((ourgrid.type >= 'A') && (ourgrid.type <= 'Z'))
X							ship->points += 100;
X						givedamage(xx, yy, ta[tcount].level * TORP_EREL, ship, 0);
X						(*ntfree)--;
X					} else {
X						ourgrid.type = TORPEDO;
X						ourgrid.energy = 5;
X						ourgrid.shield = 0;
X						storegrid(xx, yy, ourgrid);
X						ta[tcount].x = xx;
X						ta[tcount].y = yy;
X						if (ta[tcount].life-- <= 0) {
X							givedamage(xx, yy, 
X							(ta[tcount].level * TORP_EREL), ship, 0);
X							(*ntfree)--;
X							ta[tcount].inuse = 0;
X						} 
X					}
X				}
X			}
X		}
X	}
X}
X
X
firetorps(x, y, torparray, semid, ntfree, window)
int	x, y;
struct	torps	torparray[];
int	semid;
int	*ntfree;
int	window;
X{
X	static	int	key;
X	static	int	destx;
X	static	int	desty;
X	static	int	zz;
X	int	xx, yy;
X	int	x1, y1;
X	int	z = 0;
X	int	dist;
X	struct	grid	ourgrid;
X	char	tmp[80];
X	
X	release(semid);
X	mvaddstr(22,20,"Torpedo -> ");
X	refresh();
X	get_str(tmp);
X	acquire(semid);
X	if (ship->wstatus & SHIELD_UP) {
X		mvaddstr(23,20,"Captain!  The shields are UP!");
X		clrtoeol();
X		return(0);
X	}
X	xx = x;
X	yy = y;
X	if (tmp[0]) {
X		if ((!isdigit(tmp[0])) && (tmp[0] != '-')) {
X			destx = x;
X			desty = y;
X			key = findobj(&destx, &desty, &dist, toupper(tmp[0]), toupper(tmp[0]), window);
X			if (!key) {
X				mvaddstr(23,20,"Captain, I can't locate that target!");
X				clrtoeol();
X				return(0);
X			}
X			destx = -1;
X			desty = -1;
X			zz = toupper(tmp[0]);
X		} else {
X			sscanf(tmp, "%d %d", &x1, &y1);
X			destx = (x1 + x);
X			desty = (y1 + y);
X			key = give_dir(xx, yy, destx, desty);
X		}
X	}
X	xx = x; yy = y;
X	switch(key) {
X		case '9':
X			xx++;
X			yy++;
X			break;
X		case '6':
X			xx++;
X			break;
X		case '3':
X			xx++;
X			yy--;
X			break;
X		case '2':
X			yy--;
X			break;
X		case '1':
X			xx--;
X			yy--;
X			break;
X		case '4':
X			xx--;
X			break;
X		case '7':
X			xx--;
X			yy++;
X			break;
X		case '8':
X			yy++;
X			break;
X	}
X	if ((xx < 0) || (xx >= SIZE) || (yy < 0) || (yy >= SIZE))
X		return(0);			/* Don't launch, off grid */
X	readgrid(xx, yy, &ourgrid);
X	if (ourgrid.type != EMPTY) {			/* Something is there */
X		mvaddstr(23,20,"ABORT!  Something is in the way of our launch!");
X		clrtoeol();
X		return(0);
X	}
X	if (*ntfree >= num_ftorps[ship->type]) {
X		mvaddstr(23,20,"Information system overload; unable to launch");
X		clrtoeol();
X		return(0);
X	}
X	if (ship->numtorps <= 0) {
X		mvaddstr(23,20,"No torpedoes on board Captain!");
X		clrtoeol();
X		return(0);
X	}
X	ship->numtorps--;			/* Subtract one torpedo */
X	for (z = 0; z < num_ftorps[ship->type]; z++) {
X		if (!torparray[z].inuse) {	/* Found one free! */
X			(*ntfree)++;
X			torparray[z].x = xx;
X			torparray[z].y = yy;
X			torparray[z].destx = 0;
X			torparray[z].desty = 0;
X			if ((destx == -1) && (desty == -1)) {
X				torparray[z].homeship = zz;
X				torparray[z].destx = -1;
X				torparray[z].desty = -1;
X			} else {
X				torparray[z].homeship = 0;
X				torparray[z].destx = destx;
X				torparray[z].desty = desty;
X			}
X			torparray[z].travelled = 0;
X			torparray[z].life = (ship->type * 2);	/* Max dist */
X			torparray[z].level = (ship->type);	/* Blast size */
X			if (!torparray[z].level)
X				torparray[z].level++;
X			torparray[z].inuse++;			/* Entry used */
X			mvaddstr(23,20,"Torpedo fired!");
X			clrtoeol();
X			ourgrid.type = TORPEDO;
X			storegrid(xx, yy, ourgrid);
X			return(1);
X		}
X	}
X	/* If you get here, you're in trouble -- something went wrong */
X	mvaddstr(23,20,"Captain!  The torpedo tubes are jammed!");
X	clrtoeol();
X	refresh();
X	return(0);
X}
X
X
cftorps(x, y, torparray, ntfree, window)
int	x, y;
struct	torps	torparray[];
int	*ntfree;
int	window;
X{
X	static	int	key;
X	static	int	destx;
X	static	int	desty;
X	static	int	zz;
X	int	xx, yy;
X	int	x1, y1;
X	int	z = 0;
X	int	dist;
X	struct	grid	ourgrid;
X	char	tmp[80];
X	
X	if (ship->torps < 30) {
X		if (roll(200) > ship->torps) 
X			return(0);
X	}
X	destx = x;
X	desty = y;
X	key = findobj(&destx, &desty, &dist, 'A', 'Z', window);
X	if (!key) {
X		return(0);
X	}
X	readgrid(destx, desty, &ourgrid);
X	zz = ourgrid.type;			/* Save character */
X	xx = x; yy = y;
X	switch(key) {
X		case '9':
X			xx++;
X			yy++;
X			break;
X		case '6':
X			xx++;
X			break;
X		case '3':
X			xx++;
X			yy--;
X			break;
X		case '2':
X			yy--;
X			break;
X		case '1':
X			xx--;
X			yy--;
X			break;
X		case '4':
X			xx--;
X			break;
X		case '7':
X			xx--;
X			yy++;
X			break;
X		case '8':
X			yy++;
X			break;
X	}
X	if ((xx < 0) || (xx >= SIZE) || (yy < 0) || (yy >= SIZE))
X		return(0);			/* Don't launch, off grid */
X	readgrid(xx, yy, &ourgrid);
X	if (ourgrid.type != EMPTY) {			/* Something is there */
X		return(0);
X	}
X	if (*ntfree >= num_ftorps[ship->type]) {
X		return(0);
X	}
X	if (ship->numtorps <= 0) {
X		return(0);
X	}
X	ship->numtorps--;			/* Subtract one torpedo */
X	for (z = 0; z < num_ftorps[ship->type]; z++) {
X		if (!torparray[z].inuse) {	/* Found one free! */
X			(*ntfree)++;
X			torparray[z].x = xx;
X			torparray[z].y = yy;
X			torparray[z].destx = 0;
X			torparray[z].desty = 0;
X			torparray[z].homeship = zz;
X			torparray[z].destx = -1;
X			torparray[z].desty = -1;
X			torparray[z].travelled = 0;
X			torparray[z].life = (ship->type * 2);	/* Max dist */
X			torparray[z].level = (ship->type);	/* Blast size */
X			if (!torparray[z].level)
X				torparray[z].level++;
X			torparray[z].inuse++;			/* Entry used */
X			ourgrid.type = TORPEDO;
X			storegrid(xx, yy, ourgrid);
X			return(1);
X		}
X	}
X	/* If you get here, you're in trouble -- something went wrong */
X	return(0);
X}
END_OF_FILE
if test 7558 -ne `wc -c <'torpedoes.c'`; then
    echo shar: \"'torpedoes.c'\" unpacked with wrong size!
fi
# end of 'torpedoes.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 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

--
Karl Denninger (karl@ddsw1.MCS.COM, ddsw1!karl)
Data: [+1 312 566-8912], Voice: [+1 312 566-8910]
Macro Computer Solutions, Inc.    	"Quality solutions at a fair price"

karl@ddsw1.MCS.COM (Karl Denninger) (11/18/88)

Part 3 of 3, see part 1 for details

#! /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 3 (of 3)."
# Contents:  cosmos.c funcs.c
# Wrapped by karl@ddsw1 on Thu Nov 17 23:53:11 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cosmos.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cosmos.c'\"
else
echo shar: Extracting \"'cosmos.c'\" \(23237 characters\)
sed "s/^X//" >'cosmos.c' <<'END_OF_FILE'
X/*	Spacewar	- The final frontier
X
X	This package is Copyright 1988 Karl Denninger.  All rights reserved.
X	
X	All unauthorized mutants shall be destroyed, fed to vermin, and the
X	remains from this process will be prosecuted.
X
X*/
X
X/*	Definitions go below - Make sure you have these in front of include
X	files as these definitions should override the include files	*/
X
X
X#include	"cosmos.h"
X
extern	void clrin();				/* Interrupt handler */
extern	void die();				/* Death by disconnect */
X
int	extx, exty;
int	quit;					/* Halt variable */
char	*buffer;				/* Buffer pointer */
int	numcomp;				/* # of computer players */
char	home[128];				/* Home directory */
int	superuser, su2;				/* Uid of the superuser */
int	window;					/* Window size, must be < 20 */
int	foundchar = 0;				/* Found character? */
int	oldchar;				/* Old character if one */
struct	nameblock	*ship;			/* Pointer to ship's data */
struct	nameblock	name[MAXSHIPS];
struct	grid		onegrid;
struct	grid		oldgrid;
X
X
int	squares[SIZE];				/* Squares table */
int	drone = 0;				/* Not a drone */
long	numsecs;				/* Seconds since epoch */
long	nowsecs;				/* Time now */
long	startime;
long	minsday;				/* Minutes/day */
long	origmins;				/* Original minutes */
long	layoff;					/* How long to reset limits */
int	free_game;				/* Is this a free game? */
X
main(argc, argv)
int	argc;
char	*argv[];
X
X{
X
X	static	long	points;		/* Points accumulated */
X	static	int	type;		/* Class of ship */
X	char	shipname[40];
X	
X	struct	grid	tempgrid;
X	int	limited = 0;		/* Limited user */ 
X	int	timed = 0;		/* Timed user? */
X	long	now;
X	int	tenwarned = 0;		/* Warning flags */
X	int	fivewarned = 0;
X	int	twowarned = 0;
X	int	destx = -1;
X	int	nomove = 0;
X	int	desty = -1;
X	int	safe = -1;		/* Initially safe from collisions */
X	int	standir = 0;
X	int	shipcount;
X	int	scancount = 0, zx;
X	int	ntfree = 0;		/* Number of torpedoes free */
X	int	docked = 0;
X	int	tmpint;		/* Temp integer */
X	int	cheat = 0;
X
X	int	seg;			/* Shared segment number */
X	
X	int	status;			/* Status (ok/not ok) */
X	int	qcount = 0;		/* Quit counter */
X	int	energy_count = 0;	/* Temporary iterative counter */
X	int	stale_msg = TIME_PER_MSG;/* Stale message count */
X	int	tempenergy;
X	long	size;
X	int	oldx, oldy;
X	int	key;
X	int	tempint = 0;
X	
X	static	int	delta_x	= 0;	/* Initial delta 'x' */
X	static	int	delta_y = 0;	/* Initial delta 'y' */
X
X	int	semid;
X	int	flags;
X	char	tempstr[80];		/* 80 Character string */
X	char	tempstr2[80];		/* 80 Character string */
X	char	tmp[80];
X	FILE	*fid;
X	int	scanned = 0;
X
X	struct	nameblock	namebuf;
X	struct	torps	torparray[MAXFTORPS];
X					/* Array of torpedo coords */
X
X	long	game = sizeof(ccount) + (sizeof(onename) * MAXSHIPS) + 
X			(sizeof(onegrid) * MAXGRID) + (sizeof(onemsg) * MAXMSG);
X
X	size = (game);			/* Get size of game module */
X	quit = 0;
X	printf("Cosmos V%s\n", VERSION);
X	printf("Copyright 1988 MCS Inc. & Karl Denninger\n");
X#ifdef	LICENSEE
X	printf("Licensed to %s\n", LICENSEE);
X#endif
X	fflush(stdout);
X	for (extx = 0; extx < SIZE; extx++)
X		squares[extx] = (extx * extx);
X	for (extx = 0; extx < MAXFTORPS; extx++)
X		torparray[extx].inuse = 0;	/* Mark torpedo not in use */
X	sprintf(tmp, "%s", HOME);
X	if ((fid = fopen(tmp, "r")) != NULL) {
X		fscanf(fid, "%s %d %d %d %d %d %d %d", home, &superuser, &su2, 
X			&numcomp, &minsday, &origmins, &layoff, &free_game);
X		fclose(fid);
X	}
X	if ((seg = shmget(122L, size, IPC_CREAT|0660)) == -1) {
X		perror("create");
X		puts("Cannot execute due to shared-segment create fault");
X		exit(1);
X	}
X	if ((buffer = shmat(seg, (char *) NULL, 0)) == (char *) -1) {
X		perror("attach");
X		puts("Cannot execute due to shared-segment attach fault");
X		exit(1);
X	}
X	if ((semid = semget(122L, 1, 0660)) == -1) {
X		if ((semid = semget(122L, 1, 0660|IPC_CREAT)) == -1) {
X			perror("semaphone create");
X			exit(1);
X		}
X	} else {
X		acquire(semid);
X	}
X	signal(SIGHUP, die);			/* Save on hangups */
X	signal(SIGINT, clrin);			/* Clear input on ^C */
X	signal(SIGQUIT, SIG_IGN);
X	signal(SIGCLD, SIG_IGN);		/* No Zombies */
X
X#ifdef	ACCOUNTING
X/*	Now start accounting and figure out what time it is */
X
X	numsecs = addplayer(&limited, &timed, argc, argv[1]);/* Do accounting */
X	startime = time((int *) 0L);		/* Get current time */
X	nowsecs = startime + numsecs;		/* Set limit */
X	if (numsecs <= 0) {
X		release(semid);
X		printf("You are out of time at present to play COSMOS\n");
X		if (numsecs < 0) { 		/* No more credit */
X			printf("Your account balance has reached zero\n");
X			printf("Please contact the administrator\n");
X		} else
X			printf("You must wait for %d minutes before playing again\n", layoff);
X		exit(0);
X	}
X/*	End time accounting stuff */
X#endif
X
X	release(semid);
X	initscr();
X	acquire(semid);
X	noecho();
X	cbreak();
X	intrflush(stdscr, FALSE);		/* No flush on interrupt */
X#ifdef	M_TERMINFO
X	typeahead(-1);				/* No typeahead checks */
X#endif
X	srand((unsigned) time ((long *) 0L));
X	if (argc == 1)
X		showfile("Hello", semid, 0);
X	erase();
X	readgrid(0, 0, &onegrid);
X	if (onegrid.type == 0) {
X		mvaddstr(22,0,"Initializing game grid...");
X		refresh();
X		for (extx = 0; extx < SIZE; extx++) {
X			for (exty = 0; exty < SIZE; exty++) {
X				tempint = rand();
X				if (tempint < 500) {
X					if (tempint < 30) {
X						if (tempint < 10) {
X							onegrid.type = NEGBASE;
X							onegrid.energy = 1000000L;
X							onegrid.shield = 100;
X						} else {
X							onegrid.type = VOID;
X							onegrid.energy = roll(SIZE);
X							onegrid.shield = roll(SIZE);
X						}
X					} else {
X						if (tempint < 250) {
X							onegrid.type = STAR;
X							onegrid.energy = 2000000L;
X						} else { 
X							onegrid.type = PLANET;
X							onegrid.energy = 1000000L;
X						}
X						onegrid.shield = 0;
X					}
X				} else {
X					onegrid.type = EMPTY;
X					onegrid.shield = 0;
X					onegrid.energy = 0L;
X				}
X				storegrid(extx, exty, onegrid);
X			}
X		}
X		move(22,0);
X		clrtoeol();
X		refresh();
X	} 
X	if ((ship = (struct nameblock *) getship(argc, argv[1], semid, &extx, &exty)) == NULL) {
X#ifdef	ACCOUNTING
X		delplayer(argc, argv[1], startime);
X#endif
X		endwin();
X		puts("Fatal placement error");	/* Can't place the ship */
X		release(semid);			/* Release semaphore */
X		exit(0);			/* Quit */
X	}
X#ifdef	RANDOM_START
X	extx = roll(SIZE);
X	exty = roll(SIZE);
X#endif
X	if ((extx == 0) && (exty == 0)) {
X		extx = roll(SIZE); 
X		exty = roll(SIZE);
X	}
X	window = window_size[ship->type];
X	sprintf(tmp, "Welcome %s (%c)", ship->name, ship->token);
X	putmsg(tmp);
X
X/*	Now place the user's ship in the game.  	*/
X	
X	tempint = 0;
X	while (quit == 0) {
X		while ((extx < 0) || (extx >= SIZE))
X			extx = roll(SIZE);
X		while ((exty < 0) || (exty >= SIZE))
X			exty = roll(SIZE);
X		readgrid(extx, exty, &onegrid);
X		if (onegrid.type == EMPTY) 
X			quit++;
X		else {
X			extx = roll(SIZE); exty = roll(SIZE);
X			tempint++;
X			if (tempint >= 200) {
X				endwin();
X				release(semid);
X				puts("Cannot place ship!");
X			}
X		}
X	}
X	onegrid.type = ship->token;
X	onegrid.shield = ship->shield;
X	onegrid.energy = ship->energy;
X	onegrid.align = 0;			/* Neutral alignment */
X	ship->human = 1;			/* Human ship */
X	storegrid(extx, exty, onegrid);
X	quit = 0;
X	erase();
X	standout();
X	mvaddstr(23,20," Press the <?> key for assistance on COSMOS ");
X	standend();
X	while (quit == 0) {
X
X/* Move torpedoes */
X		movetorps(torparray, &ntfree); 
X		readgrid(extx, exty, &onegrid);
X		if (onegrid.type == EMPTY) {
X			if (!limited)
X				penalize();		/* Make it hurt :-) */
X			sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token);
X			putmsg(tmp);
X			explode(extx, exty, (ship->type * EXPLOSION), ship->type);/* Kill people near 'ya :-) */
X			ship->token = 0;	/* Delete from grid */
X			ship->name[0] = 0;
X			onegrid.type = EMPTY;
X			onegrid.shield = 0;
X			onegrid.energy = 0;
X			onegrid.align = 0;
X			storegrid(extx, exty, onegrid);
X			release(semid);		/* Release locks */
X			(void) dispstatus(extx, exty, window, docked);
X			refresh();
X			sleep(10);
X			erase();		/* Exit out from game */
X			refresh();
X			endwin();
X			puts("Your ship has disintegrated!");
X#ifdef	ACCOUNTING
X			if (!limited)
X				delplayer(argc, argv[1]);
X#endif
X			exit(0);
X		}
X
X/* Insert here any routines which should be performed after each turn --
X   specifically, those things which take energy when engaged such as shields */
X		
X		if (scancount > 0) {
X			scancount--;
X			if (!scancount) {
X				mvaddstr(1, 44, "                      ");
X				for (zx = 2; zx < 17; zx++) {
X					mvaddstr(zx, 44, "              ");
X				}
X			}
X		}
X		energy_count--;
X		if (energy_count < 0) {
X			energy_count = TIME_PER_EUNIT;
X			onegrid.energy--;
X		}
X#ifdef	RETIRE_MSGS
X		if (stale_msg-- <= 0) {
X			putmsg("");
X			stale_msg = TIME_PER_MSG;
X		}
X#endif
X		if (ship->wstatus & SHIELD_UP) {
X			onegrid.energy -= (ship->type * SHIELD_COST);
X			docked = 0;		/* Undock the craft */
X		}
X		if (ship->energy > onegrid.energy)
X			ship->energy = onegrid.energy;
X		if (ship->shield > onegrid.shield)
X			ship->shield = onegrid.shield;
X		if (ship->shield <= 0) {
X			ship->wstatus &= ~(SHIELD_UP);
X			ship->wstatus |= SHIELD_DEAD;
X		} else
X			ship->wstatus &= ~(SHIELD_DEAD);
X		if (ship->torps <= 0) {
X			ship->wstatus &= ~(TORPEDO_LOCK);
X			ship->wstatus |= TORPEDO_DEAD;
X			ship->numtorps = 0;	/* Blown off */
X		} else 
X			if (num_torps[ship->type] > 0)
X				ship->wstatus &= ~(TORPEDO_DEAD);
X		if (ship->mines <= 0) {
X			ship->wstatus &= ~(MINE_LOCK);
X			ship->wstatus |= MINE_DEAD;
X			ship->nummines = 0;	/* Blown off */
X		} else 
X			if (num_mines[ship->type] > 0)
X				ship->wstatus &= ~(MINE_DEAD);
X		ship->align = onegrid.align;		/* Alignment */
X		if (onegrid.hit) {
X			beep();
X			move(23,20);
X			standout();
X			if (onegrid.hit == 1)
X				printw("You've been hit!", onegrid.hit);
X			else
X				printw("You've been hit %d times!", onegrid.hit);
X			standend();
X			clrtoeol();
X			docked = 0;
X			onegrid.hit = 0;
X		}
X		storegrid(extx, exty, onegrid);
X		if ((ship->energy < 0) || (ship->life < 0) || (ship->hull < 0) || (ship->crew < 0)) {
X			if (!limited)
X				penalize();		/* Make it hurt :-) */
X			sprintf(tmp, "The %s (%c) explodes!", ship->name, ship->token);
X			putmsg(tmp);
X			explode(extx, exty, (ship->type * EXPLOSION), ship->type);/* Kill people near 'ya :-) */
X			ship->token = 0;	/* Delete from grid */
X			ship->name[0] = 0;
X			onegrid.type = EMPTY;
X			onegrid.shield = 0;
X			onegrid.energy = 0;
X			onegrid.align = 0;
X			storegrid(extx, exty, onegrid);
X			release(semid);		/* Release locks */
X			(void) dispstatus(extx, exty, window, docked);
X			refresh();
X			sleep(10);
X			erase();		/* Exit out from game */
X			refresh();
X			endwin();
X			puts("Your ship has disintegrated!");
X#ifdef	ACCOUNTING
X			delplayer(argc, argv[1]);
X#endif
X			exit(0);
X		}
X		status = dispstatus(extx, exty, window, docked);
X		if (ship->scanned) {
X			mvaddstr(23,20, "Captain!  We're being scanned!!");
X			ship->scanned = 0;
X		}
X		if (timed) {
X			now = time((long *) 0L);
X			if (now >= (nowsecs + 600)) {
X				if (!tenwarned) {
X					mvaddstr(23,20,"10 Minute warning!!!!");
X					clrtoeol();
X					beep();
X				}
X				tenwarned++;
X			}
X			if (now >= (nowsecs + 300)) {
X				if (!fivewarned) {
X					mvaddstr(23,20,"5 Minute warning!!!!");
X					clrtoeol();
X					beep();
X				}
X				fivewarned++;
X			}
X			if (now >= (nowsecs + 120)) {
X				if (!twowarned) {
X					mvaddstr(23,20,">TWO< Minute warning!!!! QUIT NOW!!");
X					clrtoeol();
X					beep();
X				}
X				twowarned++;
X			}
X			if (now >= (nowsecs)) {
X				mvaddstr(23,20,"TIME HAS EXPIRED");
X				clrtoeol();
X				beep();
X				release(semid);
X				refresh();
X				sleep(10);
X				acquire(semid);
X				quit++;		/* Exit the game next turn */
X			}
X		}
X		release(semid);		/* Release lock */
X		mvaddstr(22,20,"Command -> ");
X		clrtoeol();
X		oldx = extx;
X		oldy = exty;
X		extx = extx;
X		exty = exty;
X/*
X	The purpose of this section of code is to insure that there is
X	something to do before going off and reading input.  If there is
X	nothing to do, wait a second, then go update the display and try
X	again.
X*/
X		key = 0;
X		refresh();			/* Paint screen */
X		nap(NAPTIME);
X#ifdef	SLOWDOWN
X		if (((ship->type >= 10) && (shipcount < 5)) || (cheat))/* Marauder... */
X			shipcount = 5;		/* Nearly always can move... */
X		if (shipcount++ <= (ship->type / 3)) {/* If delay not expired */
X			nomove = 0;
X			key = 0;		/* No input allowed */
X		} else {			/* Otherwise... */
X#endif
X			nomove++;
X			shipcount = 0;		/* Reset counter to zero */
X			tempint = rdchkx(0);	/* Check stdin for input */
X			if (tempint) {		/* If key has been hit */
X				key = getchx();	/* Read it (special) */
X				move(23,20);
X				clrtoeol();
X			} 
X#ifdef	SLOWDOWN
X		}
X#endif
X		acquire(semid);			/* Regain lock on segment */
X
X/* End non-portable section */
X		if (!status)			/* If green */
X			qcount = 0;		/* Then reset exit marker */
X		if ((key >= '0') && (key <= '9')) {
X			destx = -1;		/* Clear if move key hit */
X			desty = -1;
X		}
X		if (key == 0) {
X			if ((nomove) && (destx != -1) && (desty != -1)) {
X				key = give_dir(extx, exty, destx, desty);
X				if (key == -1) {	/* Autopilot */
X					destx = -1;
X					desty = -1;
X					mvaddstr(23,20,"Arrived at destination, Captain");
X					clrtoeol();
X				}
X			}
X		}
X		switch (key) {
X			case 0:
X				break;	
X			case 24:		/* ^X - only superuser */
X				if ((getuid() == superuser) || (getuid() == su2)) { 
X					modgame(semid);
X					oldx = extx;
X					oldy = exty;
X					erase();
X				}
X				break;
X			case 23:		/* ^W - only for superuser */
X				if ((getuid() == superuser) || (getuid() == su2)){
X					window = 20;
X					erase();
X				}
X				break;
X			case 3:
X				if ((getuid() == superuser) || (getuid() == su2)) 
X					cheat ^= (-1);	/* Toggle cheat mode */
X				break;
X			case 16:		/* ^P - only superuser */
X				if ((getuid() == superuser) || (getuid() == su2)) {
X					ship->points += ship->points;
X				}
X				break;
X			case '+':
X				release(semid);
X				execit("drone","drone");/* Execute drone */
X				mvaddstr(23,20,"Enemy ship started...");
X				clrtoeol();
X				acquire(semid);
X				break;
X			case 'P':		/* PLAYERS command */
X				showplayers(semid, docked);
X				break;
X			case 'N':		/* Name (rename ship) command */
X				mvaddstr(22,20,"New Ship Name -> ");
X				release(semid);
X				refresh();
X				get_str(tempstr);
X				acquire(semid);
X				strncpy(ship->name, tempstr, 19);
X				ship->name[19] = 0;
X				break;
X			case 12:
X				clear();
X				break;
X			case 'Q':
X				if (status) {
X					if (++qcount == 1) {
X						mvaddstr(23,20,"Hit <Q> twice more to DESTRUCT");
X						clrtoeol();
X					} else {
X						if (qcount == 3)
X							quit++;
X					}
X				} else
X					quit++;
X				break;
X			case '?':
X				showfile("Help", semid, 1);
X				break;
X			case '8':
X				exty = exty + 1;
X				break;
X			case '7':
X				exty = exty + 1;
X				extx = extx - 1;
X				break;
X			case '1':
X				exty = exty - 1;
X				extx = extx - 1;
X				break;
X			case '9':
X				extx = extx + 1;
X				exty = exty + 1;
X				break;
X			case '3':
X				exty = exty - 1;
X				extx = extx + 1;
X				break;
X			case '2':
X				exty = exty - 1;
X				break;
X			case '4':
X				extx = extx - 1;
X				break;
X			case '6':
X				extx = extx + 1;
X				break;
X			case 'D':
X				docked = dock(extx, exty, &window);
X				break;
X			case 'B':
X				buildbase(semid, extx, exty);
X				break;
X			case 'b':
X				release(semid);
X				mvaddstr(22,20,"Broadcast -> ");
X				clrtoeol();
X				refresh();
X				get_str(tempstr);
X				sprintf(tempstr2, "%c: %s", ship->token, tempstr);
X				acquire(semid);
X				putmsg(tempstr2);
X				break;
X			case 'M':		
X				enter_smove(&destx, &desty, semid);
X				if ((destx < 0) || (destx >= SIZE) || (desty < 0) || (desty >= SIZE)) {
X					destx = -1;
X					desty = -1;
X				} else {
X					move(23,20);
X					sprintf(tmp, "Autopilot engaged, destination %d %d", destx, desty);
X					addstr(tmp);
X					clrtoeol();
X				}
X				break;	
X			case 'l':
X				if (ship->lasers > 30)
X					phasers(semid, extx, exty);
X				else
X					if (roll(200) < ship->lasers) 
X						phasers(semid, extx, exty);
X					else {
X						standout();
X						mvaddstr(23,20,"Laser malfunction!");
X						standend();
X						clrtoeol();
X					}
X				break;
X			case 'm':
X				if (ship->mines > 30)
X					mines(semid, extx, exty);
X				else {
X					if (roll(200) < ship->mines) 
X						mines(semid, extx, exty);
X					else {
X						standout();
X						mvaddstr(23,20,"Mine launcher malfunction!");
X						standend();
X						clrtoeol();
X					}
X				}
X				break;
X			case 'S':
X				scanned = scan(semid, extx, exty, window);/* Look */
X				if (scanned) 
X					scancount = 50;
X				ship->energy -= roll(100);
X				break;
X			case 's':
X				if (ship->shield > 30)
X					ship->wstatus = ship->wstatus ^ SHIELD_UP;
X				else {
X					if (roll(200) < ship->shield) 
X						ship->wstatus = ship->wstatus ^ SHIELD_UP;
X					else {
X						standout();
X						mvaddstr(23,20,"Shield control malfunction!");
X						standend();
X						clrtoeol();
X					}
X				}
X				break;
X			case 'R':		/* Range/RAM Control */
X				safe ^= -1;	/* XOR it... */
X				if (safe) 
X					mvaddstr(23,20,"Ramming SAFETY ON");
X				else {
X					standout();
X					mvaddstr(23,20,"Ramming SAFETY OFF");
X					standend();
X					beep();
X				}
X				clrtoeol();
X				break;
X			case 't':		/* Torpedoes! */
X				if (ship->torps > 30) {
X					if (num_torps[ship->type])
X						firetorps(extx, exty, torparray, semid, &ntfree, window);
X					else {
X						mvaddstr(23,20, "No torpedo capability");
X						clrtoeol();
X					}
X				} else {
X					if (roll(200) < ship->torps) 
X						firetorps(extx, exty, torparray, semid, &ntfree, window);
X					else {
X						standout();
X						mvaddstr(23,20,"Torpedo tube malfunction!");
X						standend();
X						clrtoeol();
X					}
X				}
X				break;
X				
X		}
X		if (extx < 0)
X			extx = 0;
X		if (exty < 0)
X			exty = 0;
X		if (extx >= SIZE)
X			extx = SIZE - 1;
X		if (exty >= SIZE)
X			exty = SIZE - 1;
X
X/* Now check to see if the engines are working... */
X
X		if (ship->engines < 30) {
X			if (roll(200) > ship->engines) {
X				extx = oldx;	/* If not, no movement! */
X				exty = oldy;
X				standout();
X				mvaddstr(23,20, "Engine failure!");
X				standend();
X				clrtoeol();
X			}
X		}
X
X/* End Engine check */
X
X		if ((extx != oldx) || (exty != oldy)) {
X			docked = 0;			/* Undock craft */
X			readgrid(extx, exty, &oldgrid);
X			if (oldgrid.type == VOID) {	/* Black hole */
X				extx = oldgrid.energy;
X				exty = oldgrid.shield;	/* Get new coords */
X				readgrid(extx, exty, &oldgrid);/* Switch! */
X			}
X			if (oldgrid.type != EMPTY) {	/* Collision! */
X				if ((safe) && (oldgrid.type != MINE)) {
X					extx = oldx;
X					exty = oldy;
X					readgrid(extx, exty, &tempgrid);
X					tempgrid.energy -= 300;
X					storegrid(extx, exty, tempgrid);
X					ship->energy -= 300;
X					destx = -1;
X					desty = -1;	/* Cancel move */
X					mvaddstr(23,20,"Collision avoided!");
X					clrtoeol();
X				} else {
X				mvaddstr(23,20, "Collision!");
X				tempenergy = oldgrid.energy;
X				readgrid(oldx, oldy, &onegrid);
X				oldgrid.energy -= ((onegrid.energy / 2) + 1000);
X				if (oldgrid.energy < 0) {
X					if ((oldgrid.type >= 'A') && (oldgrid.type <= 'Z')) {
X						namebuf.token = oldgrid.type;
X						tempint = locship(&namebuf, 1);
X						namebuf.token = 0;
X						namebuf.name[0] = 0;
X						storename(tempint, namebuf);
X					} else {
X						if (oldgrid.type == MINE) {
X							mvaddstr(23,20,"The mine explodes!");
X							refresh();
X							explode(extx, exty, (MINE_BOOM * EXPLOSION), MINE_BOOM);
X						} else {
X
X							mvaddstr(23,20, "FLASH!  The item you hit is DESTROYED!");
X							explode(extx, exty, (BIG_BOOM * EXPLOSION), BIG_BOOM);
X						}
X					}
X					clrtoeol();
X					oldgrid.type = EMPTY;
X				}
X				storegrid(extx, exty, oldgrid);
X				extx = oldx;		/* Go backwards */
X				exty = oldy;
X				if (tempenergy < 0)
X					tempenergy = 0 - tempenergy;
X				onegrid.energy -= ((tempenergy / 2) + 1000);
X				storegrid(extx, exty, onegrid);
X				}
X			} else {
X				move(22,0);
X				clrtoeol();
X				readgrid(oldx, oldy, &onegrid);
X		
X				onegrid.energy -= ((int) sqr(((extx - oldx) * (extx - oldx)) + ((exty - oldy) * (exty - oldy))) * (roll(E_RAND_PER_MOVE) + E_PER_MOVE));
X				storegrid(extx, exty, onegrid);
X				onegrid.type = EMPTY;
X				onegrid.energy = 0L;
X				onegrid.shield = 0L;
X				onegrid.align = (char) 0;
X				storegrid(oldx, oldy, onegrid);
X			}
X		}
X		
X		readgrid(extx, exty, &onegrid);
X		if (onegrid.hit) 		/* If we have been hit */
X			docked = 0;		/* Undock craft for sure */
X		if (docked) {			/* If docked with the base */
X			tmpint = (roll(RANDADD)+EADD) * ship->type;
X			onegrid.energy += (tmpint * docked);
X			ship->energy += (tmpint * docked);
X			if (onegrid.energy > e_require[ship->type]) {
X				onegrid.energy = e_require[ship->type];
X				ship->energy = e_require[ship->type];
X			}
X			if ((ship->shield < 100) && (ship->shield > 0)) {
X				if (docked != -1) {
X					ship->shield++;
X					onegrid.shield++;
X				} else {
X					ship->shield--;
X					onegrid.shield--;
X				}
X			}
X			if ((ship->engines < 100) && (ship->engines > 0))
X				ship->engines += docked;
X			if ((ship->life < 100) && (ship->life > 0))
X				ship->life += docked;
X			if ((ship->crew < 100) && (ship->crew > 0))
X				ship->crew += docked;
X			if ((ship->hull < 100) && (ship->hull > 0))
X				ship->hull += docked;
X			if ((ship->lasers < 100) && (ship->lasers > 0))
X				ship->lasers += docked;
X			if ((ship->mines < 100) && (ship->mines > 0))
X				ship->mines += docked;
X			if ((ship->torps < 100) && (ship->torps > 0))
X				ship->torps += docked;
X			if (docked != -1) {
X				ship->numtorps++;
X				ship->nummines++;
X			} else {
X				ship->numtorps--;
X				ship->nummines--;
X			}
X		}
X		if (energy_count == 0) {	/* If it's time */
X			if ((ship->shield < 100) && (ship->shield > 0)) {
X				ship->shield++;
X				onegrid.shield++;
X			}
X			if ((ship->engines < 100) && (ship->engines > 0))
X				ship->engines += 1;
X			if ((ship->life < 100) && (ship->life > 0))
X				ship->life += 1;
X			if ((ship->crew < 100) && (ship->crew > 0))
X				ship->crew += 1;
X			if ((ship->hull < 100) && (ship->hull > 0))
X				ship->hull += 1;
X			if ((ship->lasers < 100) && (ship->lasers > 0))
X				ship->lasers += 1;
X			if ((ship->torps< 100) && (ship->torps> 0))
X				ship->torps += 1;
X			if ((ship->mines < 100) && (ship->mines> 0))
X				ship->mines += 1;
X		}
X		if (ship->shield > 100) {
X			ship->shield = 100;
X			onegrid.shield = 100;
X		}
X		if (ship->engines > 100)
X			ship->engines = 100;
X		if (ship->life > 100)
X			ship->life = 100;
X		if (ship->crew > 100)
X			ship->crew = 100;
X		if (ship->hull > 100)
X			ship->hull = 100;
X		if (ship->torps > 100)
X			ship->torps = 100;
X		if (ship->lasers > 100)
X			ship->lasers = 100;
X		if (ship->mines > 100)
X			ship->mines = 100;
X		if (ship->numtorps > num_torps[ship->type])
X			ship->numtorps = num_torps[ship->type];
X		if (ship->nummines > num_mines[ship->type])
X			ship->nummines = num_mines[ship->type];
X		if (ship->nummines < 0)
X			ship->nummines = 0;
X		if (ship->numtorps < 0)
X			ship->numtorps = 0;
X		storegrid(extx, exty, onegrid);
X	}
X	sprintf(tmp, "%s (%c) leaves COSMOS", ship->name, ship->token);
X	putmsg(tmp);
X	if ((!status) && (!limited))
X		saveship(extx, exty);		/* Save position */
X	clear();
X	refresh();
X	endwin();
X	printf("Leaving the game with %d points\n", ship->points);
X	readgrid(extx, exty, &onegrid);		/* Delete ship */
X	onegrid.type = EMPTY;
X	storegrid(extx, exty, onegrid);
X	namebuf.token = ship->token;
X	tempint = locship(&namebuf, 1);
X	namebuf.token = 0;
X	namebuf.name[0] = 0;
X	storename(tempint, namebuf);
X	release(semid);
X	puts("Good bye!");
X	shmdt(buffer);				/* Detach shared segment */
X#ifdef	ACCOUNTING
X	delplayer(argc, argv[1]);
X#endif
X	exit(0);
X}
END_OF_FILE
if test 23237 -ne `wc -c <'cosmos.c'`; then
    echo shar: \"'cosmos.c'\" unpacked with wrong size!
fi
# end of 'cosmos.c'
fi
if test -f 'funcs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'funcs.c'\"
else
echo shar: Extracting \"'funcs.c'\" \(17674 characters\)
sed "s/^X//" >'funcs.c' <<'END_OF_FILE'
X/*	Spacewar	- The final frontier
X
X	This package is Copyright 1988 Karl Denninger.  All rights reserved.
X	
X	All unauthorized mutants shall be destroyed, fed to vermin, and the
X	remains from this process will be prosecuted.
X
X*/
X
X/*	Definitions go below - Make sure you have these in front of include
X	files as these definitions should override the include files	*/
X
X#include	"cosmos.h"
X
extern	char	*buffer;
extern	int	quit;
extern	char	home[128];
X
extern	struct	nameblock	*ship;
extern	struct	nameblock	name[MAXSHIPS];
extern	struct	grid		onegrid;
extern	int	extx, exty, window;
X
extern	int	oldchar;		/* The character pre-read */
extern	int	foundchar;		/* If one was pre-read */
X
extern	int	drone;			/* If this is a drone ship */
extern	int	squares[];
X
char	xq[2] = {7, 0};
X
execit(file, arg0)
char	*file;
char	*arg0;
X{
X	if (!fork()) { 			/* If child */
X		close(0);
X		close(1);
X		close(2);
X		setpgrp();
X		execlp(file, arg0, (char *) NULL);
X		exit(0);
X	} 
X	return;
X}
X
void die()
X{
X	signal(SIGHUP, SIG_IGN);		/* Ignore further hangups */
X	quit++;					/* Insure we exit */
X	return;
X}
X
sqr(x)
int	x;
X{
X	int	last[2];
X	int	llim = 0;
X	int	ulim = SIZE;
X	int	p;
X	
X	last[0] = (SIZE / 2);
X	last[1] = 0;
X	
X	if (!x)
X		return(0);
X	while (x != squares[last[0]]) {
X		if ((squares[last[0]] <= x) && (squares[last[0] + 1] > x))
X			return(last[0]);
X		if (squares[last[0]] < x) {	/* If we're too low */
X			llim = last[0];		/* Lower limit reset */
X			p = last[0] + ((ulim - last[0]) / 2);
X			last[1] = last[0];
X			last[0] = p;
X		} else {
X			ulim = last[0];		/* If too high */
X			p = last[0] - ((last[0] - llim) / 2);
X			last[1] = last[0];
X			last[0] = p;
X		}
X	}
X	return(last[0]);
X}
X
X
void	clrin()
X{
X
X	signal(SIGINT, clrin);		/* Reset handler */
X	ioctl(0, TCFLSH, 0);		/* Flush input */
X	return;
X}
X
void	beep()
X{	
X	
X	write(1, xq, 1);
X	return;
X}
X
X#ifndef	M_TERMINFO
X
char	*get_str(string)		/* Get a string with proper echoing */
char	*string;
X{
X	char	*ptr;
X	int	key;
X	
X	ptr = string;
X	while ((key = getchx()) != 10) {		/* While not newline */
X		if (key == 13) 
X			return(string);
X		if ((key == 8) || (key == 127))	{ 	/* Backspace? */
X			if (ptr != string) {		/* If not empty */
X				ptr--;
X				*ptr = 0;
X				addch(8);
X				addch(32);
X				addch(8);
X			} else 
X				continue;
X		} else {
X			*ptr = key;
X			ptr++;
X			addch(key);
X		}
X		refresh();
X	}
X	*ptr = 0;		/* Null terminate */
X	refresh();
X	return(string);
X}
X	
X#else
X
get_str(string)
char	*string;
X{
X
X	echo();
X	getstr(string);
X	noecho();
X	return;
X}
X#endif
X
X/* Give direction code from source to destination  */
X
give_dir(x, y, destx, desty)
int	x;
int	y;
int	destx;
int	desty;
X{
X	int	xx, yy;
X	int	key = 0;
X
X	xx = abs(x - destx);		/* Get absolute distances */
X	yy = abs(y - desty);
X	if (!xx && !yy)			/* If both are 0 away... */
X		return(-1);		/* We are there */
X	if (xx == yy) {				/* If equal then use diagonal */
X		if ((x < destx) && (y < desty))	/* If going up and right */
X			key = '9';		/* Enter '9' */
X		if ((x < destx) && (y > desty))	/* If going down and right */
X			key = '3';		/* Enter '3' */
X		if ((x > destx) && (y < desty))	/* If going up and right */
X			key = '7';		/* Enter '1' */
X		if ((x > destx) && (y > desty))	/* If going up and right */
X			key = '1';		/* Enter '7' */
X	} else {				/* Otherwise move horiz. */	
X		if (xx > yy) {			/* If 'x' axis is longer */
X			if (x < destx)		/* If we're left of dest */
X				key = '6';	/* Move that way */
X			else
X				key = '4';	/* If we're right of dest */
X		} else {
X			if (y < desty)		/* If we're left of dest */
X				key = '8';	/* Move that way */
X			else
X				key = '2';	/* If we're right of dest */
X		}
X	}
X	return(key);				/* Return direction code */
X}
X
enter_smove(x, y, semid)
int	*x, *y;
int	semid;
X{
X	static	char	line[80];
X	int	key;
X	char	tmp[80];
X	
X	if (ship->type < 3) {		/* If a dinky ship return */
X		mvaddstr(23,20,"Captain, we don't have a navigational mode.");
X		clrtoeol();
X		return(0);
X	}
X	release(semid);
X	mvaddstr(22,20,"Destination -> ");
X	refresh();
X	get_str(tmp);
X	acquire(semid);
X	if (tmp[0] == 0) {		/* If line is blank */
X		if (line[0] == 0)	/* If no prior move */
X			return(0);	/* do nothing at all */
X		strcpy(tmp, line);	/* Otherwise resume old destination */
X		move(23,20);
X		printw("Resuming course to %s", tmp);
X	} else 
X		strcpy(line, tmp);	/* Save coordinates for later use */
X	return(sscanf(tmp, "%d %d", x, y));
X}
X
X/* This routine locates the closest of an object or class of objects within
X   the screen window.  Used all over the place, especially by the drone.  */
X
int	findobj(x, y, dist, lowobj, highobj, window)/* Locate direction */
int	*x, *y;					/* Current location */
int	*dist;					/* Distance to object */
int	lowobj, highobj;			/* Object desired */
int	window;
X	
X{
X	struct	grid	ourgrid;	/* Grid entry */
X	int	xx, yy;			/* Temporary storage for search */
X	int	retval = 0;
X	int	xr, yr;
X	int	lastfound;
X	int	dx, dy, dt;
X	
X	lastfound = (window/2) + 1;	/* Initial location vector */
X	for (xx = (*x - (window/2)); xx <= (*x + (window/2)); xx++) {
X		for (yy = (*y - (window/2)); yy <= (*y + (window/2)); yy++) {
X			if ((xx >= 0) && (xx < SIZE) && (yy >= 0) && (yy < SIZE)) {
X				readgrid(xx, yy, &ourgrid);
X				dx = abs(xx - *x);
X				dy = abs(yy - *y);
X				if (dx > dy)
X					dt = dx;
X				else
X					dt = dy;
X				if ((ourgrid.type >= lowobj) && 
X					(ourgrid.type <= highobj) && 
X					(ourgrid.type != ship->token) && 
X#ifdef	FASTMATH
X					(sqr((dx * dx) + (dy * dy)) < lastfound)  
X					)  {
X						lastfound = (int) sqr((dx * dx) + (dy * dy));
X#else
X					(dt < lastfound)  
X					)  {
X						lastfound = dt;
X#endif
X						retval = give_dir(*x, *y, xx, yy);
X						xr = xx; yr = yy;
X				}
X			}
X		}
X	}
X	*dist = lastfound;		/* Show distance to target */
X	*x = xr;			/* Where it was found */
X	*y = yr;			/* in x,y notation system */
X	return(retval);			/* Exit w/character to get there */
X}
X
X
X#ifdef	NO_RDCHK
X
int	getchx()
X
X{
X	int	chx;
X	if (!foundchar) {
X		read(0,&chx,1);
X		return(chx & 127);
X	} else {
X		foundchar = 0;
X		return(oldchar & 127);
X	}
X}
X
X
int	rdchkx(fd)
int	fd;
X{
X	char	chx[2];
X	int	flagtx;
X	int	tmpx;
X
X	if (foundchar == 0) {
X		flagtx = fcntl(0, F_GETFL, 0);		/* Get flags */
X		flagtx |= O_NDELAY;			/* turn O_NDELAY on */
X		fcntl(0, F_SETFL, flagtx);		/* Set it */
X		tmpx = read(0, chx, 1);
X		if (tmpx > 0) {
X			foundchar++;			/* We have one */
X			oldchar = chx[0];		/* Save the character */
X		} 
X		flagtx = fcntl(0, F_GETFL, 0);		/* Get flags */
X		flagtx &= ~O_NDELAY;			/* turn O_NDELAY on */
X		fcntl(0, F_SETFL, flagtx);		/* Set it */
X	} 
X	return(foundchar);				/* Tell 'em if read */
X}
X
X#else
X
rdchkx(fid)
int	fid;
X{
X	return(rdchk(fid));
X}
X
getchx()
X{
X	return(getch());
X}
X
X#endif
X
extern	void 	givedamage();
X
X
int	proximity(x, y, unit, distance, itemx, itemy)
int	x, y;
int	unit;
int	distance;
int	*itemx, *itemy;
X{
X	struct	grid	mygrid;
X	int	xx, yy;
X	int	exitval = 0;
X
X	for (xx = (x - distance); xx <= (x + distance); xx++) {
X		for (yy = (y - distance); yy <= (y + distance); yy++) {
X			if ((xx != x) || (yy != y)) {
X				readgrid(xx, yy, &mygrid);
X				if (unit) {
X					if (mygrid.type == unit) {
X						exitval = 1;
X						*itemx = xx;
X						*itemy = yy;
X						break;
X					}
X				} else {
X
X					if ((mygrid.type >= 'A') && (mygrid.type <= 'Z')) {
X						exitval = 1;
X						*itemx = xx;
X						*itemy = yy;
X						break;
X					}
X					if (mygrid.type == BASE) {
X						exitval = 2;
X						*itemx = xx;
X						*itemy = yy;
X						break;
X					}
X				}
X			}
X		}
X	}
X	return(exitval);
X}
X
void	explode(x, y, energy, dia)	/* Explode - take damage next to boom */
int	x, y, energy;
int	dia;				/* Diameter of the blast */
X
X/*	This can be recursively called, do not use static variables!	*/
X
X{
X	int	xx, yy;
X	struct	grid	expgrid;
X	char	tmp[80];
X	int	radius;
X	int	dx, dy, dt;
X
X	radius = dia / 2;		/* Divide by 2, produce radius */
X
X	sprintf(tmp, "Explosion at %d %d!", x, y);
X	putmsg(tmp);
X	if (drone == 0)
X		refresh();
X	for (xx = (x - radius); xx <= (x + radius); xx++) {
X		for (yy = (y - (radius)); yy <= (y + (radius)); yy++) {
X			if ((xx >= 0) && (xx < SIZE) && (yy >= 0) && (yy < SIZE )) {
X				dx = abs(xx - x);
X				dy = abs(yy - y);
X				if (dx > dy)
X					dt = dx;
X				else
X					dt = dy;
X				readgrid(xx, yy, &expgrid);
X				if ((xx != x) || (yy != y)) {
X#ifdef	FASTMATH
X					givedamage(xx, yy, (int) energy / (int) sqr(((dx * dx) + (dy * dy))), (char *) NULL, 1);
X#else
X					givedamage(xx, yy, (int) energy / dt, (char *) NULL, 1);
X#endif
X				}
X			}
X		}
X	}
X	return;
X}
X
void	showplayers(semid, docked)/* Show the players in the game */
int	semid;
int	docked;
X{
X	int	x, count;
X	struct	nameblock	entry;
X	struct	passwd		*psw;
X
X	release(semid);
X	erase();
X	if (docked)
X		mvaddstr(1,15,"Ships in Use - From The Galactic Intelligence Agency");
X	else
X		mvaddstr(1,15," Your ships' status in points, class & token");
X	mvaddstr(3,0,"Tkn   User          Ship Name               Class            Points");
X	x = 4;
X	count = 0;
X	while (count < MAXSHIPS) {
X		readname(count, &entry);
X		if (entry.token) {
X			if (entry.human)
X				psw = getpwuid(entry.uid);
X			else
X				psw = NULL;
X			if (entry.token == ship->token)
X				standout();
X			if ((entry.token == ship->token) || (docked)) {
X				entry.name[MAXNAME-1] = 0;/* Just in case */
X				mvaddch(x,1,entry.token);
X				if ((psw != NULL) && (entry.human))
X					mvaddstr(x,6,psw->pw_name); 
X				mvaddstr(x,20,entry.name);
X				move(x,44);
X				addstr(shiptypes[entry.type]);
X				move(x,61);
X				printw("%ld", entry.points);/* Current points */
X				x++;
X			}
X			if (entry.token == ship->token)
X				standend();
X		}
X		count++;
X	}
X	mvaddstr(23,0,"<<<ENTER>>> To Continue Your Game (others are still playing!)");
X	refresh();
X	x = getchx();
X	erase();
X	acquire(semid);
X	return;
X}
X
int	cdock(x, y, window)
int	x, y;
int	*window;
X{
X	int	xx, yy;
X	int	dist;
X	int	located;
X
X	xx = x; yy = y;
X	located = findobj(&xx, &yy, &dist, BASE, BASE, *window);
X	if ((abs(xx - x) < 2) && (abs(yy - y) < 2))  {
X		while (ship->points > pts[ship->type]) {
X			ship->type++;
X			ship->energy = (long) e_require[ship->type];
X			*window = window_size[ship->type];	/* Change viewer */
X		}
X		return(1);
X	} else
X		return(0);
X}
X
int	dock(x, y, window)
int	x, y;
int	*window;
X{
X
X	int	xx = -1;
X	int	yy = -1;
X	int	retval = 0;
X	struct	grid	tmpgrid;
X	int	negbase;
X
X	for (xx = -1; xx < 2; xx++) {
X		for (yy = -1; yy < 2; yy++) {
X			if (((xx + x) >= 0) && ((yy + y) >= 0) && ((xx + x) < SIZE) && ((yy + y) < SIZE)) {
X				readgrid((x + xx), (y + yy), &onegrid);
X				if ((onegrid.type == BASE) || (onegrid.type == NEGBASE)) {
X					if (onegrid.align == ship->align ) {
X						retval++;
X						negbase = onegrid.type;
X					} else {
X						mvaddstr(23,20,"Not your alliance!");
X						clrtoeol();
X					}
X				}
X			}
X		}
X	}
X	if (retval == 0) {
X		mvaddstr(23,20,"Nothing to dock with in range Sir.");
X		clrtoeol();
X	} else {
X		while (ship->points > pts[ship->type]) {
X			beep();
X			(ship->type)++;
X			move(23,20);
X			printw("Congratuations!  You now command a %s", shiptypes[ship->type]);
X			clrtoeol();
X			*window = window_size[ship->type];	/* Change viewer */
X			ship->energy = e_require[ship->type];	/* Get max energy */
X			clear();
X			readgrid(x, y, &tmpgrid);
X			tmpgrid.energy = ship->energy;
X			storegrid(x, y, tmpgrid);
X		}
X	}
X	if (negbase == '-') 
X		retval = -1;
X	return(retval);
X}
X	
putmsg(msg)
char	*msg;
X
X{
X	
X	char	*ptr;
X	struct	grid	onegrid;
X	struct	nameblock	name;
X	int	*cur_msg;
X	long	sizegrid;
X	int	msgnum;
X
X	sizegrid = (sizeof(onegrid) * SIZE * SIZE);
X	cur_msg = (int *) (buffer + sizeof(ccount) + (sizeof(name) * MAXSHIPS) + sizegrid);
X	msgnum = *cur_msg;
X	ptr = (char *) cur_msg;			/* Get pointer */
X	ptr += sizeof(msgnum);			/* Point past index */
X	ptr += (msgnum * MSGLEN);		/* Point to next msg to store */
X	strncpy(ptr, msg, 39);			/* Store message */
X	*(ptr + 35) = 0;			/* Null terminate at 35 chars */
X	msgnum++;
X	if (msgnum >= MAXMSG)
X		msgnum = 0;
X	*cur_msg = msgnum;
X	return(0);
X}
X
dspmsg()
X{
X
X	static	int	current_msg;
X	static	int	last_placed = 0;
X	int	dispmsg;
X	char	*ptr;
X	struct	grid	onegrid;
X	struct	nameblock	name;
X	static	char	msg0[40] = {0};
X	static	char	msg1[40] = {0};
X	static	char	msg2[40] = {0};
X	static	char	msg3[40] = {0};
X	int	*iptr;
X
X	iptr = (int *) (buffer + sizeof(ccount) + (sizeof(name) * MAXSHIPS) + (sizeof(onegrid) * SIZE * SIZE));
X	current_msg = *iptr++;
X	ptr = (char *) iptr;
X	while (last_placed != current_msg) {
X		strcpy(msg3, msg2);		/* Everyone down one */
X		strcpy(msg2, msg1);
X		strcpy(msg1, msg0);
X		strcpy(msg0, (ptr + (MSGLEN * last_placed)));
X		last_placed++;
X		if (last_placed == MAXMSG) {
X			last_placed = 0;
X		}
X	}
X	mvaddstr(21,44,msg0);
X	clrtoeol();
X	mvaddstr(20,44,msg1);
X	clrtoeol();
X	mvaddstr(19,44,msg2);
X	clrtoeol();
X	mvaddstr(18,44,msg3);
X	clrtoeol();
X	return(0);
X}
X
X
saveship(x, y)
int	x, y;
X{
X	
X	int	uid;
X	int	fid;
X	char	fname[80];
X	int	count;
X	struct	shiprecord	record;
X
X	uid = getuid();			/* Who are we (really) */
X	sprintf(fname, "%s/space.scorefile", HOMEDIR);
X	if ((fid = open(fname, O_RDWR|O_CREAT, 0660)) < 0) {
X		perror("scorefile");
X		endwin();
X		return(1);
X	}
X	count = 0;
X	while (read(fid, &record, sizeof(record)) == sizeof(record)) {
X		if (record.uid == uid)  {
X			count++;		/* Found record */		
X			lseek(fid, 0L - (sizeof(record)), 1);
X			break;
X		}
X	}
X	record.points = ship->points;
X	record.uid = uid;
X	record.type = ship->type;
X	record.x = x;
X	record.y = y;
X	record.energy = ship->energy;
X	strcpy(record.shipname, ship->name);
X	if (write(fid, &record, sizeof(record)) != sizeof(record))
X		perror("saveship");
X	close(fid);
X	return(0);
X}
X
penalize()
X{
X	
X	int	uid;
X	int	fid;
X	char	fname[80];
X	int	count;
X	struct	shiprecord	record;
X
X	uid = getuid();			/* Who are we (really) */
X	sprintf(fname, "%s/space.scorefile", HOMEDIR);
X	if ((fid = open(fname, O_RDWR|O_CREAT, 0660)) < 0) {
X		perror("scorefile");
X		endwin();
X		return(1);
X	}
X	count = 0;
X	while (read(fid, &record, sizeof(record)) == sizeof(record)) {
X		if (record.uid == uid)  {
X			count++;		/* Found record */		
X			lseek(fid, 0L - (sizeof(record)), 1);
X			break;
X		}
X	}
X	if (count > 0) {
X		record.points = (ship->points / 2);
X		ship->points = ship->points / 2;
X		record.uid = uid;
X		if (record.type > 1)			/* Demoted... */
X			record.type--;
X		record.energy = e_require[record.type];	/* Energy starting */
X		record.x = roll(SIZE);
X		record.y = roll(SIZE);
X		strcpy(record.shipname, ship->name);
X		write(fid, &record, sizeof(record));
X	}
X	close(fid);
X	return(0);
X}
X
X
int	roll(max) 
int	max;
X{
X	int	x;
X	int	mult;
X
X	mult = 32767/max;		/* Counts per unit */
X	x = rand();
X	return(x / mult);
X}
X
X
int	locship(entry, flag)
struct	nameblock	*entry;
int	flag;
X
X{
X	int	b = 0;
X	static	int	match;			/* Match indicator */
X	struct	nameblock locbuf;
X	
X	match = -1;
X	while (b < MAXSHIPS) {
X		readname(b, &locbuf);
X		if (flag == 0) {
X			if (strcmp(locbuf.name, entry->name) == 0) {
X				match = b;
X				break;
X			}
X		} else {
X			if (locbuf.token == entry->token) {
X				match = b;
X				break;
X			}
X		}
X		b++;
X	}
X	return(match);
X}
X
X
X
X
acquire(semid)
int	semid;
X{
X	semoper(semid, -1);
X}
X
release(semid)
int	semid;
X{
X	semoper(semid, 1);
X}
X
semoper(semid, op)
int	semid;
int	op;
X
X{
X	struct	{
X		short	sem_num;
X		short	sem_op;
X		short	sem_flg;
X	} sembuf;
X
X	sembuf.sem_num = 0;
X	sembuf.sem_op = op;
X	sembuf.sem_flg = 0;
X	signal(SIGINT, SIG_IGN);
X	if (semop(semid, &sembuf, 1) == -1) {	
X		if (drone == 0)
X			endwin();
X		perror("semop");
X		puts("FATAL ERROR: Please re-run the game");
X		exit(1);
X	}
X	signal(SIGINT, clrin);
X}
X
showfile(file, semid, ind)
char	*file;
int	semid;
int	ind;
X{
X	int	x = 0, y;
X	FILE	*fid;
X	char	tmp[80];
X	int	key;
X
X	release(semid);
X	clear();
X	sprintf(tmp, "%s/%s", HOMEDIR, file);
X	if ((fid = fopen(tmp, "r")) == NULL)  {
X		acquire(semid);
X		return;
X	}
X	if (ind) {
X		x = 2;
X		mvaddstr(0,0,"--> COSMOS Online Library Display               Status >> ");
X		mvaddstr(1,0,"-------------------------------------------------------------------------------");
X	} else
X		x = 0;
X	while (fgets(tmp, 80, fid) != NULL) {
X		if (x >= 22) {
X			if (ind) {
X				mvaddstr(22,0,"-------------------------------------------------------------------------------");
X			}
X			mvaddstr(23,0,"             <<<< SPACE >>>> for the next page, <Q> to quit");
X			if (ind) {
X				while (!rdchkx(0)) {
X					if (calcstatus(extx, exty, window, 0))  {
X						standout();
X						mvaddstr(0,60,"RED");
X						standend();
X					} else
X						mvaddstr(0,60,"GREEN");
X					clrtoeol();
X					refresh();
X					sleep(1);
X				}
X			}
X			refresh();
X			key = getchx();
X			if (ind) {
X				for (y = 2; y < 22; y++) {
X					move(y, 0);
X					clrtoeol();
X				}
X			} else {
X				for (y = 0; y < 23; y++) {
X					move(y, 0);
X					clrtoeol();
X				}
X			}
X			if ((key == 'q') || (key == 'Q'))  {
X				acquire(semid);
X				erase();
X				return;
X			}
X			if (ind)
X				x = 2;
X			else
X				x = 0;
X		}
X		mvaddstr(x++, 0, tmp);
X		clrtoeol();
X	}
X	fclose(fid);
X	refresh();
X	(void) getchx();
X	erase();
X	acquire(semid);
X	return;
X}
X
readname(x, entry)
int	x;
struct	nameblock *entry;
X{
X	struct	nameblock locrec;
X	char	*ptr;
X
X	ptr = buffer + sizeof(ccount) + (sizeof(locrec) * x);
X	memcpy(entry, ptr, sizeof(locrec));
X	return(0);
X}
X
char	*storename(x, entry)
int	x;
struct	nameblock entry;
X{
X	char	*ptr;
X
X	ptr = buffer + sizeof(ccount) + (sizeof(entry) * x);
X	return((char *) memcpy(ptr, &entry, sizeof(entry)));
X}
X
readgrid(x, y, entry) 
int	x;
int	y;
struct	grid	*entry;
X
X{
X	int	incr;
X	char	*ptr;
X	long	*ptrl;
X	
X	incr = sizeof(ccount) + sizeof(name) + (x * sizeof(onegrid) * SIZE);
X	incr += y * sizeof(onegrid);
X	ptr = (buffer + incr);
X	memcpy(entry, ptr, sizeof(onegrid));
X	return(0);
X}
X
storegrid(x, y, entry) 
int	x;
int	y;
struct	grid	entry;
X{
X	int	incr;
X	char	*ptr;
X
X	incr = sizeof(ccount) + sizeof(name) + (x * sizeof(onegrid) * SIZE);
X	incr += y * sizeof(onegrid);
X	ptr = (buffer + incr);
X	memcpy(ptr, &entry, sizeof(entry));
X	return(0);
X}
END_OF_FILE
if test 17674 -ne `wc -c <'funcs.c'`; then
    echo shar: \"'funcs.c'\" unpacked with wrong size!
fi
# end of 'funcs.c'
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 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

--
Karl Denninger (karl@ddsw1.MCS.COM, ddsw1!karl)
Data: [+1 312 566-8912], Voice: [+1 312 566-8910]
Macro Computer Solutions, Inc.    	"Quality solutions at a fair price"