Checkpoint with several changes, committed so Stas can play with debug code.
authorEric S. Raymond <esr@thyrsus.com>
Mon, 18 Sep 2006 19:38:35 +0000 (19:38 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Mon, 18 Sep 2006 19:38:35 +0000 (19:38 +0000)
1. Change planet member of quadrant struct back to integer so it can be saved.
2. Add code for torpedoing an inhabited world.  Score drops by 400 when you
   do that, it's the only outcome worse than being killed.
3. Events are now structures and can hold quadrant coordinates.
4. EXPERIMENTAL tag is gone, code for BSD-Trek events is in good enough
   shape to test now.
5. User input is always logged.
6. SEED command is implemented.

src/ai.c
src/battle.c
src/events.c
src/finish.c
src/moving.c
src/planets.c
src/reports.c
src/setup.c
src/sst.c
src/sst.h

index 685fe69947d77f8547c34450966ed4dfe6929480..b753b86f3ad8569bc472ab4b7ac4c06949cdd62f 100644 (file)
--- a/src/ai.c
+++ b/src/ai.c
@@ -334,7 +334,7 @@ static bool movescom(coord iq, int flag, int *ipage)
            game.state.plnets[i].crystals == 1) {
            /* destroy the planet */
            DESTROY(&game.state.plnets[i]);
            game.state.plnets[i].crystals == 1) {
            /* destroy the planet */
            DESTROY(&game.state.plnets[i]);
-           game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = NULL;
+           game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = NOPLANET;
            if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) {
                if (*ipage==0) pause_game(1);
                *ipage = 1;
            if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) {
                if (*ipage==0) pause_game(1);
                *ipage = 1;
index c0dac65b0c2f3b2cce110b5053f470fbe9e48021..343c05a3d1cfe3644712f8205c8923546c8de082 100644 (file)
@@ -318,7 +318,7 @@ void torpedo(double course, double r, int inx, int iny, double *hit, int i, int
            crmena(1, iquad, 2, w);
            prout(_(" destroyed."));
            game.state.nplankl++;
            crmena(1, iquad, 2, w);
            prout(_(" destroyed."));
            game.state.nplankl++;
-           game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NULL;
+           game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
            DESTROY(&game.state.plnets[game.iplnet]);
            game.iplnet = 0;
            game.plnet.x = game.plnet.y = 0;
            DESTROY(&game.state.plnets[game.iplnet]);
            game.iplnet = 0;
            game.plnet.x = game.plnet.y = 0;
@@ -328,6 +328,22 @@ void torpedo(double course, double r, int inx, int iny, double *hit, int i, int
                finish(FDPLANET);
            }
            return;
                finish(FDPLANET);
            }
            return;
+       case IHW: /* Hit an inhabited world -- very bad! */
+           crmena(1, iquad, 2, w);
+           prout(_(" destroyed."));
+           game.state.nworldkl++;
+           game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
+           DESTROY(&game.state.plnets[game.iplnet]);
+           game.iplnet = 0;
+           game.plnet.x = game.plnet.y = 0;
+           game.quad[w.x][w.y] = IHDOT;
+           if (game.landed==1) {
+               /* captain perishes on planet */
+               finish(FDPLANET);
+           }
+           prout("You have just destroyed an inhabited planet.");
+           prout("Celebratory rallies are being held on the Klingon homeworld.");
+           return;
        case IHSTAR: /* Hit a star */
            if (Rand() > 0.10) {
                nova(w.x, w.y);
        case IHSTAR: /* Hit a star */
            if (Rand() > 0.10) {
                nova(w.x, w.y);
index 55de8a5040dba6dcabff12602849fd685be7e1e4..cc299cfc73ceceb142af6168f875c18c93d03bc0 100644 (file)
@@ -1,34 +1,51 @@
 #include "sst.h"
 #include <math.h>
 
 #include "sst.h"
 #include <math.h>
 
-void unschedule(int evtype)
+event *unschedule(int evtype)
 /* remove an event from the schedule */
 {
 /* remove an event from the schedule */
 {
-    game.future[evtype] = FOREVER;
+    game.future[evtype].date = FOREVER;
+    return &game.future[evtype];
 }
 
 int is_scheduled(int evtype)
 /* is an event of specified type scheduled */
 {
 }
 
 int is_scheduled(int evtype)
 /* is an event of specified type scheduled */
 {
-    return game.future[evtype] != FOREVER;
+    return game.future[evtype].date != FOREVER;
 }
 
 extern double scheduled(int evtype)
 /* when will this event happen? */
 {
 }
 
 extern double scheduled(int evtype)
 /* when will this event happen? */
 {
-    return game.future[evtype];
+    return game.future[evtype].date;
 }
 
 }
 
-void schedule(int evtype, double offset)
+event *schedule(int evtype, double offset)
 /* schedule an event of specified type */
 {
 /* schedule an event of specified type */
 {
-    game.future[evtype] = game.state.date + offset;
+    game.future[evtype].date = game.state.date + offset;
+    return &game.future[evtype];
 }
 
 void postpone(int evtype, double offset)
 /* poistpone a scheduled event */
 {
 }
 
 void postpone(int evtype, double offset)
 /* poistpone a scheduled event */
 {
-    game.future[evtype] += offset;
+    game.future[evtype].date += offset;
+}
+
+static bool cancelrest(void)
+{
+    if (game.resting) {
+       skip(1);
+       proutn(_("Mr. Spock-  \"Captain, shall we cancel the rest period?\""));
+       if (ja()) {
+           game.resting = 0;
+           game.optime = 0.0;
+           return true;
+       }
+    }
+
+    return false;
 }
 
 void events(void) 
 }
 
 void events(void) 
@@ -36,7 +53,9 @@ void events(void)
     int ictbeam=0, ipage=0, istract=0, line, i=0, j, k, l, ixhold=0, iyhold=0;
     double fintim = game.state.date + game.optime, datemin, xtime, repair, yank=0;
     int radio_was_broken;
     int ictbeam=0, ipage=0, istract=0, line, i=0, j, k, l, ixhold=0, iyhold=0;
     double fintim = game.state.date + game.optime, datemin, xtime, repair, yank=0;
     int radio_was_broken;
-    struct quadrant *pdest;
+    struct quadrant *pdest, *q;
+    coord w, hold;
+    event *ev;
 
     if (idebug) prout("=== EVENTS");
 
 
     if (idebug) prout("=== EVENTS");
 
@@ -48,9 +67,9 @@ void events(void)
        if (game.alldone) return;
        datemin = fintim;
        for (l = 1; l < NEVENTS; l++)
        if (game.alldone) return;
        datemin = fintim;
        for (l = 1; l < NEVENTS; l++)
-           if (game.future[l] < datemin) {
+           if (game.future[l].date < datemin) {
                line = l;
                line = l;
-               datemin = game.future[l];
+               datemin = game.future[l].date;
            }
        xtime = datemin-game.state.date;
        game.state.date = datemin;
            }
        xtime = datemin-game.state.date;
        game.state.date = datemin;
@@ -228,10 +247,10 @@ void events(void)
            schedule(FCDBAS, 1.0+3.0*Rand());
            if (game.isatb) /* extra time if SC already attacking */
                postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date);
            schedule(FCDBAS, 1.0+3.0*Rand());
            if (game.isatb) /* extra time if SC already attacking */
                postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date);
-           game.future[FBATTAK] = game.future[FCDBAS] +expran(0.3*game.intime);
+           game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime);
            game.iseenit = 0;
            game.iseenit = 0;
-           if (game.damage[DRADIO] != 0.0 &&
-               game.condit != IHDOCKED) break; /* No warning :-( */
+           if (game.damage[DRADIO] != 0.0 && game.condit != IHDOCKED) 
+               break; /* No warning :-( */
            game.iseenit = 1;
            if (ipage==0) pause_game(1);
            ipage = 1;
            game.iseenit = 1;
            if (ipage==0) pause_game(1);
            ipage = 1;
@@ -242,15 +261,8 @@ void events(void)
            proutn(_("   hold out only until stardate %d"),
                   (int)scheduled(FCDBAS));
            prout(".\"");
            proutn(_("   hold out only until stardate %d"),
                   (int)scheduled(FCDBAS));
            prout(".\"");
-           if (game.resting) {
-               skip(1);
-               proutn(_("Mr. Spock-  \"Captain, shall we cancel the rest period?\""));
-               if (ja()) {
-                   game.resting = 0;
-                   game.optime = 0.0;
-                   return;
-               }
-           }
+           if (cancelrest())
+               return;
            break;
        case FSCDBAS: /* Supercommander destroys base */
            unschedule(FSCDBAS);
            break;
        case FSCDBAS: /* Supercommander destroys base */
            unschedule(FSCDBAS);
@@ -380,25 +392,18 @@ void events(void)
                    return;
            }
            break;
                    return;
            }
            break;
-#ifdef EXPERIMENTAL
        case FDISTR: /* inhabited system issues distress call */
        case FDISTR: /* inhabited system issues distress call */
-           /* in BSD Trek this is a straight 1 stardate ahead */ 
-           schedule(FDISTR, 1.0 + Rand());
-           /* if we already have too many, throw this one away */
-           if (game.ndistr >= MAXDISTR)
-               break;
+           schedule(FDISTR, expran(0.5*game.intime));
            /* try a whole bunch of times to find something suitable */
            for (i = 0; i < 100; i++) {
            /* try a whole bunch of times to find something suitable */
            for (i = 0; i < 100; i++) {
-               struct quadrant *q;
-               iran(GALSIZE, &ix, &iy);
+               iran(GALSIZE, &w.x, &w.y);
                q = &game.state.galaxy[game.quadrant.x][game.quadrant.y];
                /* 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 */
                q = &game.state.galaxy[game.quadrant.x][game.quadrant.y];
                /* 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.quadrant.x && iy == game.quadrant.y) || q->stars<=0 ||
-                     (q->qsystemname & Q_DISTRESSED) ||
-                     (q->qsystemname & Q_SYSTEM) == 0 || q->klings <= 0))
+               if (!(same(game.quadrant, w) || q->stars<=0 ||
+                     q->supernova || q->status != secure || q->klingons <= 0))
                    break;
            }
            if (i >= 100)
                    break;
            }
            if (i >= 100)
@@ -406,96 +411,78 @@ void events(void)
                break;
 
            /* got one!!  Schedule its enslavement */
                break;
 
            /* got one!!  Schedule its enslavement */
-           game.ndistr++;
-           e = xsched(E_ENSLV, 1, ix, iy, q->qsystemname);
-           q->qsystemname = (e - Event) | Q_DISTRESSED;
+           ev = schedule(FENSLV, expran(game.intime));
+           ev->quadrant = w;
+           q->status = distressed;
 
            /* tell the captain about it if we can */
 
            /* tell the captain about it if we can */
-           if (game.damage[DRADIO] == 0.0)
+           if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
            {
            {
-               printf("\nUhura: Captain, starsystem %s in quadrant %d,%d is under attack\n",
-                      Systemname[e->systemname], ix, iy);
-               restcancel++;
+               prout("Uhura: Captain, starsystem %s in quadrant %d - %d is under attack.",
+                     systemname(q->planet), w.x, w.y);
+               if (cancelrest())
+                   return;
            }
            }
-           else
-               /* if we can't tell him, make it invisible */
-               e->evcode |= E_HIDDEN;
            break;
       case FENSLV:             /* starsystem is enslaved */
            break;
       case FENSLV:             /* starsystem is enslaved */
-           unschedule(e);
+           ev = unschedule(FENSLV);
            /* see if current distress call still active */
            /* 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;
+           q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
+           if (q->klingons <= 0) {
+               q->status = secure;
                break;
            }
                break;
            }
+           q->status = enslaved;
 
            /* play stork and schedule the first baby */
 
            /* play stork and schedule the first baby */
-           e = schedule(E_REPRO, Param.eventdly[E_REPRO] * franf(), e->x, e->y, e->systemname);
+           ev = schedule(FREPRO, expran(2.0 * game.intime));
 
            /* report the disaster if we can */
 
            /* report the disaster if we can */
-           if (game.damage[DRADIO] == 0.0)
+           if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
            {
            {
-               printf("\nUhura:  We've lost contact with starsystem %s\n",
-                      Systemname[e->systemname]);
-               printf("  in quadrant %d,%d.\n", e->x, e->y);
+               prout("\nUhura:  We've lost contact with starsystem %s\n",
+                     systemname(q->planet));
+               prout("  in quadrant %d,%d.\n", ev->quadrant.x,ev->quadrant.y);
            }
            }
-           else
-               e->evcode |= E_HIDDEN;
-           break;
       case FREPRO:             /* Klingon reproduces */
       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;
+           ev = schedule(FREPRO, expran(1.0 * game.intime));
+           /* see if current distress call still active */
+           q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
+           if (q->klingons <= 0) {
+               q->status = secure;
                break;
            }
                break;
            }
-           xresched(e, E_REPRO, 1);
            /* reproduce one Klingon */
            /* reproduce one Klingon */
-           ix = e->x;
-           iy = e->y;
-           if (Now.klings == 127)
+           w = ev->quadrant;
+           if (game.state.remkl >=MAXKLGAME)
                break;          /* full right now */
                break;          /* full right now */
-           if (q->klings >= MAXKLQUAD)
+           /* this quadrant not ok, pick an adjacent one */
+           for (i = w.x - 1; i <= w.x + 1; i++)
            {
            {
-               /* this quadrant not ok, pick an adjacent one */
-               for (i = ix - 1; i <= ix + 1; i++)
+               for (j = w.y - 1; j <= w.y + 1; j++)
                {
                {
-                   if (!VALID_QUADRANT(i))
+                   if (!VALID_QUADRANT(i, j))
                        continue;
                        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;
+                   q = &game.state.galaxy[w.x][w.y];
+                   /* check for this quad ok (not full & no snova) */
+                   if (q->klingons >= MAXKLQUAD || q->stars < 0)
+                       continue;
+                   goto foundit;
                }
                }
-               if (j > iy + 1)
-                   /* cannot create another yet */
-                   break;
-               ix = i;
-               iy = j;
            }
            }
+           break;      /* search for eligible quadrant failed */
+       foundit:
+           w.x = i;
+           w.y = j;
+
            /* deliver the child */
            /* deliver the child */
-           game.remkl++;
-           if (ix == game.quadrant.x && iy == game.quadrant.y)
-               newkling(++game.klhere, &ixhold, &iyhold);
+           game.state.remkl++;
+           if (same(game.quadrant, w))
+               newkling(++game.klhere, &hold);
 
            /* recompute time left */
            game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
            break;
 
            /* recompute time left */
            game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
            break;
-#endif /* EXPERIMENTAL */
        }
     }
 }
        }
     }
 }
@@ -618,7 +605,7 @@ void nova(int ix, int iy)
                        game.quad[scratch.x][scratch.y] = IHDOT;
                        break;
                    case IHP: /* Destroy planet */
                        game.quad[scratch.x][scratch.y] = IHDOT;
                        break;
                    case IHP: /* Destroy planet */
-                       game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NULL;
+                       game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
                        game.state.nplankl++;
                        crmena(1, IHP, 2, scratch);
                        prout(_(" destroyed."));
                        game.state.nplankl++;
                        crmena(1, IHP, 2, scratch);
                        prout(_(" destroyed."));
index d23723b9813f4d491728a7f95815afbb7624592e..54b5beaca08a7db10f4b5b19f89706390adf1b15 100644 (file)
@@ -326,7 +326,7 @@ void score(void)
     if (game.gamewon == 0) game.state.nromrem = 0; // None captured if no win
     iscore = 10*NKILLK + 50*NKILLC + ithperd + iwon
        - 100*game.state.basekl - 100*klship - 45*game.nhelp -5*game.state.starkl - game.casual
     if (game.gamewon == 0) game.state.nromrem = 0; // None captured if no win
     iscore = 10*NKILLK + 50*NKILLC + ithperd + iwon
        - 100*game.state.basekl - 100*klship - 45*game.nhelp -5*game.state.starkl - game.casual
-       + 20*NKILLROM + 200*NKILLSC - 10*game.state.nplankl + game.state.nromrem;
+       + 20*NKILLROM + 200*NKILLSC - 10*game.state.nplankl - 300*game.state.nworldkl + game.state.nromrem;
     if (game.alive == 0) iscore -= 200;
     skip(2);
     prout(_("Your score --"));
     if (game.alive == 0) iscore -= 200;
     skip(2);
     prout(_("Your score --"));
@@ -354,6 +354,9 @@ void score(void)
     if (game.state.nplankl)
        prout(_("%6d planets destroyed by your action   %5d"),
              game.state.nplankl, -10*game.state.nplankl);
     if (game.state.nplankl)
        prout(_("%6d planets destroyed by your action   %5d"),
              game.state.nplankl, -10*game.state.nplankl);
+    if ((game.options & OPTION_WORLDS) && game.state.nworldkl)
+       prout(_("%6d inhabited planets destroyed by your action   %5d"),
+             game.state.nplankl, -300*game.state.nworldkl);
     if (game.state.basekl)
        prout(_("%6d bases destroyed by your action     %5d"),
              game.state.basekl, -100*game.state.basekl);
     if (game.state.basekl)
        prout(_("%6d bases destroyed by your action     %5d"),
              game.state.basekl, -100*game.state.basekl);
index 5c9f67dde508bc02a1ff01b1f9d82ee9851378c0..01958a144e6cfaaa982496cc9922fbc275312773 100644 (file)
@@ -489,12 +489,12 @@ void impuls(void)
 }
 
 
 }
 
 
-void warp(int i
+void warp(bool timewarp
 {
     int blooey=0, twarp=0, iwarp;
     double power;
 
 {
     int blooey=0, twarp=0, iwarp;
     double power;
 
-    if (i!=2) { /* Not WARPX entry */
+    if (!timewarp) { /* Not WARPX entry */
        game.ididit = 0;
        if (game.damage[DWARPEN] > 10.0) {
            chew();
        game.ididit = 0;
        if (game.damage[DWARPEN] > 10.0) {
            chew();
@@ -749,10 +749,10 @@ void atover(int igrab)
        if (distreq < game.dist) game.dist = distreq;
        game.optime = 10.0*game.dist/game.wfacsq;
        game.direc = 12.0*Rand();       /* How dumb! */
        if (distreq < game.dist) game.dist = distreq;
        game.optime = 10.0*game.dist/game.wfacsq;
        game.direc = 12.0*Rand();       /* How dumb! */
-       game.justin = 0;
-       game.inorbit = 0;
-       warp(2);
-       if (game.justin == 0) {
+       game.justin = false;
+       game.inorbit = false;
+       warp(true);
+       if (!game.justin) {
            /* This is bad news, we didn't leave quadrant. */
            if (game.alldone) return;
            skip(1);
            /* This is bad news, we didn't leave quadrant. */
            if (game.alldone) return;
            skip(1);
index c1fdb16ba9ad5ac69813e75a4185ae2c3481477c..47140ea9df814282fad4db38d9556055864b9f4b 100644 (file)
@@ -58,7 +58,7 @@ void orbit(void)
 {
     skip(1);
     chew();
 {
     skip(1);
     chew();
-    if (game.inorbit!=0) {
+    if (game.inorbit) {
        prout("Already in standard orbit.");
        return;
     }
        prout("Already in standard orbit.");
        return;
     }
@@ -78,8 +78,8 @@ void orbit(void)
     if (consumeTime()) return;
     game.height = (1400.0+7200.0*Rand());
     prout("Sulu-  \"Entered orbit at altitude %.2f kilometers.\"", game.height);
     if (consumeTime()) return;
     game.height = (1400.0+7200.0*Rand());
     prout("Sulu-  \"Entered orbit at altitude %.2f kilometers.\"", game.height);
-    game.inorbit = 1;
-    game.ididit=1;
+    game.inorbit = true;
+    game.ididit = true;
 }
 
 void sensor(void) 
 }
 
 void sensor(void) 
@@ -122,7 +122,7 @@ void beam(void)
        }
        return;
     }
        }
        return;
     }
-    if (game.inorbit==0) {
+    if (!game.inorbit) {
        crmshp();
        prout(" not in standard orbit.");
        return;
        crmshp();
        prout(" not in standard orbit.");
        return;
@@ -299,7 +299,7 @@ void shuttle(void)
        else prout("Shuttle craft is now serving Big Macs.");
        return;
     }
        else prout("Shuttle craft is now serving Big Macs.");
        return;
     }
-    if (game.inorbit==0) {
+    if (!game.inorbit) {
        crmshp();
        prout(" not in standard orbit.");
        return;
        crmshp();
        prout(" not in standard orbit.");
        return;
@@ -509,7 +509,7 @@ void deathray(void)
     return;
 }
 
     return;
 }
 
-char *systemname(planet *planet)
+char *systemname(int pindx)
 {
     static char        *names[NINHAB] =
     {
 {
     static char        *names[NINHAB] =
     {
@@ -582,5 +582,5 @@ char *systemname(planet *planet)
        "Exo III",              /* TOS: "What Are Little Girls Made Of?" (Class P) */
     };
 
        "Exo III",              /* TOS: "What Are Little Girls Made Of?" (Class P) */
     };
 
-    return names[planet->inhabited];
+    return names[pindx];
 }
 }
index 22a7cee19eafa012f2036e438a03ea27d75402fd..bca27e40d50cf516410dae564c37c5ffb2387e9f 100644 (file)
@@ -316,8 +316,8 @@ static void status(int req)
        break;
     case 10:
        if (game.options & OPTION_WORLDS) {
        break;
     case 10:
        if (game.options & OPTION_WORLDS) {
-           planet *here = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet;
-           if (here && here->inhabited != UNINHABITED)
+           int here = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet;
+           if (here != NOPLANET && game.state.plnets[here].inhabited != UNINHABITED)
                proutn("Major system  %s", systemname(here));
            else
                proutn("Sector is uninhabited");
                proutn("Major system  %s", systemname(here));
            else
                proutn("Sector is uninhabited");
index 7b17fbcd9c0745556310ee8ff3ce120963257ab0..6aac3617973142ca588dfe47fccf32d9d4c29df3 100644 (file)
@@ -227,14 +227,12 @@ void setup(int needprompt)
        for_quadrants(j) {
        struct quadrant *quad = &game.state.galaxy[i][j];
            quad->charted = 0;
        for_quadrants(j) {
        struct quadrant *quad = &game.state.galaxy[i][j];
            quad->charted = 0;
-           quad->planet = NULL;
+           quad->planet = NOPLANET;
            quad->romulans = 0;
            quad->klingons = 0;
            quad->starbase = 0;
            quad->supernova = 0;
            quad->romulans = 0;
            quad->klingons = 0;
            quad->starbase = 0;
            quad->supernova = 0;
-#ifdef EXPERIMENTAL
            quad->status = secure;
            quad->status = secure;
-#endif /* EXPERIMENTAL */
        }
     // Initialize times for extraneous events
     schedule(FSNOVA, expran(0.5 * game.intime));
        }
     // Initialize times for extraneous events
     schedule(FSNOVA, expran(0.5 * game.intime));
@@ -248,12 +246,10 @@ void setup(int needprompt)
        unschedule(FSCMOVE);
     unschedule(FSCDBAS);
     unschedule(FDSPROB);
        unschedule(FSCMOVE);
     unschedule(FSCDBAS);
     unschedule(FDSPROB);
-#ifdef EXPERIMENTAL
-    if (game.options & OPTION_WORLDS)
+    if ((game.options & OPTION_WORLDS) && game.skill >= SKILL_GOOD)
        schedule(FDISTR, expran(1.0 + game.intime));
     unschedule(FENSLV);
     unschedule(FREPRO);
        schedule(FDISTR, expran(1.0 + game.intime));
     unschedule(FENSLV);
     unschedule(FREPRO);
-#endif /* EXPERIMENTAL */
     // Starchart is functional but we've never seen it
     game.lastchart = FOREVER;
     // Put stars in the galaxy
     // Starchart is functional but we've never seen it
     game.lastchart = FOREVER;
     // Put stars in the galaxy
@@ -295,8 +291,8 @@ void setup(int needprompt)
     // Position ordinary Klingon Battle Cruisers
     krem = game.inkling;
     klumper = 0.25*game.skill*(9.0-game.length)+1.0;
     // Position ordinary Klingon Battle Cruisers
     krem = game.inkling;
     klumper = 0.25*game.skill*(9.0-game.length)+1.0;
-    if (klumper > 9
-       klumper = 9; // Can't have more than 9 in quadrant
+    if (klumper > MAXKLQUAD
+       klumper = MAXKLQUAD;
     do {
        double r = Rand();
        int klump = (1.0 - r*r)*klumper;
     do {
        double r = Rand();
        int klump = (1.0 - r*r)*klumper;
@@ -337,7 +333,7 @@ void setup(int needprompt)
     }
     // Locate planets in galaxy
     for (i = 0; i < game.inplan; i++) {
     }
     // Locate planets in galaxy
     for (i = 0; i < game.inplan; i++) {
-       do iran(GALSIZE, &ix, &iy); while (game.state.galaxy[ix][iy].planet);
+       do iran(GALSIZE, &ix, &iy); while (game.state.galaxy[ix][iy].planet != NOPLANET);
        game.state.plnets[i].w.x = ix;
        game.state.plnets[i].w.y = iy;
        if (i < NINHAB) {
        game.state.plnets[i].w.x = ix;
        game.state.plnets[i].w.y = iy;
        if (i < NINHAB) {
@@ -352,7 +348,7 @@ void setup(int needprompt)
            game.state.plnets[i].inhabited = UNINHABITED;
        }
        if ((game.options & OPTION_WORLDS) || i >= NINHAB)
            game.state.plnets[i].inhabited = UNINHABITED;
        }
        if ((game.options & OPTION_WORLDS) || i >= NINHAB)
-           game.state.galaxy[ix][iy].planet = game.state.plnets + i;
+           game.state.galaxy[ix][iy].planet = i;
     }
     // Locate Romulans
     for (i = 1; i <= game.state.nromrem; i++) {
     }
     // Locate Romulans
     for (i = 1; i <= game.state.nromrem; i++) {
@@ -506,7 +502,6 @@ bool choose(bool needprompt)
     setpassword();
     if (strcmp(game.passwd, "debug")==0) {
        idebug = true;
     setpassword();
     if (strcmp(game.passwd, "debug")==0) {
        idebug = true;
-       logfp = fopen("sst-input.log", "w");
        fputs("=== Debug mode enabled\n", stdout);
     }
 
        fputs("=== Debug mode enabled\n", stdout);
     }
 
@@ -564,7 +559,7 @@ void newqad(int shutup)
     struct quadrant *here;
 
     game.iattak = 1;
     struct quadrant *here;
 
     game.iattak = 1;
-    game.justin = 1;
+    game.justin = true;
     game.base.x = game.base.y = 0;
     game.klhere = 0;
     game.comhere = 0;
     game.base.x = game.base.y = 0;
     game.klhere = 0;
     game.comhere = 0;
@@ -573,8 +568,8 @@ void newqad(int shutup)
     game.irhere = 0;
     game.iplnet = 0;
     game.nenhere = 0;
     game.irhere = 0;
     game.iplnet = 0;
     game.nenhere = 0;
-    game.neutz = 0;
-    game.inorbit = 0;
+    game.neutz = false;
+    game.inorbit = false;
     game.landed = -1;
     game.ientesc = 0;
     game.ithere = 0;
     game.landed = -1;
     game.ientesc = 0;
     game.ithere = 0;
@@ -635,9 +630,9 @@ void newqad(int shutup)
        dropin(IHB, &game.base);
        
     // If quadrant needs a planet, put it in
        dropin(IHB, &game.base);
        
     // If quadrant needs a planet, put it in
-    if (here->planet) {
-       game.iplnet = here->planet - game.state.plnets;
-       if (here->planet->inhabited == UNINHABITED)
+    if (here->planet != NOPLANET) {
+       game.iplnet = here->planet;
+       if (game.state.plnets[here->planet].inhabited == UNINHABITED)
            dropin(IHP, &game.plnet);
        else
            dropin(IHW, &game.plnet);
            dropin(IHP, &game.plnet);
        else
            dropin(IHW, &game.plnet);
@@ -649,7 +644,7 @@ void newqad(int shutup)
        dropin(IHSTAR, &w);
 
     // Check for RNZ
        dropin(IHSTAR, &w);
 
     // Check for RNZ
-    if (game.irhere > 0 && game.klhere == 0 && (!here->planet || here->planet->inhabited == UNINHABITED)) {
+    if (game.irhere > 0 && game.klhere == 0 && (here->planet == NOPLANET || game.state.plnets[here->planet].inhabited == UNINHABITED)) {
        game.neutz = 1;
        if (game.damage[DRADIO] <= 0.0) {
            skip(1);
        game.neutz = 1;
        if (game.damage[DRADIO] <= 0.0) {
            skip(1);
index 5d34a0dd43c58caee73dfeb6c61c8584c5c92162..36f444959238493d6414a44f1ab3b6c9e13671b3 100644 (file)
--- a/src/sst.c
+++ b/src/sst.c
@@ -155,9 +155,13 @@ for a lot of magic numbers and refactored the heck out of it.
 
    5. Half the quadrants now have inhabited planets, from which one 
       cannot mine dilithium (there will still be the same additional number
 
    5. Half the quadrants now have inhabited planets, from which one 
       cannot mine dilithium (there will still be the same additional number
-      of dilithium-bearing planets).  Right now this is just color, but
-      eventually we'll fold in BSD-Trek-like logic for Klingons to attack
-      and enslave inhabited worlds.
+      of dilithium-bearing planets).  Torpedoing an inhabited world is *bad*.
+      There is BSD-Trek-like logic for Klingons to attack and enslave 
+      inhabited worlds, producing more ships (only is skill is 'good' or 
+      better). (Controlled by OPTION_WORLDS and turned off if game 
+      type is "plain" or "almy".)
+
+   6. User input is now logged so we can do regression testing.
 */
 
 /* the input queue */
 */
 
 /* the input queue */
@@ -274,6 +278,8 @@ commands[] = {
        {"QUIT",        QUIT,           0},
 #define HELP   36
        {"HELP",        HELP,           0},
        {"QUIT",        QUIT,           0},
 #define HELP   36
        {"HELP",        HELP,           0},
+#define SEED   37
+       {"SEED",        SEED,           0},
 };
 
 #define NUMCOMMANDS    sizeof(commands)/sizeof(commands[0])
 };
 
 #define NUMCOMMANDS    sizeof(commands)/sizeof(commands[0])
@@ -379,7 +385,7 @@ void enqueue(char *s)
 
 static void makemoves(void) 
 {
 
 static void makemoves(void) 
 {
-    int i, v = 0;
+    int key, i, v = 0;
     bool hitme;
     clrscr();
     setwnd(message_window);
     bool hitme;
     clrscr();
     setwnd(message_window);
@@ -441,7 +447,7 @@ static void makemoves(void)
            if (game.ididit) hitme = true;
            break;
        case MOVE:                      // move
            if (game.ididit) hitme = true;
            break;
        case MOVE:                      // move
-           warp(1);
+           warp(false);
            break;
        case SHIELDS:                   // shields
            doshield(1);
            break;
        case SHIELDS:                   // shields
            doshield(1);
@@ -543,7 +549,12 @@ static void makemoves(void)
            game.alldone = 1;           // quit the game
            break;
        case HELP:
            game.alldone = 1;           // quit the game
            break;
        case HELP:
-           helpme();   // get help
+           helpme();                   // get help
+           break;
+       case SEED:                      // set random-number seed
+           key = scan();
+           if (key == IHREAL)
+               seed = (int)aaitem;
            break;
        }
        commandhook(commands[i].name, false);
            break;
        }
        commandhook(commands[i].name, false);
@@ -598,6 +609,9 @@ int main(int argc, char **argv)
            exit(0);
        }
     }
            exit(0);
        }
     }
+    /* where to save the input in case of bugs */
+    logfp = fopen("sst-input.log", "w");
+    setlinebuf(logfp);
 
     randomize();
     iostart();
 
     randomize();
     iostart();
@@ -704,7 +718,7 @@ double Rand(void)
     if (!randready) {
        if (seed == 0)
            seed = (unsigned)time(NULL);
     if (!randready) {
        if (seed == 0)
            seed = (unsigned)time(NULL);
-       if (idebug)
+       if (logfp)
            fprintf(logfp, "seed %d\n", seed);
        srand(seed);
        randready = true;
            fprintf(logfp, "seed %d\n", seed);
        srand(seed);
        randready = true;
@@ -830,7 +844,7 @@ void debugme(void)
            if (game.damage[i] > 0.0) 
                game.damage[i] = 0.0;
     }
            if (game.damage[i] > 0.0) 
                game.damage[i] = 0.0;
     }
-    proutn("Toggle game.idebug? ");
+    proutn("Toggle debug flag? ");
     if (ja() != 0) {
        idebug = !idebug;
        if (idebug) prout("Debug output ON");
     if (ja() != 0) {
        idebug = !idebug;
        if (idebug) prout("Debug output ON");
@@ -852,6 +866,8 @@ void debugme(void)
     }
     proutn("Examine/change events? ");
     if (ja() != 0) {
     }
     proutn("Examine/change events? ");
     if (ja() != 0) {
+       event *ev;
+       coord w;
        int i;
        for (i = 1; i < NEVENTS; i++) {
            int key;
        int i;
        for (i = 1; i < NEVENTS; i++) {
            int key;
@@ -864,13 +880,36 @@ void debugme(void)
            case FCDBAS:  proutn("Base Destroy    "); break;
            case FSCMOVE: proutn("SC Move         "); break;
            case FSCDBAS: proutn("SC Base Destroy "); break;
            case FCDBAS:  proutn("Base Destroy    "); break;
            case FSCMOVE: proutn("SC Move         "); break;
            case FSCDBAS: proutn("SC Base Destroy "); break;
+           //case FDSPROB:proutn("Probe Move      "); break;
+           case FDISTR:  proutn("Distress Call   "); break;
+           case FENSLV:  proutn("Enlavement      "); break;
+           case FREPRO:  proutn("Klingon Build   "); break;
            }
            proutn("%.2f", scheduled(i)-game.state.date);
            chew();
            proutn("  ?");
            key = scan();
            if (key == IHREAL) {
            }
            proutn("%.2f", scheduled(i)-game.state.date);
            chew();
            proutn("  ?");
            key = scan();
            if (key == IHREAL) {
-               schedule(i, aaitem);
+               ev = schedule(i, aaitem);
+               if (i == FENSLV || i == FREPRO) {
+                   chew();
+                   proutn("In quadrant- ");
+                   key = scan();
+                   if (key != IHREAL) {
+                       prout("Event %d canceled, no y coordinate.", i);
+                       unschedule(i);
+                       continue;
+                   }
+                   w.y = (int)aaitem;
+                   key = scan();
+                   if (key != IHREAL) {
+                       prout("Event %d canceled, no x coordinate.", i);
+                       unschedule(i);
+                       continue;
+                   }
+                   w.x = (int)aaitem;
+                   ev->quadrant = w;
+               }
            }
        }
        chew();
            }
        }
        chew();
index e5849937a5b0a1f6822bbb22b150963fae6efd6f..2b30d8b17164457d370ee5db6ee39c591a517b8b 100644 (file)
--- a/src/sst.h
+++ b/src/sst.h
@@ -65,25 +65,25 @@ typedef struct {
        starkl,                 // destroyed stars
        basekl,                 // destroyed bases
        nromrem,                // Romulans remaining
        starkl,                 // destroyed stars
        basekl,                 // destroyed bases
        nromrem,                // Romulans remaining
-       nplankl;                // destroyed planets
-       planet plnets[PLNETMAX];  // Planet information
-       double date,            // stardate
-           remres,             // remaining resources
-           remtime;            // remaining time
+       nplankl,                // destroyed uninhabited planets
+       nworldkl;               // destroyed inhabited planets
+    planet plnets[PLNETMAX];  // Planet information
+    double date,               // stardate
+       remres,         // remaining resources
+       remtime;                // remaining time
     coord baseq[BASEMAX+1];    // Base quadrant coordinates
     coord kcmdr[QUADSIZE+1];   // Commander quadrant coordinates
     coord kscmdr;              // Supercommander quadrant coordinates
     struct quadrant {
        int stars;
     coord baseq[BASEMAX+1];    // Base quadrant coordinates
     coord kcmdr[QUADSIZE+1];   // Commander quadrant coordinates
     coord kscmdr;              // Supercommander quadrant coordinates
     struct quadrant {
        int stars;
-       planet *planet;
+       int planet;
+#define NOPLANET       -1
        bool starbase;
        int klingons;
        int romulans;
        bool supernova;
        bool charted;
        bool starbase;
        int klingons;
        int romulans;
        bool supernova;
        bool charted;
-#ifdef EXPERIMENTAL
        enum {secure, distressed, enslaved} status;
        enum {secure, distressed, enslaved} status;
-#endif /* EXPERIMENTAL */
     } galaxy[GALSIZE+1][GALSIZE+1];    // The Galaxy (subscript 0 not used)
     struct page {
        int stars;
     } galaxy[GALSIZE+1][GALSIZE+1];    // The Galaxy (subscript 0 not used)
     struct page {
        int stars;
@@ -92,6 +92,9 @@ typedef struct {
     } chart[GALSIZE+1][GALSIZE+1];     // the starchart (subscript 0 not used)
 } snapshot;                            // Data that is snapshot
 
     } chart[GALSIZE+1][GALSIZE+1];     // the starchart (subscript 0 not used)
 } snapshot;                            // Data that is snapshot
 
+#define MAXKLGAME      127
+#define MAXKLQUAD      9
+
 #define NKILLK (game.inkling - game.state.remkl)
 #define NKILLC (game.incom - game.state.remcom)
 #define NKILLSC (game.inscom - game.state.nscrem)
 #define NKILLK (game.inkling - game.state.remkl)
 #define NKILLC (game.incom - game.state.remcom)
 #define NKILLSC (game.inscom - game.state.nscrem)
@@ -156,29 +159,26 @@ typedef struct {
 #define FSCMOVE 6   // Supercommander moves (might attack base)
 #define FSCDBAS 7   // Supercommander destroys base
 #define FDSPROB 8   // Move deep space probe
 #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)
 #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 */
+
+typedef struct {
+    double date;
+    coord quadrant;
+} event;
 
 /*
  * abstract out the event handling -- underlying data structures will change
  * when we implement stateful events
  */
 
 /*
  * abstract out the event handling -- underlying data structures will change
  * when we implement stateful events
  */
-extern void unschedule(int);
+extern event *unschedule(int);
 extern int is_scheduled(int);
 extern int is_scheduled(int);
-extern void schedule(int, double);
+extern event *schedule(int, double);
 extern void postpone(int, double);
 extern double scheduled(int);
 
 extern void postpone(int, double);
 extern double scheduled(int);
 
-#ifdef EXPERIMENTAL
-#define        MAXDISTR        5       /* maximum concurrent distress calls */
-#endif /* EXPERIMENTAL */
-
 #define SSTMAGIC       "SST2.0\n"
 
 struct game {
 #define SSTMAGIC       "SST2.0\n"
 
 struct game {
@@ -191,7 +191,7 @@ struct game {
     double kdist[(QUADSIZE+1)*(QUADSIZE+1)];           // enemy distances
     double kavgd[(QUADSIZE+1)*(QUADSIZE+1)];           // average distances
     double damage[NDEVICES];   // damage encountered
     double kdist[(QUADSIZE+1)*(QUADSIZE+1)];           // enemy distances
     double kavgd[(QUADSIZE+1)*(QUADSIZE+1)];           // average distances
     double damage[NDEVICES];   // damage encountered
-    double future[NEVENTS];    // future events
+    event future[NEVENTS];     // future events
     char passwd[10];           // Self Destruct password
     coord ks[(QUADSIZE+1)*(QUADSIZE+1)];       // enemy sector locations
     coord quadrant, sector;    // where we are
     char passwd[10];           // Self Destruct password
     coord ks[(QUADSIZE+1)*(QUADSIZE+1)];       // enemy sector locations
     coord quadrant, sector;    // where we are
@@ -201,23 +201,24 @@ struct game {
     coord plnet;               // location of planet in quadrant
     coord probec;      // current probe quadrant
     bool gamewon,      // Finished!
     coord plnet;               // location of planet in quadrant
     coord probec;      // current probe quadrant
     bool gamewon,      // Finished!
-       ididit,         // Action taken -- allows enemy to attack
-       alive,          // We are alive (not killed)
+       ididit,         // action taken -- allows enemy to attack
+       alive,          // we are alive (not killed)
        justin,         // just entered quadrant
        alldone,        // game is now finished
        neutz,          // Romulan Neutral Zone
        isarmed,        // probe is armed
        justin,         // just entered quadrant
        alldone,        // game is now finished
        neutz,          // Romulan Neutral Zone
        isarmed,        // probe is armed
+       inorbit,        // orbiting a planet
        thawed;         // thawed game
        thawed;         // thawed game
-    int inkling,       // Initial number of klingons
-       inbase,         // Initial number of bases
-       incom,          // Initial number of commanders
-       inscom,         // Initial number of commanders
-       inrom,          // Initial number of commanders
-       instar,         // Initial stars
-       intorps,        // Initial/Max torpedoes
-       condit,         // Condition (red/yellow/green/docked)
+    int inkling,       // initial number of klingons
+       inbase,         // initial number of bases
+       incom,          // initial number of commanders
+       inscom,         // initial number of commanders
+       inrom,          // initial number of commanders
+       instar,         // initial stars
+       intorps,        // initial/Max torpedoes
+       condit,         // condition (red/yellow/green/docked)
        torps,          // number of torpedoes
        torps,          // number of torpedoes
-       ship,           // Ship type -- 'E' is Enterprise
+       ship,           // ship type -- 'E' is Enterprise
        length,         // length of game
        skill,          // skill level
        klhere,         // klingons here
        length,         // length of game
        skill,          // skill level
        klhere,         // klingons here
@@ -226,7 +227,6 @@ struct game {
        nhelp,          // calls for help
        nkinks,         // count of energy-barrier crossings
        shldchg,        // shield is changing (affects efficiency)
        nhelp,          // calls for help
        nkinks,         // count of energy-barrier crossings
        shldchg,        // shield is changing (affects efficiency)
-       inorbit,        // orbiting
        landed,         // party on planet (1), on ship (-1)
        iplnet,         // planet # in quadrant
        imine,          // mining
        landed,         // party on planet (1), on ship (-1)
        iplnet,         // planet # in quadrant
        imine,          // mining
@@ -244,9 +244,6 @@ struct game {
        tourn,          // tournament number
        ithere,         // Tholian is here 
        iseenit,        // seen base attack report
        tourn,          // tournament number
        ithere,         // Tholian is here 
        iseenit,        // seen base attack report
-#ifdef EXPERIMENTAL
-       ndistr,         //* count of distress calls */ 
-#endif /* EXPERIMENTAL */
        proben,         // number of moves for probe
        nprobes;        // number of probes available
     double inresor,    // initial resources
        proben,         // number of moves for probe
        nprobes;        // number of probes available
     double inresor,    // initial resources
@@ -335,7 +332,7 @@ int srscan(int);
 void lrscan(void);
 void phasers(void);
 void photon(void);
 void lrscan(void);
 void phasers(void);
 void photon(void);
-void warp(int);
+void warp(bool);
 void doshield(int);
 void dock(int);
 void dreprt(void);
 void doshield(int);
 void dock(int);
 void dreprt(void);
@@ -416,7 +413,7 @@ void setpassword(void);
 void commandhook(char *, bool);
 void makechart(void);
 void enqueue(char *);
 void commandhook(char *, bool);
 void makechart(void);
 void enqueue(char *);
-char *systemname(planet *);
+char *systemname(int);
 void newkling(int, coord *);
 
 /* mode arguments for srscan() */
 void newkling(int, coord *);
 
 /* mode arguments for srscan() */