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