From b0629033955fcfdcd93a4a2cf3ab29e8adc56200 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sun, 31 Oct 2004 14:49:26 +0000 Subject: [PATCH] Initial commit of Tom Almy's version plus sst.doc. --- MAKEFILE.DOS | 14 + MAKEFILE.OS2 | 17 + ai.c | 610 ++++++++++++++++++++ battle.c | 1214 +++++++++++++++++++++++++++++++++++++++ events.c | 767 +++++++++++++++++++++++++ finish.c | 447 +++++++++++++++ linux.c | 31 + makefile | 15 + moving.c | 966 +++++++++++++++++++++++++++++++ os2.c | 31 + planets.c | 504 +++++++++++++++++ reports.c | 495 ++++++++++++++++ setup.c | 701 +++++++++++++++++++++++ sst.c | 692 +++++++++++++++++++++++ sst.doc | 1527 ++++++++++++++++++++++++++++++++++++++++++++++++++ sst.h | 426 ++++++++++++++ 16 files changed, 8457 insertions(+) create mode 100644 MAKEFILE.DOS create mode 100644 MAKEFILE.OS2 create mode 100644 ai.c create mode 100644 battle.c create mode 100644 events.c create mode 100644 finish.c create mode 100644 linux.c create mode 100644 makefile create mode 100644 moving.c create mode 100644 os2.c create mode 100644 planets.c create mode 100644 reports.c create mode 100644 setup.c create mode 100644 sst.c create mode 100644 sst.doc create mode 100644 sst.h diff --git a/MAKEFILE.DOS b/MAKEFILE.DOS new file mode 100644 index 0000000..e7e4821 --- /dev/null +++ b/MAKEFILE.DOS @@ -0,0 +1,14 @@ +MODEL=m +CFLAGS=-f87 -2 -m$(MODEL) + +.c.obj:; bcc $(CFLAGS) -c $*.c + +OBJS= sst.obj setup.obj reports.obj finish.obj moving.obj\ + battle.obj events.obj ai.obj planets.obj + +sst.exe: $(OBJS) sst.lnk + bcc @sst.lnk + + +sst.lnk: makefile + >sst.lnk $(CFLAGS) -M $(OBJS) noeh$(MODEL).lib \ No newline at end of file diff --git a/MAKEFILE.OS2 b/MAKEFILE.OS2 new file mode 100644 index 0000000..59f7dbb --- /dev/null +++ b/MAKEFILE.OS2 @@ -0,0 +1,17 @@ +CFLAGS= -O + +.SUFFIXES: .o .c .s .exe + +.c.o: + $(CC) $(CFLAGS) -c $< + +OFILES= sst.o finish.o reports.o setup.o os2.o moving.o battle.o events.o ai.o planets.o + +HFILES= sst.h + +sstos2.exe: $(OFILES) + gcc -o sstos2.exe $(OFILES) + + +$(OFILES): $(HFILES) + diff --git a/ai.c b/ai.c new file mode 100644 index 0000000..de54e7b --- /dev/null +++ b/ai.c @@ -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 > 3 ? + (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 > 3) 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 (damage[DRADIO] == 0.0 || condit == IHDOCKED) { + 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 (damage[DRADIO] > 0 && condit != IHDOCKED) + 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 || + (damage[DRADIO] > 0.0 && condit != IHDOCKED) || + 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; +} diff --git a/battle.c b/battle.c new file mode 100644 index 0000000..e9cc2f6 --- /dev/null +++ b/battle.c @@ -0,0 +1,1214 @@ +#include "sst.h" + +void sheild(int i) { + int key; + enum {NONE, SHUP, SHDN, NRG} action = NONE; + + ididit = 0; + + if (i == 2) action = SHUP; + else { + key = scan(); + if (key == IHALPHA) { + if (isit("transfer")) + action = NRG; + else { + chew(); + if (damage[DSHIELD]) { + prout("Shields damaged and down."); + return; + } + if (isit("up")) + action = SHUP; + else if (isit("down")) + action = SHDN; + } + } + if (action==NONE) { + proutn("Do you wish to change shield energy? "); + if (ja()) { + proutn("Energy to transfer to shields- "); + action = NRG; + } + else if (damage[DSHIELD]) { + prout("Shields damaged and down."); + return; + } + else if (shldup) { + proutn("Shields are up. Do you want them down? "); + if (ja()) action = SHDN; + else { + chew(); + return; + } + } + else { + proutn("Shields are down. Do you want them up? "); + if (ja()) action = SHUP; + else { + chew(); + return; + } + } + } + } + switch (action) { + case SHUP: /* raise shields */ + if (shldup) { + prout("Shields already up."); + return; + } + shldup = 1; + shldchg = 1; + if (condit != IHDOCKED) energy -= 50.0; + prout("Shields raised."); + if (energy <= 0) { + skip(1); + prout("Shields raising uses up last of energy."); + finish(FNRG); + return; + } + ididit=1; + return; + case SHDN: + if (shldup==0) { + prout("Shields already down."); + return; + } + shldup=0; + shldchg=1; + prout("Shields lowered."); + ididit=1; + return; + case NRG: + while (scan() != IHREAL) { + chew(); + proutn("Energy to transfer to shields- "); + } + chew(); + if (aaitem==0) return; + if (aaitem > energy) { + prout("Insufficient ship energy."); + return; + } + ididit = 1; + if (shield+aaitem >= inshld) { + prout("Shield energy maximized."); + if (shield+aaitem > inshld) { + prout("Excess energy requested returned to ship energy"); + } + energy -= inshld-shield; + shield = inshld; + return; + } + if (aaitem < 0.0 && energy-aaitem > inenrg) { + /* Prevent shield drain loophole */ + skip(1); + prout("Engineering to bridge--"); + prout(" Scott here. Power circuit problem, Captain."); + prout(" I can't drain the shields."); + ididit = 0; + return; + } + if (shield+aaitem < 0) { + prout("All shield energy transferred to ship."); + energy += shield; + shield = 0.0; + return; + } + proutn("Scotty- \""); + if (aaitem > 0) + prout("Transferring energy to shields.\""); + else + prout("Draining energy from shields.\""); + shield += aaitem; + energy -= aaitem; + return; + } +} + +void ram(int ibumpd, int ienm, int ix, int iy) { + double type = 1.0, extradm; + int icas, l; + + prouts("***RED ALERT! RED ALERT!"); + skip(1); + prout("***COLLISION IMMINENT."); + skip(2); + proutn("***"); + crmshp(); + switch (ienm) { + case IHR: type = 1.5; break; + case IHC: type = 2.0; break; + case IHS: type = 2.5; break; + case IHT: type = 0.5; break; + } + proutn(ibumpd ? " rammed by " : " rams "); + crmena(0, ienm, 2, ix, iy); + if (ibumpd) proutn(" (original position)"); + skip(1); + deadkl(ix, iy, ienm, sectx, secty); + proutn("***"); + crmshp(); + prout(" heavily damaged."); + icas = 10.0+20.0*Rand(); + proutn("***Sickbay reports "); + crami(icas, 1); + prout(" casualties."); + casual += icas; + for (l=1; l <= ndevice; l++) { + if (l == DDRAY) continue; // Don't damage deathray + if (damage[l] < 0) continue; + extradm = (10.0*type*Rand()+1.0)*damfac; + damage[l] += Time + extradm; /* Damage for at least time of travel! */ + } + shldup = 0; + if (d.remkl) { + pause(2); + dreprt(); + } + else finish(FWON); + return; +} + +void torpedo(double course, double r, int inx, int iny, double *hit) { + int l, iquad, ix, iy, jx, jy, shoved=0, ll; + double ac=course + 0.25*r; + double angle = (15.0-ac)*0.5235988; + double bullseye = (15.0 - course)*0.5235988; + double deltax=-sin(angle), deltay=cos(angle), x=inx, y=iny, bigger; + double ang, temp, xx, yy, kp, h1; + + bigger = fabs(deltax); + if (fabs(deltay) > bigger) bigger = fabs(deltay); + deltax /= bigger; + deltay /= bigger; + + /* Loop to move a single torpedo */ + for (l=1; l <= 15; l++) { + x += deltax; + ix = x + 0.5; + if (ix < 1 || ix > 10) break; + y += deltay; + iy = y + 0.5; + if (iy < 1 || iy > 10) break; + if (l==4 || l==9) skip(1); + cramf(x, 0, 1); + proutn(" - "); + cramf(y, 0, 1); + proutn(" "); + iquad=quad[ix][iy]; + if (iquad==IHDOT) continue; + /* hit something */ + skip(1); + switch(iquad) { + case IHE: /* Hit our ship */ + case IHF: + skip(1); + proutn("Torpedo hits "); + crmshp(); + prout("."); + *hit = 700.0 + 100.0*Rand() - + 1000.0*sqrt(square(ix-inx)+square(iy-iny))* + fabs(sin(bullseye-angle)); + *hit = fabs(*hit); + newcnd(); /* undock */ + /* We may be displaced. */ + if (landed==1) return; /* Cheat if on a planet */ + ang = angle + 2.5*(Rand()-0.5); + temp = fabs(sin(ang)); + if (fabs(cos(ang)) > temp) temp = fabs(cos(ang)); + xx = -sin(ang)/temp; + yy = cos(ang)/temp; + jx=ix+xx+0.5; + jy=iy+yy+0.5; + if (jx<1 || jx>10 || jy<1 ||jy > 10) return; + if (quad[jx][jy]==IHBLANK) { + finish(FHOLE); + return; + } + if (quad[jx][jy]!=IHDOT) { + /* can't move into object */ + return; + } + sectx = jx; + secty = jy; + crmshp(); + shoved = 1; + break; + + case IHC: /* Hit a commander */ + case IHS: + if (Rand() <= 0.05) { + crmena(1, iquad, 2, ix, iy); + prout(" uses anti-photon device;"); + prout(" torpedo neutralized."); + return; + } + case IHR: /* Hit a regular enemy */ + case IHK: + /* find the enemy */ + for (ll=1; ll <= nenhere; ll++) + if (ix==kx[ll] && iy==ky[ll]) break; + kp = fabs(kpower[ll]); + h1 = 700.0 + 100.0*Rand() - + 1000.0*sqrt(square(ix-inx)+square(iy-iny))* + fabs(sin(bullseye-angle)); + h1 = fabs(h1); + if (kp < h1) h1 = kp; + kpower[ll] -= (kpower[ll]<0 ? -h1 : h1); + if (kpower[ll] == 0) { + deadkl(ix, iy, iquad, ix, iy); + return; + } + crmena(1, iquad, 2, ix, iy); + /* If enemy damaged but not destroyed, try to displace */ + ang = angle + 2.5*(Rand()-0.5); + temp = fabs(sin(ang)); + if (fabs(cos(ang)) > temp) temp = fabs(cos(ang)); + xx = -sin(ang)/temp; + yy = cos(ang)/temp; + jx=ix+xx+0.5; + jy=iy+yy+0.5; + if (jx<1 || jx>10 || jy<1 ||jy > 10) { + prout(" damaged but not destroyed."); + return; + } + if (quad[jx][jy]==IHBLANK) { + prout(" buffeted into black hole."); + deadkl(ix, iy, iquad, jx, jy); + return; + } + if (quad[jx][jy]!=IHDOT) { + /* can't move into object */ + prout(" damaged but not destroyed."); + return; + } + prout(" damaged--"); + kx[ll] = jx; + ky[ll] = jy; + shoved = 1; + break; + case IHB: /* Hit a base */ + prout("***STARBASE DESTROYED.."); + if (starch[quadx][quady] < 0) starch[quadx][quady] = 0; + for (ll=1; ll<=d.rembase; ll++) { + if (d.baseqx[ll]==quadx && d.baseqy[ll]==quady) { + d.baseqx[ll]=d.baseqx[d.rembase]; + d.baseqy[ll]=d.baseqy[d.rembase]; + break; + } + } + quad[ix][iy]=IHDOT; + d.rembase--; + basex=basey=0; + d.galaxy[quadx][quady] -= 10; + d.basekl++; + newcnd(); + return; + case IHP: /* Hit a planet */ + crmena(1, iquad, 2, ix, iy); + prout(" destroyed."); + d.nplankl++; + d.newstuf[quadx][quady] -= 1; + d.plnets[iplnet] = nulplanet; + iplnet = 0; + plnetx = plnety = 0; + quad[ix][iy] = IHDOT; + if (landed==1) { + /* captain parishes on planet */ + finish(FDPLANET); + } + return; + case IHSTAR: /* Hit a star */ + if (Rand() > 0.10) { + nova(ix, iy); + return; + } + crmena(1, IHSTAR, 2, ix, iy); + prout(" unaffected by photon blast."); + return; + case IHQUEST: /* Hit a thingy */ + skip(1); + prouts("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"); + skip(1); + prouts(" HACK! HACK! HACK! *CHOKE!* "); + skip(1); + proutn("Mr. Spock-"); + prouts(" \"Facinating!\""); + skip(1); + quad[ix][iy] = IHDOT; + return; + case IHBLANK: /* Black hole */ + skip(1); + crmena(1, IHBLANK, 2, ix, iy); + prout(" swallows torpedo."); + return; + case IHWEB: /* hit the web */ + skip(1); + prout("***Torpedo absorbed by Tholian web."); + return; + case IHT: /* Hit a Tholian */ + skip(1); + crmena(1, IHT, 2, ix, iy); + h1 = 700.0 + 100.0*Rand() - + 1000.0*sqrt(square(ix-inx)+square(iy-iny))* + fabs(sin(bullseye-angle)); + h1 = fabs(h1); + if (h1 >= 600) { + prout(" destroyed."); + quad[ix][iy] = IHDOT; + ithere = 0; + ithx = ithy = 0; + return; + } + if (Rand() > 0.05) { + prout(" survives photon blast."); + return; + } + prout(" disappears."); + quad[ix][iy] = IHWEB; + ithere = ithx = ithy = 0; + { + int dum, my; + dropin(IHBLANK, &dum, &my); + } + return; + + default: /* Problem! */ + skip(1); + proutn("Don't know how to handle collision with "); + crmena(1, iquad, 2, ix, iy); + skip(1); + return; + } + break; + } + if (shoved) { + quad[jx][jy]=iquad; + quad[ix][iy]=IHDOT; + proutn(" displaced by blast to"); + cramlc(2, jx, jy); + skip(1); + for (ll=1; ll<=nenhere; ll++) + kdist[ll] = kavgd[ll] = sqrt(square(sectx-kx[ll])+square(secty-ky[ll])); + sortkl(); + return; + } + skip(1); + prout("Torpedo missed."); + return; +} + +static void fry(double hit) { + double ncrit, extradm; + int ktr=1, l, ll, j, cdam[6], crptr; + + /* a critical hit occured */ + if (hit < (275.0-25.0*skill)*(1.0+0.5*Rand())) return; + + ncrit = 1.0 + hit/(500.0+100.0*Rand()); + proutn("***CRITICAL HIT--"); + /* Select devices and cause damage */ + for (l = 1; l <= ncrit; l++) { + do { + j = ndevice*Rand()+1.0; + /* Cheat to prevent shuttle damage unless on ship */ + } while (damage[j] < 0.0 || (j == DSHUTTL && iscraft != 1) || + j == DDRAY); + cdam[l] = j; + extradm = (hit*damfac)/(ncrit*(75.0+25.0*Rand())); + damage[j] += extradm; + if (l > 1) { + for (ll=2; ll<=l && j != cdam[ll-1]; ll++) ; + if (ll<=l) continue; + ktr += 1; + if (ktr==3) skip(1); + proutn(" and "); + } + proutn(device[j]); + } + prout(" damaged."); + if (damage[DSHIELD] && shldup) { + prout("***Shields knocked down."); + shldup=0; + } +} + +void attack(int k) { + /* k == 0 forces use of phasers in an attack */ + int percent, ihurt=0, l, i=0, jx, jy, iquad, itflag; + int atackd = 0, attempt = 0; + double hit; + double pfac, dustfac, hitmax=0.0, hittot=0.0, chgfac=1.0, r; + + iattak = 1; + if (alldone) return; +#ifdef DEBUG + if (idebug) prout("ATTACK!"); +#endif + + if (ithere) movetho(); + + if (neutz) { /* The one chance not to be attacked */ + neutz = 0; + return; + } + if (((comhere || ishere) && (justin == 0)) || skill == 5) movcom(); + if (nenhere==0) return; + pfac = 1.0/inshld; + if (shldchg == 1) chgfac = 0.25+0.5*Rand(); + skip(1); + if (skill <= 2) i = 2; + for (l=1; l <= nenhere; l++) { + if (kpower[l] < 0) continue; /* too weak to attack */ + /* compute hit strength and diminsh shield power */ + r = Rand(); + /* Increase chance of photon torpedos if docked or enemy energy low */ + if (condit == IHDOCKED) r *= 0.25; + if (kpower[l] < 500) r *= 0.25; + jx = kx[l]; + jy = ky[l]; + iquad = quad[jx][jy]; + itflag = (iquad == IHK && r > 0.0005) || k == 0 || + (iquad==IHC && r > 0.015) || + (iquad==IHR && r > 0.3) || + (iquad==IHS && r > 0.07); + if (itflag) { + /* Enemy uses phasers */ + if (condit == IHDOCKED) continue; /* Don't waste the effort! */ + attempt = 1; /* Attempt to attack */ + dustfac = 0.8+0.05*Rand(); + hit = kpower[l]*pow(dustfac,kavgd[l]); + kpower[l] *= 0.75; + } + else { /* Enemy used photon torpedo */ + double course = 1.90985*atan2((double)secty-jy, (double)jx-sectx); + hit = 0; + proutn("***TORPEDO INCOMING"); + if (damage[DSRSENS] <= 0.0) { + proutn(" From "); + crmena(0, iquad, i, jx, jy); + } + attempt = 1; + prout("--"); + r = (Rand()+Rand())*0.5 -0.5; + r += 0.002*kpower[l]*r; + torpedo(course, r, jx, jy, &hit); + if (d.remkl==0) finish(FWON); /* Klingons did themselves in! */ + if (d.galaxy[quadx][quady] == 1000 || + alldone) return; /* Supernova or finished */ + if (hit == 0) continue; + } + if (shldup != 0 || shldchg != 0) { + /* shields will take hits */ + double absorb, hitsh, propor = pfac*shield; + if(propor < 0.1) propor = 0.1; + hitsh = propor*chgfac*hit+1.0; + atackd=1; + absorb = 0.8*hitsh; + if (absorb > shield) absorb = shield; + shield -= absorb; + hit -= hitsh; + if (propor > 0.1 && hit < 0.005*energy) continue; + } + /* It's a hit -- print out hit size */ + atackd = 1; /* We weren't going to check casualties, etc. if + shields were down for some strange reason. This + doesn't make any sense, so I've fixed it */ + ihurt = 1; + cramf(hit, 0, 2); + proutn(" unit hit"); + if ((damage[DSRSENS] > 0 && itflag) || skill <= 2) { + proutn(" on the "); + crmshp(); + } + if (damage[DSRSENS] <= 0.0 && itflag) { + proutn(" from "); + crmena(0, iquad, i, jx, jy); + } + skip(1); + /* Decide if hit is critical */ + if (hit > hitmax) hitmax = hit; + hittot += hit; + fry(hit); + printf("Hit %g energy %g\n", hit, energy); + energy -= hit; + } + if (energy <= 0) { + /* Returning home upon your shield, not with it... */ + finish(FBATTLE); + return; + } + if (attempt == 0 && condit == IHDOCKED) + prout("***Enemies decide against attacking your ship."); + if (atackd == 0) return; + percent = 100.0*pfac*shield+0.5; + if (ihurt==0) { + /* Shields fully protect ship */ + proutn("Enemy attack reduces shield strength to "); + } + else { + /* Print message if starship suffered hit(s) */ + skip(1); + proutn("Energy left "); + cramf(energy, 0, 2); + proutn(" shields "); + if (shldup) proutn("up, "); + else if (damage[DSHIELD] == 0) proutn("down, "); + else proutn("damaged, "); + } + crami(percent, 1); + proutn("% torpedoes left "); + crami(torps, 1); + skip(1); + /* Check if anyone was hurt */ + if (hitmax >= 200 || hittot >= 500) { + int icas= hittot*Rand()*0.015; + if (icas >= 2) { + skip(1); + proutn("Mc Coy- \"Sickbay to bridge. We suffered "); + crami(icas, 1); + prout(" casualties"); + prout(" in that last attack.\""); + casual += icas; + } + } + /* After attack, reset average distance to enemies */ + for (l = 1; l <= nenhere; l++) + kavgd[l] = kdist[l]; + sortkl(); + return; +} + +void deadkl(int ix, int iy, int type, int ixx, int iyy) { + /* Added ixx and iyy allow enemy to "move" before dying */ + + int i,j; + + crmena(1, type, 2, ixx, iyy); + /* Decide what kind of enemy it is and update approriately */ + if (type == IHR) { + /* chalk up a Romulan */ + d.newstuf[quadx][quady] -= 10; + irhere--; + d.nromkl++; + d.nromrem--; + } + else if (type == IHT) { + /* Killed a Tholean */ + ithere = 0; + } + else { + /* Some type of a Klingon */ + d.galaxy[quadx][quady] -= 100; + klhere--; + d.remkl--; + switch (type) { + case IHC: + comhere = 0; + for (i=1; i<=d.remcom; i++) + if (d.cx[i]==quadx && d.cy[i]==quady) break; + d.cx[i] = d.cx[d.remcom]; + d.cy[i] = d.cy[d.remcom]; + d.cx[d.remcom] = 0; + d.cy[d.remcom] = 0; + d.remcom--; + future[FTBEAM] = 1e30; + if (d.remcom != 0) + future[FTBEAM] = d.date + expran(1.0*incom/d.remcom); + d.killc++; + break; + case IHK: + d.killk++; + break; + case IHS: + d.nscrem = ishere = d.isx = d.isy = isatb = iscate = 0; + d.nsckill = 1; + future[FSCMOVE] = future[FSCDBAS] = 1e30; + break; + } + } + + /* For each kind of enemy, finish message to player */ + prout(" destroyed."); + quad[ix][iy] = IHDOT; + if (d.remkl==0) return; + + d.remtime = d.remres/(d.remkl + 4*d.remcom); + + if (type == IHT) return; + + /* Remove enemy ship from arrays describing local conditions */ + + for (i=1; i<=nenhere; i++) + if (kx[i]==ix && ky[i]==iy) break; + nenhere--; + if (i <= nenhere) { + for (j=i; j<=nenhere; j++) { + kx[j] = kx[j+1]; + ky[j] = ky[j+1]; + kpower[j] = kpower[j+1]; + kavgd[j] = kdist[j] = kdist[j+1]; + } + } + kx[nenhere+1] = 0; + ky[nenhere+1] = 0; + kdist[nenhere+1] = 0; + kavgd[nenhere+1] = 0; + kpower[nenhere+1] = 0; + return; +} + +static int targetcheck(double x, double y, double *course) { + double deltx, delty; + /* Return TRUE if target is invalid */ + if (x < 1.0 || x > 10.0 || y < 1.0 || y > 10.0) { + huh(); + return 1; + } + deltx = 0.1*(y - secty); + delty = 0.1*(sectx - x); + if (deltx==0 && delty== 0) { + skip(1); + prout("Spock- \"Bridge to sickbay. Dr. McCoy,"); + prout(" I recommend an immediate review of"); + prout(" the Captain's psychological profile."); + chew(); + return 1; + } + *course = 1.90985932*atan2(deltx, delty); + return 0; +} + +void photon(void) { + double targ[4][3], course[4]; + double r, dummy; + int key, n, i, osuabor; + + ididit = 0; + + if (damage[DPHOTON]) { + prout("Photon tubes damaged."); + chew(); + return; + } + if (torps == 0) { + prout("No torpedoes left."); + chew(); + return; + } + key = scan(); + for (;;) { + if (key == IHALPHA) { + huh(); + return; + } + else if (key == IHEOL) { + crami(torps,1); + prout(" torpedoes left."); + proutn("Number of torpedoes to fire- "); + key = scan(); + } + else /* key == IHREAL */ { + n = aaitem + 0.5; + if (n <= 0) { /* abort command */ + chew(); + return; + } + if (n > 3) { + chew(); + prout("Maximum of 3 torpedoes per burst."); + key = IHEOL; + } + if (n <= torps) break; + chew(); + key = IHEOL; + } + } + for (i = 1; i <= n; i++) { + key = scan(); + if (i==1 && key == IHEOL) { + break; /* we will try prompting */ + } + if (i==2 && key == IHEOL) { + /* direct all torpedoes at one target */ + while (i <= n) { + targ[i][1] = targ[1][1]; + targ[i][2] = targ[1][2]; + course[i] = course[1]; + i++; + } + break; + } + if (key != IHREAL) { + huh(); + return; + } + targ[i][1] = aaitem; + key = scan(); + if (key != IHREAL) { + huh(); + return; + } + targ[i][2] = aaitem; + if (targetcheck(targ[i][1], targ[i][2], &course[i])) return; + } + chew(); + if (i == 1 && key == IHEOL) { + /* prompt for each one */ + for (i = 1; i <= n; i++) { + proutn("Target sector for torpedo number"); + crami(i, 2); + proutn("- "); + key = scan(); + if (key != IHREAL) { + huh(); + return; + } + targ[i][1] = aaitem; + key = scan(); + if (key != IHREAL) { + huh(); + return; + } + targ[i][2] = aaitem; + chew(); + if (targetcheck(targ[i][1], targ[i][2], &course[i])) return; + } + } + ididit = 1; + /* Loop for moving torpedoes */ + osuabor = 0; + for (i = 1; i <= n && !osuabor; i++) { + if (condit != IHDOCKED) torps--; + r = (Rand()+Rand())*0.5 -0.5; + if (fabs(r) >= 0.47) { + /* misfire! */ + r = (Rand()+1.2) * r; + if (n>1) { + prouts("***TORPEDO NUMBER"); + crami(i, 2); + prouts(" MISFIRES."); + } + else prouts("***TORPEDO MISFIRES."); + skip(1); + if (i < n) + prout(" Remainder of burst aborted."); + osuabor=1; + if (Rand() <= 0.2) { + prout("***Photon tubes damaged by misfire."); + damage[DPHOTON] = damfac*(1.0+2.0*Rand()); + break; + } + } + if (shldup != 0 || condit == IHDOCKED) r *= 1.0 + 0.0001*shield; + if (n != 1) { + skip(1); + proutn("Track for torpedo number"); + crami(i, 2); + proutn("- "); + } + else { + skip(1); + proutn("Torpedo track- "); + } + torpedo(course[i], r, sectx, secty, &dummy); + if (alldone || d.galaxy[quadx][quady]==1000) return; + } + if (d.remkl==0) finish(FWON); +} + + + +static void overheat(double rpow) { + if (rpow > 1500) { + double chekbrn = (rpow-1500.)*0.00038; + if (Rand() <= chekbrn) { + prout("Weapons officer Sulu- \"Phasers overheated, sir.\""); + damage[DPHASER] = damfac*(1.0 + Rand()) * (1.0+chekbrn); + } + } +} + +static int checkshctrl(double rpow) { + double hit; + int icas; + + skip(1); + if (Rand() < .998) { + prout("Shields lowered."); + return 0; + } + /* Something bad has happened */ + prouts("***RED ALERT! RED ALERT!"); + skip(2); + hit = rpow*shield/inshld; + energy -= rpow+hit*0.8; + shield -= hit*0.2; + if (energy <= 0.0) { + prouts("Sulu- \"Captain! Shield malf***********************\""); + skip(1); + stars(); + finish(FPHASER); + return 1; + } + prouts("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""); + skip(2); + prout("Lt. Uhura- \"Sir, all decks reporting damage.\""); + icas = hit*Rand()*0.012; + skip(1); + fry(0.8*hit); + if (icas) { + skip(1); + prout("McCoy to bridge- \"Severe radiation burns, Jim."); + proutn(" "); + crami(icas, 1); + prout(" casualties so far.\""); + casual -= icas; + } + skip(1); + prout("Phaser energy dispersed by shields."); + prout("Enemy unaffected."); + overheat(rpow); + return 1; +} + + +void phasers(void) { + double hits[21], rpow, extra, powrem, over, temp; + int kz = 0, k=1, i; /* Cheating inhibitor */ + int ifast=0, no=0, ipoop=1, msgflag = 1; + enum {NOTSET, MANUAL, FORCEMAN, AUTOMATIC} automode = NOTSET; + int key; + + skip(1); + /* SR sensors and Computer */ + if (damage[DSRSENS]+damage[DCOMPTR] > 0) ipoop = 0; + if (condit == IHDOCKED) { + prout("Phasers can't be fired through base shields."); + chew(); + return; + } + if (damage[DPHASER] != 0) { + prout("Phaser control damaged."); + chew(); + return; + } + if (shldup) { + if (damage[DSHCTRL]) { + prout("High speed shield control damaged."); + chew(); + return; + } + if (energy <= 200.0) { + prout("Insufficient energy to activate high-speed shield control."); + chew(); + return; + } + prout("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""); + ifast = 1; + + } + ididit = 1; + /* Original code so convoluted, I re-did it all */ + while (automode==NOTSET) { + key=scan(); + if (key == IHALPHA) { + if (isit("manual")) { + if (nenhere==0) { + prout("There is no enemy present to select."); + chew(); + key = IHEOL; + automode=AUTOMATIC; + } + else { + automode = MANUAL; + key = scan(); + } + } + else if (isit("automatic")) { + if ((!ipoop) && nenhere != 0) { + automode = FORCEMAN; + } + else { + if (nenhere==0) + prout("Energy will be expended into space."); + automode = AUTOMATIC; + key = scan(); + } + } + else if (isit("no")) { + no = 1; + } + else { + huh(); + ididit = 0; + return; + } + } + else if (key == IHREAL) { + if (nenhere==0) { + prout("Energy will be expended into space."); + automode = AUTOMATIC; + } + else if (!ipoop) + automode = FORCEMAN; + else + automode = AUTOMATIC; + } + else { + /* IHEOL */ + if (nenhere==0) { + prout("Energy will be expended into space."); + automode = AUTOMATIC; + } + else if (!ipoop) + automode = FORCEMAN; + else + proutn("Manual or automatic? "); + } + } + + switch (automode) { + case AUTOMATIC: + if (key == IHALPHA && isit("no")) { + no = 1; + key = scan(); + } + if (key != IHREAL && nenhere != 0) { + proutn("Phasers locked on target. Energy available ="); + cramf(ifast?energy-200.0:energy,1,2); + skip(1); + } + do { + while (key != IHREAL) { + chew(); + proutn("Units to fire="); + key = scan(); + } + rpow = aaitem; + if (rpow >= (ifast?energy-200:energy)) { + proutn("Energy available= "); + cramf(ifast?energy-200:energy, 1,2); + skip(1); + key = IHEOL; + } + } while (rpow >= (ifast?energy-200:energy)); + if (rpow<=0) { + /* chicken out */ + ididit = 0; + chew(); + return; + } + if ((key=scan()) == IHALPHA && isit("no")) { + no = 1; + } + if (ifast) { + energy -= 200; /* Go and do it! */ + if (checkshctrl(rpow)) return; + } + chew(); + energy -= rpow; + extra = rpow; + if (nenhere) { + extra = 0.0; + powrem = rpow; + for (i = 1; i <= nenhere; i++) { + hits[i] = 0.0; + if (powrem <= 0) continue; + hits[i] = fabs(kpower[i])/(phasefac*pow(0.90,kdist[i])); + over = (0.01 + 0.05*Rand())*hits[i]; + temp = powrem; + powrem -= hits[i] + over; + if (powrem <= 0 && temp < hits[i]) hits[i] = temp; + if (powrem <= 0) over = 0.0; + extra += over; + } + if (powrem > 0.0) extra += powrem; + hittem(hits); + } + if (extra > 0 && alldone == 0) { + if (ithere) { + proutn("*** Tholian web absorbs "); + if (nenhere>0) proutn("excess "); + prout("phaser energy."); + } + else { + cramf(extra, 0, 2); + prout(" expended on empty space."); + } + } + break; + + case FORCEMAN: + chew(); + key = IHEOL; + if (damage[DCOMPTR]!=0) + prout("Battle comuter damaged, manual file only."); + else { + skip(1); + prouts("---WORKING---"); + skip(1); + prout("Short-range-sensors-damaged"); + prout("Insufficient-data-for-automatic-phaser-fire"); + prout("Manual-fire-must-be-used"); + skip(1); + } + case MANUAL: + rpow = 0.0; + for (k = 1; k <= nenhere;) { + int ii = kx[k], jj = ky[k]; + int ienm = quad[ii][jj]; + if (msgflag) { + proutn("Energy available= "); + cramf(energy-.006-(ifast?200:0), 0, 2); + skip(1); + msgflag = 0; + rpow = 0.0; + } + if (damage[DSRSENS] && !(abs(sectx-ii) < 2 && abs(secty-jj) < 2) && + (ienm == IHC || ienm == IHS)) { + cramen(ienm); + prout(" can't be located without short range scan."); + chew(); + key = IHEOL; + hits[k] = 0; /* prevent overflow -- thanks to Alexei Voitenko */ + k++; + continue; + } + if (key == IHEOL) { + chew(); + if (ipoop && k > kz) { + int irec=(fabs(kpower[k])/(phasefac*pow(0.9,kdist[k])))* + (1.01+0.05*Rand()) + 1.0; + kz = k; + proutn("("); + crami(irec, 1); + proutn(") "); + } + proutn("units to fire at "); + crmena(0, ienm, 2, ii, jj); + proutn("- "); + key = scan(); + } + if (key == IHALPHA && isit("no")) { + no = 1; + key = scan(); + continue; + } + if (key == IHALPHA) { + huh(); + ididit = 0; + return; + } + if (key == IHEOL) { + if (k==1) { /* Let me say I'm baffled by this */ + msgflag = 1; + } + continue; + } + if (aaitem < 0) { + /* abort out */ + ididit = 0; + chew(); + return; + } + hits[k] = aaitem; + rpow += aaitem; + /* If total requested is too much, inform and start over */ + + if (rpow >= (ifast?energy-200:energy)) { + prout("Available energy exceeded -- try again."); + chew(); + key = IHEOL; + k = 1; + msgflag = 1; + continue; + } + key = scan(); /* scan for next value */ + k++; + } + if (rpow == 0.0) { + /* zero energy -- abort */ + ididit = 0; + chew(); + return; + } + if (key == IHALPHA & isit("no")) { + no = 1; + } + energy -= rpow; + chew(); + if (ifast) { + energy -= 200.0; + if (checkshctrl(rpow)) return; + } + hittem(hits); + ididit=1; + } + /* Say shield raised or malfunction, if necessary */ + if (alldone) return; + if (ifast) { + skip(1); + if (no == 0) { + if (Rand() >= 0.99) { + prout("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."); + prouts(" CLICK CLICK POP . . ."); + prout(" No response, sir!"); + shldup = 0; + } + else + prout("Shields raised."); + } + else + shldup = 0; + } + overheat(rpow); +} + +void hittem(double *hits) { + double kp, kpow, wham, hit, dustfac, kpini; + int nenhr2=nenhere, k=1, kk=1, ii, jj, ienm; + + skip(1); + + for (; k <= nenhr2; k++, kk++) { + if ((wham = hits[k])==0) continue; + dustfac = 0.9 + 0.01*Rand(); + hit = wham*pow(dustfac,kdist[kk]); + kpini = kpower[kk]; + kp = fabs(kpini); + if (phasefac*hit < kp) kp = phasefac*hit; + kpower[kk] -= (kpower[kk] < 0 ? -kp: kp); + kpow = kpower[kk]; + ii = kx[kk]; + jj = ky[kk]; + if (hit > 0.005) { + cramf(hit, 0, 2); + proutn(" unit hit on "); + } + else + proutn("Very small hit on "); + ienm = quad[ii][jj]; + crmena(0,ienm,2,ii,jj); + skip(1); + if (kpow == 0) { + deadkl(ii, jj, ienm, ii, jj); + if (d.remkl==0) finish(FWON); + if (alldone) return; + kk--; /* don't do the increment */ + } + else /* decide whether or not to emasculate klingon */ + if (kpow > 0 && Rand() >= 0.9 && + kpow <= ((0.4 + 0.4*Rand())*kpini)) { + proutn("***Mr. Spock- \"Captain, the vessel at"); + cramlc(2,ii,jj); + skip(1); + prout(" has just lost its firepower.\""); + kpower[kk] = -kpow; + } + } + return; +} + diff --git a/events.c b/events.c new file mode 100644 index 0000000..192b1cb --- /dev/null +++ b/events.c @@ -0,0 +1,767 @@ +#include "sst.h" +#include + +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 && damage[DRADIO] != 0.0) { + /* 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; + 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]); + /* If radio repaired, update star chart and attack reports */ + if (stdamtim != 1e30 && damage[DRADIO] == 0.0) { + 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 || + 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 || 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(§x, §y); + 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 (damage[DRADIO] != 0.0 && + condit != IHDOCKED) 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 && + (damage[DRADIO] <= 0.0 || condit == IHDOCKED)) { + /* 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 (damage[DRADIO]==0.0 || condit == IHDOCKED) { + 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 (damage[DRADIO]==0.0 || condit == IHDOCKED) { + 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 (damage[DRADIO] == 0.0 || condit == IHDOCKED) + 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 wait(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; + /* Repair Deathray if long rest at starbase */ + if (origTime-delay >= 9.99 && condit == IHDOCKED) + damage[DDRAY] = 0.0; + } 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 */ + move(); + 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 = insy; + 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 (damage[DRADIO] == 0.0 || condit == IHDOCKED) { + 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; + 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; + future[FSCMOVE] = future[FSCDBAS] = 1e30; + } + d.remkl -= kldead; + 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) || + damage[DRADIO] == 0 || + condit == IHDOCKED) + 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; +} + + diff --git a/finish.c b/finish.c new file mode 100644 index 0000000..1d58840 --- /dev/null +++ b/finish.c @@ -0,0 +1,447 @@ +#include "sst.h" +#include +#include + +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."); + 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 1: + prout("promotes you one step in rank from \"Novice\" to \"Fair\"."); + break; + case 2: + prout("promotes you one step in rank from \"Fair\" to \"Good\"."); + break; + case 3: + prout("promotes you one step in rank from \"Good\" to \"Expert\"."); + break; + case 4: + 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 5: + 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 > 3) { + 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(); + 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(); + 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(); + 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, disipating 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; + } + 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(); +} + +void score(void) { + double timused = d.date - indate; + int ithperd, iwon, klship; + + 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) d.nromrem = 0; // None captured if no win + 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 + d.nromrem; + if (alive == 0) iscore -= 200; + skip(2); + prout("Your score --"); + if (d.nromkl) + printf("%6d Romulans destroyed %5d\n", + d.nromkl,20*d.nromkl); + if (d.nromrem) + printf("%6d Romulans captured %5d\n", + d.nromrem, d.nromrem); + if (d.killk) + printf("%6d ordinary Klingons destroyed %5d\n", + d.killk, 10*d.killk); + if (d.killc) + printf("%6d Klingon commanders destroyed %5d\n", + d.killc, 50*d.killc); + if (d.nsckill) + printf("%6d Super-Commander destroyed %5d\n", + d.nsckill, 200*d.nsckill); + if (ithperd) + printf("%6.2f Klingons per stardate %5d\n", + perdate, ithperd); + if (d.starkl) + printf("%6d stars destroyed by your action %5d\n", + d.starkl, -5*d.starkl); + if (d.nplankl) + printf("%6d planets destroyed by your action %5d\n", + d.nplankl, -10*d.nplankl); + if (d.basekl) + printf("%6d bases destroyed by your action %5d\n", + d.basekl, -100*d.basekl); + if (nhelp) + printf("%6d calls for help from starbase %5d\n", + nhelp, -45*nhelp); + if (casual) + printf("%6d casualties incurred %5d\n", + casual, -casual); + if (klship) + printf("%6d ship(s) lost or destroyed %5d\n", + klship, -100*klship); + if (alive==0) + prout("Penalty for getting yourself killed -200"); + if (gamewon) { + skip(1); + proutn("Bonus for winning "); + switch (skill) { + case 1: proutn("Novice game "); break; + case 2: proutn("Fair game "); break; + case 3: proutn("Good game "); break; + case 4: proutn("Expert game "); break; + case 5: proutn("Emeritus game"); break; + } + printf(" %5d\n", iwon); + } + skip(2); + printf("TOTAL SCORE %5d\n", iscore); +} + +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 4: fprintf(fp," Expert level\n\n"); break; + case 5: 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); +} diff --git a/linux.c b/linux.c new file mode 100644 index 0000000..9bd3b13 --- /dev/null +++ b/linux.c @@ -0,0 +1,31 @@ +#include +#include +#include + +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 getch(void) { + char chbuf[1]; + struct termio oldstate, newstate; + ioctl(0,TCGETA,&oldstate); + newstate = oldstate; + newstate.c_iflag = 0; + newstate.c_lflag = 0; + ioctl(0,TCSETA,&newstate); + read(0, &chbuf, 1); + ioctl(0,TCSETA,&oldstate); +} + diff --git a/makefile b/makefile new file mode 100644 index 0000000..3e35142 --- /dev/null +++ b/makefile @@ -0,0 +1,15 @@ +CFLAGS= -O + +.c.o: + $(CC) $(CFLAGS) -c $< + +OFILES= sst.o finish.o reports.o setup.o linux.o moving.o battle.o events.o ai.o planets.o + +HFILES= sst.h + +sstos2.exe: $(OFILES) + gcc -o sst $(OFILES) -lm + + +$(OFILES): $(HFILES) + diff --git a/moving.c b/moving.c new file mode 100644 index 0000000..fae20ff --- /dev/null +++ b/moving.c @@ -0,0 +1,966 @@ +#include "sst.h" + +static void getcd(int, int); + +void move(void) { + double angle, deltax, deltay, bigger, x, y, + finald, finalx, finaly, stopegy; + int trbeam = 0, n, l, ix, iy, kink, kinks, iquad; + + if (inorbit) { + prout("SULU- \"Leaving standard orbit.\""); + inorbit = 0; + } + + angle = ((15.0 - direc) * 0.5235988); + deltax = -sin(angle); + deltay = cos(angle); + if (fabs(deltax) > fabs(deltay)) + bigger = fabs(deltax); + else + bigger = fabs(deltay); + + deltay /= bigger; + deltax /= bigger; + + /* If tractor beam is to occur, don't move full distance */ + if (d.date+Time >= future[FTBEAM]) { + trbeam = 1; + condit = IHRED; + dist = dist*(future[FTBEAM]-d.date)/Time + 0.1; + Time = future[FTBEAM] - d.date + 1e-5; + } + /* Move within the quadrant */ + quad[sectx][secty] = IHDOT; + x = sectx; + y = secty; + n = 10.0*dist*bigger+0.5; + + if (n > 0) { + for (l = 1; l <= n; l++) { + ix = (x += deltax) + 0.5; + iy = (y += deltay) + 0.5; + if (ix < 1 || ix > 10 || iy < 1 || iy > 10) { + /* Leaving quadrant -- allow final enemy attack */ + /* Don't do it if being pushed by Nova */ + if (nenhere != 0 && iattak != 2) { + newcnd(); + for (l = 1; l <= nenhere; l++) { + finald = sqrt((ix-kx[l])*(double)(ix-kx[l]) + + (iy-ky[l])*(double)(iy-ky[l])); + kavgd[l] = 0.5 * (finald+kdist[l]); + } + if (d.galaxy[quadx][quady] != 1000) attack(0); + if (alldone) return; + } + /* compute final position -- new quadrant and sector */ + x = 10*(quadx-1)+sectx; + y = 10*(quady-1)+secty; + ix = x+10.0*dist*bigger*deltax+0.5; + iy = y+10.0*dist*bigger*deltay+0.5; + /* check for edge of galaxy */ + kinks = 0; + do { + kink = 0; + if (ix <= 0) { + ix = -ix + 1; + kink = 1; + } + if (iy <= 0) { + iy = -iy + 1; + kink = 1; + } + if (ix > 80) { + ix = 161 - ix; + kink = 1; + } + if (iy > 80) { + iy = 161 - iy; + kink = 1; + } + if (kink) kinks = 1; + } while (kink); + + if (kinks) { + nkinks += 1; + if (nkinks == 3) { + /* Three strikes -- you're out! */ + finish(FNEG3); + return; + } + prout("\nYOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER\n" + "AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,\n" + "YOU WILL BE DESTROYED.\n"); + } + /* Compute final position in new quadrant */ + if (trbeam) return; /* Don't bother if we are to be beamed */ + quadx = (ix+9)/10; + quady = (iy+9)/10; + sectx = ix - 10*(quadx-1); + secty = iy - 10*(quady-1); + proutn("\nEntering"); + cramlc(1, quadx, quady); + skip(1); + quad[sectx][secty] = ship; + newqad(0); + return; + } + iquad = quad[ix][iy]; + if (iquad != IHDOT) { + /* object encountered in flight path */ + stopegy = 50.0*dist/Time; + dist=0.1*sqrt((sectx-ix)*(double)(sectx-ix) + + (secty-iy)*(double)(secty-iy)); + switch (iquad) { + case IHT: /* Ram a Tholean */ + case IHK: /* Ram enemy ship */ + case IHC: + case IHS: + case IHR: + sectx = ix; + secty = iy; + ram(0, iquad, sectx, secty); + finalx = sectx; + finaly = secty; + break; + case IHBLANK: + skip(1); + prouts("***RED ALERT! RED ALERT!"); + skip(1); + proutn("***"); + crmshp(); + proutn(" pulled into black hole at"); + cramlc(2, ix, iy); + skip(1); + finish(FHOLE); + return; + default: + /* something else */ + skip(1); + crmshp(); + if (iquad == IHWEB) + proutn(" encounters Tholian web at"); + else + proutn(" blocked by object at"); + cramlc(2, ix,iy); + prout(";"); + proutn("Emergency stop required "); + cramf(stopegy, 0, 2); + prout(" units of energy."); + energy -= stopegy; + finalx = x-deltax+0.5; + sectx = finalx; + finaly = y-deltay+0.5; + secty = finaly; + if (energy <= 0) { + finish(FNRG); + return; + } + break; + } + goto label100; /* sorry! */ + } + } + dist = 0.1*sqrt((sectx-ix)*(double)(sectx-ix) + + (secty-iy)*(double)(secty-iy)); + sectx = ix; + secty = iy; + } + finalx = sectx; + finaly = secty; +label100: + /* No quadrant change -- compute new avg enemy distances */ + quad[sectx][secty] = ship; + if (nenhere) { + for (l = 1; l <= nenhere; l++) { + finald = sqrt((ix-kx[l])*(double)(ix-kx[l]) + + (iy-ky[l])*(double)(iy-ky[l])); + kavgd[l] = 0.5 * (finald+kdist[l]); + kdist[l] = finald; + } + sortkl(); + if (d.galaxy[quadx][quady] != 1000 && iattak == 0) + attack(0); + for (l = 1 ; l <= nenhere; l++) kavgd[l] = kdist[l]; + } + newcnd(); + iattak = 0; + return; +} + +void dock(void) { + chew(); + if (condit == IHDOCKED) { + prout("Already docked."); + return; + } + if (inorbit) { + prout("You must first leave standard orbit."); + return; + } + if (basex==0 || abs(sectx-basex) > 1 || abs(secty-basey) > 1) { + crmshp(); + prout(" not adjacent to base."); + return; + } + condit = IHDOCKED; + prout("Docked."); + if (energy < inenrg) energy = inenrg; + shield = inshld; + torps = intorps; + lsupres = inlsr; + if (stdamtim != 1e30 && + (future[FCDBAS] < 1e30 || isatb == 1) && iseenit == 0) { + /* get attack report from base */ + prout("Lt. Uhura- \"Captain, an important message from the starbase:\""); + attakreport(); + iseenit = 1; + } +} + +static void getcd(int isprobe, int akey) { + /* This program originally required input in terms of a (clock) + direction and distance. Somewhere in history, it was changed to + cartesian coordinates. So we need to convert. I think + "manual" input should still be done this way -- it's a real + pain if the computer isn't working! Manual mode is still confusing + because it involves giving x and y motions, yet the coordinates + are always displayed y - x, where +y is downward! */ + + + int irowq=quadx, icolq=quady, irows, icols, itemp=0, iprompt=0, key; + double xi, xj, xk, xl; + double deltax, deltay; + int automatic = -1; + + /* Get course direction and distance. If user types bad values, return + with DIREC = -1.0. */ + + direc = -1.0; + + if (landed == 1 && !isprobe) { + prout("Dummy! You can't leave standard orbit until you"); + proutn("are back abourt the "); + crmshp(); + prout("."); + chew(); + return; + } + while (automatic == -1) { + if (damage[DCOMPTR]) { + if (isprobe) + prout("Computer damaged; manual navigation only"); + else + prout("Computer damaged; manual movement only"); + chew(); + automatic = 0; + key = IHEOL; + break; + } + if (isprobe && akey != -1) { + /* For probe launch, use pre-scaned value first time */ + key = akey; + akey = -1; + } + else + key = scan(); + + if (key == IHEOL) { + proutn("Manual or automatic- "); + iprompt = 1; + chew(); + } + else if (key == IHALPHA) { + if (isit("manual")) { + automatic =0; + key = scan(); + break; + } + else if (isit("automatic")) { + automatic = 1; + key = scan(); + break; + } + else { + huh(); + chew(); + return; + } + } + else { /* numeric */ + if (isprobe) + prout("(Manual navigation assumed.)"); + else + prout("(Manual movement assumed.)"); + automatic = 0; + break; + } + } + + if (automatic) { + while (key == IHEOL) { + if (isprobe) + proutn("Target quadrant or quadrant§or- "); + else + proutn("Destination sector or quadrant§or- "); + chew(); + iprompt = 1; + key = scan(); + } + + if (key != IHREAL) { + huh(); + return; + } + xi = aaitem; + key = scan(); + if (key != IHREAL){ + huh(); + return; + } + xj = aaitem; + key = scan(); + if (key == IHREAL) { + /* both quadrant and sector specified */ + xk = aaitem; + key = scan(); + if (key != IHREAL) { + huh(); + return; + } + xl = aaitem; + + irowq = xi + 0.5; + icolq = xj + 0.5; + irows = xk + 0.5; + icols = xl + 0.5; + } + else { + if (isprobe) { + /* only quadrant specified -- go to center of dest quad */ + irowq = xi + 0.5; + icolq = xj + 0.5; + irows = icols = 5; + } + else { + irows = xi + 0.5; + icols = xj + 0.5; + } + itemp = 1; + } + if (irowq<1 || irowq > 8 || icolq<1 || icolq > 8 || + irows<1 || irows > 10 || icols<1 || icols > 10) { + huh(); + return; + } + skip(1); + if (!isprobe) { + if (itemp) { + if (iprompt) { + proutn("Helmsman Sulu- \"Course locked in for"); + cramlc(2, irows, icols); + prout(".\""); + } + } + else prout("Ensign Chekov- \"Course laid in, Captain.\""); + } + deltax = icolq - quady + 0.1*(icols-secty); + deltay = quadx - irowq + 0.1*(sectx-irows); + } + else { /* manual */ + while (key == IHEOL) { + proutn("X and Y displacements- "); + chew(); + iprompt = 1; + key = scan(); + } + itemp = 2; + if (key != IHREAL) { + huh(); + return; + } + deltax = aaitem; + key = scan(); + if (key != IHREAL) { + huh(); + return; + } + deltay = aaitem; + } + /* Check for zero movement */ + if (deltax == 0 && deltay == 0) { + chew(); + return; + } + if (itemp == 2 && !isprobe) { + skip(1); + prout("Helmsman Sulu- \"Aye, Sir.\""); + } + dist = sqrt(deltax*deltax + deltay*deltay); + direc = atan2(deltax, deltay)*1.90985932; + if (direc < 0.0) direc += 12.0; + chew(); + return; + +} + + + +void impuls(void) { + double power; + + ididit = 0; + if (damage[DIMPULS]) { + chew(); + skip(1); + prout("Engineer Scott- \"The impulse engines are damaged, Sir.\""); + return; + } + + if (energy > 30.0) { + getcd(FALSE, 0); + if (direc == -1.0) return; + power = 20.0 + 100.0*dist; + } + else + power = 30.0; + + if (power >= energy) { + /* Insufficient power for trip */ + skip(1); + prout("First Officer Spock- \"Captain, the impulse engines"); + prout("require 20.0 units to engage, plus 100.0 units per"); + if (energy > 30) { + proutn("quadrant. We can go, therefore, a maximum of "); + cramf(0.01 * (energy-20.0)-0.05, 0, 1); + prout(" quadrants.\""); + } + else { + prout("quadrant. They are, therefore, useless.\""); + } + chew(); + return; + } + /* Make sure enough time is left for the trip */ + Time = dist/0.095; + if (Time >= d.remtime) { + prout("First Officer Spock- \"Captain, our speed under impulse"); + prout("power is only 0.95 sectors per stardate. Are you sure"); + prout("we dare spend the time?\""); + if (ja() == 0) return; + } + /* Activate impulse engines and pay the cost */ + move(); + ididit = 1; + if (alldone) return; + power = 20.0 + 100.0*dist; + energy -= power; + Time = dist/0.095; + if (energy <= 0) finish(FNRG); + return; +} + + +void warp(int i) { + int blooey=0, twarp=0, iwarp; + double power; + + if (i!=2) { /* Not WARPX entry */ + ididit = 0; + if (damage[DWARPEN] > 10.0) { + chew(); + skip(1); + prout("Engineer Scott- \"The impulse engines are damaged, Sir.\""); + return; + } + if (damage[DWARPEN] > 0.0 && warpfac > 4.0) { + chew(); + skip(1); + prout("Engineer Scott- \"Sorry, Captain. Until this damage"); + prout(" is repaired, I can only give you warp 4.\""); + return; + } + + /* Read in course and distance */ + getcd(FALSE, 0); + if (direc == -1.0) return; + + /* Make sure starship has enough energy for the trip */ + power = (dist+0.05)*warpfac*warpfac*warpfac*(shldup+1); + + + if (power >= energy) { + /* Insufficient power for trip */ + ididit = 0; + skip(1); + prout("Engineering to bridge--"); + if (shldup==0 || 0.5*power > energy) { + iwarp = pow((energy/(dist+0.05)), 0.333333333); + if (iwarp <= 0) { + prout("We can't do it, Captain. We haven't the energy."); + } + else { + proutn("We haven't the energy, but we could do it at warp "); + crami(iwarp, 1); + if (shldup) + prout(",\nif you'll lower the shields."); + else + prout("."); + } + } + else + prout("We haven't the energy to go that far with the shields up."); + return; + } + + /* Make sure enough time is left for the trip */ + Time = 10.0*dist/wfacsq; + if (Time >= 0.8*d.remtime) { + skip(1); + prout("First Officer Spock- \"Captain, I compute that such"); + proutn(" a trip would require approximately "); + cramf(100.0*Time/d.remtime, 0, 2); + prout(" percent of our"); + prout(" remaining time. Are you sure this is wise?\""); + if (ja() == 0) { ididit = 0; return;} + } + } + /* Entry WARPX */ + if (warpfac > 6.0) { + /* Decide if engine damage will occur */ + double prob = dist*(6.0-warpfac)*(6.0-warpfac)/66.666666666; + if (prob > Rand()) { + blooey = 1; + dist = Rand()*dist; + } + /* Decide if time warp will occur */ + if (0.5*dist*pow(7.0,warpfac-10.0) > Rand()) twarp=1; +#ifdef DEBUG + if (idebug &&warpfac==10 && twarp==0) { + blooey=0; + proutn("Force time warp? "); + if (ja()==1) twarp=1; + } +#endif + if (blooey || twarp) { + /* If time warp or engine damage, check path */ + /* If it is obstructed, don't do warp or damage */ + double angle = ((15.0-direc)*0.5235998); + double deltax = -sin(angle); + double deltay = cos(angle); + double bigger, x, y; + int n, l, ix, iy; + if (fabs(deltax) > fabs(deltay)) + bigger = fabs(deltax); + else + bigger = fabs(deltay); + + deltax /= bigger; + deltay /= bigger; + n = 10.0 * dist * bigger +0.5; + x = sectx; + y = secty; + for (l = 1; l <= n; l++) { + x += deltax; + ix = x + 0.5; + if (ix < 1 || ix > 10) break; + y += deltay; + iy = y +0.5; + if (iy < 1 || iy > 10) break; + if (quad[ix][iy] != IHDOT) { + blooey = 0; + twarp = 0; + } + } + } + } + + + /* Activate Warp Engines and pay the cost */ + move(); + if (alldone) return; + energy -= dist*warpfac*warpfac*warpfac*(shldup+1); + if (energy <= 0) finish(FNRG); + Time = 10.0*dist/wfacsq; + if (twarp) timwrp(); + if (blooey) { + damage[DWARPEN] = damfac*(3.0*Rand()+1.0); + skip(1); + prout("Engineering to bridge--"); + prout(" Scott here. The warp engines are damaged."); + prout(" We'll have to reduce speed to warp 4."); + } + ididit = 1; + return; +} + + + +void setwrp(void) { + int key; + double oldfac; + + while ((key=scan()) == IHEOL) { + chew(); + proutn("Warp factor-"); + } + chew(); + if (key != IHREAL) { + huh(); + return; + } + if (damage[DWARPEN] > 10.0) { + prout("Warp engines inoperative."); + return; + } + if (damage[DWARPEN] > 0.0 && aaitem > 4.0) { + prout("Engineer Scott- \"I'm doing my best, Captain,\n" + " but right now we can only go warp 4.\""); + return; + } + if (aaitem > 10.0) { + prout("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""); + return; + } + if (aaitem < 1.0) { + prout("Helmsman Sulu- \"We can't go below warp 1, Captain.\""); + return; + } + oldfac = warpfac; + warpfac = aaitem; + wfacsq=warpfac*warpfac; + if (warpfac <= oldfac || warpfac <= 6.0) { + proutn("Helmsman Sulu- \"Warp factor "); + cramf(warpfac, 0, 1); + prout(", Captain.\""); + return; + } + if (warpfac < 8.00) { + prout("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""); + return; + } + if (warpfac == 10.0) { + prout("Engineer Scott- \"Aye, Captain, we'll try it.\""); + return; + } + prout("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""); + return; +} + +void atover(int igrab) { + double power, distreq; + + chew(); + /* is captain on planet? */ + if (landed==1) { + if (damage[DTRANSP]) { + finish(FPNOVA); + return; + } + prout("Scotty rushes to the transporter controls."); + if (shldup) { + prout("But with the shields up it's hopeless."); + finish(FPNOVA); + } + prouts("His desperate attempt to rescue you . . ."); + if (Rand() <= 0.5) { + prout("fails."); + finish(FPNOVA); + return; + } + prout("SUCCEEDS!"); + if (imine) { + imine = 0; + proutn("The crystals mined were "); + if (Rand() <= 0.25) { + prout("lost."); + } + else { + prout("saved."); + icrystl = 1; + } + } + } + if (igrab) return; + + /* Check to see if captain in shuttle craft */ + if (icraft) finish(FSTRACTOR); + if (alldone) return; + + /* Inform captain of attempt to reach safety */ + skip(1); + do { + if (justin) { + prouts("***RED ALERT! READ ALERT!"); + skip(1); + proutn("The "); + crmshp(); + prout(" has stopped in a quadrant containing"); + prouts(" a supernova."); + skip(2); + } + proutn("***Emergency automatic override attempts to hurl "); + crmshp(); + skip(1); + prout("safely out of quadrant."); + starch[quadx][quady] = damage[DRADIO] > 0.0 ? d.galaxy[quadx][quady]+1000:1; + + /* Try to use warp engines */ + if (damage[DWARPEN]) { + skip(1); + prout("Warp engines damaged."); + finish(FSNOVAED); + return; + } + warpfac = 6.0+2.0*Rand(); + wfacsq = warpfac * warpfac; + proutn("Warp factor set to "); + cramf(warpfac, 1, 1); + skip(1); + power = 0.75*energy; + dist = power/(warpfac*warpfac*warpfac*(shldup+1)); + distreq = 1.4142+Rand(); + if (distreq < dist) dist = distreq; + Time = 10.0*dist/wfacsq; + direc = 12.0*Rand(); /* How dumb! */ + justin = 0; + inorbit = 0; + warp(2); + if (justin == 0) { + /* This is bad news, we didn't leave quadrant. */ + if (alldone) return; + skip(1); + prout("Insufficient energy to leave quadrant."); + finish(FSNOVAED); + return; + } + /* Repeat if another snova */ + } while (d.galaxy[quadx][quady] == 1000); + if (d.remkl==0) finish(FWON); /* Snova killed remaining enemy. */ +} + +void timwrp() { + int l, ll, gotit; + prout("***TIME WARP ENTERED."); + if (d.snap && Rand() < 0.5) { + /* Go back in time */ + proutn("You are traveling backwards in time "); + cramf(d.date-snapsht.date, 0, 2); + prout(" stardates."); + d = snapsht; + d.snap = 0; + if (d.remcom) { + future[FTBEAM] = d.date + expran(intime/d.remcom); + future[FBATTAK] = d.date + expran(0.3*intime); + } + future[FSNOVA] = d.date + expran(0.5*intime); + future[FSNAP] = d.date +expran(0.25*d.remtime); /* next snapshot will + be sooner */ + if (d.nscrem) future[FSCMOVE] = 0.2777; + isatb = 0; + future[FCDBAS] = future[FSCDBAS] = 1e30; + batx = baty = 0; + + /* Make sure Galileo is consistant -- Snapshot may have been taken + when on planet, which would give us two Galileos! */ + gotit = 0; + for (l = 1; l <= inplan; l++) { + if (d.plnets[l].known == 2) { + gotit = 1; + if (iscraft==1 && ship==IHE) { + prout("Checkov- \"Security reports the Galileo has disappeared, Sir!"); + iscraft = 0; + } + } + } + /* Likewise, if in the original time the Galileo was abandoned, but + was on ship earlier, it would have vanished -- lets restore it */ + if (iscraft==0 && gotit==0 && damage[DSHUTTL] >= 0.0) { + prout("Checkov- \"Security reports the Galileo has reappeared in the dock!\""); + iscraft = 1; + } + + /* Revert star chart to earlier era, if it was known then*/ + if (damage[DRADIO]==0.0 || stdamtim > d.date) { + for (l = 1; l <= 8; l++) + for (ll = 1; ll <= 8; ll++) + if (starch[l][ll] > 1) + starch[l][ll]=damage[DRADIO]>0.0 ? d.galaxy[l][ll]+1000 :1; + prout("Spock has reconstructed a correct star chart from memory"); + if (damage[DRADIO] > 0.0) stdamtim = d.date; + } + } + else { + /* Go forward in time */ + Time = -0.5*intime*log(Rand()); + proutn("You are traveling forward in time "); + cramf(Time, 1, 2); + prout(" stardates."); + /* cheat to make sure no tractor beams occur during time warp */ + future[FTBEAM] += Time; + damage[DRADIO] += Time; + } + newqad(0); +} + +void probe(void) { + double angle, bigger; + int key; + /* New code to launch a deep space probe */ + if (nprobes == 0) { + chew(); + skip(1); + if (ship == IHE) + prout("Engineer Scott- \"We have no more deep space probes, Sir.\""); + else + prout("Ye Faerie Queene has no deep space probes."); + return; + } + if (damage[DDSP] != 0.0) { + chew(); + skip(1); + prout("Engineer Scott- \"The probe launcher is damaged, Sir.\""); + return; + } + if (future[FDSPROB] != 1e30) { + chew(); + skip(1); + if (damage[DRADIO] != 0 && condit != IHDOCKED) { + prout("Spock- \"Records show the previous probe has not yet"); + prout(" reached it's destination.\""); + } + else + prout("Uhura- \"The previous probe is still reporting data, Sir.\""); + return; + } + key = scan(); + + if (key == IHEOL) { + /* slow mode, so let Kirk know how many probes there are left */ + crami(nprobes,1); + prout(nprobes==1 ? " probe left." : " probes left."); + proutn("Are you sure you want to fire a probe? "); + if (ja()==0) return; + } + + isarmed = FALSE; + if (key == IHALPHA && strcmp(citem,"armed") == 0) { + isarmed = TRUE; + key = scan(); + } + else if (key == IHEOL) { + proutn("Arm NOVAMAX warhead?"); + isarmed = ja(); + } + getcd(TRUE, key); + if (direc == -1.0) return; + nprobes--; + angle = ((15.0 - direc) * 0.5235988); + probeinx = -sin(angle); + probeiny = cos(angle); + if (fabs(probeinx) > fabs(probeiny)) + bigger = fabs(probeinx); + else + bigger = fabs(probeiny); + + probeiny /= bigger; + probeinx /= bigger; + proben = 10.0*dist*bigger +0.5; + probex = quadx*10 + sectx - 1; // We will use better packing than original + probey = quady*10 + secty - 1; + probecx = quadx; + probecy = quady; + future[FDSPROB] = d.date + 0.01; // Time to move one sector + prout("Ensign Chekov- \"The deep space probe is launched, Captain.\""); + return; +} + +void help(void) { + /* There's more than one way to move in this game! */ + double ddist, xdist, probf; + int line, l, ix, iy; + + chew(); + /* Test for conditions which prevent calling for help */ + if (condit == IHDOCKED) { + prout("Lt. Uhura- \"But Captain, we're already docked.\""); + return; + } + if (damage[DRADIO] != 0) { + prout("Subspace radio damaged."); + return; + } + if (d.rembase==0) { + prout("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""); + return; + } + if (landed == 1) { + proutn("You must be aboard the "); + crmshp(); + prout("."); + return; + } + /* OK -- call for help from nearest starbase */ + nhelp++; + if (basex!=0) { + /* There's one in this quadrant */ + ddist = sqrt(square(basex-sectx)+square(basey-secty)); + } + else { + ddist = 1e30; + for (l = 1; l <= d.rembase; l++) { + xdist=10.0*sqrt(square(d.baseqx[l]-quadx)+square(d.baseqy[l]-quady)); + if (xdist < ddist) { + ddist = xdist; + line = l; + } + } + /* Since starbase not in quadrant, set up new quadrant */ + quadx = d.baseqx[line]; + quady = d.baseqy[line]; + newqad(1); + } + /* dematerialize starship */ + quad[sectx][secty]=IHDOT; + proutn("Starbase in"); + cramlc(1, quadx, quady); + proutn(" responds--"); + crmshp(); + prout(" dematerializes."); + /* Give starbase three chances to rematerialize starship */ + probf = pow((1.0 - pow(0.98,ddist)), 0.33333333); + for (l = 1; l <= 3; l++) { + switch (l) { + case 1: proutn("1st"); break; + case 2: proutn("2nd"); break; + case 3: proutn("3rd"); break; + } + proutn(" attempt to re-materialize "); + crmshp(); + prouts(" . . . . . "); + if (Rand() > probf) break; + prout("fails."); + } + if (l > 3) { + finish(FMATERIALIZE); + return; + } + /* Rematerialization attempt should succeed if can get adj to base */ + for (l = 1; l <= 5; l++) { + ix = basex+3.0*Rand()-1; + iy = basey+3.0*Rand()-1; + if (ix>=1 && ix<=10 && iy>=1 && iy<=10 && quad[ix][iy]==IHDOT) { + /* found one -- finish up */ + prout("succeeds."); + sectx=ix; + secty=iy; + quad[ix][iy]=ship; + dock(); + skip(1); + prout("Lt. Uhura- \"Captain, we made it!\""); + return; + } + } + finish(FMATERIALIZE); + return; +} diff --git a/os2.c b/os2.c new file mode 100644 index 0000000..c6a7835 --- /dev/null +++ b/os2.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +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 getch(void) { + char chbuf[1]; + struct termio oldstate, newstate; + ioctl(0,TCGETA,&oldstate); + newstate = oldstate; + newstate.c_iflag = 0; + newstate.c_lflag = 0; + ioctl(0,TCSETA,&newstate); + read(0, &chbuf, 1); + ioctl(0,TCSETA,&oldstate); +} \ No newline at end of file diff --git a/planets.c b/planets.c new file mode 100644 index 0000000..39e0846 --- /dev/null +++ b/planets.c @@ -0,0 +1,504 @@ +#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 adjacient 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 aproximately "); + 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 unpredictible. 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 disfunctional.\""); + 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- \"Facinating! . . . 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; +} diff --git a/reports.c b/reports.c new file mode 100644 index 0000000..0c8f606 --- /dev/null +++ b/reports.c @@ -0,0 +1,495 @@ +#include "sst.h" +#include +#include +#include + +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 1: s3="novice"; break; + case 2: s3="fair"; break; + case 3: s3="good"; break; + case 4: s3="expert"; break; + case 5: 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>3 && 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 Klingons have been killed", + 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 > 2) 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 (damage[DRADIO] == 0.0 || condit == IHDOCKED || 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"); + 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 ((damage[DRADIO] == 0.0 || condit == IHDOCKED)&& + 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); + 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]); + 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 */ + 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(" -"); + for (i = 1; i <= 8; i++) { + printf("%d -", i); + for (j = 1; j <= 8; j++) { + if (starch[i][j] < 0) + printf(" .1."); + else if (starch[i][j] == 0) + printf(" ..."); + else if (starch[i][j] > 999) + printf("%5d", starch[i][j]-1000); + else + printf("%5d", d.galaxy[i][j]); + } + 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) { + 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); + 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) { + prout("Insufficient energy, sir."); + 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] 10.0) { + huh(); + return; + } + } + else { + chew(); + skip(1); + return; + } + } + +} diff --git a/setup.c b/setup.c new file mode 100644 index 0000000..2306cb0 --- /dev/null +++ b/setup.c @@ -0,0 +1,701 @@ +#include +#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: "); + 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 */ + /* 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(§x, §y); + 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; + isatb = iscate = imine = icrystl = icraft = d.nsckill = d.nplankl = 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 == 1) { + 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 = 1; + else if (isit("fair")) skill = 2; + else if (isit("good")) skill = 3; + else if (isit("expert")) skill = 4; + else if (isit("emeritus")) skill = 5; + 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-"); + } +#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 > 2? 1 : 0); + d.remtime = 7.0 * length; + intime = d.remtime; + d.remkl = 2.0*intime*((skill+1 - 2*Rand())*skill*0.1+.15); + 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); + } + 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; + 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 < 3 && Rand() <= 0.02) || /* Lighten up if skill is low */ + (skill == 3 && Rand() <= 0.05) || + (skill > 3 && 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 (damage[DRADIO] <= 0.0) { + 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); +} diff --git a/sst.c b/sst.c new file mode 100644 index 0000000..2c88844 --- /dev/null +++ b/sst.c @@ -0,0 +1,692 @@ +#define INCLUDED // Define externs here +#include "sst.h" +#include +#ifdef MSDOS +#include +#endif +#include + +int getch(void); + +static char line[128], *linep = line; +static int linecount; /* for paging */ + +static void clearscreen(void); + +#define NUMCOMMANDS 34 + +/* 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. Perhaps cloaking to be added later? BSD version + + + */ + + +static char *commands[NUMCOMMANDS] = { + "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", + "abandon", + "destruct", + "freeze", + "deathray", + "debug", + "call", + "quit", + "help" +}; + +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"); + if (x) prout(" HELP"); +} + +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 < 26; i++) + if (isit(commands[i])) + break; + if (i < 26) break; + for (; i < NUMCOMMANDS; i++) + if (strcmp(commands[i], citem) == 0) break; + if (i < NUMCOMMANDS) break; + + if (skill <= 2) { + 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) hitme = TRUE; + break; + case 3: // photons + photon(); + if (ididit) 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 + wait(); + 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; + case 26: // Abandon Ship + abandn(); + break; + case 27: // Self Destruct + dstrct(); + break; + case 28: // Save Game + freeze(FALSE); + if (skill > 3) + prout("WARNING--Frozen games produce no plaques!"); + break; + case 29: // Try a desparation measure + deathray(); + if (ididit) hitme = TRUE; + break; + case 30: // What do we want for debug??? +#ifdef DEBUG + debugme(); +#endif + break; + case 31: // Call for help + help(); + break; + case 32: + alldone = 1; // quit the game +#ifdef DEBUG + if (idebug) score(); +#endif + break; + case 33: + 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; + } +} + + +void main(int argc, char **argv) { + int i; + int hitme; + char ch; + prelim(); + + 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(); + 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."); +} + + +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); + 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 */ +#ifdef __BORLANDC__ + extern void clrscr(void); + clrscr(); +#else + proutn("\033[2J"); /* Hope for an ANSI display */ +#endif +} + +/* We will pull these out in case we want to do something special later */ + +void pause(int i) { + putchar('\n'); + if (i==1) { + if (skill > 2) + prout("[ANOUNCEMENT ARRIVING...]"); + else + prout("[IMPORTANT ANNOUNCEMENT ARRIVING -- HIT SPACE BAR TO CONTINUE]"); + getch(); + } + else { + if (skill > 2) + 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(); + } +} + + +#endif diff --git a/sst.doc b/sst.doc new file mode 100644 index 0000000..afc36c3 --- /dev/null +++ b/sst.doc @@ -0,0 +1,1527 @@ + SSSSS U U PPPPP EEEEE RRRRR + S U U P P E R R + SSSSS U U PPPPP EEEE RRRRR + S U U P E R R + SSSSS UUUUU P EEEEE R R + + + SSSSSSS TTTTTTTT A RRRRRRR + SSSSSSSS TTTTTTTT AAA RRRRRRRR + SS TT AAA RR RR + SSSSSSS TT AA AA RR RR + SSSSSSS TT AA AA RRRRRRRR + SS TT AAAAAAA RRRRRRR + SS TT AAAAAAA RR RR + SSSSSSSS TT AA AA RR RR + SSSSSSS TT AA AA RR RR + + + + TTTTTTTT RRRRRRR EEEEEEEEE KK KK + TTTTTTTT RRRRRRRR EEEEEEEEE KK KK + TT RR RR EE KK KK + TT RR RR EEEEEE KKKKKK + TT RRRRRRRR EEEEEE KKKKK + TT RRRRRRR EE KK KK + TT RR RR EE KK KK + TT RR RR EEEEEEEEE KK KK + TT RR RR EEEEEEEEE KK KK + + + Produced For Your Enjoyment + + By + + David Matuszek + and + Paul Reynolds + + With Modifications By + Don Smith + + Resurected By + Tom Almy + + Permission is hereby granted for the copying, distribution, + modification and use of this program and associated documentation + for recreational purposes, provided that all references to the + authors are retained. However, permission is not and will not be + granted for the sale or promotional use of this program or program + documentation, or for use in any situation in which profit may be + considered an objective, since it is the desire of the authors to + respect the copyrights of the originators of Star Trek. + + ----------TABLE OF CONTENTS---------- + + + + SECTION PAGE + + + INTRODUCTION TO THE GAME . . . . . . . . . . . . . . 1 + + HOW TO ISSUE COMMANDS. . . . . . . . . . . . . . . . 4 + + DESCRIPTIONS OF COMMANDS . . . . . . . . . . . . . . 5 + + SHORT-RANGE SCAN. . . . . . . . . . . . . . . . 5 + STATUS REPORT . . . . . . . . . . . . . . . . . 6 + LONG-RANGE SCAN . . . . . . . . . . . . . . . . 7 + STAR CHART. . . . . . . . . . . . . . . . . . . 8 + DAMAGE REPORT . . . . . . . . . . . . . . . . . 8 + MOVE UNDER WARP DRIVE . . . . . . . . . . . . . 9 + WARP FACTOR . . . . . . . . . . . . . . . . . . 10 + IMPULSE ENGINES . . . . . . . . . . . . . . . . 10 + DEFLECTOR SHIELDS . . . . . . . . . . . . . . . 11 + PHASERS . . . . . . . . . . . . . . . . . . . . 12 + REPORT. . . . . . . . . . . . . . . . . . . . . 13 + COMPUTER. . . . . . . . . . . . . . . . . . . . 13 + PHOTON TORPEDOES. . . . . . . . . . . . . . . . 14 + DOCK AT STARBASE. . . . . . . . . . . . . . . . 15 + REST. . . . . . . . . . . . . . . . . . . . . . 15 + CALL STARBASE FOR HELP. . . . . . . . . . . . . 15 + ABANDON SHIP. . . . . . . . . . . . . . . . . . 16 + SELF-DESTRUCT . . . . . . . . . . . . . . . . . 16 + TERMINATE THE CURRENT GAME. . . . . . . . . . . 16 + SENSOR-SCAN . . . . . . . . . . . . . . . . . . 17 + ENTER STANDARD ORBIT. . . . . . . . . . . . . . 17 + TRANSPORTER-TRAVEL. . . . . . . . . . . . . . . 17 + SHUTTLE CRAFT . . . . . . . . . . . . . . . . . 18 + MINE DILITHIUM CRYSTALS . . . . . . . . . . . . 18 + LOAD DILITHIUM CRYSTALS . . . . . . . . . . . . 18 + PLANET REPORT . . . . . . . . . . . . . . . . . 19 + FREEZE. . . . . . . . . . . . . . . . . . . . . 19 + REQUEST . . . . . . . . . . . . . . . . . . . . 20 + EXPERIMENTAL DEATH RAY. . . . . . . . . . . . . 20 + LAUNCH DEEP SPACE PROBE . . . . . . . . . . . . 21 + EMERGENCY EXIT. . . . . . . . . . . . . . . . . 21 + ASK FOR HELP. . . . . . . . . . . . . . . . . . 21 + + + MISCELLANEOUS NOTES. . . . . . . . . . . . . . . . . 22 + + SCORING. . . . . . . . . . . . . . . . . . . . . . . 23 + + HANDY REFERENCE PAGE . . . . . . . . . . . . . . . . 24 + + MODIFICATIONS. . . . . . . . . . . . . . . . . . . . 25 + + ACKNOWLEDGMENTS. . . . . . . . . . . . . . . . . . . 26 + + REFERENCES . . . . . . . . . . . . . . . . . . . . . 26 + + + + -----INTRODUCTION TO THE GAME----- 1 + + +The Organian Peace Treaty has collapsed, and the Federation is at war +with the Klingon Empire. Joining the Klingons against the Federation +are the members of the "Romulan Star Empire." As commander of the +Starship U.S.S. Enterprise, your job is to wipe out the Klingon +invasion fleet and make the galaxy safe for democracy. + +Your battleground is the entire galaxy, which for convenience is +divided up into eight rows of eight quadrants each, like a +checkerboard. Rows are numbered from top to bottom, and columns are +numbered left to right, so quadrant 1 - 8 would be in the upper right +hand corner of the galaxy. + +During battle you will be concerned only with those enemies that +occupy the same quadrant as yourself. Quadrants are divided up into +sectors: ten rows of ten sectors each. Sectors are numbered in the +same way as quadrants, so the sector in the upper right corner is +sector 1 - 10. You have a short-range scanner which allows you to +look at the entire quadrant in a single display. + +Enemies recharge during your absence. If you leave a quadrant +containing a weakened enemy, when you return to that quadrant he will +be strong again. Also, each time you enter a quadrant, the positions +of everthing in the quadrant (except your ship) are randomized, to +save you the trouble of trying to remember where everything in the +quadrant is. Notice that this refers only to the positions of things +in the quadrant--the numbers of each kind of thing are not changed +(except for black holes and the Super-commander, which move around +the galaxy). If you kill something, it stays dead. + +The Romulans are not as serious a threat to the Federation as the +Klingons. For one thing, there are not as many of them. For +another, the Romulans are not as treacherous. However, Romulans are +not to be trifled with, especially when you are in violation of the +"Romulan Neutral Zone." + +There are two kinds of Klingons: Ordinary Klingons, which are bad +enough, and Klingon Commanders, which are even worse. Commanders are +about three times stronger than ordinary Klingons. Commanders are +more resistant to your weapons. Commanders can move about during +battle while Ordinary Klingons stay put. And finally, Commanders +have a thing called a "long-range tractor beam" which they can use, +at random intervals, to yank you away from what you are doing into +their quadrant, to do battle with them. There is also a special +commander, called the "Super-commander." This character is so bad he +is reserved for the Good, Expert, and Emeritus games. Fortunately, +there is just one Super-commander in a game. In addition to the +undesirable traits of Commanders, he can move from quadrant to +quadrant at will, seeking out and destroying your starbases and any +helpful planets he runs across. He also has a spy planted aboard +your ship, giving him valuable information about your condition. +Using this information, he can do dastardly things like tractor beam +your ship when you are in bad shape. And once you've been tractor +beamed by the Super-commander --- + 2 +But the advantages are not all on the side of the enemy. Your ship +is more powerful, and has better weapons. Besides, in the this +galaxy there are from two to five starbases, at which you can stop to +refuel and lick your wounds, safe from phaser attack or tractor +beams. But you had best not dally there too long, since time is not +on your side. The Klingons are not just after you; they are +attacking the entire Federation. There is always a finite "time +left," which is how much longer the Federation can hold out if you +just sit on your fat behind and do nothing. As you wipe out +Klingons, you reduce the rate at which the invasion fleet weakens the +Federation, and so the time left until the Federation collapses may +actually increase. Since Klingons are the main threat to the +Federation, the Romulans do not figure into the "time left." In +fact, you need not kill all the Romulans to win. If you can get all +the Klingons, the Federation will abide forever, and you have won the +game. + +Space is vast, and it takes precious time to move from one place to +another. In comparison, other things happen so quickly that we +assume the take no time at all. Two ways that time can pass are when +you move, or when you issue a command to sit still and rest for a +period of time. You will sometimes want to do the latter, since the +various devices aboard your starship may be damaged and require time +to repair. Of course, repairs can be made more quickly at a starbase +than than can in flight. + +In addition to Klingons, Romulans, and starbases, the galaxy contains +(surprise) stars. Mostly, stars are a nuisance and just get in your +way. You can trigger a star into going nova by shooting one of your +photon torpedoes at it. When a star novas, it does a lot of dammage +to anything immediately adjacent to it. If another star is adjacent +to a nova, it too will go nova. Stars may also occasionally go +supernova; a supernova in a quadrant destroys everything in the +quadrant andmakes the quadrant permanently uninhabitable. You may +"jump over" a quadrant containing a supernova when you move, but you +should not stop there. + +Supernovas may happen spontaneously, without provocation. If a +supernova occurs in the same quadrant you are in, your starship has +an "emergency automatic override" which picks some random direction +and some random warp factor, and tries to throw you clear of the +supernova. If the supernova occurs in some other quadrant, you just +get a warning message from starfleet about it (provided, of course, +that your subspace radio is working). + +Also a few planets are scattered through the galaxy. These can +sometimes be a great help since some of them will have "dilithium +crystals," which are capable of replenishing the ship's energy +supply. You can either beam down to the planet surface using the +transporter, or take the shuttle craft "Galileo." + +Finally, each quadrant will contain from zero to three black holes. +These can deflect or swallor torpedoes passing near them. They also +swallow enemy ships knocked into them. If your ship enters one - - - + 3 +Star Trek is a rich game, full of detail. These instructions are +written at a moderate level--no attempt has been made fully to +describe everything about the game, but there is quite a bit more +here than you need to get started. If you are new to the game, just +get a rough idea of the kinds of commands available, and start +playing. After a game or two you will have learned everthing +important, and the detailed command descriptions which follow will be +a lot more meaningful to you. + +You have weapons: phasers and photon torpedoes. You have a defense: +deflector shields. You can look at things: long-range scaners, +short-range scanners, and a star chart. You can move about, under +warp drive or impulse power. You can also dock at a starbase, rest +while repairs are being made, abandon ship, self destruct, or give up +and start a new game. + +The Klingons are waiting. + + + -----HOW TO ISSUE COMMANDS----- 4 + +When the game is waiting for you to enter a command it will print out + + COMMAND> + +You may then type in your command. All you have to remember for each +command is the mnemonic. For example, if you want to move straight up +one quadrant, you can type in the mnemonic (case insensitive) + + move + +and the computer will prompt you with + + Manual or automatic- + +Say you type in "manual". The computer then responds + + X and Y displacements- + +Now you type in "0 1" which specifies an X movement of zero and a Y +movement of one. + +When you have learned the commands, you can avoid being prompted +simply by typing in the information without waiting to be asked for +it. For example, in the above example, you could simply type in + + move manual 0 1 + +and it will be done. Or you could type in + + move manual + +and when the computer responds with the displacement prompt, you can type in + + 0 1 + +and it will understand. + +You can abbreviate most mnemonics. For "move", you can use any of + + move mov mo m + +successfully. For your safety, certain critical commands (such as to +abandon ship) must be written out in full. Also, in a few cases two +or more commands begin with the same letter, and in this case that +letter refers to a particular one of the commands; to get the other, +your abbreviation must be two or more characters long. This sounds +complicated, but you will learn the abbreviations quickly enough. + +What this all boils down to is: + (1) You can abbreviate practically anything + (2) If you forget, the computer will proompt you + (3) If you remember, you can type it all on one line + +If you are part way through entering a command and you change your +minde, you can cancel the command by typing -1 as one of the +parameters, with the exception of the manual move command. + +If anything is not clear to you, experiment. The worst you can do is +lose a game or two. + + -----DESCRIPTION OF COMMANDS----- 5 + + ******************** + * SHORT-RANGE SCAN * + ******************** + + Mnemonic: SRSCAN + Shortest abbreviation: S + Full commands: SRSCAN + SRSCAN NO + SRSCAN CHART + +The short-range scan gives you a considerable amount of information +about the quadrant your starship is in. A short-range scan is best +described by an example. + + 1 2 3 4 5 6 7 8 9 10 + 1 * . . . . R . . . . Stardate 2516.3 + 2 . . . E . . . . . . Condition RED + 3 . . . . . * . B . . Position 5 - 1, 2 - 4 + 4 . . . S . . . . . . Life Support DAMAGED, Reserves=2.30 + 5 . . . . . . . K . . Warp Factor 5.0 + 6 . K . . . . . * . Energy 2176.24 + 7 . . . . . P . . . . Torpedoes 3 + 8 . . . . * . . . . . Shields UP, 42% 1050.0 units + 9 . * . . * . . . C . Klingons Left 12 + 10 . . . . . . . . . . Time Left 3.72 + + +The left part is a picture of the quadrant. The E at sector 2 - 4 +represents the Enterprise; the B at sector 3 - 8 is a starbase. +There are ordinary Klingons (K) at sectors 5 - 8 and 6 - 2, and a +Klingon Commander (C) at 9 - 9. The (GULP) "Super-commander" (S) is +occupies sector 4 - 4, and a Romulan (R) is at 1 - 6. A planet (P) +is at sector 7 - 6. There are also a large number of stars (*). The +periods (.) are just empty space--they are printed to help you get +your bearings. Sector 6 - 4 contains a black hole ( ). + +The information on the right is assorted status information. You can +get this alone with the STATUS command. The status information will +be absent if you type "N" after SRSCAN. Otherwise status information +will be presented. + +If you type "C" after SRSCAN, you will be given a short-range scan +and a Star Chart. + +Short-range scans are free. That is, they use up no energy and no +time. If you are in battle, doing a short-range scan does not give +the enemies another chance to hit you. You can safely do a +short-range scan anytime you like. + +If your short-range sensors are damaged, this command will only show +the contents of adjacent sectors. + + 6 + ***************** + * STATUS REPORT * + ***************** + + Mnemonic: STATUS + Shortest abbreviation: ST + +This command gives you information about the current state of your +starship as follows: + + STARDATE - The current date. A stardate is the same as a day. + + CONDITION - There are four possible conditions: + DOCKED - docked at starbase. + RED - in battle. + YELLOW - low on energy (<1000 units) + GREEN - none of the above + + POSITION - Quadrant is given first, then sector + + LIFE SUPPORT - If "ACTIVE" then life support systems are + functioning normally. If on "RESERVES" the number is how many + stardates your reserve food, air, etc. will last--you must + get repairs made or get to starbase before your reserves run + out. + + WARP FACTOR - What your warp factor is currently set to. + + ENERGY - The amount of energy you have left. If it drops to zero, + you die. + + TORPEDOES - How many photon torpedoes you have left. + + SHIELDS - Whether your shields are up or down, how strong they are + (what percentage of a hit they can deflect), and shield + energy. + + KLINGONS LEFT - How many of the Klingons are still out there. + + TIME LEFT - How long the Federation can hold out against the + present number of Klingons; that is, how long until the end + if you do nothing in the meantime. If you kill Klingons + quickly, this number will go up--if not, it will go down. If + it reaches zero, the federation is conquered and you lose. + +Status information is free--it uses no time or energy, and if you are +in battle, the Klingons are not given another chance to hit you. + +Status information can also be obtained by doing a short-range scan. +See the SRSCAN command for details. + +Each item of information can be obtained singly by requesting it. +See REQUEST command for details. + + 7 + ******************* + * LONG-RANGE SCAN * + ******************* + + Mnemonic: LRSCAN + Shortest abbreviation: L + +A long-range scan gives you general information about where you are +and what is around you. Here is an example output. + + Long-range scan for Quadrant 5 - 1 + -1 107 103 + -1 316 5 + -1 105 1000 + +This scan says that you are in row 5, column 1 of the 8 by 8 galaxy. +The numbers in the scan indicate how many of each kind of thing there +is in your quadrant and all adjacent quadrants. The digits are +interpreted as follows. + + Thousands digit: 1000 indicates a supernova (only) + Hundreds digit: number of Klingons present + Tens digit: number of starbases present + Ones digit: number of stars present + +For example, in your quadrant (5 - 1) the number is 316, which +indicates 3 Klingons, 1 starbase, and 6 stars. The long-range +scanner does not distinguish between ordinary Klingons and Klingon +command ships. If there is a supernova, as in the quadrant below and +to your right (quadrant 6 - 2), there is nothing else in the +quadrant. + +Romulans possess a "cloaking device" which prevents their detection +by long-range scan. Because of this fact, Starfleet Command is never +sure how many Romulans are "out there". When you kill the last +Klingon, the remaining Romulans surrender to the Federation. + +Planets are also undetectable by long-range scan. The only way to +detect a planet is to find it in your current quadrant with the +short-range sensors. + +Since you are in column 1, there are no quadrants to your left. The +minus oones indicate the negative energy barrier at the edge of the +galaxy, which you are not permitted to cross. + +Long-range scans are free. They use up no energy or time, and can be +done safely regardless of battle conditions. + 8 + ************** + * STAR CHART * + ************** + + Mnemonic: CHART + Shortest abbreviation: C + +As you proceed in the game, you learn more and more about what things +are where in the galaxy. When ever you first do a scan in a quadrant, +telemetry sensors are ejected which will report any changes in the +quadrant(s) back to your ship, providing the sub-space radio is +working. Spock will enter this information in the chart. If the radio +is not working, Spock can only enter new information discovered from +scans, and information in other quadrants may be obsolete. + +The chart looks like an 8 by 8 array of numbers. These numbers are +interpreted exactly as they are on a long-range scan. A period (.) in +place of a digit means you do not know that information yet. For +example, ... means you know nothing about the quadrant, while .1. +menas you know it contains a base, but an unknown number of Klingons +and stars. + +Looking at the star chart is a free operation. It costs neither time +nor energy, and can be done safely whether in or out of battle. + + + ***************** + * DAMAGE REPORT * + ***************** + + Mnemonic: DAMAGES + Shortest abbreviation: DA + +At any time you may ask for a damage report to find out what devices +are damaged and how long it will take to repair them. Naturally, +repairs proceed faster at a starbase. + +If you suffer damages while moving, it is possible that a subsequent +damage report will not show any damage. This happens if the time +spent on the move exceeds the repair time, since in this case the +damaged devices were fixed en route. + +Damage reports are free. They use no energy or time, and can be done +safely even in the midst of battle. + + 9 + ************************* + * MOVE UNDER WARP DRIVE * + ************************* + + Mnemonic: MOVE + Shortest abbreviation: M + Full command: MOVE MANUAL + MOVE AUTOMATIC + +This command is the usual way to move from one place to another +within the galaxy. You move under warp drive, according to the +current warp factor (see "WARP FACTOR"). + +There are two command modes for movement: MANUAL and AUTOMATIC. The +manual mode requires the following format: + + MOVE MANUAL + + and are the horizontal and vertical displacements +for your starship, in quadrants; a displacement of one sector is 0.1 +quadrants. Specifying and causes your ship to move +in a straight line to the specified destination. If is +omitted, it is assumed zero. For example, the shortest possible +command to move one sector to the right would be + + M M .1 + +The following examples of manual movement refer to the short-range +scan shown earlier. + + Destination Sector Manual Movement command + 3 - 1 M M -.3 -.1 + 2 - 1 M M -.3 + 1 - 2 M M -.2 .1 + 1 - 4 M M 0 .1 + (leaving quadrant) M M 0 .2 + + +The automatic mode is as follows: + + MOVE AUTOMATIC + +where and are the row and column numbers of the +destination quadrant, and and are the row and column +numbers of thedestination sector in that quadrant. This command also +moves your ship in a straight line path to the destination. For +moving within a quadrant, and may be omitted. For +example, to move to sector 2 - 9 in the current quadrant, the +shortest command would be + + M A 2 9 + +To move to quadrant 3 - 7, sector 5 - 8, type + + M A 3 7 5 8 + +and it will be done. In automatic mode, either two or four numbers +must be supplied. + 10 +Automatic mode utilizes the ship's "battle computer." If the +computer is damaged, manual movement must be used. + +If warp engines are damaged less than 10 stardates (undocked) you can +still go warp 4. + +It uses time and energy to move. How much time and how much energy +depends on your current warp factor, the distance you move, and +whether your shields are up. The higher the warp factor, the faster +you move, but higher warp factors require more energy. You may move +with your shields up, but this doubles the energy required. + +You can move within a quadrant without being attacked if you just +entered the quadrant or have bee attacked since your last move +command. This enables you to move and hit them before they +retaliate. + + + *************** + * WARP FACTOR * + *************** + + Mnemonic: WARP + Shortest abbreviation: W + Full command: WARP + +Your warp factor controls the speed of your starship. The larger the +warp factor, the faster you go and the more energy you use. + +Your minimum warp factor is 1.0 and your maximum warp factor is 10.0 +(which is 100 times as fast and uses 1000 times as much energy). At +speeds above warp 6 there is some danger of causing damage to your +warp engines; this damage is larger at higher warp factors and also +depends on how far you go at that warp factor. + +At exactly warp 10 there is some probability of entering a so-called +"time warp" and being thrown foward or backward in time. The farther +you go at warp 10, the greater is the probability of entering the +time warp. + + + ******************* + * IMPULSE ENGINES * + ******************* + + Mnemonic: IMPULSE + Shortest abbreviation: I + Full command: IMPULSE MANUAL + IMPULSE AUTOMATIC + +The impulse engines give you a way to move when your warp engines are +damaged. They move you at a speed of 0.95 sectors per stardate, +which is the equivalent of a warp factor of about 0.975, so they are +much too slow to use except in emergencies. + +Movement commands are indicated just as in the "MOVE" command. + +The impulse engines require 20 units of energy to engage, plus 10 +units per sector (100 units per quadrant) traveled. It does not cost +extra to move with the shields up. + 11 + ********************* + * DEFLECTOR SHIELDS * + ********************* + + Mnemonic: SHIELDS + Shortest abbreviation: SH + Full commands: SHIELDS UP + SHIELDS DOWN + SHIELDS TRANSFER + +Your deflector shields are a defensive device to protect you from +Klingon attacks (and nearby novas). As the shields protect you, they +gradually weaken. A shield strength of 75%, for example, means that +the next time a Klingon hits you, your shields will deflect 75% of +the hit, and let 25% get through to hurt you. + +It costs 50 units of energy to raise shields, nothing to lower them. +You may move with your shields up; this costs nothing under impulse +power, but doubles the energy required for warp drive. + +Each time you raise or lower yoru shields, the Klingons have another +chance to attack. Since shields do not raise and lower +instantaneously, the hits you receive will be intermediate between +what they would be if the shields were completely up or completely +down. + +You may not fire phasers through your shields. However you may use +the "high-speed shield control" to lower shields, fire phasers, and +raise the shields again before the Klingons can react. Since rapid +lowering and raising of the shields requires more energy than normal +speed operation, it costs you 200 units of energy to activate this +control. It is automatically activated when you fire phasers while +shields are up. You may fire photon torpedoes, but they may be +deflected considerably from their intended course as they pass +through the shields (depending on shield strength). + +You may transfer energy beteen the ship's energy (given as "Energy" +in the status) and the shields. Thee word "TRANSFER" may be +abbreviated "T". The ammount of energy to transfer is the number of +units of energy you wish to take from the ship's energy and put into +the shields. If you specify an negative number, energy is drained +from the shields to the ship. Transfering energy constitutes a turn. +If you transfer energy to the shields while you are under attack, +they will be at the new energy level when you are next hit. + +Enemy torpedoes hitting your ship explode on your shields (if they +are up) and have essentially the same effect as phaser hits. + 12 + *********** + * PHASERS * + *********** + + Mnemonic: PHASERS + Shortest abbreviation: P + Full commands: PHASERS AUTOMATIC + PHASERS + PHASERS MANUAL ... + +Phasers are energy weapons. As you fire phasers at Klingons, you +specify an "amount to fire" which is drawn from your energy reserves. +The amount of total hit required to kill an enemy is partly random. +but also depends on skill level. + +The average hit required to kill an ordinary Klingon varies from 200 +units in the Novice game to 250 units in the Emeritus game. +Commanders normally require from 600 (Novice) to 700 (Emeritus). The +Super-commander requres from 875 (Good) to 1000 (Emeritus). Romulans +require an average of 350 (Novice) to 450 (Emeritus). + +Hits on enemies are cumulative, as long as you don't leave the +quadrant. + +In general, not all that you fire will reach the Klingons. The +farther away they are, the less phaser energy will reach them. If a +Klingon is adjacent to you, he will receive about 90% of the phaser +energy directed at him; a Klingon 5 sectors away will receive about +60% and a Klingon 10 sectors away will receive about 35%. There is +some randomness involved, so these figures are not exact. Phasers +have no effect beyond the boundaries of the quadrant you are in. + +Phasers may overheat (and be damaged) if you fire too large a burst +at once. Firing up to 1500 units is safe. From 1500 on up the +probability of overheat increases with the amount fired. + +If phaser firing is automatic, the computer decides how to divide up +your among the Klingons present. If phaser firing +is manual, you specify how much energy to fire at each Klingon +present (nearest first), rather than just specifying a total amount. +You can abreviate "MANUAL" and "AUTOMATIC" to one or more letters; if +you mention neither, automatic fire is usually assumed. + +Battle computer information is available by firing phasers manually, +and allowing the computer to prompt you. If you enter zero for the +amount to fire at each enemy, you will get a complete report, without +cost. The battle computer will tell you how much phaser energy to +fire at each enemy for a sure kill. This information appears in +parentheses prior to the prompt for each enemy. SInce the amount is +computed from sensor data, if either the computer or the S.R. sensors +are damaged, this information will be unavailable, and phasers must +be fired manually. + 13 +A safety interlock prevents phasers from being fired through the +shields. If this were not so, the shields would contain your fire +and you would fry yourself. However, you may utilize the +"high-speed shield control" to drop shields, fire phasers, and raise +shields before the enemy can react. Since it takes more energy to +work the shields rapidly with a shot, it costs you 200 units of +energy each time you activate this control. It is automatically +activated when you fire phasers while the shields are up. By +specifying the option, shields are not raised after firing. + +Phasers have no effect on starbases (which are shielded) or on stars. + + + ********** + * REPORT * + ********** + + Mnemonic: REPORT + Shortest abbreviation: REP + +This command supplies you with information about the state of the +current game. Its purpose is to remind you of things that you have +learned during play, but may have forgotten, and cannot otherwise +retrieve if you are not playing at a hard-copy terminal. + + You are told the following things: + + . The length and skill level of the game you are playing + . The original number of Klingons + . How many Klingons you have destroyed + . Whether the Super-Commander has been destroyed + . How many bases have been destroyed + . How many bases are left + . What bases (if any) are under attack; your subspace radio + must have been working since the attack to get this + information. + . How many casualties you have suffered + . How many times you have called for help. + +This same information is automatically given to you when you start to +play a frozen game. + + + ************ + * COMPUTER * + ************ + + Mnemonic: COMPUTER + Shortest abbreviation: CO + +This command allows using the ship's computer (if functional) to +calculate travel times and energy usage. + + + 14 + ******************** + * PHOTON TORPEDOES * + ******************** + + Mnemonic: PHOTONS + Shortest abbreviation: PHO + Full commands: PHOTONS + +Photon torpedoes are projectile weapons--you either hit what you aim +at, or you don't. There are no "partial hits". + +One photon torpedo will usually kill one ordinary Klingon, but it +usually takes about two for a Klingon Commander. Photon torpedoes +can also blow up stars and starbases, if you aren't careful. + +You may fire photon torpedoes singly, or in bursts of two or three. +Each torpedo is individually targetable. The computer will prompt +you, asking for the target sector for each torpedo. Alternately, you +may specify each target in the command line. + +Photon torpedoes cannot be aimed precisely--there is always some +randomness involved in the direction they go. Photon torpedoes may +be fired with your shields up, but as they pass through the shields +they are randomly deflected from their intended course even more. + +Photon torpedoes are proximity-fused. The closer they explode to the +enemy, the more damage they do. There is a hit "window" about one +sector wide. If the torpedo misses the hit window, it does not +explode and the enemy is unaffected. Photon torpedoes are only +effective within the quadrant. They have no effect on things in +adjacent quadrants. + +If more than one torpedo is fired and only one target sector is +specified, all torpedoes are fired at that sector. For example, to +fire two torpedoes at sector 3 - 4, you type + + PHO 2 3 4 (or) PHO 2 3 4 3 4 + +To fire torpedoes at, consecutively, sectors 2 - 6, 1 - 10, and 4 - +7, type + + PHO 3 2 6 1 10 4 7 + +There is no restriction to fire directly at a sector. For example, +you can enter + + PHO 1 3 2.5 + +to aim between two sectors. However, sector numbers must be 1 to 10 +inclusive. + + 15 + ******************** + * DOCK AT STARBASE * + ******************** + + Mnemonic: DOCK + Shortest abbreviation: D + +You may dock your starship whenever you are in one of the eight +sector positions immediately adjacent to a starbase. When you dock, +your starship is resupplied with energy, shield energy photon +torpedoes, and life support reserves. Repairs also proceed faster at +starbase, so if some of your devices are damaged, you may wish to +stay at base (by using the "REST" command) until they are fixed. If +your ship has more than its normal maximum energy (which can happen +if you've loaded crystals) the ship's energy is not changed. + +You may not dock while in standard orbit around a planet. + +Starbases have their own deflector shields, so you are completely +safe from phaser attack while docked. You are also safe from +long-range tractor beams. + +Starbases also have both short and long range sensors, which you can +use if yours are broken. There's also a subspace radio to get +information about happenings in the galaxy. Mr. Spock will update the +star chart if your ask for it while docked and your own radio is dead. + + + ******** + * REST * + ******** + + Mnemonic: REST + Shortest abbreviation: R + Full command: REST + +This command simply allows the specified number of stardates to go +by. This is useful if you have suffered damages and wish to wait +until repairs are made before you go back into battle. + +It is not generally advisable to rest while you are under attack by +Klingons. + + + ************************** + * CALL STARBASE FOR HELP * + ************************** + + Mnemonic: CALL + (No abbreviation) + +[Originally, this command was called "HELP", but these days it might +be misinterpreted as built-in documentation!] + +When you get into serious trouble, you may call starbase for help. +Starbases have a device called a "long-range transporter beam" which +they can use to teleport you to base. This works by dematerializing +your starship at its current position and re-materializing it +adjacent to the nearest starbase. Teleportation is instantaneous, +and starbase supplies the required energy--all you have to do is let +them know (via subspace radio) that you need to be rescued. + 16 +This command should be employed only when absolutely necessary. In +the first place, calling for help is an admission on your part that +you got yourself into something you cannot get yourself out of, and +you are heavily penalized for this in the final scoring. Secondly, +the long-range transporter beam is not reliable--starbase can always +manage to dematerialize your starship, but (depending on distance) +may or may not be able to re-materialize you again. The long-range +transporter beam has no absolute maximum range; if you are in the +same quadrant as a starbase, you have a good chance (about 90%) of +re-materializing successfully. your chances drop to roughly 50-50 at +just over 3 quadrants. + + + **************** + * ABANDON SHIP * + **************** + + Mnemonic: ABANDON + (no abbreviation) + +You may abandon the Enterprise if necessary. If there is still a +starbase in the galaxy, you will be sent there and put in charge of a +weaker ship, the Faerie Queene. + +The Faerie Queene cannot be abandoned. + + + ***************** + * SELF-DESTRUCT * + ***************** + + Mnemonic: DESTRUCT + (no abbreviation) + +You may self-destruct, thus killing yourself and ending the game. If +there are nearby Klingons, you may take a few of them with you (the +more energy you have left, the bigger the bang). + +In order to self-destruct you must remember the password you typed in +at the beginning of the game. + + + + ****************************** + * TERMINATE THE CURRENT GAME * + ****************************** + + Mnemonic: QUIT + (no abbreviation) + +Immediately cancel the current game; no conclusion is reached. You +will be given an opportunity to start a new game or to leave the Star +Trek program. + + + 17 + *************** + * SENSOR-SCAN * + *************** + + Mnemonic: SENSORS + Shortest abbreviation: SE + +Utilizing the short-range sensors, science officer Spock gives you a +readout on any planet in your quadrant. Planets come in three +classes: M, N, and O. Only class M planets have earth-like +conditions. Spock informs you if the planet has any dilithium +crystals. Sensor scans are free. + + + ************************ + * ENTER STANDARD ORBIT * + ************************ + + Mnemonic: ORBIT + Shortest abbreviation: O + +To land on a planet you must first be in standard orbit. You achieve +this in a manner similar to docking at starbase. Moving to one of +the eight sector positions immediately adjacent to the planet, you +give the orbit command which puts your ship into standard orbit about +the planet. Since this is a maneuver, a small amount of time is +used; negligible energy is required. If enemies are present, they +will attack. + + + ********************** + * TRANSPORTER-TRAVEL * + ********************** + + Mnemonic: TRANSPORT + Shortest abbreviation: T + +The transporter is a device which can convert any physical object +into energy, beam the energy through space, and reconstruct the +physical object at some destination. Transporting is one way to land +on a planet. Since the transporter has a limited range, you must be +in standard orbit to beam down to a planet. Shields must be down +while transporting. + +The transport command is used to beam a landing party onto a planet +to mine "dilithium crystals". Each time the command is given the +landing party (which you lead) moves from the ship to the planet, or +vice-versa. + +You are advised against needless transporting, since like all +devices, the transporter will sometimes malfunction. + +The transporter consumes negligible time and energy. Its use does +not constitute a "turn". + + 18 + ***************** + * SHUTTLE CRAFT * + ***************** + + Mnemonic: SHUTTLE + Shortest abbreviation: SHU + +An alternate way to travel to and from planets. Because of limited +range, you must be in standard orbit to use the shuttle craft, named +"Galileo". Shields must be down. + +Unlike transporting, use of the shuttle craft does constitute a +"turn" since time is consumed. The time naturally depends on orbit +altitude, and is equal to 3.0e-5 times altitude. Shuttling uses no +ship energy. + +You should use the same travel device going from the planet to the +ship as you use to go from the ship to the planet. However it is +possible to transport to the planet and have the Galileo crew come +and pick your landing party up, or to take the Galileo to the planet +and then transport back, leaving the shuttle craft on the planet. + + + *************************** + * MINE DILITHIUM CRYSTALS * + *************************** + + Mnemonic: MINE + Shortest abbreviation: MI + +Once you and your mining party are on the surface of a planet which +has dilithium crystals, this command will dig them for you. + +Mining requires time and constitutes a "turn". No energy is used. +Class M planets require 0.1 to 0.3 stardates to mine. Class N +planets take twice as long, and class O planets take three times as +long. + +Dilithium crystals contain enormous energy in a form that is readily +released in the ship's power system. It is an excellent idea to mine +them whenever possible, for use in emergencies. You keep the +crystals until the game is over or you abandon ship when not at a +starbase. + + + *************************** + * LOAD DILITHIUM CRYSTALS * + *************************** + + Mnemonic: CRYSTALS + Shortest abbreviation: CR + +This is a very powerful command which should be used with caution. +Once you have dilithium crystals aboard ship, this command will +instruct engineering officer Scott and Mr. Spock to place a raw +dilithium crystal into the power channel of the ship's +matter-antimatter converter. When it works, this command will +greatly boost the ship's energy. + 19 +Because the crystals are raw and impure, instabilities can occur in +the power channel. Usually Scotty can control these. When he +cannot, the results are disastrous. Scotty will use those crystals +that appear to be most stable first. + +Since using raw dilithium crystals for this purpose entails +considerable risk, Starfleet Regulations allow its use only during +"condition yellow". No time or energy is used. + + + ***************** + * PLANET REPORT * + ***************** + + Mnemonic: PLANETS + Shortest abbreviation: PL + +Mr. Spock presents you a list of the available information on planets +in the galaxy. Since planets do not show up on long-range scans, the +only way to obtain this information is with the "SENSORS" command. + + + ********** + * FREEZE * + ********** + + Mnemonic: FREEZE + (no abbreviation) + Full command: FREEZE + +The purpose of the FREEZE command is to allow a player to save the +current state of the game, so that it can be finished later. A +plaque may not be generated from a frozen game. A file with the +specified and type '.TRK' is created (if necessary) in +the current directory, and all pertinent information about the game +is written to that file. The game may be continued as usual or be +terminated at the user's option. + +To restart a game created by the "FREEZE" command, the user need only +type "FROZEN" in response to the initial question about the type of +game desired, followed by the . + +NOTE: A "tournament" game is like a frozen game, with the following +differences. (1) Tournament games always start from the beginning, +while a frozen game can start at any point. (2) Tournament games +require only that the player remember the name or number of the +tournament, while the information about a frozen game must be kept on +a file. Tournament games can be frozen, but then they behave like +regular frozen games. + +A point worth noting is that 'FREEZE' does not save the seed for the +random number generator, so that identical actions after restarting +the same frozen game can lead to different results. However, +identical actions after starting a given tournament game always lead +to the same results. + 20 + *********** + * REQUEST * + *********** + + Mnemonic: REQUEST + Shortest abbreviation: REQ + Full command: REQUEST + +This command allows you to get any single piece of information from +the command. specifies which information as follows: + + INFORMATION MNEMONIC FOR SHORTEST ABBREVIATION + + STARDATE DATE D + CONDITION CONDITION C + POSITION POSITION P + LIFE SUPPORT LSUPPORT L + WARP FACTOR WARPFACTOR W + ENERGY ENERGY E + TORPEDOES TORPEDOES T + SHIELDS SHIELDS S + KLINGONS LEFT KLINGONS K + TIME LEFT TIME TI + + + ************************** + * EXPERIMENTAL DEATH RAY * + ************************** + + Mnemonic: DEATHRAY + (No abbreviation) + +This command should be used only in those desperate cases where you +have absolutely no alternative. The death ray uses energy to +rearrange matter. Unfortunately, its working principles are not yet +thoroughly understood, and the results are highly unpredictable. + +The only good thing that can result is the destruction of all enemies +in your current quadrant. This will happen about 70% of the time. +Only enemies are destroyed; starbases, stars, and planets are +unaffected. + +Constituting the remaining 30% are results varying from bad to fatal. + +The death ray requires no energy or time, but if you survive, enemies +will hit you. + +The Faerie Queene has no death ray. + +If the death ray is damaged in its use, it must be totally replaced. +This can only be done at starbase. Because it is a very complex +device, it takes 9.99 stardates at base to replace the death ray. +The death ray cannot be repaired in flight. + + 21 + *************************** + * LAUNCH DEEP SPACE PROBE * + *************************** + + Mnemonic: PROBE + Shortest abbreviation: PR + Full command: PROBE MANUAL + PROBE AUTOMATIC + +The Enterprise carries a limited number of Long Range Probes. These +fly to the end of the galaxy and report back a count of the number of +important things found in each quadrant through which it went. The +probe flies at warp 10, and therefore uses time during its flight. +Results are reported immediately via subspace radio and are recorded +in the star chart. + +The probe can also be armed with a NOVAMAX warhead. When launched +with the warhead armed, the probe flies the same except as soon as it +reaches the target location, it detonates the warhead in the heart of +a star, causing a supernova and destroying everything in the +quadrant. It then flies no further. There must be a star in the +target quadrant for the NOVAMAX to function. + +The probe can fly around objects in a galaxy, but is destroyed if it +enters a quadrant containing a supernova, or if it leaves the galaxy. + +The target location is specified in the same manner as the MOVE +command, however for automatic movement, if only one pair of +coordinates are specified they are assumed to be the quadrant and not +the sector in the current quadrant! + +The Faerie Queene has no probes. + + + ****************** + * EMERGENCY EXIT * + ****************** + + Mnemonic: EMEXIT + Shortest abbreviation: E + +This command provides a quick way to exit from the game when you +observe a Klingon battle cruiser approaching your terminal. Its +effect is to freeze the game on the file 'EMSAVE.TRK' in your current +directory, erase the screen, and exit. + +Of course, you do loose the chance to get a plaque when you use this +manouver. + + + **************** + * ASK FOR HELP * + **************** + + Mnemonic: HELP + Full command: HELP + +This command reads the appropriate section from the SST.DOC file, +providing the file is in the current directory. + + **********MISCELLANEOUS NOTES********** 22 + +Starbases can be attacked by either commanders or by the +"Super-Commander". When this happens, you will be notified by +subspace radio, provided it is working. The message will inform you +how long the base under attack can last. Since the "Super-Commander" +is more powerful than an ordinary commander, he can destroy a base +more quickly. + +The "Super-Commander" travels around the galaxy at a speed of about +warp 6 or 7. His movement is strictly time based; the more time +passes, the further he can go. + +Scattered through the galaxy are certain zones of control, +collectively designated the "Romulan Neutral Zone". Any quadrant +which contains Romulans without Klingons is part of the Neutral Zone, +except if a base is present. Since Romulans do not show on either +the long-range scan or the star chart, it is easy for you to stumble +into this zone. When you do, if your subspace radio is working, you +will receive a warning message from the Romulan, politely asking you +to leave. + +In general, Romulans are a galactic nuisance. + +The high-speed shield control is fairly reliable, but it has been +known to malfunction. + +You can observe the galactic movements of the "Super-Commander" on +the star chart, provided he is in territory you have scanned and your +subspace radio is working. + +Periodically, you will receive intelligence reports from starfleet +command, indicating the current quadrant of the "Super-Commander". +Your subspace radio must be working, of course. + +Each quadrant will contain from 0 to 3 black holes. Torpedoes +entering a black hole disappear. In fact, anything entering a black +hole disappears, permanently. If you can displace an enemy into one, +he is a goner. Black holes do not necessarily remain in a quadrant. +they are transient phenomena. + +Commanders will ram your ship, killing themselves and inflicting +heavy damage to you, if they should happen to decide to advance into +your sector. + +You can get a list of commands by typing "COMMANDS". + + ----------SCORING---------- 23 + + +Scoring is fairly simple. You get points for good things, and you +lose points for bad things. + + You gain-- + + (1) 10 points for each ordinary Klingon you kill, + (2) 50 points for each commander you kill, + (3) 200 points for killing the "Super-Commander", + (4) 20 points for each Romulan killed, + (5) 1 point for each Romulan captured. + (6) 500 times your average Klingon/stardate kill rate. If you + lose the game, your kill rate is based on a minimum of + 5 stardates. + (7) You get a bonus if you win the game, based on your rating: + Novice=100, Fair=200, Good=300, Expert=400, Emeritus=500. + + You lose-- + + (8) 200 points if you get yourself killed, + (9) 100 points for each starbase you destroy, + (10) 100 points for each starship you lose, + (11) 45 points for each time you had to call for help, + (12) 10 points for each planet you destroyed, + (13) 5 points for each star you destroyed, and + (14) 1 point for each casualty you incurred. + +In addition to your score, you may also be promoted one grade in rank +if you play well enough. Promotion is based primarily on your +Klingon/stardate kill rate, since this is the best indicator of +whether you are ready to go on to the next higher rating. However, +if you have lost 100 or more points in penalties, the required kill +rate goes up. Normally, the required kill rate is 0.1 * skill * +(skill + 1.0) + 0.1, where skill ranges from 1 for Novice to 5 for +Emeritus. + +You can be promoted from any level. There is a special promotion +available if you go beyond the "Expert" range. You can also have a +certificate of merit printed with your name, date, and Klingon kill +rate, provided you are promoted from either the "Expert" or +"Emeritus" levels. This "plaque" requires a 132 column printer. You +may need print the certificate to a file, import it into your word +processor, selecting Courier 8pt font, and then print in "landscape +orientation". + +You should probably start out at the novice level, even if you are +already familiar with one of the other versions of the Star Trek +game--but, of course, the level of game you play is up to you. If +you want to start at the Expert level, go ahead. It's your funeral. +The emeritus game is strictly for masochists. + + ----------HANDY REFERENCE PAGE---------- 24 + + ABBREV FULL COMMAND DEVICE USED + ------ ------------ ----------- + ABANDON ABANDON shuttle craft + C CHART (none) + CALL CALL (for help) subspace radio + CO COMPUTER computer + CR CRYSTALS (none) + DA DAMAGES (none) + DEATHRAY DEATHRAY (none) + DESTRUCT DESTRUCT computer + D DOCK (none) + E EMEXIT (none) + FREEZE FREEZE (none) + I IMPULSE impulse engines + IMPULSE AUTOMATIC impulse engines and computer + L LRSCAN long-range sensors + MI MINE (none) + M MOVE warp engines + MOVE AUTOMATIC warp engines and computer + O ORBIT warp or impulse engines + P PHASERS phasers and computer + PHASERS AUTOMATIC phasers, computer, sr sensors + PHASERS MANUAL ... phasers + PHO PHOTONS torpedo tubes + PL PLANETS (none) + PR PROBE probe launcher, radio + PROBE AUTOMATIC launcher, radio, computer + REP REPORT (none) + REQ REQUEST (none) + R REST (none) + QUIT QUIT (none) + S SRSCAN short-range sensors + SE SENSORS short-range sensors + SH SHIELDS deflector shields + SHU SHUTTLE shuttle craft + ST STATUS (none) + T TRANSPORT transporter + W WARP (none) + + L. R. Scan: thousands digit: supernova + hundreds digit: Klingons + tens digit: starbases + ones digit: stars + period (.): digit not known (star chart only) + +Courses are given in manual mode in X - Y displacements; in automatic + mode as destination quadrant and/or sector. Manual mode is default. +Distances are given in quadrants. A distance of one sector is 0.1 quadrant. +Ordinary Klingons have about 400 units of energy, Commanders about + 1200. Romulans normally have about 800 units of energy, and the + (GULP) "Super-Commander" has about 1800. +Phaser fire diminishes to about 60 percent at 5 sectors. Up to 1500 + units may be fired in a single burst without danger of overheat. +Warp 6 is the fastest safe speed. At higher speeds, engine damage + may occur. At warp 10 you may enter a time warp. +Shields cost 50 units of energy to raise, and double the power + requirements of moving under warp drive. Engaging the high-speed + shield control requires 200 units of energy. +Warp drive requires (distance)*(warp factor cubed) units of energy + to travel at a speed of (warp factor squared)/10 quadrants per stardate. +Impulse engines require 20 units to warm up, plus 100 units per + quadrant. Speed is just under one sector per stardate. + ********MODIFICATIONS******** 25 + +Back in (about) 1977 I got a copy of this Super Star Trek game for +the CDC 6600 mainframe computer. Someone had converted it to PDP-11 +Fortran but couldn't get it to run because of its size. I modified +the program to use overlays and managed to shoehorn it in on the 56k +byte machine. + +I liked the game so much I put some time into fixing bugs, mainly +what could be called continuity errors and loopholes in the game's +logic. We even played a couple tournaments. + +In 1979, I lost access to that PDP-11. I did save the source code +listing. In 1995, missing that old friend, I started converting the +program into portable ANSI C. It's been slow, tedious work that took +over a year to accomplish. + +In early 1997, I got the bright idea to look for references to "Super +Star Trek" on the World Wide Web. There weren't many hits, but there +was one that came up with 1979 Fortran sources! This version had a +few additional features that mine didn't have, however mine had some +feature it didn't have. So I merged its features that I liked. I also +took a peek at the DECUS version (a port, less sources, to the +PDP-10), and some other variations. + +Modifications I made: + + 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". + + I added EMEXIT from the 1979 version. + + 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. + + It also had some added logic to spread the initial positioning of + bases. That made sense to add because most people abort games with + bad base placement. + + The experimental deathray originally had only a 5% chance of success, + but could be used repeatedly. I guess after a couple years of use, it + was less "experimental" because the 1979 version had a 70% success + rate. However it was prone to breaking after use. I upgraded the + deathray, but kept the original set of failure modes (great humor!). + + I put in the Tholian Web code from the 1979 version. + + I added code so that Romulans and regular Klingons could move in + advanced games. I re-enabled the code which allows enemy ships to + ram the Enterprise; it had never worked right. The 1979 version + seems to have it all fixed up, but I'm still not overly happy with + the algorithm. + + The DECUS version had a Deep Space Probe. Looked like a good idea + so I implimented it based on its description. + + + ----------ACKNOWLEDGMENTS---------- 26 + +The authors would like to thank Professor Michael Duggan for his +encouragement and administrative assistance with the development of +the Star Trek game, without which it might never have been completed. + +Much credit is due to Patrick McGehearty and Rich Cohen, who assisted +with the original design of the game and contributed greatly to its +conceptual development. + +Thanks are also due to Carl Strange, Hardy Tichenor and Steven Bruell +for their assistance with certain coding problems. + +This game was inspired by and rather loosely based on an earlier +game, programmed in the BASIC language, by Jim Korp and Grady Hicks. +It is the authors' understanding that the BASIC game was in turn +derived from a still earlier version in use at Penn State University. + + + + + ----------REFERENCES---------- + + + 1. "Star Trek" (the original television series), produced and + directed by Gene Rodenberry. + + 2. "Star Trek" (the animated television series), produced by Gene + Rodenberry and directed by Hal Sutherland. Also excellent, + and not just kiddie fare. If you enjoyed the original series + you should enjoy this one (unless you have some sort of a + hangup about watching cartoons). + + 3. "The Making of Star Trek", by Steven E. Whitfield and Gene + Rodenberry. The best and most complete readily available + book about Star Trek. (Ballantine Books) + + 4. "The World of Star Trek", by David Gerrold. Similiar in scope + to the above book. (Bantam) + + 5. "The Star Trek Guide", third revision 4/17/67, by Gene + Rodenberry. The original writer's guide for the television + series, but less comprehensive than (3) above. + (Norway Productions) + + 6. "The Trouble With Tribbles", by David Gerrold. Includes the + complete script of this popular show. (Ballantine Books) + + 7. "Star Trek", "Star Trek 2", ..., "Star Trek 9", by James Blish. + The original shows in short story form. (Bantam) + + 8. "Spock Must Die", by James Blish. An original novel, but + rather similar to the show "The Enemy Within". (Bantam) + + 9. Model kits of the Enterprise and a "Klingon Battle-Cruiser" + by AMT Corporation are available at most hobby shops. diff --git a/sst.h b/sst.h new file mode 100644 index 0000000..dcbb14d --- /dev/null +++ b/sst.h @@ -0,0 +1,426 @@ +#include +#include +#include +#include +#ifndef INCLUDED +#define EXTERN extern +#else +#define EXTERN +#endif + +// #define DEBUG + +#define ndevice (15) // Number of devices +#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 + 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 + 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 +#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 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} FINTYPE ; + + +EXTERN double aaitem; +EXTERN char citem[10]; + + +/* 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 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"}; +#endif + +#define TRUE (1) +#define FALSE (0) + +#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(void); +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 wait(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 move(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); -- 2.31.1