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.condit != IHDOCKED) {
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.condit == IHDOCKED) 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."));
144 if (game.iseenit==0) {
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(1);
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.condit==IHDOCKED || game.isatb==1 || game.iscate==1) 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 = square(game.state.kscmdr.x-game.quadrant.x) + square(game.state.kscmdr.y-game.quadrant.y);
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.condit == IHDOCKED || 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(1);
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==0) {
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;
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 = iran(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(2); /* Shldsup */
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;
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);
287 if (!damaged(DRADIO) && game.condit != IHDOCKED)
288 break; /* No warning :-( */
290 if (!ipage) pause_game(1);
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 game.battle.x = game.battle.y = 0;
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.condit == IHDOCKED)) {
337 /* Get word via subspace radio */
338 if (!ipage) pause_game(1);
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 game.battle.x = game.battle.y = 0;
365 case FSCMOVE: /* Supercommander moves */
366 schedule(FSCMOVE, 0.2777);
367 if (!game.ientesc && !istract && game.isatb != 1 &&
368 (game.iscate != 1 || !game.justin))
371 case FDSPROB: /* Move deep space probe */
372 schedule(FDSPROB, 0.01);
373 game.probex += game.probeinx;
374 game.probey += game.probeiny;
375 i = (int)(game.probex/QUADSIZE +0.05);
376 j = (int)(game.probey/QUADSIZE + 0.05);
377 if (game.probec.x != i || game.probec.y != j) {
380 if (!VALID_QUADRANT(i, j) ||
381 game.state.galaxy[game.probec.x][game.probec.y].supernova) {
382 // Left galaxy or ran into supernova
383 if (!damaged(DRADIO) || game.condit == IHDOCKED) {
384 if (ipage==0) pause_game(1);
387 proutn(_("Lt. Uhura- \"The deep space probe "));
388 if (!VALID_QUADRANT(j, i))
389 proutn(_("has left the galaxy"));
391 proutn(_("is no longer transmitting"));
397 if (!damaged(DRADIO) || game.condit == IHDOCKED) {
398 if (ipage==0) pause_game(1);
401 proutn(_("Lt. Uhura- \"The deep space probe is now in "));
402 proutn(cramlc(quadrant, game.probec));
406 pdest = &game.state.galaxy[game.probec.x][game.probec.y];
407 /* Update star chart if Radio is working or have access to
409 if (!damaged(DRADIO) || game.condit == IHDOCKED) {
410 struct page *chp = &game.state.chart[game.probec.x][game.probec.y];
412 chp->klingons = pdest->klingons;
413 chp->starbase = pdest->starbase;
414 chp->stars = pdest->stars;
415 pdest->charted = true;
417 game.proben--; // One less to travel
418 if (game.proben == 0 && game.isarmed && pdest->stars) {
419 /* lets blow the sucker! */
420 snova(true, &game.probec);
422 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova)
426 case FDISTR: /* inhabited system issues distress call */
428 /* try a whole bunch of times to find something suitable */
431 /* need a quadrant which is not the current one,
432 which has some stars which are inhabited and
433 not already under attack, which is not
434 supernova'ed, and which has some Klingons in it */
436 q = &game.state.galaxy[w.x][w.y];
438 (same(game.quadrant, w) || q->planet == NOPLANET ||
439 q->supernova || q->status!=secure || q->klingons<=0));
441 /* can't seem to find one; ignore this call */
443 prout("=== Couldn't find location for distress event.");
447 /* got one!! Schedule its enslavement */
448 ev = schedule(FENSLV, expran(game.intime));
450 q->status = distressed;
452 /* tell the captain about it if we can */
453 if (!damaged(DRADIO) || game.condit == IHDOCKED)
455 prout("Uhura- Captain, %s in %s reports it is under attack",
456 systemname(q->planet), cramlc(quadrant, w));
457 prout("by a Klingon invasion fleet.");
462 case FENSLV: /* starsystem is enslaved */
463 ev = unschedule(FENSLV);
464 /* see if current distress call still active */
465 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
466 if (q->klingons <= 0) {
470 q->status = enslaved;
472 /* play stork and schedule the first baby */
473 ev2 = schedule(FREPRO, expran(2.0 * game.intime));
474 ev2->quadrant = ev->quadrant;
476 /* report the disaster if we can */
477 if (!damaged(DRADIO) || game.condit == IHDOCKED)
479 prout("Uhura- We've lost contact with starsystem %s",
480 systemname(q->planet));
481 prout("in %s.\n", cramlc(quadrant, ev->quadrant));
484 case FREPRO: /* Klingon reproduces */
486 * If we ever switch to a real event queue, we'll need to
487 * explicitly retrieve and restore the x and y.
489 ev = schedule(FREPRO, expran(1.0 * game.intime));
490 /* see if current distress call still active */
491 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
492 if (q->klingons <= 0) {
496 if (game.state.remkl >=MAXKLGAME)
497 break; /* full right now */
498 /* reproduce one Klingon */
500 if (game.klhere >= MAXKLQUAD) {
501 /* this quadrant not ok, pick an adjacent one */
502 for (i = w.x - 1; i <= w.x + 1; i++)
504 for (j = w.y - 1; j <= w.y + 1; j++)
506 if (!VALID_QUADRANT(i, j))
508 q = &game.state.galaxy[w.x][w.y];
509 /* check for this quad ok (not full & no snova) */
510 if (q->klingons >= MAXKLQUAD || q->supernova)
515 break; /* search for eligible quadrant failed */
521 /* deliver the child */
524 if (same(game.quadrant, w))
525 newkling(++game.klhere);
527 /* recompute time left */
528 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
529 /* report the disaster if we can */
530 if (!damaged(DRADIO) || game.condit == IHDOCKED)
532 if (same(game.quadrant, w)) {
533 prout("Spock- sensors indicate the Klingons have");
534 prout("launched a warship from %s.",systemname(q->planet));
536 prout("Uhura- Starfleet reports increased Klingon activity");
537 if (q->planet != NOPLANET)
538 proutn("near %s", systemname(q->planet));
539 prout("in %s.\n", cramlc(quadrant, w));
552 double temp, delay, origTime;
557 if (key != IHEOL) break;
558 proutn(_("How long? "));
565 origTime = delay = aaitem;
566 if (delay <= 0.0) return;
567 if (delay >= game.state.remtime || game.nenhere != 0) {
568 proutn(_("Are you sure? "));
569 if (ja() == false) return;
572 /* Alternate resting periods (events) with attacks */
576 if (delay <= 0) game.resting = false;
578 prout(_("%d stardates left."), (int)game.state.remtime);
581 temp = game.optime = delay;
584 double rtime = 1.0 + Rand();
585 if (rtime < temp) temp = rtime;
588 if (game.optime < delay) attack(0);
589 if (game.alldone) return;
592 if (game.alldone) return;
594 /* Repair Deathray if long rest at starbase */
595 if (origTime-delay >= 9.99 && game.condit == IHDOCKED)
596 game.damage[DDRAY] = 0.0;
598 // leave if quadrant supernovas
599 (!game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova);
601 game.resting = false;
608 static double course[] =
609 {0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};
610 int bot, top, top2, hits[QUADSIZE+1][3], kount, icx, icy, mm, nn, j;
611 int iquad, iquad1, i, ll;
615 /* Wow! We've supernova'ed */
620 /* handle initial nova */
621 game.quad[nov.x][nov.y] = IHDOT;
622 crmena(false, IHSTAR, sector, nov);
624 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars--;
627 /* Set up stack to recursively trigger adjacent stars */
628 bot = top = top2 = 1;
634 for (mm = bot; mm <= top; mm++)
635 for (nn = 1; nn <= 3; nn++) /* nn,j represents coordinates around current */
636 for (j = 1; j <= 3; j++) {
637 if (j==2 && nn== 2) continue;
638 scratch.x = hits[mm][1]+nn-2;
639 scratch.y = hits[mm][2]+j-2;
640 if (!VALID_SECTOR(scratch.y, scratch.x)) continue;
641 iquad = game.quad[scratch.x][scratch.y];
643 // case IHDOT: /* Empty space ends reaction
650 case IHSTAR: /* Affect another star */
652 /* This star supernovas */
653 snova(false, &scratch);
657 hits[top2][1]=scratch.x;
658 hits[top2][2]=scratch.y;
659 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1;
661 crmena(true, IHSTAR, sector, scratch);
663 game.quad[scratch.x][scratch.y] = IHDOT;
665 case IHP: /* Destroy planet */
666 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
667 game.state.nplankl++;
668 crmena(true, IHP, sector, scratch);
669 prout(_(" destroyed."));
670 DESTROY(&game.state.plnets[game.iplnet]);
671 game.iplnet = game.plnet.x = game.plnet.y = 0;
672 if (game.landed == 1) {
676 game.quad[scratch.x][scratch.y] = IHDOT;
678 case IHB: /* Destroy base */
679 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = false;
681 if (same(game.state.baseq[i], game.quadrant))
683 game.state.baseq[i] = game.state.baseq[game.state.rembase];
684 game.state.rembase--;
685 game.base.x = game.base.y = 0;
688 crmena(true, IHB, sector, scratch);
689 prout(_(" destroyed."));
690 game.quad[scratch.x][scratch.y] = IHDOT;
692 case IHE: /* Buffet ship */
694 prout(_("***Starship buffeted by nova."));
696 if (game.shield >= 2000.0) game.shield -= 2000.0;
698 double diff = 2000.0 - game.shield;
702 prout(_("***Shields knocked out."));
703 game.damage[DSHIELD] += 0.005*game.damfac*Rand()*diff;
706 else game.energy -= 2000.0;
707 if (game.energy <= 0) {
711 /* add in course nova contributes to kicking starship*/
712 icx += game.sector.x-hits[mm][1];
713 icy += game.sector.y-hits[mm][2];
716 case IHK: /* kill klingon */
717 deadkl(scratch,iquad, scratch.x, scratch.y);
719 case IHC: /* Damage/destroy big enemies */
722 for_local_enemies(ll)
723 if (same(game.ks[ll], scratch)) break;
724 game.kpower[ll] -= 800.0; /* If firepower is lost, die */
725 if (game.kpower[ll] <= 0.0) {
726 deadkl(scratch, iquad, scratch.x, scratch.y);
729 newc.x = scratch.x + scratch.x - hits[mm][1];
730 newc.y = scratch.y + scratch.y - hits[mm][2];
731 crmena(true, iquad, sector, scratch);
732 proutn(_(" damaged"));
733 if (!VALID_SECTOR(newc.x, newc.y)) {
734 /* can't leave quadrant */
738 iquad1 = game.quad[newc.x][newc.y];
739 if (iquad1 == IHBLANK) {
740 proutn(_(", blasted into "));
741 crmena(false, IHBLANK, sector, newc);
743 deadkl(scratch, iquad, newc.x, newc.y);
746 if (iquad1 != IHDOT) {
747 /* can't move into something else */
751 proutn(_(", buffeted to "));
752 proutn(cramlc(sector, newc));
753 game.quad[scratch.x][scratch.y] = IHDOT;
754 game.quad[newc.x][newc.y] = iquad;
756 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc);
769 /* Starship affected by nova -- kick it away. */
770 game.dist = kount*0.1;
771 if (icx) icx = (icx < 0 ? -1 : 1);
772 if (icy) icy = (icy < 0 ? -1 : 1);
773 game.direc = course[3*(icx+1)+icy+2];
774 if (game.direc == 0.0) game.dist = 0.0;
775 if (game.dist == 0.0) return;
776 game.optime = 10.0*game.dist/16.0;
778 prout(_("Force of nova displaces starship."));
779 game.iattak=2; /* Eliminates recursion problem */
781 game.optime = 10.0*game.dist/16.0;
786 void snova(bool induced, coord *w)
787 /* star goes supernova */
789 int num = 0, nrmdead, npdead, kldead;
796 /* Scheduled supernova -- select star */
797 /* logic changed here so that we won't favor quadrants in top
799 for_quadrants(nq.x) {
800 for_quadrants(nq.y) {
801 stars += game.state.galaxy[nq.x][nq.y].stars;
804 if (stars == 0) return; /* nothing to supernova exists */
805 num = Rand()*stars + 1;
806 for_quadrants(nq.x) {
807 for_quadrants(nq.y) {
808 num -= game.state.galaxy[nq.x][nq.y].stars;
814 proutn("=== Super nova here?");
820 if (!same(nq, game.quadrant) || game.justin) {
821 /* it isn't here, or we just entered (treat as enroute) */
822 if (!damaged(DRADIO) || game.condit == IHDOCKED) {
824 prout(_("Message from Starfleet Command Stardate %.2f"), game.state.date);
825 prout(_(" Supernova in %s; caution advised."),
826 cramlc(quadrant, nq));
831 /* we are in the quadrant! */
832 num = Rand()* game.state.galaxy[nq.x][nq.y].stars + 1;
835 if (game.quad[ns.x][ns.y]==IHSTAR) {
844 prouts(_("***RED ALERT! RED ALERT!"));
846 prout(_("***Incipient supernova detected at "), cramlc(sector, ns));
847 if (square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1) {
848 proutn(_("Emergency override attempts t"));
849 prouts("***************");
856 /* destroy any Klingons in supernovaed quadrant */
857 kldead = game.state.galaxy[nq.x][nq.y].klingons;
858 game.state.galaxy[nq.x][nq.y].klingons = 0;
859 if (same(nq, game.state.kscmdr)) {
860 /* did in the Supercommander! */
861 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = game.iscate = 0;
865 if (game.state.remcom) {
866 int maxloop = game.state.remcom, l;
867 for (l = 1; l <= maxloop; l++) {
868 if (same(game.state.kcmdr[l], nq)) {
869 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom];
870 game.state.kcmdr[game.state.remcom].x = game.state.kcmdr[game.state.remcom].y = 0;
873 if (game.state.remcom==0) unschedule(FTBEAM);
878 game.state.remkl -= kldead;
879 /* destroy Romulans and planets in supernovaed quadrant */
880 nrmdead = game.state.galaxy[nq.x][nq.y].romulans;
881 game.state.galaxy[nq.x][nq.y].romulans = 0;
882 game.state.nromrem -= nrmdead;
883 npdead = num - nrmdead*10;
886 for (loop = 0; loop < game.inplan; loop++)
887 if (same(game.state.plnets[loop].w, nq)) {
888 DESTROY(&game.state.plnets[loop]);
891 /* Destroy any base in supernovaed quadrant */
892 if (game.state.rembase) {
893 int maxloop = game.state.rembase, loop;
894 for (loop = 1; loop <= maxloop; loop++)
895 if (same(game.state.baseq[loop], nq)) {
896 game.state.baseq[loop] = game.state.baseq[game.state.rembase];
897 game.state.baseq[game.state.rembase].x = game.state.baseq[game.state.rembase].y = 0;
898 game.state.rembase--;
902 /* If starship caused supernova, tally up destruction */
904 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars;
905 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase;
906 game.state.nplankl += npdead;
908 /* mark supernova in galaxy and in star chart */
909 if (same(game.quadrant, nq) || !damaged(DRADIO) || game.condit == IHDOCKED)
910 game.state.galaxy[nq.x][nq.y].supernova = true;
911 /* If supernova destroys last Klingons give special message */
912 if (KLINGREM==0 && !same(nq, game.quadrant)) {
914 if (!induced) prout(_("Lucky you!"));
915 proutn(_("A supernova in %s has just destroyed the last Klingons."),
916 cramlc(quadrant, nq));
920 /* if some Klingons remain, continue or die in supernova */
921 if (game.alldone) finish(FSNOVAED);