First checkin of experimental event code for the BSDTrek-style Klingons.
authorEric S. Raymond <esr@thyrsus.com>
Sun, 17 Sep 2006 05:14:52 +0000 (05:14 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Sun, 17 Sep 2006 05:14:52 +0000 (05:14 +0000)
E.g the attacks on inhabited systems.  Currently #ifdefed out; the
only operative change is the newkling() function and a bit of
data-structure cleanup.

TODO
src/events.c
src/setup.c
src/sst.h

diff --git a/TODO b/TODO
index 864b2d5251472a6c0c947674b39a95fede61f89d..893194ada70a526b0d0004669b46b4ee75ac46d3 100644 (file)
--- a/TODO
+++ b/TODO
@@ -15,3 +15,7 @@ Long-term items:
 * Russian translation
 
 * Wrap a GUI around it.
+
+* Wandering planet-killer as in "The Doomsday Machine";
+  see <http://www.ericweisstein.com/fun/startrek/TheDoomsdayMachine.html>.
index dc81f56e86dfb70638c872571475c8285555d2b4..5b993d00940591e9e8f2b26df3c6981a8b7aee2a 100644 (file)
@@ -347,6 +347,122 @@ void events(void)
                    return;
            }
            break;
+#ifdef EXPERIMENTAL
+       case FDISTR: /* inhabited system issues distress call */
+           /* in BSD Trek this is a straight 1 stardate ahead */ 
+           game.future[FDISTR] =  game.state.date + 1.0 + Rand();
+           /* if we already have too many, throw this one away */
+           if (game.ndistr >= MAXDISTR)
+               break;
+           /* try a whole bunch of times to find something suitable */
+           for (i = 0; i < 100; i++) {
+               struct quadrant *q;
+               iran(GALSIZE, &ix, &iy);
+               q = &game.state.galaxy[game.quadx][game.quady];
+               /* need a quadrant which is not the current one,
+                  which has some stars which are inhabited and
+                  not already under attack, which is not
+                  supernova'ed, and which has some Klingons in it */
+               if (!((ix == game.quadx && iy == game.quady) || q->stars<=0 ||
+                     (q->qsystemname & Q_DISTRESSED) ||
+                     (q->qsystemname & Q_SYSTEM) == 0 || q->klings <= 0))
+                   break;
+           }
+           if (i >= 100)
+               /* can't seem to find one; ignore this call */
+               break;
+
+           /* got one!!  Schedule its enslavement */
+           game.ndistr++;
+           e = xsched(E_ENSLV, 1, ix, iy, q->qsystemname);
+           q->qsystemname = (e - Event) | Q_DISTRESSED;
+
+           /* tell the captain about it if we can */
+           if (game.damage[DRADIO] == 0.0)
+           {
+               printf("\nUhura: Captain, starsystem %s in quadrant %d,%d is under attack\n",
+                      Systemname[e->systemname], ix, iy);
+               restcancel++;
+           }
+           else
+               /* if we can't tell him, make it invisible */
+               e->evcode |= E_HIDDEN;
+           break;
+      case FENSLV:             /* starsystem is enslaved */
+           unschedule(e);
+           /* see if current distress call still active */
+           q = &Quad[e->x][e->y];
+           if (q->klings <= 0)
+           {
+               /* no Klingons, clean up */
+               /* restore the system name */
+               q->qsystemname = e->systemname;
+               break;
+           }
+
+           /* play stork and schedule the first baby */
+           e = schedule(E_REPRO, Param.eventdly[E_REPRO] * franf(), e->x, e->y, e->systemname);
+
+           /* report the disaster if we can */
+           if (game.damage[DRADIO] == 0.0)
+           {
+               printf("\nUhura:  We've lost contact with starsystem %s\n",
+                      Systemname[e->systemname]);
+               printf("  in quadrant %d,%d.\n", e->x, e->y);
+           }
+           else
+               e->evcode |= E_HIDDEN;
+           break;
+      case FREPRO:             /* Klingon reproduces */
+           /* see if distress call is still active */
+           q = &Quad[e->x][e->y];
+           if (q->klings <= 0)
+           {
+               unschedule(e);
+               q->qsystemname = e->systemname;
+               break;
+           }
+           xresched(e, E_REPRO, 1);
+           /* reproduce one Klingon */
+           ix = e->x;
+           iy = e->y;
+           if (Now.klings == 127)
+               break;          /* full right now */
+           if (q->klings >= MAXKLQUAD)
+           {
+               /* this quadrant not ok, pick an adjacent one */
+               for (i = ix - 1; i <= ix + 1; i++)
+               {
+                   if (!VALID_QUADRANT(i))
+                       continue;
+                   for (j = iy - 1; j <= iy + 1; j++)
+                   {
+                       if (!VALID_QUADRANT(j))
+                           continue;
+                       q = &Quad[i][j];
+                       /* check for this quad ok (not full & no snova) */
+                       if (q->klings >= MAXKLQUAD || q->stars < 0)
+                           continue;
+                       break;
+                   }
+                   if (j <= iy + 1)
+                       break;
+               }
+               if (j > iy + 1)
+                   /* cannot create another yet */
+                   break;
+               ix = i;
+               iy = j;
+           }
+           /* deliver the child */
+           game.remkl++;
+           if (ix == game.quadx && iy == game.quady)
+               newkling(++game.klhere, &ixhold, &iyhold);
+
+           /* recompute time left */
+           game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
+           break;
+#endif /* EXPERIMENTAL */
        }
     }
 }
index 7b28c2d6fab57e377590ffdefa901b422a37563d..2c0f52b7cbace20581370c7dcfb89af00dc0f1f1 100644 (file)
@@ -228,12 +228,16 @@ void setup(int needprompt)
     game.docfac = 0.25;
     for_quadrants(i)
        for_quadrants(j) {
-           game.state.galaxy[i][j].charted = 0;
-           game.state.galaxy[i][j].planet = NULL;
-           game.state.galaxy[i][j].romulans = 0;
-           game.state.galaxy[i][j].klingons = 0;
-           game.state.galaxy[i][j].starbase = 0;
-           game.state.galaxy[i][j].supernova = 0;
+       struct quadrant *quad = &game.state.galaxy[i][j];
+           quad->charted = 0;
+           quad->planet = NULL;
+           quad->romulans = 0;
+           quad->klingons = 0;
+           quad->starbase = 0;
+           quad->supernova = 0;
+#ifdef EXPERIMENTAL
+           quad->status = secure;
+#endif /* EXPERIMENTAL */
        }
     // Initialize times for extraneous events
     game.future[FSNOVA] = game.state.date + expran(0.5 * game.intime);
@@ -244,6 +248,13 @@ void setup(int needprompt)
     game.future[FSCMOVE] = game.state.nscrem ? game.state.date+0.2777 : FOREVER;
     game.future[FSCDBAS] = FOREVER;
     game.future[FDSPROB] = FOREVER;
+#ifdef EXPERIMENTAL
+    if (game.options & OPTION_WORLDS)
+       /* in BSD-Trek, this is a fixed one stardate in the future */
+       game.future[FDISTR] = game.state.date + 1.0 + Rand();
+    game.future[FENSLV] = FOREVER;
+    game.future[FREPRO] = FOREVER;
+#endif /* EXPERIMENTAL */
     // Starchart is functional but we've never seen it
     game.lastchart = FOREVER;
     // Put stars in the galaxy
@@ -537,11 +548,20 @@ void newcnd(void)
     if (!game.alive) game.condit=IHDEAD;
 }
 
+void newkling(int i, int *pix, int *piy)
+/* drop new Klingon into current quadrant */
+{
+    dropin(IHK, pix, piy);
+    game.kx[i] = *pix;
+    game.ky[i] = *piy;
+    game.kdist[i] = game.kavgd[i] = sqrt(square(game.sectx-*pix) + square(game.secty-*piy));
+    game.kpower[i] = Rand()*150.0 +300.0 +25.0*game.skill;
+}
 
 void newqad(int shutup) 
 {
     int i, j, ix, iy;
-    planet *planhere;
+    struct quadrant *here;
 
     game.iattak = 1;
     game.justin = 1;
@@ -570,25 +590,21 @@ void newqad(int shutup)
     for_sectors(i)
        for_sectors(j) 
            game.quad[i][j] = IHDOT;
+    here = &game.state.galaxy[game.quadx][game.quady];
     // cope with supernova
-    if (game.state.galaxy[game.quadx][game.quady].supernova)
+    if (here->supernova)
        return;
-    game.klhere = game.state.galaxy[game.quadx][game.quady].klingons;
-    game.irhere = game.state.galaxy[game.quadx][game.quady].romulans;
+    game.klhere = here->klingons;
+    game.irhere = here->romulans;
     game.nenhere = game.klhere + game.irhere;
 
     // Position Starship
     game.quad[game.sectx][game.secty] = game.ship;
 
-    if (game.state.galaxy[game.quadx][game.quady].klingons) {
+    if (here->klingons) {
        // Position ordinary Klingons
-       for (i = 1; i <= game.klhere; i++) {
-           dropin(IHK, &ix, &iy);
-           game.kx[i] = ix;
-           game.ky[i] = iy;
-           game.kdist[i] = game.kavgd[i] = sqrt(square(game.sectx-ix) + square(game.secty-iy));
-           game.kpower[i] = Rand()*150.0 +300.0 +25.0*game.skill;
-       }
+       for (i = 1; i <= game.klhere; i++)
+           newkling(i, &ix, &iy);
        // If we need a commander, promote a Klingon
        for_commanders(i)
            if (game.state.cx[i]==game.quadx && game.state.cy[i]==game.quady) break;
@@ -616,14 +632,13 @@ void newqad(int shutup)
        game.kpower[i] = Rand()*400.0 + 450.0 + 50.0*game.skill;
     }
     // If quadrant needs a starbase, put it in
-    if (game.state.galaxy[game.quadx][game.quady].starbase)
+    if (here->starbase)
        dropin(IHB, &game.basex, &game.basey);
        
     // If quadrant needs a planet, put it in
-    planhere = game.state.galaxy[game.quadx][game.quady].planet;
-    if (planhere) {
-       game.iplnet = planhere - game.state.plnets;
-       if (planhere->inhabited == UNINHABITED)
+    if (here->planet) {
+       game.iplnet = here->planet - game.state.plnets;
+       if (here->planet->inhabited == UNINHABITED)
            dropin(IHP, &game.plnetx, &game.plnety);
        else
            dropin(IHW, &game.plnetx, &game.plnety);
@@ -631,11 +646,11 @@ void newqad(int shutup)
     // Check for game.condition
     newcnd();
     // And finally the stars
-    for (i = 1; i <= game.state.galaxy[game.quadx][game.quady].stars; i++) 
+    for (i = 1; i <= here->stars; i++) 
        dropin(IHSTAR, &ix, &iy);
 
     // Check for RNZ
-    if (game.irhere > 0 && game.klhere == 0 && (!planhere || planhere->inhabited == UNINHABITED)) {
+    if (game.irhere > 0 && game.klhere == 0 && (!here->planet || here->planet->inhabited == UNINHABITED)) {
        game.neutz = 1;
        if (game.damage[DRADIO] <= 0.0) {
            skip(1);
index 2af0f192703c146121ff4f136b385f11ae53d79b..e9bb3b2e68494474acb86acc5ffe0c22d0a1f915 100644 (file)
--- a/src/sst.h
+++ b/src/sst.h
@@ -72,7 +72,7 @@ typedef struct {
        double date,            // stardate
            remres,             // remaining resources
            remtime;            // remaining time
-    struct {
+    struct quadrant {
        int stars;
        planet *planet;
        int starbase;
@@ -80,6 +80,9 @@ typedef struct {
        int romulans;
        int supernova;
        int charted;
+#ifdef EXPERIMENTAL
+       enum {secure, distressed, enslaved} status;
+#endif /* EXPERIMENTAL */
     } galaxy[GALSIZE+1][GALSIZE+1];    // The Galaxy (subscript 0 not used)
     struct {
        int stars;
@@ -152,7 +155,18 @@ typedef struct {
 #define FSCMOVE 6   // Supercommander moves (might attack base)
 #define FSCDBAS 7   // Supercommander destroys base
 #define FDSPROB 8   // Move deep space probe
+#ifndef EXPERIMENTAL
 #define NEVENTS (9)
+#else /* EXPERIMENTAL */
+#define FDISTR 9   // Emit distress call from an inhabited world 
+#define FENSLV 10  // Inhabited word is enslaved */
+#define FREPRO 11  // Klingons build a ship in an enslaved system
+#define NEVENTS (12)
+#endif /* EXPERIMENTAL */
+
+#ifdef EXPERIMENTAL
+#define        MAXDISTR        5       /* maximum concurrent distress calls */
+#endif /* EXPERIMENTAL */
 
 #define SSTMAGIC       "SST2.0\n"
 
@@ -228,6 +242,9 @@ struct game {
        ithx,           // coordinates of Tholian
        ithy,           //
        iseenit,        // seen base attack report
+#ifdef EXPERIMENTAL
+       ndistr,         //* count of distress calls */ 
+#endif /* EXPERIMENTAL */
        probecx,        // current probe quadrant
        probecy,        //
        proben,         // number of moves for probe
@@ -401,6 +418,7 @@ void commandhook(char *, int);
 void makechart(void);
 void enqueue(char *);
 char *systemname(planet *);
+void newkling(int, int *, int *);
 
 /* mode arguments for srscan() */
 #define SCAN_FULL              1