Initial commit with sst files from Tom Almy's website

This commit is contained in:
Anthony Giacalone 2015-07-22 16:20:47 -07:00
parent d6c2375f6c
commit 7a2b6bd349
13 changed files with 9086 additions and 0 deletions

610
ai.c Executable file
View File

@ -0,0 +1,610 @@
#include "sst.h"
static int tryexit(int lookx, int looky, int ienm, int loccom, int irun) {
int iqx, iqy, l;
iqx = quadx+(lookx+9)/10 - 1;
iqy = quady+(looky+9)/10 - 1;
if (iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
d.galaxy[iqx][iqy] > 899)
return 0; /* no can do -- neg energy, supernovae, or >8 Klingons */
if (ienm == IHR) return 0; /* Romulans cannot escape! */
if (irun == 0) {
/* avoid intruding on another commander's territory */
if (ienm == IHC) {
for (l = 1; l <= d.remcom; l++)
if (d.cx[l]==iqx && d.cy[l]==iqy) return 0;
/* refuse to leave if currently attacking starbase */
if (batx==quadx && baty==quady) return 0;
}
/* don't leave if over 1000 units of energy */
if (kpower[loccom] > 1000.) return 0;
}
/* print escape message and move out of quadrant.
We know this if either short or long range sensors are working */
if (damage[DSRSENS] == 0.0 || damage[DLRSENS] == 0.0 ||
condit == IHDOCKED) {
proutn("***");
cramen(ienm);
proutn(" escapes to");
cramlc(1, iqx, iqy);
prout(" (and regains strength).");
}
/* handle local matters related to escape */
kx[loccom] = kx[nenhere];
ky[loccom] = ky[nenhere];
kavgd[loccom] = kavgd[nenhere];
kpower[loccom] = kpower[nenhere];
kdist[loccom] = kdist[nenhere];
klhere--;
nenhere--;
if (condit != IHDOCKED) newcnd();
/* Handle global matters related to escape */
d.galaxy[quadx][quady] -= 100;
d.galaxy[iqx][iqy] += 100;
if (ienm==IHS) {
ishere=0;
iscate=0;
ientesc=0;
isatb=0;
future[FSCMOVE]=0.2777+d.date;
future[FSCDBAS]=1e30;
d.isx=iqx;
d.isy=iqy;
}
else {
for (l=1; l<=d.remcom; l++) {
if (d.cx[l]==quadx && d.cy[l]==quady) {
d.cx[l]=iqx;
d.cy[l]=iqy;
break;
}
}
comhere = 0;
}
return 1; /* success */
}
static void movebaddy(int comx, int comy, int loccom, int ienm) {
int motion, mdist, nsteps, mx, my, nextx, nexty, lookx, looky, ll;
int irun = 0;
int krawlx, krawly;
int success;
int attempts;
/* This should probably be just comhere + ishere */
int nbaddys = skill > SGOOD ?
(int)((comhere*2 + ishere*2+klhere*1.23+irhere*1.5)/2.0):
(comhere + ishere);
double dist1, forces;
dist1 = kdist[loccom];
mdist = dist1 + 0.5; /* Nearest integer distance */
/* If SC, check with spy to see if should hi-tail it */
if (ienm==IHS &&
(kpower[loccom] <= 500.0 || (condit==IHDOCKED && damage[DPHOTON]==0))) {
irun = 1;
motion = -10;
}
else {
/* decide whether to advance, retreat, or hold position */
/* Algorithm:
* Enterprise has "force" based on condition of phaser and photon torpedoes.
If both are operating full strength, force is 1000. If both are damaged,
force is -1000. Having shields down subtracts an additional 1000.
* Enemy has forces equal to the energy of the attacker plus
100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
Attacker Initial energy levels (nominal):
Klingon Romulan Commander Super-Commander
Novice 400 700 1200
Fair 425 750 1250
Good 450 800 1300 1750
Expert 475 850 1350 1875
Emeritus 500 900 1400 2000
VARIANCE 75 200 200 200
Enemy vessels only move prior to their attack. In Novice - Good games
only commanders move. In Expert games, all enemy vessels move if there
is a commander present. In Emeritus games all enemy vessels move.
* If Enterprise is not docked, an agressive action is taken if enemy
forces are 1000 greater than Enterprise.
Agressive action on average cuts the distance between the ship and
the enemy to 1/4 the original.
* At lower energy advantage, movement units are proportional to the
advantage with a 650 advantage being to hold ground, 800 to move forward
1, 950 for two, 150 for back 4, etc. Variance of 100.
If docked, is reduced by roughly 1.75*skill, generally forcing a
retreat, especially at high skill levels.
* Motion is limited to skill level, except for SC hi-tailing it out.
*/
forces = kpower[loccom]+100.0*nenhere+400*(nbaddys-1);
if (shldup==0) forces += 1000; /* Good for enemy if shield is down! */
if (damage[DPHASER] == 0.0 || damage[DPHOTON] == 0.0) {
if (damage[DPHASER] != 0) /* phasers damaged */
forces += 300.0;
else
forces -= 0.2*(energy - 2500.0);
if (damage[DPHOTON] != 0) /* photon torpedoes damaged */
forces += 300.0;
else
forces -= 50.0*torps;
}
else {
/* phasers and photon tubes both out! */
forces += 1000.0;
}
motion = 0;
if (forces <= 1000.0 && condit != IHDOCKED) /* Typical situation */
motion = ((forces+200.0*Rand())/150.0) - 5.0;
else {
if (forces > 1000.0) /* Very strong -- move in for kill */
motion = (1.0-square(Rand()))*dist1 + 1.0;
if (condit==IHDOCKED) /* protected by base -- back off ! */
motion -= skill*(2.0-square(Rand()));
}
#ifdef DEBUG
if (idebug) {
proutn("MOTION = ");
cramf(motion, 1, 2);
proutn(" FORCES = ");
cramf(forces, 1, 2);
skip(1);
}
#endif
/* don't move if no motion */
if (motion==0) return;
/* Limit motion according to skill */
if (abs(motion) > skill) motion = (motion < 0) ? -skill : skill;
}
/* calcuate preferred number of steps */
nsteps = motion < 0 ? -motion : motion;
if (motion > 0 && nsteps > mdist) nsteps = mdist; /* don't overshoot */
if (nsteps > 10) nsteps = 10; /* This shouldn't be necessary */
if (nsteps < 1) nsteps = 1; /* This shouldn't be necessary */
#ifdef DEBUG
if (idebug) {
proutn("NSTEPS = ");
crami(nsteps, 1);
skip(1);
}
#endif
/* Compute preferred values of delta X and Y */
mx = sectx - comx;
my = secty - comy;
if (2.0 * abs(mx) < abs(my)) mx = 0;
if (2.0 * abs(my) < abs(sectx-comx)) my = 0;
if (mx != 0) mx = mx*motion < 0 ? -1 : 1;
if (my != 0) my = my*motion < 0 ? -1 : 1;
nextx = comx;
nexty = comy;
quad[comx][comy] = IHDOT;
/* main move loop */
for (ll = 1; ll <= nsteps; ll++) {
#ifdef DEBUG
if (idebug) {
crami(ll,2);
skip(1);
}
#endif
/* Check if preferred position available */
lookx = nextx + mx;
looky = nexty + my;
krawlx = mx < 0 ? 1 : -1;
krawly = my < 0 ? 1 : -1;
success = 0;
attempts = 0; /* Settle mysterious hang problem */
while (attempts++ < 20 && !success) {
if (lookx < 1 || lookx > 10) {
if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
return;
if (krawlx == mx || my == 0) break;
lookx = nextx + krawlx;
krawlx = -krawlx;
}
else if (looky < 1 || looky > 10) {
if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))
return;
if (krawly == my || mx == 0) break;
looky = nexty + krawly;
krawly = -krawly;
}
else if (quad[lookx][looky] != IHDOT) {
/* See if we should ram ship */
if (quad[lookx][looky] == ship &&
(ienm == IHC || ienm == IHS)) {
ram(1, ienm, comx, comy);
return;
}
if (krawlx != mx && my != 0) {
lookx = nextx + krawlx;
krawlx = -krawlx;
}
else if (krawly != my && mx != 0) {
looky = nexty + krawly;
krawly = -krawly;
}
else break; /* we have failed */
}
else success = 1;
}
if (success) {
nextx = lookx;
nexty = looky;
#ifdef DEBUG
if (idebug) {
cramlc(0, nextx, nexty);
skip(1);
}
#endif
}
else break; /* done early */
}
/* Put commander in place within same quadrant */
quad[nextx][nexty] = ienm;
if (nextx != comx || nexty != comy) {
/* it moved */
kx[loccom] = nextx;
ky[loccom] = nexty;
kdist[loccom] = kavgd[loccom] =
sqrt(square(sectx-nextx)+square(secty-nexty));
if (damage[DSRSENS] == 0 || condit == IHDOCKED) {
proutn("***");
cramen(ienm);
if (kdist[loccom] < dist1) proutn(" advances to");
else proutn(" retreats to");
cramlc(2, nextx, nexty);
skip(1);
}
}
}
void movcom(void) {
int ix, iy, i;
#ifdef DEBUG
if (idebug) prout("MOVCOM");
#endif
/* Figure out which Klingon is the commander (or Supercommander)
and do move */
if (comhere) for (i = 1; i <= nenhere; i++) {
ix = kx[i];
iy = ky[i];
if (quad[ix][iy] == IHC) {
movebaddy(ix, iy, i, IHC);
break;
}
}
if (ishere) for (i = 1; i <= nenhere; i++) {
ix = kx[i];
iy = ky[i];
if (quad[ix][iy] == IHS) {
movebaddy(ix, iy, i, IHS);
break;
}
}
/* if skill level is high, move other Klingons and Romulans too!
Move these last so they can base their actions on what the
commander(s) do. */
if (skill > SGOOD) for (i = 1; i <= nenhere; i++) {
ix = kx[i];
iy = ky[i];
if (quad[ix][iy] == IHK || quad[ix][iy] == IHR)
movebaddy(ix, iy, i, quad[ix][iy]);
}
sortkl();
}
static int checkdest(int iqx, int iqy, int flag, int *ipage) {
int i, j;
if ((iqx==quadx && iqy==quady) ||
iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||
d.galaxy[iqx][iqy] > 899) return 1;
if (flag) {
/* Avoid quadrants with bases if we want to avoid Enterprise */
for (i = 1; i <= d.rembase; i++)
if (d.baseqx[i]==iqx && d.baseqy[i]==iqy) return 1;
}
/* do the move */
d.galaxy[d.isx][d.isy] -= 100;
d.isx = iqx;
d.isy = iqy;
d.galaxy[d.isx][d.isy] += 100;
if (iscate) {
/* SC has scooted, Remove him from current quadrant */
iscate=0;
isatb=0;
ishere=0;
ientesc=0;
future[FSCDBAS]=1e30;
for (i = 1; i <= nenhere; i++)
if (quad[kx[i]][ky[i]] == IHS) break;
quad[kx[i]][ky[i]] = IHDOT;
kx[i] = kx[nenhere];
ky[i] = ky[nenhere];
kdist[i] = kdist[nenhere];
kavgd[i] = kavgd[nenhere];
kpower[i] = kpower[nenhere];
klhere--;
nenhere--;
if (condit!=IHDOCKED) newcnd();
sortkl();
}
/* check for a helpful planet */
for (i = 1; i <= inplan; i++) {
if (d.plnets[i].x==d.isx && d.plnets[i].y==d.isy &&
d.plnets[i].crystals == 1) {
/* destroy the planet */
d.plnets[i] = nulplanet;
d.newstuf[d.isx][d.isy] -= 1;
if (REPORTS) {
if (*ipage==0) pause(1);
*ipage = 1;
prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
proutn(" a planet in");
cramlc(1, d.isx, d.isy);
prout(" has been destroyed");
prout(" by the Super-commander.\"");
}
break;
}
}
return 0; /* looks good! */
}
void scom(int *ipage) {
int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;
int iqx, iqy;
int basetbl[6];
double bdist[6];
int flag;
#ifdef DEBUG
if (idebug) prout("SCOM");
#endif
/* Decide on being active or passive */
flag = ((d.killc+d.killk)/(d.date+0.01-indate) < 0.1*skill*(skill+1.0) ||
(d.date-indate) < 3.0);
if (iscate==0 && flag) {
/* compute move away from Enterprise */
ideltax = d.isx-quadx;
ideltay = d.isy-quady;
if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {
/* circulate in space */
ideltax = d.isy-quady;
ideltay = quadx-d.isx;
}
}
else {
/* compute distances to starbases */
if (d.rembase <= 0) {
/* nothing left to do */
future[FSCMOVE] = 1e30;
return;
}
sx = d.isx;
sy = d.isy;
for (i = 1; i <= d.rembase; i++) {
basetbl[i] = i;
ibqx = d.baseqx[i];
ibqy = d.baseqy[i];
bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));
}
if (d.rembase > 1) {
/* sort into nearest first order */
int iswitch;
do {
iswitch = 0;
for (i=1; i < d.rembase-1; i++) {
if (bdist[i] > bdist[i+1]) {
int ti = basetbl[i];
double t = bdist[i];
bdist[i] = bdist[i+1];
bdist[i+1] = t;
basetbl[i] = basetbl[i+1];
basetbl[i+1] =ti;
iswitch = 1;
}
}
} while (iswitch);
}
/* look for nearest base without a commander, no Enterprise, and
without too many Klingons, and not already under attack. */
ifindit = iwhichb = 0;
for (i2 = 1; i2 <= d.rembase; i2++) {
i = basetbl[i2]; /* bug in original had it not finding nearest*/
ibqx = d.baseqx[i];
ibqy = d.baseqy[i];
if ((ibqx == quadx && ibqy == quady) ||
(ibqx == batx && ibqy == baty) ||
d.galaxy[ibqx][ibqy] > 899) continue;
/* if there is a commander, an no other base is appropriate,
we will take the one with the commander */
for (j = 1; j <= d.remcom; j++) {
if (ibqx==d.cx[j] && ibqy==d.cy[j] && ifindit!= 2) {
ifindit = 2;
iwhichb = i;
break;
}
}
if (j > d.remcom) { /* no commander -- use this one */
ifindit = 1;
iwhichb = i;
break;
}
}
if (ifindit==0) return; /* Nothing suitable -- wait until next time*/
ibqx = d.baseqx[iwhichb];
ibqy = d.baseqy[iwhichb];
/* decide how to move toward base */
ideltax = ibqx - d.isx;
ideltay = ibqy - d.isy;
}
/* Maximum movement is 1 quadrant in either or both axis */
if (ideltax > 1) ideltax = 1;
if (ideltax < -1) ideltax = -1;
if (ideltay > 1) ideltay = 1;
if (ideltay < -1) ideltay = -1;
/* try moving in both x and y directions */
iqx = d.isx + ideltax;
iqy = d.isy + ideltax;
if (checkdest(iqx, iqy, flag, ipage)) {
/* failed -- try some other maneuvers */
if (ideltax==0 || ideltay==0) {
/* attempt angle move */
if (ideltax != 0) {
iqy = d.isy + 1;
if (checkdest(iqx, iqy, flag, ipage)) {
iqy = d.isy - 1;
checkdest(iqx, iqy, flag, ipage);
}
}
else {
iqx = d.isx + 1;
if (checkdest(iqx, iqy, flag, ipage)) {
iqx = d.isx - 1;
checkdest(iqx, iqy, flag, ipage);
}
}
}
else {
/* try moving just in x or y */
iqy = d.isy;
if (checkdest(iqx, iqy, flag, ipage)) {
iqy = d.isy + ideltay;
iqx = d.isx;
checkdest(iqx, iqy, flag, ipage);
}
}
}
/* check for a base */
if (d.rembase == 0) {
future[FSCMOVE] = 1e30;
}
else for (i=1; i<=d.rembase; i++) {
ibqx = d.baseqx[i];
ibqy = d.baseqy[i];
if (ibqx==d.isx && ibqy == d.isy && d.isx != batx && d.isy != baty) {
/* attack the base */
if (flag) return; /* no, don't attack base! */
iseenit = 0;
isatb=1;
future[FSCDBAS] = d.date + 1.0 +2.0*Rand();
if (batx != 0) future[FSCDBAS] += future[FCDBAS]-d.date;
if (!REPORTS)
return; /* no warning */
iseenit = 1;
if (*ipage == 0) pause(1);
*ipage=1;
proutn("Lt. Uhura- \"Captain, the starbase in");
cramlc(1, d.isx, d.isy);
skip(1);
prout(" reports that it is under attack from the Klingon Super-commander.");
proutn(" It can survive until stardate ");
cramf(future[FSCDBAS], 0, 1);
prout(" .\"");
if (resting==0) return;
prout("Mr. Spock- \"Captain, shall we cancel the rest period?\"");
if (ja()==0) return;
resting = 0;
Time = 0.0; /* actually finished */
return;
}
}
/* Check for intelligence report */
if (
#ifdef DEBUG
idebug==0 &&
#endif
(Rand() > 0.2 ||
(!REPORTS) ||
starch[d.isx][d.isy] > 0))
return;
if (*ipage==0) pause(1);
*ipage = 1;
prout("Lt. Uhura- \"Captain, Starfleet Intelligence reports");
proutn(" the Super-commander is in");
cramlc(1, d.isx, d.isy);
prout(".\"");
return;
}
void movetho(void) {
int idx, idy, im, i, dum, my;
/* Move the Tholean */
if (ithere==0 || justin == 1) return;
if (ithx == 1 && ithy == 1) {
idx = 1; idy = 10;
}
else if (ithx == 1 && ithy == 10) {
idx = 10; idy = 10;
}
else if (ithx == 10 && ithy == 10) {
idx = 10; idy = 1;
}
else if (ithx == 10 && ithy == 1) {
idx = 1; idy = 1;
}
else {
/* something is wrong! */
ithere = 0;
return;
}
/* Do nothing if we are blocked */
if (quad[idx][idy]!= IHDOT && quad[idx][idy]!= IHWEB) return;
quad[ithx][ithy] = IHWEB;
if (ithx != idx) {
/* move in x axis */
im = fabs((double)idx - ithx)/((double)idx - ithx);
while (ithx != idx) {
ithx += im;
if (quad[ithx][ithy]==IHDOT) quad[ithx][ithy] = IHWEB;
}
}
else if (ithy != idy) {
/* move in y axis */
im = fabs((double)idy - ithy)/((double)idy - ithy);
while (ithy != idy) {
ithy += im;
if (quad[ithx][ithy]==IHDOT) quad[ithx][ithy] = IHWEB;
}
}
quad[ithx][ithy] = IHT;
/* check to see if all holes plugged */
for (i = 1; i < 11; i++) {
if (quad[1][i]!=IHWEB && quad[1][i]!=IHT) return;
if (quad[10][i]!=IHWEB && quad[10][i]!=IHT) return;
if (quad[i][1]!=IHWEB && quad[i][1]!=IHT) return;
if (quad[i][10]!=IHWEB && quad[i][10]!=IHT) return;
}
/* All plugged up -- Tholian splits */
quad[ithx][ithy]=IHWEB;
dropin(IHBLANK, &dum, &my);
crmena(1,IHT, 2, ithx, ithy);
prout(" completes web.");
ithere = ithx = ithy = 0;
return;
}

1483
battle.c Executable file

File diff suppressed because it is too large Load Diff

783
events.c Executable file
View File

@ -0,0 +1,783 @@
#include "sst.h"
#include <math.h>
void events(void) {
int ictbeam=0, ipage=0, istract=0, line, i, j, k, l, ixhold, iyhold;
double fintim = d.date + Time, datemin, xtime, repair, yank;
#ifdef DEBUG
if (idebug) prout("EVENTS");
#endif
if (stdamtim == 1e30 && !REPORTS)
{
/* chart will no longer be updated because radio is dead */
stdamtim = d.date;
for (i=1; i <= 8 ; i++)
for (j=1; j <= 8; j++)
if (starch[i][j] == 1) starch[i][j] = d.galaxy[i][j]+1000;
}
for (;;) {
/* Select earliest extraneous event, line==0 if no events */
line = FSPY;
if (alldone) return;
datemin = fintim;
for (l=1; l<=NEVENTS; l++)
if (future[l] <= datemin) {
line = l;
datemin = future[l];
}
xtime = datemin-d.date;
#ifdef CLOAKING
if (iscloaking) {
energy -= xtime*500.0;
if (energy <= 0.) {
finish(FNRG);
return;
}
}
#endif
d.date = datemin;
/* Decrement Federation resources and recompute remaining time */
d.remres -= (d.remkl+4*d.remcom)*xtime;
d.remtime = d.remres/(d.remkl+4*d.remcom);
if (d.remtime <=0) {
finish(FDEPLETE);
return;
}
/* Is life support adequate? */
if (damage[DLIFSUP] && condit != IHDOCKED) {
if (lsupres < xtime && damage[DLIFSUP] > lsupres) {
finish(FLIFESUP);
return;
}
lsupres -= xtime;
if (damage[DLIFSUP] <= xtime) lsupres = inlsr;
}
/* Fix devices */
repair = xtime;
if (condit == IHDOCKED) repair /= docfac;
/* Don't fix Deathray here */
for (l=1; l<=ndevice; l++)
if (damage[l] > 0.0 && l != DDRAY)
damage[l] -= (damage[l]-repair > 0.0 ? repair : damage[l]);
/* Fix Deathray if docked */
if (damage[DDRAY] > 0.0 && condit == IHDOCKED)
damage[DDRAY] -= (damage[l] - xtime > 0.0 ? xtime : damage[DDRAY]);
/* If radio repaired, update star chart and attack reports */
if (stdamtim != 1e30 && REPORTS) {
stdamtim = 1e30;
prout("Lt. Uhura- \"Captain, the sub-space radio is working and");
prout(" surveillance reports are coming in.");
skip(1);
for (i=1; i <= 8 ; i++)
for (j=1; j <= 8; j++)
if (starch[i][j] > 999) starch[i][j] = 1;
if (iseenit==0) {
attakreport();
iseenit = 1;
}
skip(1);
prout(" The star chart is now up to date.\"");
skip(1);
}
/* Cause extraneous event LINE to occur */
Time -= xtime;
switch (line) {
case FSNOVA: /* Supernova */
if (ipage==0) pause(1);
ipage=1;
snova(0,0);
future[FSNOVA] = d.date + expran(0.5*intime);
if (d.galaxy[quadx][quady] == 1000) return;
break;
case FSPY: /* Check with spy to see if S.C. should tractor beam */
if (d.nscrem == 0 ||
#ifdef CLOAKING
iscloaked || /* Cannot tractor beam if we can't be seen! */
#endif
ictbeam+istract > 0 ||
condit==IHDOCKED || isatb==1 || iscate==1) return;
if (ientesc ||
(energy < 2000 && torps < 4 && shield < 1250) ||
(damage[DPHASER]>0 && (damage[DPHOTON]>0 || torps < 4)) ||
(damage[DSHIELD] > 0 &&
(energy < 2500 || damage[DPHASER] > 0) &&
(torps < 5 || damage[DPHOTON] > 0))) {
/* Tractor-beam her! */
istract=1;
yank = square(d.isx-quadx) + square(d.isy-quady);
/*********TBEAM CODE***********/
}
else return;
case FTBEAM: /* Tractor beam */
if (line==FTBEAM) {
if (d.remcom == 0) {
future[FTBEAM] = 1e30;
break;
}
i = Rand()*d.remcom+1.0;
yank = square(d.cx[i]-quadx) + square(d.cy[i]-quady);
if (istract || condit == IHDOCKED ||
#ifdef CLOAKING
iscloaked || /* cannot tractor beam if we can't be seen */
#endif
yank == 0) {
/* Drats! Have to reschedule */
future[FTBEAM] = d.date + Time +
expran(1.5*intime/d.remcom);
break;
}
}
/* tractor beaming cases merge here */
yank = sqrt(yank);
if (ipage==0) pause(1);
ipage=1;
Time = (10.0/(7.5*7.5))*yank; /* 7.5 is yank rate (warp 7.5) */
ictbeam = 1;
skip(1);
proutn("***");
crmshp();
prout(" caught in long range tractor beam--");
/* If Kirk & Co. screwing around on planet, handle */
atover(1); /* atover(1) is Grab */
if (alldone) return;
if (icraft == 1) { /* Caught in Galileo? */
finish(FSTRACTOR);
return;
}
/* Check to see if shuttle is aboard */
if (iscraft==0) {
skip(1);
if (Rand() >0.5) {
prout("Galileo, left on the planet surface, is captured");
prout("by aliens and made into a flying McDonald's.");
damage[DSHUTTL] = -10;
iscraft = -1;
}
else {
prout("Galileo, left on the planet surface, is well hidden.");
}
}
if (line==0) {
quadx = d.isx;
quady = d.isy;
}
else {
quadx = d.cx[i];
quady = d.cy[i];
}
iran10(&sectx, &secty);
crmshp();
proutn(" is pulled to");
cramlc(1, quadx, quady);
proutn(", ");
cramlc(2, sectx, secty);
skip(1);
if (resting) {
prout("(Remainder of rest/repair period cancelled.)");
resting = 0;
}
if (shldup==0) {
if (damage[DSHIELD]==0 && shield > 0) {
sheild(2); /* Shldsup */
shldchg=0;
}
else prout("(Shields not currently useable.)");
}
newqad(0);
/* Adjust finish time to time of tractor beaming */
fintim = d.date+Time;
if (d.remcom <= 0) future[FTBEAM] = 1e30;
else future[FTBEAM] = d.date+Time+expran(1.5*intime/d.remcom);
break;
case FSNAP: /* Snapshot of the universe (for time warp) */
snapsht = d;
d.snap = 1;
future[FSNAP] = d.date + expran(0.5 * intime);
break;
case FBATTAK: /* Commander attacks starbase */
if (d.remcom==0 || d.rembase==0) {
/* no can do */
future[FBATTAK] = future[FCDBAS] = 1e30;
break;
}
i = 0;
for (j=1; j<=d.rembase; j++) {
for (k=1; k<=d.remcom; k++)
if (d.baseqx[j]==d.cx[k] && d.baseqy[j]==d.cy[k] &&
(d.baseqx[j]!=quadx || d.baseqy[j]!=quady) &&
(d.baseqx[j]!=d.isx || d.baseqy[j]!=d.isy)) {
i = 1;
break;
}
if (i == 1) break;
}
if (j>d.rembase) {
/* no match found -- try later */
future[FBATTAK] = d.date + expran(0.3*intime);
future[FCDBAS] = 1e30;
break;
}
/* commander + starbase combination found -- launch attack */
batx = d.baseqx[j];
baty = d.baseqy[j];
future[FCDBAS] = d.date+1.0+3.0*Rand();
if (isatb) /* extra time if SC already attacking */
future[FCDBAS] += future[FSCDBAS]-d.date;
future[FBATTAK] = future[FCDBAS] +expran(0.3*intime);
iseenit = 0;
if (!REPORTS)
break; /* No warning :-( */
iseenit = 1;
if (ipage==0) pause(1);
ipage = 1;
skip(1);
proutn("Lt. Uhura- \"Captain, the starbase in");
cramlc(1, batx, baty);
skip(1);
prout(" reports that it is under atttack and that it can");
proutn(" hold out only until stardate ");
cramf(future[FCDBAS],1,1);
prout(".\"");
if (resting) {
skip(1);
proutn("Mr. Spock- \"Captain, shall we cancel the rest period?\"");
if (ja()) {
resting = 0;
Time = 0.0;
return;
}
}
break;
case FSCDBAS: /* Supercommander destroys base */
future[FSCDBAS] = 1e30;
isatb = 2;
if (d.galaxy[d.isx][d.isy]%100 < 10) break; /* WAS RETURN! */
ixhold = batx;
iyhold = baty;
batx = d.isx;
baty = d.isy;
case FCDBAS: /* Commander succeeds in destroying base */
if (line==FCDBAS) {
future[FCDBAS] = 1e30;
/* find the lucky pair */
for (i = 1; i <= d.remcom; i++)
if (d.cx[i]==batx && d.cy[i]==baty) break;
if (i > d.remcom || d.rembase == 0 ||
d.galaxy[batx][baty] % 100 < 10) {
/* No action to take after all */
batx = baty = 0;
break;
}
}
/* Code merges here for any commander destroying base */
/* Not perfect, but will have to do */
if (starch[batx][baty] == -1) starch[batx][baty] = 0;
/* Handle case where base is in same quadrant as starship */
if (batx==quadx && baty==quady) {
if (starch[batx][baty] > 999) starch[batx][baty] -= 10;
quad[basex][basey]= IHDOT;
basex=basey=0;
newcnd();
skip(1);
prout("Spock- \"Captain, I believe the starbase has been destroyed.\"");
}
else if (d.rembase != 1 && REPORTS) {
/* Get word via subspace radio */
if (ipage==0) pause(1);
ipage = 1;
skip(1);
prout("Lt. Uhura- \"Captain, Starfleet Command reports that");
proutn(" the starbase in");
cramlc(1, batx, baty);
prout(" has been destroyed by");
if (isatb==2) prout("the Klingon Super-Commander");
else prout("a Klingon Commander");
}
/* Remove Starbase from galaxy */
d.galaxy[batx][baty] -= 10;
for (i=1; i <= d.rembase; i++)
if (d.baseqx[i]==batx && d.baseqy[i]==baty) {
d.baseqx[i]=d.baseqx[d.rembase];
d.baseqy[i]=d.baseqy[d.rembase];
}
d.rembase--;
if (isatb == 2) {
/* reinstate a commander's base attack */
batx = ixhold;
baty = iyhold;
isatb = 0;
}
else {
batx = baty = 0;
}
break;
case FSCMOVE: /* Supercommander moves */
future[FSCMOVE] = d.date+0.2777;
if (ientesc+istract==0 &&
isatb!=1 &&
(iscate!=1 || justin==1)) scom(&ipage);
break;
case FDSPROB: /* Move deep space probe */
future[FDSPROB] = d.date + 0.01;
probex += probeinx;
probey += probeiny;
i = (int)(probex/10 +0.05);
j = (int)(probey/10 + 0.05);
if (probecx != i || probecy != j) {
probecx = i;
probecy = j;
if (i < 1 || i > 8 || j < 1 || j > 8 ||
d.galaxy[probecx][probecy] == 1000) {
// Left galaxy or ran into supernova
if (REPORTS) {
if (ipage==0) pause(1);
ipage = 1;
skip(1);
proutn("Lt. Uhura- \"The deep space probe ");
if (i < 1 ||i > 8 || j < 1 || j > 8)
proutn("has left the galaxy");
else
proutn("is no longer transmitting");
prout(".\"");
}
future[FDSPROB] = 1e30;
break;
}
if (REPORTS) {
if (ipage==0) pause(1);
ipage = 1;
skip(1);
proutn("Lt. Uhura- \"The deep space probe is now in ");
cramlc(1, probecx, probecy);
prout(".\"");
}
}
/* Update star chart if Radio is working or have access to
radio. */
if (REPORTS)
starch[probecx][probecy] = damage[DRADIO] > 0.0 ?
d.galaxy[probecx][probecy]+1000 : 1;
proben--; // One less to travel
if (proben == 0 && isarmed &&
d.galaxy[probecx][probecy] % 10 > 0) {
/* lets blow the sucker! */
snova(1,0);
future[FDSPROB] = 1e30;
if (d.galaxy[quadx][quady] == 1000) return;
}
break;
}
}
}
void waiting(void) {
int key;
double temp, delay, origTime;
ididit = 0;
for (;;) {
key = scan();
if (key != IHEOL) break;
proutn("How long? ");
}
chew();
if (key != IHREAL) {
huh();
return;
}
origTime = delay = aaitem;
if (delay <= 0.0) return;
if (delay >= d.remtime || nenhere != 0) {
prout("Are you sure? ");
if (ja() == 0) return;
}
/* Alternate resting periods (events) with attacks */
resting = 1;
do {
if (delay <= 0) resting = 0;
if (resting == 0) {
cramf(d.remtime, 0, 2);
prout(" stardates left.");
return;
}
temp = Time = delay;
if (nenhere) {
double rtime = 1.0 + Rand();
if (rtime < temp) temp = rtime;
Time = temp;
}
if (Time < delay) attack(0);
if (nenhere==0) movetho();
if (alldone) return;
events();
ididit = 1;
if (alldone) return;
delay -= temp;
} while (d.galaxy[quadx][quady] != 1000); // leave if quadrant supernovas
resting = 0;
Time = 0;
}
void nova(int ix, int iy) {
static double course[] =
{0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};
int bot, top, top2, burst, hits[11][3], kount, icx, icy, mm, nn, j;
int iquad, iquad1, i, ll, newcx, newcy, ii, jj;
if (Rand() < 0.05) {
/* Wow! We've supernova'ed */
snova(ix, iy);
return;
}
/* handle initial nova */
quad[ix][iy] = IHDOT;
crmena(1, IHSTAR, 2, ix, iy);
prout(" novas.");
d.galaxy[quadx][quady] -= 1;
d.starkl++;
/* Set up stack to recursively trigger adjacent stars */
bot = top = top2 = 1;
kount = 0;
icx = icy = 0;
hits[1][1] = ix;
hits[1][2] = iy;
while (1) {
for (mm = bot; mm <= top; mm++)
for (nn = 1; nn <= 3; nn++) /* nn,j represents coordinates around current */
for (j = 1; j <= 3; j++) {
if (j==2 && nn== 2) continue;
ii = hits[mm][1]+nn-2;
jj = hits[mm][2]+j-2;
if (ii < 1 || ii > 10 || jj < 1 || jj > 10) continue;
iquad = quad[ii][jj];
switch (iquad) {
// case IHDOT: /* Empty space ends reaction
// case IHQUEST:
// case IHBLANK:
// case IHT:
// case IHWEB:
default:
break;
case IHSTAR: /* Affect another star */
if (Rand() < 0.05) {
/* This star supernovas */
snova(ii,jj);
return;
}
top2++;
hits[top2][1]=ii;
hits[top2][2]=jj;
d.galaxy[quadx][quady] -= 1;
d.starkl++;
crmena(1, IHSTAR, 2, ii, jj);
prout(" novas.");
quad[ii][jj] = IHDOT;
break;
case IHP: /* Destroy planet */
d.newstuf[quadx][quady] -= 1;
d.nplankl++;
crmena(1, IHP, 2, ii, jj);
prout(" destroyed.");
d.plnets[iplnet] = nulplanet;
iplnet = plnetx = plnety = 0;
if (landed == 1) {
finish(FPNOVA);
return;
}
quad[ii][jj] = IHDOT;
break;
case IHB: /* Destroy base */
d.galaxy[quadx][quady] -= 10;
for (i = 1; i <= d.rembase; i++)
if (d.baseqx[i]==quadx && d.baseqy[i]==quady) break;
d.baseqx[i] = d.baseqx[d.rembase];
d.baseqy[i] = d.baseqy[d.rembase];
d.rembase--;
basex = basey = 0;
d.basekl++;
newcnd();
crmena(1, IHB, 2, ii, jj);
prout(" destroyed.");
quad[ii][jj] = IHDOT;
break;
case IHE: /* Buffet ship */
case IHF:
prout("***Starship buffeted by nova.");
if (shldup) {
if (shield >= 2000.0) shield -= 2000.0;
else {
double diff = 2000.0 - shield;
energy -= diff;
shield = 0.0;
shldup = 0;
prout("***Shields knocked out.");
damage[DSHIELD] += 0.005*damfac*Rand()*diff;
}
}
else energy -= 2000.0;
if (energy <= 0) {
finish(FNOVA);
return;
}
/* add in course nova contributes to kicking starship*/
icx += sectx-hits[mm][1];
icy += secty-hits[mm][2];
kount++;
break;
case IHK: /* kill klingon */
deadkl(ii,jj,iquad, ii, jj);
break;
case IHC: /* Damage/destroy big enemies */
case IHS:
case IHR:
for (ll = 1; ll <= nenhere; ll++)
if (kx[ll]==ii && ky[ll]==jj) break;
kpower[ll] -= 800.0; /* If firepower is lost, die */
if (kpower[ll] <= 0.0) {
deadkl(ii, jj, iquad, ii, jj);
break;
}
newcx = ii + ii - hits[mm][1];
newcy = jj + jj - hits[mm][2];
crmena(1, iquad, 2, ii, jj);
proutn(" damaged");
if (newcx<1 || newcx>10 || newcy<1 || newcy>10) {
/* can't leave quadrant */
skip(1);
break;
}
iquad1 = quad[newcx][newcy];
if (iquad1 == IHBLANK) {
proutn(", blasted into ");
crmena(0, IHBLANK, 2, newcx, newcy);
skip(1);
deadkl(ii, jj, iquad, newcx, newcy);
break;
}
if (iquad1 != IHDOT) {
/* can't move into something else */
skip(1);
break;
}
proutn(", buffeted to");
cramlc(2, newcx, newcy);
quad[ii][jj] = IHDOT;
quad[newcx][newcy] = iquad;
kx[ll] = newcx;
ky[ll] = newcy;
kavgd[ll] = sqrt(square(sectx-newcx)+square(secty-newcy));
kdist[ll] = kavgd[ll];
skip(1);
break;
}
}
if (top == top2) break;
bot = top + 1;
top = top2;
}
if (kount==0) return;
/* Starship affected by nova -- kick it away. */
dist = kount*0.1;
if (icx) icx = (icx < 0 ? -1 : 1);
if (icy) icy = (icy < 0 ? -1 : 1);
direc = course[3*(icx+1)+icy+2];
if (direc == 0.0) dist = 0.0;
if (dist == 0.0) return;
Time = 10.0*dist/16.0;
skip(1);
prout("Force of nova displaces starship.");
iattak=2; /* Eliminates recursion problem */
lmove();
Time = 10.0*dist/16.0;
return;
}
void snova(int insx, int insy) {
int comdead, nqx, nqy, nsx, nsy, num, kldead, iscdead;
int nrmdead, npdead;
int insipient=0;
nsx = insx;
nsy = insy;
if (insy== 0) {
if (insx == 1) {
/* NOVAMAX being used */
nqx = probecx;
nqy = probecy;
}
else {
int stars = 0;
/* Scheduled supernova -- select star */
/* logic changed here so that we won't favor quadrants in top
left of universe */
for (nqx = 1; nqx<=8; nqx++) {
for (nqy = 1; nqy<=8; nqy++) {
stars += d.galaxy[nqx][nqy] % 10;
}
}
if (stars == 0) return; /* nothing to supernova exists */
num = Rand()*stars + 1;
for (nqx = 1; nqx<=8; nqx++) {
for (nqy = 1; nqy<=8; nqy++) {
num -= d.galaxy[nqx][nqy] % 10;
if (num <= 0) break;
}
if (num <=0) break;
}
#ifdef DEBUG
if (idebug) {
proutn("Super nova here?");
if (ja()==1) {
nqx = quadx;
nqy = quady;
}
}
#endif
}
if (nqx != quady || nqy != quady || justin != 0) {
/* it isn't here, or we just entered (treat as inroute) */
if (REPORTS) {
skip(1);
proutn("Message from Starfleet Command Stardate ");
cramf(d.date, 0, 1);
skip(1);
proutn(" Supernova in");
cramlc(1, nqx, nqy);
prout("; caution advised.");
}
}
else {
/* we are in the quadrant! */
insipient = 1;
num = Rand()* (d.galaxy[nqx][nqy]%10) + 1;
for (nsx=1; nsx < 10; nsx++) {
for (nsy=1; nsy < 10; nsy++) {
if (quad[nsx][nsy]==IHSTAR) {
num--;
if (num==0) break;
}
}
if (num==0) break;
}
}
}
else {
insipient = 1;
}
if (insipient) {
skip(1);
prouts("***RED ALERT! RED ALERT!");
skip(1);
proutn("***Incipient supernova detected at");
cramlc(2, nsx, nsy);
skip(1);
nqx = quadx;
nqy = quady;
if (square(nsx-sectx) + square(nsy-secty) <= 2.1) {
proutn("Emergency override attempts t");
prouts("***************");
skip(1);
stars();
alldone=1;
}
}
/* destroy any Klingons in supernovaed quadrant */
num=d.galaxy[nqx][nqy];
kldead = num/100;
d.remkl -= kldead; // Moved here to correctly set remaining Klingon count
comdead = iscdead = 0;
if (nqx==d.isx && nqy == d.isy) {
/* did in the Supercommander! */
d.nscrem = d.isx = d.isy = isatb = iscate = 0;
iscdead = 1;
kldead--; /* Get proper kill credit */
future[FSCMOVE] = future[FSCDBAS] = 1e30;
}
if (d.remcom) {
int maxloop = d.remcom, l;
for (l = 1; l <= maxloop; l++) {
if (d.cx[l] == nqx && d.cy[l] == nqy) {
d.cx[l] = d.cx[d.remcom];
d.cy[l] = d.cy[d.remcom];
d.cx[d.remcom] = d.cy[d.remcom] = 0;
d.remcom--;
kldead--;
comdead++;
if (d.remcom==0) future[FTBEAM] = 1e30;
break;
}
}
}
/* destroy Romulans and planets in supernovaed quadrant */
num = d.newstuf[nqx][nqy];
d.newstuf[nqx][nqy] = 0;
nrmdead = num/10;
d.nromrem -= nrmdead;
npdead = num - nrmdead*10;
if (npdead) {
int l;
for (l = 1; l <= inplan; l++)
if (d.plnets[l].x == nqx && d.plnets[l].y == nqy) {
d.plnets[l] = nulplanet;
}
}
/* Destroy any base in supernovaed quadrant */
if (d.rembase) {
int maxloop = d.rembase, l;
for (l = 1; l <= maxloop; l++)
if (d.baseqx[l]==nqx && d.baseqy[l]==nqy) {
d.baseqx[l] = d.baseqx[d.rembase];
d.baseqy[l] = d.baseqy[d.rembase];
d.baseqx[d.rembase] = d.baseqy[d.rembase] = 0;
d.rembase--;
break;
}
}
/* If starship caused supernova, tally up destruction */
if (insx) {
num = d.galaxy[nqx][nqy] % 100;
d.starkl += num % 10;
d.basekl += num/10;
d.killk += kldead;
d.killc += comdead;
d.nromkl += nrmdead;
d.nplankl += npdead;
d.nsckill += iscdead;
}
/* mark supernova in galaxy and in star chart */
if ((quadx == nqx && quady == nqy) || REPORTS)
starch[nqx][nqy] = 1;
d.galaxy[nqx][nqy] = 1000;
/* If supernova destroys last klingons give special message */
if (d.remkl==0 && (nqx != quadx || nqy != quady)) {
skip(2);
if (insx == 0) prout("Lucky you!");
proutn("A supernova in");
cramlc(1, nqx, nqy);
prout(" has just destroyed the last Klingons.");
finish(FWON);
return;
}
/* if some Klingons remain, continue or die in supernova */
if (alldone) finish(FSNOVAED);
return;
}

491
finish.c Executable file
View File

@ -0,0 +1,491 @@
#include "sst.h"
#include <string.h>
#include <time.h>
void dstrct() {
/* Finish with a BANG! */
chew();
if (damage[DCOMPTR] != 0.0) {
prout("Computer damaged; cannot execute destruct sequence.");
return;
}
skip(1);
prouts("---WORKING---"); skip(1);
prout("SELF-DESTRUCT-SEQUENCE-ACTIVATED");
prouts(" 10"); skip(1);
prouts(" 9"); skip(1);
prouts(" 8"); skip(1);
prouts(" 7"); skip(1);
prouts(" 6"); skip(1);
prout("ENTER-CORRECT-PASSWORD-TO-CONTINUE-");
prout("SELF-DESTRUCT-SEQUENCE-OTHERWISE-");
prout("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED");
scan();
chew();
if (strcmp(passwd, citem) != 0) {
prouts("PASSWORD-REJECTED;"); skip(1);
prout("CONTINUITY-EFFECTED");
skip(1);
return;
}
prouts("PASSWORD-ACCEPTED"); skip(1);
prouts(" 5"); skip(1);
prouts(" 4"); skip(1);
prouts(" 3"); skip(1);
prouts(" 2"); skip(1);
prouts(" 1"); skip(1);
if (Rand() < 0.15) {
prouts("GOODBYE-CRUEL-WORLD");
skip(1);
}
skip(2);
kaboom();
}
void kaboom(void) {
stars();
if (ship==IHE) prouts("***");
prouts("********* Entropy of ");
crmshp();
prouts(" maximized *********");
skip(1);
stars();
skip(1);
if (nenhere != 0) {
double whammo = 25.0 * energy;
int l=1;
while (l <= nenhere) {
if (kpower[l]*kdist[l] <= whammo)
deadkl(kx[l],ky[l], quad[kx[l]][ky[l]], kx[l], ky[l]);
l++;
}
}
finish(FDILITHIUM);
}
void finish(FINTYPE ifin) {
int igotit = 0;
alldone = 1;
skip(3);
printf("It is stardate %.1f .\n\n", d.date);
switch (ifin) {
case FWON: // Game has been won
if (d.nromrem != 0)
printf("The remaining %d Romulans surrender to Starfleet Command.\n",
d.nromrem);
prout("You have smashed the Klingon invasion fleet and saved");
prout("the Federation.");
#ifdef CAPTURE
if (alive && brigcapacity-brigfree > 0) { // captured Klingon crew will get transfered to starbase
kcaptured += brigcapacity-brigfree;
printf("The %d captured Klingons are transferred to Star Fleet Command.\n",
brigcapacity-brigfree);
}
#endif
gamewon=1;
if (alive) {
double badpt;
badpt = 5.*d.starkl + casual + 10.*d.nplankl +
45.*nhelp+100.*d.basekl;
if (ship == IHF) badpt += 100.0;
else if (ship == 0) badpt += 200.0;
if (badpt < 100.0) badpt = 0.0; // Close enough!
if (d.date-indate < 5.0 ||
// killsPerDate >= RateMax
(d.killk+d.killc+d.nsckill)/(d.date-indate) >=
0.1*skill*(skill+1.0) + 0.1 + 0.008*badpt) {
skip(1);
prout("In fact, you have done so well that Starfleet Command");
switch (skill) {
case SNOVICE:
prout("promotes you one step in rank from \"Novice\" to \"Fair\".");
break;
case SFAIR:
prout("promotes you one step in rank from \"Fair\" to \"Good\".");
break;
case SGOOD:
prout("promotes you one step in rank from \"Good\" to \"Expert\".");
break;
case SEXPERT:
prout("promotes you to Commodore Emeritus.");
skip(1);
prout("Now that you think you're really good, try playing");
prout("the \"Emeritus\" game. It will splatter your ego.");
break;
case SEMERITUS:
skip(1);
prout("Computer- ERROR-ERROR-ERROR-ERROR");
skip(1);
prout(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM");
prout(" THIS-PROGRAM-MUST-SURVIVE");
prout(" THIS-PROGRAM-MUST-SURVIVE");
prout(" THIS-PROGRAM-MUST-SURVIVE");
prout(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI");
skip(1);
prout("Now you can retire and write your own Star Trek game!");
skip(1);
break;
}
if (skill > SGOOD) {
if (thawed
#ifdef DEBUG
&& !idebug
#endif
)
prout("You cannot get a citation, so...");
else {
prout("Do you want your Commodore Emeritus Citation printed?");
proutn("(You need a 132 column printer.)");
chew();
if (ja()) {
igotit = 1;
}
}
}
}
// Only grant long life if alive (original didn't!)
skip(1);
prout("LIVE LONG AND PROSPER.");
}
score(0);
if (igotit != 0) plaque();
return;
case FDEPLETE: // Federation Resources Depleted
prout("Your time has run out and the Federation has been");
prout("conquered. Your starship is now Klingon property,");
prout("and you are put on trial as a war criminal. On the");
proutn("basis of your record, you are ");
if (d.remkl*3.0 > inkling) {
prout("aquitted.");
skip(1);
prout("LIVE LONG AND PROSPER.");
}
else {
prout("found guilty and");
prout("sentenced to death by slow torture.");
alive = 0;
}
score(0);
return;
case FLIFESUP:
prout("Your life support reserves have run out, and");
prout("you die of thirst, starvation, and asphyxiation.");
prout("Your starship is a derelict in space.");
break;
case FNRG:
prout("Your energy supply is exhausted.");
skip(1);
prout("Your starship is a derelict in space.");
break;
case FBATTLE:
proutn("The ");
crmshp();
prout("has been destroyed in battle.");
skip(1);
prout("Dulce et decorum est pro patria mori.");
break;
case FNEG3:
prout("You have made three attempts to cross the negative energy");
prout("barrier which surrounds the galaxy.");
skip(1);
prout("Your navigation is abominable.");
score(0);
return;
case FNOVA:
prout("Your starship has been destroyed by a nova.");
prout("That was a great shot.");
skip(1);
break;
case FSNOVAED:
proutn("The ");
crmshp();
prout(" has been fried by a supernova.");
prout("...Not even cinders remain...");
break;
case FABANDN:
prout("You have been captured by the Klingons. If you still");
prout("had a starbase to be returned to, you would have been");
prout("repatriated and given another chance. Since you have");
prout("no starbases, you will be mercilessly tortured to death.");
break;
case FDILITHIUM:
prout("Your starship is now an expanding cloud of subatomic particles");
break;
case FMATERIALIZE:
prout("Starbase was unable to re-materialize your starship.");
prout("Sic transit gloria muntdi");
break;
case FPHASER:
proutn("The ");
crmshp();
prout(" has been cremated by its own phasers.");
break;
case FLOST:
prout("You and your landing party have been");
prout("converted to energy, dissipating through space.");
break;
case FMINING:
prout("You are left with your landing party on");
prout("a wild jungle planet inhabited by primitive cannibals.");
skip(1);
prout("They are very fond of \"Captain Kirk\" soup.");
skip(1);
proutn("Without your leadership, the ");
crmshp();
prout(" is destroyed.");
break;
case FDPLANET:
prout("You and your mining party perish.");
skip(1);
prout("That was a great shot.");
skip(1);
break;
case FSSC:
prout("The Galileo is instantly annihilated by the supernova.");
// no break;
case FPNOVA:
prout("You and your mining party are atomized.");
skip(1);
proutn("Mr. Spock takes command of the ");
crmshp();
prout(" and");
prout("joins the Romulans, reigning terror on the Federation.");
break;
case FSTRACTOR:
prout("The shuttle craft Galileo is also caught,");
prout("and breaks up under the strain.");
skip(1);
prout("Your debris is scattered for millions of miles.");
proutn("Without your leadership, the ");
crmshp();
prout(" is destroyed.");
break;
case FDRAY:
prout("The mutants attack and kill Spock.");
prout("Your ship is captured by Klingons, and");
prout("your crew is put on display in a Klingon zoo.");
break;
case FTRIBBLE:
prout("Tribbles consume all remaining water,");
prout("food, and oxygen on your ship.");
skip(1);
prout("You die of thirst, starvation, and asphyxiation.");
prout("Your starship is a derelict in space.");
break;
case FHOLE:
prout("Your ship is drawn to the center of the black hole.");
prout("You are crushed into extremely dense matter.");
break;
#ifdef CLOAKING
case FCLOAK:
ncviol++;
prout("You have violated the Treaty of Algeron.");
prout("The Romulan Empire can never trust you again.");
break;
#endif
}
#ifdef CLOAKING
if (ifin!=FWON && ifin!=FCLOAK && iscloaked!=0) {
prout("Your ship was cloaked so your subspace radio did not receive anything.");
prout("You may have missed some warning messages.");
skip(1);
}
#endif
if (ship==IHF) ship= 0;
else if (ship == IHE) ship = IHF;
alive = 0;
if (d.remkl != 0) {
double goodies = d.remres/inresor;
double baddies = (d.remkl + 2.0*d.remcom)/(inkling+2.0*incom);
if (goodies/baddies >= 1.0+0.5*Rand()) {
prout("As a result of your actions, a treaty with the Klingon");
prout("Empire has been signed. The terms of the treaty are");
if (goodies/baddies >= 3.0+Rand()) {
prout("favorable to the Federation.");
skip(1);
prout("Congratulations!");
}
else
prout("highly unfavorable to the Federation.");
}
else
prout("The Federation will be destroyed.");
}
else {
prout("Since you took the last Klingon with you, you are a");
prout("martyr and a hero. Someday maybe they'll erect a");
prout("statue in your memory. Rest in peace, and try not");
prout("to think about pigeons.");
gamewon = 1;
}
score(0);
}
void score(int inGame) {
double timused = d.date - indate;
int ithperd, iwon, klship;
int dnromrem = d.nromrem; // Leave global value alone
if (!inGame) pause(0);
iskill = skill;
if ((timused == 0 || d.remkl != 0) && timused < 5.0) timused = 5.0;
perdate = (d.killc + d.killk + d.nsckill)/timused;
ithperd = 500*perdate + 0.5;
iwon = 0;
if (gamewon) iwon = 100*skill;
if (ship == IHE) klship = 0;
else if (ship == IHF) klship = 1;
else klship = 2;
if (gamewon == 0 || inGame) dnromrem = 0; // None captured if no win or if still in the game
iscore = 10*d.killk + 50*d.killc + ithperd + iwon
- 100*d.basekl - 100*klship - 45*nhelp -5*d.starkl - casual
+ 20*d.nromkl + 200*d.nsckill - 10*d.nplankl + dnromrem;
#ifdef CLOAKING
iscore -= 100*ncviol;
#endif
#ifdef CAPTURE
iscore += 3*kcaptured;
#endif
if (alive == 0) iscore -= 200;
skip(2);
if (inGame) prout("Your score so far --");
else prout("Your score --");
if (d.nromkl)
printf(d.nromkl> 1 ? "%6d Romulan ships destroyed %5d\n" : "%6d Romulan ship destroyed %5d\n",
d.nromkl, 20*d.nromkl);
if (dnromrem)
printf(dnromrem > 1 ? "%6d Romulan ships captured %5d\n" : "%6d Romulan ship captured %5d\n",
dnromrem, dnromrem);
if (d.killk)
printf(d.killk > 1 ? "%6d ordinary Klingon ships destroyed %5d\n" : "%6d ordinary Klingon ship destroyed %5d\n",
d.killk, 10*d.killk);
if (d.killc)
printf(d.killc > 1 ? "%6d Klingon Commander ships destroyed %5d\n" : "%6d Klingon Commander ship destroyed %5d\n",
d.killc, 50*d.killc);
if (d.nsckill)
printf("%6d Super-Commander ship destroyed %5d\n",
d.nsckill, 200*d.nsckill);
if (ithperd)
printf("%6.2f Klingons per stardate %5d\n",
perdate, ithperd);
#ifdef CAPTURE
if (kcaptured)
printf(kcaptured > 1 ? "%6d Klingons captured %5d\n" : "%6d Klingon captured %5d\n",
kcaptured, 3*kcaptured);
#endif
if (d.starkl)
printf(d.starkl > 1 ? "%6d stars destroyed by your action %5d\n" : "%6d star destroyed by your action %5d\n",
d.starkl, -5*d.starkl);
if (d.nplankl)
printf(d.nplankl > 1 ? "%6d planets destroyed by your action %5d\n" : "%6d planet destroyed by your action %5d\n",
d.nplankl, -10*d.nplankl);
if (d.basekl)
printf(d.basekl > 1 ? "%6d bases destroyed by your action %5d\n" : "%6d base destroyed by your action %5d\n",
d.basekl, -100*d.basekl);
if (nhelp)
printf(nhelp > 1 ? "%6d calls for help from starbase %5d\n" : "%6d call for help from starbase %5d\n",
nhelp, -45*nhelp);
if (casual)
printf(casual > 1 ? "%6d casualties incurred %5d\n" : "%6d casualty incurred %5d\n",
casual, -casual);
if (klship)
printf(klship > 1 ? "%6d ships lost or destroyed %5d\n" : "%6d ship lost or destroyed %5d\n",
klship, -100*klship);
#ifdef CLOAKING
if (ncviol>0)
printf(ncviol > 1 ? "%6d Treaty of Algeron violations %5d\n" : "%6d Treaty of Algeron violation %5d\n",
ncviol, -100*ncviol);
#endif
if (alive==0)
prout("Penalty for getting yourself killed -200");
if (gamewon) {
skip(1);
proutn("Bonus for winning ");
switch (skill) {
case SNOVICE: proutn("Novice game "); break;
case SFAIR: proutn("Fair game "); break;
case SGOOD: proutn("Good game "); break;
case SEXPERT: proutn("Expert game "); break;
case SEMERITUS: proutn("Emeritus game"); break;
}
printf(" %5d\n", iwon);
}
skip(2);
printf("TOTAL SCORE %5d\n", iscore);
if (inGame && skill < SGOOD) printf("REMEMBER--The score doesn't really matter until the mission is accomplished!\n");
}
void plaque(void) {
FILE *fp=NULL;
time_t t;
char *timestring;
int nskip;
char winner[128];
skip(2);
while (fp == NULL) {
printf("File or device name for your plaque:");
fgets(winner, 128, stdin);
winner[strlen(winner)-1] = '\0';
fp = fopen(winner, "w");
if (fp==NULL) {
printf("Invalid name.\n");
}
}
printf("Enter name to go on plaque (up to 30 characters):");
fgets(winner, 128, stdin);
winner[strlen(winner)-1] = '\0';
winner[30] = '\0';
nskip = 64 - strlen(winner)/2;
fprintf(fp,"\n\n\n\n");
/* --------DRAW ENTERPRISE PICTURE. */
fprintf(fp, " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" );
fprintf(fp, " EEE E : : : E\n" );
fprintf(fp, " EE EEE E : : NCC-1701 : E\n");
fprintf(fp, " EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE E : : : E\n");
fprintf(fp, " E E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n");
fprintf(fp, " EEEEEEEEE EEEEEEEEEEEEE E E\n");
fprintf(fp, " EEEEEEE EEEEE E E E E\n");
fprintf(fp, " EEE E E E E\n");
fprintf(fp, " E E E E\n");
fprintf(fp, " EEEEEEEEEEEEE E E\n");
fprintf(fp, " EEE : EEEEEEE EEEEEEEE\n");
fprintf(fp, " :E : EEEE E\n");
fprintf(fp, " .-E -:----- E\n");
fprintf(fp, " :E : E\n");
fprintf(fp, " EE : EEEEEEEE\n");
fprintf(fp, " EEEEEEEEEEEEEEEEEEEEEEE\n");
fprintf(fp, "\n\n\n");
fprintf(fp, " U. S. S. ENTERPRISE\n");
fprintf(fp, "\n\n\n\n");
fprintf(fp, " For demonstrating outstanding ability as a starship captain\n");
fprintf(fp, "\n");
fprintf(fp, " Starfleet Command bestows to you\n");
fprintf(fp, "\n");
fprintf(fp,"%*s%s\n\n", nskip, "", winner);
fprintf(fp, " the rank of\n\n");
fprintf(fp, " \"Commodore Emeritus\"\n\n");
fprintf(fp, " ");
switch (iskill) {
case SEXPERT: fprintf(fp," Expert level\n\n"); break;
case SEMERITUS: fprintf(fp,"Emeritus level\n\n"); break;
default: fprintf(fp," Cheat level\n\n"); break;
}
t = time(NULL);
timestring = ctime(&t);
fprintf(fp, " This day of %.6s %.4s, %.8s\n\n",
timestring+4, timestring+20, timestring+11);
fprintf(fp," Your score: %d\n\n", iscore);
fprintf(fp," Klingons per stardate: %.2f\n", perdate);
fclose(fp);
}

18
makefile Normal file
View File

@ -0,0 +1,18 @@
CFLAGS= -O -DSCORE -DCAPTURE -DCLOAKING -Wno-unused-result
# CFLAGS= -O -Wno-unused-result
.c.o:
$(CC) $(CFLAGS) -c $<
OFILES= sst.o finish.o reports.o setup.o osx.o moving.o battle.o events.o ai.o planets.o
HFILES= sst.h
sst: $(OFILES)
gcc -o sst $(OFILES) -lm
clean:
rm $(OFILES)
$(OFILES): $(HFILES)

1017
moving.c Executable file

File diff suppressed because it is too large Load Diff

37
osx.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
void randomize(void) {
srand((int)time(NULL));
}
int max(int a, int b) {
if (a > b) return a;
return b;
}
int min(int a, int b) {
if (a < b) return a;
return b;
}
int // <editor-fold defaultstate="collapsed" desc="comment">
getch// </editor-fold>
(void) {
char chbuf[1];
struct termios oldstate, newstate;
fflush(stdout);
tcgetattr(0, &oldstate);
newstate = oldstate;
newstate.c_lflag &= ~ICANON;
newstate.c_lflag &= ~ECHO;
tcsetattr(0, TCSANOW, &newstate);
read(0, &chbuf, 1);
tcsetattr(0, TCSANOW, &oldstate);
return chbuf[0];
}

505
planets.c Executable file
View File

@ -0,0 +1,505 @@
#include "sst.h"
static char classes[4][2]={"","M","N","O"};
static int height;
static int consumeTime(void) {
/* I think most of this avoidance was caused by overlay scheme.
Let's see what happens if all events can occur here */
// double asave;
ididit = 1;
#if 0
/* Don't wory about this */
if (future[FTBEAM] <= d.date+Time && d.remcom != 0 && condit != IHDOCKED) {
/* We are about to be tractor beamed -- operation fails */
return 1;
}
#endif
// asave = future[FSNOVA];
// future[FSNOVA] = 1e30; /* defer supernovas */
events(); /* Used to avoid if future[FSCMOVE] within time */
// future[FSNOVA] = asave;
/*fails if game over, quadrant super-novas or we've moved to new quadrant*/
if (alldone || d.galaxy[quadx][quady] == 1000 || justin != 0) return 1;
return 0;
}
void preport(void) {
int iknow = 0, i;
skip(1);
chew();
prout("Spock- \"Planet report follows, Captain.\"");
skip(1);
for (i = 1; i <= inplan; i++) {
if (d.plnets[i].known
#ifdef DEBUG
|| ( idebug && d.plnets[i].x !=0)
#endif
) {
iknow = 1;
#ifdef DEBUG
if (idebug && d.plnets[i].known==0) proutn("(Unknown) ");
#endif
cramlc(1, d.plnets[i].x, d.plnets[i].y);
proutn(" class ");
proutn(classes[d.plnets[i].pclass]);
proutn(" ");
if (d.plnets[i].crystals == 0) proutn("no ");
prout("dilithium crystals present.");
if (d.plnets[i].known==2)
prout(" Shuttle Craft Galileo on surface.");
}
}
if (iknow==0) prout("No information available.");
}
void orbit(void) {
double asave;
skip(1);
chew();
ididit=0;
if (inorbit!=0) {
prout("Already in standard orbit.");
return;
}
if (damage[DWARPEN] != 0 && damage[DIMPULS] != 0) {
prout("Both warp and impulse engines damaged.");
return;
}
if (plnetx == 0 || abs(sectx-plnetx) > 1 || abs(secty-plnety) > 1) {
crmshp();
prout(" not adjacent to planet.\n");
return;
}
Time = 0.02+0.03*Rand();
prout("Helmsman Sulu- \"Entering standard orbit, Sir.\"");
newcnd();
if (consumeTime()) return;
proutn("Sulu- \"Entered orbit at altitude ");
cramf(height = (1400.+7200.*Rand()), 0, 2);
prout(" kilometers.\"");
inorbit = 1;
return;
}
void sensor(void) {
skip(1);
chew();
if (damage[DSRSENS] != 0.0) {
prout("Short range sensors damaged.");
return;
}
if (plnetx == 0) {
prout("No planet in this quadrant.");
return;
}
proutn("Spock- \"Sensor scan for");
cramlc(1, quadx, quady);
prout("-");
skip(1);
proutn(" Planet at");
cramlc(2, plnetx, plnety);
proutn(" is of class ");
proutn(classes[d.plnets[iplnet].pclass]);
prout(".");
if (d.plnets[iplnet].known==2)
prout(" Sensors show Galileo still on surface.");
proutn(" Readings indicate");
if (d.plnets[iplnet].crystals == 0) proutn(" no");
prout(" dilithium crystals present.\"");
if (d.plnets[iplnet].known == 0) d.plnets[iplnet].known = 1;
return;
}
void beam(void) {
chew();
skip(1);
if (damage[DTRANSP] != 0) {
prout("Transporter damaged.");
if (damage[DSHUTTL]==0 && (d.plnets[iplnet].known==2 || iscraft == 1)) {
skip(1);
prout("Spock- \"May I suggest the shuttle craft, Sir?\" ");
if (ja() != 0) shuttle();
}
return;
}
if (inorbit==0) {
crmshp();
prout(" not in standard orbit.");
return;
}
if (shldup!=0) {
prout("Impossible to transport through shields.");
return;
}
if (d.plnets[iplnet].known==0) {
prout("Spock- \"Captain, we have no information on this planet");
prout(" and Starfleet Regulations clearly state that in this situation");
prout(" you may not go down.\"");
return;
}
if (landed==1) {
/* Coming from planet */
if (d.plnets[iplnet].known==2) {
proutn("Spock- \"Wouldn't you rather take the Galileo?\" ");
if (ja() != 0) {
chew();
return;
}
prout("Your crew hides the Galileo to prevent capture by aliens.");
}
prout("Landing party assembled, ready to beam up.");
skip(1);
prout("Kirk whips out communicator...");
prouts("BEEP BEEP BEEP");
skip(2);
prout("\"Kirk to enterprise- Lock on coordinates...energize.\"");
}
else {
/* Going to planet */
if (d.plnets[iplnet].crystals==0) {
prout("Spock- \"Captain, I fail to see the logic in");
prout(" exploring a planet with no dilithium crystals.");
proutn(" Are you sure this is wise?\" ");
if (ja()==0) {
chew();
return;
}
}
prout("Scotty- \"Transporter room ready, Sir.\"");
skip(1);
prout("Kirk, and landing party prepare to beam down to planet surface.");
skip(1);
prout("Kirk- \"Energize.\"");
}
skip(1);
prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .");
skip(2);
if (Rand() > 0.98) {
prouts("BOOOIIIOOOIIOOOOIIIOIING . . .");
skip(2);
prout("Scotty- \"Oh my God! I've lost them.\"");
finish(FLOST);
return;
}
prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW");
skip(2);
prout("Transport complete.");
landed = -landed;
if (landed==1 && d.plnets[iplnet].known==2) {
prout("The shuttle craft Galileo is here!");
}
if (landed!=1 && imine==1) {
icrystl = 1;
cryprob = 0.05;
}
imine = 0;
return;
}
void mine(void) {
ididit = 0;
skip(1);
chew();
if (landed!= 1) {
prout("Mining party not on planet.");
return;
}
if (d.plnets[iplnet].crystals == 0) {
prout("No dilithium crystals on this planet.");
return;
}
if (imine == 1) {
prout("You've already mined enough crystals for this trip.");
return;
}
if (icrystl == 1 && cryprob == 0.05) {
proutn("With all those fresh crystals aboard the ");
crmshp();
skip(1);
prout("there's no reason to mine more at this time.");
return;
}
Time = (0.1+0.2*Rand())*d.plnets[iplnet].pclass;
if (consumeTime()) return;
prout("Mining operation complete.");
imine = 1;
return;
}
void usecrystals(void) {
skip(1);
chew();
if (icrystl!=1) {
prout("No dilithium crystals available.");
return;
}
if (energy >= 1000) {
prout("Spock- \"Captain, Starfleet Regulations prohibit such an operation");
prout(" except when condition Yellow exists.");
return;
}
prout("Spock- \"Captain, I must warn you that loading");
prout(" raw dilithium crystals into the ship's power");
prout(" system may risk a severe explosion.");
proutn(" Are you sure this is wise?\" ");
if (ja()==0) {
chew();
return;
}
skip(1);
prout("Engineering Officer Scott- \"(GULP) Aye Sir.");
prout(" Mr. Spock and I will try it.\"");
skip(1);
prout("Spock- \"Crystals in place, Sir.");
prout(" Ready to activate circuit.\"");
skip(1);
prouts("Scotty- \"Keep your fingers crossed, Sir!\"");
skip(1);
if (Rand() <= cryprob) {
prouts(" \"Activating now! - - No good! It's***");
skip(2);
prouts("***RED ALERT! RED A*L********************************");
skip(1);
stars();
prouts("****************** KA-BOOM!!!! *******************");
skip(1);
kaboom();
return;
}
energy += 5000.0*(1.0 + 0.9*Rand());
prouts(" \"Activating now! - - ");
prout("The instruments");
prout(" are going crazy, but I think it's");
prout(" going to work!! Congratulations, Sir!\"");
cryprob *= 2.0;
return;
}
void shuttle(void) {
chew();
skip(1);
ididit = 0;
if(damage[DSHUTTL] != 0.0) {
if (damage[DSHUTTL] == -1.0) {
if (inorbit && d.plnets[iplnet].known == 2)
prout("Ye Faerie Queene has no shuttle craft bay to dock it at.");
else
prout("Ye Faerie Queene had no shuttle craft.");
}
else if (damage[DSHUTTL] > 0)
prout("The Galileo is damaged.");
else prout("Shuttle craft is now serving Big Mac's.");
return;
}
if (inorbit==0) {
crmshp();
prout(" not in standard orbit.");
return;
}
if ((d.plnets[iplnet].known != 2) && iscraft != 1) {
prout("Shuttle craft not currently available.");
return;
}
if (landed==-1 && d.plnets[iplnet].known==2) {
prout("You will have to beam down to retrieve the shuttle craft.");
return;
}
if (shldup!=0 || condit == IHDOCKED) {
prout("Shuttle craft cannot pass through shields.");
return;
}
if (d.plnets[iplnet].known==0) {
prout("Spock- \"Captain, we have no information on this planet");
prout(" and Starfleet Regulations clearly state that in this situation");
prout(" you may not fly down.\"");
return;
}
Time = 3.0e-5*height;
if (Time >= 0.8*d.remtime) {
prout("First Officer Spock- \"Captain, I compute that such");
prout(" a maneuver would require approximately ");
cramf(100*Time/d.remtime,0,4);
prout("% of our");
prout("remaining time.");
prout("Are you sure this is wise?\" ");
if (ja()==0) {
Time = 0.0;
return;
}
}
if (landed == 1) {
/* Kirk on planet */
if (iscraft==1) {
/* Galileo on ship! */
if (damage[DTRANSP]==0) {
proutn("Spock- \"Would you rather use the transporter?\" ");
if (ja() != 0) {
beam();
return;
}
proutn("Shuttle crew");
}
else
proutn("Rescue party");
prout(" boards Galileo and swoops toward planet surface.");
iscraft = 0;
skip(1);
if (consumeTime()) return;
d.plnets[iplnet].known=2;
prout("Trip complete.");
return;
}
else {
/* Ready to go back to ship */
prout("You and your mining party board the");
prout("shuttle craft for the trip back to the Enterprise.");
skip(1);
prout("The short hop begins . . .");
d.plnets[iplnet].known=1;
icraft = 1;
skip(1);
landed = -1;
if (consumeTime()) return;
iscraft = 1;
icraft = 0;
if (imine!=0) {
icrystl = 1;
cryprob = 0.05;
}
imine = 0;
prout("Trip complete.");
return;
}
}
else {
/* Kirk on ship */
/* and so is Galileo */
prout("Mining party assembles in the hangar deck,");
prout("ready to board the shuttle craft \"Galileo\".");
skip(1);
prouts("The hangar doors open; the trip begins.");
skip(1);
icraft = 1;
iscraft = 0;
if (consumeTime()) return;
d.plnets[iplnet].known = 2;
landed = 1;
icraft = 0;
prout("Trip complete");
return;
}
}
void deathray(void) {
double r = Rand();
ididit = 0;
skip(1);
chew();
if (ship != IHE) {
prout("Ye Faerie Queene has no death ray.");
return;
}
if (nenhere==0) {
prout("Sulu- \"But Sir, there are no enemies in this quadrant.\"");
return;
}
if (damage[DDRAY] > 0.0) {
prout("Death Ray is damaged.");
return;
}
prout("Spock- \"Captain, the 'Experimental Death Ray'");
prout(" is highly unpredictable. Considering the alternatives,");
prout(" are you sure this is wise?\" ");
if (ja()==0) return;
prout("Spock- \"Acknowledged.\"");
skip(1);
ididit=1;
prouts("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE");
skip(1);
prout("Crew scrambles in emergency preparation.");
prout("Spock and Scotty ready the death ray and");
prout("prepare to channel all ship's power to the device.");
skip(1);
prout("Spock- \"Preparations complete, sir.\"");
prout("Kirk- \"Engage!\"");
skip(1);
prouts("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR");
skip(1);
if (r > .30) {
prouts("Sulu- \"Captain! It's working!\"");
skip(2);
while (nenhere > 0) {
deadkl(kx[1],ky[1],quad[kx[1]][ky[1]],kx[1],ky[1]);
}
prout("Ensign Chekov- \"Congratulations, Captain!\"");
if (d.remkl == 0) finish(FWON);
prout("Spock- \"Captain, I believe the `Experimental Death Ray'");
if (Rand() <= 0.05) {
prout(" is still operational.\"");
}
else {
prout(" has been rendered dysfunctional.\"");
damage[DDRAY] = 39.95;
}
return;
}
r = Rand(); // Pick failure method
if (r <= .30) {
prouts("Sulu- \"Captain! It's working!\"");
skip(1);
prouts("***RED ALERT! RED ALERT!");
skip(1);
prout("***MATTER-ANTIMATTER IMPLOSION IMMINENT!");
skip(1);
prouts("***RED ALERT! RED A*L********************************");
skip(1);
stars();
prouts("****************** KA-BOOM!!!! *******************");
skip(1);
kaboom();
return;
}
if (r <= .55) {
prouts("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\"");
skip(1);
prout("Lt. Uhura- \"Graaeek! Graaeek!\"");
skip(1);
prout("Spock- \"Fascinating! . . . All humans aboard");
prout(" have apparently been transformed into strange mutations.");
prout(" Vulcans do not seem to be affected.");
skip(1);
prout("Kirk- \"Raauch! Raauch!\"");
finish(FDRAY);
return;
}
if (r <= 0.75) {
int i,j;
prouts("Sulu- \"Captain! It's --WHAT?!?!\"");
skip(2);
proutn("Spock- \"I believe the word is");
prouts(" *ASTONISHING*");
prout(" Mr. Sulu.");
for (i=1; i<=10; i++)
for (j=1; j<=10; j++)
if (quad[i][j] == IHDOT) quad[i][j] = IHQUEST;
prout(" Captain, our quadrant is now infested with");
prouts(" - - - - - - *THINGS*.");
skip(1);
prout(" I have no logical explanation.\"");
return;
}
prouts("Sulu- \"Captain! The Death Ray is creating tribbles!\"");
skip(1);
prout("Scotty- \"There are so many tribbles down here");
prout(" in Engineering, we can't move for 'em, Captain.\"");
finish(FTRIBBLE);
return;
}

552
reports.c Executable file
View File

@ -0,0 +1,552 @@
#include "sst.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
void attakreport(void) {
if (future[FCDBAS] < 1e30) {
proutn("Starbase in ");
cramlc(1, batx, baty);
prout(" is currently under attack.");
proutn("It can hold out until Stardate ");
cramf(future[FCDBAS], 0,1);
prout(".");
}
if (isatb == 1) {
proutn("Starbase in ");
cramlc(1, d.isx, d.isy);
prout(" is under Super-commander attack.");
proutn("It can hold out until Stardate ");
cramf(future[FSCDBAS], 0, 1);
prout(".");
}
}
void report(int f) {
char *s1,*s2,*s3;
chew();
s1 = (thawed?"thawed ":"");
switch (length) {
case 1: s2="short"; break;
case 2: s2="medium"; break;
case 4: s2="long"; break;
default: s2="unknown length"; break;
}
switch (skill) {
case SNOVICE: s3="novice"; break;
case SFAIR: s3="fair"; break;
case SGOOD: s3="good"; break;
case SEXPERT: s3="expert"; break;
case SEMERITUS: s3="emeritus"; break;
default: s3="skilled"; break;
}
printf("\nYou %s playing a %s%s %s game.\n",
alldone? "were": "are now", s1, s2, s3);
if (skill>SGOOD && thawed && !alldone) prout("No plaque is allowed.");
if (tourn) printf("This is tournament game %d.\n", tourn);
if (f) printf("Your secret password is \"%s\"\n",passwd);
printf("%d of %d Klingon ships have been destroyed",
d.killk+d.killc+d.nsckill, inkling);
if (d.killc) printf(", including %d Commander%s.\n", d.killc, d.killc==1?"":"s");
else if (d.killk+d.nsckill > 0) prout(", but no Commanders.");
else prout(".");
if (skill > SFAIR) printf("The Super Commander has %sbeen destroyed.\n",
d.nscrem?"not ":"");
if (d.rembase != inbase) {
proutn("There ");
if (inbase-d.rembase==1) proutn("has been 1 base");
else {
proutn("have been ");
crami(inbase-d.rembase, 1);
proutn(" bases");
}
proutn(" destroyed, ");
crami(d.rembase, 1);
prout(" remaining.");
}
else printf("There are %d bases.\n", inbase);
if (REPORTS || iseenit) {
/* Don't report this if not seen and
either the radio is dead or not at base! */
attakreport();
iseenit = 1;
}
if (casual) printf("%d casualt%s suffered so far.\n",
casual, casual==1? "y" : "ies");
#ifdef CAPTURE
if (brigcapacity != brigfree) printf("%d Klingon%s in brig.\n",
brigcapacity-brigfree, brigcapacity-brigfree>1 ? "s" : "");
if (kcaptured > 0) printf("%d captured Klingon%s turned in to Star Fleet.\n",
kcaptured, kcaptured>1 ? "s" : "");
#endif
if (nhelp) printf("There were %d call%s for help.\n",
nhelp, nhelp==1 ? "" : "s");
if (ship == IHE) {
proutn("You have ");
if (nprobes) crami(nprobes,1);
else proutn("no");
proutn(" deep space probe");
if (nprobes!=1) proutn("s");
prout(".");
}
if (REPORTS && future[FDSPROB] != 1e30) {
if (isarmed)
proutn("An armed deep space probe is in");
else
proutn("A deep space probe is in");
cramlc(1, probecx, probecy);
prout(".");
}
if (icrystl) {
if (cryprob <= .05)
prout("Dilithium crystals aboard ship...not yet used.");
else {
int i=0;
double ai = 0.05;
while (cryprob > ai) {
ai *= 2.0;
i++;
}
printf("Dilithium crystals have been used %d time%s.\n",
i, i==1? "" : "s");
}
}
skip(1);
}
void lrscan(void) {
int x, y;
chew();
if (damage[DLRSENS] != 0.0) {
/* Now allow base's sensors if docked */
if (condit != IHDOCKED) {
prout("LONG-RANGE SENSORS DAMAGED.");
return;
}
skip(1);
proutn("Starbase's long-range scan for");
}
else {
skip(1);
proutn("Long-range scan for");
}
cramlc(1, quadx, quady);
skip(1);
if (coordfixed)
for (y = quady+1; y >= quady-1; y--) {
for (x = quadx-1; x <= quadx+1; x++) {
if (x == 0 || x > 8 || y == 0 || y > 8)
printf(" -1");
else {
printf("%5d", d.galaxy[x][y]);
// If radio works, mark star chart so
// it will show current information.
// Otherwise mark with current
// value which is fixed.
starch[x][y] = damage[DRADIO] > 0 ? d.galaxy[x][y]+1000 :1;
}
}
putchar('\n');
}
else
for (x = quadx-1; x <= quadx+1; x++) {
for (y = quady-1; y <= quady+1; y++) {
if (x == 0 || x > 8 || y == 0 || y > 8)
printf(" -1");
else {
printf("%5d", d.galaxy[x][y]);
// If radio works, mark star chart so
// it will show current information.
// Otherwise mark with current
// value which is fixed.
starch[x][y] = damage[DRADIO] > 0 ? d.galaxy[x][y]+1000 :1;
}
}
putchar('\n');
}
}
void dreprt(void) {
int jdam = FALSE, i;
chew();
for (i = 1; i <= ndevice; i++) {
if (damage[i] > 0.0) {
if (!jdam) {
skip(1);
prout("DEVICE -REPAIR TIMES-");
prout(" IN FLIGHT DOCKED");
jdam = TRUE;
}
printf(" %16s ", device[i]);
cramf(damage[i]+0.05, 8, 2);
proutn(" ");
cramf(docfac*damage[i]+0.005, 8, 2);
skip(1);
}
}
if (!jdam) prout("All devices functional.");
}
void chart(int nn) {
int i,j;
chew();
skip(1);
if (stdamtim != 1e30 && stdamtim != d.date && condit == IHDOCKED) {
prout("Spock- \"I revised the Star Chart from the");
prout(" starbase's records.\"");
skip(1);
}
if (nn == 0) prout("STAR CHART FOR THE KNOWN GALAXY");
if (stdamtim != 1e30) {
if (condit == IHDOCKED) {
/* We are docked, so restore chart from base information -- these values won't update! */
stdamtim = d.date;
for (i=1; i <= 8 ; i++)
for (j=1; j <= 8; j++)
if (starch[i][j] == 1) starch[i][j] = d.galaxy[i][j]+1000;
}
else {
proutn("(Last surveillance update ");
cramf(d.date-stdamtim, 0, 1);
prout(" stardates ago.)");
}
}
if (nn ==0) skip(1);
prout(" 1 2 3 4 5 6 7 8");
prout(" ----------------------------------------");
if (nn==0) prout(" -");
if (coordfixed)
for (j = 8; j >= 1; j--) {
printf("%d -", j);
for (i = 1; i <= 8; i++) {
if (starch[i][j] < 0) // We know only about the bases
printf(" .1.");
else if (starch[i][j] == 0) // Unknown
printf(" ...");
else if (starch[i][j] > 999) // Memorized value
printf("%5d", starch[i][j]-1000);
else
printf("%5d", d.galaxy[i][j]); // What is actually there (happens when value is 1)
}
prout(" -");
}
else
for (i = 1; i <= 8; i++) {
printf("%d -", i);
for (j = 1; j <= 8; j++) {
if (starch[i][j] < 0) // We know only about the bases
printf(" .1.");
else if (starch[i][j] == 0) // Unknown
printf(" ...");
else if (starch[i][j] > 999) // Memorized value
printf("%5d", starch[i][j]-1000);
else
printf("%5d", d.galaxy[i][j]); // What is actually there (happens when value is 1)
}
prout(" -");
}
if (nn == 0) {
skip(1);
crmshp();
proutn(" is currently in");
cramlc(1, quadx, quady);
skip(1);
}
}
void srscan(int l) {
static char requests[][3] =
{"","da","co","po","ls","wa","en","to","sh","kl","ti"};
char *cp;
int leftside=TRUE, rightside=TRUE, i, j, jj, k=0, nn=FALSE;
int goodScan=TRUE;
switch (l) {
case 1: // SRSCAN
if (damage[DSRSENS] != 0) {
/* Allow base's sensors if docked */
if (condit != IHDOCKED) {
prout("SHORT-RANGE SENSORS DAMAGED");
goodScan=FALSE;
}
else
prout("[Using starbase's sensors]");
}
if (goodScan)
starch[quadx][quady] = damage[DRADIO]>0.0 ?
d.galaxy[quadx][quady]+1000:1;
scan();
if (isit("chart")) nn = TRUE;
if (isit("no")) rightside = FALSE;
chew();
prout("\n 1 2 3 4 5 6 7 8 9 10");
break;
case 2: // REQUEST
while (scan() == IHEOL)
printf("Information desired? ");
chew();
for (k = 1; k <= 10; k++)
if (strncmp(citem,requests[k],min(2,strlen(citem)))==0)
break;
if (k > 10) {
prout("UNRECOGNIZED REQUEST. Legal requests are:\n"
" date, condition, position, lsupport, warpfactor,\n"
" energy, torpedoes, shields, klingons, time.");
return;
}
// no "break"
case 3: // STATUS
chew();
leftside = FALSE;
skip(1);
}
for (i = 1; i <= 10; i++) {
int jj = (k!=0 ? k : i);
if (leftside) {
if (coordfixed) {
printf("%2d ", 11-i);
for (j = 1; j <= 10; j++) {
if (goodScan || (abs((11-i)-secty)<= 1 && abs(j-sectx) <= 1))
printf("%c ",quad[j][11-i]);
else
printf("- ");
}
} else {
printf("%2d ", i);
for (j = 1; j <= 10; j++) {
if (goodScan || (abs(i-sectx)<= 1 && abs(j-secty) <= 1))
printf("%c ",quad[i][j]);
else
printf("- ");
}
}
}
if (rightside) {
switch (jj) {
case 1:
printf(" Stardate %.1f", d.date);
break;
case 2:
if (condit != IHDOCKED) newcnd();
switch (condit) {
case IHRED: cp = "RED"; break;
case IHGREEN: cp = "GREEN"; break;
case IHYELLOW: cp = "YELLOW"; break;
case IHDOCKED: cp = "DOCKED"; break;
}
printf(" Condition %s", cp);
#ifdef CLOAKING
if (iscloaked) printf(", CLOAKED");
#endif
break;
case 3:
printf(" Position ");
cramlc(0, quadx, quady);
putchar(',');
cramlc(0, sectx, secty);
break;
case 4:
printf(" Life Support ");
if (damage[DLIFSUP] != 0.0) {
if (condit == IHDOCKED)
printf("DAMAGED, supported by starbase");
else
printf("DAMAGED, reserves=%4.2f", lsupres);
}
else
printf("ACTIVE");
break;
case 5:
printf(" Warp Factor %.1f", warpfac);
break;
case 6:
printf(" Energy %.2f", energy);
break;
case 7:
printf(" Torpedoes %d", torps);
break;
case 8:
printf(" Shields ");
if (damage[DSHIELD] != 0)
printf("DAMAGED,");
else if (shldup)
printf("UP,");
else
printf("DOWN,");
printf(" %d%% %.1f units",
(int)((100.0*shield)/inshld + 0.5), shield);
break;
case 9:
printf(" Klingons Left %d", d.remkl);
break;
case 10:
printf(" Time Left %.2f", d.remtime);
break;
}
}
skip(1);
if (k!=0) return;
}
if (nn) chart(1);
}
void eta(void) {
int key, ix1, ix2, iy1, iy2, prompt=FALSE;
int wfl;
double ttime, twarp, tpower;
if (damage[DCOMPTR] != 0.0) {
prout("COMPUTER DAMAGED, USE A POCKET CALCULATOR.");
skip(1);
return;
}
if (scan() != IHREAL) {
prompt = TRUE;
chew();
proutn("Destination quadrant and/or sector? ");
if (scan()!=IHREAL) {
huh();
return;
}
}
iy1 = aaitem +0.5;
if (scan() != IHREAL) {
huh();
return;
}
ix1 = aaitem + 0.5;
if (scan() == IHREAL) {
iy2 = aaitem + 0.5;
if (scan() != IHREAL) {
huh();
return;
}
ix2 = aaitem + 0.5;
}
else { // same quadrant
ix2 = ix1;
iy2 = iy1;
ix1 = quady; // ya got me why x and y are reversed!
iy1 = quadx;
}
if (ix1 > 8 || ix1 < 1 || iy1 > 8 || iy1 < 1 ||
ix2 > 10 || ix2 < 1 || iy2 > 10 || iy2 < 1) {
huh();
return;
}
dist = sqrt(square(iy1-quadx+0.1*(iy2-sectx))+
square(ix1-quady+0.1*(ix2-secty)));
wfl = FALSE;
if (prompt) prout("Answer \"no\" if you don't know the value:");
while (TRUE) {
chew();
proutn("Time or arrival date? ");
if (scan()==IHREAL) {
ttime = aaitem;
if (ttime > d.date) ttime -= d.date; // Actually a star date
if (ttime <= 1e-10 ||
(twarp=(floor(sqrt((10.0*dist)/ttime)*10.0)+1.0)/10.0) > 10) {
prout("We'll never make it, sir.");
chew();
return;
}
if (twarp < 1.0) twarp = 1.0;
break;
}
chew();
proutn("Warp factor? ");
if (scan()== IHREAL) {
wfl = TRUE;
twarp = aaitem;
if (twarp<1.0 || twarp > 10.0) {
huh();
return;
}
break;
}
prout("Captain, certainly you can give me one of these.");
}
while (TRUE) {
chew();
ttime = (10.0*dist)/square(twarp);
tpower = dist*twarp*twarp*twarp*(shldup+1);
if (tpower >= energy) { // Suggestion from Ethan Staffin -- give amount needed
prout("Insufficient energy, sir: we would need ");
cramf(tpower, 1, 1);
proutn (" units.");
if (shldup==0 || tpower > energy*2.0) {
if (!wfl) return;
proutn("New warp factor to try? ");
if (scan() == IHREAL) {
wfl = TRUE;
twarp = aaitem;
if (twarp<1.0 || twarp > 10.0) {
huh();
return;
}
continue;
}
else {
chew();
skip(1);
return;
}
}
prout("But if you lower your shields,");
proutn("remaining");
tpower /= 2;
}
else
proutn("Remaining");
proutn(" energy will be ");
cramf(energy-tpower, 1, 1);
prout(".");
if (wfl) {
proutn("And we will arrive at stardate ");
cramf(d.date+ttime, 1, 1);
prout(".");
}
else if (twarp==1.0)
prout("Any warp speed is adequate.");
else {
proutn("Minimum warp needed is ");
cramf(twarp, 1, 2);
skip(1);
proutn("and we will arrive at stardate ");
cramf(d.date+ttime, 1, 2);
prout(".");
}
if (d.remtime < ttime)
prout("Unfortunately, the Federation will be destroyed by then.");
if (twarp > 6.0)
prout("You'll be taking risks at that speed, Captain");
if ((isatb==1 && d.isy == ix1 && d.isx == iy1 &&
future[FSCDBAS]< ttime+d.date)||
(future[FCDBAS]<ttime+d.date && baty==ix1 && batx == iy1))
prout("The starbase there will be destroyed by then.");
proutn("New warp factor to try? ");
if (scan() == IHREAL) {
wfl = TRUE;
twarp = aaitem;
if (twarp<1.0 || twarp > 10.0) {
huh();
return;
}
}
else {
chew();
skip(1);
return;
}
}
}

723
setup.c Executable file
View File

@ -0,0 +1,723 @@
#include <time.h>
#include "sst.h"
void prelim(void) {
skip(2);
prout("-SUPER- STAR TREK");
skip(1);
prout("Latest update-21 Sept 78");
skip(1);
}
void freeze(int boss) {
char *x, *y;
FILE *fp;
int key;
if (boss) {
strcpy(citem, "emsave.trk");
}
else {
if ((key = scan()) == IHEOL) {
proutn("File name(9 characters maximum): ");
key = scan();
}
if (key != IHALPHA) {
huh();
return;
}
chew();
if (strchr(citem, '.') == NULL) {
strcat(citem, ".trk");
}
}
if ((fp = fopen(citem, "wb")) == NULL) {
proutn("Can't freeze game as file ");
proutn(citem);
skip(1);
return;
}
fwrite(&d, sizeof(d), 1, fp);
fwrite(&snapsht, sizeof(snapsht), 1, fp);
fwrite(quad, sizeof(quad), 1, fp);
fwrite(kx, sizeof(kx), 1, fp);
fwrite(ky, sizeof(ky), 1, fp);
fwrite(starch, sizeof(starch), 1, fp);
fwrite(kpower, sizeof(kpower), 1, fp);
fwrite(kdist, sizeof(kdist), 1, fp);
fwrite(kavgd, sizeof(kavgd), 1, fp);
fwrite(damage, sizeof(damage), 1, fp);
fwrite(future, sizeof(future), 1, fp);
fwrite(&a, sizeof(a), 1, fp);
fwrite(passwd, sizeof(passwd), 1, fp);
fclose(fp);
/* I hope that's enough! */
}
void thaw(void) {
char *x, *y;
FILE *fp;
int key;
passwd[0] = '\0';
if ((key = scan()) == IHEOL) {
proutn("File name: ");
key = scan();
}
if (key != IHALPHA) {
huh();
return;
}
chew();
if (strchr(citem, '.') == NULL) {
strcat(citem, ".trk");
}
if ((fp = fopen(citem, "rb")) == NULL) {
proutn("Can't find game file ");
proutn(citem);
skip(1);
return;
}
fread(&d, sizeof(d), 1, fp);
fread(&snapsht, sizeof(snapsht), 1, fp);
fread(quad, sizeof(quad), 1, fp);
fread(kx, sizeof(kx), 1, fp);
fread(ky, sizeof(ky), 1, fp);
fread(starch, sizeof(starch), 1, fp);
fread(kpower, sizeof(kpower), 1, fp);
fread(kdist, sizeof(kdist), 1, fp);
fread(kavgd, sizeof(kavgd), 1, fp);
fread(damage, sizeof(damage), 1, fp);
fread(future, sizeof(future), 1, fp);
fread(&a, sizeof(a), 1, fp);
fread(passwd, sizeof(passwd), 1, fp);
fclose(fp);
/* I hope that's enough! */
}
void abandn(void) {
int nb, l;
chew();
if (condit==IHDOCKED) {
if (ship!=IHE) {
prout("You cannot abandon Ye Faerie Queene.");
return;
}
}
else {
/* Must take shuttle craft to exit */
if (damage[DSHUTTL]==-1) {
prout("Ye Faerie Queene has no shuttle craft.");
return;
}
if (damage[DSHUTTL]<0) {
prout("Shuttle craft now serving Big Mac's.");
return;
}
if (damage[DSHUTTL]>0) {
prout("Shuttle craft damaged.");
return;
}
if (landed==1) {
prout("You must be aboard the Enterprise.");
return;
}
if (iscraft!=1) {
prout("Shuttle craft not currently available.");
return;
}
/* Print abandon ship messages */
skip(1);
prouts("***ABANDON SHIP! ABANDON SHIP!");
skip(1);
prouts("***ALL HANDS ABANDON SHIP!");
skip(2);
prout("Captain and crew escape in shuttle craft.");
prout("Remainder of ship's complement beam down");
prout("to nearest habitable planet.");
if (d.rembase==0) {
/* Ops! no place to go... */
finish(FABANDN);
return;
}
/* If at least one base left, give 'em the Faerie Queene */
skip(1);
icrystl = 0; /* crystals are lost */
nprobes = 0; /* No probes */
prout("You are captured by Klingons and released to");
prout("the Federation in a prisoner-of-war exchange.");
nb = Rand()*d.rembase+1;
/* Set up quadrant and position FQ adjacient to base */
if (quadx!=d.baseqx[nb] || quady!=d.baseqy[nb]) {
quadx = d.baseqx[nb];
quady = d.baseqy[nb];
sectx = secty = 5;
newqad(1);
}
for (;;) {
/* position next to base by trial and error */
quad[sectx][secty] = IHDOT;
for (l = 1; l <= 10; l++) {
sectx = 3.0*Rand() - 1.0 + basex;
secty = 3.0*Rand() - 1.0 + basey;
if (sectx >= 1 && sectx <= 10 &&
secty >= 1 && secty <= 10 &&
quad[sectx][secty] == IHDOT) break;
}
if (l < 11) break; /* found a spot */
sectx=5;
secty=5;
newqad(1);
}
}
/* Get new commission */
quad[sectx][secty] = ship = IHF;
prout("Starfleet puts you in command of another ship,");
prout("the Faerie Queene, which is antiquated but,");
prout("still useable.");
if (icrystl!=0) prout("The dilithium crystals have been moved.");
imine=0;
iscraft=0; /* Gallileo disappears */
#ifdef CAPTURE
brigcapacity = 300; // Less capacity now
brigfree = brigcapacity;
#endif
#ifdef CLOAKING
iscloaked = iscloaking = FALSE;
#endif
/* Resupply ship */
condit=IHDOCKED;
for (l = 1; l <= ndevice; l++) damage[l] = 0.0;
damage[DSHUTTL] = -1;
energy = inenrg = 3000.0;
shield = inshld = 1250.0;
torps = intorps = 6;
lsupres=inlsr=3.0;
shldup=0;
warpfac=5.0;
wfacsq=25.0;
return;
}
void setup(void) {
int i,j, krem, klumper;
int ix, iy;
alldone = gamewon = 0;
#ifdef DEBUG
idebug = 0;
#endif
// Decide how many of everything
if (choose()) return; // frozen game
// Prepare the Enterprise
ship = IHE;
energy = inenrg = 5000.0;
shield = inshld = 2500.0;
shldchg = shldup = 0;
inlsr = 4.0;
lsupres = 4.0;
iran8(&quadx, &quady);
iran10(&sectx, &secty);
torps = intorps = 10;
nprobes = (int)(3.0*Rand() + 2.0); /* Give them 2-4 of these wonders */
warpfac = 5.0;
wfacsq = warpfac * warpfac;
for (i=0; i <= ndevice; i++) damage[i] = 0.0;
// Set up assorted game parameters
batx = baty = 0;
d.date = indate = 100.0*(int)(31.0*Rand()+20.0);
d.killk = d.killc = nkinks = nhelp = resting = casual = d.nromkl = 0;
// Added d.starkl=0 6/2015
isatb = iscate = imine = icrystl = icraft = d.nsckill = d.nplankl = d.starkl = 0;
iscraft = 1;
landed = -1;
alive = 1;
docfac = 0.25;
for (i = 1; i <= 8; i++)
for (j = 1; j <= 8; j++) d.newstuf[i][j] = starch[i][j] = 0;
// Initialize times for extraneous events
future[FSNOVA] = d.date + expran(0.5 * intime);
future[FTBEAM] = d.date + expran(1.5 * (intime / d.remcom));
future[FSNAP] = d.date + 1.0 + Rand(); // Force an early snapshot
future[FBATTAK] = d.date + expran(0.3*intime);
future[FCDBAS] = 1e30;
future[FSCMOVE] = d.nscrem ? d.date+0.2777 : 1e30;
future[FSCDBAS] = 1e30;
future[FDSPROB] = 1e30;
// Starchart is functional
stdamtim = 1e30;
// Put stars in the galaxy
instar = 0;
for (i=1; i<=8; i++)
for (j=1; j<=8; j++) {
int k = Rand()*9.0 + 1.0;
instar += k;
d.galaxy[i][j] = k;
}
// Locate star bases in galaxy
for (i = 1; i <= inbase; i++) {
int contflag;
do {
do iran8(&ix, &iy);
while (d.galaxy[ix][iy] >= 10);
contflag = FALSE;
for (j = i-1; j > 0; j--) {
/* Improved placement algorithm to spread out bases */
double distq = square(ix-d.baseqx[j]) + square(iy-d.baseqy[j]);
if (distq < 6.0*(6-inbase) && Rand() < 0.75) {
contflag = TRUE;
#ifdef DEBUG
printf("DEBUG: Abandoning base #%d at %d-%d\n", i, ix, iy);
#endif
break;
}
#ifdef DEBUG
else if (distq < 6.0 * (6-inbase)) {
printf("DEBUG: saving base #%d, close to #%d\n", i, j);
}
#endif
}
} while (contflag);
d.baseqx[i] = ix;
d.baseqy[i] = iy;
starch[ix][iy] = -1;
d.galaxy[ix][iy] += 10;
}
// Position ordinary Klingon Battle Cruisers
krem = inkling - incom - d.nscrem;
klumper = 0.25*skill*(9.0-length)+1.0;
if (klumper > 9) klumper = 9; // Can't have more than 9 in quadrant
do {
double r = Rand();
int klump = (1.0 - r*r)*klumper;
if (klump > krem) klump = krem;
krem -= klump;
klump *= 100;
do iran8(&ix, &iy);
while (d.galaxy[ix][iy] + klump >= 1000);
d.galaxy[ix][iy] += klump;
} while (krem > 0);
// Position Klingon Commander Ships
#ifdef DEBUG
klumper = 1;
#endif
for (i = 1; i <= incom; i++) {
do {
do { /* IF debugging, put commanders by bases, always! */
#ifdef DEBUG
if (idebug && klumper <= inbase) {
ix = d.baseqx[klumper];
iy = d.baseqy[klumper];
klumper++;
}
else
#endif
iran8(&ix, &iy);
}
while ((d.galaxy[ix][iy] < 99 && Rand() < 0.75)||
d.galaxy[ix][iy]>899);
// check for duplicate
for (j = 1; j < i; j++)
if (d.cx[j]==ix && d.cy[j]==iy) break;
} while (j < i);
d.galaxy[ix][iy] += 100;
d.cx[i] = ix;
d.cy[i] = iy;
}
// Locate planets in galaxy
for (i = 1; i <= inplan; i++) {
do iran8(&ix, &iy);
while (d.newstuf[ix][iy] > 0);
d.newstuf[ix][iy] = 1;
d.plnets[i].x = ix;
d.plnets[i].y = iy;
d.plnets[i].pclass = Rand()*3.0 + 1.0; // Planet class M N or O
d.plnets[i].crystals = 1.5*Rand(); // 1 in 3 chance of crystals
d.plnets[i].known = 0;
}
// Locate Romulans
for (i = 1; i <= d.nromrem; i++) {
iran8(&ix, &iy);
d.newstuf[ix][iy] += 10;
}
// Locate the Super Commander
if (d.nscrem > 0) {
do iran8(&ix, &iy);
while (d.galaxy[ix][iy] >= 900);
d.isx = ix;
d.isy = iy;
d.galaxy[ix][iy] += 100;
}
// Place thing (in tournament game, thingx == -1, don't want one!)
if (Rand() < 0.1 && thingx != -1) {
iran8(&thingx, &thingy);
}
else {
thingx = thingy = 0;
}
// idate = date;
skip(3);
d.snap = 0;
if (skill == SNOVICE) {
printf("It is stardate %d. The Federation is being attacked by\n",
(int)d.date);
printf("a deadly Klingon invasion force. As captain of the United\n"
"Starship U.S.S. Enterprise, it is your mission to seek out\n"
"and destroy this invasion force of %d battle cruisers.\n",
inkling);
printf("You have an initial allotment of %d stardates to complete\n"
"your mission. As you proceed you may be given more time.\n\n"
"You will have %d supporting starbases.\n"
"Starbase locations- ",
(int)intime, inbase);
}
else {
printf("Stardate %d.\n\n"
"%d Klingons,\nan unknown number of Romulans\n",
(int)d.date, inkling);
if (d.nscrem) printf("and one (GULP) Super-Commander.\n");
printf("%d stardates\n%d starbases in ",(int)intime, inbase);
}
for (i = 1; i <= inbase; i++) {
cramlc(0, d.baseqx[i], d.baseqy[i]);
if (i < inbase) proutn(" ");
}
skip(2);
proutn("The Enterprise is currently in");
cramlc(1, quadx, quady);
proutn(" ");
cramlc(2, sectx, secty);
skip(2);
prout("Good Luck!");
if (d.nscrem) proutn(" YOU'LL NEED IT.");
skip(1);
newqad(0);
if (nenhere) shldup=1.0;
if (neutz) attack(0); // bad luck to start in a Romulan Neutral Zone
}
int choose(void) {
tourn = 0;
thawed = 0;
skill = 0;
length = 0;
while (TRUE) {
if (fromcommandline) /* Can start with command line options */
fromcommandline = 0;
else
proutn("Would you like a regular, tournament, or frozen game?");
scan();
if (strlen(citem)==0) continue; // Try again
if (isit("tournament")) {
while (scan() == IHEOL) {
proutn("Type in tournament number-");
}
if (aaitem == 0) {
chew();
continue; // We don't want a blank entry
}
tourn = (int)aaitem;
thingx = -1;
srand((unsigned int)(int)aaitem);
break;
}
if (isit("frozen")) {
thaw();
chew();
if (*passwd==0) continue;
randomize();
Rand(); Rand(); Rand(); Rand();
if (!alldone) thawed = 1; // No plaque if not finished
report(1);
return TRUE;
}
if (isit("regular")) {
skip(2);
randomize();
Rand(); Rand(); Rand(); Rand();
break;
}
proutn("What is \"");
proutn(citem);
prout("\"?");
chew();
}
while (length==0 || skill==0) {
if (scan() == IHALPHA) {
if (isit("short")) length = 1;
else if (isit("medium")) length = 2;
else if (isit("long")) length = 4;
else if (isit("novice")) skill = SNOVICE;
else if (isit("fair")) skill = SFAIR;
else if (isit("good")) skill = SGOOD;
else if (isit("expert")) skill = SEXPERT;
else if (isit("emeritus")) skill = SEMERITUS;
else {
proutn("What is \"");
proutn(citem);
prout("\"?");
}
}
else {
chew();
if (length==0) proutn("Would you like a Short, Medium, or Long game? ");
else if (skill == 0) proutn("Are you a Novice, Fair, Good, Expert, or Emeritus player?");
}
}
while (TRUE) {
scan();
strcpy(passwd, citem);
chew();
if (*passwd != 0) break;
proutn("Please type in a secret password (9 characters maximum)-");
}
#ifdef DEBUG
if (strcmp(passwd, "debug")==0) idebug = 1;
#endif
// Use parameters to generate initial values of things
damfac = 0.5 * skill;
d.rembase = 3.0*Rand()+2.0;
inbase = d.rembase;
inplan = (PLNETMAX/2) + (PLNETMAX/2+1)*Rand();
d.nromrem = (2.0+Rand())*skill;
d.nscrem = (skill > SFAIR? 1 : 0);
d.remtime = 7.0 * length;
intime = d.remtime;
d.remkl = 2.0*intime*((skill+1 - 2*Rand())*skill*0.1+.15); // d.remkl and inkling includes commanders and SC
inkling = d.remkl;
incom = skill + 0.0625*inkling*Rand();
d.remcom= min(10, incom);
incom = d.remcom;
d.remres = (inkling+4*incom)*intime;
inresor = d.remres;
if (inkling > 50) {
inbase = (d.rembase += 1);
}
#ifdef CAPTURE
brigcapacity = 400;
brigfree = brigcapacity;
kcaptured = 0; // TAA fix 6/2015
#endif
#ifdef CLOAKING
ncviol = 0; // TAA fix 6/2015
iscloaked = FALSE;
iscloaking = FALSE;
#endif
return FALSE;
}
void dropin(int iquad, int *ix, int *iy) {
do iran10(ix, iy);
while (quad[*ix][*iy] != IHDOT);
quad[*ix][*iy] = iquad;
}
void newcnd(void) {
condit = IHGREEN;
if (energy < 1000.0) condit = IHYELLOW;
if (d.galaxy[quadx][quady] > 99 || d.newstuf[quadx][quady] > 9)
condit = IHRED;
}
void newqad(int shutup) {
int quadnum = d.galaxy[quadx][quady];
int newnum = d.newstuf[quadx][quady];
int i, j, ix, iy, nplan;
iattak = 1;
justin = 1;
basex = basey = 0;
klhere = 0;
comhere = 0;
plnetx = plnety = 0;
ishere = 0;
irhere = 0;
iplnet = 0;
nenhere = 0;
neutz = 0;
inorbit = 0;
landed = -1;
ientesc = 0;
ithere = 0;
iseenit = 0;
#ifdef CLOAKING
isviolreported = FALSE;
#endif
if (iscate) {
// Attempt to escape Super-commander, so tbeam back!
iscate = 0;
ientesc = 1;
}
// Clear quadrant
for (i=1; i <= 10; i++)
for (j=1; j <= 10; j++) quad[i][j] = IHDOT;
// cope with supernova
if (quadnum > 999) {
return;
}
klhere = quadnum/100;
irhere = newnum/10;
nplan = newnum%10;
nenhere = klhere + irhere;
// Position Starship
quad[sectx][secty] = ship;
// Decide if quadrant needs a Tholian
if ((skill < SGOOD && Rand() <= 0.02) || /* Lighten up if skill is low */
(skill == SGOOD && Rand() <= 0.05) ||
(skill > SGOOD && Rand() <= 0.08)
#ifdef DEBUG
|| strcmp(passwd, "tholianx")==0
#endif
) {
do {
ithx = Rand() > 0.5 ? 10 : 1;
ithy = Rand() > 0.5 ? 10 : 1;
} while (quad[ithx][ithy] != IHDOT);
quad[ithx][ithy] = IHT;
ithere = 1;
/* Reserve unocupied corners */
if (quad[1][1]==IHDOT) quad[1][1] = 'X';
if (quad[1][10]==IHDOT) quad[1][10] = 'X';
if (quad[10][1]==IHDOT) quad[10][1] = 'X';
if (quad[10][10]==IHDOT) quad[10][10] = 'X';
}
if (quadnum >= 100) {
// Position ordinary Klingons
quadnum -= 100*klhere;
for (i = 1; i <= klhere; i++) {
dropin(IHK, &ix, &iy);
kx[i] = ix;
ky[i] = iy;
kdist[i] = kavgd[i] = sqrt(square(sectx-ix) + square(secty-iy));
kpower[i] = Rand()*150.0 +300.0 +25.0*skill;
}
// If we need a commander, promote a Klingon
for (i = 1; i <= d.remcom ; i++)
if (d.cx[i]==quadx && d.cy[i]==quady) break;
if (i <= d.remcom) {
quad[ix][iy] = IHC;
kpower[klhere] = 950.0+400.0*Rand()+50.0*skill;
comhere = 1;
}
// If we need a super-commander, promote a Klingon
if (quadx == d.isx && quady == d.isy) {
quad[kx[1]][ky[1]] = IHS;
kpower[1] = 1175.0 + 400.0*Rand() + 125.0*skill;
iscate = 1;
ishere = 1;
}
}
// Put in Romulans if needed
for (i = klhere+1; i <= nenhere; i++) {
dropin(IHR, &ix, &iy);
kx[i] = ix;
ky[i] = iy;
kdist[i] = kavgd[i] = sqrt(square(sectx-ix) + square(secty-iy));
kpower[i] = Rand()*400.0 + 450.0 + 50.0*skill;
}
sortkl();
// If quadrant needs a starbase, put it in
if (quadnum >= 10) {
quadnum -= 10;
dropin(IHB, &basex, &basey);
}
if (nplan) {
// If quadrant needs a planet, put it in
for (i=1; i <= inplan; i++)
if (d.plnets[i].x == quadx && d.plnets[i].y == quady) break;
if (i <= inplan) {
iplnet = i;
dropin(IHP, &plnetx, &plnety);
}
}
// Check for condition
newcnd();
// And finally the stars
for (i = 1; i <= quadnum; i++) dropin(IHSTAR, &ix, &iy);
// Check for RNZ
if (irhere > 0 && klhere == 0 && basex == 0) {
neutz = 1;
if (REPORTS) {
skip(1);
prout("LT. UHURA- \"Captain, an urgent message.");
prout(" I'll put it on audio.\" CLICK");
skip(1);
prout("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE.");
prout("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!");
}
}
if (shutup==0) {
// Put in THING if needed
if (thingx == quadx && thingy == quady) {
dropin(IHQUEST, &ix, &iy);
thingx = thingy = 0; // Transient
if (damage[DSRSENS] == 0.0) {
skip(1);
prout("MR. SPOCK- \"Captain, this is most unusual.");
prout(" Please examine your short-range scan.\"");
}
}
}
// Put in a few black holes
for (i = 1; i <= 3; i++)
if (Rand() > 0.5) dropin(IHBLANK, &ix, &iy);
// Take out X's in corners if Tholian present
if (ithere) {
if (quad[1][1]=='X') quad[1][1] = IHDOT;
if (quad[1][10]=='X') quad[1][10] = IHDOT;
if (quad[10][1]=='X') quad[10][1] = IHDOT;
if (quad[10][10]=='X') quad[10][10] = IHDOT;
}
}
void sortkl(void) {
double t;
int sw, j, k;
// The author liked bubble sort. So we will use it. :-(
if (nenhere < 2) return;
do {
sw = FALSE;
for (j = 1; j < nenhere; j++)
if (kdist[j] > kdist[j+1]) {
sw = TRUE;
t = kdist[j];
kdist[j] = kdist[j+1];
kdist[j+1] = t;
t = kavgd[j];
kavgd[j] = kavgd[j+1];
kavgd[j+1] = t;
k = kx[j];
kx[j] = kx[j+1];
kx[j+1] = k;
k = ky[j];
ky[j] = ky[j+1];
ky[j+1] = k;
t = kpower[j];
kpower[j] = kpower[j+1];
kpower[j+1] = t;
}
} while (sw);
}

784
sst.c Executable file
View File

@ -0,0 +1,784 @@
#define INCLUDED // Define externs here
#include "sst.h"
#include <ctype.h>
#ifdef MSDOS
#include <dos.h>
#endif
#include <time.h>
/*int getch(void);
*/
static char line[128], *linep = line;
static int linecount; /* for paging */
static void clearscreen(void);
/* Compared to original version, I've changed the "help" command to
"call" and the "terminate" command to "quit" to better match
user expectations. The DECUS version apparently made those changes
as well as changing "freeze" to "save". However I like "freeze".
When I got a later version of Super Star Trek that I was converting
from, I added the emexit command.
That later version also mentions srscan and lrscan working when
docked (using the starbase's scanners), so I made some changes here
to do this (and indicating that fact to the player), and then realized
the base would have a subspace radio as well -- doing a Chart when docked
updates the star chart, and all radio reports will be heard. The Dock
command will also give a report if a base is under attack.
Movecom no longer reports movement if sensors are damaged so you wouldn't
otherwise know it.
Also added:
1. Better base positioning at startup
2. deathray improvement (but keeping original failure alternatives)
3. Tholian Web
4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
move in Expert and Emeritus games. This code could use improvement.
5. The deep space probe looks interesting! DECUS version
6. Cloaking (with contributions from Erik Olofsen) and Capturing (BSD version).
*/
// I don't like the way this is done, relying on an index. But I don't
// want to invest the time to make this nice and table driven.
static char *commands[] = {
"srscan",
"lrscan",
"phasers",
"photons",
"move",
"shields",
"dock",
"damages",
"chart",
"impulse",
"rest",
"warp",
"status",
"sensors",
"orbit",
"transport",
"mine",
"crystals",
"shuttle",
"planets",
"request",
"report",
"computer",
"commands",
"emexit",
"probe",
"cloak",
"capture",
"score",
"abandon",
"destruct",
"freeze",
"deathray",
"debug",
"call",
"quit",
"help"
};
#define NUMCOMMANDS (sizeof(commands)/sizeof(char *))
static void listCommands(int x) {
prout(" SRSCAN MOVE PHASERS CALL\n"
" STATUS IMPULSE PHOTONS ABANDON\n"
" LRSCAN WARP SHIELDS DESTRUCT\n"
" CHART REST DOCK QUIT\n"
" DAMAGES REPORT SENSORS ORBIT\n"
" TRANSPORT MINE CRYSTALS SHUTTLE\n"
" PLANETS REQUEST DEATHRAY FREEZE\n"
" COMPUTER EMEXIT PROBE COMMANDS");
proutn(" ");
#ifdef SCORE
proutn("SCORE ");
#endif
#ifdef CLOAKING
proutn("CLOAK ");
#endif
#ifdef CAPTURE
proutn("CAPTURE ");
#endif
if (x) proutn("HELP ");
prout("");
}
static void helpme(void) {
int i, j;
char cmdbuf[32];
char linebuf[132];
FILE *fp;
/* Give help on commands */
int key;
key = scan();
while (TRUE) {
if (key == IHEOL) {
proutn("Help on what command?");
key = scan();
}
if (key == IHEOL) return;
for (i = 0; i < NUMCOMMANDS; i++) {
if (strcmp(commands[i], citem)==0) break;
}
if (i != NUMCOMMANDS) break;
skip(1);
prout("Valid commands:");
listCommands(FALSE);
key = IHEOL;
chew();
skip(1);
}
if (i == 23) {
strcpy(cmdbuf, " ABBREV");
}
else {
strcpy(cmdbuf, " Mnemonic: ");
j = 0;
while ((cmdbuf[j+13] = toupper(commands[i][j])) != 0) j++;
}
fp = fopen("sst.doc", "r");
if (fp == NULL) {
prout("Spock- \"Captain, that information is missing from the");
prout(" computer. You need to find SST.DOC and put it in the");
prout(" current directory.\"");
return;
}
i = strlen(cmdbuf);
do {
if (fgets(linebuf, 132, fp) == NULL) {
prout("Spock- \"Captain, there is no information on that command.\"");
fclose(fp);
return;
}
} while (strncmp(linebuf, cmdbuf, i) != 0);
skip(1);
prout("Spock- \"Captain, I've found the following information:\"");
skip(1);
do {
if (linebuf[0]!=12) { // ignore page break lines
linebuf[strlen(linebuf)-1] = '\0'; // No \n at end
prout(linebuf);
}
fgets(linebuf,132,fp);
} while (strstr(linebuf, "******")==NULL);
fclose(fp);
}
static void makemoves(void) {
int i, hitme;
char ch;
while (TRUE) { /* command loop */
hitme = FALSE;
justin = 0;
Time = 0.0;
i = -1;
while (TRUE) { /* get a command */
chew();
skip(1);
proutn("COMMAND> ");
if (scan() == IHEOL) continue;
for (i=0; i < 29; i++) // Abbreviations allowed for the first 29 commands, only.
if (isit(commands[i]))
break;
if (i < 29) break;
for (; i < NUMCOMMANDS; i++)
if (strcmp(commands[i], citem) == 0) break;
if (i < NUMCOMMANDS
#ifndef CLOAKING
&& i != 26 // ignore the CLOAK command
#endif
#ifndef CAPTURE
&& i != 27 // ignore the CAPTURE command
#endif
#ifndef SCORE
&& i != 28 // ignore the SCORE command
#endif
#ifndef DEBUG
&& i != 33 // ignore the DEBUG command
#endif
) break;
if (skill <= SFAIR) {
prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
listCommands(TRUE);
}
else prout("UNRECOGNIZED COMMAND.");
}
switch (i) { /* command switch */
case 0: // srscan
srscan(1);
break;
case 1: // lrscan
lrscan();
break;
case 2: // phasers
phasers();
if (ididit) {
#ifdef CLOAKING
if (irhere && d.date >= ALGERON && !isviolreported) {
prout("The Romulan ship discovers you are breaking the Treaty of Algeron!");
ncviol++;
isviolreported = TRUE;
}
#endif
hitme = TRUE;
}
break;
case 3: // photons
photon();
if (ididit) {
#ifdef CLOAKING
if (irhere && d.date >= ALGERON && !isviolreported) {
prout("The Romulan ship discovers you are breaking the Treaty of Algeron!");
ncviol++;
isviolreported = TRUE;
}
#endif
hitme = TRUE;
}
break;
case 4: // move
warp(1);
break;
case 5: // shields
sheild(1);
if (ididit) {
attack(2);
shldchg = 0;
}
break;
case 6: // dock
dock();
break;
case 7: // damages
dreprt();
break;
case 8: // chart
chart(0);
break;
case 9: // impulse
impuls();
break;
case 10: // rest
waiting();
if (ididit) hitme = TRUE;
break;
case 11: // warp
setwrp();
break;
case 12: // status
srscan(3);
break;
case 13: // sensors
sensor();
break;
case 14: // orbit
orbit();
if (ididit) hitme = TRUE;
break;
case 15: // transport "beam"
beam();
break;
case 16: // mine
mine();
if (ididit) hitme = TRUE;
break;
case 17: // crystals
usecrystals();
break;
case 18: // shuttle
shuttle();
if (ididit) hitme = TRUE;
break;
case 19: // Planet list
preport();
break;
case 20: // Status information
srscan(2);
break;
case 21: // Game Report
report(0);
break;
case 22: // use COMPUTER!
eta();
break;
case 23:
listCommands(TRUE);
break;
case 24: // Emergency exit
clearscreen(); // Hide screen
freeze(TRUE); // forced save
exit(1); // And quick exit
break;
case 25:
probe(); // Launch probe
break;
#ifdef CLOAKING
case 26:
cloak(); // turn on/off cloaking
if (iscloaking) {
attack(2); // We will be seen while we cloak
iscloaking = FALSE;
iscloaked = TRUE;
}
break;
#endif
#ifdef CAPTURE
case 27:
capture(); // Attempt to get Klingon ship to surrender
if (ididit) hitme = TRUE;
break;
#endif
#ifdef SCORE
case 28:
score(1); // get the score
break;
#endif
case 29: // Abandon Ship
abandn();
break;
case 30: // Self Destruct
dstrct();
break;
case 31: // Save Game
freeze(FALSE);
if (skill > SGOOD)
prout("WARNING--Frozen games produce no plaques!");
break;
case 32: // Try a desparation measure
deathray();
if (ididit) hitme = TRUE;
break;
#ifdef DEBUG
case 33: // What do we want for debug???
debugme();
break;
#endif
case 34: // Call for help
help();
break;
case 35:
alldone = 1; // quit the game
#ifdef DEBUG
if (idebug) score(0);
#endif
break;
case 36:
helpme(); // get help
break;
}
for (;;) {
if (alldone) break; // Game has ended
#ifdef DEBUG
if (idebug) prout("2500");
#endif
if (Time != 0.0) {
events();
if (alldone) break; // Events did us in
}
if (d.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
atover(0);
continue;
}
if (nenhere == 0) movetho();
if (hitme && justin==0) {
attack(2);
if (alldone) break;
if (d.galaxy[quadx][quady] == 1000) { // went NOVA!
atover(0);
hitme = TRUE;
continue;
}
}
break;
}
if (alldone) break;
}
}
int main(int argc, char **argv) {
int i;
int hitme;
char ch;
prelim();
if (argc > 1) { // look for -f option
if (strcmp(argv[1], "-f")== 0) {
coordfixed = 1;
argc--;
argv++;
}
}
if (argc > 1) {
fromcommandline = 1;
line[0] = '\0';
while (--argc > 0) {
strcat(line, *(++argv));
strcat(line, " ");
}
}
else fromcommandline = 0;
while (TRUE) { /* Play a game */
setup();
if (alldone) {
score(0);
alldone = 0;
}
else makemoves();
skip(2);
stars();
skip(1);
if (tourn && alldone) {
printf("Do you want your score recorded?");
if (ja()) {
chew2();
freeze(FALSE);
}
}
printf("Do you want to play again?");
if (!ja()) break;
}
skip(1);
prout("May the Great Bird of the Galaxy roost upon your home planet.");
return 0;
}
void cramen(int i) {
/* return an enemy */
char *s;
switch (i) {
case IHR: s = "Romulan"; break;
case IHK: s = "Klingon"; break;
case IHC: s = "Commander"; break;
case IHS: s = "Super-commander"; break;
case IHSTAR: s = "Star"; break;
case IHP: s = "Planet"; break;
case IHB: s = "Starbase"; break;
case IHBLANK: s = "Black hole"; break;
case IHT: s = "Tholean"; break;
case IHWEB: s = "Tholean web"; break;
default: s = "Unknown??"; break;
}
proutn(s);
}
void cramlc(int key, int x, int y) {
if (key == 1) proutn(" Quadrant");
else if (key == 2) proutn(" Sector");
proutn(" ");
crami(x, 1);
proutn(" - ");
crami(y, 1);
}
void crmena(int i, int enemy, int key, int x, int y) {
if (i == 1) proutn("***");
cramen(enemy);
proutn(" at");
cramlc(key, x, y);
}
void crmshp(void) {
char *s;
switch (ship) {
case IHE: s = "Enterprise"; break;
case IHF: s = "Faerie Queene"; break;
default: s = "Ship???"; break;
}
proutn(s);
}
void stars(void) {
prouts("******************************************************");
skip(1);
}
double expran(double avrage) {
return -avrage*log(1e-7 + Rand());
}
double Rand(void) {
return rand()/(1.0 + (double)RAND_MAX);
}
void iran8(int *i, int *j) {
*i = Rand()*8.0 + 1.0;
*j = Rand()*8.0 + 1.0;
}
void iran10(int *i, int *j) {
*i = Rand()*10.0 + 1.0;
*j = Rand()*10.0 + 1.0;
}
void chew(void) {
linecount = 0;
linep = line;
*linep = 0;
}
void chew2(void) {
/* return IHEOL next time */
linecount = 0;
linep = line+1;
*linep = 0;
}
int scan(void) {
int i;
char *cp;
linecount = 0;
// Init result
aaitem = 0.0;
*citem = 0;
// Read a line if nothing here
if (*linep == 0) {
if (linep != line) {
chew();
return IHEOL;
}
// gets(line);
// We should really be using fgets
fgets(line,sizeof(line),stdin);
if (line[strlen(line)-1] == '\n')
line[strlen(line)-1] = '\0';
linep = line;
}
// Skip leading white space
while (*linep == ' ') linep++;
// Nothing left
if (*linep == 0) {
chew();
return IHEOL;
}
if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
// treat as a number
if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
linep = line; // Invalid numbers are ignored
*linep = 0;
return IHEOL;
}
else {
// skip to end
linep += i;
return IHREAL;
}
}
// Treat as alpha
cp = citem;
while (*linep && *linep!=' ') {
if ((cp - citem) < 9) *cp++ = tolower(*linep);
linep++;
}
*cp = 0;
return IHALPHA;
}
int ja(void) {
chew();
while (TRUE) {
scan();
chew();
if (*citem == 'y') return TRUE;
if (*citem == 'n') return FALSE;
proutn("Please answer with \"Y\" or \"N\":");
}
}
void cramf(double x, int w, int d) {
char buf[64];
sprintf(buf, "%*.*f", w, d, x);
proutn(buf);
}
void crami(int i, int w) {
char buf[16];
sprintf(buf, "%*d", w, i);
proutn(buf);
}
double square(double i) { return i*i; }
static void clearscreen(void) {
/* Somehow we need to clear the screen */
proutn("\033[2J\033[0;0H"); /* Hope for an ANSI display */
}
/* We will pull these out in case we want to do something special later */
void pause(int i) {
#ifdef CLOAKING
if (iscloaked) return;
#endif
putchar('\n');
if (i==1) {
if (skill > SFAIR)
prout("[ANNOUNCEMENT ARRIVING...]");
else
prout("[IMPORTANT ANNOUNCEMENT ARRIVING -- HIT SPACE BAR TO CONTINUE]");
getch();
}
else {
if (skill > SFAIR)
proutn("[CONTINUE?]");
else
proutn("[HIT SPACE BAR TO CONTINUE]");
getch();
proutn("\r \r");
}
if (i != 0) {
clearscreen();
}
linecount = 0;
}
void skip(int i) {
while (i-- > 0) {
linecount++;
if (linecount >= 23)
pause(0);
else
putchar('\n');
}
}
void proutn(char *s) {
fputs(s, stdout);
}
void prout(char *s) {
proutn(s);
skip(1);
}
void prouts(char *s) {
clock_t endTime;
/* print slowly! */
while (*s) {
endTime = clock() + CLOCKS_PER_SEC*0.05;
while (clock() < endTime) ;
putchar(*s++);
fflush(stdout);
}
}
void huh(void) {
chew();
skip(1);
prout("Beg your pardon, Captain?");
}
int isit(char *s) {
/* New function -- compares s to scaned citem and returns true if it
matches to the length of s */
return strncmp(s, citem, max(1, strlen(citem))) == 0;
}
#ifdef DEBUG
void debugme(void) {
proutn("Reset levels? ");
if (ja() != 0) {
if (energy < inenrg) energy = inenrg;
shield = inshld;
torps = intorps;
lsupres = inlsr;
}
proutn("Reset damage? ");
if (ja() != 0) {
int i;
for (i=0; i <= ndevice; i++) if (damage[i] > 0.0) damage[i] = 0.0;
stdamtim = 1e30;
}
proutn("Toggle idebug? ");
if (ja() != 0) {
idebug = !idebug;
if (idebug) prout("Debug output ON");
else prout("Debug output OFF");
}
proutn("Cause selective damage? ");
if (ja() != 0) {
int i, key;
for (i=1; i <= ndevice; i++) {
proutn("Kill ");
proutn(device[i]);
proutn("? ");
chew();
key = scan();
if (key == IHALPHA && isit("y")) {
damage[i] = 10.0;
if (i == DRADIO) stdamtim = d.date;
}
}
}
proutn("Examine/change events? ");
if (ja() != 0) {
int i;
for (i = 1; i < NEVENTS; i++) {
int key;
if (future[i] == 1e30) continue;
switch (i) {
case FSNOVA: proutn("Supernova "); break;
case FTBEAM: proutn("T Beam "); break;
case FSNAP: proutn("Snapshot "); break;
case FBATTAK: proutn("Base Attack "); break;
case FCDBAS: proutn("Base Destroy "); break;
case FSCMOVE: proutn("SC Move "); break;
case FSCDBAS: proutn("SC Base Destroy "); break;
}
cramf(future[i]-d.date, 8, 2);
chew();
proutn(" ?");
key = scan();
if (key == IHREAL) {
future[i] = d.date + aaitem;
}
}
chew();
}
proutn("Make universe visible? ");
if (ja() != 0) {
int i, j;
for (i = 1; i < 9; i++)
{
for (j = 1; j < 9; j++)
{
starch[i][j] = 1;
}
}
}
}
#endif

1591
sst.doc Executable file

File diff suppressed because it is too large Load Diff

492
sst.h Executable file
View File

@ -0,0 +1,492 @@
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#ifndef INCLUDED
#define EXTERN extern
#else
#define EXTERN
#endif
// #define DEBUG
// #define SCORE
// #define CLOAKING
// #define CAPTURE
#ifdef CLOAKING
#define ndevice (16)
#else
#define ndevice (15) // Number of devices
#endif
#define phasefac (2.0)
#define PLNETMAX (10)
#define NEVENTS (8)
typedef struct {
int x; /* Quadrant location of planet */
int y;
int pclass; /* class M, N, or O (1, 2, or 3) */
int crystals; /* has crystals */
int known; /* =1 contents known, =2 shuttle on this planet */
} PLANETS;
EXTERN struct foo {
int snap, // snapshot taken
remkl, // remaining klingons
remcom, // remaining commanders
rembase, // remaining bases
starkl, // destroyed stars
basekl, // destroyed bases
killk, // Klingons killed
killc, // commanders killed
galaxy[9][9], // The Galaxy (subscript 0 not used)
cx[11],cy[11], // Commander quadrant coordinates
baseqx[6], // Base quadrant X
baseqy[6], // Base quadrant Y
newstuf[9][9], // Extended galaxy goodies
isx, isy, // Coordinate of Super Commander
nscrem, // remaining super commanders
nromkl, // Romulans killed
nromrem, // Romulans remaining
nsckill, // super commanders killed
nplankl; // destroyed planets
PLANETS plnets[PLNETMAX+1]; // Planet information
#ifdef CAPTURE
int kcaptured, brigfree;
#endif
double date, // stardate
remres, // remaining resources
remtime; // remaining time
} d, snapsht; // Data that is snapshot
EXTERN char
quad[11][11]; // contents of our quadrant
// Scalar variables that are needed for freezing the game
// are placed in a structure. #defines are used to access by their
// original names. Gee, I could have done this with the d structure,
// but I just didn't think of it back when I started.
EXTERN struct foo2 {
int inkling,
inbase,
incom,
instar,
intorps,
condit,
torps,
ship,
quadx,
quady,
sectx,
secty,
length,
skill,
basex,
basey,
klhere,
comhere,
casual,
nhelp,
nkinks,
ididit,
gamewon,
alive,
justin,
alldone,
shldchg,
thingx,
thingy,
plnetx,
plnety,
inorbit,
landed,
iplnet,
imine,
inplan,
nenhere,
ishere,
neutz,
irhere,
icraft,
ientesc,
iscraft,
isatb,
iscate,
#ifdef DEBUG
idebug,
#endif
#ifdef CLOAKING
iscloaked,
iscloaking,
ncviol,
isviolreported,
#endif
#ifdef CAPTURE
brigcapacity,
#endif
iattak,
icrystl,
tourn,
thawed,
batx,
baty,
ithere,
ithx,
ithy,
iseenit,
probecx,
probecy,
proben,
isarmed,
nprobes;
double inresor,
intime,
inenrg,
inshld,
inlsr,
indate,
energy,
shield,
shldup,
warpfac,
wfacsq,
lsupres,
dist,
direc,
Time,
docfac,
resting,
damfac,
stdamtim,
cryprob,
probex,
probey,
probeinx,
probeiny;
} a;
#define inkling a.inkling // Initial number of klingons
#define inbase a.inbase // Initial number of bases
#define incom a.incom // Initian number of commanders
#define instar a.instar // Initial stars
#define intorps a.intorps // Initial/Max torpedoes
#define condit a.condit // Condition (red, yellow, green docked)
#define torps a.torps // number of torpedoes
#define ship a.ship // Ship type -- 'E' is Enterprise
#define quadx a.quadx // where we are
#define quady a.quady //
#define sectx a.sectx // where we are
#define secty a.secty //
#define length a.length // length of game
#define skill a.skill // skill level
#define basex a.basex // position of base in current quad
#define basey a.basey //
#define klhere a.klhere // klingons here
#define comhere a.comhere // commanders here
#define casual a.casual // causalties
#define nhelp a.nhelp // calls for help
#define nkinks a.nkinks //
#define ididit a.ididit // Action taken -- allows enemy to attack
#define gamewon a.gamewon // Finished!
#define alive a.alive // We are alive (not killed)
#define justin a.justin // just entered quadrant
#define alldone a.alldone // game is now finished
#define shldchg a.shldchg // shield is changing (affects efficiency)
#define thingx a.thingx // location of strange object in galaxy
#define thingy a.thingy //
#define plnetx a.plnetx // location of planet in quadrant
#define plnety a.plnety //
#define inorbit a.inorbit // orbiting
#define landed a.landed // party on planet (1), on ship (-1)
#define iplnet a.iplnet // planet # in quadrant
#define imine a.imine // mining
#define inplan a.inplan // initial planets
#define nenhere a.nenhere // Number of enemies in quadrant
#define ishere a.ishere // Super-commander in quandrant
#define neutz a.neutz // Romulan Neutral Zone
#define irhere a.irhere // Romulans in quadrant
#define icraft a.icraft // Kirk in Galileo
#define ientesc a.ientesc // Attempted escape from supercommander
#define iscraft a.iscraft // =1 if craft on ship, -1 if removed from game
#define isatb a.isatb // =1 if SuperCommander is attacking base
#define iscate a.iscate // Super Commander is here
#ifdef DEBUG
#define idebug a.idebug // Debug mode
#endif
#ifdef CLOAKING
#define iscloaked a.iscloaked // Cloaking is enabled
#define iscloaking a.iscloaking // However if iscloaking is TRUE then in process of cloaking and can be attacked
#define ncviol a.ncviol // Treaty violations
#define isviolreported a.isviolreported // Violation reported by Romulan in quadrant
#endif
#ifdef CAPTURE
#define kcaptured d.kcaptured // number of captured Klingons
#define brigfree d.brigfree // room in the brig
#define brigcapacity a.brigcapacity // How many Klingons the brig will hold
#endif
#define iattak a.iattak // attack recursion elimination (was cracks[4])
#define icrystl a.icrystl // dilithium crystals aboard
#define tourn a.tourn // Tournament number
#define thawed a.thawed // Thawed game
#define batx a.batx // Base coordinates being attacked
#define baty a.baty //
#define ithere a.ithere // Tholean is here
#define ithx a.ithx // coordinates of tholean
#define ithy a.ithy
#define iseenit a.iseenit // Seen base attack report
#define inresor a.inresor // initial resources
#define intime a.intime // initial time
#define inenrg a.inenrg // Initial/Max Energy
#define inshld a.inshld // Initial/Max Shield
#define inlsr a.inlsr // initial life support resources
#define indate a.indate // Initial date
#define energy a.energy // Energy level
#define shield a.shield // Shield level
#define shldup a.shldup // Shields are up
#define warpfac a.warpfac // Warp speed
#define wfacsq a.wfacsq // squared warp factor
#define lsupres a.lsupres // life support reserves
#define dist a.dist // movement distance
#define direc a.direc // movement direction
#define Time a.Time // time taken by current operation
#define docfac a.docfac // repair factor when docking (constant?)
#define resting a.resting // rest time
#define damfac a.damfac // damage factor
#define stdamtim a.stdamtim // time that star chart was damaged
#define cryprob a.cryprob // probability that crystal will work
#define probex a.probex // location of probe
#define probey a.probey
#define probecx a.probecx // current probe quadrant
#define probecy a.probecy
#define probeinx a.probeinx // Probe x,y increment
#define probeiny a.probeiny
#define proben a.proben // number of moves for probe
#define isarmed a.isarmed // Probe is armed
#define nprobes a.nprobes // number of probes available
EXTERN int
kx[21], // enemy sector locations
ky[21],
starch[9][9]; // star chart
EXTERN int fromcommandline; // Game start from command line options
EXTERN int coordfixed; // Fix those dumb coordinates.
EXTERN char passwd[10], // Self Destruct password
*device[ndevice+1];
EXTERN PLANETS nulplanet; // zeroed planet structure
EXTERN double
kpower[21], // enemy energy levels
kdist[21], // enemy distances
kavgd[21], // average distances
damage[ndevice+1], // damage encountered
future[NEVENTS+1]; // future events
EXTERN int iscore, iskill; // Common PLAQ
EXTERN double perdate;
typedef enum {FWON, FDEPLETE, FLIFESUP, FNRG, FBATTLE,
FNEG3, FNOVA, FSNOVAED, FABANDN, FDILITHIUM,
FMATERIALIZE, FPHASER, FLOST, FMINING, FDPLANET,
FPNOVA, FSSC, FSTRACTOR, FDRAY, FTRIBBLE,
FHOLE
#ifdef CLOAKING
, FCLOAK
#endif
} FINTYPE ;
/* Skill levels */
typedef enum {SNOVICE=1, SFAIR, SGOOD, SEXPERT, SEMERITUS} SKILLTYPE;
EXTERN double aaitem;
EXTERN char citem[24];
/* Define devices */
#define DSRSENS 1
#define DLRSENS 2
#define DPHASER 3
#define DPHOTON 4
#define DLIFSUP 5
#define DWARPEN 6
#define DIMPULS 7
#define DSHIELD 8
#define DRADIO 9
#define DSHUTTL 10
#define DCOMPTR 11
#define DTRANSP 12
#define DSHCTRL 13
#define DDRAY 14 // Added deathray
#define DDSP 15 // Added deep space probe
#define DCLOAK 16 // Added cloaking device
/* Define future events */
#define FSPY 0 // Spy event happens always (no future[] entry)
// can cause SC to tractor beam Enterprise
#define FSNOVA 1 // Supernova
#define FTBEAM 2 // Commander tractor beams Enterprise
#define FSNAP 3 // Snapshot for time warp
#define FBATTAK 4 // Commander attacks base
#define FCDBAS 5 // Commander destroys base
#define FSCMOVE 6 // Supercommander moves (might attack base)
#define FSCDBAS 7 // Supercommander destroys base
#define FDSPROB 8 // Move deep space probe
#ifdef INCLUDED
PLANETS nulplanet = {0};
char *device[ndevice+1] = {
"",
"S. R. Sensors",
"L. R. Sensors",
"Phasers",
"Photon Tubes",
"Life Support",
"Warp Engines",
"Impulse Engines",
"Shields",
"Subspace Radio",
"Shuttle Craft",
"Computer",
"Transporter",
"Shield Control",
"Death Ray",
"D. S. Probe"
#ifdef CLOAKING
,"Cloaking Device"
#endif
};
#endif
#define ALGERON (2311) /* Date of the Treaty of Algeron */
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#define IHR 'R'
#define IHK 'K'
#define IHC 'C'
#define IHS 'S'
#define IHSTAR '*'
#define IHP 'P'
#define IHB 'B'
#define IHBLANK ' '
#define IHDOT '.'
#define IHQUEST '?'
#define IHE 'E'
#define IHF 'F'
#define IHT 'T'
#define IHWEB '#'
#define IHGREEN 'G'
#define IHYELLOW 'Y'
#define IHRED 'R'
#define IHDOCKED 'D'
/* Function prototypes */
void prelim(void);
void attack(int);
int choose(void);
void setup(void);
void score(int);
void atover(int);
void srscan(int);
void lrscan(void);
void phasers(void);
void photon(void);
void warp(int);
void sheild(int);
void dock(void);
void dreprt(void);
void chart(int);
void impuls(void);
void waiting(void);
void setwrp(void);
void events(void);
void report(int);
void eta(void);
void help(void);
void abandn(void);
void finish(FINTYPE);
void dstrct(void);
void kaboom(void);
void freeze(int);
void thaw(void);
void plaque(void);
int scan(void);
#define IHEOL (0)
#define IHALPHA (1)
#define IHREAL (2)
void chew(void);
void chew2(void);
void skip(int);
void prout(char *s);
void proutn(char *s);
void stars(void);
void newqad(int);
int ja(void);
void cramen(int);
void crmshp(void);
void cramlc(int, int, int);
double expran(double);
double Rand(void);
void iran8(int *, int *);
void iran10(int *, int *);
double square(double);
void dropin(int, int*, int*);
void newcnd(void);
void sortkl(void);
void lmove(void);
void ram(int, int, int, int);
void crmena(int, int, int, int, int);
void deadkl(int, int, int, int, int);
void timwrp(void);
void movcom(void);
void torpedo(double, double, int, int, double *);
void cramf(double, int, int);
void crami(int, int);
void huh(void);
void pause(int);
void nova(int, int);
void snova(int, int);
void scom(int *);
void hittem(double *);
void prouts(char *);
int isit(char *);
void preport(void);
void orbit(void);
void sensor(void);
void beam(void);
void mine(void);
void usecrystals(void);
void shuttle(void);
void deathray(void);
void debugme(void);
void attakreport(void);
void movetho(void);
void probe(void);
int min(int, int);
int max(int, int);
void randomize(void);
int getch(void);
#ifdef CLOAKING
void cloak(void);
#endif
#ifdef CAPTURE
void capture(void);
#endif
#ifdef CLOAKING
#define REPORTS ((condit==IHDOCKED || damage[DRADIO]<=0.0) && !iscloaked)
#else
#define REPORTS (condit==IHDOCKED || damage[DRADIO]<=0.0)
#endif