[net.sources.games] Trek73 Bug Fixes

okamoto@ucbvax.BERKELEY.EDU (The New Number Who) (12/19/86)

This article consists of some fixes to problems mailed to me
since trek73 has been posted.  The source files included here
should replace their original couterparts.

Bugs fixed include:
	parsit.c - a fix that I had long ago thought corrected
		is in the loop that frees up the array.  SYSV
		and BSD handle this loop differently.  This fix
		should clear up segmentation violations that
		occur upon typing the second command.
	save.c - Some of the BSD-specific things have ben fixed.
		It may not work the same, and for that I apologize.
		I culled the save routines from rogue.
	Makefile - Fixed and added stuff so parsit should compile
		correctly.

The New Number Who,	okamoto@ucbvax.berkeley.edu
Jeff Okamoto		..!ucbvax!okamoto

-----Cut here-----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	dist.c
#	parsit.c
#	save.c
#	shipyard.c
#	subs.c
# This archive created: Fri Dec 19 12:15:50 1986
# By:	Jeff Okamoto ()
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# Makefile for TREK73
#

#
# Select which operating system you are using.
# Acceptable flags are BSD and SYSV.
#
OS =	BSD

#
# Select method of installing the binaries into the system
# NOTE: UNIX System V Release 2.0 does not have install
# and should therefore use either mv or cp.
#
INSTALL = install

#
# Select destination directory in the system.
# This option need only be set when actually ready to install
# the binaries.
#
DESTDIR = /usr/games

#
# Select whether you wish to use symbolic debugger or not.
# NOTE: UNIX System V Release 2.0 cannot do profiling on programs
# compiled with -g.  Also, sdb will not be very useful if the
# symbols are stripped from the load module. (See STRIP)
#SDB =	-g
SDB =

#
# Select whether code optimization is to be done.
OPT =	-O
#OPT =

#
# Select whether profiling is to be done.
# NOTE: In System V Relase 2.0, this is incompatible with
# both SDB and STRIP.
# PROF =	-p
PROF =

#
# Select whether or not the load module is to be stripped.
# This is incompatible with both SDB and PROF.
# Note: In BSD Unix, this option should always be blank
# STRIP =	-s
STRIP =

#
# Select whether or not tracing mode is to be turned on.
# This is useful when testing new strategies.
#TRACE =	-DTRACE
TRACE =


DEFINES = -D${OS}
CFLAGS = ${DEFINES} ${SDB} ${OPT} ${PROF} ${STRIP}

T73OBJECTS = cmds1.o cmds2.o cmds3.o cmds4.o damage.o dist.o endgame.o\
	enemycom.o firing.o globals.o init.o main.o misc.o mission.o\
	moveships.o parseopts.o parsit.o save.o ships.o special.o\
	strat1.o subs.o vers.o

T73CFILES = cmds1.c cmds2.c cmds3.c cmds4.c damage.c dist.c endgame.c\
	enemycom.c firing.c globals.c init.c main.c misc.c mission.c\
	moveships.c parseopts.c pXrsit.c save.c ships.c special.c\
	strat1.c subs.c vers.c

BPVOBJECTS = bpv.o ships.o

BPVFILES = bpv.c ships.c

DYOOBJECTS = shipyard.o

DYOFILES = shipyard.c

HEADS= structs.h defines.h externs.h

RDIST = ${T73CFILES} ${BPVFILES} ${DYOFILES} ${HEADS}

LIBS= -lm

FLUFF = parsit.o make.out errs core lint.errs a.out tags\
	shar.1 shar.2 shar.3 shar.4

BINS = trek73 bpv shipyard


all:	${BINS}

trek73:	${T73OBJECTS} parsit.o
	cc ${CFLAGS} ${T73OBJECTS} parsit.o ${LIBS}
	mv a.out trek73

bpv:	${BPVOBJECTS}
	cc ${CFLAGS} ${BPVOBJECTS}
	mv a.out bpv

shipyard:	${DYOOBJECTS}
	cc ${CFLAGS} ${DYOOBJECTS} -lm
	mv a.out shipyard

install:	${BINS}
	${INSTALL} trek73 ${DESTDIR}
	${INSTALL} bpv ${DESTDIR}
	${INSTALL} shipyard ${DESTDIR}

${T73OBJECTS}: ${HEADS}

${BPVOBJECTS}: ${HEADS}

${DYOOBJECTS}: ${HEADS}

tags: ${T73CFILES}
	ctags ${T73CFILES} ${HEADS}

count:
	wc ${T73CFILES} ${HEADS}

lint:
	lint -abchx ${DEFINES} ${T73CFILES} > lint.errs

clean:
	rm -f ${BINS} ${T73OBJECTS} ${DYOOBJECTS} ${BPVOBJECTS} ${FLUFF}

shar: shar.1 shar.2 shar.3 shar.4

shar.1: Makefile defines.h externs.h options.h structs.h cmds1.c cmds2.c
	shar Makefile defines.h externs.h options.h structs.h cmds1.c cmds2.c >$@

shar.2: cmds3.c cmds4.c damage.c dist.c endgame.c enemycom.c
	shar cmds3.c cmds4.c damage.c dist.c endgame.c enemycom.c >$@

shar.3: firing.c globals.c init.c main.c misc.c mission.c bpv.c shipyard.c
	shar firing.c globals.c init.c main.c misc.c mission.c bpv.c shipyard.c >$@

shar.4: moveships.c parseopts.c parsit.c save.c ships.c special.c strat1.c subs.c vers.c 
	shar moveships.c parseopts.c parsit.c save.c ships.c special.c strat1.c subs.c vers.c >$@ 
SHAR_EOF
chmod +x 'Makefile'
fi # end of overwriting check
if test -f 'dist.c'
then
	echo shar: will not over-write existing file "'dist.c'"
else
cat << \SHAR_EOF > 'dist.c'
/*
 * TREK73: dist.c
 *
 * Power distribution routines
 *
 * distribute
 *
 */

#include "externs.h"


distribute(sp)
struct ship *sp;
{
	register int i;
	register float fuel;
	register int load;
	register int effload;
	register int drain;
	register int loop;
	float shield;
	struct ship *fed;

	fed = shiplist[0];
	/*
	 * Granularity of 1 second as far as this loop is concerned
	 */
	for (loop = 0; loop < (int)timeperturn; loop++) {

		fuel = sp->energy + sp->regen;	/* Slightly unrealistic */
		/*
		 * Calculate negative phaser drains
		 */
		for (i=0; i<sp->num_phasers; i++) {
			load = sp->phasers[i].load;
			drain = sp->phasers[i].drain;
			if ((sp->phasers[i].status & P_DAMAGED)
			    || (drain >= 0) || (load <= 0))
				continue;
			/*
			 * Drain the lesser of either the current load if the
			 * load is less than the drain, or the drain value
			 */
			effload = max(load + drain, 0);
			fuel += load - effload;
			sp->phasers[i].load = effload;
		}
		/*
		 * Calculate shield drains
		 */
		shield = 0.0;
		for (i=0; i<SHIELDS; i++)
			shield += sp->shields[i].attemp_drain;
		drain = ceil((double) shield);
		/*
		 * If all attempted drains are zero, or we have no
		 * fuel, our shields are down!
		 */
		if ((shield * fuel == 0) && !shutup[SHIELDSF]
		    && sp == shiplist[0]) {
			printf("%s: %s, our shields are down!\n",engineer, title);
			shutup[SHIELDSF]++;
		}
		/*
		 * If there's not enough fuel to sustain the drains, then
		 * ration it out in proportion to the attempted drains and
		 * say that shields are fluctuating.
		 */
		if (drain <= fuel) {
			fuel -= drain;
			for (i=0; i<SHIELDS; i++)
				sp->shields[i].drain = sp->shields[i].attemp_drain;
		} else {
			if (!shutup[SHIELDSF] && sp == shiplist[0]) {
				printf("%s: %s, our shields are fluctuating!\n",
				    engineer, title);
				shutup[SHIELDSF]++;
			}
			for (i=0; i<SHIELDS; i++)
				sp->shields[i].drain =
				    sp->shields[i].attemp_drain *
				    fuel / drain;
			fuel = 0.;
		}
		/*
		 * Calculate cloaking device drains.  If there is
		 * in sufficient energy to run the device, then
		 * it is turned off completely
		 */
		if (cantsee(sp)) {
			if (fuel < sp->cloak_energy) {
				if (sp == shiplist[0]) {
					sp->cloaking = C_OFF;
					printf("%s:  %s, there's not enough energy to",
					    engineer, title);
					puts("    keep our cloaking device activated.");
				} else
					(void) e_cloak_off(sp, fed);
			} else
				fuel -= sp->cloak_energy;
		}
		/*
		 * Calculate positive phaser drains
		 */
		for (i=0; i<sp->num_phasers && fuel > 0; i++) {
			if (fuel <=0.)
				break;
			load = sp->phasers[i].load;
			drain = sp->phasers[i].drain;
			if ((sp->phasers[i].status & P_DAMAGED)
			    || load >= MAX_PHASER_CHARGE || drain <= 0)
				continue;
			/*
			 * Load phasers either enough to top them off, or
			 * the full drain
			 */
			effload = min(MAX_PHASER_CHARGE,
			    load + min(drain, fuel));
			fuel -= effload - load;
			sp->phasers[i].load = effload;
		}
		/*
		 * Now balance the level of energy with the numer of pods
		 */
		sp->energy = min(fuel, sp->pods);
	}
}
SHAR_EOF
chmod +x 'dist.c'
fi # end of overwriting check
if test -f 'parsit.c'
then
	echo shar: will not over-write existing file "'parsit.c'"
else
cat << \SHAR_EOF > 'parsit.c'
/*
 * TREK73: parsit.c
 *
 * Parse and get input
 *
 * Gets, parsit (courtesy, P. Lapsley)
 *
 */

#ifdef SYSV
#define index strchr
#endif

#include <stdio.h>
extern void free();
extern char *gets(), *malloc(), *strcpy(), *index();

static int gindx;
static char **argv;

char *
Gets(buf, len)
char *buf;
int len;
{
	register char *tmp;

	if (argv[gindx] == NULL) {
		(void) fgets(buf, len, stdin);
		if (tmp = index(buf, '\n'))
			*tmp = '\0';
		return(buf);
	}
	++gindx;
	if (argv[gindx] == NULL) {
		(void) fgets(buf, len, stdin);
		if (tmp = index(buf, '\n'))
			*tmp = '\0';
		return (buf);
	}
	(void) strcpy (buf, argv[gindx]);
	puts (buf);
	return (buf);
}

/*
** parsit.c  23 September 1984  P. Lapsley (phil@Berkeley.ARPA)
**
** Parse a string of words separated by spaces into an
** array of pointers to characters, just like good ol' argv[]
** and argc.
**
** Usage:
**
** char line[132];
** char **argv;
** int argc;
**
**	argv = (char **) NULL;
**	argc = parsit(line, &argv);
**
** returns the number of words parsed in argc.  argv[argc] will
** be (char *) NULL to indicate end of list, if you're not
** happy with just knowing how many words you have.
**
** Note that setting argv = (char **) NULL is only done the first
** time the routine is called with a new "argv" -- it tells
** parsit that "argv" is a new array, and parsit shouldn't free
** up the elements (as it would do if it were an old array).
*/


parsit(line, array)
char *line;
char ***array;
{
	char *malloc();
	char word[132];
	char *linecp;
	int i, j, num_words;

	gindx = 0;
	argv = *array;
	if (argv != (char **) NULL) {  /* Check to see if we should */
		/* free up the old array */
		for (i=0; argv[i] != (char *) NULL; i++) {
			free(argv[i]);	/* If so, free each member */
		}
		free((char *)argv);		/* and then free the ptr itself */
	}

	linecp = line;
	num_words = 0;
	while (1) {	/* count words in input */
		for (; *linecp == ' ' || *linecp == '\t'; ++linecp)
			;
		if (*linecp == '\0')
			break;

		for (; *linecp != ' ' && *linecp != '\t' && *linecp != '\0'; ++linecp)
			;
		++num_words;
		if (*linecp == '\0')
			break;
	}

	/* Then malloc enough for that many words plus 1 (for null) */

	if ((argv = (char **) malloc((unsigned)((num_words + 1) * sizeof(char *)))) ==
		(char **) NULL) {
		fprintf(stderr, "parsit: malloc out of space!\n");
		return(0);
	}

	j = i = 0;
	while (1) {	/* Now build the list of words */
		for (; *line == ' ' || *line == '\t'; ++line)
			;
		if (*line == '\0')
			break;

		i = 0;
		for (; *line != ' ' && *line != '\t' && *line != '\0'; ++line)
			word[i++] =  *line;
		word[i] = '\0';
		argv[j] = malloc(strlen(word) + 1);
		if (argv[j] == (char *) NULL) {
			fprintf(stderr, "parsit: malloc out of space!\n");
			return(0);
		}

		(void) strcpy(argv[j], word);
		++j;
		if (*line == '\0')
			break;
	}
	argv[j] = (char *) NULL;  /* remember null at end of list */
	*array = argv;
	return(j);
}


SHAR_EOF
chmod +x 'parsit.c'
fi # end of overwriting check
if test -f 'save.c'
then
	echo shar: will not over-write existing file "'save.c'"
else
cat << \SHAR_EOF > 'save.c'
/*
 * TREK73: save.c
 *
 * save and restore routines
 *
 * @(#)save.c	4.15 (Berkeley) 5/10/82
 */

#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>

#define MAXSTR	256

typedef struct stat STAT;

extern char *sys_errlist[], version[], encstr[];
extern int errno;

char *sbrk();

STAT sbuf;

set_save()
{
	register char		*env;
	register struct passwd	*pw;
	char			*getpass();
	extern char		home[];
	extern char		savefile[];
	char			*getenv();

	if ((env = getenv("HOME")) != NULL)
		strcpy(home, env);
	else if ((pw = (struct password *)getpwuid(getuid())) != NULL)
		strcpy(home, pw->pw_dir);
	else
		home[0] = '\0';
	strcat(home, "/");

	strcpy(savefile, home);
	strcat(savefile, "trek73.save");
}

/*
 * save_game:
 *	Implement the "save game" command
 */
save_game()
{
    register FILE *savef;
    register int c;
    char buf[MAXSTR];
    extern char savefile[];

    /*
     * get file name
     */

over:
    if (savefile[0] != '\0')
    {
	for (;;)
	{
	    printf("Save file (%s)? ", savefile);
	    c = getchar();
	    if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
		break;
	    else
		printf("\nPlease answer Yes or No");
	}
	if (c == 'y' || c == 'Y')
	{
	    strcpy(buf, savefile);
	    goto gotfile;
	}
    }

    do
    {
	stdin->_cnt = 0;
	printf("File name: ");
	buf[0] = '\0';
	gets(buf);
gotfile:
	/*
	 * test to see if the file exists
	 */
	if (stat(buf, &sbuf) >= 0)
	{
	    for (;;)
	    {
		stdin->_cnt = 0;
		printf("\nFile exists.  Do you wish to overwrite it?");
		if (c == 'y' || c == 'Y')
		    break;
		else if (c == 'n' || c == 'N')
		    goto over;
		else
		    printf("\nPlease answer Y or N");
	    }
	}
	strcpy(savefile, buf);
	if ((savef = fopen(savefile, "w")) == NULL)
	    perror("Trek73: Save problems");
    } while (savef == NULL);

    /*
     * write out encrpyted file (after a stat)
     * The fwrite is to force allocation of the buffer before the write
     */
    save_file(savef);
    exit(0);
}

/*
 * save_file:
 *	Write the saved game on the file
 */
save_file(savef)
register FILE *savef;
{
    /*
     * close any open score file
     */
    fstat(fileno(savef), &sbuf);
    /*
     * DO NOT DELETE.  This forces stdio to allocate the output buffer
     * so that malloc doesn't get confused on restart
     */
    fwrite("junk", 1, 5, savef);

    fseek(savef, 0L, 0);
    encwrite(version, sbrk(0) - version, savef);
    fclose(savef);
    exit(0);
}

/*
 * restore:
 *	Restore a saved game from a file with elaborate checks for file
 *	integrity from cheaters
 */
restore(file, envp)
register char *file;
char **envp;
{
    register int inf, (*func)();
    register char syml;
    extern char **environ;
    char buf[MAXSTR];
    STAT sbuf2;

#ifdef BSD
    func = signal(SIGTSTP, SIG_IGN);
#endif
#ifdef SYSV
    func = signal(SIGQUIT, SIG_IGN);
#endif

    if ((inf = open(file, 0)) < 0)
    {
	perror(file);
	return 0;
    }
    fstat(inf, &sbuf2);
#ifdef BSD
    syml = symlink(file);
#endif
#ifdef SYSV
    syml = link(file);
#endif
    if (unlink(file) < 0)
    {
	printf("Cannot unlink file\n");
	return 0;
    }

    fflush(stdout);
    encread(buf, (unsigned int) (strlen(version) + 1), inf);
    if (strcmp(buf, version) != 0)
    {
	printf("Sorry, saved game is out of date.\n");
	return 0;
    }

    fflush(stdout);
    brk(version + sbuf2.st_size);
    lseek(inf, 0L, 0);
    encread(version, (unsigned int) sbuf2.st_size, inf);
    /*
     * we do not close the file so that we will have a hold of the
     * inode for as long as possible
     */
	if (sbuf2.st_ino != sbuf.st_ino || sbuf2.st_dev != sbuf.st_dev)
	{
	    printf("Sorry, saved game is not in the same file.\n");
	    return 0;
	}
#ifdef NOTDEF
    /*
     * defeat multiple restarting from the same place
     */
	if (sbuf2.st_nlink != 1 || syml)
	{
	    printf("Cannot restore from a linked file %d %d\n", sbuf2.st_nlink, syml);
	    """"""Cb""""b#pP"BqC"p""""""""2 """""""""""""""b"""""""""""""""""""""""""""""""""bu""""""""""""""""BP """"Q"Q#a""0
	}
#endif
    signal(SIGTSTP, SIG_DFL);

    environ = envp;
    stdin->_cnt = 0;
    playit();
    /*NOTREACHED*/
}

/*
 * encwrite:
 *	Perform an encrypted write
 */
encwrite(start, size, outf)
register char *start;
unsigned int size;
register FILE *outf;
{
    register char *ep;

    ep = encstr;

    while (size--)
    {
	putc(*start++ ^ *ep++, outf);
	if (*ep == '\0')
	    ep = encstr;
    }
}

/*
 * encread:
 *	Perform an encrypted read
 */
encread(start, size, inf)
register char *start;
unsigned int size;
register int inf;
{
    register char *ep;
    register int read_size;

    if ((read_size = read(inf, start, size)) == -1 || read_size == 0)
	return read_size;

    ep = encstr;

    while (size--)
    {
	*start++ ^= *ep++;
	if (*ep == '\0')
	    ep = encstr;
    }
    return read_size;
}

SHAR_EOF
chmod +x 'save.c'
fi # end of overwriting check
if test -f 'shipyard.c'
then
	echo shar: will not over-write existing file "'shipyard.c'"
else
cat << \SHAR_EOF > 'shipyard.c'
/*
 * TREK73: shipyard.c
 *
 * Design your own ship
 *
 */

#include <stdio.h>
#ifdef BSD
#include <strings.h>
#endif
#ifdef SYSV
#include <string.h>
#endif
#include <fcntl.h>
#include "externs.h"

char buf[20];
char class[3];
char cloak;
double bpv;
struct {
	char description[30];
	char race[30];
	char empire[30];
} stuff;

struct ship_stat design;

main()
{
	double regen, efficiency, atof(), floor(), round();
	int crew, phasers, torps, pods, max_speed, turn, p_div, t_div;
	int done, atoi();

	printf("Class identifier           :");
	gets(class);
	class[2] = '\0';
	printf("Class description          :");
	gets(stuff.description);
	stuff.description[29] = '\0';
	printf("Race name                  :");
	gets(stuff.race);
	stuff.race[29] = '\0';
	printf("Empire name                :");
	gets(stuff.empire);
	stuff.empire[29] = '\0';
	done = 0;
	while (!done) {
		printf("Regeneration               :");
		gets(buf);
		regen = atof(buf);
		if (regen >= 0)
			done = 1;
		else
			printf(">>> Be reasonable.\n");
	}
	done = 0;
	while (!done) {
		printf("Pods                       :");
		gets(buf);
		pods = atof(buf);
		if (pods >= 0)
			done = 1;
		else
			printf(">>> Be reasonable.\n");
	}
	done = 0;
	while (!done) {
		printf("Number of phasers          :");
		gets(buf);
		phasers = atoi(buf);
		if ((phasers >= 0) && (phasers < MAXWEAPONS))
			done = 1;
		else
			if (phasers < 0)
				printf(">>> Be reasonable.\n");
			else
				printf(">>> Can't have more than %d.\n",
				    MAXWEAPONS-1);
	}
	done = 0;
	while (!done) {
		printf("Number of tubes            :");
		gets(buf);
		torps = atoi(buf);
		if ((torps >= 0) && (torps < MAXWEAPONS))
			done = 1;
		else
			if (torps < 0)
				printf(">>> Be reasonable.\n");
			else
				printf(">>> Can't have more than %d.\n",
				    MAXWEAPONS-1);
	}
	done = 0;
	while (!done) {
		printf("Shield divisor for phasers :");
		gets(buf);
		p_div = atof(buf);
		if (p_div > 0)
			done = 1;
		else
			printf(">>> Be reasonable.\n");
	}
	done = 0;
	while (!done) {
		printf("Shield divisor for torps   :");
		gets(buf);
		t_div = atof(buf);
		if (t_div > 0)
			done = 1;
		else
			printf(">>> Be reasonable.\n");
	}
	done = 0;
	while (!done) {
		printf("Crew                       :");
		gets(buf);
		crew = atoi(buf);
		if (crew > 0)
			done = 1;
		else
			printf(">>> Be reasonable.\n");
	}
	printf("Can the ship cloak         ?");
	gets(buf);
	if (buf != NULL && (buf[0] == 'y' || buf[0] == 'Y'))
		cloak = 1;
	else
		cloak = 0;

	bpv = 0.;
	bpv += regen * 12;
	bpv += pods / 2;
	bpv += p_div * 30;
	bpv += t_div * 40;
	bpv += (phasers + torps) * 10;
	bpv += crew / 15;
	printf("%s: BPV = %.2f\n", class, bpv);

	efficiency = round(4 * (0.0034 * bpv - 0.78)) / 4;
	if (efficiency < 0.25)
		efficiency = 0.25;
	turn = 10 - floor(bpv / 100);
	if (turn < 1)
		turn = 1;
	max_speed = (int) round(-0.004 * bpv + 11);
	if (max_speed < 1)
		max_speed = 1;

	printf("Efficiency = %.2f\n", efficiency);
	printf("Turn = %d\n", turn);
	printf("Max speed = %d\n", max_speed);

	strcpy(design.abbr, class);
	design.num_phaser = phasers;
	design.num_torp = torps;
	design.o_warpmax = max_speed;
	design.e_warpmax = max_speed + 2;
	design.o_eff = efficiency;
	design.e_eff = efficiency;
	design.regen = regen;
	/* XXXX */
	design.energy = pods * 3 / 4;
	design.pods = pods;
	design.o_crew = crew;
	design.e_crew = crew * 5 / 4;
	design.ph_shield = p_div;
	design.tp_shield = t_div;
	design.turn_rate = turn;
	design.cloaking_energy = 4;
	/* XXXX */
	design.t_blind_left = 135;
	design.t_blind_right = 225;
	design.p_blind_left = 125;
	design.p_blind_right = 235;
	design.p_firing_delay = 4;
	design.t_firing_delay = 4;

	save_design();
}

double round(x)
double x;
{
	return( floor(x + 0.5));
}

save_design()
{
	int fd, bytes;
	char path[BUFSIZ];
	char *home, *getenv();

	if ((home = getenv("HOME")) != NULL)
		strcpy(path, home);
	else
		strcpy(path, ".");
	
	strcat(path, "/.trek");
	strcat(path, design.abbr);
	printf("Saving to file %s\n", path);
	
	if ((fd = open(path, O_WRONLY|O_CREAT, 0644)) < 0) {
		perror("open");
		exit(1);
	}
	bytes = write(fd, (char *)&design, sizeof(struct ship_stat));
	if (bytes != sizeof(struct ship_stat)) {
		fprintf(stderr, "Wrote only %d, not %d bytes\n", bytes,
		    sizeof(struct ship_stat));
		unlink(path);
		exit(1);
	}
	bytes = write(fd, &stuff, sizeof(stuff));
	bytes = write(fd, &cloak, 1);
	bytes = write(fd, (char *)&bpv, sizeof(int));
	close(fd);
}
SHAR_EOF
chmod +x 'shipyard.c'
fi # end of overwriting check
if test -f 'subs.c'
then
	echo shar: will not over-write existing file "'subs.c'"
else
cat << \SHAR_EOF > 'subs.c'
/*
 * TREK73: subs.c
 *
 * Miscellaneous Subroutines
 *
 * ship_name, newitem, delitem, rangefind, bearing, phaser_hit,
 * torpedo_hit, antimatter_hit, round, rectify
 */

#include "externs.h"
#include <ctype.h>


struct ship *ship_name(name)
char *name;
{
	register int i;
	register int j;
	register int len;

	if (isascii(*name) && islower(*name))
		*name = toupper(*name);
	j = shipnum;
	len = strlen(name);
	for (i=1; i<=j; i++) {
		if (shiplist[i]->complement < 0)
			continue;
		if (!strncmp(name, shiplist[i]->name, len))
			return shiplist[i];
	}
	printf("%s: I am unable to find the %s\n", science, name);
	return NULL;
}


struct list *newitem(item)
int item;
{
	register struct	list *new;
	register struct	list *newtail;

	/*
	 * if there's no "tail" node, make one (only happens at init)
	 */
	if (tail == NULL) {
		new = MKNODE(struct list, *, 1);
		if (new == (struct list *)NULL) {
			fprintf(stderr, "newitem: malloc failed\n");
			exit(2);
		}
		new->back = &head;
		new->fwd = NULL;
		new->data.tp = NULL;
		head.fwd = new;
		tail = new;
	}
	new = tail;
	/*
	 * now make the new tail node
	 */
	newtail = MKNODE(struct list, *, 1);
	if (newtail == (struct list *)NULL) {
		fprintf(stderr, "newitem: malloc failed\n");
		exit(2);
	}
	newtail->back = new;
	newtail->fwd = NULL;
	newtail->data.tp = NULL;
	newtail->type = 0;
	tail = newtail;
	/*
	 * link the old tail node to the new one
	 */
	new->type = item;
	new->fwd = newtail;
	return new;
}


int delitem(item)
struct list *item;
{
	register struct list *bp;
	register struct list *fp;

	bp = item->back;
	fp = item->fwd;
	if (item->data.tp != NULL)
		free((char *) item->data.tp);
	/*
	 * re-arrange pointers on both the next and the previous
	 * nodes; if no forward pointer, we were the tail so make
	 * the bp the new tail node.
	 */
	if (fp != NULL) {
		bp->fwd = fp;
		fp->back = bp;
	} else {
		tail = bp;
		bp->fwd = NULL;
	}
	free((char *) item);
}

int rangefind(xfrom, xto, yfrom, yto)
int xfrom;
int xto;
int yfrom;
int yto;
{
	register double x, y;

	x = xto - xfrom;
	y = yto - yfrom;
	if (x == 0.0 && y == 0.0)
		return 0;
	else
	return (int) hypot(x, y);
}

/*
 * This routine finds the bearing of (xto,yto) from (xfrom,yfrom)
 */
float bearing(xfrom, xto, yfrom, yto)
int xfrom;
int xto;
int yfrom;
int yto;
{
	register double x, y;
	register float bear;

	x = xto - xfrom;
	y = yto - yfrom;
	if (x == 0.0 && y == 0.0)
		bear = 0.0;
	else
		bear = todegrees(atan2(y, x));
	bear = rectify(bear);
	return bear;
}

int phaser_hit(sp, x, y, bank, true_bear)
struct ship *sp;
int x;
int y;
struct phaser *bank;
float true_bear;
{
	register int hit;
	int	i;
	float	spread;
	float	bear;
	double	d1;
	double	d2;

	hit = 0;
	i = rangefind(sp->x, x, sp->y, y);
	if (i < MAX_PHASER_RANGE) {
		bear = bearing(sp->x, x, sp->y, y);
		spread = rectify(true_bear - bear);
		/*
		 * Check if a target is within the phaser spread
		 */
		if (betw(spread, sp->p_spread, 360-spread))
			return 0;
		d1 = 1.0 - (float)i/MAX_PHASER_RANGE;
		d2 = (float)bank->load * sqrt(d1) * sp->p_percent / 100;
		/* XXXX */
		/*
		 * This may have to be changed if phaser spread or maximum
		 * phaser load is changed
		 */
		d2 = (float)bank->load * d2 * 45.0/(float)sp->p_spread * sp->p_percent / 100;
		hit = d2/10.0;
	}
	return hit;
}

int torpedo_hit(fuel, x, y, tx, ty)
int fuel;
int x;
int y;
int tx;
int ty;
{
	register int hit;
	int	i;
	double	d1;
	double	d2;
	float	f1;
	float	f2;

	hit = 0;
	i = rangefind(x, tx, y, ty);
	f1 = fuel * HIT_PER_POD;
	f2 = fuel * PROX_PER_POD;
	if (i < f2) {
		d1 = 1.0 - (float)i/f2;
		d2 = (float)f1 * sqrt(d1);
		hit = d2;
	}
	return hit;
}


antimatter_hit(ptr, x, y, fuel)
char *ptr;
int x;
int y;
int fuel;
{
	register struct list *lp;
	register int hit;
	int	tarx, tary;
	int	s;
	float	bear;
	struct 	torpedo *tp;
	struct	ship *sp;

	for (lp = &head; lp != tail; lp = lp->fwd) {
		if (lp->type == 0)
			continue;
		sp = NULL;
		tp = NULL;
		if (lp->type == I_SHIP) {
			sp = lp->data.sp;
			tarx = sp->x;
			tary = sp->y;
		} else {
			tp = lp->data.tp;
			tarx = tp->x;
			tary = tp->y;
		}
		if (sp == (struct ship *) ptr || tp == (struct torpedo *) ptr)
			continue;
		hit = torpedo_hit(fuel, x, y, tarx, tary);
		if (hit <= 0)
			continue;
		if (sp) {
			/* 
			 * Determine which shield is hit
			 */
			bear = rectify(bearing(tarx, x, tary, y) - sp->course);
			if (bear <= 45.0 || bear >= 315.0)
				s = 1;
			else if (bear <= 135.0)
				s = 2;
			else if (bear < 225.0)
				s = 3;
			else
				s = 4;
			(void) damage(hit, sp, s, &a_damage, D_ANTIMATTER);
		} else {
			if (tp->timedelay <= segment)
				continue;
			tp->timedelay = segment;
			switch (lp->type) {
				case I_TORPEDO:
					printf("hit on torpedo %d\n", 
						tp->id);
					break;
				case I_PROBE:
					printf("hit on probe %d\n", 
						tp->id);
					break;
				case I_ENG:
					printf("hit on %s engineering\n",
						tp->from->name);
					break;
				default:
					printf("hit on unknown item %d\n",
					    tp->id);
			}
		}
	}
}

float round(x)
float x;
{
	return(floor(x + 0.5));
}

float rectify(x)
float x;
{
	while (x < 0.0) {
		x += 360.0;
	}
	while (x >= 360.0){
		x -= 360.0;
	}
	return x;
}
SHAR_EOF
chmod +x 'subs.c'
fi # end of overwriting check
#	End of shell archive
exit 0