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)
48 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""));
61 int ictbeam=0, ipage=0, istract=0, line, i=0, j, k, l, ixhold=0, iyhold=0;
62 double fintim = game.state.date + game.optime, datemin, xtime, repair, yank=0;
64 struct quadrant *pdest, *q;
69 prout("=== EVENTS from %.2f to %.2f:", game.state.date, fintim);
70 for (i = 1; i < NEVENTS; i++) {
72 case FSNOVA: proutn("=== Supernova "); break;
73 case FTBEAM: proutn("=== T Beam "); break;
74 case FSNAP: proutn("=== Snapshot "); break;
75 case FBATTAK: proutn("=== Base Attack "); break;
76 case FCDBAS: proutn("=== Base Destroy "); break;
77 case FSCMOVE: proutn("=== SC Move "); break;
78 case FSCDBAS: proutn("=== SC Base Destroy "); break;
79 case FDSPROB: proutn("=== Probe Move "); break;
80 case FDISTR: proutn("=== Distress Call "); break;
81 case FENSLV: proutn("=== Enlavement "); break;
82 case FREPRO: proutn("=== Klingon Build "); break;
85 prout("%.2f", scheduled(i));
92 radio_was_broken = (game.damage[DRADIO] != 0.0);
95 /* Select earliest extraneous event, line==0 if no events */
97 if (game.alldone) return;
99 for (l = 1; l < NEVENTS; l++)
100 if (game.future[l].date < datemin) {
103 prout("== Event %d fires", line);
104 datemin = game.future[l].date;
106 xtime = datemin-game.state.date;
107 game.state.date = datemin;
108 /* Decrement Federation resources and recompute remaining time */
109 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime;
110 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
111 if (game.state.remtime <=0) {
115 /* Is life support adequate? */
116 if (game.damage[DLIFSUP] && game.condit != IHDOCKED) {
117 if (game.lsupres < xtime && game.damage[DLIFSUP] > game.lsupres) {
121 game.lsupres -= xtime;
122 if (game.damage[DLIFSUP] <= xtime) game.lsupres = game.inlsr;
126 if (game.condit == IHDOCKED) repair /= game.docfac;
127 /* Don't fix Deathray here */
128 for (l=0; l<NDEVICES; l++)
129 if (game.damage[l] > 0.0 && l != DDRAY)
130 game.damage[l] -= (game.damage[l]-repair > 0.0 ? repair : game.damage[l]);
131 /* If radio repaired, update star chart and attack reports */
132 if (radio_was_broken && game.damage[DRADIO] == 0.0) {
133 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"));
134 prout(_(" surveillance reports are coming in."));
136 if (game.iseenit==0) {
141 prout(_(" The star chart is now up to date.\""));
144 /* Cause extraneous event LINE to occur */
145 game.optime -= xtime;
147 case FSNOVA: /* Supernova */
148 if (ipage==0) pause_game(1);
151 schedule(FSNOVA, expran(0.5*game.intime));
152 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) return;
154 case FSPY: /* Check with spy to see if S.C. should tractor beam */
155 if (game.state.nscrem == 0 ||
156 ictbeam+istract > 0 ||
157 game.condit==IHDOCKED || game.isatb==1 || game.iscate==1) return;
159 (game.energy < 2000 && game.torps < 4 && game.shield < 1250) ||
160 (game.damage[DPHASER]>0 && (game.damage[DPHOTON]>0 || game.torps < 4)) ||
161 (game.damage[DSHIELD] > 0 &&
162 (game.energy < 2500 || game.damage[DPHASER] > 0) &&
163 (game.torps < 5 || game.damage[DPHOTON] > 0))) {
164 /* Tractor-beam her! */
166 yank = square(game.state.kscmdr.x-game.quadrant.x) + square(game.state.kscmdr.y-game.quadrant.y);
167 /********* fall through to FTBEAM code ***********/
170 case FTBEAM: /* Tractor beam */
172 if (game.state.remcom == 0) {
176 i = Rand()*game.state.remcom+1.0;
177 yank = square(game.state.kcmdr[i].x-game.quadrant.x) + square(game.state.kcmdr[i].y-game.quadrant.y);
178 if (istract || game.condit == IHDOCKED || yank == 0) {
179 /* Drats! Have to reschedule */
181 game.optime + expran(1.5*game.intime/game.state.remcom));
185 /* tractor beaming cases merge here */
187 if (ipage==0) pause_game(1);
189 game.optime = (10.0/(7.5*7.5))*yank; /* 7.5 is yank rate (warp 7.5) */
194 prout(_(" caught in long range tractor beam--"));
195 /* If Kirk & Co. screwing around on planet, handle */
196 atover(1); /* atover(1) is Grab */
197 if (game.alldone) return;
198 if (game.icraft == 1) { /* Caught in Galileo? */
202 /* Check to see if shuttle is aboard */
203 if (game.iscraft==0) {
206 prout(_("Galileo, left on the planet surface, is captured"));
207 prout(_("by aliens and made into a flying McDonald's."));
208 game.damage[DSHUTTL] = -10;
212 prout(_("Galileo, left on the planet surface, is well hidden."));
216 game.quadrant = game.state.kscmdr;
218 game.quadrant = game.state.kcmdr[i];
219 iran(QUADSIZE, &game.sector.x, &game.sector.y);
221 proutn(_(" is pulled to "));
222 proutn(cramlc(quadrant, game.quadrant));
224 prout(cramlc(sector, game.sector));
226 prout(_("(Remainder of rest/repair period cancelled.)"));
227 game.resting = false;
230 if (game.damage[DSHIELD]==0 && game.shield > 0) {
231 doshield(2); /* Shldsup */
234 else prout(_("(Shields not currently useable.)"));
237 /* Adjust finish time to time of tractor beaming */
238 fintim = game.state.date+game.optime;
240 if (game.state.remcom <= 0) unschedule(FTBEAM);
241 else schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom));
243 case FSNAP: /* Snapshot of the universe (for time warp) */
244 game.snapsht = game.state;
246 schedule(FSNAP, expran(0.5 * game.intime));
248 case FBATTAK: /* Commander attacks starbase */
249 if (game.state.remcom==0 || game.state.rembase==0) {
258 if (same(game.state.baseq[j], game.state.kcmdr[k]) &&
259 !same(game.state.baseq[j], game.quadrant) &&
260 !same(game.state.baseq[j], game.state.kscmdr)) {
266 if (j>game.state.rembase) {
267 /* no match found -- try later */
268 schedule(FBATTAK, expran(0.3*game.intime));
272 /* commander + starbase combination found -- launch attack */
273 game.battle = game.state.baseq[j];
274 schedule(FCDBAS, 1.0+3.0*Rand());
275 if (game.isatb) /* extra time if SC already attacking */
276 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date);
277 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime);
279 if (game.damage[DRADIO] != 0.0 && game.condit != IHDOCKED)
280 break; /* No warning :-( */
282 if (ipage==0) pause_game(1);
285 proutn(_("Lt. Uhura- \"Captain, the starbase in "));
286 prout(cramlc(quadrant, game.battle));
287 prout(_(" reports that it is under attack and that it can"));
288 proutn(_(" hold out only until stardate %d"),
289 (int)scheduled(FCDBAS));
294 case FSCDBAS: /* Supercommander destroys base */
297 if (!game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase)
298 break; /* WAS RETURN! */
299 ixhold = game.battle.x;
300 iyhold = game.battle.y;
301 game.battle = game.state.kscmdr;
303 case FCDBAS: /* Commander succeeds in destroying base */
306 /* find the lucky pair */
308 if (same(game.state.kcmdr[i], game.battle))
310 if (i > game.state.remcom || game.state.rembase == 0 ||
311 !game.state.galaxy[game.battle.x][game.battle.y].starbase) {
312 /* No action to take after all */
313 game.battle.x = game.battle.y = 0;
317 /* Code merges here for any commander destroying base */
318 /* Not perfect, but will have to do */
319 /* Handle case where base is in same quadrant as starship */
320 if (same(game.battle, game.quadrant)) {
321 game.state.chart[game.battle.x][game.battle.y].starbase = false;
322 game.quad[game.base.x][game.base.y] = IHDOT;
323 game.base.x=game.base.y=0;
326 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""));
328 else if (game.state.rembase != 1 &&
329 (game.damage[DRADIO] <= 0.0 || game.condit == IHDOCKED)) {
330 /* Get word via subspace radio */
331 if (ipage==0) pause_game(1);
334 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"));
335 proutn(_(" the starbase in "));
336 proutn(cramlc(quadrant, game.battle));
337 prout(_(" has been destroyed by"));
339 prout(_("the Klingon Super-Commander"));
340 else prout(_("a Klingon Commander"));
341 game.state.chart[game.battle.x][game.battle.y].starbase = false;
343 /* Remove Starbase from galaxy */
344 game.state.galaxy[game.battle.x][game.battle.y].starbase = false;
346 if (same(game.state.baseq[i], game.battle))
347 game.state.baseq[i] = game.state.baseq[game.state.rembase];
348 game.state.rembase--;
349 if (game.isatb == 2) {
350 /* reinstate a commander's base attack */
351 game.battle.x = ixhold;
352 game.battle.y = iyhold;
356 game.battle.x = game.battle.y = 0;
359 case FSCMOVE: /* Supercommander moves */
360 schedule(FSCMOVE, 0.2777);
361 if (game.ientesc+istract==0 &&
363 (game.iscate != 1 || !game.justin)) scom(&ipage);
365 case FDSPROB: /* Move deep space probe */
366 schedule(FDSPROB, 0.01);
367 game.probex += game.probeinx;
368 game.probey += game.probeiny;
369 i = (int)(game.probex/QUADSIZE +0.05);
370 j = (int)(game.probey/QUADSIZE + 0.05);
371 if (game.probec.x != i || game.probec.y != j) {
374 if (!VALID_QUADRANT(i, j) ||
375 game.state.galaxy[game.probec.x][game.probec.y].supernova) {
376 // Left galaxy or ran into supernova
377 if (game.damage[DRADIO]==0.0 || game.condit == IHDOCKED) {
378 if (ipage==0) pause_game(1);
381 proutn(_("Lt. Uhura- \"The deep space probe "));
382 if (!VALID_QUADRANT(j, i))
383 proutn(_("has left the galaxy"));
385 proutn(_("is no longer transmitting"));
391 if (game.damage[DRADIO]==0.0 || game.condit == IHDOCKED) {
392 if (ipage==0) pause_game(1);
395 proutn(_("Lt. Uhura- \"The deep space probe is now in "));
396 proutn(cramlc(quadrant, game.probec));
400 pdest = &game.state.galaxy[game.probec.x][game.probec.y];
401 /* Update star chart if Radio is working or have access to
403 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) {
404 struct page *chp = &game.state.chart[game.probec.x][game.probec.y];
406 chp->klingons = pdest->klingons;
407 chp->starbase = pdest->starbase;
408 chp->stars = pdest->stars;
409 pdest->charted = true;
411 game.proben--; // One less to travel
412 if (game.proben == 0 && game.isarmed && pdest->stars) {
413 /* lets blow the sucker! */
416 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova)
420 case FDISTR: /* inhabited system issues distress call */
422 /* try a whole bunch of times to find something suitable */
425 /* need a quadrant which is not the current one,
426 which has some stars which are inhabited and
427 not already under attack, which is not
428 supernova'ed, and which has some Klingons in it */
429 iran(GALSIZE, &w.x, &w.y);
430 q = &game.state.galaxy[w.x][w.y];
432 (same(game.quadrant, w) || q->planet == NOPLANET ||
433 q->supernova || q->status!=secure || q->klingons<=0));
435 /* can't seem to find one; ignore this call */
437 prout("=== Couldn't find location for distress event.");
441 /* got one!! Schedule its enslavement */
442 ev = schedule(FENSLV, expran(game.intime));
444 q->status = distressed;
446 /* tell the captain about it if we can */
447 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
449 prout("Uhura- Captain, starsystem %s in quadrant %s",
450 systemname(q->planet), cramlc(quadrant, w));
451 prout("is under attack.");
456 case FENSLV: /* starsystem is enslaved */
457 ev = unschedule(FENSLV);
458 /* see if current distress call still active */
459 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
460 if (q->klingons <= 0) {
464 q->status = enslaved;
466 /* play stork and schedule the first baby */
467 ev2 = schedule(FREPRO, expran(2.0 * game.intime));
468 ev2->quadrant = ev->quadrant;
470 /* report the disaster if we can */
471 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
473 prout("Uhura- We've lost contact with starsystem %s",
474 systemname(q->planet));
475 prout("in quadrant %s.\n", cramlc(quadrant, ev->quadrant));
478 case FREPRO: /* Klingon reproduces */
480 * If we ever switch to a real event queue, we'll need to
481 * explicitly retrieve and restore the x and y.
483 ev = schedule(FREPRO, expran(1.0 * game.intime));
484 /* see if current distress call still active */
485 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
486 if (q->klingons <= 0) {
490 /* reproduce one Klingon */
492 if (game.state.remkl >=MAXKLGAME)
493 break; /* full right now */
494 /* this quadrant not ok, pick an adjacent one */
495 for (i = w.x - 1; i <= w.x + 1; i++)
497 for (j = w.y - 1; j <= w.y + 1; j++)
499 if (!VALID_QUADRANT(i, j))
501 q = &game.state.galaxy[w.x][w.y];
502 /* check for this quad ok (not full & no snova) */
503 if (q->klingons >= MAXKLQUAD || !q->supernova)
508 break; /* search for eligible quadrant failed */
513 /* deliver the child */
516 if (same(game.quadrant, w))
517 newkling(++game.klhere, &hold);
519 /* recompute time left */
520 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
530 double temp, delay, origTime;
535 if (key != IHEOL) break;
536 proutn(_("How long? "));
543 origTime = delay = aaitem;
544 if (delay <= 0.0) return;
545 if (delay >= game.state.remtime || game.nenhere != 0) {
546 proutn(_("Are you sure? "));
547 if (ja() == 0) return;
550 /* Alternate resting periods (events) with attacks */
554 if (delay <= 0) game.resting = false;
556 prout(_("%d stardates left."), (int)game.state.remtime);
559 temp = game.optime = delay;
562 double rtime = 1.0 + Rand();
563 if (rtime < temp) temp = rtime;
566 if (game.optime < delay) attack(0);
567 if (game.alldone) return;
570 if (game.alldone) return;
572 /* Repair Deathray if long rest at starbase */
573 if (origTime-delay >= 9.99 && game.condit == IHDOCKED)
574 game.damage[DDRAY] = 0.0;
576 // leave if quadrant supernovas
577 (!game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova);
579 game.resting = false;
583 void nova(int ix, int iy)
585 static double course[] =
586 {0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};
587 int bot, top, top2, hits[QUADSIZE+1][3], kount, icx, icy, mm, nn, j;
588 int iquad, iquad1, i, ll;
589 coord newc, nov, scratch;
591 nov.x = ix; nov.y = iy;
593 /* Wow! We've supernova'ed */
598 /* handle initial nova */
599 game.quad[ix][iy] = IHDOT;
600 crmena(1, IHSTAR, 2, nov);
602 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars--;
605 /* Set up stack to recursively trigger adjacent stars */
606 bot = top = top2 = 1;
612 for (mm = bot; mm <= top; mm++)
613 for (nn = 1; nn <= 3; nn++) /* nn,j represents coordinates around current */
614 for (j = 1; j <= 3; j++) {
615 if (j==2 && nn== 2) continue;
616 scratch.x = hits[mm][1]+nn-2;
617 scratch.y = hits[mm][2]+j-2;
618 if (!VALID_SECTOR(scratch.y, scratch.x)) continue;
619 iquad = game.quad[scratch.x][scratch.y];
621 // case IHDOT: /* Empty space ends reaction
628 case IHSTAR: /* Affect another star */
630 /* This star supernovas */
631 snova(scratch.x,scratch.y);
635 hits[top2][1]=scratch.x;
636 hits[top2][2]=scratch.y;
637 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1;
639 crmena(1, IHSTAR, 2, scratch);
641 game.quad[scratch.x][scratch.y] = IHDOT;
643 case IHP: /* Destroy planet */
644 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
645 game.state.nplankl++;
646 crmena(1, IHP, 2, scratch);
647 prout(_(" destroyed."));
648 DESTROY(&game.state.plnets[game.iplnet]);
649 game.iplnet = game.plnet.x = game.plnet.y = 0;
650 if (game.landed == 1) {
654 game.quad[scratch.x][scratch.y] = IHDOT;
656 case IHB: /* Destroy base */
657 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = false;
659 if (game.state.baseq[i].x==game.quadrant.x && game.state.baseq[i].y==game.quadrant.y)
661 game.state.baseq[i] = game.state.baseq[game.state.rembase];
662 game.state.rembase--;
663 game.base.x = game.base.y = 0;
666 crmena(1, IHB, 2, scratch);
667 prout(_(" destroyed."));
668 game.quad[scratch.x][scratch.y] = IHDOT;
670 case IHE: /* Buffet ship */
672 prout(_("***Starship buffeted by nova."));
674 if (game.shield >= 2000.0) game.shield -= 2000.0;
676 double diff = 2000.0 - game.shield;
680 prout(_("***Shields knocked out."));
681 game.damage[DSHIELD] += 0.005*game.damfac*Rand()*diff;
684 else game.energy -= 2000.0;
685 if (game.energy <= 0) {
689 /* add in course nova contributes to kicking starship*/
690 icx += game.sector.x-hits[mm][1];
691 icy += game.sector.y-hits[mm][2];
694 case IHK: /* kill klingon */
695 deadkl(scratch,iquad, scratch.x, scratch.y);
697 case IHC: /* Damage/destroy big enemies */
700 for_local_enemies(ll)
701 if (game.ks[ll].x==scratch.x && game.ks[ll].y==scratch.y) break;
702 game.kpower[ll] -= 800.0; /* If firepower is lost, die */
703 if (game.kpower[ll] <= 0.0) {
704 deadkl(scratch, iquad, scratch.x, scratch.y);
707 newc.x = scratch.x + scratch.x - hits[mm][1];
708 newc.y = scratch.y + scratch.y - hits[mm][2];
709 crmena(1, iquad, 2, scratch);
710 proutn(_(" damaged"));
711 if (!VALID_SECTOR(newc.x, newc.y)) {
712 /* can't leave quadrant */
716 iquad1 = game.quad[newc.x][newc.y];
717 if (iquad1 == IHBLANK) {
718 proutn(_(", blasted into "));
719 crmena(0, IHBLANK, 2, newc);
721 deadkl(scratch, iquad, newc.x, newc.y);
724 if (iquad1 != IHDOT) {
725 /* can't move into something else */
729 proutn(_(", buffeted to "));
730 proutn(cramlc(sector, newc));
731 game.quad[scratch.x][scratch.y] = IHDOT;
732 game.quad[newc.x][newc.y] = iquad;
733 game.ks[ll].x = newc.x;
734 game.ks[ll].y = newc.y;
735 game.kavgd[ll] = sqrt(square(game.sector.x-newc.x)+square(game.sector.y-newc.y));
736 game.kdist[ll] = game.kavgd[ll];
749 /* Starship affected by nova -- kick it away. */
750 game.dist = kount*0.1;
751 if (icx) icx = (icx < 0 ? -1 : 1);
752 if (icy) icy = (icy < 0 ? -1 : 1);
753 game.direc = course[3*(icx+1)+icy+2];
754 if (game.direc == 0.0) game.dist = 0.0;
755 if (game.dist == 0.0) return;
756 game.optime = 10.0*game.dist/16.0;
758 prout(_("Force of nova displaces starship."));
759 game.iattak=2; /* Eliminates recursion problem */
761 game.optime = 10.0*game.dist/16.0;
766 void snova(int insx, int insy)
768 int comdead, nsx, nsy, num=0, kldead, iscdead;
779 /* NOVAMAX being used */
783 /* Scheduled supernova -- select star */
784 /* logic changed here so that we won't favor quadrants in top
786 for_quadrants(nq.x) {
787 for_quadrants(nq.y) {
788 stars += game.state.galaxy[nq.x][nq.y].stars;
791 if (stars == 0) return; /* nothing to supernova exists */
792 num = Rand()*stars + 1;
793 for_quadrants(nq.x) {
794 for_quadrants(nq.y) {
795 num -= game.state.galaxy[nq.x][nq.y].stars;
801 proutn("=== Super nova here?");
803 nq.x = game.quadrant.x;
804 nq.y = game.quadrant.y;
809 if (nq.x != game.quadrant.y || nq.y != game.quadrant.y || game.justin != 0) {
810 /* it isn't here, or we just entered (treat as inroute) */
811 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) {
813 prout(_("Message from Starfleet Command Stardate %.2f"), game.state.date);
814 prout(_(" Supernova in %s; caution advised."),
815 cramlc(quadrant, nq));
819 /* we are in the quadrant! */
821 num = Rand()* game.state.galaxy[nq.x][nq.y].stars + 1;
824 if (game.quad[nsx][nsy]==IHSTAR) {
840 prouts(_("***RED ALERT! RED ALERT!"));
842 nd.x = nsx; nd.y = nsy;
843 prout(_("***Incipient supernova detected at "), cramlc(sector, nd));
845 if (square(nsx-game.sector.x) + square(nsy-game.sector.y) <= 2.1) {
846 proutn(_("Emergency override attempts t"));
847 prouts("***************");
853 /* destroy any Klingons in supernovaed quadrant */
854 kldead = game.state.galaxy[nq.x][nq.y].klingons;
855 game.state.galaxy[nq.x][nq.y].klingons = 0;
856 comdead = iscdead = 0;
857 if (same(nq, game.state.kscmdr)) {
858 /* did in the Supercommander! */
859 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = game.iscate = 0;
864 if (game.state.remcom) {
865 int maxloop = game.state.remcom, l;
866 for (l = 1; l <= maxloop; l++) {
867 if (same(game.state.kcmdr[l], nq)) {
868 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom];
869 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 (l = 0; l < game.inplan; l++)
887 if (same(game.state.plnets[l].w, nq)) {
888 DESTROY(&game.state.plnets[l]);
891 /* Destroy any base in supernovaed quadrant */
892 if (game.state.rembase) {
893 int maxloop = game.state.rembase, l;
894 for (l = 1; l <= maxloop; l++)
895 if (same(game.state.baseq[l], nq)) {
896 game.state.baseq[l] = 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) || game.damage[DRADIO] == 0 || 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 && (nq.x != game.quadrant.x || nq.y != game.quadrant.y)) {
914 if (insx == 0) 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);