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