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 istract=0, evcode, i=0, j, k, l;
62 double fintim = game.state.date + game.optime, datemin, xtime, repair, yank=0;
63 bool radio_was_broken, ictbeam = false, ipage = false;
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, evcode==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", evcode);
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 EVCODE to occur */
145 game.optime -= xtime;
147 case FSNOVA: /* Supernova */
148 if (!ipage) 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 */
171 if (evcode==FTBEAM) {
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) 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) 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! */
300 game.battle = game.state.kscmdr;
302 case FCDBAS: /* Commander succeeds in destroying base */
303 if (evcode==FCDBAS) {
305 /* find the lucky pair */
307 if (same(game.state.kcmdr[i], game.battle))
309 if (i > game.state.remcom || game.state.rembase == 0 ||
310 !game.state.galaxy[game.battle.x][game.battle.y].starbase) {
311 /* No action to take after all */
312 game.battle.x = game.battle.y = 0;
316 /* Code merges here for any commander destroying base */
317 /* Not perfect, but will have to do */
318 /* Handle case where base is in same quadrant as starship */
319 if (same(game.battle, game.quadrant)) {
320 game.state.chart[game.battle.x][game.battle.y].starbase = false;
321 game.quad[game.base.x][game.base.y] = IHDOT;
322 game.base.x=game.base.y=0;
325 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""));
327 else if (game.state.rembase != 1 &&
328 (game.damage[DRADIO] <= 0.0 || game.condit == IHDOCKED)) {
329 /* Get word via subspace radio */
330 if (!ipage) pause_game(1);
333 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"));
334 proutn(_(" the starbase in "));
335 proutn(cramlc(quadrant, game.battle));
336 prout(_(" has been destroyed by"));
338 prout(_("the Klingon Super-Commander"));
339 else prout(_("a Klingon Commander"));
340 game.state.chart[game.battle.x][game.battle.y].starbase = false;
342 /* Remove Starbase from galaxy */
343 game.state.galaxy[game.battle.x][game.battle.y].starbase = false;
345 if (same(game.state.baseq[i], game.battle))
346 game.state.baseq[i] = game.state.baseq[game.state.rembase];
347 game.state.rembase--;
348 if (game.isatb == 2) {
349 /* reinstate a commander's base attack */
354 game.battle.x = game.battle.y = 0;
357 case FSCMOVE: /* Supercommander moves */
358 schedule(FSCMOVE, 0.2777);
359 if (game.ientesc+istract==0 &&
361 (game.iscate != 1 || !game.justin)) scom(&ipage);
363 case FDSPROB: /* Move deep space probe */
364 schedule(FDSPROB, 0.01);
365 game.probex += game.probeinx;
366 game.probey += game.probeiny;
367 i = (int)(game.probex/QUADSIZE +0.05);
368 j = (int)(game.probey/QUADSIZE + 0.05);
369 if (game.probec.x != i || game.probec.y != j) {
372 if (!VALID_QUADRANT(i, j) ||
373 game.state.galaxy[game.probec.x][game.probec.y].supernova) {
374 // Left galaxy or ran into supernova
375 if (game.damage[DRADIO]==0.0 || game.condit == IHDOCKED) {
376 if (ipage==0) pause_game(1);
379 proutn(_("Lt. Uhura- \"The deep space probe "));
380 if (!VALID_QUADRANT(j, i))
381 proutn(_("has left the galaxy"));
383 proutn(_("is no longer transmitting"));
389 if (game.damage[DRADIO]==0.0 || game.condit == IHDOCKED) {
390 if (ipage==0) pause_game(1);
393 proutn(_("Lt. Uhura- \"The deep space probe is now in "));
394 proutn(cramlc(quadrant, game.probec));
398 pdest = &game.state.galaxy[game.probec.x][game.probec.y];
399 /* Update star chart if Radio is working or have access to
401 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) {
402 struct page *chp = &game.state.chart[game.probec.x][game.probec.y];
404 chp->klingons = pdest->klingons;
405 chp->starbase = pdest->starbase;
406 chp->stars = pdest->stars;
407 pdest->charted = true;
409 game.proben--; // One less to travel
410 if (game.proben == 0 && game.isarmed && pdest->stars) {
411 /* lets blow the sucker! */
414 if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova)
418 case FDISTR: /* inhabited system issues distress call */
420 /* try a whole bunch of times to find something suitable */
423 /* need a quadrant which is not the current one,
424 which has some stars which are inhabited and
425 not already under attack, which is not
426 supernova'ed, and which has some Klingons in it */
427 iran(GALSIZE, &w.x, &w.y);
428 q = &game.state.galaxy[w.x][w.y];
430 (same(game.quadrant, w) || q->planet == NOPLANET ||
431 q->supernova || q->status!=secure || q->klingons<=0));
433 /* can't seem to find one; ignore this call */
435 prout("=== Couldn't find location for distress event.");
439 /* got one!! Schedule its enslavement */
440 ev = schedule(FENSLV, expran(game.intime));
442 q->status = distressed;
444 /* tell the captain about it if we can */
445 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
447 prout("Uhura- Captain, starsystem %s in quadrant %s",
448 systemname(q->planet), cramlc(quadrant, w));
449 prout("is under attack.");
454 case FENSLV: /* starsystem is enslaved */
455 ev = unschedule(FENSLV);
456 /* see if current distress call still active */
457 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
458 if (q->klingons <= 0) {
462 q->status = enslaved;
464 /* play stork and schedule the first baby */
465 ev2 = schedule(FREPRO, expran(2.0 * game.intime));
466 ev2->quadrant = ev->quadrant;
468 /* report the disaster if we can */
469 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED)
471 prout("Uhura- We've lost contact with starsystem %s",
472 systemname(q->planet));
473 prout("in quadrant %s.\n", cramlc(quadrant, ev->quadrant));
476 case FREPRO: /* Klingon reproduces */
478 * If we ever switch to a real event queue, we'll need to
479 * explicitly retrieve and restore the x and y.
481 ev = schedule(FREPRO, expran(1.0 * game.intime));
482 /* see if current distress call still active */
483 q = &game.state.galaxy[ev->quadrant.x][ev->quadrant.y];
484 if (q->klingons <= 0) {
488 /* reproduce one Klingon */
490 if (game.state.remkl >=MAXKLGAME)
491 break; /* full right now */
492 /* this quadrant not ok, pick an adjacent one */
493 for (i = w.x - 1; i <= w.x + 1; i++)
495 for (j = w.y - 1; j <= w.y + 1; j++)
497 if (!VALID_QUADRANT(i, j))
499 q = &game.state.galaxy[w.x][w.y];
500 /* check for this quad ok (not full & no snova) */
501 if (q->klingons >= MAXKLQUAD || !q->supernova)
506 break; /* search for eligible quadrant failed */
511 /* deliver the child */
514 if (same(game.quadrant, w))
515 newkling(++game.klhere, &hold);
517 /* recompute time left */
518 game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
528 double temp, delay, origTime;
533 if (key != IHEOL) break;
534 proutn(_("How long? "));
541 origTime = delay = aaitem;
542 if (delay <= 0.0) return;
543 if (delay >= game.state.remtime || game.nenhere != 0) {
544 proutn(_("Are you sure? "));
545 if (ja() == 0) return;
548 /* Alternate resting periods (events) with attacks */
552 if (delay <= 0) game.resting = false;
554 prout(_("%d stardates left."), (int)game.state.remtime);
557 temp = game.optime = delay;
560 double rtime = 1.0 + Rand();
561 if (rtime < temp) temp = rtime;
564 if (game.optime < delay) attack(0);
565 if (game.alldone) return;
568 if (game.alldone) return;
570 /* Repair Deathray if long rest at starbase */
571 if (origTime-delay >= 9.99 && game.condit == IHDOCKED)
572 game.damage[DDRAY] = 0.0;
574 // leave if quadrant supernovas
575 (!game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova);
577 game.resting = false;
581 void nova(int ix, int iy)
583 static double course[] =
584 {0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};
585 int bot, top, top2, hits[QUADSIZE+1][3], kount, icx, icy, mm, nn, j;
586 int iquad, iquad1, i, ll;
587 coord newc, nov, scratch;
589 nov.x = ix; nov.y = iy;
591 /* Wow! We've supernova'ed */
596 /* handle initial nova */
597 game.quad[ix][iy] = IHDOT;
598 crmena(1, IHSTAR, 2, nov);
600 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars--;
603 /* Set up stack to recursively trigger adjacent stars */
604 bot = top = top2 = 1;
610 for (mm = bot; mm <= top; mm++)
611 for (nn = 1; nn <= 3; nn++) /* nn,j represents coordinates around current */
612 for (j = 1; j <= 3; j++) {
613 if (j==2 && nn== 2) continue;
614 scratch.x = hits[mm][1]+nn-2;
615 scratch.y = hits[mm][2]+j-2;
616 if (!VALID_SECTOR(scratch.y, scratch.x)) continue;
617 iquad = game.quad[scratch.x][scratch.y];
619 // case IHDOT: /* Empty space ends reaction
626 case IHSTAR: /* Affect another star */
628 /* This star supernovas */
629 snova(scratch.x,scratch.y);
633 hits[top2][1]=scratch.x;
634 hits[top2][2]=scratch.y;
635 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1;
637 crmena(1, IHSTAR, 2, scratch);
639 game.quad[scratch.x][scratch.y] = IHDOT;
641 case IHP: /* Destroy planet */
642 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET;
643 game.state.nplankl++;
644 crmena(1, IHP, 2, scratch);
645 prout(_(" destroyed."));
646 DESTROY(&game.state.plnets[game.iplnet]);
647 game.iplnet = game.plnet.x = game.plnet.y = 0;
648 if (game.landed == 1) {
652 game.quad[scratch.x][scratch.y] = IHDOT;
654 case IHB: /* Destroy base */
655 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = false;
657 if (game.state.baseq[i].x==game.quadrant.x && game.state.baseq[i].y==game.quadrant.y)
659 game.state.baseq[i] = game.state.baseq[game.state.rembase];
660 game.state.rembase--;
661 game.base.x = game.base.y = 0;
664 crmena(1, IHB, 2, scratch);
665 prout(_(" destroyed."));
666 game.quad[scratch.x][scratch.y] = IHDOT;
668 case IHE: /* Buffet ship */
670 prout(_("***Starship buffeted by nova."));
672 if (game.shield >= 2000.0) game.shield -= 2000.0;
674 double diff = 2000.0 - game.shield;
678 prout(_("***Shields knocked out."));
679 game.damage[DSHIELD] += 0.005*game.damfac*Rand()*diff;
682 else game.energy -= 2000.0;
683 if (game.energy <= 0) {
687 /* add in course nova contributes to kicking starship*/
688 icx += game.sector.x-hits[mm][1];
689 icy += game.sector.y-hits[mm][2];
692 case IHK: /* kill klingon */
693 deadkl(scratch,iquad, scratch.x, scratch.y);
695 case IHC: /* Damage/destroy big enemies */
698 for_local_enemies(ll)
699 if (game.ks[ll].x==scratch.x && game.ks[ll].y==scratch.y) break;
700 game.kpower[ll] -= 800.0; /* If firepower is lost, die */
701 if (game.kpower[ll] <= 0.0) {
702 deadkl(scratch, iquad, scratch.x, scratch.y);
705 newc.x = scratch.x + scratch.x - hits[mm][1];
706 newc.y = scratch.y + scratch.y - hits[mm][2];
707 crmena(1, iquad, 2, scratch);
708 proutn(_(" damaged"));
709 if (!VALID_SECTOR(newc.x, newc.y)) {
710 /* can't leave quadrant */
714 iquad1 = game.quad[newc.x][newc.y];
715 if (iquad1 == IHBLANK) {
716 proutn(_(", blasted into "));
717 crmena(0, IHBLANK, 2, newc);
719 deadkl(scratch, iquad, newc.x, newc.y);
722 if (iquad1 != IHDOT) {
723 /* can't move into something else */
727 proutn(_(", buffeted to "));
728 proutn(cramlc(sector, newc));
729 game.quad[scratch.x][scratch.y] = IHDOT;
730 game.quad[newc.x][newc.y] = iquad;
731 game.ks[ll].x = newc.x;
732 game.ks[ll].y = newc.y;
733 game.kavgd[ll] = sqrt(square(game.sector.x-newc.x)+square(game.sector.y-newc.y));
734 game.kdist[ll] = game.kavgd[ll];
747 /* Starship affected by nova -- kick it away. */
748 game.dist = kount*0.1;
749 if (icx) icx = (icx < 0 ? -1 : 1);
750 if (icy) icy = (icy < 0 ? -1 : 1);
751 game.direc = course[3*(icx+1)+icy+2];
752 if (game.direc == 0.0) game.dist = 0.0;
753 if (game.dist == 0.0) return;
754 game.optime = 10.0*game.dist/16.0;
756 prout(_("Force of nova displaces starship."));
757 game.iattak=2; /* Eliminates recursion problem */
759 game.optime = 10.0*game.dist/16.0;
764 void snova(int insx, int insy)
766 int comdead, nsx, nsy, num=0, kldead, iscdead;
777 /* NOVAMAX being used */
781 /* Scheduled supernova -- select star */
782 /* logic changed here so that we won't favor quadrants in top
784 for_quadrants(nq.x) {
785 for_quadrants(nq.y) {
786 stars += game.state.galaxy[nq.x][nq.y].stars;
789 if (stars == 0) return; /* nothing to supernova exists */
790 num = Rand()*stars + 1;
791 for_quadrants(nq.x) {
792 for_quadrants(nq.y) {
793 num -= game.state.galaxy[nq.x][nq.y].stars;
799 proutn("=== Super nova here?");
801 nq.x = game.quadrant.x;
802 nq.y = game.quadrant.y;
807 if (nq.x != game.quadrant.y || nq.y != game.quadrant.y || game.justin != 0) {
808 /* it isn't here, or we just entered (treat as inroute) */
809 if (game.damage[DRADIO] == 0.0 || game.condit == IHDOCKED) {
811 prout(_("Message from Starfleet Command Stardate %.2f"), game.state.date);
812 prout(_(" Supernova in %s; caution advised."),
813 cramlc(quadrant, nq));
817 /* we are in the quadrant! */
819 num = Rand()* game.state.galaxy[nq.x][nq.y].stars + 1;
822 if (game.quad[nsx][nsy]==IHSTAR) {
838 prouts(_("***RED ALERT! RED ALERT!"));
840 nd.x = nsx; nd.y = nsy;
841 prout(_("***Incipient supernova detected at "), cramlc(sector, nd));
843 if (square(nsx-game.sector.x) + square(nsy-game.sector.y) <= 2.1) {
844 proutn(_("Emergency override attempts t"));
845 prouts("***************");
851 /* destroy any Klingons in supernovaed quadrant */
852 kldead = game.state.galaxy[nq.x][nq.y].klingons;
853 game.state.galaxy[nq.x][nq.y].klingons = 0;
854 comdead = iscdead = 0;
855 if (same(nq, game.state.kscmdr)) {
856 /* did in the Supercommander! */
857 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = game.iscate = 0;
862 if (game.state.remcom) {
863 int maxloop = game.state.remcom, l;
864 for (l = 1; l <= maxloop; l++) {
865 if (same(game.state.kcmdr[l], nq)) {
866 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom];
867 game.state.kcmdr[game.state.remcom].x = game.state.kcmdr[game.state.remcom].y = 0;
871 if (game.state.remcom==0) unschedule(FTBEAM);
876 game.state.remkl -= kldead;
877 /* destroy Romulans and planets in supernovaed quadrant */
878 nrmdead = game.state.galaxy[nq.x][nq.y].romulans;
879 game.state.galaxy[nq.x][nq.y].romulans = 0;
880 game.state.nromrem -= nrmdead;
881 npdead = num - nrmdead*10;
884 for (l = 0; l < game.inplan; l++)
885 if (same(game.state.plnets[l].w, nq)) {
886 DESTROY(&game.state.plnets[l]);
889 /* Destroy any base in supernovaed quadrant */
890 if (game.state.rembase) {
891 int maxloop = game.state.rembase, l;
892 for (l = 1; l <= maxloop; l++)
893 if (same(game.state.baseq[l], nq)) {
894 game.state.baseq[l] = game.state.baseq[game.state.rembase];
895 game.state.baseq[game.state.rembase].x = game.state.baseq[game.state.rembase].y = 0;
896 game.state.rembase--;
900 /* If starship caused supernova, tally up destruction */
902 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars;
903 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase;
904 game.state.nplankl += npdead;
906 /* mark supernova in galaxy and in star chart */
907 if (same(game.quadrant, nq) || game.damage[DRADIO] == 0 || game.condit == IHDOCKED)
908 game.state.galaxy[nq.x][nq.y].supernova = true;
909 /* If supernova destroys last Klingons give special message */
910 if (KLINGREM==0 && (nq.x != game.quadrant.x || nq.y != game.quadrant.y)) {
912 if (insx == 0) prout(_("Lucky you!"));
913 proutn(_("A supernova in %s has just destroyed the last Klingons."),
914 cramlc(quadrant, nq));
918 /* if some Klingons remain, continue or die in supernova */
919 if (game.alldone) finish(FSNOVAED);