FDISTR/FENSLV/FREPRO sequence looks like it's working.
[super-star-trek.git] / src / events.c
index cc299cfc73ceceb142af6168f875c18c93d03bc0..6f2cac95e9df814c0c607c192a738e90d0079524 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * events.c -- event-queue handling
+ *
+ * This isn't a real event queue a la BSD Trek yet -- you can only have one 
+ * event of each type active at any given time.  Mostly these means we can 
+ * only have one FDISTR/FENSLV/FREPRO sequence going at any given time;
+ * BSD Trek, from which we swiped the idea, can have up to 5.
+ */
 #include "sst.h"
 #include <math.h>
 
@@ -39,7 +47,7 @@ static bool cancelrest(void)
        skip(1);
        proutn(_("Mr. Spock-  \"Captain, shall we cancel the rest period?\""));
        if (ja()) {
-           game.resting = 0;
+           game.resting = false;
            game.optime = 0.0;
            return true;
        }
@@ -55,9 +63,31 @@ void events(void)
     int radio_was_broken;
     struct quadrant *pdest, *q;
     coord w, hold;
-    event *ev;
+    event *ev, *ev2;
+
+    if (idebug) {
+       prout("=== EVENTS from %.2f to %.2f:", game.state.date, fintim);
+       for (i = 1; i < NEVENTS; i++) {
+           switch (i) {
+           case FSNOVA:  proutn("=== Supernova       "); break;
+           case FTBEAM:  proutn("=== T Beam          "); break;
+           case FSNAP:   proutn("=== Snapshot        "); break;
+           case FBATTAK: proutn("=== Base Attack     "); break;
+           case FCDBAS:  proutn("=== Base Destroy    "); break;
+           case FSCMOVE: proutn("=== SC Move         "); break;
+           case FSCDBAS: proutn("=== SC Base Destroy "); break;
+           case FDSPROB: proutn("=== Probe Move      "); break;
+           case FDISTR:  proutn("=== Distress Call   "); break;
+           case FENSLV:  proutn("=== Enlavement      "); break;
+           case FREPRO:  proutn("=== Klingon Build   "); break;
+           }
+           if (is_scheduled(i))
+               prout("%.2f", scheduled(i));
+           else
+               prout("never");
 
-    if (idebug) prout("=== EVENTS");
+       }
+    }
 
     radio_was_broken = (game.damage[DRADIO] != 0.0);
 
@@ -69,6 +99,8 @@ void events(void)
        for (l = 1; l < NEVENTS; l++)
            if (game.future[l].date < datemin) {
                line = l;
+               if (idebug)
+                   prout("== Event %d fires", line);
                datemin = game.future[l].date;
            }
        xtime = datemin-game.state.date;
@@ -180,14 +212,10 @@ void events(void)
                    prout(_("Galileo, left on the planet surface, is well hidden."));
                }
            }
-           if (line==0) {
-               game.quadrant.x = game.state.kscmdr.x;
-               game.quadrant.y = game.state.kscmdr.y;
-           }
-           else {
-               game.quadrant.x = game.state.kcmdr[i].x;
-               game.quadrant.y = game.state.kcmdr[i].y;
-           }
+           if (line==0)
+               game.quadrant = game.state.kscmdr;
+           else
+               game.quadrant = game.state.kcmdr[i];
            iran(QUADSIZE, &game.sector.x, &game.sector.y);
            crmshp();
            proutn(_(" is pulled to "));
@@ -196,9 +224,9 @@ void events(void)
            prout(cramlc(sector, game.sector));
            if (game.resting) {
                prout(_("(Remainder of rest/repair period cancelled.)"));
-               game.resting = 0;
+               game.resting = false;
            }
-           if (game.shldup==0) {
+           if (!game.shldup) {
                if (game.damage[DSHIELD]==0 && game.shield > 0) {
                    doshield(2); /* Shldsup */
                    game.shldchg=0;
@@ -227,9 +255,9 @@ void events(void)
            i = 0;
            for_starbases(j) {
                for_commanders(k)
-                   if (game.state.baseq[j].x==game.state.kcmdr[k].x && game.state.baseq[j].y==game.state.kcmdr[k].y &&
-                       (game.state.baseq[j].x!=game.quadrant.x || game.state.baseq[j].y!=game.quadrant.y) &&
-                       (game.state.baseq[j].x!=game.state.kscmdr.x || game.state.baseq[j].y!=game.state.kscmdr.y)) {
+                   if (same(game.state.baseq[j], game.state.kcmdr[k]) &&
+                       !same(game.state.baseq[j], game.quadrant) &&
+                       !same(game.state.baseq[j], game.state.kscmdr)) {
                        i = 1;
                        break;
                    }
@@ -242,8 +270,7 @@ void events(void)
                break;
            }
            /* commander + starbase combination found -- launch attack */
-           game.battle.x = game.state.baseq[j].x;
-           game.battle.y = game.state.baseq[j].y;
+           game.battle = game.state.baseq[j];
            schedule(FCDBAS, 1.0+3.0*Rand());
            if (game.isatb) /* extra time if SC already attacking */
                postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date);
@@ -271,14 +298,14 @@ void events(void)
                break; /* WAS RETURN! */
            ixhold = game.battle.x;
            iyhold = game.battle.y;
-           game.battle.x = game.state.kscmdr.x;
-           game.battle.y = game.state.kscmdr.y;
+           game.battle = game.state.kscmdr;
+           /* FALL THROUGH */
        case FCDBAS: /* Commander succeeds in destroying base */
            if (line==FCDBAS) {
                unschedule(FCDBAS);
                /* find the lucky pair */
                for_commanders(i)
-                   if (game.state.kcmdr[i].x==game.battle.x && game.state.kcmdr[i].y==game.battle.y
+                   if (same(game.state.kcmdr[i], game.battle)
                        break;
                if (i > game.state.remcom || game.state.rembase == 0 ||
                    !game.state.galaxy[game.battle.x][game.battle.y].starbase) {
@@ -290,7 +317,7 @@ void events(void)
            /* Code merges here for any commander destroying base */
            /* Not perfect, but will have to do */
            /* Handle case where base is in same quadrant as starship */
-           if (game.battle.x==game.quadrant.x && game.battle.y==game.quadrant.y) {
+           if (same(game.battle, game.quadrant)) {
                game.state.chart[game.battle.x][game.battle.y].starbase = false;
                game.quad[game.base.x][game.base.y] = IHDOT;
                game.base.x=game.base.y=0;
@@ -316,10 +343,8 @@ void events(void)
            /* Remove Starbase from galaxy */
            game.state.galaxy[game.battle.x][game.battle.y].starbase = false;
            for_starbases(i)
-               if (game.state.baseq[i].x==game.battle.x && game.state.baseq[i].y==game.battle.y) {
-                   game.state.baseq[i].x=game.state.baseq[game.state.rembase].x;
-                   game.state.baseq[i].y=game.state.baseq[game.state.rembase].y;
-               }
+               if (same(game.state.baseq[i], game.battle))
+                   game.state.baseq[i] = game.state.baseq[game.state.rembase];
            game.state.rembase--;
            if (game.isatb == 2) {
                /* reinstate a commander's base attack */
@@ -393,22 +418,25 @@ void events(void)
            }
            break;
        case FDISTR: /* inhabited system issues distress call */
-           schedule(FDISTR, expran(0.5*game.intime));
+           unschedule(FDISTR);
            /* try a whole bunch of times to find something suitable */
-           for (i = 0; i < 100; i++) {
-               iran(GALSIZE, &w.x, &w.y);
-               q = &game.state.galaxy[game.quadrant.x][game.quadrant.y];
+           i = 100;
+           do {
                /* 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 (!(same(game.quadrant, w) || q->stars<=0 ||
-                     q->supernova || q->status != secure || q->klingons <= 0))
-                   break;
-           }
-           if (i >= 100)
+               iran(GALSIZE, &w.x, &w.y);
+               q = &game.state.galaxy[w.x][w.y];
+           } while (--i &&
+                    (same(game.quadrant, w) || q->planet == NOPLANET ||
+                     q->supernova || q->status!=secure || q->klingons<=0));
+           if (i == 0) {
                /* can't seem to find one; ignore this call */
+               if (idebug)
+                   prout("=== Couldn't find location for distress event.");
                break;
+           }
 
            /* got one!!  Schedule its enslavement */
            ev = schedule(FENSLV, expran(game.intime));
@@ -418,13 +446,14 @@ void events(void)
            /* tell the captain about it if we can */
            if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
            {
-               prout("Uhura: Captain, starsystem %s in quadrant %d - %d is under attack.",
-                     systemname(q->planet), w.x, w.y);
+               prout("Uhura- Captain, starsystem %s in quadrant %s",
+                     systemname(q->planet), cramlc(quadrant, w));
+               prout("is under attack.");
                if (cancelrest())
                    return;
            }
            break;
-      case FENSLV:             /* starsystem is enslaved */
+       case FENSLV:            /* starsystem is enslaved */
            ev = unschedule(FENSLV);
            /* see if current distress call still active */
            q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
@@ -435,16 +464,22 @@ void events(void)
            q->status = enslaved;
 
            /* play stork and schedule the first baby */
-           ev = schedule(FREPRO, expran(2.0 * game.intime));
+           ev2 = schedule(FREPRO, expran(2.0 * game.intime));
+           ev2->quadrant = ev->quadrant;
 
            /* report the disaster if we can */
            if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
            {
-               prout("\nUhura:  We've lost contact with starsystem %s\n",
+               prout("Uhura- We've lost contact with starsystem %s",
                      systemname(q->planet));
-               prout("  in quadrant %d,%d.\n", ev->quadrant.x,ev->quadrant.y);
+               prout("in quadrant %s.\n", cramlc(quadrant, ev->quadrant));
            }
-      case FREPRO:             /* Klingon reproduces */
+           break;
+       case FREPRO:            /* Klingon reproduces */
+           /*
+            * If we ever switch to a real event queue, we'll need to
+            * explicitly retrieve and restore the x and y.
+            */
            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];
@@ -465,7 +500,7 @@ void events(void)
                        continue;
                    q = &game.state.galaxy[w.x][w.y];
                    /* check for this quad ok (not full & no snova) */
-                   if (q->klingons >= MAXKLQUAD || q->stars < 0)
+                   if (q->klingons >= MAXKLQUAD || !q->supernova)
                        continue;
                    goto foundit;
                }
@@ -477,6 +512,7 @@ void events(void)
 
            /* deliver the child */
            game.state.remkl++;
+           q->klingons++;
            if (same(game.quadrant, w))
                newkling(++game.klhere, &hold);
 
@@ -513,10 +549,10 @@ void wait(void)
 
     /* Alternate resting periods (events) with attacks */
 
-    game.resting = 1;
+    game.resting = true;
     do {
-       if (delay <= 0) game.resting = 0;
-       if (game.resting == 0) {
+       if (delay <= 0) game.resting = false;
+       if (!game.resting) {
            prout(_("%d stardates left."), (int)game.state.remtime);
            return;
        }
@@ -540,7 +576,7 @@ void wait(void)
        // leave if quadrant supernovas
        (!game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova);
 
-    game.resting = 0;
+    game.resting = false;
     game.optime = 0;
 }
 
@@ -640,7 +676,7 @@ void nova(int ix, int iy)
                                double diff = 2000.0 - game.shield;
                                game.energy -= diff;
                                game.shield = 0.0;
-                               game.shldup = 0;
+                               game.shldup = false;
                                prout(_("***Shields knocked out."));
                                game.damage[DSHIELD] += 0.005*game.damfac*Rand()*diff;
                            }
@@ -870,11 +906,9 @@ void snova(int insx, int insy)
        game.state.nplankl += npdead;
     }
     /* mark supernova in galaxy and in star chart */
-    if ((game.quadrant.x == nq.x && game.quadrant.y == nq.y) ||
-       game.damage[DRADIO] == 0 ||
-       game.condit == IHDOCKED)
+    if (same(game.quadrant, nq) || game.damage[DRADIO] == 0 || game.condit == IHDOCKED)
        game.state.galaxy[nq.x][nq.y].supernova = true;
-    /* If supernova destroys last klingons give special message */
+    /* If supernova destroys last Klingons give special message */
     if (KLINGREM==0 && (nq.x != game.quadrant.x || nq.y != game.quadrant.y)) {
        skip(2);
        if (insx == 0) prout(_("Lucky you!"));