2 * events.c -- event-queue handling
4 * This isn't a real event queue a la BSD Trek yet -- you can only have one
5 * event of each type active at any given time. Mostly these means we can
6 * only have one FDISTR/FENSLV/FREPRO sequence going at any given time;
7 * BSD Trek, from which we swiped the idea, can have up to 5.
12 event *unschedule(int evtype)
13 /* remove an event from the schedule */
15 game.future[evtype].date = FOREVER;
16 return &game.future[evtype];
19 int is_scheduled(int evtype)
20 /* is an event of specified type scheduled */
22 return game.future[evtype].date != FOREVER;
25 extern double scheduled(int evtype)
26 /* when will this event happen? */
28 return game.future[evtype].date;
31 event *schedule(int evtype, double offset)
32 /* schedule an event of specified type */
34 game.future[evtype].date = game.state.date + offset;
35 return &game.future[evtype];
38 void postpone(int evtype, double offset)
39 /* poistpone a scheduled event */
41 game.future[evtype].date += offset;
44 static bool cancelrest(void)
45 /* rest period is interrupted by event */
49 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""));
61 /* run through the event queue looking for things to do */
63 int evcode, i=0, j, k, l;
64 double fintim = game.state.date + game.optime, datemin, xtime, repair, yank=0;
65 bool radio_was_broken, ictbeam = false, ipage = false, istract = false;
66 struct quadrant *pdest, *q;
71 prout("=== EVENTS from %.2f to %.2f:", game.state.date, fintim);
72 for (i = 1; i < NEVENTS; i++) {
74 case FSNOVA: proutn("=== Supernova "); break;
75 case FTBEAM: proutn("=== T Beam "); break;
76 case FSNAP: proutn("=== Snapshot "); break;
77 case FBATTAK: proutn("=== Base Attack "); break;
78 case FCDBAS: proutn("=== Base Destroy "); break;
79 case FSCMOVE: proutn("=== SC Move "); break;
80 case FSCDBAS: proutn("=== SC Base Destroy "); break;
81 case FDSPROB: proutn("=== Probe Move "); break;
82 case FDISTR: proutn("=== Distress Call "); break;
83 case FENSLV: proutn("=== Enlavement "); break;
84 case FREPRO: proutn("=== Klingon Build "); break;
87 prout("%.2f", scheduled(i));
94 radio_was_broken = damaged(DRADIO);
98 /* Select earliest extraneous event, evcode==0 if no events */
100 if (game.alldone) return;
102 for (l = 1; l < NEVENTS; l++)
103 if (game.future[l].date < datemin) {
106 prout("== Event %d fires", evcode);
107 datemin = game.future[l].date;
109 xtime = datemin-game.state.date;
110 game.state.date = datemin;
111 /* Decrement Federation resources and recompute remaining time */
112 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime;
113 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
114 if (game.state.remtime <=0) {
118 /* Any crew left alive? */
119 if (game.state.crew <=0) {
123 /* Is life support adequate? */
124 if (damaged(DLIFSUP) && game.condition != docked) {
125 if (game.lsupres < xtime && game.damage[DLIFSUP] > game.lsupres) {
129 game.lsupres -= xtime;
130 if (game.damage[DLIFSUP] <= xtime) game.lsupres = game.inlsr;
134 if (game.condition == docked) repair /= game.docfac;
135 /* Don't fix Deathray here */
136 for (l=0; l<NDEVICES; l++)
137 if (game.damage[l] > 0.0 && l != DDRAY)
138 game.damage[l] -= (game.damage[l]-repair > 0.0 ? repair : game.damage[l]);
139 /* If radio repaired, update star chart and attack reports */
140 if (radio_was_broken && !damaged(DRADIO)) {
141 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"));
142 prout(_(" surveillance reports are coming in."));
149 prout(_(" The star chart is now up to date.\""));
152 /* Cause extraneous event EVCODE to occur */
153 game.optime -= xtime;
155 case FSNOVA: /* Supernova */
156 if (!ipage) pause_game(true);
159 schedule(FSNOVA, expran(0.5*game.intime));
160 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) return;
162 case FSPY: /* Check with spy to see if S.C. should tractor beam */
163 if (game.state.nscrem == 0 ||
164 ictbeam || istract ||
165 game.condition==docked || game.isatb==1 || game.iscate) return;
167 (game.energy < 2000 && game.torps < 4 && game.shield < 1250) ||
168 (damaged(DPHASER) && (damaged(DPHOTON) || game.torps < 4)) ||
170 (game.energy < 2500 || damaged(DPHASER)) &&
171 (game.torps < 5 || damaged(DPHOTON)))) {
172 /* Tractor-beam her! */
174 yank = distance(game.state.kscmdr, game.quadrant);
175 /********* fall through to FTBEAM code ***********/
178 case FTBEAM: /* Tractor beam */
179 if (evcode==FTBEAM) {
180 if (game.state.remcom == 0) {
184 i = Rand()*game.state.remcom+1.0;
185 yank = square(game.state.kcmdr[i].x-game.quadrant.x) + square(game.state.kcmdr[i].y-game.quadrant.y);
186 if (istract || game.condition == docked || yank == 0) {
187 /* Drats! Have to reschedule */
189 game.optime + expran(1.5*game.intime/game.state.remcom));
193 /* tractor beaming cases merge here */
195 if (!ipage) pause_game(true);
197 game.optime = (10.0/(7.5*7.5))*yank; /* 7.5 is yank rate (warp 7.5) */
202 prout(_(" caught in long range tractor beam--"));
203 /* If Kirk & Co. screwing around on planet, handle */
204 atover(true); /* atover(true) is Grab */
205 if (game.alldone) return;
206 if (game.icraft) { /* Caught in Galileo? */
210 /* Check to see if shuttle is aboard */
211 if (game.iscraft == offship) {
214 prout(_("Galileo, left on the planet surface, is captured"));
215 prout(_("by aliens and made into a flying McDonald's."));
216 game.damage[DSHUTTL] = -10;
217 game.iscraft = removed;
220 prout(_("Galileo, left on the planet surface, is well hidden."));
224 game.quadrant = game.state.kscmdr;
226 game.quadrant = game.state.kcmdr[i];
227 game.sector = randplace(QUADSIZE);
229 proutn(_(" is pulled to "));
230 proutn(cramlc(quadrant, game.quadrant));
232 prout(cramlc(sector, game.sector));
234 prout(_("(Remainder of rest/repair period cancelled.)"));
235 game.resting = false;
238 if (!damaged(DSHIELD) && game.shield > 0) {
239 doshield(true); /* raise shields */
242 else prout(_("(Shields not currently useable.)"));
245 /* Adjust finish time to time of tractor beaming */
246 fintim = game.state.date+game.optime;
248 if (game.state.remcom <= 0) unschedule(FTBEAM);
249 else schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom));
251 case FSNAP: /* Snapshot of the universe (for time warp) */
252 game.snapsht = game.state;
253 game.state.snap = true;
254 schedule(FSNAP, expran(0.5 * game.intime));
256 case FBATTAK: /* Commander attacks starbase */
257 if (game.state.remcom==0 || game.state.rembase==0) {
266 if (same(game.state.baseq[j], game.state.kcmdr[k]) &&
267 !same(game.state.baseq[j], game.quadrant) &&
268 !same(game.state.baseq[j], game.state.kscmdr)) {
274 if (j>game.state.rembase) {
275 /* no match found -- try later */
276 schedule(FBATTAK, expran(0.3*game.intime));
280 /* commander + starbase combination found -- launch attack */
281 game.battle = game.state.baseq[j];
282 schedule(FCDBAS, 1.0+3.0*Rand());
283 if (game.isatb) /* extra time if SC already attacking */
284 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date);
285 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime);
286 game.iseenit = false;
287 if (!damaged(DRADIO) && game.condition != docked)
288 break; /* No warning :-( */
290 if (!ipage) pause_game(true);
293 proutn(_("Lt. Uhura- \"Captain, the starbase in "));
294 prout(cramlc(quadrant, game.battle));
295 prout(_(" reports that it is under attack and that it can"));
296 proutn(_(" hold out only until stardate %d"),
297 (int)scheduled(FCDBAS));
302 case FSCDBAS: /* Supercommander destroys base */
305 if (!game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase)
306 break; /* WAS RETURN! */
308 game.battle = game.state.kscmdr;
310 case FCDBAS: /* Commander succeeds in destroying base */
311 if (evcode==FCDBAS) {
313 /* find the lucky pair */
315 if (same(game.state.kcmdr[i], game.battle))
317 if (i > game.state.remcom || game.state.rembase == 0 ||
318 !game.state.galaxy[game.battle.x][game.battle.y].starbase) {
319 /* No action to take after all */
320 invalidate(game.battle);
324 /* Code merges here for any commander destroying base */
325 /* Not perfect, but will have to do */
326 /* Handle case where base is in same quadrant as starship */
327 if (same(game.battle, game.quadrant)) {
328 game.state.chart[game.battle.x][game.battle.y].starbase = false;
329 game.quad[game.base.x][game.base.y] = IHDOT;
330 game.base.x=game.base.y=0;
333 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""));
335 else if (game.state.rembase != 1 &&
336 (!damaged(DRADIO) || game.condition == docked)) {
337 /* Get word via subspace radio */
338 if (!ipage) pause_game(true);
341 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"));
342 proutn(_(" the starbase in "));
343 proutn(cramlc(quadrant, game.battle));
344 prout(_(" has been destroyed by"));
346 prout(_("the Klingon Super-Commander"));
347 else prout(_("a Klingon Commander"));
348 game.state.chart[game.battle.x][game.battle.y].starbase = false;
350 /* Remove Starbase from galaxy */
351 game.state.galaxy[game.battle.x][game.battle.y].starbase = false;
353 if (same(game.state.baseq[i], game.battle))
354 game.state.baseq[i] = game.state.baseq[game.state.rembase];
355 game.state.rembase--;
356 if (game.isatb == 2) {
357 /* reinstate a commander's base attack */
362 invalidate(game.battle);
364 case FSCMOVE: /* Supercommander moves */
365 schedule(FSCMOVE, 0.2777);
366 if (!game.ientesc && !istract && game.isatb != 1 &&
367 (!game.iscate || !game.justin))
370 case FDSPROB: /* Move deep space probe */
371 schedule(FDSPROB, 0.01);
372 game.probex += game.probeinx;
373 game.probey += game.probeiny;
374 i = (int)(game.probex/QUADSIZE +0.05);
375 j = (int)(game.probey/QUADSIZE + 0.05);
376 if (game.probec.x != i || game.probec.y != j) {
379 if (!VALID_QUADRANT(i, j) ||
380 game.state.galaxy[game.probec.x][game.probec.y].supernova) {
381 // Left galaxy or ran into supernova
382 if (!damaged(DRADIO) || game.condition == docked) {
383 if (!ipage) pause_game(true);
386 proutn(_("Lt. Uhura- \"The deep space probe "));
387 if (!VALID_QUADRANT(j, i))
388 proutn(_("has left the galaxy"));
390 proutn(_("is no longer transmitting"));
396 if (!damaged(DRADIO) || game.condition == docked) {
397 if (!ipage) pause_game(true);
400 proutn(_("Lt. Uhura- \"The deep space probe is now in "));
401 proutn(cramlc(quadrant, game.probec));
405 pdest = &game.state.galaxy[game.probec.x][game.probec.y];
406 /* Update star chart if Radio is working or have access to
408 if (!damaged(DRADIO) || game.condition == docked) {
409 struct page *chp = &game.state.chart[game.probec.x][game.probec.y];
411 chp->klingons = pdest->klingons;
412 chp->starbase = pdest->starbase;
413 chp->stars = pdest->stars;
414 pdest->charted = true;
416 game.proben--; // One less to travel
417 if (game.proben == 0 && game.isarmed && pdest->stars) {
418 /* lets blow the sucker! */
419 snova(true, &game.probec);
421 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova)
425 case FDISTR: /* inhabited system issues distress call */
427 /* try a whole bunch of times to find something suitable */
430 /* need a quadrant which is not the current one,
431 which has some stars which are inhabited and
432 not already under attack, which is not
433 supernova'ed, and which has some Klingons in it */
434 w = randplace(GALSIZE);
435 q = &game.state.galaxy[w.x][w.y];
437 (same(game.quadrant, w) || q->planet == NOPLANET ||
438 q->supernova || q->status!=secure || q->klingons<=0));
440 /* can't seem to find one; ignore this call */
442 prout("=== Couldn't find location for distress event.");
446 /* got one!! Schedule its enslavement */
447 ev = schedule(FENSLV, expran(game.intime));
449 q->status = distressed;
451 /* tell the captain about it if we can */
452 if (!damaged(DRADIO) || game.condition == docked)
454 prout("Uhura- Captain, %s in %s reports it is under attack",
455 systnames[q->planet], cramlc(quadrant, w));
456 prout("by a Klingon invasion fleet.");
461 case FENSLV: /* starsystem is enslaved */
462 ev = unschedule(FENSLV);
463 /* see if current distress call still active */
464 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
465 if (q->klingons <= 0) {
469 q->status = enslaved;
471 /* play stork and schedule the first baby */
472 ev2 = schedule(FREPRO, expran(2.0 * game.intime));
473 ev2->quadrant = ev->quadrant;
475 /* report the disaster if we can */
476 if (!damaged(DRADIO) || game.condition == docked)
478 prout("Uhura- We've lost contact with starsystem %s",
479 systnames[q->planet]);
480 prout("in %s.\n", cramlc(quadrant, ev->quadrant));
483 case FREPRO: /* Klingon reproduces */
485 * If we ever switch to a real event queue, we'll need to
486 * explicitly retrieve and restore the x and y.
488 ev = schedule(FREPRO, expran(1.0 * game.intime));
489 /* see if current distress call still active */
490 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
491 if (q->klingons <= 0) {
495 if (game.state.remkl >=MAXKLGAME)
496 break; /* full right now */
497 /* reproduce one Klingon */
499 if (game.klhere >= MAXKLQUAD) {
500 /* this quadrant not ok, pick an adjacent one */
501 for (i = w.x - 1; i <= w.x + 1; i++)
503 for (j = w.y - 1; j <= w.y + 1; j++)
505 if (!VALID_QUADRANT(i, j))
507 q = &game.state.galaxy[w.x][w.y];
508 /* check for this quad ok (not full & no snova) */
509 if (q->klingons >= MAXKLQUAD || q->supernova)
514 break; /* search for eligible quadrant failed */
520 /* deliver the child */
523 if (same(game.quadrant, w))
524 newkling(++game.klhere);
526 /* recompute time left */
527 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
528 /* report the disaster if we can */
529 if (!damaged(DRADIO) || game.condition == docked)
531 if (same(game.quadrant, w)) {
532 prout("Spock- sensors indicate the Klingons have");
533 prout("launched a warship from %s.", systnames[q->planet]);
535 prout("Uhura- Starfleet reports increased Klingon activity");
536 if (q->planet != NOPLANET)
537 proutn("near %s", systnames[q->planet]);
538 prout("in %s.\n", cramlc(quadrant, w));
551 double temp, delay, origTime;
556 if (key != IHEOL) break;
557 proutn(_("How long? "));
564 origTime = delay = aaitem;
565 if (delay <= 0.0) return;
566 if (delay >= game.state.remtime || game.nenhere != 0) {
567 proutn(_("Are you sure? "));
568 if (ja() == false) return;
571 /* Alternate resting periods (events) with attacks */
575 if (delay <= 0) game.resting = false;
577 prout(_("%d stardates left."), (int)game.state.remtime);
580 temp = game.optime = delay;
583 double rtime = 1.0 + Rand();
584 if (rtime < temp) temp = rtime;
587 if (game.optime < delay) attack(false);
588 if (game.alldone) return;
591 if (game.alldone) return;
593 /* Repair Deathray if long rest at starbase */
594 if (origTime-delay >= 9.99 && game.condition == docked)
595 game.damage[DDRAY] = 0.0;
597 // leave if quadrant supernovas
598 (!game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova);
600 game.resting = false;
605 * A nova occurs. It is the result of having a star hit with a
606 * photon torpedo, or possibly of a probe warhead going off.
607 * Stars that go nova cause stars which surround them to undergo
608 * the same probabilistic process. Klingons next to them are
609 * destroyed. And if the starship is next to it, it gets zapped.
610 * If the zap is too much, it gets destroyed.
615 static double course[] =
616 {0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};
617 int bot, top, top2, hits[QUADSIZE+1][3], kount, icx, icy, mm, nn, j;
618 int iquad, iquad1, i, ll;
622 /* Wow! We've supernova'ed */
627 /* handle initial nova */
628 game.quad[nov.x][nov.y] = IHDOT;
629 crmena(false, IHSTAR, sector, nov);
631 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars--;
634 /* Set up stack to recursively trigger adjacent stars */
635 bot = top = top2 = 1;
641 for (mm = bot; mm <= top; mm++)
642 for (nn = 1; nn <= 3; nn++) /* nn,j represents coordinates around current */
643 for (j = 1; j <= 3; j++) {
644 if (j==2 && nn== 2) continue;
645 scratch.x = hits[mm][1]+nn-2;
646 scratch.y = hits[mm][2]+j-2;
647 if (!VALID_SECTOR(scratch.y, scratch.x)) continue;
648 iquad = game.quad[scratch.x][scratch.y];
650 // case IHDOT: /* Empty space ends reaction
657 case IHSTAR: /* Affect another star */
659 /* This star supernovas */
660 snova(false, &scratch);
664 hits[top2][1]=scratch.x;
665 hits[top2][2]=scratch.y;
666 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1;
668 crmena(true, IHSTAR, sector, scratch);
670 game.quad[scratch.x][scratch.y] = IHDOT;
672 case IHP: /* Destroy planet */
673 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
674 game.state.nplankl++;
675 crmena(true, IHP, sector, scratch);
676 prout(_(" destroyed."));
677 DESTROY(&game.state.plnets[game.iplnet]);
679 invalidate(game.plnet);
684 game.quad[scratch.x][scratch.y] = IHDOT;
686 case IHB: /* Destroy base */
687 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = false;
689 if (same(game.state.baseq[i], game.quadrant))
691 game.state.baseq[i] = game.state.baseq[game.state.rembase];
692 game.state.rembase--;
693 invalidate(game.base);
696 crmena(true, IHB, sector, scratch);
697 prout(_(" destroyed."));
698 game.quad[scratch.x][scratch.y] = IHDOT;
700 case IHE: /* Buffet ship */
702 prout(_("***Starship buffeted by nova."));
704 if (game.shield >= 2000.0) game.shield -= 2000.0;
706 double diff = 2000.0 - game.shield;
710 prout(_("***Shields knocked out."));
711 game.damage[DSHIELD] += 0.005*game.damfac*Rand()*diff;
714 else game.energy -= 2000.0;
715 if (game.energy <= 0) {
719 /* add in course nova contributes to kicking starship*/
720 icx += game.sector.x-hits[mm][1];
721 icy += game.sector.y-hits[mm][2];
724 case IHK: /* kill klingon */
725 deadkl(scratch,iquad, scratch);
727 case IHC: /* Damage/destroy big enemies */
730 for_local_enemies(ll)
731 if (same(game.ks[ll], scratch)) break;
732 game.kpower[ll] -= 800.0; /* If firepower is lost, die */
733 if (game.kpower[ll] <= 0.0) {
734 deadkl(scratch, iquad, scratch);
737 newc.x = scratch.x + scratch.x - hits[mm][1];
738 newc.y = scratch.y + scratch.y - hits[mm][2];
739 crmena(true, iquad, sector, scratch);
740 proutn(_(" damaged"));
741 if (!VALID_SECTOR(newc.x, newc.y)) {
742 /* can't leave quadrant */
746 iquad1 = game.quad[newc.x][newc.y];
747 if (iquad1 == IHBLANK) {
748 proutn(_(", blasted into "));
749 crmena(false, IHBLANK, sector, newc);
751 deadkl(scratch, iquad, newc);
754 if (iquad1 != IHDOT) {
755 /* can't move into something else */
759 proutn(_(", buffeted to "));
760 proutn(cramlc(sector, newc));
761 game.quad[scratch.x][scratch.y] = IHDOT;
762 game.quad[newc.x][newc.y] = iquad;
764 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc);
777 /* Starship affected by nova -- kick it away. */
778 game.dist = kount*0.1;
779 if (icx) icx = (icx < 0 ? -1 : 1);
780 if (icy) icy = (icy < 0 ? -1 : 1);
781 game.direc = course[3*(icx+1)+icy+2];
782 if (game.direc == 0.0) game.dist = 0.0;
783 if (game.dist == 0.0) return;
784 game.optime = 10.0*game.dist/16.0;
786 prout(_("Force of nova displaces starship."));
788 game.optime = 10.0*game.dist/16.0;
793 void snova(bool induced, coord *w)
794 /* star goes supernova */
796 int num = 0, nrmdead, npdead, kldead;
803 /* Scheduled supernova -- select star */
804 /* logic changed here so that we won't favor quadrants in top
806 for_quadrants(nq.x) {
807 for_quadrants(nq.y) {
808 stars += game.state.galaxy[nq.x][nq.y].stars;
811 if (stars == 0) return; /* nothing to supernova exists */
812 num = Rand()*stars + 1;
813 for_quadrants(nq.x) {
814 for_quadrants(nq.y) {
815 num -= game.state.galaxy[nq.x][nq.y].stars;
821 proutn("=== Super nova here?");
827 if (!same(nq, game.quadrant) || game.justin) {
828 /* it isn't here, or we just entered (treat as enroute) */
829 if (!damaged(DRADIO) || game.condition == docked) {
831 prout(_("Message from Starfleet Command Stardate %.2f"), game.state.date);
832 prout(_(" Supernova in %s; caution advised."),
833 cramlc(quadrant, nq));
838 /* we are in the quadrant! */
839 num = Rand()* game.state.galaxy[nq.x][nq.y].stars + 1;
842 if (game.quad[ns.x][ns.y]==IHSTAR) {
851 prouts(_("***RED ALERT! RED ALERT!"));
853 prout(_("***Incipient supernova detected at %s"), cramlc(sector, ns));
854 if (square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1) {
855 proutn(_("Emergency override attempts t"));
856 prouts("***************");
863 /* destroy any Klingons in supernovaed quadrant */
864 kldead = game.state.galaxy[nq.x][nq.y].klingons;
865 game.state.galaxy[nq.x][nq.y].klingons = 0;
866 if (same(nq, game.state.kscmdr)) {
867 /* did in the Supercommander! */
868 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0;
873 if (game.state.remcom) {
874 int maxloop = game.state.remcom, l;
875 for (l = 1; l <= maxloop; l++) {
876 if (same(game.state.kcmdr[l], nq)) {
877 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom];
878 invalidate(game.state.kcmdr[game.state.remcom]);
881 if (game.state.remcom==0) unschedule(FTBEAM);
886 game.state.remkl -= kldead;
887 /* destroy Romulans and planets in supernovaed quadrant */
888 nrmdead = game.state.galaxy[nq.x][nq.y].romulans;
889 game.state.galaxy[nq.x][nq.y].romulans = 0;
890 game.state.nromrem -= nrmdead;
891 npdead = num - nrmdead*10;
894 for (loop = 0; loop < game.inplan; loop++)
895 if (same(game.state.plnets[loop].w, nq)) {
896 DESTROY(&game.state.plnets[loop]);
899 /* Destroy any base in supernovaed quadrant */
900 if (game.state.rembase) {
901 int maxloop = game.state.rembase, loop;
902 for (loop = 1; loop <= maxloop; loop++)
903 if (same(game.state.baseq[loop], nq)) {
904 game.state.baseq[loop] = game.state.baseq[game.state.rembase];
905 invalidate(game.state.baseq[game.state.rembase]);
906 game.state.rembase--;
910 /* If starship caused supernova, tally up destruction */
912 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars;
913 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase;
914 game.state.nplankl += npdead;
916 /* mark supernova in galaxy and in star chart */
917 if (same(game.quadrant, nq) || !damaged(DRADIO) || game.condition == docked)
918 game.state.galaxy[nq.x][nq.y].supernova = true;
919 /* If supernova destroys last Klingons give special message */
920 if (KLINGREM==0 && !same(nq, game.quadrant)) {
922 if (!induced) prout(_("Lucky you!"));
923 proutn(_("A supernova in %s has just destroyed the last Klingons."),
924 cramlc(quadrant, nq));
928 /* if some Klingons remain, continue or die in supernova */
929 if (game.alldone) finish(FSNOVAED);