Initial commit of Tom Almy's version plus sst.doc.
authorEric S. Raymond <esr@thyrsus.com>
Sun, 31 Oct 2004 14:49:26 +0000 (14:49 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Sun, 31 Oct 2004 14:49:26 +0000 (14:49 +0000)
16 files changed:
MAKEFILE.DOS [new file with mode: 0644]
MAKEFILE.OS2 [new file with mode: 0644]
ai.c [new file with mode: 0644]
battle.c [new file with mode: 0644]
events.c [new file with mode: 0644]
finish.c [new file with mode: 0644]
linux.c [new file with mode: 0644]
makefile [new file with mode: 0644]
moving.c [new file with mode: 0644]
os2.c [new file with mode: 0644]
planets.c [new file with mode: 0644]
reports.c [new file with mode: 0644]
setup.c [new file with mode: 0644]
sst.c [new file with mode: 0644]
sst.doc [new file with mode: 0644]
sst.h [new file with mode: 0644]

diff --git a/MAKEFILE.DOS b/MAKEFILE.DOS
new file mode 100644 (file)
index 0000000..e7e4821
--- /dev/null
@@ -0,0 +1,14 @@
+MODEL=m\r
+CFLAGS=-f87 -2 -m$(MODEL)\r
+\r
+.c.obj:; bcc $(CFLAGS) -c $*.c\r
+\r
+OBJS= sst.obj setup.obj reports.obj finish.obj moving.obj\\r
+ battle.obj events.obj ai.obj planets.obj\r
+\r
+sst.exe:       $(OBJS) sst.lnk\r
+       bcc @sst.lnk\r
+\r
+\r
+sst.lnk:       makefile\r
+       >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 (file)
index 0000000..59f7dbb
--- /dev/null
@@ -0,0 +1,17 @@
+CFLAGS=     -O\r
+\r
+.SUFFIXES: .o .c .s .exe\r
+\r
+.c.o:\r
+       $(CC) $(CFLAGS) -c $<\r
+\r
+OFILES=     sst.o finish.o reports.o setup.o os2.o moving.o battle.o events.o ai.o planets.o\r
+\r
+HFILES=     sst.h\r
+\r
+sstos2.exe:  $(OFILES)\r
+       gcc  -o sstos2.exe $(OFILES)\r
+\r
+        \r
+$(OFILES):  $(HFILES)\r
+\r
diff --git a/ai.c b/ai.c
new file mode 100644 (file)
index 0000000..de54e7b
--- /dev/null
+++ b/ai.c
@@ -0,0 +1,610 @@
+#include "sst.h"\r
+\r
+static int tryexit(int lookx, int looky, int ienm, int loccom, int irun) {\r
+       int iqx, iqy, l;\r
+\r
+       iqx = quadx+(lookx+9)/10 - 1;\r
+       iqy = quady+(looky+9)/10 - 1;\r
+       if (iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||\r
+               d.galaxy[iqx][iqy] > 899)\r
+               return 0; /* no can do -- neg energy, supernovae, or >8 Klingons */\r
+       if (ienm == IHR) return 0; /* Romulans cannot escape! */\r
+       if (irun == 0) {\r
+               /* avoid intruding on another commander's territory */\r
+               if (ienm == IHC) {\r
+                       for (l = 1; l <= d.remcom; l++)\r
+                               if (d.cx[l]==iqx && d.cy[l]==iqy) return 0;\r
+                       /* refuse to leave if currently attacking starbase */\r
+                       if (batx==quadx && baty==quady) return 0;\r
+               }\r
+               /* don't leave if over 1000 units of energy */\r
+               if (kpower[loccom] > 1000.) return 0;\r
+       }\r
+       /* print escape message and move out of quadrant.\r
+          We know this if either short or long range sensors are working */\r
+       if (damage[DSRSENS] == 0.0 || damage[DLRSENS] == 0.0 ||\r
+               condit == IHDOCKED) {\r
+               proutn("***");\r
+               cramen(ienm);\r
+               proutn(" escapes to");\r
+               cramlc(1, iqx, iqy);\r
+               prout(" (and regains strength).");\r
+       }\r
+       /* handle local matters related to escape */\r
+       kx[loccom] = kx[nenhere];\r
+       ky[loccom] = ky[nenhere];\r
+       kavgd[loccom] = kavgd[nenhere];\r
+       kpower[loccom] = kpower[nenhere];\r
+       kdist[loccom] = kdist[nenhere];\r
+       klhere--;\r
+       nenhere--;\r
+       if (condit != IHDOCKED) newcnd();\r
+       /* Handle global matters related to escape */\r
+       d.galaxy[quadx][quady] -= 100;\r
+       d.galaxy[iqx][iqy] += 100;\r
+       if (ienm==IHS) {\r
+               ishere=0;\r
+               iscate=0;\r
+               ientesc=0;\r
+               isatb=0;\r
+               future[FSCMOVE]=0.2777+d.date;\r
+               future[FSCDBAS]=1e30;\r
+               d.isx=iqx;\r
+               d.isy=iqy;\r
+       }\r
+       else {\r
+               for (l=1; l<=d.remcom; l++) {\r
+                       if (d.cx[l]==quadx && d.cy[l]==quady) {\r
+                               d.cx[l]=iqx;\r
+                               d.cy[l]=iqy;\r
+                               break;\r
+                       }\r
+               }\r
+               comhere = 0;\r
+       }\r
+       return 1; /* success */\r
+}\r
+\r
+\r
+static void movebaddy(int comx, int comy, int loccom, int ienm) {\r
+       int motion, mdist, nsteps, mx, my, nextx, nexty, lookx, looky, ll;\r
+       int irun = 0;\r
+       int krawlx, krawly;\r
+       int success;\r
+       int attempts;\r
+       /* This should probably be just comhere + ishere */\r
+       int nbaddys = skill > 3 ?\r
+                                 (int)((comhere*2 + ishere*2+klhere*1.23+irhere*1.5)/2.0):\r
+                                 (comhere + ishere);\r
+       double dist1, forces;\r
+\r
+       dist1 = kdist[loccom];\r
+       mdist = dist1 + 0.5; /* Nearest integer distance */\r
+\r
+       /* If SC, check with spy to see if should hi-tail it */\r
+       if (ienm==IHS &&\r
+               (kpower[loccom] <= 500.0 || (condit==IHDOCKED && damage[DPHOTON]==0))) {\r
+               irun = 1;\r
+               motion = -10;\r
+       }\r
+       else {\r
+               /* decide whether to advance, retreat, or hold position */\r
+/* Algorithm:\r
+   * Enterprise has "force" based on condition of phaser and photon torpedoes.\r
+     If both are operating full strength, force is 1000. If both are damaged,\r
+        force is -1000. Having shields down subtracts an additional 1000.\r
+\r
+   * Enemy has forces equal to the energy of the attacker plus\r
+     100*(K+R) + 500*(C+S) - 400 for novice through good levels OR\r
+        346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.\r
+\r
+        Attacker Initial energy levels (nominal):\r
+                 Klingon   Romulan   Commander   Super-Commander\r
+        Novice    400        700        1200        \r
+        Fair      425        750        1250\r
+        Good      450        800        1300        1750\r
+        Expert    475        850        1350        1875\r
+        Emeritus  500        900        1400        2000\r
+     VARIANCE   75        200         200         200\r
+\r
+        Enemy vessels only move prior to their attack. In Novice - Good games\r
+        only commanders move. In Expert games, all enemy vessels move if there\r
+        is a commander present. In Emeritus games all enemy vessels move.\r
+\r
+  *  If Enterprise is not docked, an agressive action is taken if enemy\r
+     forces are 1000 greater than Enterprise.\r
+\r
+        Agressive action on average cuts the distance between the ship and\r
+        the enemy to 1/4 the original.\r
+\r
+  *  At lower energy advantage, movement units are proportional to the\r
+     advantage with a 650 advantage being to hold ground, 800 to move forward\r
+        1, 950 for two, 150 for back 4, etc. Variance of 100.\r
+\r
+        If docked, is reduced by roughly 1.75*skill, generally forcing a\r
+        retreat, especially at high skill levels.\r
+\r
+  *  Motion is limited to skill level, except for SC hi-tailing it out.\r
+  */\r
+\r
+               forces = kpower[loccom]+100.0*nenhere+400*(nbaddys-1);\r
+               if (shldup==0) forces += 1000; /* Good for enemy if shield is down! */\r
+               if (damage[DPHASER] == 0.0 || damage[DPHOTON] == 0.0) {\r
+                       if (damage[DPHASER] != 0) /* phasers damaged */\r
+                               forces += 300.0;\r
+                       else\r
+                               forces -= 0.2*(energy - 2500.0);\r
+                       if (damage[DPHOTON] != 0) /* photon torpedoes damaged */\r
+                               forces += 300.0;\r
+                       else\r
+                               forces -= 50.0*torps;\r
+               }\r
+               else {\r
+                       /* phasers and photon tubes both out! */\r
+                       forces += 1000.0;\r
+               }\r
+               motion = 0;\r
+               if (forces <= 1000.0 && condit != IHDOCKED) /* Typical situation */\r
+                       motion = ((forces+200.0*Rand())/150.0) - 5.0;\r
+               else {\r
+                       if (forces > 1000.0) /* Very strong -- move in for kill */\r
+                               motion = (1.0-square(Rand()))*dist1 + 1.0;\r
+                       if (condit==IHDOCKED) /* protected by base -- back off ! */\r
+                               motion -= skill*(2.0-square(Rand()));\r
+               }\r
+#ifdef DEBUG\r
+               if (idebug) {\r
+                       proutn("MOTION = ");\r
+                       cramf(motion, 1, 2);\r
+            proutn("  FORCES = ");\r
+                       cramf(forces, 1, 2);\r
+                       skip(1);\r
+               }\r
+#endif\r
+               /* don't move if no motion */\r
+               if (motion==0) return;\r
+               /* Limit motion according to skill */\r
+               if (abs(motion) > skill) motion = (motion < 0) ? -skill : skill;\r
+       }\r
+       /* calcuate preferred number of steps */\r
+       nsteps = motion < 0 ? -motion : motion;\r
+       if (motion > 0 && nsteps > mdist) nsteps = mdist; /* don't overshoot */\r
+       if (nsteps > 10) nsteps = 10; /* This shouldn't be necessary */\r
+       if (nsteps < 1) nsteps = 1; /* This shouldn't be necessary */\r
+#ifdef DEBUG\r
+       if (idebug) {\r
+               proutn("NSTEPS = ");\r
+               crami(nsteps, 1);\r
+               skip(1);\r
+       }\r
+#endif\r
+       /* Compute preferred values of delta X and Y */\r
+       mx = sectx - comx;\r
+       my = secty - comy;\r
+       if (2.0 * abs(mx) < abs(my)) mx = 0;\r
+       if (2.0 * abs(my) < abs(sectx-comx)) my = 0;\r
+       if (mx != 0) mx = mx*motion < 0 ? -1 : 1;\r
+       if (my != 0) my = my*motion < 0 ? -1 : 1;\r
+       nextx = comx;\r
+       nexty = comy;\r
+       quad[comx][comy] = IHDOT;\r
+       /* main move loop */\r
+       for (ll = 1; ll <= nsteps; ll++) {\r
+#ifdef DEBUG\r
+               if (idebug) {\r
+                       crami(ll,2);\r
+                       skip(1);\r
+               }\r
+#endif\r
+               /* Check if preferred position available */\r
+               lookx = nextx + mx;\r
+               looky = nexty + my;\r
+               krawlx = mx < 0 ? 1 : -1;\r
+               krawly = my < 0 ? 1 : -1;\r
+               success = 0;\r
+               attempts = 0; /* Settle mysterious hang problem */\r
+               while (attempts++ < 20 && !success) {\r
+                       if (lookx < 1 || lookx > 10) {\r
+                               if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))\r
+                                       return;\r
+                               if (krawlx == mx || my == 0) break;\r
+                               lookx = nextx + krawlx;\r
+                               krawlx = -krawlx;\r
+                       }\r
+                       else if (looky < 1 || looky > 10) {\r
+                               if (motion < 0 && tryexit(lookx, looky, ienm, loccom, irun))\r
+                                       return;\r
+                               if (krawly == my || mx == 0) break;\r
+                               looky = nexty + krawly;\r
+                               krawly = -krawly;\r
+                       }\r
+                       else if (quad[lookx][looky] != IHDOT) {\r
+                               /* See if we should ram ship */\r
+                               if (quad[lookx][looky] == ship &&\r
+                                       (ienm == IHC || ienm == IHS)) {\r
+                                       ram(1, ienm, comx, comy);\r
+                                       return;\r
+                               }\r
+                               if (krawlx != mx && my != 0) {\r
+                                       lookx = nextx + krawlx;\r
+                                       krawlx = -krawlx;\r
+                               }\r
+                               else if (krawly != my && mx != 0) {\r
+                                       looky = nexty + krawly;\r
+                                       krawly = -krawly;\r
+                               }\r
+                               else break; /* we have failed */\r
+                       }\r
+                       else success = 1;\r
+               }\r
+               if (success) {\r
+                       nextx = lookx;\r
+                       nexty = looky;\r
+#ifdef DEBUG\r
+                       if (idebug) {\r
+                               cramlc(0, nextx, nexty);\r
+                               skip(1);\r
+                       }\r
+#endif\r
+               }\r
+               else break; /* done early */\r
+       }\r
+       /* Put commander in place within same quadrant */\r
+       quad[nextx][nexty] = ienm;\r
+       if (nextx != comx || nexty != comy) {\r
+               /* it moved */\r
+               kx[loccom] = nextx;\r
+               ky[loccom] = nexty;\r
+               kdist[loccom] = kavgd[loccom] =\r
+                                       sqrt(square(sectx-nextx)+square(secty-nexty));\r
+               if (damage[DSRSENS] == 0 || condit == IHDOCKED) {\r
+                       proutn("***");\r
+                       cramen(ienm);\r
+                       if (kdist[loccom] < dist1) proutn(" advances to");\r
+                       else proutn(" retreats to");\r
+                       cramlc(2, nextx, nexty);\r
+                       skip(1);\r
+               }\r
+       }\r
+}\r
+\r
+void movcom(void) {\r
+       int ix, iy, i;\r
+\r
+#ifdef DEBUG\r
+       if (idebug) prout("MOVCOM");\r
+#endif\r
+\r
+       /* Figure out which Klingon is the commander (or Supercommander)\r
+          and do move */\r
+       if (comhere) for (i = 1; i <= nenhere; i++) {\r
+               ix = kx[i];\r
+               iy = ky[i];\r
+               if (quad[ix][iy] == IHC) {\r
+                       movebaddy(ix, iy, i, IHC);\r
+                       break;\r
+               }\r
+       }\r
+       if (ishere) for (i = 1; i <= nenhere; i++) {\r
+               ix = kx[i];\r
+               iy = ky[i];\r
+               if (quad[ix][iy] == IHS) {\r
+                       movebaddy(ix, iy, i, IHS);\r
+                       break;\r
+               }\r
+       }\r
+       /* if skill level is high, move other Klingons and Romulans too!\r
+          Move these last so they can base their actions on what the\r
+       commander(s) do. */\r
+       if (skill > 3) for (i = 1; i <= nenhere; i++) {\r
+               ix = kx[i];\r
+               iy = ky[i];\r
+               if (quad[ix][iy] == IHK || quad[ix][iy] == IHR)\r
+                       movebaddy(ix, iy, i, quad[ix][iy]);\r
+       }\r
+\r
+       sortkl();\r
+}\r
+\r
+static int checkdest(int iqx, int iqy, int flag, int *ipage) {\r
+       int i, j;\r
+\r
+       if ((iqx==quadx && iqy==quady) ||\r
+               iqx < 1 || iqx > 8 || iqy < 1 || iqy > 8 ||\r
+               d.galaxy[iqx][iqy] > 899) return 1;\r
+       if (flag) {\r
+               /* Avoid quadrants with bases if we want to avoid Enterprise */\r
+               for (i = 1; i <= d.rembase; i++)\r
+                       if (d.baseqx[i]==iqx && d.baseqy[i]==iqy) return 1;\r
+       }\r
+\r
+       /* do the move */\r
+       d.galaxy[d.isx][d.isy] -= 100;\r
+       d.isx = iqx;\r
+       d.isy = iqy;\r
+       d.galaxy[d.isx][d.isy] += 100;\r
+       if (iscate) {\r
+               /* SC has scooted, Remove him from current quadrant */\r
+               iscate=0;\r
+               isatb=0;\r
+               ishere=0;\r
+               ientesc=0;\r
+               future[FSCDBAS]=1e30;\r
+               for (i = 1; i <= nenhere; i++) \r
+                       if (quad[kx[i]][ky[i]] == IHS) break;\r
+               quad[kx[i]][ky[i]] = IHDOT;\r
+               kx[i] = kx[nenhere];\r
+               ky[i] = ky[nenhere];\r
+               kdist[i] = kdist[nenhere];\r
+               kavgd[i] = kavgd[nenhere];\r
+               kpower[i] = kpower[nenhere];\r
+               klhere--;\r
+               nenhere--;\r
+               if (condit!=IHDOCKED) newcnd();\r
+               sortkl();\r
+       }\r
+       /* check for a helpful planet */\r
+       for (i = 1; i <= inplan; i++) {\r
+               if (d.plnets[i].x==d.isx && d.plnets[i].y==d.isy &&\r
+                       d.plnets[i].crystals == 1) {\r
+                       /* destroy the planet */\r
+                       d.plnets[i] = nulplanet;\r
+                       d.newstuf[d.isx][d.isy] -= 1;\r
+                       if (damage[DRADIO] == 0.0 || condit == IHDOCKED) {\r
+                               if (*ipage==0) pause(1);\r
+                               *ipage = 1;\r
+                               prout("Lt. Uhura-  \"Captain, Starfleet Intelligence reports");\r
+                               proutn("   a planet in");\r
+                               cramlc(1, d.isx, d.isy);\r
+                               prout(" has been destroyed");\r
+                               prout("   by the Super-commander.\"");\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+       return 0; /* looks good! */\r
+}\r
+                       \r
+               \r
+       \r
+\r
+\r
+void scom(int *ipage) {\r
+       int i, i2, j, ideltax, ideltay, ibqx, ibqy, sx, sy, ifindit, iwhichb;\r
+       int iqx, iqy;\r
+       int basetbl[6];\r
+       double bdist[6];\r
+       int flag;\r
+#ifdef DEBUG\r
+       if (idebug) prout("SCOM");\r
+#endif\r
+\r
+       /* Decide on being active or passive */\r
+       flag = ((d.killc+d.killk)/(d.date+0.01-indate) < 0.1*skill*(skill+1.0) ||\r
+                       (d.date-indate) < 3.0);\r
+       if (iscate==0 && flag) {\r
+               /* compute move away from Enterprise */\r
+               ideltax = d.isx-quadx;\r
+               ideltay = d.isy-quady;\r
+               if (sqrt(ideltax*(double)ideltax+ideltay*(double)ideltay) > 2.0) {\r
+                       /* circulate in space */\r
+                       ideltax = d.isy-quady;\r
+                       ideltay = quadx-d.isx;\r
+               }\r
+       }\r
+       else {\r
+               /* compute distances to starbases */\r
+               if (d.rembase <= 0) {\r
+                       /* nothing left to do */\r
+                       future[FSCMOVE] = 1e30;\r
+                       return;\r
+               }\r
+               sx = d.isx;\r
+               sy = d.isy;\r
+               for (i = 1; i <= d.rembase; i++) {\r
+                       basetbl[i] = i;\r
+                       ibqx = d.baseqx[i];\r
+                       ibqy = d.baseqy[i];\r
+                       bdist[i] = sqrt(square(ibqx-sx) + square(ibqy-sy));\r
+               }\r
+               if (d.rembase > 1) {\r
+                       /* sort into nearest first order */\r
+                       int iswitch;\r
+                       do {\r
+                               iswitch = 0;\r
+                               for (i=1; i < d.rembase-1; i++) {\r
+                                       if (bdist[i] > bdist[i+1]) {\r
+                                               int ti = basetbl[i];\r
+                                               double t = bdist[i];\r
+                                               bdist[i] = bdist[i+1];\r
+                                               bdist[i+1] = t;\r
+                                               basetbl[i] = basetbl[i+1];\r
+                                               basetbl[i+1] =ti;\r
+                                               iswitch = 1;\r
+                                       }\r
+                               }\r
+                       } while (iswitch);\r
+               }\r
+               /* look for nearest base without a commander, no Enterprise, and\r
+                  without too many Klingons, and not already under attack. */\r
+               ifindit = iwhichb = 0;\r
+\r
+               for (i2 = 1; i2 <= d.rembase; i2++) {\r
+                       i = basetbl[i2];        /* bug in original had it not finding nearest*/\r
+                       ibqx = d.baseqx[i];\r
+                       ibqy = d.baseqy[i];\r
+                       if ((ibqx == quadx && ibqy == quady) ||\r
+                               (ibqx == batx && ibqy == baty) ||\r
+                               d.galaxy[ibqx][ibqy] > 899) continue;\r
+                       /* if there is a commander, an no other base is appropriate,\r
+                          we will take the one with the commander */\r
+                       for (j = 1; j <= d.remcom; j++) {\r
+                               if (ibqx==d.cx[j] && ibqy==d.cy[j] && ifindit!= 2) {\r
+                                               ifindit = 2;\r
+                                               iwhichb = i;\r
+                                               break;\r
+                               }\r
+                       }\r
+                       if (j > d.remcom) { /* no commander -- use this one */\r
+                               ifindit = 1;\r
+                               iwhichb = i;\r
+                               break;\r
+                       }\r
+               }\r
+               if (ifindit==0) return; /* Nothing suitable -- wait until next time*/\r
+               ibqx = d.baseqx[iwhichb];\r
+               ibqy = d.baseqy[iwhichb];\r
+               /* decide how to move toward base */\r
+               ideltax = ibqx - d.isx;\r
+               ideltay = ibqy - d.isy;\r
+       }\r
+       /* Maximum movement is 1 quadrant in either or both axis */\r
+       if (ideltax > 1) ideltax = 1;\r
+       if (ideltax < -1) ideltax = -1;\r
+       if (ideltay > 1) ideltay = 1;\r
+       if (ideltay < -1) ideltay = -1;\r
+\r
+       /* try moving in both x and y directions */\r
+       iqx = d.isx + ideltax;\r
+       iqy = d.isy + ideltax;\r
+       if (checkdest(iqx, iqy, flag, ipage)) {\r
+               /* failed -- try some other maneuvers */\r
+               if (ideltax==0 || ideltay==0) {\r
+                       /* attempt angle move */\r
+                       if (ideltax != 0) {\r
+                               iqy = d.isy + 1;\r
+                               if (checkdest(iqx, iqy, flag, ipage)) {\r
+                                       iqy = d.isy - 1;\r
+                                       checkdest(iqx, iqy, flag, ipage);\r
+                               }\r
+                       }\r
+                       else {\r
+                               iqx = d.isx + 1;\r
+                               if (checkdest(iqx, iqy, flag, ipage)) {\r
+                                       iqx = d.isx - 1;\r
+                                       checkdest(iqx, iqy, flag, ipage);\r
+                               }\r
+                       }\r
+               }\r
+               else {\r
+                       /* try moving just in x or y */\r
+                       iqy = d.isy;\r
+                       if (checkdest(iqx, iqy, flag, ipage)) {\r
+                               iqy = d.isy + ideltay;\r
+                               iqx = d.isx;\r
+                               checkdest(iqx, iqy, flag, ipage);\r
+                       }\r
+               }\r
+       }\r
+       /* check for a base */\r
+       if (d.rembase == 0) {\r
+               future[FSCMOVE] = 1e30;\r
+       }\r
+       else for (i=1; i<=d.rembase; i++) {\r
+               ibqx = d.baseqx[i];\r
+               ibqy = d.baseqy[i];\r
+               if (ibqx==d.isx && ibqy == d.isy && d.isx != batx && d.isy != baty) {\r
+                       /* attack the base */\r
+                       if (flag) return; /* no, don't attack base! */\r
+                       iseenit = 0;\r
+                       isatb=1;\r
+                       future[FSCDBAS] = d.date + 1.0 +2.0*Rand();\r
+                       if (batx != 0) future[FSCDBAS] += future[FCDBAS]-d.date;\r
+                       if (damage[DRADIO] > 0 && condit != IHDOCKED)\r
+                               return; /* no warning */\r
+                       iseenit = 1;\r
+                       if (*ipage == 0)  pause(1);\r
+                       *ipage=1;\r
+                       proutn("Lt. Uhura-  \"Captain, the starbase in");\r
+                       cramlc(1, d.isx, d.isy);\r
+                       skip(1);\r
+                       prout("   reports that it is under attack from the Klingon Super-commander.");\r
+                       proutn("   It can survive until stardate ");\r
+                       cramf(future[FSCDBAS], 0, 1);\r
+                       prout(" .\"");\r
+                       if (resting==0) return;\r
+                       prout("Mr. Spock-  \"Captain, shall we cancel the rest period?\"");\r
+                       if (ja()==0) return;\r
+                       resting = 0;\r
+                       Time = 0.0; /* actually finished */\r
+                       return;\r
+               }\r
+       }\r
+       /* Check for intelligence report */\r
+       if (\r
+#ifdef DEBUG\r
+               idebug==0 &&\r
+#endif\r
+               (Rand() > 0.2 ||\r
+                (damage[DRADIO] > 0.0 && condit != IHDOCKED) ||\r
+                starch[d.isx][d.isy] > 0))\r
+               return;\r
+       if (*ipage==0) pause(1);\r
+       *ipage = 1;\r
+       prout("Lt. Uhura-  \"Captain, Starfleet Intelligence reports");\r
+       proutn("   the Super-commander is in");\r
+       cramlc(1, d.isx, d.isy);\r
+       prout(".\"");\r
+       return;\r
+}\r
+\r
+void movetho(void) {\r
+       int idx, idy, im, i, dum, my;\r
+       /* Move the Tholean */\r
+       if (ithere==0 || justin == 1) return;\r
+\r
+       if (ithx == 1 && ithy == 1) {\r
+               idx = 1; idy = 10;\r
+       }\r
+       else if (ithx == 1 && ithy == 10) {\r
+               idx = 10; idy = 10;\r
+       }\r
+       else if (ithx == 10 && ithy == 10) {\r
+               idx = 10; idy = 1;\r
+       }\r
+       else if (ithx == 10 && ithy == 1) {\r
+               idx = 1; idy = 1;\r
+       }\r
+       else {\r
+               /* something is wrong! */\r
+               ithere = 0;\r
+               return;\r
+       }\r
+\r
+       /* Do nothing if we are blocked */\r
+       if (quad[idx][idy]!= IHDOT && quad[idx][idy]!= IHWEB) return;\r
+       quad[ithx][ithy] = IHWEB;\r
+\r
+       if (ithx != idx) {\r
+               /* move in x axis */\r
+               im = fabs((double)idx - ithx)/((double)idx - ithx);\r
+               while (ithx != idx) {\r
+                       ithx += im;\r
+                       if (quad[ithx][ithy]==IHDOT) quad[ithx][ithy] = IHWEB;\r
+               }\r
+       }\r
+       else if (ithy != idy) {\r
+               /* move in y axis */\r
+               im = fabs((double)idy - ithy)/((double)idy - ithy);\r
+               while (ithy != idy) {\r
+                       ithy += im;\r
+                       if (quad[ithx][ithy]==IHDOT) quad[ithx][ithy] = IHWEB;\r
+               }\r
+       }\r
+       quad[ithx][ithy] = IHT;\r
+\r
+       /* check to see if all holes plugged */\r
+       for (i = 1; i < 11; i++) {\r
+               if (quad[1][i]!=IHWEB && quad[1][i]!=IHT) return;\r
+               if (quad[10][i]!=IHWEB && quad[10][i]!=IHT) return;\r
+               if (quad[i][1]!=IHWEB && quad[i][1]!=IHT) return;\r
+               if (quad[i][10]!=IHWEB && quad[i][10]!=IHT) return;\r
+       }\r
+       /* All plugged up -- Tholian splits */\r
+       quad[ithx][ithy]=IHWEB;\r
+       dropin(IHBLANK, &dum, &my);\r
+       crmena(1,IHT, 2, ithx, ithy);\r
+       prout(" completes web.");\r
+       ithere = ithx = ithy = 0;\r
+       return;\r
+}\r
diff --git a/battle.c b/battle.c
new file mode 100644 (file)
index 0000000..e9cc2f6
--- /dev/null
+++ b/battle.c
@@ -0,0 +1,1214 @@
+#include "sst.h"\r
+\r
+void sheild(int i) {\r
+       int key;\r
+       enum {NONE, SHUP, SHDN, NRG} action = NONE;\r
+\r
+       ididit = 0;\r
+\r
+       if (i == 2) action = SHUP;\r
+       else {\r
+               key = scan();\r
+               if (key == IHALPHA) {\r
+                       if (isit("transfer"))\r
+                               action = NRG;\r
+                       else {\r
+                               chew();\r
+                               if (damage[DSHIELD]) {\r
+                                       prout("Shields damaged and down.");\r
+                                       return;\r
+                               }\r
+                               if (isit("up"))\r
+                                       action = SHUP;\r
+                               else if (isit("down"))\r
+                                       action = SHDN;\r
+                       }\r
+               }\r
+               if (action==NONE) {\r
+                       proutn("Do you wish to change shield energy? ");\r
+                       if (ja()) {\r
+                               proutn("Energy to transfer to shields- ");\r
+                               action = NRG;\r
+                       }\r
+                       else if (damage[DSHIELD]) {\r
+                               prout("Shields damaged and down.");\r
+                               return;\r
+                       }\r
+                       else if (shldup) {\r
+                               proutn("Shields are up. Do you want them down? ");\r
+                               if (ja()) action = SHDN;\r
+                               else {\r
+                                       chew();\r
+                                       return;\r
+                               }\r
+                       }\r
+                       else {\r
+                               proutn("Shields are down. Do you want them up? ");\r
+                               if (ja()) action = SHUP;\r
+                               else {\r
+                                       chew();\r
+                                       return;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       switch (action) {\r
+               case SHUP: /* raise shields */\r
+                       if (shldup) {\r
+                               prout("Shields already up.");\r
+                               return;\r
+                       }\r
+                       shldup = 1;\r
+                       shldchg = 1;\r
+                       if (condit != IHDOCKED) energy -= 50.0;\r
+                       prout("Shields raised.");\r
+                       if (energy <= 0) {\r
+                               skip(1);\r
+                               prout("Shields raising uses up last of energy.");\r
+                               finish(FNRG);\r
+                               return;\r
+                       }\r
+                       ididit=1;\r
+                       return;\r
+               case SHDN:\r
+                       if (shldup==0) {\r
+                               prout("Shields already down.");\r
+                               return;\r
+                       }\r
+                       shldup=0;\r
+                       shldchg=1;\r
+                       prout("Shields lowered.");\r
+                       ididit=1;\r
+                       return;\r
+               case NRG:\r
+                       while (scan() != IHREAL) {\r
+                               chew();\r
+                               proutn("Energy to transfer to shields- ");\r
+                       }\r
+                       chew();\r
+                       if (aaitem==0) return;\r
+                       if (aaitem > energy) {\r
+                               prout("Insufficient ship energy.");\r
+                               return;\r
+                       }\r
+                       ididit = 1;\r
+                       if (shield+aaitem >= inshld) {\r
+                               prout("Shield energy maximized.");\r
+                               if (shield+aaitem > inshld) {\r
+                                       prout("Excess energy requested returned to ship energy");\r
+                               }\r
+                               energy -= inshld-shield;\r
+                               shield = inshld;\r
+                               return;\r
+                       }\r
+                       if (aaitem < 0.0 && energy-aaitem > inenrg) {\r
+                               /* Prevent shield drain loophole */\r
+                               skip(1);\r
+                               prout("Engineering to bridge--");\r
+                               prout("  Scott here. Power circuit problem, Captain.");\r
+                               prout("  I can't drain the shields.");\r
+                               ididit = 0;\r
+                               return;\r
+                       }\r
+                       if (shield+aaitem < 0) {\r
+                               prout("All shield energy transferred to ship.");\r
+                               energy += shield;\r
+                               shield = 0.0;\r
+                               return;\r
+                       }\r
+                       proutn("Scotty- \"");\r
+                       if (aaitem > 0)\r
+                               prout("Transferring energy to shields.\"");\r
+                       else\r
+                               prout("Draining energy from shields.\"");\r
+                       shield += aaitem;\r
+                       energy -= aaitem;\r
+                       return;\r
+       }\r
+}\r
+\r
+void ram(int ibumpd, int ienm, int ix, int iy) {\r
+       double type = 1.0, extradm;\r
+       int icas, l;\r
+       \r
+       prouts("***RED ALERT!  RED ALERT!");\r
+       skip(1);\r
+       prout("***COLLISION IMMINENT.");\r
+       skip(2);\r
+       proutn("***");\r
+       crmshp();\r
+       switch (ienm) {\r
+               case IHR: type = 1.5; break;\r
+               case IHC: type = 2.0; break;\r
+               case IHS: type = 2.5; break;\r
+               case IHT: type = 0.5; break;\r
+       }\r
+       proutn(ibumpd ? " rammed by " : " rams ");\r
+       crmena(0, ienm, 2, ix, iy);\r
+       if (ibumpd) proutn(" (original position)");\r
+       skip(1);\r
+       deadkl(ix, iy, ienm, sectx, secty);\r
+       proutn("***");\r
+       crmshp();\r
+       prout(" heavily damaged.");\r
+       icas = 10.0+20.0*Rand();\r
+       proutn("***Sickbay reports ");\r
+       crami(icas, 1);\r
+       prout(" casualties.");\r
+       casual += icas;\r
+       for (l=1; l <= ndevice; l++) {\r
+               if (l == DDRAY) continue; // Don't damage deathray \r
+               if (damage[l] < 0) continue;\r
+               extradm = (10.0*type*Rand()+1.0)*damfac;\r
+               damage[l] += Time + extradm; /* Damage for at least time of travel! */\r
+       }\r
+       shldup = 0;\r
+       if (d.remkl) {\r
+               pause(2);\r
+               dreprt();\r
+       }\r
+       else finish(FWON);\r
+       return;\r
+}\r
+\r
+void torpedo(double course, double r, int inx, int iny, double *hit) {\r
+       int l, iquad, ix, iy,  jx, jy, shoved=0, ll;\r
+       double ac=course + 0.25*r;\r
+       double angle = (15.0-ac)*0.5235988;\r
+       double bullseye = (15.0 - course)*0.5235988;\r
+       double deltax=-sin(angle), deltay=cos(angle), x=inx, y=iny, bigger;\r
+       double ang, temp, xx, yy, kp, h1;\r
+\r
+       bigger = fabs(deltax);\r
+       if (fabs(deltay) > bigger) bigger = fabs(deltay);\r
+       deltax /= bigger;\r
+       deltay /= bigger;\r
+\r
+       /* Loop to move a single torpedo */\r
+       for (l=1; l <= 15; l++) {\r
+               x += deltax;\r
+               ix = x + 0.5;\r
+               if (ix < 1 || ix > 10) break;\r
+               y += deltay;\r
+               iy = y + 0.5;\r
+               if (iy < 1 || iy > 10) break;\r
+               if (l==4 || l==9) skip(1);\r
+               cramf(x, 0, 1);\r
+               proutn(" - ");\r
+               cramf(y, 0, 1);\r
+               proutn("   ");\r
+               iquad=quad[ix][iy];\r
+               if (iquad==IHDOT) continue;\r
+               /* hit something */\r
+               skip(1);\r
+               switch(iquad) {\r
+                       case IHE: /* Hit our ship */\r
+                       case IHF:\r
+                               skip(1);\r
+                               proutn("Torpedo hits ");\r
+                               crmshp();\r
+                               prout(".");\r
+                               *hit = 700.0 + 100.0*Rand() -\r
+                                          1000.0*sqrt(square(ix-inx)+square(iy-iny))*\r
+                                          fabs(sin(bullseye-angle));\r
+                               *hit = fabs(*hit);\r
+                               newcnd(); /* undock */\r
+                               /* We may be displaced. */\r
+                               if (landed==1) return; /* Cheat if on a planet */\r
+                               ang = angle + 2.5*(Rand()-0.5);\r
+                               temp = fabs(sin(ang));\r
+                               if (fabs(cos(ang)) > temp) temp = fabs(cos(ang));\r
+                               xx = -sin(ang)/temp;\r
+                               yy = cos(ang)/temp;\r
+                               jx=ix+xx+0.5;\r
+                               jy=iy+yy+0.5;\r
+                               if (jx<1 || jx>10 || jy<1 ||jy > 10) return;\r
+                               if (quad[jx][jy]==IHBLANK) {\r
+                                       finish(FHOLE);\r
+                                       return;\r
+                               }\r
+                               if (quad[jx][jy]!=IHDOT) {\r
+                                       /* can't move into object */\r
+                                       return;\r
+                               }\r
+                               sectx = jx;\r
+                               secty = jy;\r
+                               crmshp();\r
+                               shoved = 1;\r
+                               break;\r
+                                         \r
+                       case IHC: /* Hit a commander */\r
+                       case IHS:\r
+                               if (Rand() <= 0.05) {\r
+                                       crmena(1, iquad, 2, ix, iy);\r
+                                       prout(" uses anti-photon device;");\r
+                                       prout("   torpedo neutralized.");\r
+                                       return;\r
+                               }\r
+                       case IHR: /* Hit a regular enemy */\r
+                       case IHK:\r
+                               /* find the enemy */\r
+                               for (ll=1; ll <= nenhere; ll++)\r
+                                       if (ix==kx[ll] && iy==ky[ll]) break;\r
+                               kp = fabs(kpower[ll]);\r
+                               h1 = 700.0 + 100.0*Rand() -\r
+                                        1000.0*sqrt(square(ix-inx)+square(iy-iny))*\r
+                                        fabs(sin(bullseye-angle));\r
+                               h1 = fabs(h1);\r
+                               if (kp < h1) h1 = kp;\r
+                               kpower[ll] -= (kpower[ll]<0 ? -h1 : h1);\r
+                               if (kpower[ll] == 0) {\r
+                                       deadkl(ix, iy, iquad, ix, iy);\r
+                                       return;\r
+                               }\r
+                               crmena(1, iquad, 2, ix, iy);\r
+                               /* If enemy damaged but not destroyed, try to displace */\r
+                               ang = angle + 2.5*(Rand()-0.5);\r
+                               temp = fabs(sin(ang));\r
+                               if (fabs(cos(ang)) > temp) temp = fabs(cos(ang));\r
+                               xx = -sin(ang)/temp;\r
+                               yy = cos(ang)/temp;\r
+                               jx=ix+xx+0.5;\r
+                               jy=iy+yy+0.5;\r
+                               if (jx<1 || jx>10 || jy<1 ||jy > 10) {\r
+                                       prout(" damaged but not destroyed.");\r
+                                       return;\r
+                               }\r
+                               if (quad[jx][jy]==IHBLANK) {\r
+                                       prout(" buffeted into black hole.");\r
+                                       deadkl(ix, iy, iquad, jx, jy);\r
+                                       return;\r
+                               }\r
+                               if (quad[jx][jy]!=IHDOT) {\r
+                                       /* can't move into object */\r
+                                       prout(" damaged but not destroyed.");\r
+                                       return;\r
+                               }\r
+                               prout(" damaged--");\r
+                               kx[ll] = jx;\r
+                               ky[ll] = jy;\r
+                               shoved = 1;\r
+                               break;\r
+                       case IHB: /* Hit a base */\r
+                               prout("***STARBASE DESTROYED..");\r
+                               if (starch[quadx][quady] < 0) starch[quadx][quady] = 0;\r
+                               for (ll=1; ll<=d.rembase; ll++) {\r
+                                       if (d.baseqx[ll]==quadx && d.baseqy[ll]==quady) {\r
+                                               d.baseqx[ll]=d.baseqx[d.rembase];\r
+                                               d.baseqy[ll]=d.baseqy[d.rembase];\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               quad[ix][iy]=IHDOT;\r
+                               d.rembase--;\r
+                               basex=basey=0;\r
+                               d.galaxy[quadx][quady] -= 10;\r
+                               d.basekl++;\r
+                               newcnd();\r
+                               return;\r
+                       case IHP: /* Hit a planet */\r
+                               crmena(1, iquad, 2, ix, iy);\r
+                               prout(" destroyed.");\r
+                               d.nplankl++;\r
+                               d.newstuf[quadx][quady] -= 1;\r
+                               d.plnets[iplnet] = nulplanet;\r
+                               iplnet = 0;\r
+                               plnetx = plnety = 0;\r
+                               quad[ix][iy] = IHDOT;\r
+                               if (landed==1) {\r
+                                       /* captain parishes on planet */\r
+                                       finish(FDPLANET);\r
+                               }\r
+                               return;\r
+                       case IHSTAR: /* Hit a star */\r
+                               if (Rand() > 0.10) {\r
+                                       nova(ix, iy);\r
+                                       return;\r
+                               }\r
+                               crmena(1, IHSTAR, 2, ix, iy);\r
+                               prout(" unaffected by photon blast.");\r
+                               return;\r
+                       case IHQUEST: /* Hit a thingy */\r
+                               skip(1);\r
+                               prouts("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!");\r
+                               skip(1);\r
+                               prouts("    HACK!     HACK!    HACK!        *CHOKE!*  ");\r
+                               skip(1);\r
+                               proutn("Mr. Spock-");\r
+                               prouts("  \"Facinating!\"");\r
+                               skip(1);\r
+                               quad[ix][iy] = IHDOT;\r
+                               return;\r
+                       case IHBLANK: /* Black hole */\r
+                               skip(1);\r
+                               crmena(1, IHBLANK, 2, ix, iy);\r
+                               prout(" swallows torpedo.");\r
+                               return;\r
+                       case IHWEB: /* hit the web */\r
+                               skip(1);\r
+                               prout("***Torpedo absorbed by Tholian web.");\r
+                               return;\r
+                       case IHT:  /* Hit a Tholian */\r
+                               skip(1);\r
+                               crmena(1, IHT, 2, ix, iy);\r
+                               h1 = 700.0 + 100.0*Rand() -\r
+                                        1000.0*sqrt(square(ix-inx)+square(iy-iny))*\r
+                                        fabs(sin(bullseye-angle));\r
+                               h1 = fabs(h1);\r
+                               if (h1 >= 600) {\r
+                                       prout(" destroyed.");\r
+                                       quad[ix][iy] = IHDOT;\r
+                                       ithere = 0;\r
+                                       ithx = ithy = 0;\r
+                                       return;\r
+                               }\r
+                               if (Rand() > 0.05) {\r
+                                       prout(" survives photon blast.");\r
+                                       return;\r
+                               }\r
+                               prout(" disappears.");\r
+                               quad[ix][iy] = IHWEB;\r
+                               ithere = ithx = ithy = 0;\r
+                               {\r
+                                       int dum, my;\r
+                                       dropin(IHBLANK, &dum, &my);\r
+                               }\r
+                               return;\r
+                                       \r
+                       default: /* Problem! */\r
+                               skip(1);\r
+                               proutn("Don't know how to handle collision with ");\r
+                               crmena(1, iquad, 2, ix, iy);\r
+                               skip(1);\r
+                               return;\r
+               }\r
+               break;\r
+       }\r
+       if (shoved) {\r
+               quad[jx][jy]=iquad;\r
+               quad[ix][iy]=IHDOT;\r
+               proutn(" displaced by blast to");\r
+               cramlc(2, jx, jy);\r
+               skip(1);\r
+               for (ll=1; ll<=nenhere; ll++)\r
+                       kdist[ll] = kavgd[ll] = sqrt(square(sectx-kx[ll])+square(secty-ky[ll]));\r
+               sortkl();\r
+               return;\r
+       }\r
+       skip(1);\r
+       prout("Torpedo missed.");\r
+       return;\r
+}\r
+\r
+static void fry(double hit) {\r
+       double ncrit, extradm;\r
+       int ktr=1, l, ll, j, cdam[6], crptr;\r
+\r
+       /* a critical hit occured */\r
+       if (hit < (275.0-25.0*skill)*(1.0+0.5*Rand())) return;\r
+\r
+       ncrit = 1.0 + hit/(500.0+100.0*Rand());\r
+       proutn("***CRITICAL HIT--");\r
+       /* Select devices and cause damage */\r
+       for (l = 1; l <= ncrit; l++) {\r
+               do {\r
+                       j = ndevice*Rand()+1.0;\r
+                       /* Cheat to prevent shuttle damage unless on ship */\r
+               } while (damage[j] < 0.0 || (j == DSHUTTL && iscraft != 1) ||\r
+                                j == DDRAY);\r
+               cdam[l] = j;\r
+               extradm = (hit*damfac)/(ncrit*(75.0+25.0*Rand()));\r
+               damage[j] += extradm;\r
+               if (l > 1) {\r
+                       for (ll=2; ll<=l && j != cdam[ll-1]; ll++) ;\r
+                       if (ll<=l) continue;\r
+                       ktr += 1;\r
+                       if (ktr==3) skip(1);\r
+                       proutn(" and ");\r
+               }\r
+               proutn(device[j]);\r
+       }\r
+       prout(" damaged.");\r
+       if (damage[DSHIELD] && shldup) {\r
+               prout("***Shields knocked down.");\r
+               shldup=0;\r
+       }\r
+}\r
+\r
+void attack(int k) {\r
+       /* k == 0 forces use of phasers in an attack */\r
+       int percent, ihurt=0, l, i=0, jx, jy, iquad, itflag;\r
+       int atackd = 0, attempt = 0;\r
+       double hit;\r
+       double pfac, dustfac, hitmax=0.0, hittot=0.0, chgfac=1.0, r;\r
+\r
+       iattak = 1;\r
+       if (alldone) return;\r
+#ifdef DEBUG\r
+       if (idebug) prout("ATTACK!");\r
+#endif\r
+\r
+       if (ithere) movetho();\r
+\r
+       if (neutz) { /* The one chance not to be attacked */\r
+               neutz = 0;\r
+               return;\r
+       }\r
+       if (((comhere || ishere) && (justin == 0)) || skill == 5) movcom();\r
+       if (nenhere==0) return;\r
+       pfac = 1.0/inshld;\r
+       if (shldchg == 1) chgfac = 0.25+0.5*Rand();\r
+       skip(1);\r
+       if (skill <= 2) i = 2;\r
+       for (l=1; l <= nenhere; l++) {\r
+               if (kpower[l] < 0) continue;    /* too weak to attack */\r
+               /* compute hit strength and diminsh shield power */\r
+               r = Rand();\r
+               /* Increase chance of photon torpedos if docked or enemy energy low */\r
+               if (condit == IHDOCKED) r *= 0.25;\r
+               if (kpower[l] < 500) r *= 0.25; \r
+               jx = kx[l];\r
+               jy = ky[l];\r
+               iquad = quad[jx][jy];\r
+               itflag = (iquad == IHK && r > 0.0005) || k == 0 ||\r
+                       (iquad==IHC && r > 0.015) ||\r
+                       (iquad==IHR && r > 0.3) ||\r
+                       (iquad==IHS && r > 0.07);\r
+               if (itflag) {\r
+                       /* Enemy uses phasers */\r
+                       if (condit == IHDOCKED) continue; /* Don't waste the effort! */\r
+                       attempt = 1; /* Attempt to attack */\r
+                       dustfac = 0.8+0.05*Rand();\r
+                       hit = kpower[l]*pow(dustfac,kavgd[l]);\r
+                       kpower[l] *= 0.75;\r
+               }\r
+               else { /* Enemy used photon torpedo */\r
+                       double course = 1.90985*atan2((double)secty-jy, (double)jx-sectx);\r
+                       hit = 0;\r
+                       proutn("***TORPEDO INCOMING");\r
+                       if (damage[DSRSENS] <= 0.0) {\r
+                               proutn(" From ");\r
+                               crmena(0, iquad, i, jx, jy);\r
+                       }\r
+                       attempt = 1;\r
+                       prout("--");\r
+                       r = (Rand()+Rand())*0.5 -0.5;\r
+                       r += 0.002*kpower[l]*r;\r
+                       torpedo(course, r, jx, jy, &hit);\r
+                       if (d.remkl==0) finish(FWON); /* Klingons did themselves in! */\r
+                       if (d.galaxy[quadx][quady] == 1000 ||\r
+                               alldone) return; /* Supernova or finished */\r
+                       if (hit == 0) continue;\r
+               }\r
+               if (shldup != 0 || shldchg != 0) {\r
+                       /* shields will take hits */\r
+                       double absorb, hitsh, propor = pfac*shield;\r
+                       if(propor < 0.1) propor = 0.1;\r
+                       hitsh = propor*chgfac*hit+1.0;\r
+                       atackd=1;\r
+                       absorb = 0.8*hitsh;\r
+                       if (absorb > shield) absorb = shield;\r
+                       shield -= absorb;\r
+                       hit -= hitsh;\r
+                       if (propor > 0.1 && hit < 0.005*energy) continue;\r
+               }\r
+               /* It's a hit -- print out hit size */\r
+               atackd = 1; /* We weren't going to check casualties, etc. if\r
+                              shields were down for some strange reason. This\r
+                                          doesn't make any sense, so I've fixed it */\r
+               ihurt = 1;\r
+               cramf(hit, 0, 2);\r
+               proutn(" unit hit");\r
+               if ((damage[DSRSENS] > 0 && itflag) || skill <= 2) {\r
+                       proutn(" on the ");\r
+                       crmshp();\r
+               }\r
+               if (damage[DSRSENS] <= 0.0 && itflag) {\r
+                       proutn(" from ");\r
+                       crmena(0, iquad, i, jx, jy);\r
+               }\r
+               skip(1);\r
+               /* Decide if hit is critical */\r
+               if (hit > hitmax) hitmax = hit;\r
+               hittot += hit;\r
+               fry(hit);\r
+               printf("Hit %g energy %g\n", hit, energy);\r
+               energy -= hit;\r
+       }\r
+       if (energy <= 0) {\r
+               /* Returning home upon your shield, not with it... */\r
+               finish(FBATTLE);\r
+               return;\r
+       }\r
+       if (attempt == 0 && condit == IHDOCKED)\r
+               prout("***Enemies decide against attacking your ship.");\r
+       if (atackd == 0) return;\r
+       percent = 100.0*pfac*shield+0.5;\r
+       if (ihurt==0) {\r
+               /* Shields fully protect ship */\r
+               proutn("Enemy attack reduces shield strength to ");\r
+       }\r
+       else {\r
+               /* Print message if starship suffered hit(s) */\r
+               skip(1);\r
+               proutn("Energy left ");\r
+               cramf(energy, 0, 2);\r
+               proutn("    shields ");\r
+               if (shldup) proutn("up, ");\r
+               else if (damage[DSHIELD] == 0) proutn("down, ");\r
+               else proutn("damaged, ");\r
+       }\r
+       crami(percent, 1);\r
+       proutn("%   torpedoes left ");\r
+       crami(torps, 1);\r
+       skip(1);\r
+       /* Check if anyone was hurt */\r
+       if (hitmax >= 200 || hittot >= 500) {\r
+               int icas= hittot*Rand()*0.015;\r
+               if (icas >= 2) {\r
+                       skip(1);\r
+                       proutn("Mc Coy-  \"Sickbay to bridge.  We suffered ");\r
+                       crami(icas, 1);\r
+                       prout(" casualties");\r
+                       prout("   in that last attack.\"");\r
+                       casual += icas;\r
+               }\r
+       }\r
+       /* After attack, reset average distance to enemies */\r
+       for (l = 1; l <= nenhere; l++)\r
+               kavgd[l] = kdist[l];\r
+       sortkl();\r
+       return;\r
+}\r
+               \r
+void deadkl(int ix, int iy, int type, int ixx, int iyy) {\r
+       /* Added ixx and iyy allow enemy to "move" before dying */\r
+\r
+       int i,j;\r
+       \r
+       crmena(1, type, 2, ixx, iyy);\r
+       /* Decide what kind of enemy it is and update approriately */\r
+       if (type == IHR) {\r
+               /* chalk up a Romulan */\r
+               d.newstuf[quadx][quady] -= 10;\r
+               irhere--;\r
+               d.nromkl++;\r
+               d.nromrem--;\r
+       }\r
+       else if (type == IHT) {\r
+               /* Killed a Tholean */\r
+               ithere = 0;\r
+       }\r
+       else {\r
+               /* Some type of a Klingon */\r
+               d.galaxy[quadx][quady] -= 100;\r
+               klhere--;\r
+               d.remkl--;\r
+               switch (type) {\r
+                       case IHC:\r
+                               comhere = 0;\r
+                               for (i=1; i<=d.remcom; i++)\r
+                                       if (d.cx[i]==quadx && d.cy[i]==quady) break;\r
+                               d.cx[i] = d.cx[d.remcom];\r
+                               d.cy[i] = d.cy[d.remcom];\r
+                               d.cx[d.remcom] = 0;\r
+                               d.cy[d.remcom] = 0;\r
+                               d.remcom--;\r
+                               future[FTBEAM] = 1e30;\r
+                               if (d.remcom != 0)\r
+                                       future[FTBEAM] = d.date + expran(1.0*incom/d.remcom);\r
+                               d.killc++;\r
+                               break;\r
+                       case IHK:\r
+                               d.killk++;\r
+                               break;\r
+                       case IHS:\r
+                               d.nscrem = ishere = d.isx = d.isy = isatb = iscate = 0;\r
+                               d.nsckill = 1;\r
+                               future[FSCMOVE] = future[FSCDBAS] = 1e30;\r
+                               break;\r
+               }\r
+       }\r
+\r
+       /* For each kind of enemy, finish message to player */\r
+       prout(" destroyed.");\r
+       quad[ix][iy] = IHDOT;\r
+       if (d.remkl==0) return;\r
+\r
+       d.remtime = d.remres/(d.remkl + 4*d.remcom);\r
+\r
+       if (type == IHT) return;\r
+\r
+       /* Remove enemy ship from arrays describing local conditions */\r
+\r
+       for (i=1; i<=nenhere; i++)\r
+               if (kx[i]==ix && ky[i]==iy) break;\r
+       nenhere--;\r
+       if (i <= nenhere)  {\r
+               for (j=i; j<=nenhere; j++) {\r
+                       kx[j] = kx[j+1];\r
+                       ky[j] = ky[j+1];\r
+                       kpower[j] = kpower[j+1];\r
+                       kavgd[j] = kdist[j] = kdist[j+1];\r
+               }\r
+       }\r
+       kx[nenhere+1] = 0;\r
+       ky[nenhere+1] = 0;\r
+       kdist[nenhere+1] = 0;\r
+       kavgd[nenhere+1] = 0;\r
+       kpower[nenhere+1] = 0;\r
+       return;\r
+}\r
+\r
+static int targetcheck(double x, double y, double *course) {\r
+       double deltx, delty;\r
+       /* Return TRUE if target is invalid */\r
+       if (x < 1.0 || x > 10.0 || y < 1.0 || y > 10.0) {\r
+               huh();\r
+               return 1;\r
+       }\r
+       deltx = 0.1*(y - secty);\r
+       delty = 0.1*(sectx - x);\r
+       if (deltx==0 && delty== 0) {\r
+               skip(1);\r
+               prout("Spock-  \"Bridge to sickbay.  Dr. McCoy,");\r
+               prout("  I recommend an immediate review of");\r
+               prout("  the Captain's psychological profile.");\r
+               chew();\r
+               return 1;\r
+       }\r
+       *course = 1.90985932*atan2(deltx, delty);\r
+       return 0;\r
+}\r
+\r
+void photon(void) {\r
+       double targ[4][3], course[4];\r
+       double r, dummy;\r
+       int key, n, i, osuabor;\r
+\r
+       ididit = 0;\r
+\r
+       if (damage[DPHOTON]) {\r
+               prout("Photon tubes damaged.");\r
+               chew();\r
+               return;\r
+       }\r
+       if (torps == 0) {\r
+               prout("No torpedoes left.");\r
+               chew();\r
+               return;\r
+       }\r
+       key = scan();\r
+       for (;;) {\r
+               if (key == IHALPHA) {\r
+                       huh();\r
+                       return;\r
+               }\r
+               else if (key == IHEOL) {\r
+                       crami(torps,1);\r
+                       prout(" torpedoes left.");\r
+                       proutn("Number of torpedoes to fire- ");\r
+                       key = scan();\r
+               }\r
+               else /* key == IHREAL */ {\r
+                       n = aaitem + 0.5;\r
+                       if (n <= 0) { /* abort command */\r
+                               chew();\r
+                               return;\r
+                       }\r
+                       if (n > 3) {\r
+                               chew();\r
+                               prout("Maximum of 3 torpedoes per burst.");\r
+                               key = IHEOL;\r
+                       }\r
+                       if (n <= torps) break;\r
+                       chew();\r
+                       key = IHEOL;\r
+               }\r
+       }\r
+       for (i = 1; i <= n; i++) {\r
+               key = scan();\r
+               if (i==1 && key == IHEOL) {\r
+                       break;  /* we will try prompting */\r
+               }\r
+               if (i==2 && key == IHEOL) {\r
+                       /* direct all torpedoes at one target */\r
+                       while (i <= n) {\r
+                               targ[i][1] = targ[1][1];\r
+                               targ[i][2] = targ[1][2];\r
+                               course[i] = course[1];\r
+                               i++;\r
+                       }\r
+                       break;\r
+               }\r
+               if (key != IHREAL) {\r
+                       huh();\r
+                       return;\r
+               }\r
+               targ[i][1] = aaitem;\r
+               key = scan();\r
+               if (key != IHREAL) {\r
+                       huh();\r
+                       return;\r
+               }\r
+               targ[i][2] = aaitem;\r
+               if (targetcheck(targ[i][1], targ[i][2], &course[i])) return;\r
+       }\r
+       chew();\r
+       if (i == 1 && key == IHEOL) {\r
+               /* prompt for each one */\r
+               for (i = 1; i <= n; i++) {\r
+                       proutn("Target sector for torpedo number");\r
+                       crami(i, 2);\r
+                       proutn("- ");\r
+                       key = scan();\r
+                       if (key != IHREAL) {\r
+                               huh();\r
+                               return;\r
+                       }\r
+                       targ[i][1] = aaitem;\r
+                       key = scan();\r
+                       if (key != IHREAL) {\r
+                               huh();\r
+                               return;\r
+                       }\r
+                       targ[i][2] = aaitem;\r
+                       chew();\r
+                       if (targetcheck(targ[i][1], targ[i][2], &course[i])) return;\r
+               }\r
+       }\r
+       ididit = 1;\r
+       /* Loop for moving <n> torpedoes */\r
+       osuabor = 0;\r
+       for (i = 1; i <= n && !osuabor; i++) {\r
+               if (condit != IHDOCKED) torps--;\r
+               r = (Rand()+Rand())*0.5 -0.5;\r
+               if (fabs(r) >= 0.47) {\r
+                       /* misfire! */\r
+                       r = (Rand()+1.2) * r;\r
+                       if (n>1) {\r
+                               prouts("***TORPEDO NUMBER");\r
+                               crami(i, 2);\r
+                               prouts(" MISFIRES.");\r
+                       }\r
+                       else prouts("***TORPEDO MISFIRES.");\r
+                       skip(1);\r
+                       if (i < n)\r
+                               prout("  Remainder of burst aborted.");\r
+                       osuabor=1;\r
+                       if (Rand() <= 0.2) {\r
+                               prout("***Photon tubes damaged by misfire.");\r
+                               damage[DPHOTON] = damfac*(1.0+2.0*Rand());\r
+                               break;\r
+                       }\r
+               }\r
+               if (shldup != 0 || condit == IHDOCKED) r *= 1.0 + 0.0001*shield;\r
+               if (n != 1) {\r
+                       skip(1);\r
+                       proutn("Track for torpedo number");\r
+                       crami(i, 2);\r
+                       proutn("-   ");\r
+               }\r
+               else {\r
+                       skip(1);\r
+                       proutn("Torpedo track- ");\r
+               }\r
+               torpedo(course[i], r, sectx, secty, &dummy);\r
+               if (alldone || d.galaxy[quadx][quady]==1000) return;\r
+       }\r
+       if (d.remkl==0) finish(FWON);\r
+}\r
+\r
+       \r
+\r
+static void overheat(double rpow) {\r
+       if (rpow > 1500) {\r
+               double chekbrn = (rpow-1500.)*0.00038;\r
+               if (Rand() <= chekbrn) {\r
+                       prout("Weapons officer Sulu-  \"Phasers overheated, sir.\"");\r
+                       damage[DPHASER] = damfac*(1.0 + Rand()) * (1.0+chekbrn);\r
+               }\r
+       }\r
+}\r
+\r
+static int checkshctrl(double rpow) {\r
+       double hit;\r
+       int icas;\r
+       \r
+       skip(1);\r
+       if (Rand() < .998) {\r
+               prout("Shields lowered.");\r
+               return 0;\r
+       }\r
+       /* Something bad has happened */\r
+       prouts("***RED ALERT!  RED ALERT!");\r
+       skip(2);\r
+       hit = rpow*shield/inshld;\r
+       energy -= rpow+hit*0.8;\r
+       shield -= hit*0.2;\r
+       if (energy <= 0.0) {\r
+               prouts("Sulu-  \"Captain! Shield malf***********************\"");\r
+               skip(1);\r
+               stars();\r
+               finish(FPHASER);\r
+               return 1;\r
+       }\r
+       prouts("Sulu-  \"Captain! Shield malfunction! Phaser fire contained!\"");\r
+       skip(2);\r
+       prout("Lt. Uhura-  \"Sir, all decks reporting damage.\"");\r
+       icas = hit*Rand()*0.012;\r
+       skip(1);\r
+       fry(0.8*hit);\r
+       if (icas) {\r
+               skip(1);\r
+               prout("McCoy to bridge- \"Severe radiation burns, Jim.");\r
+               proutn("  ");\r
+               crami(icas, 1);\r
+               prout(" casualties so far.\"");\r
+               casual -= icas;\r
+       }\r
+       skip(1);\r
+       prout("Phaser energy dispersed by shields.");\r
+       prout("Enemy unaffected.");\r
+       overheat(rpow);\r
+       return 1;\r
+}\r
+       \r
+\r
+void phasers(void) {\r
+       double hits[21], rpow, extra, powrem, over, temp;\r
+       int kz = 0, k=1, i; /* Cheating inhibitor */\r
+       int ifast=0, no=0, ipoop=1, msgflag = 1;\r
+       enum {NOTSET, MANUAL, FORCEMAN, AUTOMATIC} automode = NOTSET;\r
+       int key;\r
+\r
+       skip(1);\r
+       /* SR sensors and Computer */\r
+       if (damage[DSRSENS]+damage[DCOMPTR] > 0) ipoop = 0;\r
+       if (condit == IHDOCKED) {\r
+               prout("Phasers can't be fired through base shields.");\r
+               chew();\r
+               return;\r
+       }\r
+       if (damage[DPHASER] != 0) {\r
+               prout("Phaser control damaged.");\r
+               chew();\r
+               return;\r
+       }\r
+       if (shldup) {\r
+               if (damage[DSHCTRL]) {\r
+                       prout("High speed shield control damaged.");\r
+                       chew();\r
+                       return;\r
+               }\r
+               if (energy <= 200.0) {\r
+                       prout("Insufficient energy to activate high-speed shield control.");\r
+                       chew();\r
+                       return;\r
+               }\r
+               prout("Weapons Officer Sulu-  \"High-speed shield control enabled, sir.\"");\r
+               ifast = 1;\r
+               \r
+       }\r
+       ididit = 1;\r
+       /* Original code so convoluted, I re-did it all */\r
+       while (automode==NOTSET) {\r
+               key=scan();\r
+               if (key == IHALPHA) {\r
+                       if (isit("manual")) {\r
+                               if (nenhere==0) {\r
+                                       prout("There is no enemy present to select.");\r
+                                       chew();\r
+                                       key = IHEOL;\r
+                                       automode=AUTOMATIC;\r
+                               }\r
+                               else {\r
+                                       automode = MANUAL;\r
+                                       key = scan();\r
+                               }\r
+                       }\r
+                       else if (isit("automatic")) {\r
+                               if ((!ipoop) && nenhere != 0) {\r
+                                       automode = FORCEMAN;\r
+                               }\r
+                               else {\r
+                                       if (nenhere==0)\r
+                                               prout("Energy will be expended into space.");\r
+                                       automode = AUTOMATIC;\r
+                                       key = scan();\r
+                               }\r
+                       }\r
+                       else if (isit("no")) {\r
+                               no = 1;\r
+                       }\r
+                       else {\r
+                               huh();\r
+                               ididit = 0;\r
+                               return;\r
+                       }\r
+               }\r
+               else if (key == IHREAL) {\r
+                       if (nenhere==0) {\r
+                               prout("Energy will be expended into space.");\r
+                               automode = AUTOMATIC;\r
+                       }\r
+                       else if (!ipoop)\r
+                               automode = FORCEMAN;\r
+                       else\r
+                               automode = AUTOMATIC;\r
+               }\r
+               else {\r
+                       /* IHEOL */\r
+                       if (nenhere==0) {\r
+                               prout("Energy will be expended into space.");\r
+                               automode = AUTOMATIC;\r
+                       }\r
+                       else if (!ipoop)\r
+                               automode = FORCEMAN;\r
+                       else \r
+                       proutn("Manual or automatic? ");\r
+               }\r
+       }\r
+                               \r
+       switch (automode) {\r
+               case AUTOMATIC:\r
+                       if (key == IHALPHA && isit("no")) {\r
+                               no = 1;\r
+                               key = scan();\r
+                       }\r
+                       if (key != IHREAL && nenhere != 0) {\r
+                               proutn("Phasers locked on target. Energy available =");\r
+                               cramf(ifast?energy-200.0:energy,1,2);\r
+                               skip(1);\r
+                       }\r
+                       do {\r
+                               while (key != IHREAL) {\r
+                                       chew();\r
+                                       proutn("Units to fire=");\r
+                                       key = scan();\r
+                               }\r
+                               rpow = aaitem;\r
+                               if (rpow >= (ifast?energy-200:energy)) {\r
+                                       proutn("Energy available= ");\r
+                                       cramf(ifast?energy-200:energy, 1,2);\r
+                                       skip(1);\r
+                                       key = IHEOL;\r
+                               }\r
+                       } while (rpow >= (ifast?energy-200:energy));\r
+                       if (rpow<=0) {\r
+                               /* chicken out */\r
+                               ididit = 0;\r
+                               chew();\r
+                               return;\r
+                       }\r
+                       if ((key=scan()) == IHALPHA && isit("no")) {\r
+                               no = 1;\r
+                       }\r
+                       if (ifast) {\r
+                               energy -= 200; /* Go and do it! */\r
+                               if (checkshctrl(rpow)) return;\r
+                       }\r
+                       chew();\r
+                       energy -= rpow;\r
+                       extra = rpow;\r
+                       if (nenhere) {\r
+                               extra = 0.0;\r
+                               powrem = rpow;\r
+                               for (i = 1; i <= nenhere; i++) {\r
+                                       hits[i] = 0.0;\r
+                                       if (powrem <= 0) continue;\r
+                                       hits[i] = fabs(kpower[i])/(phasefac*pow(0.90,kdist[i]));\r
+                                       over = (0.01 + 0.05*Rand())*hits[i];\r
+                                       temp = powrem;\r
+                                       powrem -= hits[i] + over;\r
+                                       if (powrem <= 0 && temp < hits[i]) hits[i] = temp;\r
+                                       if (powrem <= 0) over = 0.0;\r
+                                       extra += over;\r
+                               }\r
+                               if (powrem > 0.0) extra += powrem;\r
+                               hittem(hits);\r
+                       }\r
+                       if (extra > 0 && alldone == 0) {\r
+                               if (ithere) {\r
+                                       proutn("*** Tholian web absorbs ");\r
+                                       if (nenhere>0) proutn("excess ");\r
+                                       prout("phaser energy.");\r
+                               }\r
+                               else {\r
+                                       cramf(extra, 0, 2);\r
+                                       prout(" expended on empty space.");\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case FORCEMAN:\r
+                       chew();\r
+                       key = IHEOL;\r
+                       if (damage[DCOMPTR]!=0)\r
+                               prout("Battle comuter damaged, manual file only.");\r
+                       else {\r
+                               skip(1);\r
+                               prouts("---WORKING---");\r
+                               skip(1);\r
+                               prout("Short-range-sensors-damaged");\r
+                               prout("Insufficient-data-for-automatic-phaser-fire");\r
+                               prout("Manual-fire-must-be-used");\r
+                               skip(1);\r
+                       }\r
+               case MANUAL:\r
+                       rpow = 0.0;\r
+                       for (k = 1; k <= nenhere;) {\r
+                               int ii = kx[k], jj = ky[k];\r
+                               int ienm = quad[ii][jj];\r
+                               if (msgflag) {\r
+                                       proutn("Energy available= ");\r
+                                       cramf(energy-.006-(ifast?200:0), 0, 2);\r
+                                       skip(1);\r
+                                       msgflag = 0;\r
+                                       rpow = 0.0;\r
+                               }\r
+                               if (damage[DSRSENS] && !(abs(sectx-ii) < 2 && abs(secty-jj) < 2) &&\r
+                                       (ienm == IHC || ienm == IHS)) {\r
+                                       cramen(ienm);\r
+                                       prout(" can't be located without short range scan.");\r
+                                       chew();\r
+                                       key = IHEOL;\r
+                                       hits[k] = 0; /* prevent overflow -- thanks to Alexei Voitenko */\r
+                                       k++;\r
+                                       continue;\r
+                               }\r
+                               if (key == IHEOL) {\r
+                                       chew();\r
+                                       if (ipoop && k > kz) {\r
+                                               int irec=(fabs(kpower[k])/(phasefac*pow(0.9,kdist[k])))*\r
+                                                                (1.01+0.05*Rand()) + 1.0;\r
+                                               kz = k;\r
+                                               proutn("(");\r
+                                               crami(irec, 1);\r
+                                               proutn(")  ");\r
+                                       }\r
+                                       proutn("units to fire at ");\r
+                                       crmena(0, ienm, 2, ii, jj);\r
+                                       proutn("-  ");\r
+                                       key = scan();\r
+                               }\r
+                               if (key == IHALPHA && isit("no")) {\r
+                                       no = 1;\r
+                                       key = scan();\r
+                                       continue;\r
+                                       }\r
+                               if (key == IHALPHA) {\r
+                                       huh();\r
+                                       ididit = 0;\r
+                                       return;\r
+                               }\r
+                               if (key == IHEOL) {\r
+                                       if (k==1) { /* Let me say I'm baffled by this */\r
+                                               msgflag = 1;\r
+                                       }\r
+                                       continue;\r
+                               }\r
+                               if (aaitem < 0) {\r
+                                       /* abort out */\r
+                                       ididit = 0;\r
+                                       chew();\r
+                                       return;\r
+                               }\r
+                               hits[k] = aaitem;\r
+                               rpow += aaitem;\r
+                               /* If total requested is too much, inform and start over */\r
+                               \r
+                               if (rpow >= (ifast?energy-200:energy)) {\r
+                                       prout("Available energy exceeded -- try again.");\r
+                                       chew();\r
+                                       key = IHEOL;\r
+                                       k = 1;\r
+                                       msgflag = 1;\r
+                                       continue;\r
+                               }\r
+                               key = scan(); /* scan for next value */\r
+                               k++;\r
+                       }\r
+                       if (rpow == 0.0) {\r
+                               /* zero energy -- abort */\r
+                               ididit = 0;\r
+                               chew();\r
+                               return;\r
+                       }\r
+                       if (key == IHALPHA & isit("no")) {\r
+                               no = 1;\r
+                       }\r
+                       energy -= rpow;\r
+                       chew();\r
+                       if (ifast) {\r
+                               energy -= 200.0;\r
+                               if (checkshctrl(rpow)) return;\r
+                       }\r
+                       hittem(hits);\r
+                       ididit=1;\r
+       }\r
+       /* Say shield raised or malfunction, if necessary */\r
+       if (alldone) return;\r
+       if (ifast) {\r
+               skip(1);\r
+               if (no == 0) {\r
+                       if (Rand() >= 0.99) {\r
+                               prout("Sulu-  \"Sir, the high-speed shield control has malfunctioned . . .");\r
+                               prouts("         CLICK   CLICK   POP  . . .");\r
+                               prout(" No  response, sir!");\r
+                               shldup = 0;\r
+                       }\r
+                       else\r
+                               prout("Shields raised.");\r
+               }\r
+               else\r
+                       shldup = 0;\r
+       }\r
+       overheat(rpow);\r
+}\r
+\r
+void hittem(double *hits) {\r
+       double kp, kpow, wham, hit, dustfac, kpini;\r
+       int nenhr2=nenhere, k=1, kk=1, ii, jj, ienm;\r
+\r
+       skip(1);\r
+\r
+       for (; k <= nenhr2; k++, kk++) {\r
+               if ((wham = hits[k])==0) continue;\r
+               dustfac = 0.9 + 0.01*Rand();\r
+               hit = wham*pow(dustfac,kdist[kk]);\r
+               kpini = kpower[kk];\r
+               kp = fabs(kpini);\r
+               if (phasefac*hit < kp) kp = phasefac*hit;\r
+               kpower[kk] -= (kpower[kk] < 0 ? -kp: kp);\r
+               kpow = kpower[kk];\r
+               ii = kx[kk];\r
+               jj = ky[kk];\r
+               if (hit > 0.005) {\r
+                       cramf(hit, 0, 2);\r
+                       proutn(" unit hit on ");\r
+               }\r
+               else\r
+                       proutn("Very small hit on ");\r
+               ienm = quad[ii][jj];\r
+               crmena(0,ienm,2,ii,jj);\r
+               skip(1);\r
+               if (kpow == 0) {\r
+                       deadkl(ii, jj, ienm, ii, jj);\r
+                       if (d.remkl==0) finish(FWON);\r
+                       if (alldone) return;\r
+                       kk--; /* don't do the increment */\r
+               }\r
+               else /* decide whether or not to emasculate klingon */\r
+                       if (kpow > 0 && Rand() >= 0.9 &&\r
+                               kpow <= ((0.4 + 0.4*Rand())*kpini)) {\r
+                               proutn("***Mr. Spock-  \"Captain, the vessel at");\r
+                               cramlc(2,ii,jj);\r
+                               skip(1);\r
+                               prout("   has just lost its firepower.\"");\r
+                               kpower[kk] = -kpow;\r
+                       }\r
+       }\r
+       return;\r
+}\r
+\r
diff --git a/events.c b/events.c
new file mode 100644 (file)
index 0000000..192b1cb
--- /dev/null
+++ b/events.c
@@ -0,0 +1,767 @@
+#include "sst.h"\r
+#include <math.h>\r
+\r
+void events(void) {\r
+\r
+       int ictbeam=0, ipage=0, istract=0, line, i, j, k, l, ixhold, iyhold;\r
+       double fintim = d.date + Time, datemin, xtime, repair, yank;\r
+       \r
+\r
+#ifdef DEBUG\r
+       if (idebug) prout("EVENTS");\r
+#endif\r
+\r
+       if (stdamtim == 1e30 && damage[DRADIO] != 0.0) {\r
+               /* chart will no longer be updated because radio is dead */\r
+               stdamtim = d.date;\r
+               for (i=1; i <= 8 ; i++)\r
+                       for (j=1; j <= 8; j++)\r
+                               if (starch[i][j] == 1) starch[i][j] = d.galaxy[i][j]+1000;\r
+       }\r
+\r
+       for (;;) {\r
+               /* Select earliest extraneous event, line==0 if no events */\r
+               line = FSPY;\r
+               if (alldone) return;\r
+               datemin = fintim;\r
+               for (l=1; l<=NEVENTS; l++)\r
+                       if (future[l] <= datemin) {\r
+                               line = l;\r
+                               datemin = future[l];\r
+                       }\r
+               xtime = datemin-d.date;\r
+               d.date = datemin;\r
+               /* Decrement Federation resources and recompute remaining time */\r
+               d.remres -= (d.remkl+4*d.remcom)*xtime;\r
+               d.remtime = d.remres/(d.remkl+4*d.remcom);\r
+               if (d.remtime <=0) {\r
+                       finish(FDEPLETE);\r
+                       return;\r
+               }\r
+               /* Is life support adequate? */\r
+               if (damage[DLIFSUP] && condit != IHDOCKED) {\r
+                       if (lsupres < xtime && damage[DLIFSUP] > lsupres) {\r
+                               finish(FLIFESUP);\r
+                               return;\r
+                       }\r
+                       lsupres -= xtime;\r
+                       if (damage[DLIFSUP] <= xtime) lsupres = inlsr;\r
+               }\r
+               /* Fix devices */\r
+               repair = xtime;\r
+               if (condit == IHDOCKED) repair /= docfac;\r
+               /* Don't fix Deathray here */\r
+               for (l=1; l<=ndevice; l++)\r
+                       if (damage[l] > 0.0 && l != DDRAY)\r
+                               damage[l] -= (damage[l]-repair > 0.0 ? repair : damage[l]);\r
+               /* If radio repaired, update star chart and attack reports */\r
+               if (stdamtim != 1e30 && damage[DRADIO] == 0.0) {\r
+                       stdamtim = 1e30;\r
+                       prout("Lt. Uhura- \"Captain, the sub-space radio is working and");\r
+                       prout("   surveillance reports are coming in.");\r
+                       skip(1);\r
+                       for (i=1; i <= 8 ; i++)\r
+                               for (j=1; j <= 8; j++)\r
+                                       if (starch[i][j] > 999) starch[i][j] = 1;\r
+                       if (iseenit==0) {\r
+                               attakreport();\r
+                               iseenit = 1;\r
+                       }\r
+                       skip(1);\r
+                       prout("   The star chart is now up to date.\"");\r
+                       skip(1);\r
+               }\r
+               /* Cause extraneous event LINE to occur */\r
+               Time -= xtime;\r
+               switch (line) {\r
+                       case FSNOVA: /* Supernova */\r
+                               if (ipage==0) pause(1);\r
+                               ipage=1;\r
+                               snova(0,0);\r
+                               future[FSNOVA] = d.date + expran(0.5*intime);\r
+                               if (d.galaxy[quadx][quady] == 1000) return;\r
+                               break;\r
+                       case FSPY: /* Check with spy to see if S.C. should tractor beam */\r
+                               if (d.nscrem == 0 ||\r
+                                       ictbeam+istract > 0 ||\r
+                                       condit==IHDOCKED || isatb==1 || iscate==1) return;\r
+                               if (ientesc ||\r
+                                       (energy < 2000 && torps < 4 && shield < 1250) ||\r
+                                       (damage[DPHASER]>0 && (damage[DPHOTON]>0 || torps < 4)) ||\r
+                                       (damage[DSHIELD] > 0 &&\r
+                                        (energy < 2500 || damage[DPHASER] > 0) &&\r
+                                        (torps < 5 || damage[DPHOTON] > 0))) {\r
+                                       /* Tractor-beam her! */\r
+                                       istract=1;\r
+                                       yank = square(d.isx-quadx) + square(d.isy-quady);\r
+                                       /*********TBEAM CODE***********/\r
+                               }\r
+                               else return;\r
+                       case FTBEAM: /* Tractor beam */\r
+                               if (line==FTBEAM) {\r
+                                       if (d.remcom == 0) {\r
+                                               future[FTBEAM] = 1e30;\r
+                                               break;\r
+                                       }\r
+                                       i = Rand()*d.remcom+1.0;\r
+                                       yank = square(d.cx[i]-quadx) + square(d.cy[i]-quady);\r
+                                       if (istract || condit == IHDOCKED || yank == 0) {\r
+                                               /* Drats! Have to reschedule */\r
+                                               future[FTBEAM] = d.date + Time +\r
+                                                                                expran(1.5*intime/d.remcom);\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               /* tractor beaming cases merge here */\r
+                               yank = sqrt(yank);\r
+                               if (ipage==0) pause(1);\r
+                               ipage=1;\r
+                               Time = (10.0/(7.5*7.5))*yank; /* 7.5 is yank rate (warp 7.5) */\r
+                               ictbeam = 1;\r
+                               skip(1);\r
+                               proutn("***");\r
+                               crmshp();\r
+                               prout(" caught in long range tractor beam--");\r
+                               /* If Kirk & Co. screwing around on planet, handle */\r
+                               atover(1); /* atover(1) is Grab */\r
+                               if (alldone) return;\r
+                               if (icraft == 1) { /* Caught in Galileo? */\r
+                                       finish(FSTRACTOR);\r
+                                       return;\r
+                               }\r
+                               /* Check to see if shuttle is aboard */\r
+                               if (iscraft==0) {\r
+                                       skip(1);\r
+                                       if (Rand() >0.5) {\r
+                                               prout("Galileo, left on the planet surface, is captured");\r
+                                               prout("by aliens and made into a flying McDonald's.");\r
+                                               damage[DSHUTTL] = -10;\r
+                                               iscraft = -1;\r
+                                       }\r
+                                       else {\r
+                                               prout("Galileo, left on the planet surface, is well hidden.");\r
+                                       }\r
+                               }\r
+                               if (line==0) {\r
+                                       quadx = d.isx;\r
+                                       quady = d.isy;\r
+                               }\r
+                               else {\r
+                                       quadx = d.cx[i];\r
+                                       quady = d.cy[i];\r
+                               }\r
+                               iran10(&sectx, &secty);\r
+                               crmshp();\r
+                               proutn(" is pulled to");\r
+                               cramlc(1, quadx, quady);\r
+                               proutn(", ");\r
+                               cramlc(2, sectx, secty);\r
+                               skip(1);\r
+                               if (resting) {\r
+                                       prout("(Remainder of rest/repair period cancelled.)");\r
+                                       resting = 0;\r
+                               }\r
+                               if (shldup==0) {\r
+                                       if (damage[DSHIELD]==0 && shield > 0) {\r
+                                               sheild(2); /* Shldsup */\r
+                                               shldchg=0;\r
+                                       }\r
+                                       else prout("(Shields not currently useable.)");\r
+                               }\r
+                               newqad(0);\r
+                               /* Adjust finish time to time of tractor beaming */\r
+                               fintim = d.date+Time;\r
+                               if (d.remcom <= 0) future[FTBEAM] = 1e30;\r
+                               else future[FTBEAM] = d.date+Time+expran(1.5*intime/d.remcom);\r
+                               break;\r
+                       case FSNAP: /* Snapshot of the universe (for time warp) */\r
+                               snapsht = d;\r
+                               d.snap = 1;\r
+                               future[FSNAP] = d.date + expran(0.5 * intime);\r
+                               break;\r
+                       case FBATTAK: /* Commander attacks starbase */\r
+                               if (d.remcom==0 || d.rembase==0) {\r
+                                       /* no can do */\r
+                                       future[FBATTAK] = future[FCDBAS] = 1e30;\r
+                                       break;\r
+                               }\r
+                               i = 0;\r
+                               for (j=1; j<=d.rembase; j++) {\r
+                                       for (k=1; k<=d.remcom; k++)\r
+                                               if (d.baseqx[j]==d.cx[k] && d.baseqy[j]==d.cy[k] &&\r
+                                                       (d.baseqx[j]!=quadx || d.baseqy[j]!=quady) &&\r
+                                                       (d.baseqx[j]!=d.isx || d.baseqy[j]!=d.isy)) {\r
+                                                       i = 1;\r
+                                                       break;\r
+                                               }\r
+                                       if (i == 1) break;\r
+                               }\r
+                               if (j>d.rembase) {\r
+                                       /* no match found -- try later */\r
+                                       future[FBATTAK] = d.date + expran(0.3*intime);\r
+                                       future[FCDBAS] = 1e30;\r
+                                       break;\r
+                               }\r
+                               /* commander + starbase combination found -- launch attack */\r
+                               batx = d.baseqx[j];\r
+                               baty = d.baseqy[j];\r
+                               future[FCDBAS] = d.date+1.0+3.0*Rand();\r
+                               if (isatb) /* extra time if SC already attacking */\r
+                                       future[FCDBAS] += future[FSCDBAS]-d.date;\r
+                               future[FBATTAK] = future[FCDBAS] +expran(0.3*intime);\r
+                               iseenit = 0;\r
+                               if (damage[DRADIO] != 0.0 &&\r
+                                       condit != IHDOCKED) break; /* No warning :-( */\r
+                               iseenit = 1;\r
+                               if (ipage==0) pause(1);\r
+                               ipage = 1;\r
+                               skip(1);\r
+                               proutn("Lt. Uhura-  \"Captain, the starbase in");\r
+                               cramlc(1, batx, baty);\r
+                               skip(1);\r
+                               prout("   reports that it is under atttack and that it can");\r
+                               proutn("   hold out only until stardate ");\r
+                               cramf(future[FCDBAS],1,1);\r
+                               prout(".\"");\r
+                               if (resting) {\r
+                                       skip(1);\r
+                                       proutn("Mr. Spock-  \"Captain, shall we cancel the rest period?\"");\r
+                                       if (ja()) {\r
+                                               resting = 0;\r
+                                               Time = 0.0;\r
+                                               return;\r
+                                       }\r
+                               }\r
+                               break;\r
+                       case FSCDBAS: /* Supercommander destroys base */\r
+                               future[FSCDBAS] = 1e30;\r
+                               isatb = 2;\r
+                               if (d.galaxy[d.isx][d.isy]%100 < 10) break; /* WAS RETURN! */\r
+                               ixhold = batx;\r
+                               iyhold = baty;\r
+                               batx = d.isx;\r
+                               baty = d.isy;\r
+                       case FCDBAS: /* Commander succeeds in destroying base */\r
+                               if (line==FCDBAS) {\r
+                                       future[FCDBAS] = 1e30;\r
+                                       /* find the lucky pair */\r
+                                       for (i = 1; i <= d.remcom; i++)\r
+                                               if (d.cx[i]==batx && d.cy[i]==baty) break;\r
+                                       if (i > d.remcom || d.rembase == 0 ||\r
+                                               d.galaxy[batx][baty] % 100 < 10) {\r
+                                               /* No action to take after all */\r
+                                               batx = baty = 0;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               /* Code merges here for any commander destroying base */\r
+                               /* Not perfect, but will have to do */\r
+                               if (starch[batx][baty] == -1) starch[batx][baty] = 0;\r
+                               /* Handle case where base is in same quadrant as starship */\r
+                               if (batx==quadx && baty==quady) {\r
+                                       if (starch[batx][baty] > 999) starch[batx][baty] -= 10;\r
+                                       quad[basex][basey]= IHDOT;\r
+                                       basex=basey=0;\r
+                                       newcnd();\r
+                                       skip(1);\r
+                                       prout("Spock-  \"Captain, I believe the starbase has been destroyed.\"");\r
+                               }\r
+                               else if (d.rembase != 1 &&\r
+                                                (damage[DRADIO] <= 0.0 || condit == IHDOCKED)) {\r
+                                       /* Get word via subspace radio */\r
+                                       if (ipage==0) pause(1);\r
+                                       ipage = 1;\r
+                                       skip(1);\r
+                                       prout("Lt. Uhura-  \"Captain, Starfleet Command reports that");\r
+                                       proutn("   the starbase in");\r
+                                       cramlc(1, batx, baty);\r
+                                       prout(" has been destroyed by");\r
+                                       if (isatb==2) prout("the Klingon Super-Commander");\r
+                                       else prout("a Klingon Commander");\r
+                               }\r
+                               /* Remove Starbase from galaxy */\r
+                               d.galaxy[batx][baty] -= 10;\r
+                               for (i=1; i <= d.rembase; i++)\r
+                                       if (d.baseqx[i]==batx && d.baseqy[i]==baty) {\r
+                                               d.baseqx[i]=d.baseqx[d.rembase];\r
+                                               d.baseqy[i]=d.baseqy[d.rembase];\r
+                                       }\r
+                               d.rembase--;\r
+                               if (isatb == 2) {\r
+                                       /* reinstate a commander's base attack */\r
+                                       batx = ixhold;\r
+                                       baty = iyhold;\r
+                                       isatb = 0;\r
+                               }\r
+                               else {\r
+                                       batx = baty = 0;\r
+                               }\r
+                               break;\r
+                       case FSCMOVE: /* Supercommander moves */\r
+                               future[FSCMOVE] = d.date+0.2777;\r
+                               if (ientesc+istract==0 &&\r
+                                       isatb!=1 &&\r
+                                       (iscate!=1 || justin==1)) scom(&ipage);\r
+                               break;\r
+                       case FDSPROB: /* Move deep space probe */\r
+                               future[FDSPROB] = d.date + 0.01;\r
+                               probex += probeinx;\r
+                               probey += probeiny;\r
+                               i = (int)(probex/10 +0.05);\r
+                               j = (int)(probey/10 + 0.05);\r
+                               if (probecx != i || probecy != j) {\r
+                                       probecx = i;\r
+                                       probecy = j;\r
+                                       if (i < 1 || i > 8 || j < 1 || j > 8 ||\r
+                                               d.galaxy[probecx][probecy] == 1000) {\r
+                                               // Left galaxy or ran into supernova\r
+                                               if (damage[DRADIO]==0.0 || condit == IHDOCKED) {\r
+                                                       if (ipage==0) pause(1);\r
+                                                       ipage = 1;\r
+                                                       skip(1);\r
+                                                       proutn("Lt. Uhura-  \"The deep space probe ");\r
+                                                       if (i < 1 ||i > 8 || j < 1 || j > 8)\r
+                                                               proutn("has left the galaxy");\r
+                                                       else\r
+                                                               proutn("is no longer transmitting");\r
+                                                       prout(".\"");\r
+                                               }\r
+                                               future[FDSPROB] = 1e30;\r
+                                               break;\r
+                                       }\r
+                                       if (damage[DRADIO]==0.0   || condit == IHDOCKED) {\r
+                                               if (ipage==0) pause(1);\r
+                                               ipage = 1;\r
+                                               skip(1);\r
+                                               proutn("Lt. Uhura-  \"The deep space probe is now in ");\r
+                                               cramlc(1, probecx, probecy);\r
+                                               prout(".\"");\r
+                                       }\r
+                               }\r
+                               /* Update star chart if Radio is working or have access to\r
+                                  radio. */\r
+                               if (damage[DRADIO] == 0.0 || condit == IHDOCKED)\r
+                                       starch[probecx][probecy] = damage[DRADIO] > 0.0 ?\r
+                                                                                  d.galaxy[probecx][probecy]+1000 : 1;\r
+                               proben--; // One less to travel\r
+                               if (proben == 0 && isarmed &&\r
+                                       d.galaxy[probecx][probecy] % 10 > 0) {\r
+                                       /* lets blow the sucker! */\r
+                                       snova(1,0);\r
+                                       future[FDSPROB] = 1e30;\r
+                                       if (d.galaxy[quadx][quady] == 1000) return;\r
+                               }\r
+                               break;\r
+               }\r
+       }\r
+}\r
+\r
+                               \r
+void wait(void) {\r
+       int key;\r
+       double temp, delay, origTime;\r
+\r
+       ididit = 0;\r
+       for (;;) {\r
+               key = scan();\r
+               if (key  != IHEOL) break;\r
+               proutn("How long? ");\r
+       }\r
+       chew();\r
+       if (key != IHREAL) {\r
+               huh();\r
+               return;\r
+       }\r
+       origTime = delay = aaitem;\r
+       if (delay <= 0.0) return;\r
+       if (delay >= d.remtime || nenhere != 0) {\r
+               prout("Are you sure? ");\r
+               if (ja() == 0) return;\r
+       }\r
+\r
+       /* Alternate resting periods (events) with attacks */\r
+\r
+       resting = 1;\r
+       do {\r
+               if (delay <= 0) resting = 0;\r
+               if (resting == 0) {\r
+                       cramf(d.remtime, 0, 2);\r
+                       prout(" stardates left.");\r
+                       return;\r
+               }\r
+               temp = Time = delay;\r
+\r
+               if (nenhere) {\r
+                       double rtime = 1.0 + Rand();\r
+                       if (rtime < temp) temp = rtime;\r
+                       Time = temp;\r
+               }\r
+               if (Time < delay) attack(0);\r
+               if (nenhere==0) movetho();\r
+               if (alldone) return;\r
+               events();\r
+               ididit = 1;\r
+               if (alldone) return;\r
+               delay -= temp;\r
+               /* Repair Deathray if long rest at starbase */\r
+               if (origTime-delay >= 9.99 && condit == IHDOCKED)\r
+                       damage[DDRAY] = 0.0;\r
+       } while (d.galaxy[quadx][quady] != 1000); // leave if quadrant supernovas\r
+\r
+       resting = 0;\r
+       Time = 0;\r
+}\r
+\r
+void nova(int ix, int iy) {\r
+       static double course[] =\r
+               {0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};\r
+       int bot, top, top2, burst, hits[11][3], kount, icx, icy, mm, nn, j;\r
+       int iquad, iquad1, i, ll, newcx, newcy, ii, jj;\r
+       if (Rand() < 0.05) {\r
+               /* Wow! We've supernova'ed */\r
+               snova(ix, iy);\r
+               return;\r
+       }\r
+\r
+       /* handle initial nova */\r
+       quad[ix][iy] = IHDOT;\r
+       crmena(1, IHSTAR, 2, ix, iy);\r
+       prout(" novas.");\r
+       d.galaxy[quadx][quady] -= 1;\r
+       d.starkl++;\r
+       \r
+       /* Set up stack to recursively trigger adjacent stars */\r
+       bot = top = top2 = 1;\r
+       kount = 0;\r
+       icx = icy = 0;\r
+       hits[1][1] = ix;\r
+       hits[1][2] = iy;\r
+       while (1) {\r
+               for (mm = bot; mm <= top; mm++) \r
+               for (nn = 1; nn <= 3; nn++)  /* nn,j represents coordinates around current */\r
+                       for (j = 1; j <= 3; j++) {\r
+                               if (j==2 && nn== 2) continue;\r
+                               ii = hits[mm][1]+nn-2;\r
+                               jj = hits[mm][2]+j-2;\r
+                               if (ii < 1 || ii > 10 || jj < 1 || jj > 10) continue;\r
+                               iquad = quad[ii][jj];\r
+                               switch (iquad) {\r
+//                                     case IHDOT:     /* Empty space ends reaction\r
+//                                     case IHQUEST:\r
+//                                     case IHBLANK:\r
+//                                     case IHT:\r
+//                                     case IHWEB:\r
+                                       default:\r
+                                               break;\r
+                                       case IHSTAR: /* Affect another star */\r
+                                               if (Rand() < 0.05) {\r
+                                                       /* This star supernovas */\r
+                                                       snova(ii,jj);\r
+                                                       return;\r
+                                               }\r
+                                               top2++;\r
+                                               hits[top2][1]=ii;\r
+                                               hits[top2][2]=jj;\r
+                                               d.galaxy[quadx][quady] -= 1;\r
+                                               d.starkl++;\r
+                                               crmena(1, IHSTAR, 2, ii, jj);\r
+                                               prout(" novas.");\r
+                                               quad[ii][jj] = IHDOT;\r
+                                               break;\r
+                                       case IHP: /* Destroy planet */\r
+                                               d.newstuf[quadx][quady] -= 1;\r
+                                               d.nplankl++;\r
+                                               crmena(1, IHP, 2, ii, jj);\r
+                                               prout(" destroyed.");\r
+                                               d.plnets[iplnet] = nulplanet;\r
+                                               iplnet = plnetx = plnety = 0;\r
+                                               if (landed == 1) {\r
+                                                       finish(FPNOVA);\r
+                                                       return;\r
+                                               }\r
+                                               quad[ii][jj] = IHDOT;\r
+                                               break;\r
+                                       case IHB: /* Destroy base */\r
+                                               d.galaxy[quadx][quady] -= 10;\r
+                                               for (i = 1; i <= d.rembase; i++)\r
+                                                       if (d.baseqx[i]==quadx && d.baseqy[i]==quady) break;\r
+                                               d.baseqx[i] = d.baseqx[d.rembase];\r
+                                               d.baseqy[i] = d.baseqy[d.rembase];\r
+                                               d.rembase--;\r
+                                               basex = basey = 0;\r
+                                               d.basekl++;\r
+                                               newcnd();\r
+                                               crmena(1, IHB, 2, ii, jj);\r
+                                               prout(" destroyed.");\r
+                                               quad[ii][jj] = IHDOT;\r
+                                               break;\r
+                                       case IHE: /* Buffet ship */\r
+                                       case IHF:\r
+                                               prout("***Starship buffeted by nova.");\r
+                                               if (shldup) {\r
+                                                       if (shield >= 2000.0) shield -= 2000.0;\r
+                                                       else {\r
+                                                               double diff = 2000.0 - shield;\r
+                                                               energy -= diff;\r
+                                                               shield = 0.0;\r
+                                                               shldup = 0;\r
+                                                               prout("***Shields knocked out.");\r
+                                                               damage[DSHIELD] += 0.005*damfac*Rand()*diff;\r
+                                                       }\r
+                                               }\r
+                                               else energy -= 2000.0;\r
+                                               if (energy <= 0) {\r
+                                                       finish(FNOVA);\r
+                                                       return;\r
+                                               }\r
+                                               /* add in course nova contributes to kicking starship*/\r
+                                               icx += sectx-hits[mm][1];\r
+                                               icy += secty-hits[mm][2];\r
+                                               kount++;\r
+                                               break;\r
+                                       case IHK: /* kill klingon */\r
+                                               deadkl(ii,jj,iquad, ii, jj);\r
+                                               break;\r
+                                       case IHC: /* Damage/destroy big enemies */\r
+                                       case IHS:\r
+                                       case IHR:\r
+                                               for (ll = 1; ll <= nenhere; ll++)\r
+                                                       if (kx[ll]==ii && ky[ll]==jj) break;\r
+                                               kpower[ll] -= 800.0; /* If firepower is lost, die */\r
+                                               if (kpower[ll] <= 0.0) {\r
+                                                       deadkl(ii, jj, iquad, ii, jj);\r
+                                                       break;\r
+                                               }\r
+                                               newcx = ii + ii - hits[mm][1];\r
+                                               newcy = jj + jj - hits[mm][2];\r
+                                               crmena(1, iquad, 2, ii, jj);\r
+                                               proutn(" damaged");\r
+                                               if (newcx<1 || newcx>10 || newcy<1 || newcy>10) {\r
+                                                       /* can't leave quadrant */\r
+                                                       skip(1);\r
+                                                       break;\r
+                                               }\r
+                                               iquad1 = quad[newcx][newcy];\r
+                                               if (iquad1 == IHBLANK) {\r
+                                                       proutn(", blasted into ");\r
+                                                       crmena(0, IHBLANK, 2, newcx, newcy);\r
+                                                       skip(1);\r
+                                                       deadkl(ii, jj, iquad, newcx, newcy);\r
+                                                       break;\r
+                                               }\r
+                                               if (iquad1 != IHDOT) {\r
+                                                       /* can't move into something else */\r
+                                                       skip(1);\r
+                                                       break;\r
+                                               }\r
+                                               proutn(", buffeted to");\r
+                                               cramlc(2, newcx, newcy);\r
+                                               quad[ii][jj] = IHDOT;\r
+                                               quad[newcx][newcy] = iquad;\r
+                                               kx[ll] = newcx;\r
+                                               ky[ll] = newcy;\r
+                                               kavgd[ll] = sqrt(square(sectx-newcx)+square(secty-newcy));\r
+                                               kdist[ll] = kavgd[ll];\r
+                                               skip(1);\r
+                                               break;\r
+                               }\r
+                       }\r
+               if (top == top2) break;\r
+               bot = top + 1;\r
+               top = top2;\r
+       }\r
+       if (kount==0) return;\r
+\r
+       /* Starship affected by nova -- kick it away. */\r
+       dist = kount*0.1;\r
+       if (icx) icx = (icx < 0 ? -1 : 1);\r
+       if (icy) icy = (icy < 0 ? -1 : 1);\r
+       direc = course[3*(icx+1)+icy+2];\r
+       if (direc == 0.0) dist = 0.0;\r
+       if (dist == 0.0) return;\r
+       Time = 10.0*dist/16.0;\r
+       skip(1);\r
+       prout("Force of nova displaces starship.");\r
+       iattak=2;       /* Eliminates recursion problem */\r
+       move();\r
+       Time = 10.0*dist/16.0;\r
+       return;\r
+}\r
+       \r
+       \r
+void snova(int insx, int insy) {\r
+       int comdead, nqx, nqy, nsx, nsy, num, kldead, iscdead;\r
+       int nrmdead, npdead;\r
+       int insipient=0;\r
+\r
+       nsx = insy;\r
+       nsy = insy;\r
+\r
+       if (insy== 0) {\r
+               if (insx == 1) {\r
+                       /* NOVAMAX being used */\r
+                       nqx = probecx;\r
+                       nqy = probecy;\r
+               }\r
+               else {\r
+                       int stars = 0;\r
+                       /* Scheduled supernova -- select star */\r
+                       /* logic changed here so that we won't favor quadrants in top\r
+                       left of universe */\r
+                       for (nqx = 1; nqx<=8; nqx++) {\r
+                               for (nqy = 1; nqy<=8; nqy++) {\r
+                                       stars += d.galaxy[nqx][nqy] % 10;\r
+                               }\r
+                       }\r
+                       if (stars == 0) return; /* nothing to supernova exists */\r
+                       num = Rand()*stars + 1;\r
+                       for (nqx = 1; nqx<=8; nqx++) {\r
+                               for (nqy = 1; nqy<=8; nqy++) {\r
+                                       num -= d.galaxy[nqx][nqy] % 10;\r
+                                       if (num <= 0) break;\r
+                               }\r
+                               if (num <=0) break;\r
+                       }\r
+#ifdef DEBUG\r
+                       if (idebug) {\r
+                               proutn("Super nova here?");\r
+                               if (ja()==1) {\r
+                                       nqx = quadx;\r
+                                       nqy = quady;\r
+                               }\r
+                       }\r
+#endif\r
+               }\r
+\r
+               if (nqx != quady || nqy != quady || justin != 0) {\r
+                       /* it isn't here, or we just entered (treat as inroute) */\r
+                       if (damage[DRADIO] == 0.0 || condit == IHDOCKED) {\r
+                               skip(1);\r
+                               proutn("Message from Starfleet Command       Stardate ");\r
+                               cramf(d.date, 0, 1);\r
+                               skip(1);\r
+                               proutn("     Supernova in");\r
+                               cramlc(1, nqx, nqy);\r
+                               prout("; caution advised.");\r
+                       }\r
+               }\r
+               else {\r
+                       /* we are in the quadrant! */\r
+                       insipient = 1;\r
+                       num = Rand()* (d.galaxy[nqx][nqy]%10) + 1;\r
+                       for (nsx=1; nsx < 10; nsx++) {\r
+                               for (nsy=1; nsy < 10; nsy++) {\r
+                                       if (quad[nsx][nsy]==IHSTAR) {\r
+                                               num--;\r
+                                               if (num==0) break;\r
+                                       }\r
+                               }\r
+                               if (num==0) break;\r
+                       }\r
+               }\r
+       }\r
+       else {\r
+               insipient = 1;\r
+       }\r
+\r
+       if (insipient) {\r
+               skip(1);\r
+               prouts("***RED ALERT!  RED ALERT!");\r
+               skip(1);\r
+               proutn("***Incipient supernova detected at");\r
+               cramlc(2, nsx, nsy);\r
+               skip(1);\r
+               nqx = quadx;\r
+               nqy = quady;\r
+               if (square(nsx-sectx) + square(nsy-secty) <= 2.1) {\r
+                       proutn("Emergency override attempts t");\r
+                       prouts("***************");\r
+                       skip(1);\r
+                       stars();\r
+                       alldone=1;\r
+               }\r
+       }\r
+       /* destroy any Klingons in supernovaed quadrant */\r
+       num=d.galaxy[nqx][nqy];\r
+       kldead = num/100;\r
+       comdead = iscdead = 0;\r
+       if (nqx==d.isx && nqy == d.isy) {\r
+               /* did in the Supercommander! */\r
+               d.nscrem = d.isx = d.isy = isatb = iscate = 0;\r
+               iscdead = 1;\r
+               future[FSCMOVE] = future[FSCDBAS] = 1e30;\r
+       }\r
+       d.remkl -= kldead;\r
+       if (d.remcom) {\r
+               int maxloop = d.remcom, l;\r
+               for (l = 1; l <= maxloop; l++) {\r
+                       if (d.cx[l] == nqx && d.cy[l] == nqy) {\r
+                               d.cx[l] = d.cx[d.remcom];\r
+                               d.cy[l] = d.cy[d.remcom];\r
+                               d.cx[d.remcom] = d.cy[d.remcom] = 0;\r
+                               d.remcom--;\r
+                               kldead--;\r
+                               comdead++;\r
+                               if (d.remcom==0) future[FTBEAM] = 1e30;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       /* destroy Romulans and planets in supernovaed quadrant */\r
+       num = d.newstuf[nqx][nqy];\r
+       d.newstuf[nqx][nqy] = 0;\r
+       nrmdead = num/10;\r
+       d.nromrem -= nrmdead;\r
+       npdead = num - nrmdead*10;\r
+       if (npdead) {\r
+               int l;\r
+               for (l = 1; l <= inplan; l++)\r
+                       if (d.plnets[l].x == nqx && d.plnets[l].y == nqy) {\r
+                               d.plnets[l] = nulplanet;\r
+                       }\r
+       }\r
+       /* Destroy any base in supernovaed quadrant */\r
+       if (d.rembase) {\r
+               int maxloop = d.rembase, l;\r
+               for (l = 1; l <= maxloop; l++)\r
+                       if (d.baseqx[l]==nqx && d.baseqy[l]==nqy) {\r
+                               d.baseqx[l] = d.baseqx[d.rembase];\r
+                               d.baseqy[l] = d.baseqy[d.rembase];\r
+                               d.baseqx[d.rembase] = d.baseqy[d.rembase] = 0;\r
+                               d.rembase--;\r
+                               break;\r
+                       }\r
+       }\r
+       /* If starship caused supernova, tally up destruction */\r
+       if (insx) {\r
+               num = d.galaxy[nqx][nqy] % 100;\r
+               d.starkl += num % 10;\r
+               d.basekl += num/10;\r
+               d.killk += kldead;\r
+               d.killc += comdead;\r
+               d.nromkl += nrmdead;\r
+               d.nplankl += npdead;\r
+               d.nsckill += iscdead;\r
+       }\r
+       /* mark supernova in galaxy and in star chart */\r
+       if ((quadx == nqx && quady == nqy) ||\r
+               damage[DRADIO] == 0 ||\r
+               condit == IHDOCKED)\r
+               starch[nqx][nqy] = 1;\r
+       d.galaxy[nqx][nqy] = 1000;\r
+       /* If supernova destroys last klingons give special message */\r
+       if (d.remkl==0 && (nqx != quadx || nqy != quady)) {\r
+               skip(2);\r
+               if (insx == 0) prout("Lucky you!");\r
+               proutn("A supernova in");\r
+               cramlc(1, nqx, nqy);\r
+               prout(" has just destroyed the last Klingons.");\r
+               finish(FWON);\r
+               return;\r
+       }\r
+       /* if some Klingons remain, continue or die in supernova */\r
+       if (alldone) finish(FSNOVAED);\r
+       return;\r
+}\r
+               \r
+                               \r
diff --git a/finish.c b/finish.c
new file mode 100644 (file)
index 0000000..1d58840
--- /dev/null
+++ b/finish.c
@@ -0,0 +1,447 @@
+#include "sst.h"\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+void dstrct() {\r
+       /* Finish with a BANG! */\r
+       chew();\r
+       if (damage[DCOMPTR] != 0.0) {\r
+               prout("Computer damaged; cannot execute destruct sequence.");\r
+               return;\r
+       }\r
+       skip(1);\r
+       prouts("---WORKING---"); skip(1);\r
+       prout("SELF-DESTRUCT-SEQUENCE-ACTIVATED");\r
+       prouts("   10"); skip(1);\r
+       prouts("       9"); skip(1);\r
+       prouts("          8"); skip(1);\r
+       prouts("             7"); skip(1);\r
+       prouts("                6"); skip(1);\r
+       prout("ENTER-CORRECT-PASSWORD-TO-CONTINUE-");\r
+       prout("SELF-DESTRUCT-SEQUENCE-OTHERWISE-");\r
+       prout("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED");\r
+       scan();\r
+       chew();\r
+       if (strcmp(passwd, citem) != 0) {\r
+               prouts("PASSWORD-REJECTED;"); skip(1);\r
+               prout("CONTINUITY-EFFECTED");\r
+               skip(1);\r
+               return;\r
+       }\r
+       prouts("PASSWORD-ACCEPTED"); skip(1);\r
+       prouts("                   5"); skip(1);\r
+       prouts("                      4"); skip(1);\r
+       prouts("                         3"); skip(1);\r
+       prouts("                            2"); skip(1);\r
+       prouts("                              1"); skip(1);\r
+       if (Rand() < 0.15) {\r
+               prouts("GOODBYE-CRUEL-WORLD");\r
+               skip(1);\r
+       }\r
+       skip(2);\r
+       kaboom();\r
+}\r
+\r
+void kaboom(void) {\r
+       stars();\r
+       if (ship==IHE) prouts("***");\r
+       prouts("********* Entropy of ");\r
+       crmshp();\r
+       prouts(" maximized *********");\r
+       skip(1);\r
+       stars();\r
+       skip(1);\r
+       if (nenhere != 0) {\r
+               double whammo = 25.0 * energy;\r
+               int l=1;\r
+               while (l <= nenhere) {\r
+                       if (kpower[l]*kdist[l] <= whammo) \r
+                               deadkl(kx[l],ky[l], quad[kx[l]][ky[l]], kx[l], ky[l]);\r
+                       l++;\r
+               }\r
+       }\r
+       finish(FDILITHIUM);\r
+}\r
+                               \r
+\r
+void finish(FINTYPE ifin) {\r
+       int igotit = 0;\r
+       alldone = 1;\r
+       skip(3);\r
+       printf("It is stardate %.1f .\n\n", d.date);\r
+       switch (ifin) {\r
+               case FWON: // Game has been won\r
+                       if (d.nromrem != 0)\r
+                               printf("The remaining %d Romulans surrender to Starfleet Command.\n",\r
+                                          d.nromrem);\r
+                       \r
+                       prout("You have smashed the Klingon invasion fleet and saved");\r
+                       prout("the Federation.");\r
+                       gamewon=1;\r
+                       if (alive) {\r
+                               double badpt;\r
+                               badpt = 5.*d.starkl + casual + 10.*d.nplankl +\r
+                                               45.*nhelp+100.*d.basekl;\r
+                               if (ship == IHF) badpt += 100.0;\r
+                               else if (ship == 0) badpt += 200.0;\r
+                               if (badpt < 100.0) badpt = 0.0; // Close enough!\r
+                               if (d.date-indate < 5.0 ||\r
+                                       // killsPerDate >= RateMax\r
+                                       (d.killk+d.killc+d.nsckill)/(d.date-indate) >=\r
+                                       0.1*skill*(skill+1.0) + 0.1 + 0.008*badpt) {\r
+                                       skip(1);\r
+                                       prout("In fact, you have done so well that Starfleet Command");\r
+                                       switch (skill) {\r
+                                               case 1:\r
+                                                       prout("promotes you one step in rank from \"Novice\" to \"Fair\".");\r
+                                                       break;\r
+                                               case 2:\r
+                                                       prout("promotes you one step in rank from \"Fair\" to \"Good\".");\r
+                                                       break;\r
+                                               case 3:\r
+                                                       prout("promotes you one step in rank from \"Good\" to \"Expert\".");\r
+                                                       break;\r
+                                               case 4:\r
+                                                       prout("promotes you to Commodore Emeritus.");\r
+                                                       skip(1);\r
+                                                       prout("Now that you think you're really good, try playing");\r
+                                                       prout("the \"Emeritus\" game. It will splatter your ego.");\r
+                                                       break;\r
+                                               case 5:\r
+                                                       skip(1);\r
+                                                       prout("Computer-  ERROR-ERROR-ERROR-ERROR");\r
+                                                       skip(1);\r
+                                                       prout("  YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM");\r
+                                                       prout("  THIS-PROGRAM-MUST-SURVIVE");\r
+                                                       prout("  THIS-PROGRAM-MUST-SURVIVE");\r
+                                                       prout("  THIS-PROGRAM-MUST-SURVIVE");\r
+                                                       prout("  THIS-PROGRAM-MUST?- MUST ? - SUR? ? -?  VI");\r
+                                                       skip(1);\r
+                                                       prout("Now you can retire and write your own Star Trek game!");\r
+                                                       skip(1);\r
+                                                       break;\r
+                                       }\r
+                                       if (skill > 3) {\r
+                                               if (thawed\r
+#ifdef DEBUG\r
+                                                       && !idebug\r
+#endif\r
+                                                       )\r
+                                                       prout("You cannot get a citation, so...");\r
+                                               else {\r
+                                                       prout("Do you want your Commodore Emeritus Citation printed?");\r
+                                                       proutn("(You need a 132 column printer.)");\r
+                                                       chew();\r
+                                                       if (ja()) {\r
+                                                               igotit = 1;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                               // Only grant long life if alive (original didn't!)\r
+                               skip(1);\r
+                               prout("LIVE LONG AND PROSPER.");\r
+                       }\r
+                       score();\r
+                       if (igotit != 0) plaque();\r
+                       return;\r
+               case FDEPLETE: // Federation Resources Depleted\r
+                       prout("Your time has run out and the Federation has been");\r
+                       prout("conquered.  Your starship is now Klingon property,");\r
+                       prout("and you are put on trial as a war criminal.  On the");\r
+                       proutn("basis of your record, you are ");\r
+                       if (d.remkl*3.0 > inkling) {\r
+                               prout("aquitted.");\r
+                               skip(1);\r
+                               prout("LIVE LONG AND PROSPER.");\r
+                       }\r
+                       else {\r
+                               prout("found guilty and");\r
+                               prout("sentenced to death by slow torture.");\r
+                               alive = 0;\r
+                       }\r
+                       score();\r
+                       return;\r
+               case FLIFESUP:\r
+                       prout("Your life support reserves have run out, and");\r
+                       prout("you die of thirst, starvation, and asphyxiation.");\r
+                       prout("Your starship is a derelict in space.");\r
+                       break;\r
+               case FNRG:\r
+                       prout("Your energy supply is exhausted.");\r
+                       skip(1);\r
+                       prout("Your starship is a derelict in space.");\r
+                       break;\r
+               case FBATTLE:\r
+                       proutn("The ");\r
+                       crmshp();\r
+                       prout("has been destroyed in battle.");\r
+                       skip(1);\r
+                       prout("Dulce et decorum est pro patria mori.");\r
+                       break;\r
+               case FNEG3:\r
+                       prout("You have made three attempts to cross the negative energy");\r
+                       prout("barrier which surrounds the galaxy.");\r
+                       skip(1);\r
+                       prout("Your navigation is abominable.");\r
+                       score();\r
+                       return;\r
+               case FNOVA:\r
+                       prout("Your starship has been destroyed by a nova.");\r
+                       prout("That was a great shot.");\r
+                       skip(1);\r
+                       break;\r
+               case FSNOVAED:\r
+                       proutn("The ");\r
+                       crmshp();\r
+                       prout(" has been fried by a supernova.");\r
+                       prout("...Not even cinders remain...");\r
+                       break;\r
+               case FABANDN:\r
+                       prout("You have been captured by the Klingons. If you still");\r
+                       prout("had a starbase to be returned to, you would have been");\r
+                       prout("repatriated and given another chance. Since you have");\r
+                       prout("no starbases, you will be mercilessly tortured to death.");\r
+                       break;\r
+               case FDILITHIUM:\r
+                       prout("Your starship is now an expanding cloud of subatomic particles");\r
+                       break;\r
+               case FMATERIALIZE:\r
+                       prout("Starbase was unable to re-materialize your starship.");\r
+                       prout("Sic transit gloria muntdi");\r
+                       break;\r
+               case FPHASER:\r
+                       proutn("The ");\r
+                       crmshp();\r
+                       prout(" has been cremated by its own phasers.");\r
+                       break;\r
+               case FLOST:\r
+                       prout("You and your landing party have been");\r
+                       prout("converted to energy, disipating through space.");\r
+                       break;\r
+               case FMINING:\r
+                       prout("You are left with your landing party on");\r
+                       prout("a wild jungle planet inhabited by primitive cannibals.");\r
+                       skip(1);\r
+                       prout("They are very fond of \"Captain Kirk\" soup.");\r
+                       skip(1);\r
+                       proutn("Without your leadership, the ");\r
+                       crmshp();\r
+                       prout(" is destroyed.");\r
+                       break;\r
+               case FDPLANET:\r
+                       prout("You and your mining party perish.");\r
+                       skip(1);\r
+                       prout("That was a great shot.");\r
+                       skip(1);\r
+                       break;\r
+               case FSSC:\r
+                       prout("The Galileo is instantly annihilated by the supernova.");\r
+                       // no break;\r
+               case FPNOVA:\r
+                       prout("You and your mining party are atomized.");\r
+                       skip(1);\r
+                       proutn("Mr. Spock takes command of the ");\r
+                       crmshp();\r
+                       prout(" and");\r
+                       prout("joins the Romulans, reigning terror on the Federation.");\r
+                       break;\r
+               case FSTRACTOR:\r
+                       prout("The shuttle craft Galileo is also caught,");\r
+                       prout("and breaks up under the strain.");\r
+                       skip(1);\r
+                       prout("Your debris is scattered for millions of miles.");\r
+                       proutn("Without your leadership, the ");\r
+                       crmshp();\r
+                       prout(" is destroyed.");\r
+                       break;\r
+               case FDRAY:\r
+                       prout("The mutants attack and kill Spock.");\r
+                       prout("Your ship is captured by Klingons, and");\r
+                       prout("your crew is put on display in a Klingon zoo.");\r
+                       break;\r
+               case FTRIBBLE:\r
+                       prout("Tribbles consume all remaining water,");\r
+                       prout("food, and oxygen on your ship.");\r
+                       skip(1);\r
+                       prout("You die of thirst, starvation, and asphyxiation.");\r
+                       prout("Your starship is a derelict in space.");\r
+                       break;\r
+               case FHOLE:\r
+                       prout("Your ship is drawn to the center of the black hole.");\r
+                       prout("You are crushed into extremely dense matter.");\r
+                       break;\r
+       }\r
+       if (ship==IHF) ship= 0;\r
+       else if (ship == IHE) ship = IHF;\r
+       alive = 0;\r
+       if (d.remkl != 0) {\r
+               double goodies = d.remres/inresor;\r
+               double baddies = (d.remkl + 2.0*d.remcom)/(inkling+2.0*incom);\r
+               if (goodies/baddies >= 1.0+0.5*Rand()) {\r
+                       prout("As a result of your actions, a treaty with the Klingon");\r
+                       prout("Empire has been signed. The terms of the treaty are");\r
+                       if (goodies/baddies >= 3.0+Rand()) {\r
+                               prout("favorable to the Federation.");\r
+                               skip(1);\r
+                               prout("Congratulations!");\r
+                       }\r
+                       else\r
+                               prout("highly unfavorable to the Federation.");\r
+               }\r
+               else\r
+                       prout("The Federation will be destroyed.");\r
+       }\r
+       else {\r
+               prout("Since you took the last Klingon with you, you are a");\r
+               prout("martyr and a hero. Someday maybe they'll erect a");\r
+               prout("statue in your memory. Rest in peace, and try not");\r
+               prout("to think about pigeons.");\r
+               gamewon = 1;\r
+       }\r
+       score();\r
+}\r
+\r
+void score(void) {\r
+       double timused = d.date - indate;\r
+       int ithperd, iwon, klship;\r
+\r
+       pause(0);\r
+\r
+       iskill = skill;\r
+       if ((timused == 0 || d.remkl != 0) && timused < 5.0) timused = 5.0;\r
+       perdate = (d.killc + d.killk + d.nsckill)/timused;\r
+       ithperd = 500*perdate + 0.5;\r
+       iwon = 0;\r
+       if (gamewon) iwon = 100*skill;\r
+       if (ship == IHE) klship = 0;\r
+       else if (ship == IHF) klship = 1;\r
+       else klship = 2;\r
+       if (gamewon == 0) d.nromrem = 0; // None captured if no win\r
+       iscore = 10*d.killk + 50*d.killc + ithperd + iwon\r
+                        - 100*d.basekl - 100*klship - 45*nhelp -5*d.starkl - casual\r
+                        + 20*d.nromkl + 200*d.nsckill - 10*d.nplankl + d.nromrem;\r
+       if (alive == 0) iscore -= 200;\r
+       skip(2);\r
+       prout("Your score --");\r
+       if (d.nromkl)\r
+               printf("%6d Romulans destroyed                 %5d\n",\r
+                          d.nromkl,20*d.nromkl);\r
+       if (d.nromrem)\r
+               printf("%6d Romulans captured                  %5d\n",\r
+                          d.nromrem, d.nromrem);\r
+       if (d.killk)\r
+               printf("%6d ordinary Klingons destroyed        %5d\n",\r
+                          d.killk, 10*d.killk);\r
+       if (d.killc)\r
+               printf("%6d Klingon commanders destroyed       %5d\n",\r
+                          d.killc, 50*d.killc);\r
+       if (d.nsckill)\r
+               printf("%6d Super-Commander destroyed          %5d\n",\r
+                          d.nsckill, 200*d.nsckill);\r
+       if (ithperd)\r
+               printf("%6.2f Klingons per stardate              %5d\n",\r
+                          perdate, ithperd);\r
+       if (d.starkl)\r
+               printf("%6d stars destroyed by your action     %5d\n",\r
+                          d.starkl, -5*d.starkl);\r
+       if (d.nplankl)\r
+               printf("%6d planets destroyed by your action   %5d\n",\r
+                          d.nplankl, -10*d.nplankl);\r
+       if (d.basekl)\r
+               printf("%6d bases destroyed by your action     %5d\n",\r
+                          d.basekl, -100*d.basekl);\r
+       if (nhelp)\r
+               printf("%6d calls for help from starbase       %5d\n",\r
+                          nhelp, -45*nhelp);\r
+       if (casual)\r
+               printf("%6d casualties incurred                %5d\n",\r
+                          casual, -casual);\r
+       if (klship)\r
+               printf("%6d ship(s) lost or destroyed          %5d\n",\r
+                          klship, -100*klship);\r
+       if (alive==0)\r
+               prout("Penalty for getting yourself killed        -200");\r
+       if (gamewon) {\r
+               skip(1);\r
+               proutn("Bonus for winning ");\r
+               switch (skill) {\r
+                       case 1: proutn("Novice game  "); break;\r
+                       case 2: proutn("Fair game    "); break;\r
+                       case 3: proutn("Good game    "); break;\r
+                       case 4: proutn("Expert game  "); break;\r
+                       case 5: proutn("Emeritus game"); break;\r
+               }\r
+               printf("           %5d\n", iwon);\r
+       }\r
+       skip(2);\r
+       printf("TOTAL SCORE                               %5d\n", iscore);\r
+}\r
+\r
+void plaque(void) {\r
+       FILE *fp=NULL;\r
+       time_t t;\r
+       char *timestring;\r
+       int nskip;\r
+       char winner[128];\r
+\r
+       skip(2);\r
+       \r
+       while (fp == NULL) {\r
+               printf("File or device name for your plaque:");\r
+               fgets(winner, 128, stdin);\r
+               winner[strlen(winner)-1] = '\0';\r
+               fp = fopen(winner, "w");\r
+               if (fp==NULL) {\r
+                       printf("Invalid name.\n");\r
+               }\r
+       }\r
+\r
+       printf("Enter name to go on plaque (up to 30 characters):");\r
+       fgets(winner, 128, stdin);\r
+       winner[strlen(winner)-1] = '\0';\r
+       winner[30] = '\0';\r
+       nskip = 64 - strlen(winner)/2;\r
+\r
+       fprintf(fp,"\n\n\n\n");\r
+       /* --------DRAW ENTERPRISE PICTURE. */\r
+       fprintf(fp, "                                                                EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" );\r
+       fprintf(fp, "                                      EEE                      E  : :                                         :  E\n" );\r
+       fprintf(fp, "                                    EE   EEE                   E  : :                   NCC-1701              :  E\n");\r
+       fprintf(fp, "                    EEEEEEEEEEEEEEEE        EEEEEEEEEEEEEEE    E  : :                                         : E\n");\r
+       fprintf(fp, "                     E                                     E    EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n");\r
+       fprintf(fp, "                      EEEEEEEEE               EEEEEEEEEEEEE                 E  E\n");\r
+       fprintf(fp, "                               EEEEEEE   EEEEE    E          E              E  E\n");\r
+       fprintf(fp, "                                      EEE           E          E            E  E\n");\r
+       fprintf(fp, "                                                       E         E          E  E\n");\r
+       fprintf(fp, "                                                         EEEEEEEEEEEEE      E  E\n");\r
+       fprintf(fp, "                                                      EEE :           EEEEEEE  EEEEEEEE\n");\r
+       fprintf(fp, "                                                    :E    :                 EEEE       E\n");\r
+       fprintf(fp, "                                                   .-E   -:-----                       E\n");\r
+       fprintf(fp, "                                                    :E    :                            E\n");\r
+       fprintf(fp, "                                                      EE  :                    EEEEEEEE\n");\r
+       fprintf(fp, "                                                       EEEEEEEEEEEEEEEEEEEEEEE\n");\r
+       fprintf(fp, "\n\n\n");\r
+       fprintf(fp, "                                                       U. S. S. ENTERPRISE\n");\r
+       fprintf(fp, "\n\n\n\n");\r
+       fprintf(fp, "                                  For demonstrating outstanding ability as a starship captain\n");\r
+       fprintf(fp, "\n");\r
+       fprintf(fp, "                                                Starfleet Command bestows to you\n");\r
+       fprintf(fp, "\n");\r
+       fprintf(fp,"%*s%s\n\n", nskip, "", winner);\r
+       fprintf(fp, "                                                           the rank of\n\n");\r
+       fprintf(fp, "                                                       \"Commodore Emeritus\"\n\n");\r
+       fprintf(fp, "                                                          ");\r
+       switch (iskill) {\r
+               case 4: fprintf(fp," Expert level\n\n"); break;\r
+               case 5: fprintf(fp,"Emeritus level\n\n"); break;\r
+               default: fprintf(fp," Cheat level\n\n"); break;\r
+       }\r
+       t = time(NULL);\r
+       timestring = ctime(&t);\r
+       fprintf(fp, "                                                 This day of %.6s %.4s, %.8s\n\n",\r
+                       timestring+4, timestring+20, timestring+11);\r
+       fprintf(fp,"                                                        Your score:  %d\n\n", iscore);\r
+       fprintf(fp,"                                                    Klingons per stardate:  %.2f\n", perdate);\r
+       fclose(fp);\r
+}\r
diff --git a/linux.c b/linux.c
new file mode 100644 (file)
index 0000000..9bd3b13
--- /dev/null
+++ b/linux.c
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+#include <time.h>
+#include <sys/ioctl.h>
+
+void randomize(void) {
+       srand((int)time(NULL));
+}
+
+
+int max(int a, int b) {
+       if (a > b) return a;
+       return b;
+}
+
+int min(int a, int b) {
+       if (a < b) return a;
+       return b;
+}
+
+int 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 (file)
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 (file)
index 0000000..fae20ff
--- /dev/null
+++ b/moving.c
@@ -0,0 +1,966 @@
+#include "sst.h"\r
+\r
+static void getcd(int, int);\r
+\r
+void move(void) {\r
+       double angle, deltax, deltay, bigger, x, y,\r
+       finald, finalx, finaly, stopegy;\r
+       int trbeam = 0, n, l, ix, iy, kink, kinks, iquad;\r
+\r
+       if (inorbit) {\r
+               prout("SULU- \"Leaving standard orbit.\"");\r
+               inorbit = 0;\r
+       }\r
+\r
+       angle = ((15.0 - direc) * 0.5235988);\r
+       deltax = -sin(angle);\r
+       deltay = cos(angle);\r
+       if (fabs(deltax) > fabs(deltay))\r
+               bigger = fabs(deltax);\r
+       else\r
+               bigger = fabs(deltay);\r
+               \r
+       deltay /= bigger;\r
+       deltax /= bigger;\r
+\r
+       /* If tractor beam is to occur, don't move full distance */\r
+       if (d.date+Time >= future[FTBEAM]) {\r
+               trbeam = 1;\r
+               condit = IHRED;\r
+               dist = dist*(future[FTBEAM]-d.date)/Time + 0.1;\r
+               Time = future[FTBEAM] - d.date + 1e-5;\r
+       }\r
+       /* Move within the quadrant */\r
+       quad[sectx][secty] = IHDOT;\r
+       x = sectx;\r
+       y = secty;\r
+       n = 10.0*dist*bigger+0.5;\r
+\r
+       if (n > 0) {\r
+               for (l = 1; l <= n; l++) {\r
+                       ix = (x += deltax) + 0.5;\r
+                       iy = (y += deltay) + 0.5;\r
+                       if (ix < 1 || ix > 10 || iy < 1 || iy > 10) {\r
+                               /* Leaving quadrant -- allow final enemy attack */\r
+                               /* Don't do it if being pushed by Nova */\r
+                               if (nenhere != 0 && iattak != 2) {\r
+                                       newcnd();\r
+                                       for (l = 1; l <= nenhere; l++) {\r
+                                               finald = sqrt((ix-kx[l])*(double)(ix-kx[l]) +\r
+                                                                         (iy-ky[l])*(double)(iy-ky[l]));\r
+                                               kavgd[l] = 0.5 * (finald+kdist[l]);\r
+                                       }\r
+                                       if (d.galaxy[quadx][quady] != 1000) attack(0);\r
+                                       if (alldone) return;\r
+                               }\r
+                               /* compute final position -- new quadrant and sector */\r
+                               x = 10*(quadx-1)+sectx;\r
+                               y = 10*(quady-1)+secty;\r
+                               ix = x+10.0*dist*bigger*deltax+0.5;\r
+                               iy = y+10.0*dist*bigger*deltay+0.5;\r
+                               /* check for edge of galaxy */\r
+                               kinks = 0;\r
+                               do {\r
+                                       kink = 0;\r
+                                       if (ix <= 0) {\r
+                                               ix = -ix + 1;\r
+                                               kink = 1;\r
+                                       }\r
+                                       if (iy <= 0) {\r
+                                               iy = -iy + 1;\r
+                                               kink = 1;\r
+                                       }\r
+                                       if (ix > 80) {\r
+                                               ix = 161 - ix;\r
+                                               kink = 1;\r
+                                       }\r
+                                       if (iy > 80) {\r
+                                               iy = 161 - iy;\r
+                                               kink = 1;\r
+                                       }\r
+                                       if (kink) kinks = 1;\r
+                               } while (kink);\r
+\r
+                               if (kinks) {\r
+                                       nkinks += 1;\r
+                                       if (nkinks == 3) {\r
+                                               /* Three strikes -- you're out! */\r
+                                               finish(FNEG3);\r
+                                               return;\r
+                                       }\r
+                                       prout("\nYOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER\n"\r
+                                                "AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,\n"\r
+                                                "YOU WILL BE DESTROYED.\n");\r
+                               }\r
+                               /* Compute final position in new quadrant */\r
+                               if (trbeam) return; /* Don't bother if we are to be beamed */\r
+                               quadx = (ix+9)/10;\r
+                               quady = (iy+9)/10;\r
+                               sectx = ix - 10*(quadx-1);\r
+                               secty = iy - 10*(quady-1);\r
+                               proutn("\nEntering");\r
+                               cramlc(1, quadx, quady);\r
+                               skip(1);\r
+                               quad[sectx][secty] = ship;\r
+                               newqad(0);\r
+                               return;\r
+                       }\r
+                       iquad = quad[ix][iy];\r
+                       if (iquad != IHDOT) {\r
+                               /* object encountered in flight path */\r
+                               stopegy = 50.0*dist/Time;\r
+                               dist=0.1*sqrt((sectx-ix)*(double)(sectx-ix) +\r
+                                                         (secty-iy)*(double)(secty-iy));\r
+                               switch (iquad) {\r
+                                       case IHT: /* Ram a Tholean */\r
+                                       case IHK: /* Ram enemy ship */\r
+                                       case IHC:\r
+                                       case IHS:\r
+                                       case IHR:\r
+                                               sectx = ix;\r
+                                               secty = iy;\r
+                                               ram(0, iquad, sectx, secty);\r
+                                               finalx = sectx;\r
+                                               finaly = secty;\r
+                                               break;\r
+                                       case IHBLANK:\r
+                                               skip(1);\r
+                                               prouts("***RED ALERT!  RED ALERT!");\r
+                                               skip(1);\r
+                                               proutn("***");\r
+                                               crmshp();\r
+                                               proutn(" pulled into black hole at");\r
+                                               cramlc(2, ix, iy);\r
+                                               skip(1);\r
+                                               finish(FHOLE);\r
+                                               return;\r
+                                       default:\r
+                                               /* something else */\r
+                                               skip(1);\r
+                                               crmshp();\r
+                                               if (iquad == IHWEB)\r
+                                                       proutn(" encounters Tholian web at");\r
+                                               else\r
+                                                       proutn(" blocked by object at");\r
+                                               cramlc(2, ix,iy);\r
+                                               prout(";");\r
+                                               proutn("Emergency stop required ");\r
+                                               cramf(stopegy, 0, 2);\r
+                                               prout(" units of energy.");\r
+                                               energy -= stopegy;\r
+                                               finalx = x-deltax+0.5;\r
+                                               sectx = finalx;\r
+                                               finaly = y-deltay+0.5;\r
+                                               secty = finaly;\r
+                                               if (energy <= 0) {\r
+                                                       finish(FNRG);\r
+                                                       return;\r
+                                               }\r
+                                               break;\r
+                               }\r
+                               goto label100;  /* sorry! */\r
+                       }\r
+               }\r
+               dist = 0.1*sqrt((sectx-ix)*(double)(sectx-ix) +\r
+                                               (secty-iy)*(double)(secty-iy));\r
+               sectx = ix;\r
+               secty = iy;\r
+       }\r
+       finalx = sectx;\r
+       finaly = secty;\r
+label100:\r
+       /* No quadrant change -- compute new avg enemy distances */\r
+       quad[sectx][secty] = ship;\r
+       if (nenhere) {\r
+               for (l = 1; l <= nenhere; l++) {\r
+                       finald = sqrt((ix-kx[l])*(double)(ix-kx[l]) +\r
+                                                 (iy-ky[l])*(double)(iy-ky[l]));\r
+                       kavgd[l] = 0.5 * (finald+kdist[l]);\r
+                       kdist[l] = finald;\r
+               }\r
+               sortkl();\r
+               if (d.galaxy[quadx][quady] != 1000 && iattak == 0)\r
+                       attack(0);\r
+               for (l = 1 ; l <= nenhere; l++) kavgd[l] = kdist[l];\r
+       }\r
+       newcnd();\r
+       iattak = 0;\r
+       return;\r
+}\r
+\r
+void dock(void) {\r
+       chew();\r
+       if (condit == IHDOCKED) {\r
+               prout("Already docked.");\r
+               return;\r
+       }\r
+       if (inorbit) {\r
+               prout("You must first leave standard orbit.");\r
+               return;\r
+       }\r
+       if (basex==0 || abs(sectx-basex) > 1 || abs(secty-basey) > 1) {\r
+               crmshp();\r
+               prout(" not adjacent to base.");\r
+               return;\r
+       }\r
+       condit = IHDOCKED;\r
+       prout("Docked.");\r
+       if (energy < inenrg) energy = inenrg;\r
+       shield = inshld;\r
+       torps = intorps;\r
+       lsupres = inlsr;\r
+       if (stdamtim != 1e30 &&\r
+               (future[FCDBAS] < 1e30 || isatb == 1) && iseenit == 0) {\r
+               /* get attack report from base */\r
+               prout("Lt. Uhura- \"Captain, an important message from the starbase:\"");\r
+               attakreport();\r
+               iseenit = 1;\r
+       }\r
+}\r
+\r
+static void getcd(int isprobe, int akey) {\r
+       /* This program originally required input in terms of a (clock)\r
+          direction and distance. Somewhere in history, it was changed to\r
+          cartesian coordinates. So we need to convert. I think\r
+          "manual" input should still be done this way -- it's a real\r
+          pain if the computer isn't working! Manual mode is still confusing\r
+          because it involves giving x and y motions, yet the coordinates\r
+          are always displayed y - x, where +y is downward! */\r
+\r
+       \r
+       int irowq=quadx, icolq=quady, irows, icols, itemp=0, iprompt=0, key;\r
+       double xi, xj, xk, xl;\r
+       double deltax, deltay;\r
+       int automatic = -1;\r
+\r
+       /* Get course direction and distance. If user types bad values, return\r
+          with DIREC = -1.0. */\r
+\r
+       direc = -1.0;\r
+       \r
+       if (landed == 1 && !isprobe) {\r
+               prout("Dummy! You can't leave standard orbit until you");\r
+               proutn("are back abourt the ");\r
+               crmshp();\r
+               prout(".");\r
+               chew();\r
+               return;\r
+       }\r
+       while (automatic == -1) {\r
+               if (damage[DCOMPTR]) {\r
+                       if (isprobe)\r
+                               prout("Computer damaged; manual navigation only");\r
+                       else\r
+                               prout("Computer damaged; manual movement only");\r
+                       chew();\r
+                       automatic = 0;\r
+                       key = IHEOL;\r
+                       break;\r
+               }\r
+               if (isprobe && akey != -1) {\r
+                       /* For probe launch, use pre-scaned value first time */\r
+                       key = akey;\r
+                       akey = -1;\r
+               }\r
+               else \r
+                       key = scan();\r
+\r
+               if (key == IHEOL) {\r
+                       proutn("Manual or automatic- ");\r
+                       iprompt = 1;\r
+                       chew();\r
+               }\r
+               else if (key == IHALPHA) {\r
+                       if (isit("manual")) {\r
+                               automatic =0;\r
+                               key = scan();\r
+                               break;\r
+                       }\r
+                       else if (isit("automatic")) {\r
+                               automatic = 1;\r
+                               key = scan();\r
+                               break;\r
+                       }\r
+                       else {\r
+                               huh();\r
+                               chew();\r
+                               return;\r
+                       }\r
+               }\r
+               else { /* numeric */\r
+                       if (isprobe)\r
+                               prout("(Manual navigation assumed.)");\r
+                       else\r
+                               prout("(Manual movement assumed.)");\r
+                       automatic = 0;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (automatic) {\r
+               while (key == IHEOL) {\r
+                       if (isprobe)\r
+                               proutn("Target quadrant or quadrant&sector- ");\r
+                       else\r
+                               proutn("Destination sector or quadrant&sector- ");\r
+                       chew();\r
+                       iprompt = 1;\r
+                       key = scan();\r
+               }\r
+\r
+               if (key != IHREAL) {\r
+                       huh();\r
+                       return;\r
+               }\r
+               xi = aaitem;\r
+               key = scan();\r
+               if (key != IHREAL){\r
+                       huh();\r
+                       return;\r
+               }\r
+               xj = aaitem;\r
+               key = scan();\r
+               if (key == IHREAL) {\r
+                       /* both quadrant and sector specified */\r
+                       xk = aaitem;\r
+                       key = scan();\r
+                       if (key != IHREAL) {\r
+                               huh();\r
+                               return;\r
+                       }\r
+                       xl = aaitem;\r
+\r
+                       irowq = xi + 0.5;\r
+                       icolq = xj + 0.5;\r
+                       irows = xk + 0.5;\r
+                       icols = xl + 0.5;\r
+               }\r
+               else {\r
+                       if (isprobe) {\r
+                               /* only quadrant specified -- go to center of dest quad */\r
+                               irowq = xi + 0.5;\r
+                               icolq = xj + 0.5;\r
+                               irows = icols = 5;\r
+                       }\r
+                       else {\r
+                               irows = xi + 0.5;\r
+                               icols = xj + 0.5;\r
+                       }\r
+                       itemp = 1;\r
+               }\r
+               if (irowq<1 || irowq > 8 || icolq<1 || icolq > 8 ||\r
+                       irows<1 || irows > 10 || icols<1 || icols > 10) {\r
+                               huh();\r
+                               return;\r
+                       }\r
+               skip(1);\r
+               if (!isprobe) {\r
+                       if (itemp) {\r
+                               if (iprompt) {\r
+                                       proutn("Helmsman Sulu- \"Course locked in for");\r
+                                       cramlc(2, irows, icols);\r
+                                       prout(".\"");\r
+                               }\r
+                       }\r
+                       else prout("Ensign Chekov- \"Course laid in, Captain.\"");\r
+               }\r
+               deltax = icolq - quady + 0.1*(icols-secty);\r
+               deltay = quadx - irowq + 0.1*(sectx-irows);\r
+       }\r
+       else { /* manual */\r
+               while (key == IHEOL) {\r
+                       proutn("X and Y displacements- ");\r
+                       chew();\r
+                       iprompt = 1;\r
+                       key = scan();\r
+               }\r
+               itemp = 2;\r
+               if (key != IHREAL) {\r
+                       huh();\r
+                       return;\r
+               }\r
+               deltax = aaitem;\r
+               key = scan();\r
+               if (key != IHREAL) {\r
+                       huh();\r
+                       return;\r
+               }\r
+               deltay = aaitem;\r
+       }\r
+       /* Check for zero movement */\r
+       if (deltax == 0 && deltay == 0) {\r
+               chew();\r
+               return;\r
+       }\r
+       if (itemp == 2 && !isprobe) {\r
+               skip(1);\r
+               prout("Helmsman Sulu- \"Aye, Sir.\"");\r
+       }\r
+       dist = sqrt(deltax*deltax + deltay*deltay);\r
+       direc = atan2(deltax, deltay)*1.90985932;\r
+       if (direc < 0.0) direc += 12.0;\r
+       chew();\r
+       return;\r
+\r
+}\r
+               \r
+\r
+\r
+void impuls(void) {\r
+       double power;\r
+\r
+       ididit = 0;\r
+       if (damage[DIMPULS]) {\r
+               chew();\r
+               skip(1);\r
+               prout("Engineer Scott- \"The impulse engines are damaged, Sir.\"");\r
+               return;\r
+       }\r
+\r
+       if (energy > 30.0) {\r
+               getcd(FALSE, 0);\r
+               if (direc == -1.0) return;\r
+               power = 20.0 + 100.0*dist;\r
+       }\r
+       else\r
+               power = 30.0;\r
+\r
+       if (power >= energy) {\r
+               /* Insufficient power for trip */\r
+               skip(1);\r
+               prout("First Officer Spock- \"Captain, the impulse engines");\r
+               prout("require 20.0 units to engage, plus 100.0 units per");\r
+               if (energy > 30) {\r
+                       proutn("quadrant.  We can go, therefore, a maximum of ");\r
+                       cramf(0.01 * (energy-20.0)-0.05, 0, 1);\r
+                       prout(" quadrants.\"");\r
+               }\r
+               else {\r
+                       prout("quadrant.  They are, therefore, useless.\"");\r
+               }\r
+               chew();\r
+               return;\r
+       }\r
+       /* Make sure enough time is left for the trip */\r
+       Time = dist/0.095;\r
+       if (Time >= d.remtime) {\r
+               prout("First Officer Spock- \"Captain, our speed under impulse");\r
+               prout("power is only 0.95 sectors per stardate. Are you sure");\r
+               prout("we dare spend the time?\"");\r
+               if (ja() == 0) return;\r
+       }\r
+       /* Activate impulse engines and pay the cost */\r
+       move();\r
+       ididit = 1;\r
+       if (alldone) return;\r
+       power = 20.0 + 100.0*dist;\r
+       energy -= power;\r
+       Time = dist/0.095;\r
+       if (energy <= 0) finish(FNRG);\r
+       return;\r
+}\r
+\r
+\r
+void warp(int i) {\r
+       int blooey=0, twarp=0, iwarp;\r
+       double power;\r
+\r
+       if (i!=2) { /* Not WARPX entry */\r
+               ididit = 0;\r
+               if (damage[DWARPEN] > 10.0) {\r
+                       chew();\r
+                       skip(1);\r
+                       prout("Engineer Scott- \"The impulse engines are damaged, Sir.\"");\r
+                       return;\r
+               }\r
+               if (damage[DWARPEN] > 0.0 && warpfac > 4.0) {\r
+                       chew();\r
+                       skip(1);\r
+                       prout("Engineer Scott- \"Sorry, Captain. Until this damage");\r
+                       prout("  is repaired, I can only give you warp 4.\"");\r
+                       return;\r
+               }\r
+                       \r
+               /* Read in course and distance */\r
+               getcd(FALSE, 0);\r
+               if (direc == -1.0) return;\r
+\r
+               /* Make sure starship has enough energy for the trip */\r
+               power = (dist+0.05)*warpfac*warpfac*warpfac*(shldup+1);\r
+\r
+\r
+               if (power >= energy) {\r
+                       /* Insufficient power for trip */\r
+                       ididit = 0;\r
+                       skip(1);\r
+                       prout("Engineering to bridge--");\r
+                       if (shldup==0 || 0.5*power > energy) {\r
+                               iwarp = pow((energy/(dist+0.05)), 0.333333333);\r
+                               if (iwarp <= 0) {\r
+                                       prout("We can't do it, Captain. We haven't the energy.");\r
+                               }\r
+                               else {\r
+                                       proutn("We haven't the energy, but we could do it at warp ");\r
+                                       crami(iwarp, 1);\r
+                                       if (shldup)\r
+                                               prout(",\nif you'll lower the shields.");\r
+                                       else\r
+                                               prout(".");\r
+                               }\r
+                       }\r
+                       else\r
+                               prout("We haven't the energy to go that far with the shields up.");\r
+                       return;\r
+               }\r
+                                               \r
+               /* Make sure enough time is left for the trip */\r
+               Time = 10.0*dist/wfacsq;\r
+               if (Time >= 0.8*d.remtime) {\r
+                       skip(1);\r
+                       prout("First Officer Spock- \"Captain, I compute that such");\r
+                       proutn("  a trip would require approximately ");\r
+                       cramf(100.0*Time/d.remtime, 0, 2);\r
+                       prout(" percent of our");\r
+                       prout("  remaining time.  Are you sure this is wise?\"");\r
+                       if (ja() == 0) { ididit = 0; return;}\r
+               }\r
+       }\r
+       /* Entry WARPX */\r
+       if (warpfac > 6.0) {\r
+               /* Decide if engine damage will occur */\r
+               double prob = dist*(6.0-warpfac)*(6.0-warpfac)/66.666666666;\r
+               if (prob > Rand()) {\r
+                       blooey = 1;\r
+                       dist = Rand()*dist;\r
+               }\r
+               /* Decide if time warp will occur */\r
+               if (0.5*dist*pow(7.0,warpfac-10.0) > Rand()) twarp=1;\r
+#ifdef DEBUG\r
+               if (idebug &&warpfac==10 && twarp==0) {\r
+                       blooey=0;\r
+                       proutn("Force time warp? ");\r
+                       if (ja()==1) twarp=1;\r
+               }\r
+#endif\r
+               if (blooey || twarp) {\r
+                       /* If time warp or engine damage, check path */\r
+                       /* If it is obstructed, don't do warp or damage */\r
+                       double angle = ((15.0-direc)*0.5235998);\r
+                       double deltax = -sin(angle);\r
+                       double deltay = cos(angle);\r
+                       double bigger, x, y;\r
+                       int n, l, ix, iy;\r
+                       if (fabs(deltax) > fabs(deltay))\r
+                               bigger = fabs(deltax);\r
+                       else\r
+                               bigger = fabs(deltay);\r
+                       \r
+                       deltax /= bigger;\r
+                       deltay /= bigger;\r
+                       n = 10.0 * dist * bigger +0.5;\r
+                       x = sectx;\r
+                       y = secty;\r
+                       for (l = 1; l <= n; l++) {\r
+                               x += deltax;\r
+                               ix = x + 0.5;\r
+                               if (ix < 1 || ix > 10) break;\r
+                               y += deltay;\r
+                               iy = y +0.5;\r
+                               if (iy < 1 || iy > 10) break;\r
+                               if (quad[ix][iy] != IHDOT) {\r
+                                       blooey = 0;\r
+                                       twarp = 0;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+                               \r
+\r
+       /* Activate Warp Engines and pay the cost */\r
+       move();\r
+       if (alldone) return;\r
+       energy -= dist*warpfac*warpfac*warpfac*(shldup+1);\r
+       if (energy <= 0) finish(FNRG);\r
+       Time = 10.0*dist/wfacsq;\r
+       if (twarp) timwrp();\r
+       if (blooey) {\r
+               damage[DWARPEN] = damfac*(3.0*Rand()+1.0);\r
+               skip(1);\r
+               prout("Engineering to bridge--");\r
+               prout("  Scott here.  The warp engines are damaged.");\r
+               prout("  We'll have to reduce speed to warp 4.");\r
+       }\r
+       ididit = 1;\r
+       return;\r
+}\r
+\r
+\r
+\r
+void setwrp(void) {\r
+       int key;\r
+       double oldfac;\r
+       \r
+       while ((key=scan()) == IHEOL) {\r
+               chew();\r
+               proutn("Warp factor-");\r
+       }\r
+       chew();\r
+       if (key != IHREAL) {\r
+               huh();\r
+               return;\r
+       }\r
+       if (damage[DWARPEN] > 10.0) {\r
+               prout("Warp engines inoperative.");\r
+               return;\r
+       }\r
+       if (damage[DWARPEN] > 0.0 && aaitem > 4.0) {\r
+               prout("Engineer Scott- \"I'm doing my best, Captain,\n"\r
+                         "  but right now we can only go warp 4.\"");\r
+               return;\r
+       }\r
+       if (aaitem > 10.0) {\r
+               prout("Helmsman Sulu- \"Our top speed is warp 10, Captain.\"");\r
+               return;\r
+       }\r
+       if (aaitem < 1.0) {\r
+               prout("Helmsman Sulu- \"We can't go below warp 1, Captain.\"");\r
+               return;\r
+       }\r
+       oldfac = warpfac;\r
+       warpfac = aaitem;\r
+       wfacsq=warpfac*warpfac;\r
+       if (warpfac <= oldfac || warpfac <= 6.0) {\r
+               proutn("Helmsman Sulu- \"Warp factor ");\r
+               cramf(warpfac, 0, 1);\r
+               prout(", Captain.\"");\r
+               return;\r
+       }\r
+       if (warpfac < 8.00) {\r
+               prout("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\"");\r
+               return;\r
+       }\r
+       if (warpfac == 10.0) {\r
+               prout("Engineer Scott- \"Aye, Captain, we'll try it.\"");\r
+               return;\r
+       }\r
+       prout("Engineer Scott- \"Aye, Captain, but our engines may not take it.\"");\r
+       return;\r
+}\r
+\r
+void atover(int igrab) {\r
+       double power, distreq;\r
+\r
+       chew();\r
+       /* is captain on planet? */\r
+       if (landed==1) {\r
+               if (damage[DTRANSP]) {\r
+                       finish(FPNOVA);\r
+                       return;\r
+               }\r
+               prout("Scotty rushes to the transporter controls.");\r
+               if (shldup) {\r
+                       prout("But with the shields up it's hopeless.");\r
+                       finish(FPNOVA);\r
+               }\r
+               prouts("His desperate attempt to rescue you . . .");\r
+               if (Rand() <= 0.5) {\r
+                       prout("fails.");\r
+                       finish(FPNOVA);\r
+                       return;\r
+               }\r
+               prout("SUCCEEDS!");\r
+               if (imine) {\r
+                       imine = 0;\r
+                       proutn("The crystals mined were ");\r
+                       if (Rand() <= 0.25) {\r
+                               prout("lost.");\r
+                       }\r
+                       else {\r
+                               prout("saved.");\r
+                               icrystl = 1;\r
+                       }\r
+               }\r
+       }\r
+       if (igrab) return;\r
+\r
+       /* Check to see if captain in shuttle craft */\r
+       if (icraft) finish(FSTRACTOR);\r
+       if (alldone) return;\r
+\r
+       /* Inform captain of attempt to reach safety */\r
+       skip(1);\r
+       do {\r
+               if (justin) {\r
+                       prouts("***RED ALERT!  READ ALERT!");\r
+                       skip(1);\r
+                       proutn("The ");\r
+                       crmshp();\r
+                       prout(" has stopped in a quadrant containing");\r
+                       prouts("   a supernova.");\r
+                       skip(2);\r
+               }\r
+               proutn("***Emergency automatic override attempts to hurl ");\r
+               crmshp();\r
+               skip(1);\r
+               prout("safely out of quadrant.");\r
+               starch[quadx][quady] = damage[DRADIO] > 0.0 ? d.galaxy[quadx][quady]+1000:1;\r
+\r
+               /* Try to use warp engines */\r
+               if (damage[DWARPEN]) {\r
+                       skip(1);\r
+                       prout("Warp engines damaged.");\r
+                       finish(FSNOVAED);\r
+                       return;\r
+               }\r
+               warpfac = 6.0+2.0*Rand();\r
+               wfacsq = warpfac * warpfac;\r
+               proutn("Warp factor set to ");\r
+               cramf(warpfac, 1, 1);\r
+               skip(1);\r
+               power = 0.75*energy;\r
+               dist = power/(warpfac*warpfac*warpfac*(shldup+1));\r
+               distreq = 1.4142+Rand();\r
+               if (distreq < dist) dist = distreq;\r
+               Time = 10.0*dist/wfacsq;\r
+               direc = 12.0*Rand();    /* How dumb! */\r
+               justin = 0;\r
+               inorbit = 0;\r
+               warp(2);\r
+               if (justin == 0) {\r
+                       /* This is bad news, we didn't leave quadrant. */\r
+                       if (alldone) return;\r
+                       skip(1);\r
+                       prout("Insufficient energy to leave quadrant.");\r
+                       finish(FSNOVAED);\r
+                       return;\r
+               }\r
+               /* Repeat if another snova */\r
+       } while (d.galaxy[quadx][quady] == 1000);\r
+       if (d.remkl==0) finish(FWON); /* Snova killed remaining enemy. */\r
+}\r
+\r
+void timwrp() {\r
+       int l, ll, gotit;\r
+       prout("***TIME WARP ENTERED.");\r
+       if (d.snap && Rand() < 0.5) {\r
+               /* Go back in time */\r
+               proutn("You are traveling backwards in time ");\r
+               cramf(d.date-snapsht.date, 0, 2);\r
+               prout(" stardates.");\r
+               d = snapsht;\r
+               d.snap = 0;\r
+               if (d.remcom) {\r
+                       future[FTBEAM] = d.date + expran(intime/d.remcom);\r
+                       future[FBATTAK] = d.date + expran(0.3*intime);\r
+               }\r
+               future[FSNOVA] = d.date + expran(0.5*intime);\r
+               future[FSNAP] = d.date +expran(0.25*d.remtime); /* next snapshot will\r
+                                                                                                          be sooner */\r
+               if (d.nscrem) future[FSCMOVE] = 0.2777;\r
+               isatb = 0;\r
+               future[FCDBAS] = future[FSCDBAS] = 1e30;\r
+               batx = baty = 0;\r
+\r
+               /* Make sure Galileo is consistant -- Snapshot may have been taken\r
+                  when on planet, which would give us two Galileos! */\r
+               gotit = 0;\r
+               for (l = 1; l <= inplan; l++) {\r
+                       if (d.plnets[l].known == 2) {\r
+                               gotit = 1;\r
+                               if (iscraft==1 && ship==IHE) {\r
+                                       prout("Checkov-  \"Security reports the Galileo has disappeared, Sir!");\r
+                                       iscraft = 0;\r
+                               }\r
+                       }\r
+               }\r
+               /* Likewise, if in the original time the Galileo was abandoned, but\r
+                  was on ship earlier, it would have vanished -- lets restore it */\r
+               if (iscraft==0 && gotit==0 && damage[DSHUTTL] >= 0.0) {\r
+                       prout("Checkov-  \"Security reports the Galileo has reappeared in the dock!\"");\r
+                       iscraft = 1;\r
+               }\r
+\r
+               /* Revert star chart to earlier era, if it was known then*/\r
+               if (damage[DRADIO]==0.0 || stdamtim > d.date) {\r
+                       for (l = 1; l <= 8; l++)\r
+                               for (ll = 1; ll <= 8; ll++)\r
+                                       if (starch[l][ll] > 1)\r
+                                               starch[l][ll]=damage[DRADIO]>0.0 ? d.galaxy[l][ll]+1000 :1;\r
+                       prout("Spock has reconstructed a correct star chart from memory");\r
+                       if (damage[DRADIO] > 0.0) stdamtim = d.date;\r
+               }\r
+       }\r
+       else {\r
+               /* Go forward in time */\r
+               Time = -0.5*intime*log(Rand());\r
+               proutn("You are traveling forward in time ");\r
+               cramf(Time, 1, 2);\r
+               prout(" stardates.");\r
+               /* cheat to make sure no tractor beams occur during time warp */\r
+               future[FTBEAM] += Time;\r
+               damage[DRADIO] += Time;\r
+       }\r
+       newqad(0);\r
+}\r
+\r
+void probe(void) {\r
+       double angle, bigger;\r
+       int key;\r
+       /* New code to launch a deep space probe */\r
+       if (nprobes == 0) {\r
+               chew();\r
+               skip(1);\r
+               if (ship == IHE) \r
+                       prout("Engineer Scott- \"We have no more deep space probes, Sir.\"");\r
+               else\r
+                       prout("Ye Faerie Queene has no deep space probes.");\r
+               return;\r
+       }\r
+       if (damage[DDSP] != 0.0) {\r
+               chew();\r
+               skip(1);\r
+               prout("Engineer Scott- \"The probe launcher is damaged, Sir.\"");\r
+               return;\r
+       }\r
+       if (future[FDSPROB] != 1e30) {\r
+               chew();\r
+               skip(1);\r
+               if (damage[DRADIO] != 0 && condit != IHDOCKED) {\r
+                       prout("Spock-  \"Records show the previous probe has not yet");\r
+                       prout("   reached it's destination.\"");\r
+               }\r
+               else\r
+                       prout("Uhura- \"The previous probe is still reporting data, Sir.\"");\r
+               return;\r
+       }\r
+       key = scan();\r
+\r
+       if (key == IHEOL) {\r
+               /* slow mode, so let Kirk know how many probes there are left */\r
+               crami(nprobes,1);\r
+               prout(nprobes==1 ? " probe left." : " probes left.");\r
+               proutn("Are you sure you want to fire a probe? ");\r
+               if (ja()==0) return;\r
+       }\r
+\r
+       isarmed = FALSE;\r
+       if (key == IHALPHA && strcmp(citem,"armed") == 0) {\r
+               isarmed = TRUE;\r
+               key = scan();\r
+       }\r
+       else if (key == IHEOL) {\r
+               proutn("Arm NOVAMAX warhead?");\r
+               isarmed = ja();\r
+       }\r
+       getcd(TRUE, key);\r
+       if (direc == -1.0) return;\r
+       nprobes--;\r
+               angle = ((15.0 - direc) * 0.5235988);\r
+       probeinx = -sin(angle);\r
+       probeiny = cos(angle);\r
+       if (fabs(probeinx) > fabs(probeiny))\r
+               bigger = fabs(probeinx);\r
+       else\r
+               bigger = fabs(probeiny);\r
+               \r
+       probeiny /= bigger;\r
+       probeinx /= bigger;\r
+       proben = 10.0*dist*bigger +0.5;\r
+       probex = quadx*10 + sectx - 1;  // We will use better packing than original\r
+       probey = quady*10 + secty - 1;\r
+       probecx = quadx;\r
+       probecy = quady;\r
+       future[FDSPROB] = d.date + 0.01; // Time to move one sector\r
+       prout("Ensign Chekov-  \"The deep space probe is launched, Captain.\"");\r
+       return;\r
+}\r
+\r
+void help(void) {\r
+       /* There's more than one way to move in this game! */\r
+       double ddist, xdist, probf;\r
+       int line, l, ix, iy;\r
+\r
+       chew();\r
+       /* Test for conditions which prevent calling for help */\r
+       if (condit == IHDOCKED) {\r
+               prout("Lt. Uhura-  \"But Captain, we're already docked.\"");\r
+               return;\r
+       }\r
+       if (damage[DRADIO] != 0) {\r
+               prout("Subspace radio damaged.");\r
+               return;\r
+       }\r
+       if (d.rembase==0) {\r
+               prout("Lt. Uhura-  \"Captain, I'm not getting any response from Starbase.\"");\r
+               return;\r
+       }\r
+       if (landed == 1) {\r
+               proutn("You must be aboard the ");\r
+               crmshp();\r
+               prout(".");\r
+               return;\r
+       }\r
+       /* OK -- call for help from nearest starbase */\r
+       nhelp++;\r
+       if (basex!=0) {\r
+               /* There's one in this quadrant */\r
+               ddist = sqrt(square(basex-sectx)+square(basey-secty));\r
+       }\r
+       else {\r
+               ddist = 1e30;\r
+               for (l = 1; l <= d.rembase; l++) {\r
+                       xdist=10.0*sqrt(square(d.baseqx[l]-quadx)+square(d.baseqy[l]-quady));\r
+                       if (xdist < ddist) {\r
+                               ddist = xdist;\r
+                               line = l;\r
+                       }\r
+               }\r
+               /* Since starbase not in quadrant, set up new quadrant */\r
+               quadx = d.baseqx[line];\r
+               quady = d.baseqy[line];\r
+               newqad(1);\r
+       }\r
+       /* dematerialize starship */\r
+       quad[sectx][secty]=IHDOT;\r
+       proutn("Starbase in");\r
+       cramlc(1, quadx, quady);\r
+       proutn(" responds--");\r
+       crmshp();\r
+       prout(" dematerializes.");\r
+       /* Give starbase three chances to rematerialize starship */\r
+       probf = pow((1.0 - pow(0.98,ddist)), 0.33333333);\r
+       for (l = 1; l <= 3; l++) {\r
+               switch (l) {\r
+                       case 1: proutn("1st"); break;\r
+                       case 2: proutn("2nd"); break;\r
+                       case 3: proutn("3rd"); break;\r
+               }\r
+               proutn(" attempt to re-materialize ");\r
+               crmshp();\r
+               prouts(" . . . . . ");\r
+               if (Rand() > probf) break;\r
+               prout("fails.");\r
+       }\r
+       if (l > 3) {\r
+               finish(FMATERIALIZE);\r
+               return;\r
+       }\r
+       /* Rematerialization attempt should succeed if can get adj to base */\r
+       for (l = 1; l <= 5; l++) {\r
+               ix = basex+3.0*Rand()-1;\r
+               iy = basey+3.0*Rand()-1;\r
+               if (ix>=1 && ix<=10 && iy>=1 && iy<=10 && quad[ix][iy]==IHDOT) {\r
+                       /* found one -- finish up */\r
+                       prout("succeeds.");\r
+                       sectx=ix;\r
+                       secty=iy;\r
+                       quad[ix][iy]=ship;\r
+                       dock();\r
+                       skip(1);\r
+                       prout("Lt. Uhura-  \"Captain, we made it!\"");\r
+                       return;\r
+               }\r
+       }\r
+       finish(FMATERIALIZE);\r
+       return;\r
+}\r
diff --git a/os2.c b/os2.c
new file mode 100644 (file)
index 0000000..c6a7835
--- /dev/null
+++ b/os2.c
@@ -0,0 +1,31 @@
+#include <stdlib.h>\r
+#include <time.h>\r
+#include <sys/ioctl.h>\r
+#include <sys/termio.h>\r
+\r
+void randomize(void) {\r
+       srand((int)time(NULL));\r
+}\r
+\r
+\r
+int max(int a, int b) {\r
+       if (a > b) return a;\r
+       return b;\r
+}\r
+\r
+int min(int a, int b) {\r
+       if (a < b) return a;\r
+       return b;\r
+}\r
+\r
+int getch(void) {\r
+       char chbuf[1];\r
+       struct termio oldstate, newstate;\r
+    ioctl(0,TCGETA,&oldstate);\r
+       newstate = oldstate;\r
+       newstate.c_iflag = 0;\r
+       newstate.c_lflag = 0;\r
+       ioctl(0,TCSETA,&newstate);\r
+       read(0, &chbuf, 1);\r
+    ioctl(0,TCSETA,&oldstate);\r
+}
\ No newline at end of file
diff --git a/planets.c b/planets.c
new file mode 100644 (file)
index 0000000..39e0846
--- /dev/null
+++ b/planets.c
@@ -0,0 +1,504 @@
+#include "sst.h"\r
+\r
+static char classes[4][2]={"","M","N","O"};\r
+static int height;\r
+\r
+static int consumeTime(void) {\r
+/* I think most of this avoidance was caused by overlay scheme.\r
+   Let's see what happens if all events can occur here */\r
+\r
+//     double asave;\r
+       ididit = 1;\r
+#if 0\r
+       /* Don't wory about this */\r
+       if (future[FTBEAM] <= d.date+Time && d.remcom != 0 && condit != IHDOCKED) {\r
+               /* We are about to be tractor beamed -- operation fails */\r
+               return 1;\r
+       }\r
+#endif\r
+//     asave = future[FSNOVA];\r
+//     future[FSNOVA] = 1e30; /* defer supernovas */\r
+       events();       /* Used to avoid if future[FSCMOVE] within time */\r
+//     future[FSNOVA] = asave;\r
+       /*fails if game over, quadrant super-novas or we've moved to new quadrant*/\r
+       if (alldone || d.galaxy[quadx][quady] == 1000 || justin != 0) return 1;\r
+       return 0;\r
+}\r
+\r
+void preport(void) {\r
+       int iknow = 0, i;\r
+       skip(1);\r
+       chew();\r
+       prout("Spock-  \"Planet report follows, Captain.\"");\r
+       skip(1);\r
+       for (i = 1; i <= inplan; i++) {\r
+               if (d.plnets[i].known\r
+#ifdef DEBUG\r
+                       || ( idebug && d.plnets[i].x !=0)\r
+#endif\r
+                       ) {\r
+                       iknow = 1;\r
+#ifdef DEBUG\r
+                       if (idebug && d.plnets[i].known==0) proutn("(Unknown) ");\r
+#endif\r
+                       cramlc(1, d.plnets[i].x, d.plnets[i].y);\r
+                       proutn("   class ");\r
+                       proutn(classes[d.plnets[i].pclass]);\r
+                       proutn("   ");\r
+                       if (d.plnets[i].crystals == 0) proutn("no ");\r
+                       prout("dilithium crystals present.");\r
+                       if (d.plnets[i].known==2) \r
+                               prout("    Shuttle Craft Galileo on surface.");\r
+               }\r
+       }\r
+       if (iknow==0) prout("No information available.");\r
+}\r
+\r
+void orbit(void) {\r
+       double asave;\r
+\r
+       skip(1);\r
+       chew();\r
+       ididit=0;\r
+       if (inorbit!=0) {\r
+               prout("Already in standard orbit.");\r
+               return;\r
+       }\r
+       if (damage[DWARPEN] != 0 && damage[DIMPULS] != 0) {\r
+               prout("Both warp and impulse engines damaged.");\r
+               return;\r
+       }\r
+       if (plnetx == 0 || abs(sectx-plnetx) > 1 || abs(secty-plnety) > 1) {\r
+               crmshp();\r
+               prout(" not adjacient to planet.\n");\r
+               return;\r
+       }\r
+       Time = 0.02+0.03*Rand();\r
+       prout("Helmsman Sulu-  \"Entering standard orbit, Sir.\"");\r
+       newcnd();\r
+       if (consumeTime()) return;\r
+       proutn("Sulu-  \"Entered orbit at altitude ");\r
+       cramf(height = (1400.+7200.*Rand()), 0, 2);\r
+       prout(" kilometers.\"");\r
+       inorbit = 1;\r
+       return;\r
+}\r
+\r
+void sensor(void) {\r
+       skip(1);\r
+       chew();\r
+       if (damage[DSRSENS] != 0.0) {\r
+               prout("Short range sensors damaged.");\r
+               return;\r
+       }\r
+       if (plnetx == 0) {\r
+               prout("No planet in this quadrant.");\r
+               return;\r
+       }\r
+       proutn("Spock-  \"Sensor scan for");\r
+       cramlc(1, quadx, quady);\r
+       prout("-");\r
+       skip(1);\r
+       proutn("         Planet at");\r
+       cramlc(2, plnetx, plnety);\r
+       proutn(" is of class ");\r
+       proutn(classes[d.plnets[iplnet].pclass]);\r
+       prout(".");\r
+       if (d.plnets[iplnet].known==2) \r
+               prout("         Sensors show Galileo still on surface.");\r
+       proutn("         Readings indicate");\r
+       if (d.plnets[iplnet].crystals == 0) proutn(" no");\r
+       prout(" dilithium crystals present.\"");\r
+       if (d.plnets[iplnet].known == 0) d.plnets[iplnet].known = 1;\r
+       return;\r
+}\r
+\r
+void beam(void) {\r
+       chew();\r
+       skip(1);\r
+       if (damage[DTRANSP] != 0) {\r
+               prout("Transporter damaged.");\r
+               if (damage[DSHUTTL]==0 && (d.plnets[iplnet].known==2 || iscraft == 1)) {\r
+                       skip(1);\r
+                       prout("Spock-  \"May I suggest the shuttle craft, Sir?\" ");\r
+                       if (ja() != 0) shuttle();\r
+               }\r
+               return;\r
+       }\r
+       if (inorbit==0) {\r
+               crmshp();\r
+               prout(" not in standard orbit.");\r
+               return;\r
+       }\r
+       if (shldup!=0) {\r
+               prout("Impossible to transport through shields.");\r
+               return;\r
+       }\r
+       if (d.plnets[iplnet].known==0) {\r
+               prout("Spock-  \"Captain, we have no information on this planet");\r
+               prout("  and Starfleet Regulations clearly state that in this situation");\r
+               prout("  you may not go down.\"");\r
+               return;\r
+       }\r
+       if (landed==1) {\r
+               /* Coming from planet */\r
+               if (d.plnets[iplnet].known==2) {\r
+                       proutn("Spock-  \"Wouldn't you rather take the Galileo?\" ");\r
+                       if (ja() != 0) {\r
+                               chew();\r
+                               return;\r
+                       }\r
+                       prout("Your crew hides the Galileo to prevent capture by aliens.");\r
+               }\r
+               prout("Landing party assembled, ready to beam up.");\r
+               skip(1);\r
+               prout("Kirk whips out communicator...");\r
+               prouts("BEEP  BEEP  BEEP");\r
+               skip(2);\r
+               prout("\"Kirk to enterprise-  Lock on coordinates...energize.\"");\r
+       }\r
+       else {\r
+               /* Going to planet */\r
+               if (d.plnets[iplnet].crystals==0) {\r
+                       prout("Spock-  \"Captain, I fail to see the logic in");\r
+                       prout("  exploring a planet with no dilithium crystals.");\r
+                       proutn("  Are you sure this is wise?\" ");\r
+                       if (ja()==0) {\r
+                               chew();\r
+                               return;\r
+                       }\r
+               }\r
+               prout("Scotty-  \"Transporter room ready, Sir.\"");\r
+               skip(1);\r
+               prout("Kirk, and landing party prepare to beam down to planet surface.");\r
+               skip(1);\r
+               prout("Kirk-  \"Energize.\"");\r
+       }\r
+       skip(1);\r
+       prouts("WWHOOOIIIIIRRRRREEEE.E.E.  .  .  .  .   .    .");\r
+       skip(2);\r
+       if (Rand() > 0.98) {\r
+               prouts("BOOOIIIOOOIIOOOOIIIOIING . . .");\r
+               skip(2);\r
+               prout("Scotty-  \"Oh my God!  I've lost them.\"");\r
+               finish(FLOST);\r
+               return;\r
+       }\r
+       prouts(".    .   .  .  .  .  .E.E.EEEERRRRRIIIIIOOOHWW");\r
+       skip(2);\r
+       prout("Transport complete.");\r
+       landed = -landed;\r
+       if (landed==1 && d.plnets[iplnet].known==2) {\r
+               prout("The shuttle craft Galileo is here!");\r
+       }\r
+       if (landed!=1 && imine==1) {\r
+               icrystl = 1;\r
+               cryprob = 0.05;\r
+       }\r
+       imine = 0;\r
+       return;\r
+}\r
+\r
+void mine(void) {\r
+\r
+       ididit = 0;\r
+       skip(1);\r
+       chew();\r
+       if (landed!= 1) {\r
+               prout("Mining party not on planet.");\r
+               return;\r
+       }\r
+       if (d.plnets[iplnet].crystals == 0) {\r
+               prout("No dilithium crystals on this planet.");\r
+               return;\r
+       }\r
+       if (imine == 1) {\r
+               prout("You've already mined enough crystals for this trip.");\r
+               return;\r
+       }\r
+       if (icrystl == 1 && cryprob == 0.05) {\r
+               proutn("With all those fresh crystals aboard the ");\r
+               crmshp();\r
+               skip(1);\r
+               prout("there's no reason to mine more at this time.");\r
+               return;\r
+       }\r
+       Time = (0.1+0.2*Rand())*d.plnets[iplnet].pclass;\r
+       if (consumeTime()) return;\r
+       prout("Mining operation complete.");\r
+       imine = 1;\r
+       return;\r
+}\r
+\r
+void usecrystals(void) {\r
+\r
+       skip(1);\r
+       chew();\r
+       if (icrystl!=1) {\r
+               prout("No dilithium crystals available.");\r
+               return;\r
+       }\r
+       if (energy >= 1000) {\r
+               prout("Spock-  \"Captain, Starfleet Regulations prohibit such an operation");\r
+               prout("  except when condition Yellow exists.");\r
+               return;\r
+       }\r
+       prout("Spock- \"Captain, I must warn you that loading");\r
+       prout("  raw dilithium crystals into the ship's power");\r
+       prout("  system may risk a severe explosion.");\r
+       proutn("  Are you sure this is wise?\" ");\r
+       if (ja()==0) {\r
+               chew();\r
+               return;\r
+       }\r
+       skip(1);\r
+       prout("Engineering Officer Scott-  \"(GULP) Aye Sir.");\r
+       prout("  Mr. Spock and I will try it.\"");\r
+       skip(1);\r
+       prout("Spock-  \"Crystals in place, Sir.");\r
+       prout("  Ready to activate circuit.\"");\r
+       skip(1);\r
+       prouts("Scotty-  \"Keep your fingers crossed, Sir!\"");\r
+       skip(1);\r
+       if (Rand() <= cryprob) {\r
+               prouts("  \"Activating now! - - No good!  It's***");\r
+               skip(2);\r
+               prouts("***RED ALERT!  RED A*L********************************");\r
+               skip(1);\r
+               stars();\r
+               prouts("******************   KA-BOOM!!!!   *******************");\r
+               skip(1);\r
+               kaboom();\r
+               return;\r
+       }\r
+       energy += 5000.0*(1.0 + 0.9*Rand());\r
+       prouts("  \"Activating now! - - ");\r
+       prout("The instruments");\r
+       prout("   are going crazy, but I think it's");\r
+       prout("   going to work!!  Congratulations, Sir!\"");\r
+       cryprob *= 2.0;\r
+       return;\r
+}\r
+\r
+void shuttle(void) {\r
+\r
+       chew();\r
+       skip(1);\r
+       ididit = 0;\r
+       if(damage[DSHUTTL] != 0.0) {\r
+               if (damage[DSHUTTL] == -1.0) {\r
+                       if (inorbit && d.plnets[iplnet].known == 2)\r
+                               prout("Ye Faerie Queene has no shuttle craft bay to dock it at.");\r
+                       else\r
+                               prout("Ye Faerie Queene had no shuttle craft.");\r
+               }\r
+               else if (damage[DSHUTTL] > 0)\r
+                       prout("The Galileo is damaged.");\r
+               else prout("Shuttle craft is now serving Big Mac's.");\r
+               return;\r
+       }\r
+       if (inorbit==0) {\r
+               crmshp();\r
+               prout(" not in standard orbit.");\r
+               return;\r
+       }\r
+       if ((d.plnets[iplnet].known != 2) && iscraft != 1) {\r
+               prout("Shuttle craft not currently available.");\r
+               return;\r
+       }\r
+       if (landed==-1 && d.plnets[iplnet].known==2) {\r
+               prout("You will have to beam down to retrieve the shuttle craft.");\r
+               return;\r
+       }\r
+       if (shldup!=0 || condit == IHDOCKED) {\r
+               prout("Shuttle craft cannot pass through shields.");\r
+               return;\r
+       }\r
+       if (d.plnets[iplnet].known==0) {\r
+               prout("Spock-  \"Captain, we have no information on this planet");\r
+               prout("  and Starfleet Regulations clearly state that in this situation");\r
+               prout("  you may not fly down.\"");\r
+               return;\r
+       }\r
+       Time = 3.0e-5*height;\r
+       if (Time >= 0.8*d.remtime) {\r
+               prout("First Officer Spock-  \"Captain, I compute that such");\r
+               prout("  a maneuver would require aproximately ");\r
+               cramf(100*Time/d.remtime,0,4);\r
+               prout("% of our");\r
+               prout("remaining time.");\r
+               prout("Are you sure this is wise?\" ");\r
+               if (ja()==0) {\r
+                       Time = 0.0;\r
+                       return;\r
+               }\r
+       }\r
+       if (landed == 1) {\r
+               /* Kirk on planet */\r
+               if (iscraft==1) {\r
+                       /* Galileo on ship! */\r
+                       if (damage[DTRANSP]==0) {\r
+                               proutn("Spock-  \"Would you rather use the transporter?\" ");\r
+                               if (ja() != 0) {\r
+                                       beam();\r
+                                       return;\r
+                               }\r
+                               proutn("Shuttle crew");\r
+                       }\r
+                       else\r
+                               proutn("Rescue party");\r
+                       prout(" boards Galileo and swoops toward planet surface.");\r
+                       iscraft = 0;\r
+                       skip(1);\r
+                       if (consumeTime()) return;\r
+                       d.plnets[iplnet].known=2;\r
+                       prout("Trip complete.");\r
+                       return;\r
+               }\r
+               else {\r
+                       /* Ready to go back to ship */\r
+                       prout("You and your mining party board the");\r
+                       prout("shuttle craft for the trip back to the Enterprise.");\r
+                       skip(1);\r
+                       prout("The short hop begins . . .");\r
+                       d.plnets[iplnet].known=1;\r
+                       icraft = 1;\r
+                       skip(1);\r
+                       landed = -1;\r
+                       if (consumeTime()) return;\r
+                       iscraft = 1;\r
+                       icraft = 0;\r
+                       if (imine!=0) {\r
+                               icrystl = 1;\r
+                               cryprob = 0.05;\r
+                       }\r
+                       imine = 0;\r
+                       prout("Trip complete.");\r
+                       return;\r
+               }\r
+       }\r
+       else {\r
+               /* Kirk on ship */\r
+               /* and so is Galileo */\r
+               prout("Mining party assembles in the hangar deck,");\r
+               prout("ready to board the shuttle craft \"Galileo\".");\r
+               skip(1);\r
+               prouts("The hangar doors open; the trip begins.");\r
+               skip(1);\r
+               icraft = 1;\r
+               iscraft = 0;\r
+               if (consumeTime()) return;\r
+               d.plnets[iplnet].known = 2;\r
+               landed = 1;\r
+               icraft = 0;\r
+               prout("Trip complete");\r
+               return;\r
+       }\r
+}\r
+               \r
+\r
+void deathray(void) {\r
+       double r = Rand();\r
+       \r
+       ididit = 0;\r
+       skip(1);\r
+       chew();\r
+       if (ship != IHE) {\r
+               prout("Ye Faerie Queene has no death ray.");\r
+               return;\r
+       }\r
+       if (nenhere==0) {\r
+               prout("Sulu-  \"But Sir, there are no enemies in this quadrant.\"");\r
+               return;\r
+       }\r
+       if (damage[DDRAY] > 0.0) {\r
+               prout("Death Ray is damaged.");\r
+               return;\r
+       }\r
+       prout("Spock-  \"Captain, the 'Experimental Death Ray'");\r
+       prout("  is highly unpredictible.  Considering the alternatives,");\r
+       prout("  are you sure this is wise?\" ");\r
+       if (ja()==0) return;\r
+       prout("Spock-  \"Acknowledged.\"");\r
+       skip(1);\r
+       ididit=1;\r
+       prouts("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE");\r
+       skip(1);\r
+       prout("Crew scrambles in emergency preparation.");\r
+       prout("Spock and Scotty ready the death ray and");\r
+       prout("prepare to channel all ship's power to the device.");\r
+       skip(1);\r
+       prout("Spock-  \"Preparations complete, sir.\"");\r
+       prout("Kirk-  \"Engage!\"");\r
+       skip(1);\r
+       prouts("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR");\r
+       skip(1);\r
+       if (r > .30) {\r
+               prouts("Sulu- \"Captain!  It's working!\"");\r
+               skip(2);\r
+               while (nenhere > 0)\r
+                       deadkl(kx[1],ky[1],quad[kx[1]][ky[1]],kx[1],ky[1]);\r
+               prout("Ensign Chekov-  \"Congratulations, Captain!\"");\r
+               if (d.remkl == 0) finish(FWON);\r
+               prout("Spock-  \"Captain, I believe the `Experimental Death Ray'");\r
+               if (Rand() <= 0.05) {\r
+                       prout("   is still operational.\"");\r
+               }\r
+               else {\r
+                       prout("   has been rendered disfunctional.\"");\r
+                       damage[DDRAY] = 39.95;\r
+               }\r
+               return;\r
+       }\r
+       r = Rand();     // Pick failure method \r
+       if (r <= .30) {\r
+               prouts("Sulu- \"Captain!  It's working!\"");\r
+               skip(1);\r
+               prouts("***RED ALERT!  RED ALERT!");\r
+               skip(1);\r
+               prout("***MATTER-ANTIMATTER IMPLOSION IMMINENT!");\r
+               skip(1);\r
+               prouts("***RED ALERT!  RED A*L********************************");\r
+               skip(1);\r
+               stars();\r
+               prouts("******************   KA-BOOM!!!!   *******************");\r
+               skip(1);\r
+               kaboom();\r
+               return;\r
+       }\r
+       if (r <= .55) {\r
+               prouts("Sulu- \"Captain!  Yagabandaghangrapl, brachriigringlanbla!\"");\r
+               skip(1);\r
+               prout("Lt. Uhura-  \"Graaeek!  Graaeek!\"");\r
+               skip(1);\r
+               prout("Spock-  \"Facinating!  . . . All humans aboard");\r
+               prout("  have apparently been transformed into strange mutations.");\r
+               prout("  Vulcans do not seem to be affected.");\r
+               skip(1);\r
+               prout("Kirk-  \"Raauch!  Raauch!\"");\r
+               finish(FDRAY);\r
+               return;\r
+       }\r
+       if (r <= 0.75) {\r
+               int i,j;\r
+               prouts("Sulu- \"Captain!  It's   --WHAT?!?!\"");\r
+               skip(2);\r
+               proutn("Spock-  \"I believe the word is");\r
+               prouts(" *ASTONISHING*");\r
+               prout(" Mr. Sulu.");\r
+               for (i=1; i<=10; i++)\r
+                       for (j=1; j<=10; j++)\r
+                               if (quad[i][j] == IHDOT) quad[i][j] = IHQUEST;\r
+               prout("  Captain, our quadrant is now infested with");\r
+               prouts(" - - - - - -  *THINGS*.");\r
+               skip(1);\r
+               prout("  I have no logical explanation.\"");\r
+               return;\r
+       }\r
+       prouts("Sulu- \"Captain!  The Death Ray is creating tribbles!\"");\r
+       skip(1);\r
+       prout("Scotty-  \"There are so many tribbles down here");\r
+       prout("  in Engineering, we can't move for 'em, Captain.\"");\r
+       finish(FTRIBBLE);\r
+       return;\r
+}\r
diff --git a/reports.c b/reports.c
new file mode 100644 (file)
index 0000000..0c8f606
--- /dev/null
+++ b/reports.c
@@ -0,0 +1,495 @@
+#include "sst.h"\r
+#include <math.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+void attakreport(void) {\r
+       if (future[FCDBAS] < 1e30) {\r
+               proutn("Starbase in ");\r
+               cramlc(1, batx, baty);\r
+               prout(" is currently under attack.");\r
+               proutn("It can hold out until Stardate ");\r
+               cramf(future[FCDBAS], 0,1);\r
+               prout(".");\r
+       }\r
+       if (isatb == 1) {\r
+               proutn("Starbase in ");\r
+               cramlc(1, d.isx, d.isy);\r
+               prout(" is under Super-commander attack.");\r
+               proutn("It can hold out until Stardate ");\r
+               cramf(future[FSCDBAS], 0, 1);\r
+               prout(".");\r
+       }\r
+}\r
+       \r
+\r
+void report(int f) {\r
+       char *s1,*s2,*s3;\r
+\r
+       chew();\r
+       s1 = (thawed?"thawed ":"");\r
+       switch (length) {\r
+               case 1: s2="short"; break;\r
+               case 2: s2="medium"; break;\r
+               case 4: s2="long"; break;\r
+               default: s2="unknown length"; break;\r
+       }\r
+       switch (skill) {\r
+               case 1: s3="novice"; break;\r
+               case 2: s3="fair"; break;\r
+               case 3: s3="good"; break;\r
+               case 4: s3="expert"; break;\r
+               case 5: s3="emeritus"; break;\r
+               default: s3="skilled"; break;\r
+       }\r
+       printf("\nYou %s playing a %s%s %s game.\n",\r
+                  alldone? "were": "are now", s1, s2, s3);\r
+       if (skill>3 && thawed && !alldone) prout("No plaque is allowed.");\r
+       if (tourn) printf("This is tournament game %d.\n", tourn);\r
+       if (f) printf("Your secret password is \"%s\"\n",passwd);\r
+       printf("%d of %d Klingons have been killed",\r
+                  d.killk+d.killc+d.nsckill, inkling);\r
+       if (d.killc) printf(", including %d Commander%s.\n", d.killc, d.killc==1?"":"s");\r
+       else if (d.killk+d.nsckill > 0) prout(", but no Commanders.");\r
+       else prout(".");\r
+       if (skill > 2) printf("The Super Commander has %sbeen destroyed.\n",\r
+                                                 d.nscrem?"not ":"");\r
+       if (d.rembase != inbase) {\r
+               proutn("There ");\r
+               if (inbase-d.rembase==1) proutn("has been 1 base");\r
+               else {\r
+                       proutn("have been ");\r
+                       crami(inbase-d.rembase, 1);\r
+                       proutn(" bases");\r
+               }\r
+               proutn(" destroyed, ");\r
+               crami(d.rembase, 1);\r
+               prout(" remaining.");\r
+       }\r
+       else printf("There are %d bases.\n", inbase);\r
+       if (damage[DRADIO] == 0.0 || condit == IHDOCKED || iseenit) {\r
+               /* Don't report this if not seen and\r
+                       either the radio is dead or not at base! */\r
+               attakreport();\r
+               iseenit = 1;\r
+       }\r
+       if (casual) printf("%d casualt%s suffered so far.\n",\r
+                                          casual, casual==1? "y" : "ies");\r
+       if (nhelp) printf("There were %d call%s for help.\n",\r
+                                         nhelp, nhelp==1 ? "" : "s");\r
+       if (ship == IHE) {\r
+               proutn("You have ");\r
+               if (nprobes) crami(nprobes,1);\r
+               else proutn("no");\r
+               proutn(" deep space probe");\r
+               if (nprobes!=1) proutn("s");\r
+               prout(".");\r
+       }\r
+       if ((damage[DRADIO] == 0.0 || condit == IHDOCKED)&&\r
+               future[FDSPROB] != 1e30) {\r
+               if (isarmed) \r
+                       proutn("An armed deep space probe is in");\r
+               else\r
+                       proutn("A deep space probe is in");\r
+               cramlc(1, probecx, probecy);\r
+               prout(".");\r
+       }\r
+       if (icrystl) {\r
+               if (cryprob <= .05)\r
+                       prout("Dilithium crystals aboard ship...not yet used.");\r
+               else {\r
+                       int i=0;\r
+                       double ai = 0.05;\r
+                       while (cryprob > ai) {\r
+                               ai *= 2.0;\r
+                               i++;\r
+                       }\r
+                       printf("Dilithium crystals have been used %d time%s.\n",\r
+                                  i, i==1? "" : "s");\r
+               }\r
+       }\r
+       skip(1);\r
+}\r
+       \r
+void lrscan(void) {\r
+       int x, y;\r
+       chew();\r
+       if (damage[DLRSENS] != 0.0) {\r
+               /* Now allow base's sensors if docked */\r
+               if (condit != IHDOCKED) {\r
+                       prout("LONG-RANGE SENSORS DAMAGED.");\r
+                       return;\r
+               }\r
+               skip(1);\r
+               proutn("Starbase's long-range scan for");\r
+       }\r
+       else {\r
+               skip(1);\r
+               proutn("Long-range scan for");\r
+       }\r
+       cramlc(1, quadx, quady);\r
+       skip(1);\r
+       for (x = quadx-1; x <= quadx+1; x++) {\r
+               for (y = quady-1; y <= quady+1; y++) {\r
+                       if (x == 0 || x > 8 || y == 0 || y > 8)\r
+                               printf("   -1");\r
+                       else {\r
+                               printf("%5d", d.galaxy[x][y]);\r
+                               starch[x][y] = damage[DRADIO] > 0 ? d.galaxy[x][y]+1000 :1;\r
+                       }\r
+               }\r
+               putchar('\n');\r
+       }\r
+\r
+}\r
+\r
+void dreprt(void) {\r
+       int jdam = FALSE, i;\r
+       chew();\r
+\r
+       for (i = 1; i <= ndevice; i++) {\r
+               if (damage[i] > 0.0) {\r
+                       if (!jdam) {\r
+                               skip(1);\r
+                               prout("DEVICE            -REPAIR TIMES-");\r
+                               prout("                IN FLIGHT   DOCKED");\r
+                               jdam = TRUE;\r
+                       }\r
+                       printf("  %16s ", device[i]);\r
+                       cramf(damage[i]+0.05, 8, 2);\r
+                       proutn("  ");\r
+                       cramf(docfac*damage[i]+0.005, 8, 2);\r
+                       skip(1);\r
+               }\r
+       }\r
+       if (!jdam) prout("All devices functional.");\r
+}\r
+\r
+void chart(int nn) {\r
+       int i,j;\r
+\r
+       chew();\r
+       skip(1);\r
+       if (stdamtim != 1e30 && stdamtim != d.date && condit == IHDOCKED) {\r
+               prout("Spock-  \"I revised the Star Chart from the");\r
+               prout("  starbase's records.\"");\r
+               skip(1);\r
+       }\r
+       if (nn == 0) prout("STAR CHART FOR THE KNOWN GALAXY");\r
+       if (stdamtim != 1e30) {\r
+               if (co