From: Eric S. Raymond Date: Sun, 31 Oct 2004 14:49:26 +0000 (+0000) Subject: Initial commit of Tom Almy's version plus sst.doc. X-Git-Tag: 2.0~459 X-Git-Url: https://jxself.org/git/?p=super-star-trek.git;a=commitdiff_plain;h=b0629033955fcfdcd93a4a2cf3ab29e8adc56200 Initial commit of Tom Almy's version plus sst.doc. --- b0629033955fcfdcd93a4a2cf3ab29e8adc56200 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);