2935404971853361eb375ce2f3c12a16b31673d2
[super-star-trek.git] / events.c
1 #include "sst.h"
2 #include <math.h>
3
4 void events(void) 
5 {
6     int ictbeam=0, ipage=0, istract=0, line, i=0, j, k, l, ixhold=0, iyhold=0;
7     double fintim = game.state.date + Time, datemin, xtime, repair, yank=0;
8     int radio_was_broken;
9
10 #ifdef DEBUG
11     if (idebug) prout("EVENTS");
12 #endif
13
14     radio_was_broken = (game.damage[DRADIO] != 0.0);
15
16     for (;;) {
17         /* Select earliest extraneous event, line==0 if no events */
18         line = FSPY;
19         if (alldone) return;
20         datemin = fintim;
21         for (l = 1; l < NEVENTS; l++)
22             if (game.future[l] < datemin) {
23                 line = l;
24                 datemin = game.future[l];
25             }
26         xtime = datemin-game.state.date;
27         game.state.date = datemin;
28         /* Decrement Federation resources and recompute remaining time */
29         game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime;
30         game.state.remtime = game.state.remres/(game.state.remkl+4*game.state.remcom);
31         if (game.state.remtime <=0) {
32             finish(FDEPLETE);
33             return;
34         }
35         /* Is life support adequate? */
36         if (game.damage[DLIFSUP] && condit != IHDOCKED) {
37             if (lsupres < xtime && game.damage[DLIFSUP] > lsupres) {
38                 finish(FLIFESUP);
39                 return;
40             }
41             lsupres -= xtime;
42             if (game.damage[DLIFSUP] <= xtime) lsupres = inlsr;
43         }
44         /* Fix devices */
45         repair = xtime;
46         if (condit == IHDOCKED) repair /= docfac;
47         /* Don't fix Deathray here */
48         for (l=0; l<NDEVICES; l++)
49             if (game.damage[l] > 0.0 && l != DDRAY)
50                 game.damage[l] -= (game.damage[l]-repair > 0.0 ? repair : game.damage[l]);
51         /* If radio repaired, update star chart and attack reports */
52         if (radio_was_broken && game.damage[DRADIO] == 0.0) {
53             stdamtim = FOREVER;
54             prout("Lt. Uhura- \"Captain, the sub-space radio is working and");
55             prout("   surveillance reports are coming in.");
56             skip(1);
57             if (iseenit==0) {
58                 attakreport(0);
59                 iseenit = 1;
60             }
61             rechart();
62             prout("   The star chart is now up to date.\"");
63             skip(1);
64         }
65         /* Cause extraneous event LINE to occur */
66         Time -= xtime;
67         switch (line) {
68         case FSNOVA: /* Supernova */
69             if (ipage==0) pause_game(1);
70             ipage=1;
71             snova(0,0);
72             game.future[FSNOVA] = game.state.date + expran(0.5*intime);
73             if (game.state.galaxy[quadx][quady].supernova) return;
74             break;
75         case FSPY: /* Check with spy to see if S.C. should tractor beam */
76             if (game.state.nscrem == 0 ||
77                 ictbeam+istract > 0 ||
78                 condit==IHDOCKED || isatb==1 || iscate==1) return;
79             if (ientesc ||
80                 (energy < 2000 && torps < 4 && shield < 1250) ||
81                 (game.damage[DPHASER]>0 && (game.damage[DPHOTON]>0 || torps < 4)) ||
82                 (game.damage[DSHIELD] > 0 &&
83                  (energy < 2500 || game.damage[DPHASER] > 0) &&
84                  (torps < 5 || game.damage[DPHOTON] > 0))) {
85                 /* Tractor-beam her! */
86                 istract=1;
87                 yank = square(game.state.isx-quadx) + square(game.state.isy-quady);
88                 /********* fall through to FTBEAM code ***********/
89             }
90             else return;
91         case FTBEAM: /* Tractor beam */
92             if (line==FTBEAM) {
93                 if (game.state.remcom == 0) {
94                     game.future[FTBEAM] = FOREVER;
95                     break;
96                 }
97                 i = Rand()*game.state.remcom+1.0;
98                 yank = square(game.state.cx[i]-quadx) + square(game.state.cy[i]-quady);
99                 if (istract || condit == IHDOCKED || yank == 0) {
100                     /* Drats! Have to reschedule */
101                     game.future[FTBEAM] = game.state.date + Time +
102                         expran(1.5*intime/game.state.remcom);
103                     break;
104                 }
105             }
106             /* tractor beaming cases merge here */
107             yank = sqrt(yank);
108             if (ipage==0) pause_game(1);
109             ipage=1;
110             Time = (10.0/(7.5*7.5))*yank; /* 7.5 is yank rate (warp 7.5) */
111             ictbeam = 1;
112             skip(1);
113             proutn("***");
114             crmshp();
115             prout(" caught in long range tractor beam--");
116             /* If Kirk & Co. screwing around on planet, handle */
117             atover(1); /* atover(1) is Grab */
118             if (alldone) return;
119             if (icraft == 1) { /* Caught in Galileo? */
120                 finish(FSTRACTOR);
121                 return;
122             }
123             /* Check to see if shuttle is aboard */
124             if (iscraft==0) {
125                 skip(1);
126                 if (Rand() > 0.5) {
127                     prout("Galileo, left on the planet surface, is captured");
128                     prout("by aliens and made into a flying McDonald's.");
129                     game.damage[DSHUTTL] = -10;
130                     iscraft = -1;
131                 }
132                 else {
133                     prout("Galileo, left on the planet surface, is well hidden.");
134                 }
135             }
136             if (line==0) {
137                 quadx = game.state.isx;
138                 quady = game.state.isy;
139             }
140             else {
141                 quadx = game.state.cx[i];
142                 quady = game.state.cy[i];
143             }
144             iran(QUADSIZE, &sectx, &secty);
145             crmshp();
146             proutn(" is pulled to ");
147             proutn(cramlc(quadrant, quadx, quady));
148             proutn(", ");
149             prout(cramlc(sector, sectx, secty));
150             if (resting) {
151                 prout("(Remainder of rest/repair period cancelled.)");
152                 resting = 0;
153             }
154             if (shldup==0) {
155                 if (game.damage[DSHIELD]==0 && shield > 0) {
156                     doshield(2); /* Shldsup */
157                     shldchg=0;
158                 }
159                 else prout("(Shields not currently useable.)");
160             }
161             newqad(0);
162             /* Adjust finish time to time of tractor beaming */
163             fintim = game.state.date+Time;
164             attack(0);
165             if (game.state.remcom <= 0) game.future[FTBEAM] = FOREVER;
166             else game.future[FTBEAM] = game.state.date+Time+expran(1.5*intime/game.state.remcom);
167             break;
168         case FSNAP: /* Snapshot of the universe (for time warp) */
169             game.snapsht = game.state;
170             game.state.snap = 1;
171             game.future[FSNAP] = game.state.date + expran(0.5 * intime);
172             break;
173         case FBATTAK: /* Commander attacks starbase */
174             if (game.state.remcom==0 || game.state.rembase==0) {
175                 /* no can do */
176                 game.future[FBATTAK] = game.future[FCDBAS] = FOREVER;
177                 break;
178             }
179             i = 0;
180             for_starbases(j) {
181                 for_commanders(k)
182                     if (game.state.baseqx[j]==game.state.cx[k] && game.state.baseqy[j]==game.state.cy[k] &&
183                         (game.state.baseqx[j]!=quadx || game.state.baseqy[j]!=quady) &&
184                         (game.state.baseqx[j]!=game.state.isx || game.state.baseqy[j]!=game.state.isy)) {
185                         i = 1;
186                         break;
187                     }
188                 if (i == 1) break;
189             }
190             if (j>game.state.rembase) {
191                 /* no match found -- try later */
192                 game.future[FBATTAK] = game.state.date + expran(0.3*intime);
193                 game.future[FCDBAS] = FOREVER;
194                 break;
195             }
196             /* commander + starbase combination found -- launch attack */
197             batx = game.state.baseqx[j];
198             baty = game.state.baseqy[j];
199             game.future[FCDBAS] = game.state.date+1.0+3.0*Rand();
200             if (isatb) /* extra time if SC already attacking */
201                 game.future[FCDBAS] += game.future[FSCDBAS]-game.state.date;
202             game.future[FBATTAK] = game.future[FCDBAS] +expran(0.3*intime);
203             iseenit = 0;
204             if (game.damage[DRADIO] != 0.0 &&
205                 condit != IHDOCKED) break; /* No warning :-( */
206             iseenit = 1;
207             if (ipage==0) pause_game(1);
208             ipage = 1;
209             skip(1);
210             proutn("Lt. Uhura-  \"Captain, the starbase in ");
211             prout(cramlc(quadrant, batx, baty));
212             prout("   reports that it is under attack and that it can");
213             proutn("   hold out only until stardate %d",
214                    (int)game.future[FCDBAS]);
215             prout(".\"");
216             if (resting) {
217                 skip(1);
218                 proutn("Mr. Spock-  \"Captain, shall we cancel the rest period?\" ");
219                 if (ja()) {
220                     resting = 0;
221                     Time = 0.0;
222                     return;
223                 }
224             }
225             break;
226         case FSCDBAS: /* Supercommander destroys base */
227             game.future[FSCDBAS] = FOREVER;
228             isatb = 2;
229             if (!game.state.galaxy[game.state.isx][game.state.isy].starbase) 
230                 break; /* WAS RETURN! */
231             ixhold = batx;
232             iyhold = baty;
233             batx = game.state.isx;
234             baty = game.state.isy;
235         case FCDBAS: /* Commander succeeds in destroying base */
236             if (line==FCDBAS) {
237                 game.future[FCDBAS] = FOREVER;
238                 /* find the lucky pair */
239                 for_commanders(i)
240                     if (game.state.cx[i]==batx && game.state.cy[i]==baty) 
241                         break;
242                 if (i > game.state.remcom || game.state.rembase == 0 ||
243                     !game.state.galaxy[batx][baty].starbase) {
244                     /* No action to take after all */
245                     batx = baty = 0;
246                     break;
247                 }
248             }
249             /* Code merges here for any commander destroying base */
250             /* Not perfect, but will have to do */
251             /* Handle case where base is in same quadrant as starship */
252             if (batx==quadx && baty==quady) {
253                 game.state.chart[batx][baty].starbase = FALSE;
254                 game.quad[basex][basey]= IHDOT;
255                 basex=basey=0;
256                 newcnd();
257                 skip(1);
258                 prout("Spock-  \"Captain, I believe the starbase has been destroyegame.state.\"");
259             }
260             else if (game.state.rembase != 1 &&
261                      (game.damage[DRADIO] <= 0.0 || condit == IHDOCKED)) {
262                 /* Get word via subspace radio */
263                 if (ipage==0) pause_game(1);
264                 ipage = 1;
265                 skip(1);
266                 prout("Lt. Uhura-  \"Captain, Starfleet Command reports that");
267                 proutn("   the starbase in ");
268                 proutn(cramlc(quadrant, batx, baty));
269                 prout(" has been destroyed by");
270                 if (isatb==2) prout("the Klingon Super-Commander");
271                 else prout("a Klingon Commander");
272                 game.state.chart[batx][baty].starbase = FALSE;
273             }
274             /* Remove Starbase from galaxy */
275             game.state.galaxy[batx][baty].starbase = FALSE;
276             for_starbases(i)
277                 if (game.state.baseqx[i]==batx && game.state.baseqy[i]==baty) {
278                     game.state.baseqx[i]=game.state.baseqx[game.state.rembase];
279                     game.state.baseqy[i]=game.state.baseqy[game.state.rembase];
280                 }
281             game.state.rembase--;
282             if (isatb == 2) {
283                 /* reinstate a commander's base attack */
284                 batx = ixhold;
285                 baty = iyhold;
286                 isatb = 0;
287             }
288             else {
289                 batx = baty = 0;
290             }
291             break;
292         case FSCMOVE: /* Supercommander moves */
293             game.future[FSCMOVE] = game.state.date+0.2777;
294             if (ientesc+istract==0 &&
295                 isatb!=1 &&
296                 (iscate!=1 || justin==1)) scom(&ipage);
297             break;
298         case FDSPROB: /* Move deep space probe */
299             game.future[FDSPROB] = game.state.date + 0.01;
300             probex += probeinx;
301             probey += probeiny;
302             i = (int)(probex/QUADSIZE +0.05);
303             j = (int)(probey/QUADSIZE + 0.05);
304             if (probecx != i || probecy != j) {
305                 probecx = i;
306                 probecy = j;
307                 if (!VALID_QUADRANT(i, j) ||
308                     game.state.galaxy[probecx][probecy].supernova) {
309                     // Left galaxy or ran into supernova
310                     if (game.damage[DRADIO]==0.0 || condit == IHDOCKED) {
311                         if (ipage==0) pause_game(1);
312                         ipage = 1;
313                         skip(1);
314                         proutn("Lt. Uhura-  \"The deep space probe ");
315                         if (!VALID_QUADRANT(j, i))
316                             proutn("has left the galaxy");
317                         else
318                             proutn("is no longer transmitting");
319                         prout(".\"");
320                     }
321                     game.future[FDSPROB] = FOREVER;
322                     break;
323                 }
324                 if (game.damage[DRADIO]==0.0   || condit == IHDOCKED) {
325                     if (ipage==0) pause_game(1);
326                     ipage = 1;
327                     skip(1);
328                     proutn("Lt. Uhura-  \"The deep space probe is now in ");
329                     proutn(cramlc(quadrant, probecx, probecy));
330                     prout(".\"");
331                 }
332             }
333             /* Update star chart if Radio is working or have access to
334                radio. */
335             if (game.damage[DRADIO] == 0.0 || condit == IHDOCKED) {
336                 game.state.chart[probecx][probecy].klingons = game.state.galaxy[probecx][probecy].klingons;
337                 game.state.chart[probecx][probecy].starbase = game.state.galaxy[probecx][probecy].starbase;
338                 game.state.chart[probecx][probecy].stars = game.state.galaxy[probecx][probecy].stars;
339                 game.state.galaxy[probecx][probecy].charted = TRUE;
340             }
341             proben--; // One less to travel
342             if (proben == 0 && isarmed &&
343                 game.state.galaxy[probecx][probecy].stars) {
344                 /* lets blow the sucker! */
345                 snova(1,0);
346                 game.future[FDSPROB] = FOREVER;
347                 if (game.state.galaxy[quadx][quady].supernova) 
348                     return;
349             }
350             break;
351         }
352     }
353 }
354
355                                 
356 void wait(void) 
357 {
358     int key;
359     double temp, delay, origTime;
360
361     ididit = 0;
362     for (;;) {
363         key = scan();
364         if (key  != IHEOL) break;
365         proutn("How long? ");
366     }
367     chew();
368     if (key != IHREAL) {
369         huh();
370         return;
371     }
372     origTime = delay = aaitem;
373     if (delay <= 0.0) return;
374     if (delay >= game.state.remtime || nenhere != 0) {
375         proutn("Are you sure? ");
376         if (ja() == 0) return;
377     }
378
379     /* Alternate resting periods (events) with attacks */
380
381     resting = 1;
382     do {
383         if (delay <= 0) resting = 0;
384         if (resting == 0) {
385             prout("%d stardates left.", (int)game.state.remtime);
386             return;
387         }
388         temp = Time = delay;
389
390         if (nenhere) {
391             double rtime = 1.0 + Rand();
392             if (rtime < temp) temp = rtime;
393             Time = temp;
394         }
395         if (Time < delay) attack(0);
396         if (alldone) return;
397         events();
398         ididit = 1;
399         if (alldone) return;
400         delay -= temp;
401         /* Repair Deathray if long rest at starbase */
402         if (origTime-delay >= 9.99 && condit == IHDOCKED)
403             game.damage[DDRAY] = 0.0;
404     } while 
405         // leave if quadrant supernovas
406         (!game.state.galaxy[quadx][quady].supernova);
407
408     resting = 0;
409     Time = 0;
410 }
411
412 void nova(int ix, int iy) 
413 {
414     static double course[] =
415         {0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5};
416     int bot, top, top2, hits[QUADSIZE+1][3], kount, icx, icy, mm, nn, j;
417     int iquad, iquad1, i, ll, newcx, newcy, ii, jj;
418     if (Rand() < 0.05) {
419         /* Wow! We've supernova'ed */
420         snova(ix, iy);
421         return;
422     }
423
424     /* handle initial nova */
425     game.quad[ix][iy] = IHDOT;
426     crmena(1, IHSTAR, 2, ix, iy);
427     prout(" novas.");
428     game.state.galaxy[quadx][quady].stars--;
429     game.state.starkl++;
430         
431     /* Set up stack to recursively trigger adjacent stars */
432     bot = top = top2 = 1;
433     kount = 0;
434     icx = icy = 0;
435     hits[1][1] = ix;
436     hits[1][2] = iy;
437     while (1) {
438         for (mm = bot; mm <= top; mm++) 
439             for (nn = 1; nn <= 3; nn++)  /* nn,j represents coordinates around current */
440                 for (j = 1; j <= 3; j++) {
441                     if (j==2 && nn== 2) continue;
442                     ii = hits[mm][1]+nn-2;
443                     jj = hits[mm][2]+j-2;
444                     if (!VALID_SECTOR(jj, ii)) continue;
445                     iquad = game.quad[ii][jj];
446                     switch (iquad) {
447                     // case IHDOT:      /* Empty space ends reaction
448                     // case IHQUEST:
449                     // case IHBLANK:
450                     // case IHT:
451                     // case IHWEB:
452                     default:
453                         break;
454                     case IHSTAR: /* Affect another star */
455                         if (Rand() < 0.05) {
456                             /* This star supernovas */
457                             snova(ii,jj);
458                             return;
459                         }
460                         top2++;
461                         hits[top2][1]=ii;
462                         hits[top2][2]=jj;
463                         game.state.galaxy[quadx][quady].stars -= 1;
464                         game.state.starkl++;
465                         crmena(1, IHSTAR, 2, ii, jj);
466                         prout(" novas.");
467                         game.quad[ii][jj] = IHDOT;
468                         break;
469                     case IHP: /* Destroy planet */
470                         game.state.galaxy[quadx][quady].planets -= 1;
471                         game.state.nplankl++;
472                         crmena(1, IHP, 2, ii, jj);
473                         prout(" destroyed.");
474                         DESTROY(&game.state.plnets[iplnet]);
475                         iplnet = plnetx = plnety = 0;
476                         if (landed == 1) {
477                             finish(FPNOVA);
478                             return;
479                         }
480                         game.quad[ii][jj] = IHDOT;
481                         break;
482                     case IHB: /* Destroy base */
483                         game.state.galaxy[quadx][quady].starbase = FALSE;
484                         for_starbases(i)
485                             if (game.state.baseqx[i]==quadx && game.state.baseqy[i]==quady) 
486                                 break;
487                         game.state.baseqx[i] = game.state.baseqx[game.state.rembase];
488                         game.state.baseqy[i] = game.state.baseqy[game.state.rembase];
489                         game.state.rembase--;
490                         basex = basey = 0;
491                         game.state.basekl++;
492                         newcnd();
493                         crmena(1, IHB, 2, ii, jj);
494                         prout(" destroyed.");
495                         game.quad[ii][jj] = IHDOT;
496                         break;
497                     case IHE: /* Buffet ship */
498                     case IHF:
499                         prout("***Starship buffeted by nova.");
500                         if (shldup) {
501                             if (shield >= 2000.0) shield -= 2000.0;
502                             else {
503                                 double diff = 2000.0 - shield;
504                                 energy -= diff;
505                                 shield = 0.0;
506                                 shldup = 0;
507                                 prout("***Shields knocked out.");
508                                 game.damage[DSHIELD] += 0.005*damfac*Rand()*diff;
509                             }
510                         }
511                         else energy -= 2000.0;
512                         if (energy <= 0) {
513                             finish(FNOVA);
514                             return;
515                         }
516                         /* add in course nova contributes to kicking starship*/
517                         icx += sectx-hits[mm][1];
518                         icy += secty-hits[mm][2];
519                         kount++;
520                         break;
521                     case IHK: /* kill klingon */
522                         deadkl(ii,jj,iquad, ii, jj);
523                         break;
524                     case IHC: /* Damage/destroy big enemies */
525                     case IHS:
526                     case IHR:
527                         for_local_enemies(ll)
528                             if (game.kx[ll]==ii && game.ky[ll]==jj) break;
529                         game.kpower[ll] -= 800.0; /* If firepower is lost, die */
530                         if (game.kpower[ll] <= 0.0) {
531                             deadkl(ii, jj, iquad, ii, jj);
532                             break;
533                         }
534                         newcx = ii + ii - hits[mm][1];
535                         newcy = jj + jj - hits[mm][2];
536                         crmena(1, iquad, 2, ii, jj);
537                         proutn(" damaged");
538                         if (!VALID_SECTOR(newcx, newcy)) {
539                             /* can't leave quadrant */
540                             skip(1);
541                             break;
542                         }
543                         iquad1 = game.quad[newcx][newcy];
544                         if (iquad1 == IHBLANK) {
545                             proutn(", blasted into ");
546                             crmena(0, IHBLANK, 2, newcx, newcy);
547                             skip(1);
548                             deadkl(ii, jj, iquad, newcx, newcy);
549                             break;
550                         }
551                         if (iquad1 != IHDOT) {
552                             /* can't move into something else */
553                             skip(1);
554                             break;
555                         }
556                         proutn(", buffeted to ");
557                         proutn(cramlc(sector, newcx, newcy));
558                         game.quad[ii][jj] = IHDOT;
559                         game.quad[newcx][newcy] = iquad;
560                         game.kx[ll] = newcx;
561                         game.ky[ll] = newcy;
562                         game.kavgd[ll] = sqrt(square(sectx-newcx)+square(secty-newcy));
563                         game.kdist[ll] = game.kavgd[ll];
564                         skip(1);
565                         break;
566                     }
567                 }
568         if (top == top2) 
569             break;
570         bot = top + 1;
571         top = top2;
572     }
573     if (kount==0) 
574         return;
575
576     /* Starship affected by nova -- kick it away. */
577     dist = kount*0.1;
578     if (icx) icx = (icx < 0 ? -1 : 1);
579     if (icy) icy = (icy < 0 ? -1 : 1);
580     direc = course[3*(icx+1)+icy+2];
581     if (direc == 0.0) dist = 0.0;
582     if (dist == 0.0) return;
583     Time = 10.0*dist/16.0;
584     skip(1);
585     prout("Force of nova displaces starship.");
586     iattak=2;   /* Eliminates recursion problem */
587     imove();
588     Time = 10.0*dist/16.0;
589     return;
590 }
591         
592         
593 void snova(int insx, int insy) 
594 {
595     int comdead, nqx=0, nqy=0, nsx, nsy, num=0, kldead, iscdead;
596     int nrmdead, npdead;
597     int incipient=0;
598
599     nsx = insy;
600     nsy = insy;
601
602     if (insy== 0) {
603         if (insx == 1) {
604             /* NOVAMAX being used */
605             nqx = probecx;
606             nqy = probecy;
607         }
608         else {
609             int stars = 0;
610             /* Scheduled supernova -- select star */
611             /* logic changed here so that we won't favor quadrants in top
612                left of universe */
613             for_quadrants(nqx) {
614                 for_quadrants(nqy) {
615                     stars += game.state.galaxy[nqx][nqy].stars;
616                 }
617             }
618             if (stars == 0) return; /* nothing to supernova exists */
619             num = Rand()*stars + 1;
620             for_quadrants(nqx) {
621                 for_quadrants(nqy) {
622                     num -= game.state.galaxy[nqx][nqy].stars;
623                     if (num <= 0) break;
624                 }
625                 if (num <=0) break;
626             }
627 #ifdef DEBUG
628             if (idebug) {
629                 proutn("Super nova here?");
630                 if (ja()==1) {
631                     nqx = quadx;
632                     nqy = quady;
633                 }
634             }
635 #endif
636         }
637
638         if (nqx != quady || nqy != quady || justin != 0) {
639             /* it isn't here, or we just entered (treat as inroute) */
640             if (game.damage[DRADIO] == 0.0 || condit == IHDOCKED) {
641                 skip(1);
642                 prout("Message from Starfleet Command       Stardate %.2f", game.state.date);
643                 prout("     Supernova in %s; caution advised.",
644                       cramlc(quadrant, nqx, nqy));
645             }
646         }
647         else {
648             /* we are in the quadrant! */
649             incipient = 1;
650             num = Rand()* game.state.galaxy[nqx][nqy].stars + 1;
651             for_sectors(nsx) {
652                 for_sectors(nsy) {
653                     if (game.quad[nsx][nsy]==IHSTAR) {
654                         num--;
655                         if (num==0) break;
656                     }
657                 }
658                 if (num==0) break;
659             }
660         }
661     }
662     else {
663         incipient = 1;
664     }
665
666     if (incipient) {
667         skip(1);
668         prouts("***RED ALERT!  RED ALERT!");
669         skip(1);
670         prout("***Incipient supernova detected at ", cramlc(sector, nsx, nsy));
671         nqx = quadx;
672         nqy = quady;
673         if (square(nsx-sectx) + square(nsy-secty) <= 2.1) {
674             proutn("Emergency override attempts t");
675             prouts("***************");
676             skip(1);
677             stars();
678             alldone=1;
679         }
680     }
681     /* destroy any Klingons in supernovaed quadrant */
682     kldead = game.state.galaxy[nqx][nqy].klingons;
683     game.state.galaxy[nqx][nqy].klingons = 0;
684     comdead = iscdead = 0;
685     if (nqx==game.state.isx && nqy == game.state.isy) {
686         /* did in the Supercommander! */
687         game.state.nscrem = game.state.isx = game.state.isy = isatb = iscate = 0;
688         iscdead = 1;
689         game.future[FSCMOVE] = game.future[FSCDBAS] = FOREVER;
690     }
691     game.state.remkl -= kldead;
692     if (game.state.remcom) {
693         int maxloop = game.state.remcom, l;
694         for (l = 1; l <= maxloop; l++) {
695             if (game.state.cx[l] == nqx && game.state.cy[l] == nqy) {
696                 game.state.cx[l] = game.state.cx[game.state.remcom];
697                 game.state.cy[l] = game.state.cy[game.state.remcom];
698                 game.state.cx[game.state.remcom] = game.state.cy[game.state.remcom] = 0;
699                 game.state.remcom--;
700                 kldead--;
701                 comdead++;
702                 if (game.state.remcom==0) game.future[FTBEAM] = FOREVER;
703                 break;
704             }
705         }
706     }
707     /* destroy Romulans and planets in supernovaed quadrant */
708     nrmdead = game.state.galaxy[nqx][nqy].romulans;
709     game.state.galaxy[nqx][nqy].romulans = 0;
710     game.state.nromrem -= nrmdead;
711     npdead = num - nrmdead*10;
712     if (npdead) {
713         int l;
714         for (l = 0; l < inplan; l++)
715             if (game.state.plnets[l].x == nqx && game.state.plnets[l].y == nqy) {
716                 DESTROY(&game.state.plnets[l]);
717             }
718     }
719     /* Destroy any base in supernovaed quadrant */
720     if (game.state.rembase) {
721         int maxloop = game.state.rembase, l;
722         for (l = 1; l <= maxloop; l++)
723             if (game.state.baseqx[l]==nqx && game.state.baseqy[l]==nqy) {
724                 game.state.baseqx[l] = game.state.baseqx[game.state.rembase];
725                 game.state.baseqy[l] = game.state.baseqy[game.state.rembase];
726                 game.state.baseqx[game.state.rembase] = game.state.baseqy[game.state.rembase] = 0;
727                 game.state.rembase--;
728                 break;
729             }
730     }
731     /* If starship caused supernova, tally up destruction */
732     if (insx) {
733         game.state.starkl += game.state.galaxy[nqx][nqy].stars;
734         game.state.basekl += game.state.galaxy[nqx][nqy].starbase;
735         game.state.killk += kldead;
736         game.state.killc += comdead;
737         game.state.nromkl += nrmdead;
738         game.state.nplankl += npdead;
739         game.state.nsckill += iscdead;
740     }
741     /* mark supernova in galaxy and in star chart */
742     if ((quadx == nqx && quady == nqy) ||
743         game.damage[DRADIO] == 0 ||
744         condit == IHDOCKED)
745         game.state.galaxy[nqx][nqy].supernova = TRUE;
746     /* If supernova destroys last klingons give special message */
747     if (game.state.remkl==0 && (nqx != quadx || nqy != quady)) {
748         skip(2);
749         if (insx == 0) prout("Lucky you!");
750         proutn("A supernova in %s has just destroyed the last Klingons.",
751                cramlc(quadrant, nqx, nqy));
752         finish(FWON);
753         return;
754     }
755     /* if some Klingons remain, continue or die in supernova */
756     if (alldone) finish(FSNOVAED);
757     return;
758 }
759                 
760