Abstract all references to the future array (outside of events.c) away.
[super-star-trek.git] / src / events.c
index ac674a27e581c0c749378c6fe1a547d7246de548..7b915f22e28f45b3119f74d3c6c0013da5b74ed6 100644 (file)
@@ -1,6 +1,36 @@
 #include "sst.h"
 #include <math.h>
 
+void unschedule(int evtype)
+/* remove an event from the schedule */
+{
+    game.future[evtype] = FOREVER;
+}
+
+int is_scheduled(int evtype)
+/* is an event of specified type scheduled */
+{
+    return game.future[evtype] != FOREVER;
+}
+
+extern double scheduled(int evtype)
+/* when will this event happen? */
+{
+    return game.future[evtype];
+}
+
+void schedule(int evtype, double offset)
+/* schedule an event of specified type */
+{
+    game.future[evtype] = game.state.date + offset;
+}
+
+void postpone(int evtype, double offset)
+/* poistpone a scheduled event */
+{
+    game.future[evtype] += offset;
+}
+
 void events(void) 
 {
     int ictbeam=0, ipage=0, istract=0, line, i=0, j, k, l, ixhold=0, iyhold=0;
@@ -50,15 +80,15 @@ void events(void)
                game.damage[l] -= (game.damage[l]-repair > 0.0 ? repair : game.damage[l]);
        /* If radio repaired, update star chart and attack reports */
        if (radio_was_broken && game.damage[DRADIO] == 0.0) {
-           prout("Lt. Uhura- \"Captain, the sub-space radio is working and");
-           prout("   surveillance reports are coming in.");
+           prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"));
+           prout(_("   surveillance reports are coming in."));
            skip(1);
            if (game.iseenit==0) {
                attakreport(0);
                game.iseenit = 1;
            }
            rechart();
-           prout("   The star chart is now up to date.\"");
+           prout(_("   The star chart is now up to date.\""));
            skip(1);
        }
        /* Cause extraneous event LINE to occur */
@@ -68,7 +98,7 @@ void events(void)
            if (ipage==0) pause_game(1);
            ipage=1;
            snova(0,0);
-           game.future[FSNOVA] = game.state.date + expran(0.5*game.intime);
+           schedule(FSNOVA, expran(0.5*game.intime));
            if (game.state.galaxy[game.quadx][game.quady].supernova) return;
            break;
        case FSPY: /* Check with spy to see if S.C. should tractor beam */
@@ -90,15 +120,15 @@ void events(void)
        case FTBEAM: /* Tractor beam */
            if (line==FTBEAM) {
                if (game.state.remcom == 0) {
-                   game.future[FTBEAM] = FOREVER;
+                   unschedule(FTBEAM);
                    break;
                }
                i = Rand()*game.state.remcom+1.0;
                yank = square(game.state.cx[i]-game.quadx) + square(game.state.cy[i]-game.quady);
                if (istract || game.condit == IHDOCKED || yank == 0) {
                    /* Drats! Have to reschedule */
-                   game.future[FTBEAM] = game.state.date + game.optime +
-                       expran(1.5*game.intime/game.state.remcom);
+                   schedule(FTBEAM, 
+                            game.optime + expran(1.5*game.intime/game.state.remcom));
                    break;
                }
            }
@@ -111,7 +141,7 @@ void events(void)
            skip(1);
            proutn("***");
            crmshp();
-           prout(" caught in long range tractor beam--");
+           prout(_(" caught in long range tractor beam--"));
            /* If Kirk & Co. screwing around on planet, handle */
            atover(1); /* atover(1) is Grab */
            if (game.alldone) return;
@@ -123,13 +153,13 @@ void events(void)
            if (game.iscraft==0) {
                skip(1);
                if (Rand() > 0.5) {
-                   prout("Galileo, left on the planet surface, is captured");
-                   prout("by aliens and made into a flying McDonald's.");
+                   prout(_("Galileo, left on the planet surface, is captured"));
+                   prout(_("by aliens and made into a flying McDonald's."));
                    game.damage[DSHUTTL] = -10;
                    game.iscraft = -1;
                }
                else {
-                   prout("Galileo, left on the planet surface, is well hidden.");
+                   prout(_("Galileo, left on the planet surface, is well hidden."));
                }
            }
            if (line==0) {
@@ -142,12 +172,12 @@ void events(void)
            }
            iran(QUADSIZE, &game.sectx, &game.secty);
            crmshp();
-           proutn(" is pulled to ");
+           proutn(_(" is pulled to "));
            proutn(cramlc(quadrant, game.quadx, game.quady));
            proutn(", ");
            prout(cramlc(sector, game.sectx, game.secty));
            if (game.resting) {
-               prout("(Remainder of rest/repair period cancelled.)");
+               prout(_("(Remainder of rest/repair period cancelled.)"));
                game.resting = 0;
            }
            if (game.shldup==0) {
@@ -155,24 +185,25 @@ void events(void)
                    doshield(2); /* Shldsup */
                    game.shldchg=0;
                }
-               else prout("(Shields not currently useable.)");
+               else prout(_("(Shields not currently useable.)"));
            }
            newqad(0);
            /* Adjust finish time to time of tractor beaming */
            fintim = game.state.date+game.optime;
            attack(0);
-           if (game.state.remcom <= 0) game.future[FTBEAM] = FOREVER;
-           else game.future[FTBEAM] = game.state.date+game.optime+expran(1.5*game.intime/game.state.remcom);
+           if (game.state.remcom <= 0) unschedule(FTBEAM);
+           else schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom));
            break;
        case FSNAP: /* Snapshot of the universe (for time warp) */
            game.snapsht = game.state;
            game.state.snap = 1;
-           game.future[FSNAP] = game.state.date + expran(0.5 * game.intime);
+           schedule(FSNAP, expran(0.5 * game.intime));
            break;
        case FBATTAK: /* Commander attacks starbase */
            if (game.state.remcom==0 || game.state.rembase==0) {
                /* no can do */
-               game.future[FBATTAK] = game.future[FCDBAS] = FOREVER;
+               unschedule(FBATTAK);
+               unschedule(FCDBAS);
                break;
            }
            i = 0;
@@ -188,16 +219,16 @@ void events(void)
            }
            if (j>game.state.rembase) {
                /* no match found -- try later */
-               game.future[FBATTAK] = game.state.date + expran(0.3*game.intime);
-               game.future[FCDBAS] = FOREVER;
+               schedule(FBATTAK, expran(0.3*game.intime));
+               unschedule(FCDBAS);
                break;
            }
            /* commander + starbase combination found -- launch attack */
            game.batx = game.state.baseqx[j];
            game.baty = game.state.baseqy[j];
-           game.future[FCDBAS] = game.state.date+1.0+3.0*Rand();
+           schedule(FCDBAS, 1.0+3.0*Rand());
            if (game.isatb) /* extra time if SC already attacking */
-               game.future[FCDBAS] += game.future[FSCDBAS]-game.state.date;
+               postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date);
            game.future[FBATTAK] = game.future[FCDBAS] +expran(0.3*game.intime);
            game.iseenit = 0;
            if (game.damage[DRADIO] != 0.0 &&
@@ -206,15 +237,15 @@ void events(void)
            if (ipage==0) pause_game(1);
            ipage = 1;
            skip(1);
-           proutn("Lt. Uhura-  \"Captain, the starbase in ");
+           proutn(_("Lt. Uhura-  \"Captain, the starbase in "));
            prout(cramlc(quadrant, game.batx, game.baty));
-           prout("   reports that it is under attack and that it can");
-           proutn("   hold out only until stardate %d",
-                  (int)game.future[FCDBAS]);
+           prout(_("   reports that it is under attack and that it can"));
+           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?\" ");
+               proutn(_("Mr. Spock-  \"Captain, shall we cancel the rest period?\""));
                if (ja()) {
                    game.resting = 0;
                    game.optime = 0.0;
@@ -223,7 +254,7 @@ void events(void)
            }
            break;
        case FSCDBAS: /* Supercommander destroys base */
-           game.future[FSCDBAS] = FOREVER;
+           unschedule(FSCDBAS);
            game.isatb = 2;
            if (!game.state.galaxy[game.state.isx][game.state.isy].starbase) 
                break; /* WAS RETURN! */
@@ -233,7 +264,7 @@ void events(void)
            game.baty = game.state.isy;
        case FCDBAS: /* Commander succeeds in destroying base */
            if (line==FCDBAS) {
-               game.future[FCDBAS] = FOREVER;
+               unschedule(FCDBAS);
                /* find the lucky pair */
                for_commanders(i)
                    if (game.state.cx[i]==game.batx && game.state.cy[i]==game.baty) 
@@ -254,7 +285,7 @@ void events(void)
                game.basex=game.basey=0;
                newcnd();
                skip(1);
-               prout("Spock-  \"Captain, I believe the starbase has been destroyegame.state.\"");
+               prout(_("Spock-  \"Captain, I believe the starbase has been destroyed.\""));
            }
            else if (game.state.rembase != 1 &&
                     (game.damage[DRADIO] <= 0.0 || game.condit == IHDOCKED)) {
@@ -262,12 +293,12 @@ void events(void)
                if (ipage==0) pause_game(1);
                ipage = 1;
                skip(1);
-               prout("Lt. Uhura-  \"Captain, Starfleet Command reports that");
-               proutn("   the starbase in ");
+               prout(_("Lt. Uhura-  \"Captain, Starfleet Command reports that"));
+               proutn(_("   the starbase in "));
                proutn(cramlc(quadrant, game.batx, game.baty));
-               prout(" has been destroyed by");
-               if (game.isatb==2) prout("the Klingon Super-Commander");
-               else prout("a Klingon Commander");
+               prout(_(" has been destroyed by"));
+               if (game.isatb==2) prout(_("the Klingon Super-Commander"));
+               else prout(_("a Klingon Commander"));
                game.state.chart[game.batx][game.baty].starbase = FALSE;
            }
            /* Remove Starbase from galaxy */
@@ -289,13 +320,13 @@ void events(void)
            }
            break;
        case FSCMOVE: /* Supercommander moves */
-           game.future[FSCMOVE] = game.state.date+0.2777;
+           schedule(FSCMOVE, 0.2777);
            if (game.ientesc+istract==0 &&
                game.isatb!=1 &&
                (game.iscate!=1 || game.justin==1)) scom(&ipage);
            break;
        case FDSPROB: /* Move deep space probe */
-           game.future[FDSPROB] = game.state.date + 0.01;
+           schedule(FDSPROB, 0.01);
            game.probex += game.probeinx;
            game.probey += game.probeiny;
            i = (int)(game.probex/QUADSIZE +0.05);
@@ -310,21 +341,21 @@ void events(void)
                        if (ipage==0) pause_game(1);
                        ipage = 1;
                        skip(1);
-                       proutn("Lt. Uhura-  \"The deep space probe ");
+                       proutn(_("Lt. Uhura-  \"The deep space probe "));
                        if (!VALID_QUADRANT(j, i))
-                           proutn("has left the galaxy");
+                           proutn(_("has left the galaxy"));
                        else
-                           proutn("is no longer transmitting");
+                           proutn(_("is no longer transmitting"));
                        prout(".\"");
                    }
-                   game.future[FDSPROB] = FOREVER;
+                   unschedule(FDSPROB);
                    break;
                }
                if (game.damage[DRADIO]==0.0   || game.condit == IHDOCKED) {
                    if (ipage==0) pause_game(1);
                    ipage = 1;
                    skip(1);
-                   proutn("Lt. Uhura-  \"The deep space probe is now in ");
+                   proutn(_("Lt. Uhura-  \"The deep space probe is now in "));
                    proutn(cramlc(quadrant, game.probecx, game.probecy));
                    prout(".\"");
                }
@@ -342,11 +373,127 @@ void events(void)
                game.state.galaxy[game.probecx][game.probecy].stars) {
                /* lets blow the sucker! */
                snova(1,0);
-               game.future[FDSPROB] = FOREVER;
+               unschedule(FDSPROB);
                if (game.state.galaxy[game.quadx][game.quady].supernova) 
                    return;
            }
            break;
+#ifdef EXPERIMENTAL
+       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;
+           /* 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 */
        }
     }
 }
@@ -361,7 +508,7 @@ void wait(void)
     for (;;) {
        key = scan();
        if (key  != IHEOL) break;
-       proutn("How long? ");
+       proutn(_("How long? "));
     }
     chew();
     if (key != IHREAL) {
@@ -371,7 +518,7 @@ void wait(void)
     origTime = delay = aaitem;
     if (delay <= 0.0) return;
     if (delay >= game.state.remtime || game.nenhere != 0) {
-       proutn("Are you sure? ");
+       proutn(_("Are you sure? "));
        if (ja() == 0) return;
     }
 
@@ -381,7 +528,7 @@ void wait(void)
     do {
        if (delay <= 0) game.resting = 0;
        if (game.resting == 0) {
-           prout("%d stardates left.", (int)game.state.remtime);
+           prout(_("%d stardates left."), (int)game.state.remtime);
            return;
        }
        temp = game.optime = delay;
@@ -423,7 +570,7 @@ void nova(int ix, int iy)
     /* handle initial nova */
     game.quad[ix][iy] = IHDOT;
     crmena(1, IHSTAR, 2, ix, iy);
-    prout(" novas.");
+    prout(_(" novas."));
     game.state.galaxy[game.quadx][game.quady].stars--;
     game.state.starkl++;
        
@@ -462,14 +609,14 @@ void nova(int ix, int iy)
                        game.state.galaxy[game.quadx][game.quady].stars -= 1;
                        game.state.starkl++;
                        crmena(1, IHSTAR, 2, ii, jj);
-                       prout(" novas.");
+                       prout(_(" novas."));
                        game.quad[ii][jj] = IHDOT;
                        break;
                    case IHP: /* Destroy planet */
-                       game.state.galaxy[game.quadx][game.quady].planets -= 1;
+                       game.state.galaxy[game.quadx][game.quady].planet = NULL;
                        game.state.nplankl++;
                        crmena(1, IHP, 2, ii, jj);
-                       prout(" destroyed.");
+                       prout(_(" destroyed."));
                        DESTROY(&game.state.plnets[game.iplnet]);
                        game.iplnet = game.plnetx = game.plnety = 0;
                        if (game.landed == 1) {
@@ -490,12 +637,12 @@ void nova(int ix, int iy)
                        game.state.basekl++;
                        newcnd();
                        crmena(1, IHB, 2, ii, jj);
-                       prout(" destroyed.");
+                       prout(_(" destroyed."));
                        game.quad[ii][jj] = IHDOT;
                        break;
                    case IHE: /* Buffet ship */
                    case IHF:
-                       prout("***Starship buffeted by nova.");
+                       prout(_("***Starship buffeted by nova."));
                        if (game.shldup) {
                            if (game.shield >= 2000.0) game.shield -= 2000.0;
                            else {
@@ -503,7 +650,7 @@ void nova(int ix, int iy)
                                game.energy -= diff;
                                game.shield = 0.0;
                                game.shldup = 0;
-                               prout("***Shields knocked out.");
+                               prout(_("***Shields knocked out."));
                                game.damage[DSHIELD] += 0.005*game.damfac*Rand()*diff;
                            }
                        }
@@ -533,7 +680,7 @@ void nova(int ix, int iy)
                        newcx = ii + ii - hits[mm][1];
                        newcy = jj + jj - hits[mm][2];
                        crmena(1, iquad, 2, ii, jj);
-                       proutn(" damaged");
+                       proutn(_(" damaged"));
                        if (!VALID_SECTOR(newcx, newcy)) {
                            /* can't leave quadrant */
                            skip(1);
@@ -541,7 +688,7 @@ void nova(int ix, int iy)
                        }
                        iquad1 = game.quad[newcx][newcy];
                        if (iquad1 == IHBLANK) {
-                           proutn(", blasted into ");
+                           proutn(_(", blasted into "));
                            crmena(0, IHBLANK, 2, newcx, newcy);
                            skip(1);
                            deadkl(ii, jj, iquad, newcx, newcy);
@@ -552,7 +699,7 @@ void nova(int ix, int iy)
                            skip(1);
                            break;
                        }
-                       proutn(", buffeted to ");
+                       proutn(_(", buffeted to "));
                        proutn(cramlc(sector, newcx, newcy));
                        game.quad[ii][jj] = IHDOT;
                        game.quad[newcx][newcy] = iquad;
@@ -581,7 +728,7 @@ void nova(int ix, int iy)
     if (game.dist == 0.0) return;
     game.optime = 10.0*game.dist/16.0;
     skip(1);
-    prout("Force of nova displaces starship.");
+    prout(_("Force of nova displaces starship."));
     game.iattak=2;     /* Eliminates recursion problem */
     imove();
     game.optime = 10.0*game.dist/16.0;
@@ -638,8 +785,8 @@ void snova(int insx, int insy)
            /* it isn't here, or we just entered (treat as inroute) */
            if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) {
                skip(1);
-               prout("Message from Starfleet Command       Stardate %.2f", game.state.date);
-               prout("     Supernova in %s; caution advised.",
+               prout(_("Message from Starfleet Command       Stardate %.2f"), game.state.date);
+               prout(_("     Supernova in %s; caution advised."),
                      cramlc(quadrant, nqx, nqy));
            }
        }
@@ -664,13 +811,13 @@ void snova(int insx, int insy)
 
     if (incipient) {
        skip(1);
-       prouts("***RED ALERT!  RED ALERT!");
+       prouts(_("***RED ALERT!  RED ALERT!"));
        skip(1);
-       prout("***Incipient supernova detected at ", cramlc(sector, nsx, nsy));
+       prout(_("***Incipient supernova detected at "), cramlc(sector, nsx, nsy));
        nqx = game.quadx;
        nqy = game.quady;
        if (square(nsx-game.sectx) + square(nsy-game.secty) <= 2.1) {
-           proutn("Emergency override attempts t");
+           proutn(_("Emergency override attempts t"));
            prouts("***************");
            skip(1);
            stars();
@@ -685,7 +832,8 @@ void snova(int insx, int insy)
        /* did in the Supercommander! */
        game.state.nscrem = game.state.isx = game.state.isy = game.isatb = game.iscate = 0;
        iscdead = 1;
-       game.future[FSCMOVE] = game.future[FSCDBAS] = FOREVER;
+       unschedule(FSCMOVE);
+       unschedule(FSCDBAS);
     }
     if (game.state.remcom) {
        int maxloop = game.state.remcom, l;
@@ -697,7 +845,7 @@ void snova(int insx, int insy)
                game.state.remcom--;
                kldead--;
                comdead++;
-               if (game.state.remcom==0) game.future[FTBEAM] = FOREVER;
+               if (game.state.remcom==0) unschedule(FTBEAM);
                break;
            }
        }
@@ -741,8 +889,8 @@ void snova(int insx, int insy)
     /* If supernova destroys last klingons give special message */
     if (KLINGREM==0 && (nqx != game.quadx || nqy != game.quady)) {
        skip(2);
-       if (insx == 0) prout("Lucky you!");
-       proutn("A supernova in %s has just destroyed the last Klingons.",
+       if (insx == 0) prout(_("Lucky you!"));
+       proutn(_("A supernova in %s has just destroyed the last Klingons."),
               cramlc(quadrant, nqx, nqy));
        finish(FWON);
        return;