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