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 */
103 for (l = 1; l < NEVENTS; l++)
104 if (game.future[l].date < datemin) {
107 prout("== Event %d fires", evcode);
108 datemin = game.future[l].date;
110 xtime = datemin-game.state.date;
111 game.state.date = datemin;
112 /* Decrement Federation resources and recompute remaining time */
113 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime;
114 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
115 if (game.state.remtime <=0) {
119 /* Any crew left alive? */
120 if (game.state.crew <=0) {
124 /* Is life support adequate? */
125 if (damaged(DLIFSUP) && game.condition != docked) {
126 if (game.lsupres < xtime && game.damage[DLIFSUP] > game.lsupres) {
130 game.lsupres -= xtime;
131 if (game.damage[DLIFSUP] <= xtime)
132 game.lsupres = game.inlsr;
136 if (game.condition == docked)
137 repair /= game.docfac;
138 /* Don't fix Deathray here */
139 for (l=0; l<NDEVICES; l++)
140 if (game.damage[l] > 0.0 && l != DDRAY)
141 game.damage[l] -= (game.damage[l]-repair > 0.0 ? repair : game.damage[l]);
142 /* If radio repaired, update star chart and attack reports */
143 if (radio_was_broken && !damaged(DRADIO)) {
144 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"));
145 prout(_(" surveillance reports are coming in."));
152 prout(_(" The star chart is now up to date.\""));
155 /* Cause extraneous event EVCODE to occur */
156 game.optime -= xtime;
158 case FSNOVA: /* Supernova */
163 schedule(FSNOVA, expran(0.5*game.intime));
164 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova)
167 case FSPY: /* Check with spy to see if S.C. should tractor beam */
168 if (game.state.nscrem == 0 ||
169 ictbeam || istract ||
170 game.condition==docked || game.isatb==1 || game.iscate) return;
172 (game.energy < 2000 && game.torps < 4 && game.shield < 1250) ||
173 (damaged(DPHASER) && (damaged(DPHOTON) || game.torps < 4)) ||
175 (game.energy < 2500 || damaged(DPHASER)) &&
176 (game.torps < 5 || damaged(DPHOTON)))) {
177 /* Tractor-beam her! */
179 yank = distance(game.state.kscmdr, game.quadrant);
180 /********* fall through to FTBEAM code ***********/
184 case FTBEAM: /* Tractor beam */
185 if (evcode==FTBEAM) {
186 if (game.state.remcom == 0) {
190 i = Rand()*game.state.remcom+1.0;
191 yank = square(game.state.kcmdr[i].x-game.quadrant.x) + square(game.state.kcmdr[i].y-game.quadrant.y);
192 if (istract || game.condition == docked || yank == 0) {
193 /* Drats! Have to reschedule */
195 game.optime + expran(1.5*game.intime/game.state.remcom));
199 /* tractor beaming cases merge here */
204 game.optime = (10.0/(7.5*7.5))*yank; /* 7.5 is yank rate (warp 7.5) */
209 prout(_(" caught in long range tractor beam--"));
210 /* If Kirk & Co. screwing around on planet, handle */
211 atover(true); /* atover(true) is Grab */
214 if (game.icraft) { /* Caught in Galileo? */
218 /* Check to see if shuttle is aboard */
219 if (game.iscraft == offship) {
222 prout(_("Galileo, left on the planet surface, is captured"));
223 prout(_("by aliens and made into a flying McDonald's."));
224 game.damage[DSHUTTL] = -10;
225 game.iscraft = removed;
228 prout(_("Galileo, left on the planet surface, is well hidden."));
232 game.quadrant = game.state.kscmdr;
234 game.quadrant = game.state.kcmdr[i];
235 game.sector = randplace(QUADSIZE);
237 proutn(_(" is pulled to "));
238 proutn(cramlc(quadrant, game.quadrant));
240 prout(cramlc(sector, game.sector));
242 prout(_("(Remainder of rest/repair period cancelled.)"));
243 game.resting = false;
246 if (!damaged(DSHIELD) && game.shield > 0) {
247 doshield(true); /* raise shields */
251 prout(_("(Shields not currently useable.)"));
254 /* Adjust finish time to time of tractor beaming */
255 fintim = game.state.date+game.optime;
257 if (game.state.remcom <= 0)
260 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom));
262 case FSNAP: /* Snapshot of the universe (for time warp) */
263 game.snapsht = game.state;
264 game.state.snap = true;
265 schedule(FSNAP, expran(0.5 * game.intime));
267 case FBATTAK: /* Commander attacks starbase */
268 if (game.state.remcom==0 || game.state.rembase==0) {
277 if (same(game.state.baseq[j], game.state.kcmdr[k]) &&
278 !same(game.state.baseq[j], game.quadrant) &&
279 !same(game.state.baseq[j], game.state.kscmdr)) {
286 if (j>game.state.rembase) {
287 /* no match found -- try later */
288 schedule(FBATTAK, expran(0.3*game.intime));
292 /* commander + starbase combination found -- launch attack */
293 game.battle = game.state.baseq[j];
294 schedule(FCDBAS, 1.0+3.0*Rand());
295 if (game.isatb) /* extra time if SC already attacking */
296 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date);
297 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime);
298 game.iseenit = false;
299 if (!damaged(DRADIO) && game.condition != docked)
300 break; /* No warning :-( */
306 proutn(_("Lt. Uhura- \"Captain, the starbase in "));
307 prout(cramlc(quadrant, game.battle));
308 prout(_(" reports that it is under attack and that it can"));
309 proutn(_(" hold out only until stardate %d"),
310 (int)scheduled(FCDBAS));
315 case FSCDBAS: /* Supercommander destroys base */
318 if (!game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase)
319 break; /* WAS RETURN! */
321 game.battle = game.state.kscmdr;
323 case FCDBAS: /* Commander succeeds in destroying base */
324 if (evcode==FCDBAS) {
326 /* find the lucky pair */
328 if (same(game.state.kcmdr[i], game.battle))
330 if (i > game.state.remcom || game.state.rembase == 0 ||
331 !game.state.galaxy[game.battle.x][game.battle.y].starbase) {
332 /* No action to take after all */
333 invalidate(game.battle);
337 /* Code merges here for any commander destroying base */
338 /* Not perfect, but will have to do */
339 /* Handle case where base is in same quadrant as starship */
340 if (same(game.battle, game.quadrant)) {
341 game.state.chart[game.battle.x][game.battle.y].starbase = false;
342 game.quad[game.base.x][game.base.y] = IHDOT;
343 game.base.x=game.base.y=0;
346 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""));
348 else if (game.state.rembase != 1 &&
349 (!damaged(DRADIO) || game.condition == docked)) {
350 /* Get word via subspace radio */
355 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"));
356 proutn(_(" the starbase in "));
357 proutn(cramlc(quadrant, game.battle));
358 prout(_(" has been destroyed by"));
360 prout(_("the Klingon Super-Commander"));
362 prout(_("a Klingon Commander"));
363 game.state.chart[game.battle.x][game.battle.y].starbase = false;
365 /* Remove Starbase from galaxy */
366 game.state.galaxy[game.battle.x][game.battle.y].starbase = false;
368 if (same(game.state.baseq[i], game.battle))
369 game.state.baseq[i] = game.state.baseq[game.state.rembase];
370 game.state.rembase--;
371 if (game.isatb == 2) {
372 /* reinstate a commander's base attack */
377 invalidate(game.battle);
379 case FSCMOVE: /* Supercommander moves */
380 schedule(FSCMOVE, 0.2777);
381 if (!game.ientesc && !istract && game.isatb != 1 &&
382 (!game.iscate || !game.justin))
385 case FDSPROB: /* Move deep space probe */
386 schedule(FDSPROB, 0.01);
387 game.probex += game.probeinx;
388 game.probey += game.probeiny;
389 i = (int)(game.probex/QUADSIZE +0.05);
390 j = (int)(game.probey/QUADSIZE + 0.05);
391 if (game.probec.x != i || game.probec.y != j) {
394 if (!VALID_QUADRANT(i, j) ||
395 game.state.galaxy[game.probec.x][game.probec.y].supernova) {
396 // Left galaxy or ran into supernova
397 if (!damaged(DRADIO) || game.condition == docked) {
402 proutn(_("Lt. Uhura- \"The deep space probe "));
403 if (!VALID_QUADRANT(j, i))
404 proutn(_("has left the galaxy"));
406 proutn(_("is no longer transmitting"));
412 if (!damaged(DRADIO) || game.condition == docked) {
417 proutn(_("Lt. Uhura- \"The deep space probe is now in "));
418 proutn(cramlc(quadrant, game.probec));
422 pdest = &game.state.galaxy[game.probec.x][game.probec.y];
423 /* Update star chart if Radio is working or have access to
425 if (!damaged(DRADIO) || game.condition == docked) {
426 struct page *chp = &game.state.chart[game.probec.x][game.probec.y];
428 chp->klingons = pdest->klingons;
429 chp->starbase = pdest->starbase;
430 chp->stars = pdest->stars;
431 pdest->charted = true;
433 game.proben--; // One less to travel
434 if (game.proben == 0 && game.isarmed && pdest->stars) {
435 /* lets blow the sucker! */
436 snova(true, &game.probec);
438 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova)
442 case FDISTR: /* inhabited system issues distress call */
444 /* try a whole bunch of times to find something suitable */
447 /* need a quadrant which is not the current one,
448 which has some stars which are inhabited and
449 not already under attack, which is not
450 supernova'ed, and which has some Klingons in it */
451 w = randplace(GALSIZE);
452 q = &game.state.galaxy[w.x][w.y];
454 (same(game.quadrant, w) || q->planet == NOPLANET ||
455 q->supernova || q->status!=secure || q->klingons<=0));
457 /* can't seem to find one; ignore this call */
459 prout("=== Couldn't find location for distress event.");
463 /* got one!! Schedule its enslavement */
464 ev = schedule(FENSLV, expran(game.intime));
466 q->status = distressed;
468 /* tell the captain about it if we can */
469 if (!damaged(DRADIO) || game.condition == docked)
471 prout("Uhura- Captain, %s in %s reports it is under attack",
472 systnames[q->planet], cramlc(quadrant, w));
473 prout("by a Klingon invasion fleet.");
478 case FENSLV: /* starsystem is enslaved */
479 ev = unschedule(FENSLV);
480 /* see if current distress call still active */
481 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
482 if (q->klingons <= 0) {
486 q->status = enslaved;
488 /* play stork and schedule the first baby */
489 ev2 = schedule(FREPRO, expran(2.0 * game.intime));
490 ev2->quadrant = ev->quadrant;
492 /* report the disaster if we can */
493 if (!damaged(DRADIO) || game.condition == docked)
495 prout("Uhura- We've lost contact with starsystem %s",
496 systnames[q->planet]);
497 prout("in %s.\n", cramlc(quadrant, ev->quadrant));
500 case FREPRO: /* Klingon reproduces */
502 * If we ever switch to a real event queue, we'll need to
503 * explicitly retrieve and restore the x and y.
505 ev = schedule(FREPRO, expran(1.0 * game.intime));
506 /* see if current distress call still active */
507 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
508 if (q->klingons <= 0) {
512 if (game.state.remkl >=MAXKLGAME)
513 break; /* full right now */
514 /* reproduce one Klingon */
516 if (game.klhere >= MAXKLQUAD) {
517 /* this quadrant not ok, pick an adjacent one */
518 for (i = w.x - 1; i <= w.x + 1; i++)
520 for (j = w.y - 1; j <= w.y + 1; j++)
522 if (!VALID_QUADRANT(i, j))
524 q = &game.state.galaxy[w.x][w.y];
525 /* check for this quad ok (not full & no snova) */
526 if (q->klingons >= MAXKLQUAD || q->supernova)
531 break; /* search for eligible quadrant failed */
537 /* deliver the child */
540 if (same(game.quadrant, w))
541 newkling(++game.klhere);
543 /* recompute time left */
544 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
545 /* report the disaster if we can */
546 if (!damaged(DRADIO) || game.condition == docked)
548 if (same(game.quadrant, w)) {
549 prout("Spock- sensors indicate the Klingons have");
550 prout("launched a warship from %s.", systnames[q->planet]);
552 prout("Uhura- Starfleet reports increased Klingon activity");
553 if (q->planet != NOPLANET)
554 proutn("near %s", systnames[q->planet]);
555 prout("in %s.\n", cramlc(quadrant, w));
568 double temp, delay, origTime;
575 proutn(_("How long? "));
582 origTime = delay = aaitem;
585 if (delay >= game.state.remtime || game.nenhere != 0) {
586 proutn(_("Are you sure? "));
591 /* Alternate resting periods (events) with attacks */
596 game.resting = false;
598 prout(_("%d stardates left."), (int)game.state.remtime);
601 temp = game.optime = delay;
604 double rtime = 1.0 + Rand();
609 if (game.optime < delay)
618 /* Repair Deathray if long rest at starbase */
619 if (origTime-delay >= 9.99 && game.condition == docked)
620 game.damage[DDRAY] = 0.0;
622 // leave if quadrant supernovas
623 (!game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova);
625 game.resting = false;
630 * A nova occurs. It is the result of having a star hit with a
631 * photon torpedo, or possibly of a probe warhead going off.
632 * Stars that go nova cause stars which surround them to undergo
633 * the same probabilistic process. Klingons next to them are
634 * destroyed. And if the starship is next to it, it gets zapped.
635 * If the zap is too much, it gets destroyed.
640 static double course[] =
641 {0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};
642 int bot, top, top2, hits[QUADSIZE+1][3], kount, icx, icy, mm, nn, j;
643 int iquad, iquad1, i, ll;
647 /* Wow! We've supernova'ed */
652 /* handle initial nova */
653 game.quad[nov.x][nov.y] = IHDOT;
654 crmena(false, IHSTAR, sector, nov);
656 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars--;
659 /* Set up stack to recursively trigger adjacent stars */
660 bot = top = top2 = 1;
666 for (mm = bot; mm <= top; mm++)
667 for (nn = 1; nn <= 3; nn++) /* nn,j represents coordinates around current */
668 for (j = 1; j <= 3; j++) {
671 scratch.x = hits[mm][1]+nn-2;
672 scratch.y = hits[mm][2]+j-2;
673 if (!VALID_SECTOR(scratch.y, scratch.x))
675 iquad = game.quad[scratch.x][scratch.y];
677 // case IHDOT: /* Empty space ends reaction
684 case IHSTAR: /* Affect another star */
686 /* This star supernovas */
687 snova(false, &scratch);
691 hits[top2][1]=scratch.x;
692 hits[top2][2]=scratch.y;
693 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1;
695 crmena(true, IHSTAR, sector, scratch);
697 game.quad[scratch.x][scratch.y] = IHDOT;
699 case IHP: /* Destroy planet */
700 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
701 game.state.nplankl++;
702 crmena(true, IHP, sector, scratch);
703 prout(_(" destroyed."));
704 DESTROY(&game.state.planets[game.iplnet]);
706 invalidate(game.plnet);
711 game.quad[scratch.x][scratch.y] = IHDOT;
713 case IHB: /* Destroy base */
714 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = false;
716 if (same(game.state.baseq[i], game.quadrant))
718 game.state.baseq[i] = game.state.baseq[game.state.rembase];
719 game.state.rembase--;
720 invalidate(game.base);
723 crmena(true, IHB, sector, scratch);
724 prout(_(" destroyed."));
725 game.quad[scratch.x][scratch.y] = IHDOT;
727 case IHE: /* Buffet ship */
729 prout(_("***Starship buffeted by nova."));
731 if (game.shield >= 2000.0)
732 game.shield -= 2000.0;
734 double diff = 2000.0 - game.shield;
738 prout(_("***Shields knocked out."));
739 game.damage[DSHIELD] += 0.005*game.damfac*Rand()*diff;
743 game.energy -= 2000.0;
744 if (game.energy <= 0) {
748 /* add in course nova contributes to kicking starship*/
749 icx += game.sector.x-hits[mm][1];
750 icy += game.sector.y-hits[mm][2];
753 case IHK: /* kill klingon */
754 deadkl(scratch,iquad, scratch);
756 case IHC: /* Damage/destroy big enemies */
759 for_local_enemies(ll)
760 if (same(game.ks[ll], scratch))
762 game.kpower[ll] -= 800.0; /* If firepower is lost, die */
763 if (game.kpower[ll] <= 0.0) {
764 deadkl(scratch, iquad, scratch);
767 newc.x = scratch.x + scratch.x - hits[mm][1];
768 newc.y = scratch.y + scratch.y - hits[mm][2];
769 crmena(true, iquad, sector, scratch);
770 proutn(_(" damaged"));
771 if (!VALID_SECTOR(newc.x, newc.y)) {
772 /* can't leave quadrant */
776 iquad1 = game.quad[newc.x][newc.y];
777 if (iquad1 == IHBLANK) {
778 proutn(_(", blasted into "));
779 crmena(false, IHBLANK, sector, newc);
781 deadkl(scratch, iquad, newc);
784 if (iquad1 != IHDOT) {
785 /* can't move into something else */
789 proutn(_(", buffeted to "));
790 proutn(cramlc(sector, newc));
791 game.quad[scratch.x][scratch.y] = IHDOT;
792 game.quad[newc.x][newc.y] = iquad;
794 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc);
807 /* Starship affected by nova -- kick it away. */
808 game.dist = kount*0.1;
810 icx = (icx < 0 ? -1 : 1);
812 icy = (icy < 0 ? -1 : 1);
813 game.direc = course[3*(icx+1)+icy+2];
814 if (game.direc == 0.0)
816 if (game.dist == 0.0)
818 game.optime = 10.0*game.dist/16.0;
820 prout(_("Force of nova displaces starship."));
822 game.optime = 10.0*game.dist/16.0;
827 void snova(bool induced, coord *w)
828 /* star goes supernova */
830 int num = 0, nrmdead, npdead, kldead;
837 /* Scheduled supernova -- select star */
838 /* logic changed here so that we won't favor quadrants in top
840 for_quadrants(nq.x) {
841 for_quadrants(nq.y) {
842 stars += game.state.galaxy[nq.x][nq.y].stars;
845 if (stars == 0) return; /* nothing to supernova exists */
846 num = Rand()*stars + 1;
847 for_quadrants(nq.x) {
848 for_quadrants(nq.y) {
849 num -= game.state.galaxy[nq.x][nq.y].stars;
857 proutn("=== Super nova here?");
863 if (!same(nq, game.quadrant) || game.justin) {
864 /* it isn't here, or we just entered (treat as enroute) */
865 if (!damaged(DRADIO) || game.condition == docked) {
867 prout(_("Message from Starfleet Command Stardate %.2f"), game.state.date);
868 prout(_(" Supernova in %s; caution advised."),
869 cramlc(quadrant, nq));
874 /* we are in the quadrant! */
875 num = Rand()* game.state.galaxy[nq.x][nq.y].stars + 1;
878 if (game.quad[ns.x][ns.y]==IHSTAR) {
889 prouts(_("***RED ALERT! RED ALERT!"));
891 prout(_("***Incipient supernova detected at %s"), cramlc(sector, ns));
892 if (square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1) {
893 proutn(_("Emergency override attempts t"));
894 prouts("***************");
901 /* destroy any Klingons in supernovaed quadrant */
902 kldead = game.state.galaxy[nq.x][nq.y].klingons;
903 game.state.galaxy[nq.x][nq.y].klingons = 0;
904 if (same(nq, game.state.kscmdr)) {
905 /* did in the Supercommander! */
906 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0;
911 if (game.state.remcom) {
912 int maxloop = game.state.remcom, l;
913 for (l = 1; l <= maxloop; l++) {
914 if (same(game.state.kcmdr[l], nq)) {
915 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom];
916 invalidate(game.state.kcmdr[game.state.remcom]);
919 if (game.state.remcom==0)
925 game.state.remkl -= kldead;
926 /* destroy Romulans and planets in supernovaed quadrant */
927 nrmdead = game.state.galaxy[nq.x][nq.y].romulans;
928 game.state.galaxy[nq.x][nq.y].romulans = 0;
929 game.state.nromrem -= nrmdead;
930 npdead = num - nrmdead*10;
933 for (loop = 0; loop < game.inplan; loop++)
934 if (same(game.state.planets[loop].w, nq)) {
935 DESTROY(&game.state.planets[loop]);
938 /* Destroy any base in supernovaed quadrant */
939 if (game.state.rembase) {
940 int maxloop = game.state.rembase, loop;
941 for (loop = 1; loop <= maxloop; loop++)
942 if (same(game.state.baseq[loop], nq)) {
943 game.state.baseq[loop] = game.state.baseq[game.state.rembase];
944 invalidate(game.state.baseq[game.state.rembase]);
945 game.state.rembase--;
949 /* If starship caused supernova, tally up destruction */
951 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars;
952 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase;
953 game.state.nplankl += npdead;
955 /* mark supernova in galaxy and in star chart */
956 if (same(game.quadrant, nq) || !damaged(DRADIO) || game.condition == docked)
957 game.state.galaxy[nq.x][nq.y].supernova = true;
958 /* If supernova destroys last Klingons give special message */
959 if (KLINGREM==0 && !same(nq, game.quadrant)) {
962 prout(_("Lucky you!"));
963 proutn(_("A supernova in %s has just destroyed the last Klingons."),
964 cramlc(quadrant, nq));
968 /* if some Klingons remain, continue or die in supernova */