#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;
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 */
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;
}
}
/* 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;
}
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 &&
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]);
+ (int)scheduled(FCDBAS));
prout(".\"");
if (game.resting) {
skip(1);
}
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! */
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)
}
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);
proutn(_("is no longer transmitting"));
prout(".\"");
}
- game.future[FDSPROB] = FOREVER;
+ unschedule(FDSPROB);
break;
}
if (game.damage[DRADIO]==0.0 || game.condit == IHDOCKED) {
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 */
}
}
}
/* 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;
game.state.remcom--;
kldead--;
comdead++;
- if (game.state.remcom==0) game.future[FTBEAM] = FOREVER;
+ if (game.state.remcom==0) unschedule(FTBEAM);
break;
}
}