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