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