Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!watmath!clyde!cbatt!ucbvax!okamoto
From: okamoto@ucbvax.UUCP
Newsgroups: net.sources.games
Subject: Trek73 (Part 4 of 6)
Message-ID: <16577@ucbvax.BERKELEY.EDU>
Date: Wed, 10-Dec-86 12:30:27 EST
Article-I.D.: ucbvax.16577
Posted: Wed Dec 10 12:30:27 1986
Date-Received: Sun, 14-Dec-86 05:28:19 EST
Organization: University of California at Berkeley
Lines: 1971
#! /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:
# moveships.c
# parseopts.c
# parsit.c
# save.c
# ships.c
# special.c
# strat1.c
# subs.c
# vers.c
# This archive created: Wed Dec 10 09:01:32 1986
# By: Jeff Okamoto ()
export PATH; PATH=/bin:$PATH
if test -f 'moveships.c'
then
echo shar: will not over-write existing file "'moveships.c'"
else
cat << \SHAR_EOF > 'moveships.c'
/*
* TREK73: moveships.c
*
* Actual command execution
*
* move_ships, check_targets, misc_timers, disposition
*
*/
#include "externs.h"
move_ships()
{
register int i;
register float j;
register float k;
register struct list *lp;
register struct ship *sp;
register float fuel_use;
struct torpedo *tp;
struct ship *fed;
struct list *lp1;
struct ship *sp1;
float iterations;
float tmpf;
float energy;
float course, newcourse;
float warp, newwarp;
int x, y;
struct ship *target;
double d0;
float Mpersegment;
double floor(), fabs();
/*
* The value 100 is the number of Megameters per second
* per warp-factor
*/
Mpersegment = segment * 100.0;
iterations = (int)floor(timeperturn/segment + 0.5); /* What a crock! */
for (i=0; i<=shipnum; i++)
distribute(shiplist[i]);
fed = shiplist[0];
for (i=0; ifwd) {
if (lp == tail)
break;
if (lp->type == I_UNDEFINED)
continue;
sp = NULL;
tp = NULL;
if (lp->type == I_SHIP)
sp = lp->data.sp;
else
tp = lp->data.tp;
if (sp && is_dead(sp, S_DEAD))
continue;
if ((sp) && (i % sp->p_firing_delay == 0))
(void) phaser_firing(sp);
if ((sp) && (i % sp->t_firing_delay == 0))
(void) torpedo_firing(sp);
/*
* time fuses
*/
if (tp) {
tp->timedelay -= segment;
if (tp->timedelay <= 0.) {
torp_detonate(tp, lp);
continue;
}
} else {
sp->delay -= segment;
if (sp->delay <= 0.) {
ship_detonate(sp, lp);
continue;
}
}
/*
* proximity fuse
*/
if (tp && tp->prox != 0) {
for (lp1 = &head; lp1 != tail; lp1 = lp1->fwd) {
if (lp1->type == I_SHIP) {
sp1 = lp1->data.sp;
if (sp1 == tp->from)
continue;
if (cantsee(sp1))
continue;
j = rangefind(tp->x, sp1->x,
tp->y, sp1->y);
} else if (lp1->type == I_ENG) {
sp1 = lp1->data.sp;
if (sp1 == tp->from)
continue;
if (cantsee(sp1))
continue;
j = rangefind(tp->x, sp1->x,
tp->y, sp1->y);
} else
continue;
if (j >= tp->prox)
continue;
torp_detonate(tp, lp);
break;
}
if (lp1 != tail)
continue;
}
/*
* movement simulation
*/
if (sp && is_dead(sp, S_DEAD))
continue;
if (sp) {
x = sp->x;
y = sp->y;
warp = sp->warp;
if (fabs(sp->newwarp) > sp->max_speed)
sp->newwarp = (sp->newwarp > 0)
? sp->max_speed : -sp->max_speed;
newwarp = sp->newwarp;
course = sp->course;
newcourse = sp->newcourse;
target = sp->target;
energy = sp->energy;
/*
* fuel consumption
*/
if (fabs(warp) > 1.0)
fuel_use = (fabs(warp) * sp->eff * segment);
else
fuel_use = 0.;
#ifdef TRACE
/*
if (trace)
printf("*** Fuel use = %.2f, energy = %.2f\n",
fuel_use, energy);
*/
#endif
if (fuel_use > energy) {
if (!shutup[BURNOUT + sp->id] &&
!(is_dead(sp, S_WARP)) && cansee(sp)) {
printf("%s's warp drive burning out.\n",
sp->name);
shutup[BURNOUT + sp->id]++;
}
newwarp = (warp < 0.0) ? -0.99 : 0.99;
energy = 0;
} else
energy -= fuel_use;
} else {
x = tp->x;
y = tp->y;
warp = tp->speed;
newwarp = tp->newspeed;
course = tp->course;
newcourse = course;
target = tp->target;
}
/*
* destroyed warp drive
*/
if (sp && (is_dead(sp, S_WARP)))
if (fabs(warp) > 1.0)
newwarp = (warp < 0.0) ? -0.99 : 0.99;
/*
* automatic pilot
*/
if (target != NULL)
if (sp && (is_dead(target, S_DEAD))) {
if ((sp == fed) && !shutup[DISENGAGE]
&& !is_dead(sp, S_DEAD)) {
printf("%s's autopilot disengaging.\n",
sp->name);
shutup[DISENGAGE]++;
}
newcourse = course;
target = NULL;
sp->relbear = 0.0;
} else {
if (cantsee(target))
j =bearing(x,target->position.x,
y, target->position.y);
else
j = bearing(x, target->x, y, target->y);
if (sp)
j = rectify(j - sp->relbear);
newcourse = j;
}
/*
* turn rate (known to be a ship)
*/
if (tp)
course = newcourse;
if (sp && course != newcourse) {
j = rectify(newcourse - course);
if (j > 180)
j -= 360;
/*
* maximum degrees turned in one turn
*/
k = ((sp->max_speed + 2.0 - warp)
* sp->deg_turn * segment);
/* If you have no warp drive, you're less
* maneuverable
*/
if (is_dead(sp, S_WARP))
k /= 2;
k = course + (j < 0.0 ? -1.0 : 1.0) *
min(fabs(j), k);
course = rectify(k);
}
/*
* acceleration
*/
tmpf = newwarp - warp;
d0 = fabs(tmpf);
warp += ((tmpf < 0.0) ? -1 : 1) * sqrt(d0) * segment;
d0 = toradians(course);
x += (int) (warp * cos(d0) * Mpersegment);
y += (int) (warp * sin(d0) * Mpersegment);
/*
* projected position (cloaked)
*/
if (sp && cantsee(sp)) {
d0 = toradians(sp->position.course);
sp->position.x += (sp->position.warp * cos(d0)
* segment);
sp->position.y += (sp->position.warp * sin(d0)
* segment);
}
/*
* reset all the vars
*/
if (sp) {
sp->x = x;
sp->y = y;
sp->warp = warp;
sp->newwarp = newwarp;
/* XXXXX should these be rectified? */
sp->course = rectify(course);
sp->newcourse = rectify(newcourse);
sp->energy = energy;
sp->target = target;
} else {
tp->x = x;
tp->y = y;
tp->speed = warp;
tp->course = rectify(course);
tp->target = target;
}
}
}
}
check_targets()
{
register int i;
register int j;
struct ship *sp;
struct ship *fed;
struct ship *target;
fed = shiplist[0];
for (i=0; i <= shipnum; i++) { /* Check targets */
sp = shiplist[i];
if (is_dead(sp, S_DEAD))
continue;
target = sp->target;
if (target && is_dead(target, S_DEAD)) {
if ((sp == fed) && !shutup[DISENGAGE]) {
puts(" helm lock disengaging");
shutup[DISENGAGE]++;
}
sp->target = NULL;
sp->relbear = 0.0;
}
for (j=0; jnum_phasers; j++) {
target = sp->phasers[j].target;
if (target && is_dead(target, S_DEAD)) {
if ((sp == fed) && (!shutup[PHASERS+j])
&& !(is_dead(sp, S_DEAD))) {
printf(" phaser %d disengaging\n",j+1);
shutup[PHASERS+j]++;
}
sp->phasers[j].target = NULL;
} else if (target)
sp->phasers[j].bearing = rectify(bearing(sp->x,
(cantsee(target)) ? target->position.x
: target->x, sp->y,
(cantsee(target)) ? target->position.y
: target->y) - sp->course);
}
for (j=0; jnum_tubes; j++) {
target = sp->tubes[j].target;
if (target && is_dead(target, S_DEAD)) {
if ((sp == fed) && (!shutup[TUBES+j])
&& !(is_dead(sp, S_DEAD))) {
printf(" tube %d disengaging\n", j+1);
shutup[TUBES+j]++;
}
sp->tubes[j].target = NULL;
} else if (target)
sp->tubes[j].bearing = rectify(bearing(sp->x,
(cantsee(target)) ? target->position.x
: target->x, sp->y,
(cantsee(target)) ? target->position.y
: target->y) - sp->course);
}
}
if (sp->cloak_delay > 0)
sp->cloak_delay--;
}
misc_timers()
{
struct ship *fed;
/*
* self-destruct warning
*/
fed = shiplist[0];
if ((fed->delay < 1000.) && (fed->delay > 0.)) {
if (is_dead(fed, S_COMP)) {
printf("%s: Self-destruct has been aborted due to computer damage\n",
science);
fed->delay = 10000.;
} else
printf("Computer: %5.2f seconds to self destruct.\n",
fed->delay);
}
fed->probe_status = PR_NORMAL;
/*
* Ruses, bluffs, surrenders
*/
if (defenseless)
defenseless++;
if (corbomite)
corbomite++;
if (surrender)
surrender++;
if (surrenderp)
surrenderp++;
}
disposition()
{
struct ship *sp;
struct ship *fed;
struct ship *ep;
int kills;
int others;
int fedstatus;
register int i;
register int j;
register int k;
/*
* Federation dispostion
*/
fed = shiplist[0];
sp = fed;
kills = others = fedstatus = 0;
if (sp->complement <= 0 && !is_dead(sp, S_DEAD)) {
sp->status[S_DEAD] = 100;
sp->newwarp = 0.0;
sp->newcourse = sp->course;
sp->target = NULL;
sp->relbear = 0.0;
for (i = 0; i < sp->num_phasers; i++) {
sp->phasers[i].target = NULL;
sp->phasers[i].drain = MIN_PHASER_DRAIN;
sp->phasers[i].status &= ~P_FIRING;
}
for (i = 0; i < sp->num_tubes; i++) {
sp->tubes[i].target = NULL;
sp->tubes[i].status &= ~T_FIRING;
}
for (i = 0; i < SHIELDS; i++)
sp->shields[i].attemp_drain = 0.0;
sp->regen = 0.0;
sp->cloaking = C_NONE;
}
if (is_dead(sp, S_DEAD))
fedstatus = 1;
else {
for (i=0; inum_phasers; i++)
if (!(sp->phasers[i].status & P_DAMAGED))
break;
if (i == sp->num_phasers) {
for (i=0; inum_tubes; i++)
if (!(sp->tubes[i].status & T_DAMAGED))
break;
if (i == sp->num_tubes)
fedstatus = 1;
}
}
/*
* enemy disposition
*/
for (k=1; k <= shipnum; k++) {
ep = shiplist[k];
if (ep->complement <= 0 && !is_dead(ep, S_DEAD)) {
ep->status[S_DEAD] = 100;
ep->newwarp = 0.0;
ep->newcourse = ep->course;
ep->target = NULL;
ep->relbear = 0.0;
for (i = 0; i < ep->num_phasers; i++) {
ep->phasers[i].target = NULL;
ep->phasers[i].drain = MIN_PHASER_DRAIN;
ep->phasers[i].status &= ~P_FIRING;
}
for (i = 0; i < ep->num_tubes; i++) {
ep->tubes[i].target = NULL;
ep->tubes[i].status &= ~T_FIRING;
}
for (i = 0; i < SHIELDS; i++)
ep->shields[i].attemp_drain = 0.0;
ep->regen = 0.0;
ep->cloaking = C_NONE;
}
if (is_dead(ep, S_DEAD)) {
kills++;
continue;
}
if (fedstatus)
continue;
j = rangefind(sp->x, ep->x, sp->y, ep->y);
if ((j>3500 && is_dead(ep, S_WARP)) ||
(j>4500 && ep->delay<10.)) {
others++;
continue;
}
/* Check if we are within range to turn off the flag */
if ((j <= 3500) && (reengaged))
reengaged = 0;
if (ep->energy > 10)
continue;
for (i=0; inum_phasers; i++)
if (!(ep->phasers[i].status & P_DAMAGED))
break;
if (i != ep->num_phasers)
continue;
for (i=0; inum_tubes; i++)
if (!(ep->tubes[i].status & T_DAMAGED))
break;
if (i != ep->num_tubes)
continue;
kills++;
}
if (!fedstatus && (global & E_SURRENDER)) /* enemy surrender */
if (leftovers())
(void) warn(FIN_E_SURRENDER);
else
(void) final(FIN_E_SURRENDER);
if ((is_dead(fed, S_SURRENDER)) && (kills + others < shipnum))
if (leftovers()) /* federation surrender */
(void) warn(FIN_F_SURRENDER);
else
(void) final(FIN_F_SURRENDER);
if (!fedstatus && (kills + others) < shipnum) /* play continues */
return 0;
if (fedstatus && kills < shipnum) /* Fed. defeated */
if (leftovers())
(void) warn(FIN_F_LOSE);
else
(void) final(FIN_F_LOSE);
if (!fedstatus && kills == shipnum) /* Fed. victory */
if (leftovers())
(void) warn(FIN_E_LOSE);
else
(void) final(FIN_E_LOSE);
if (!fedstatus && (kills + others) == shipnum) /* outmaneuvered */
if (leftovers())
(void) warn(FIN_TACTICAL);
else
(void) final(FIN_TACTICAL);
if (fedstatus && kills == shipnum)
(void) final(FIN_COMPLETE); /* both sides dead */
return 0;
}
SHAR_EOF
chmod +x 'moveships.c'
fi # end of overwriting check
if test -f 'parseopts.c'
then
echo shar: will not over-write existing file "'parseopts.c'"
else
cat << \SHAR_EOF > 'parseopts.c'
/*
* TREK73: parseopts.c
*
* Parse the environment variable TREK73OPTS and command line options
*
* parse_opts, get_comlineopts
*/
#include
#include
#include "externs.h"
#include "options.h"
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
/*
* description of an option and what to do with it
*/
struct optstruct {
char *o_name; /* option name */
int *o_opt; /* pointer to thing to set */
int o_type /* Boolean or string */
};
typedef struct optstruct OPTION;
OPTION optlist[] = {
{"terse", (int *)&terse, BOOLEAN},
{"name", (int *)captain, STRING},
{"sex", (int *)sex, STRING},
{"science", (int *)science, STRING},
{"engineer", (int *)engineer, STRING},
{"com", (int *)com, STRING},
{"nav", (int *)nav, STRING},
{"helmsman", (int *)helmsman, STRING},
{"shipname", (int *)shipname, STRING},
{"enemy", (int *)racename, STRING},
{"foename", (int *)foename, STRING},
{"silly", (int *)&silly, BOOLEAN},
{"class", (int *)class, STRING},
{"foeclass", (int *)foeclass, STRING},
{"time", (int *)com_delay, STRING},
{"teletype", (int *)&teletype, BOOLEAN},
{"trace", (int *)&trace, BOOLEAN},
{"savefile", (int *)savefile, STRING}
};
/*
* parse_opts:
* Parse options from string, usually taken from the environment.
* The string is a series of comma separated values, with booleans
* being stated as "name" (true) or "noname" (false), and strings
* being "name=....", with the string being defined up to a comma
* or the end of the entire option string.
*/
parse_opts(str)
register char *str;
{
register char *sp;
register OPTION *op;
register int len;
while (*str)
{
/*
* Get option name
*/
for (sp = str; isascii(*sp) && isalpha(*sp); sp++)
continue;
len = sp - str;
/*
* Look it up and deal with it
*/
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
if (EQSTR(str, op->o_name, len))
{
if (op->o_type == BOOLEAN) /* if option is a boolean */
*op->o_opt = 1;
else /* string option */
{
register char *start;
/*
* Skip to start of string value
*/
for (str = sp + 1; *str == '='; str++)
continue;
start = (char *) op->o_opt;
/*
* Skip to end of string value
*/
for (sp = str + 1; *sp && *sp != ','; sp++)
continue;
strucpy(start, str, sp - str);
}
break;
}
/*
* check for "noname" for booleans
*/
else if (op->o_type == BOOLEAN
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
{
*op->o_opt = 0;
break;
}
/*
* skip to start of next option name
*/
while (*sp && !(isascii(*sp) && isalpha(*sp)))
sp++;
str = sp;
}
}
/*
* strucpy:
* Copy string using unctrl for things
*/
strucpy(s1, s2, len)
register char *s1, *s2;
register int len;
{
if (len > 100)
len = 100;
while (len--)
{
if (isascii(*s2) && isprint(*s2))
*s1++ = *s2;
s2++;
}
*s1 = '\0';
}
get_comlineopts(argc, argv)
int argc;
char *argv[];
{
int c;
char *opts = "Rtc:s:S:E:C:N:H:f:r:d:yTn:F:l:v";
int errflg = 0;
while ((c = getopt(argc, argv, opts)) != EOF) {
switch(c) {
case 'R':
restart = 1;
break;
case 't':
terse = 1;
break;
case 'c':
(void) strncpy(captain, optarg, sizeof captain);
captain[sizeof captain - 1] = '\0';
break;
case 's':
(void) strncpy(sex, optarg, sizeof sex);
sex[sizeof sex - 1] = '\0';
break;
case 'S':
(void) strncpy(science, optarg, sizeof science);
science[sizeof science - 1] = '\0';
break;
case 'E':
(void) strncpy(engineer, optarg, sizeof engineer);
engineer[sizeof engineer - 1] = '\0';
break;
case 'C':
(void) strncpy(com, optarg, sizeof com);
com[sizeof com - 1] = '\0';
break;
case 'N':
(void) strncpy(nav, optarg, sizeof nav);
nav[sizeof nav - 1] = '\0';
break;
case 'H':
(void) strncpy(helmsman, optarg, sizeof helmsman);
helmsman[sizeof helmsman - 1] = '\0';
break;
case 'f':
(void) strncpy(foename, optarg, sizeof foename);
foename[sizeof foename - 1] = '\0';
break;
case 'r':
(void) strncpy(racename, optarg, sizeof racename);
racename[sizeof racename - 1] = '\0';
break;
case 'd':
(void) strncpy(com_delay, optarg, sizeof com_delay);
com_delay[sizeof com_delay - 1] = '\0';
break;
case 'y':
silly = 1;
break;
case 'T':
teletype = 1;
break;
case 'n':
(void) strncpy(shipname, optarg, sizeof shipname);
shipname[sizeof shipname - 1] = '\0';
break;
case 'F':
(void) strncpy(foeclass, optarg, sizeof foeclass);
foeclass[sizeof foeclass - 1] = '\0';
break;
case 'l':
(void) strncpy(class, optarg, sizeof class);
class[sizeof class - 1] = '\0';
break;
case 'v':
trace = TR_ON;
break;
case '?':
default:
errflg++;
break;
}
}
if (errflg) {
fprintf(stderr, "Usage: trek73 [-t] [-c captain's name] [-s sex] [-S science officer]\n [-E engineer] [-C communications officer] [-N navigator] [-H helmsman]\n");
fprintf(stderr, " [-f enemy captain] [-r enemy race] [-d command delay time] [-y] [-T] \n [-n shipname] [-F enemy ship type] [-l federation ship type] [-v]\n");
fprintf(stderr, " or trek73 -R");
exit(1);
}
}
SHAR_EOF
chmod +x 'parseopts.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)
*
*/
#include
extern void free();
extern char *gets(), *malloc(), *strcpy(), *index();
static int gindex;
static char **argv;
char *
Gets(buf, len)
char *buf;
int len;
{
register char *tmp;
if (argv[gindex] == NULL) {
(void) fgets(buf, len, stdin);
if (tmp = index(buf, '\n'))
*tmp = '\0';
return(buf);
}
++gindex;
if (argv[gindex] == NULL) {
(void) fgets(buf, len, stdin);
if (tmp = index(buf, '\n'))
*tmp = '\0';
return (buf);
}
(void) strcpy (buf, argv[gindex]);
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;
gindex = 0;
argv = *array;
if (argv != (char **) NULL) { /* Check to see if we should */
i = 0; /* free up the old array */
do {
free(argv[i]); /* If so, free each member */
} while (argv[i++] != (char *) NULL);
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
#include
#include
#include
#include
#include
#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 = 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;
func = signal(SIGTSTP, SIG_IGN);
if ((inf = open(file, 0)) < 0)
{
perror(file);
return 0;
}
fstat(inf, &sbuf2);
syml = symlink(file);
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);
return 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 'ships.c'
then
echo shar: will not over-write existing file "'ships.c'"
else
cat << \SHAR_EOF > 'ships.c'
/*
* TREK73: ships.c
*
* Global Ship Defs for TREK73
*
*/
#include "externs.h"
/*
* starting stats for the ships depending on the type
*/
struct ship_stat stats[] = {
{ "DN", 0, 6, 8, 8, 10, 2., 1.5, 15., 200, 300, 600, 450, 5., 4., 2, 4,
135, 225, 125, 235, 4, 4},
{ "CA", 1, 4, 6, 9, 11, 1., 0.75, 10., 150, 200, 450, 350, 3., 2., 5, 2,
135, 225, 125, 235, 4, 4},
{ "CL", 2, 4, 4, 9, 11, 0.75, 0.5, 10., 125, 175, 350, 250, 3., 2., 6, 2,
150, 210, 140, 220, 4, 4},
{ "DD", 3, 2, 4, 10, 12, 0.5, 0.5, 8., 100, 150, 200, 150, 2., 1.5, 7, 1,
160, 200, 150, 210, 4, 4}
};
SHAR_EOF
chmod +x 'ships.c'
fi # end of overwriting check
if test -f 'special.c'
then
echo shar: will not over-write existing file "'special.c'"
else
cat << \SHAR_EOF > 'special.c'
/*
* TREK73: special.c
*
* special: Take care of special commands like defenseless ruses,
* corbomite bluffs, surrenders (both sides)
*
*/
#include "externs.h"
special(sp, range, fed)
struct ship *sp;
int range;
struct ship *fed;
{
int loop, loop2, loop3;
/*
* Play dead effects
*/
switch (defenseless) {
case 1:
/* Monty Pythons? */
if (aliens[enemynum].defenseless == -1)
aliens[enemynum].defenseless = randm(100);
if (randm(100) > aliens[enemynum].defenseless) {
/* Didn't work. Too bad. */
if (cansee(sp)) {
printf("%s: No apparent change in the enemy's actions.\n",
helmsman);
}
defenseless = 6;
break;
}
defenseless = 2;
case 2:
case 3:
/* Okay, he's fallen for it. Choose his action */
if (randm(2) == 1) {
sp->target = NULL;
sp->newwarp = 0.0;
} else {
sp->newwarp = 1.0;
}
if (cansee(sp)) {
printf("%s: The %s is ", helmsman, sp->name);
if (sp->target != NULL) {
puts("cautiously advancing.");
} else {
puts("turning away.");
}
}
case 4:
case 5:
/*
* Now he might get suspicious. If he's moving too
* fast or if we're close enough, or if his shields
* are up, we'll spot him.
*/
if ((fabs(sp->target->warp) > 1.0) || (range < 200))
defenseless = 6;
else
for (loop = 0; loop < SHIELDS; loop++)
if (sp->target->shields[loop].drain)
defenseless = 6;
}
/*
* Corbomite bluff effects.
*/
switch (corbomite) {
case 1:
/* Monty Pythons? */
if (aliens[enemynum].corbomite == -1)
aliens[enemynum].corbomite = randm(100);
if (randm(100) > aliens[enemynum].corbomite) {
/* He didn't fall for it */
printf("%s: Message coming in from the %ss.\n",
com, foerace);
printf("%s: Put it on audio.\n", captain);
if (randm(2) == 1)
printf ("%s: Ha, ha, ha, %s. You lose.\n",
foename, captain);
else
printf("%s: I fell for that the last time we met, idiot!\n",
foename);
corbomite = 6;
break;
}
if (cansee(sp)) {
printf("%s: %ss giving ground, Captain. Obviously they\n",
science, foerace);
puts(" tapped in as you expected them to.");
printf("%s: A logical assumption, Mr. %s. Are they still\n",
captain, science);
puts(" retreating?");
printf("%s: Yes, %s\n", science, title);
printf("%s: Good. All hands, stand by.\n", captain);
}
corbomite = 2;
case 2:
/* He fell for it, retrograde out of here! */
sp->target = NULL;
sp->newwarp = -(3.0 + randm(7));
break;
case 3:
case 4:
case 5:
/* Begin to get suspicious */
if (fabs(sp->target->warp) > 2.0)
corbomite = 6;
break;
}
/*
* Will the enemy accept your surrender?
*/
switch (surrender) {
case 1:
/* Monty Python */
if (aliens[enemynum].surrender == -1)
aliens[enemynum].surrender = randm(100);
/* Just a little reminder */
if (aliens[enemynum].surrender <= 10)
printf("%s: The %ss do not take prisoners.\n",
nav, foerace);
if (randm(100) > aliens[enemynum].surrender) {
/* Tough luck */
if (randm(2) == 1) {
printf("%s: Message coming in from the %ss.\n",
com, foerace);
printf("%s: Put it on audio.\n", captain);
printf("%s: Prepare to die, Chicken %s!\n",
foename, captain);
} else
printf("%s: No reply from the %ss",
com, foerace);
surrender = 6;
break;
}
/* He took it! */
printf("%s: Message coming in from the %ss.\n",
com, foerace);
printf("%s: Put it on audio.\n", captain);
printf("%s: On behalf of the %s %s, I accept your surrender.\n",
foename, foerace, empire);
puts(" You have five seconds to drop your shields, cut");
puts(" warp, and prepare to be boarded.");
global |= F_SURRENDER;
case 2:
case 3:
if (surrender == 1)
surrender = 2;
else
(void) warn(FIN_F_SURRENDER);
sp->target = fed;
sp->newwarp = sp->max_speed;
(void) e_cloak_off(sp, fed);
break;
case 4:
case 5:
/* Begin checking surrender conditions */
for (loop = 0; loop < SHIELDS; loop++)
if (sp->target->shields[loop].drain)
break;
if (loop < SHIELDS)
break;
if (range <= 1400)
sp->newwarp = 1.0;
if ((range <= 1000) && (fabs(sp->target->warp) <= 1.0)) {
fed->status[S_SURRENDER] = 100;
final(FIN_F_SURRENDER);
}
if (surrender == 4)
break;
if (!shutup[SURRENDER])
printf("%s: Captain %s, you have not fulfilled our terms.\n",
foename, captain);
printf(" We are resuming our attack.\n");
surrender = 6;
shutup[SURRENDER]++;
default:
global &= ~F_SURRENDER;
break;
}
/*
* Enemy surrenders?
*/
switch (surrenderp) {
case 1:
for (loop = 1; loop <= shipnum; loop++)
if (!is_dead(shiplist[loop], S_ENG)
&& (sp->complement > 100)) {
printf("%s: Message coming in from the %ss.\n",
com, foerace);
printf("%s: Put it on audio.\n", captain);
printf("%s: You must be joking, Captain %s.\n",
foename, captain);
puts(" Why don't you surrender?");
surrenderp = 6;
break;
}
if (loop <= shipnum)
break;
/* Monty Python */
if (aliens[enemynum].surrenderp == -1)
aliens[enemynum].surrenderp = randm(100);
if (randm(100) > aliens[enemynum].surrenderp) {
printf("%s: I'll never surrender to you, %s\n",
foename, captain);
surrenderp = 6;
break;
}
printf("%s: As much as I hate to, Captain %s, we will surrender.\n",
foename, captain);
puts(" We are dropping shields. You may board us.");
case 2:
case 3:
if (surrenderp == 1)
surrenderp = 2;
else
(void) warn(FIN_E_SURRENDER);
for (loop = 0; loop < SHIELDS; loop++)
sp->shields[loop].attemp_drain = 0.0;
sp->newwarp = 0.0;
for (loop = 1; loop <= shipnum; loop++)
shiplist[loop]->status[S_SURRENDER] = 100;
global |= E_SURRENDER;
break;
}
/*
* Unsportsmanlike firing
*/
if (betw(defenseless, 0, 6) || betw(corbomite, 0, 6)
|| betw(surrender, 0, 6) || betw(surrenderp, 0, 6)) {
for (loop = 0; loop < fed->num_phasers; loop++)
if (fed->phasers[loop].status & P_FIRING)
break;
for (loop2 = 0; loop2 < fed->num_tubes; loop2++)
if (fed->tubes[loop].status & T_FIRING)
break;
loop3 = (fed->probe_status != PR_NORMAL);
/* Has he fired? */
if ((loop != fed->num_phasers) ||
(loop2 != fed->num_tubes) ||
(loop3 == 1)) {
/* Yes, be angry and disbelieve everything from now on */
printf("%s: How dare you fire on us! We are resuming our attack!\n",
foename);
global = NORMAL;
if (betw(defenseless,0,6))
defenseless = 6;
if (betw(corbomite,0,6))
corbomite = 6;
if (betw(surrender,0,6))
surrender = 6;
if (betw(surrenderp,0,6))
surrenderp = 6;
for (loop = 0; loop <= shipnum; loop++)
shiplist[loop]->status[S_SURRENDER] = 0;
}
}
}
SHAR_EOF
chmod +x 'special.c'
fi # end of overwriting check
if test -f 'strat1.c'
then
echo shar: will not over-write existing file "'strat1.c'"
else
cat << \SHAR_EOF > 'strat1.c'
/*
* TREK73: strat1.c
*
* Standard Enemy Strategy
*
* standard_strategy
*
*/
#include "externs.h"
standard_strategy(sp)
struct ship *sp;
{
register struct ship *fed;
float bear;
int range;
float tmpf;
fed = shiplist[0];
if (is_dead(sp, S_DEAD))
return;
range = rangefind(sp->x, fed->x, sp->y, fed->y);
bear = bearing(sp->x, fed->x, sp->y, fed->y);
bear = rectify(bear - sp->course);
/*
* Handle special requests
*/
special(sp, range, fed);
/*
* Now check for surrendering flags
*/
if ((global & F_SURRENDER) || (global & E_SURRENDER))
return;
/*
* Always turn on cloaking device if we have it and if we
* can afford it
*/
if ((sp->cloaking == C_OFF) && (sp->energy >= 20)
&& e_cloak_on(sp, fed))
return;
/*
* Check for hostile antimatter devices
*/
if ((sp->cloaking == C_OFF) && e_closetorps(sp, fed))
return;
if ((sp->cloaking == C_OFF) && e_checkprobe(sp))
return;
/*
* If cloaking is on, and we're running low on energy,
* drop the cloak
*/
/* XXXX May want to change number */
if ((sp->cloaking == C_ON) && (sp->energy < 30)
&& e_cloak_off(sp, fed))
return;
/*
* Short range?
*/
if (range < 1050) {
if (e_checkarms(sp) < randm((int)(sp->num_phasers+
sp->num_tubes)/3)) {
if (!e_cloak_on(sp, fed))
(void) e_runaway(sp, fed);
return;
}
if (e_lockphasers(sp, fed))
return;
if (e_phasers(sp, fed))
return;
if (betw(bear, 90.0, 270.0)) {
(void) e_pursue(sp, fed, 1.0);
return;
}
if (e_launchprobe(sp, fed))
return;
if (sp->pods< 20 && sp->regen < 4.0 && e_destruct(sp, fed))
return;
/*
* set course?
*/
tmpf = fabs(fed->warp);
if (sp->target != fed || fabs(sp->warp) + tmpf > 2.0) {
(void) e_pursue(sp, fed, tmpf);
return;
}
if (e_cloak_on(sp, fed))
return;
}
if (range < 3800) {
/*
* Either medium range, or we can't figure out what
* to do at short range
*/
if (e_locktubes(sp, fed))
return;
if (sp->energy > 30 && sp->pods > 40 && e_loadtubes(sp))
return;
if (e_torpedo(sp))
return;
/*
* should we run away; can we?
*/
if (e_checkarms(sp) < randm((int)(sp->num_phasers+
sp->num_tubes)/3)) {
if (!e_cloak_on(sp, fed))
(void) e_runaway(sp, fed);
return;
}
/*
* Pursued from behind, low power: jettison engineering!
*/
if (betw(bear, 90.0, 270.0) && sp->energy < 10
&& sp->regen < 4.0 && e_jettison(sp, fed))
return;
/*
* put in other junk later
*/
if (e_cloak_on(sp, fed))
return;
}
/*
* Either distant range, or we can't figure out
* what to do at medium range
*/
/* Warp drive dead and Federation destructing, run away! */
if (fed->delay < 15. && (is_dead(sp, S_WARP))) {
(void) e_runaway(sp, fed);
return;
}
/*
* enemy in our blind area? make a quick turn.
*/
/* XXXX Should we check for blind spots?
* or should we check for forward/aft
*/
if (betw(bear, sp->t_blind_left, sp->t_blind_right)) {
(void) e_pursue(sp, fed, 1.0);
return;
}
if (e_locktubes(sp, fed))
return;
if (e_lockphasers(sp, fed))
return;
/*
* attack?
*/
/*
tmpf = fabs(fed->warp);
if (sp->target != fed || sp->warp + tmpf > 2.0) {
(void) e_pursue(sp, fed, (int)tmpf + 2.0 + randm(2));
return;
}
*/
if (e_attack(sp, fed))
return;
if (sp->energy > 30 && sp->pods > 40 && e_loadtubes(sp))
return;
if (e_cloak_on(sp, fed))
return;
/*
* gee, there's nothing that we want to do!
*/
if (cansee(sp))
printf("%s: We're being scanned by the %s\n",
science, sp->name);
}
SHAR_EOF
chmod +x 'strat1.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
#include
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
if test -f 'vers.c'
then
echo shar: will not over-write existing file "'vers.c'"
else
cat << \SHAR_EOF > 'vers.c'
/*
* TREK73: vers.c
*
* version
*/
vers()
{
extern char version[];
printf("%s\n", version);
printf("Jeff Okamoto, Peter Yee, and Roger Noe\n");
return 1;
}
SHAR_EOF
chmod +x 'vers.c'
fi # end of overwriting check
# End of shell archive
exit 0