Code, comment, and documentation typo fixes.
[super-star-trek.git] / battle.c
1 #include "sst.h"\r
2 \r
3 void doshield(int i) {\r
4         int key;\r
5         enum {NONE, SHUP, SHDN, NRG} action = NONE;\r
6 \r
7         ididit = 0;\r
8 \r
9         if (i == 2) action = SHUP;\r
10         else {\r
11                 key = scan();\r
12                 if (key == IHALPHA) {\r
13                         if (isit("transfer"))\r
14                                 action = NRG;\r
15                         else {\r
16                                 chew();\r
17                                 if (damage[DSHIELD]) {\r
18                                         prout("Shields damaged and down.");\r
19                                         return;\r
20                                 }\r
21                                 if (isit("up"))\r
22                                         action = SHUP;\r
23                                 else if (isit("down"))\r
24                                         action = SHDN;\r
25                         }\r
26                 }\r
27                 if (action==NONE) {\r
28                         proutn("Do you wish to change shield energy? ");\r
29                         if (ja()) {\r
30                                 proutn("Energy to transfer to shields- ");\r
31                                 action = NRG;\r
32                         }\r
33                         else if (damage[DSHIELD]) {\r
34                                 prout("Shields damaged and down.");\r
35                                 return;\r
36                         }\r
37                         else if (shldup) {\r
38                                 proutn("Shields are up. Do you want them down? ");\r
39                                 if (ja()) action = SHDN;\r
40                                 else {\r
41                                         chew();\r
42                                         return;\r
43                                 }\r
44                         }\r
45                         else {\r
46                                 proutn("Shields are down. Do you want them up? ");\r
47                                 if (ja()) action = SHUP;\r
48                                 else {\r
49                                         chew();\r
50                                         return;\r
51                                 }\r
52                         }\r
53                 }\r
54         }\r
55         switch (action) {\r
56                 case SHUP: /* raise shields */\r
57                         if (shldup) {\r
58                                 prout("Shields already up.");\r
59                                 return;\r
60                         }\r
61                         shldup = 1;\r
62                         shldchg = 1;\r
63                         if (condit != IHDOCKED) energy -= 50.0;\r
64                         prout("Shields raised.");\r
65                         if (energy <= 0) {\r
66                                 skip(1);\r
67                                 prout("Shields raising uses up last of energy.");\r
68                                 finish(FNRG);\r
69                                 return;\r
70                         }\r
71                         ididit=1;\r
72                         return;\r
73                 case SHDN:\r
74                         if (shldup==0) {\r
75                                 prout("Shields already down.");\r
76                                 return;\r
77                         }\r
78                         shldup=0;\r
79                         shldchg=1;\r
80                         prout("Shields lowered.");\r
81                         ididit=1;\r
82                         return;\r
83                 case NRG:\r
84                         while (scan() != IHREAL) {\r
85                                 chew();\r
86                                 proutn("Energy to transfer to shields- ");\r
87                         }\r
88                         chew();\r
89                         if (aaitem==0) return;\r
90                         if (aaitem > energy) {\r
91                                 prout("Insufficient ship energy.");\r
92                                 return;\r
93                         }\r
94                         ididit = 1;\r
95                         if (shield+aaitem >= inshld) {\r
96                                 prout("Shield energy maximized.");\r
97                                 if (shield+aaitem > inshld) {\r
98                                         prout("Excess energy requested returned to ship energy");\r
99                                 }\r
100                                 energy -= inshld-shield;\r
101                                 shield = inshld;\r
102                                 return;\r
103                         }\r
104                         if (aaitem < 0.0 && energy-aaitem > inenrg) {\r
105                                 /* Prevent shield drain loophole */\r
106                                 skip(1);\r
107                                 prout("Engineering to bridge--");\r
108                                 prout("  Scott here. Power circuit problem, Captain.");\r
109                                 prout("  I can't drain the shields.");\r
110                                 ididit = 0;\r
111                                 return;\r
112                         }\r
113                         if (shield+aaitem < 0) {\r
114                                 prout("All shield energy transferred to ship.");\r
115                                 energy += shield;\r
116                                 shield = 0.0;\r
117                                 return;\r
118                         }\r
119                         proutn("Scotty- \"");\r
120                         if (aaitem > 0)\r
121                                 prout("Transferring energy to shields.\"");\r
122                         else\r
123                                 prout("Draining energy from shields.\"");\r
124                         shield += aaitem;\r
125                         energy -= aaitem;\r
126                         return;\r
127         }\r
128 }\r
129 \r
130 void ram(int ibumpd, int ienm, int ix, int iy) {\r
131         double type = 1.0, extradm;\r
132         int icas, l;\r
133         \r
134         prouts("***RED ALERT!  RED ALERT!");\r
135         skip(1);\r
136         prout("***COLLISION IMMINENT.");\r
137         skip(2);\r
138         proutn("***");\r
139         crmshp();\r
140         switch (ienm) {\r
141                 case IHR: type = 1.5; break;\r
142                 case IHC: type = 2.0; break;\r
143                 case IHS: type = 2.5; break;\r
144                 case IHT: type = 0.5; break;\r
145         }\r
146         proutn(ibumpd ? " rammed by " : " rams ");\r
147         crmena(0, ienm, 2, ix, iy);\r
148         if (ibumpd) proutn(" (original position)");\r
149         skip(1);\r
150         deadkl(ix, iy, ienm, sectx, secty);\r
151         proutn("***");\r
152         crmshp();\r
153         prout(" heavily damaged.");\r
154         icas = 10.0+20.0*Rand();\r
155         proutn("***Sickbay reports ");\r
156         crami(icas, 1);\r
157         prout(" casualties.");\r
158         casual += icas;\r
159         for (l=1; l <= ndevice; l++) {\r
160                 if (l == DDRAY) continue; // Don't damage deathray \r
161                 if (damage[l] < 0) continue;\r
162                 extradm = (10.0*type*Rand()+1.0)*damfac;\r
163                 damage[l] += Time + extradm; /* Damage for at least time of travel! */\r
164         }\r
165         shldup = 0;\r
166         if (d.remkl) {\r
167                 pause(2);\r
168                 dreprt();\r
169         }\r
170         else finish(FWON);\r
171         return;\r
172 }\r
173 \r
174 void torpedo(double course, double r, int inx, int iny, double *hit) {\r
175         int l, iquad, ix, iy,  jx, jy, shoved=0, ll;\r
176         double ac=course + 0.25*r;\r
177         double angle = (15.0-ac)*0.5235988;\r
178         double bullseye = (15.0 - course)*0.5235988;\r
179         double deltax=-sin(angle), deltay=cos(angle), x=inx, y=iny, bigger;\r
180         double ang, temp, xx, yy, kp, h1;\r
181 \r
182         bigger = fabs(deltax);\r
183         if (fabs(deltay) > bigger) bigger = fabs(deltay);\r
184         deltax /= bigger;\r
185         deltay /= bigger;\r
186 \r
187         /* Loop to move a single torpedo */\r
188         for (l=1; l <= 15; l++) {\r
189                 x += deltax;\r
190                 ix = x + 0.5;\r
191                 if (ix < 1 || ix > 10) break;\r
192                 y += deltay;\r
193                 iy = y + 0.5;\r
194                 if (iy < 1 || iy > 10) break;\r
195                 if (l==4 || l==9) skip(1);\r
196                 cramf(x, 0, 1);\r
197                 proutn(" - ");\r
198                 cramf(y, 0, 1);\r
199                 proutn("   ");\r
200                 iquad=quad[ix][iy];\r
201                 if (iquad==IHDOT) continue;\r
202                 /* hit something */\r
203                 skip(1);\r
204                 switch(iquad) {\r
205                         case IHE: /* Hit our ship */\r
206                         case IHF:\r
207                                 skip(1);\r
208                                 proutn("Torpedo hits ");\r
209                                 crmshp();\r
210                                 prout(".");\r
211                                 *hit = 700.0 + 100.0*Rand() -\r
212                                            1000.0*sqrt(square(ix-inx)+square(iy-iny))*\r
213                                            fabs(sin(bullseye-angle));\r
214                                 *hit = fabs(*hit);\r
215                                 newcnd(); /* undock */\r
216                                 /* We may be displaced. */\r
217                                 if (landed==1) return; /* Cheat if on a planet */\r
218                                 ang = angle + 2.5*(Rand()-0.5);\r
219                                 temp = fabs(sin(ang));\r
220                                 if (fabs(cos(ang)) > temp) temp = fabs(cos(ang));\r
221                                 xx = -sin(ang)/temp;\r
222                                 yy = cos(ang)/temp;\r
223                                 jx=ix+xx+0.5;\r
224                                 jy=iy+yy+0.5;\r
225                                 if (jx<1 || jx>10 || jy<1 ||jy > 10) return;\r
226                                 if (quad[jx][jy]==IHBLANK) {\r
227                                         finish(FHOLE);\r
228                                         return;\r
229                                 }\r
230                                 if (quad[jx][jy]!=IHDOT) {\r
231                                         /* can't move into object */\r
232                                         return;\r
233                                 }\r
234                                 sectx = jx;\r
235                                 secty = jy;\r
236                                 crmshp();\r
237                                 shoved = 1;\r
238                                 break;\r
239                                           \r
240                         case IHC: /* Hit a commander */\r
241                         case IHS:\r
242                                 if (Rand() <= 0.05) {\r
243                                         crmena(1, iquad, 2, ix, iy);\r
244                                         prout(" uses anti-photon device;");\r
245                                         prout("   torpedo neutralized.");\r
246                                         return;\r
247                                 }\r
248                         case IHR: /* Hit a regular enemy */\r
249                         case IHK:\r
250                                 /* find the enemy */\r
251                                 for (ll=1; ll <= nenhere; ll++)\r
252                                         if (ix==kx[ll] && iy==ky[ll]) break;\r
253                                 kp = fabs(kpower[ll]);\r
254                                 h1 = 700.0 + 100.0*Rand() -\r
255                                          1000.0*sqrt(square(ix-inx)+square(iy-iny))*\r
256                                          fabs(sin(bullseye-angle));\r
257                                 h1 = fabs(h1);\r
258                                 if (kp < h1) h1 = kp;\r
259                                 kpower[ll] -= (kpower[ll]<0 ? -h1 : h1);\r
260                                 if (kpower[ll] == 0) {\r
261                                         deadkl(ix, iy, iquad, ix, iy);\r
262                                         return;\r
263                                 }\r
264                                 crmena(1, iquad, 2, ix, iy);\r
265                                 /* If enemy damaged but not destroyed, try to displace */\r
266                                 ang = angle + 2.5*(Rand()-0.5);\r
267                                 temp = fabs(sin(ang));\r
268                                 if (fabs(cos(ang)) > temp) temp = fabs(cos(ang));\r
269                                 xx = -sin(ang)/temp;\r
270                                 yy = cos(ang)/temp;\r
271                                 jx=ix+xx+0.5;\r
272                                 jy=iy+yy+0.5;\r
273                                 if (jx<1 || jx>10 || jy<1 ||jy > 10) {\r
274                                         prout(" damaged but not destroyed.");\r
275                                         return;\r
276                                 }\r
277                                 if (quad[jx][jy]==IHBLANK) {\r
278                                         prout(" buffeted into black hole.");\r
279                                         deadkl(ix, iy, iquad, jx, jy);\r
280                                         return;\r
281                                 }\r
282                                 if (quad[jx][jy]!=IHDOT) {\r
283                                         /* can't move into object */\r
284                                         prout(" damaged but not destroyed.");\r
285                                         return;\r
286                                 }\r
287                                 prout(" damaged--");\r
288                                 kx[ll] = jx;\r
289                                 ky[ll] = jy;\r
290                                 shoved = 1;\r
291                                 break;\r
292                         case IHB: /* Hit a base */\r
293                                 prout("***STARBASE DESTROYED..");\r
294                                 if (starch[quadx][quady] < 0) starch[quadx][quady] = 0;\r
295                                 for (ll=1; ll<=d.rembase; ll++) {\r
296                                         if (d.baseqx[ll]==quadx && d.baseqy[ll]==quady) {\r
297                                                 d.baseqx[ll]=d.baseqx[d.rembase];\r
298                                                 d.baseqy[ll]=d.baseqy[d.rembase];\r
299                                                 break;\r
300                                         }\r
301                                 }\r
302                                 quad[ix][iy]=IHDOT;\r
303                                 d.rembase--;\r
304                                 basex=basey=0;\r
305                                 d.galaxy[quadx][quady] -= 10;\r
306                                 d.basekl++;\r
307                                 newcnd();\r
308                                 return;\r
309                         case IHP: /* Hit a planet */\r
310                                 crmena(1, iquad, 2, ix, iy);\r
311                                 prout(" destroyed.");\r
312                                 d.nplankl++;\r
313                                 d.newstuf[quadx][quady] -= 1;\r
314                                 d.plnets[iplnet] = nulplanet;\r
315                                 iplnet = 0;\r
316                                 plnetx = plnety = 0;\r
317                                 quad[ix][iy] = IHDOT;\r
318                                 if (landed==1) {\r
319                                         /* captain parishes on planet */\r
320                                         finish(FDPLANET);\r
321                                 }\r
322                                 return;\r
323                         case IHSTAR: /* Hit a star */\r
324                                 if (Rand() > 0.10) {\r
325                                         nova(ix, iy);\r
326                                         return;\r
327                                 }\r
328                                 crmena(1, IHSTAR, 2, ix, iy);\r
329                                 prout(" unaffected by photon blast.");\r
330                                 return;\r
331                         case IHQUEST: /* Hit a thingy */\r
332                                 skip(1);\r
333                                 prouts("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!");\r
334                                 skip(1);\r
335                                 prouts("    HACK!     HACK!    HACK!        *CHOKE!*  ");\r
336                                 skip(1);\r
337                                 proutn("Mr. Spock-");\r
338                                 prouts("  \"Facinating!\"");\r
339                                 skip(1);\r
340                                 quad[ix][iy] = IHDOT;\r
341                                 return;\r
342                         case IHBLANK: /* Black hole */\r
343                                 skip(1);\r
344                                 crmena(1, IHBLANK, 2, ix, iy);\r
345                                 prout(" swallows torpedo.");\r
346                                 return;\r
347                         case IHWEB: /* hit the web */\r
348                                 skip(1);\r
349                                 prout("***Torpedo absorbed by Tholian web.");\r
350                                 return;\r
351                         case IHT:  /* Hit a Tholian */\r
352                                 skip(1);\r
353                                 crmena(1, IHT, 2, ix, iy);\r
354                                 h1 = 700.0 + 100.0*Rand() -\r
355                                          1000.0*sqrt(square(ix-inx)+square(iy-iny))*\r
356                                          fabs(sin(bullseye-angle));\r
357                                 h1 = fabs(h1);\r
358                                 if (h1 >= 600) {\r
359                                         prout(" destroyed.");\r
360                                         quad[ix][iy] = IHDOT;\r
361                                         ithere = 0;\r
362                                         ithx = ithy = 0;\r
363                                         return;\r
364                                 }\r
365                                 if (Rand() > 0.05) {\r
366                                         prout(" survives photon blast.");\r
367                                         return;\r
368                                 }\r
369                                 prout(" disappears.");\r
370                                 quad[ix][iy] = IHWEB;\r
371                                 ithere = ithx = ithy = 0;\r
372                                 {\r
373                                         int dum, my;\r
374                                         dropin(IHBLANK, &dum, &my);\r
375                                 }\r
376                                 return;\r
377                                         \r
378                         default: /* Problem! */\r
379                                 skip(1);\r
380                                 proutn("Don't know how to handle collision with ");\r
381                                 crmena(1, iquad, 2, ix, iy);\r
382                                 skip(1);\r
383                                 return;\r
384                 }\r
385                 break;\r
386         }\r
387         if (shoved) {\r
388                 quad[jx][jy]=iquad;\r
389                 quad[ix][iy]=IHDOT;\r
390                 proutn(" displaced by blast to");\r
391                 cramlc(2, jx, jy);\r
392                 skip(1);\r
393                 for (ll=1; ll<=nenhere; ll++)\r
394                         kdist[ll] = kavgd[ll] = sqrt(square(sectx-kx[ll])+square(secty-ky[ll]));\r
395                 sortkl();\r
396                 return;\r
397         }\r
398         skip(1);\r
399         prout("Torpedo missed.");\r
400         return;\r
401 }\r
402 \r
403 static void fry(double hit) {\r
404         double ncrit, extradm;\r
405         int ktr=1, l, ll, j, cdam[6], crptr;\r
406 \r
407         /* a critical hit occured */\r
408         if (hit < (275.0-25.0*skill)*(1.0+0.5*Rand())) return;\r
409 \r
410         ncrit = 1.0 + hit/(500.0+100.0*Rand());\r
411         proutn("***CRITICAL HIT--");\r
412         /* Select devices and cause damage */\r
413         for (l = 1; l <= ncrit; l++) {\r
414                 do {\r
415                         j = ndevice*Rand()+1.0;\r
416                         /* Cheat to prevent shuttle damage unless on ship */\r
417                 } while (damage[j] < 0.0 || (j == DSHUTTL && iscraft != 1) ||\r
418                                  j == DDRAY);\r
419                 cdam[l] = j;\r
420                 extradm = (hit*damfac)/(ncrit*(75.0+25.0*Rand()));\r
421                 damage[j] += extradm;\r
422                 if (l > 1) {\r
423                         for (ll=2; ll<=l && j != cdam[ll-1]; ll++) ;\r
424                         if (ll<=l) continue;\r
425                         ktr += 1;\r
426                         if (ktr==3) skip(1);\r
427                         proutn(" and ");\r
428                 }\r
429                 proutn(device[j]);\r
430         }\r
431         prout(" damaged.");\r
432         if (damage[DSHIELD] && shldup) {\r
433                 prout("***Shields knocked down.");\r
434                 shldup=0;\r
435         }\r
436 }\r
437 \r
438 void attack(int k) {\r
439         /* k == 0 forces use of phasers in an attack */\r
440         int percent, ihurt=0, l, i=0, jx, jy, iquad, itflag;\r
441         int atackd = 0, attempt = 0;\r
442         double hit;\r
443         double pfac, dustfac, hitmax=0.0, hittot=0.0, chgfac=1.0, r;\r
444 \r
445         iattak = 1;\r
446         if (alldone) return;\r
447 #ifdef DEBUG\r
448         if (idebug) prout("ATTACK!");\r
449 #endif\r
450 \r
451         if (ithere) movetho();\r
452 \r
453         if (neutz) { /* The one chance not to be attacked */\r
454                 neutz = 0;\r
455                 return;\r
456         }\r
457         if (((comhere || ishere) && (justin == 0)) || skill == 5) movcom();\r
458         if (nenhere==0) return;\r
459         pfac = 1.0/inshld;\r
460         if (shldchg == 1) chgfac = 0.25+0.5*Rand();\r
461         skip(1);\r
462         if (skill <= 2) i = 2;\r
463         for (l=1; l <= nenhere; l++) {\r
464                 if (kpower[l] < 0) continue;    /* too weak to attack */\r
465                 /* compute hit strength and diminsh shield power */\r
466                 r = Rand();\r
467                 /* Increase chance of photon torpedos if docked or enemy energy low */\r
468                 if (condit == IHDOCKED) r *= 0.25;\r
469                 if (kpower[l] < 500) r *= 0.25; \r
470                 jx = kx[l];\r
471                 jy = ky[l];\r
472                 iquad = quad[jx][jy];\r
473                 itflag = (iquad == IHK && r > 0.0005) || k == 0 ||\r
474                         (iquad==IHC && r > 0.015) ||\r
475                         (iquad==IHR && r > 0.3) ||\r
476                         (iquad==IHS && r > 0.07);\r
477                 if (itflag) {\r
478                         /* Enemy uses phasers */\r
479                         if (condit == IHDOCKED) continue; /* Don't waste the effort! */\r
480                         attempt = 1; /* Attempt to attack */\r
481                         dustfac = 0.8+0.05*Rand();\r
482                         hit = kpower[l]*pow(dustfac,kavgd[l]);\r
483                         kpower[l] *= 0.75;\r
484                 }\r
485                 else { /* Enemy used photon torpedo */\r
486                         double course = 1.90985*atan2((double)secty-jy, (double)jx-sectx);\r
487                         hit = 0;\r
488                         proutn("***TORPEDO INCOMING");\r
489                         if (damage[DSRSENS] <= 0.0) {\r
490                                 proutn(" From ");\r
491                                 crmena(0, iquad, i, jx, jy);\r
492                         }\r
493                         attempt = 1;\r
494                         prout("--");\r
495                         r = (Rand()+Rand())*0.5 -0.5;\r
496                         r += 0.002*kpower[l]*r;\r
497                         torpedo(course, r, jx, jy, &hit);\r
498                         if (d.remkl==0) finish(FWON); /* Klingons did themselves in! */\r
499                         if (d.galaxy[quadx][quady] == 1000 ||\r
500                                 alldone) return; /* Supernova or finished */\r
501                         if (hit == 0) continue;\r
502                 }\r
503                 if (shldup != 0 || shldchg != 0) {\r
504                         /* shields will take hits */\r
505                         double absorb, hitsh, propor = pfac*shield;\r
506                         if(propor < 0.1) propor = 0.1;\r
507                         hitsh = propor*chgfac*hit+1.0;\r
508                         atackd=1;\r
509                         absorb = 0.8*hitsh;\r
510                         if (absorb > shield) absorb = shield;\r
511                         shield -= absorb;\r
512                         hit -= hitsh;\r
513                         if (propor > 0.1 && hit < 0.005*energy) continue;\r
514                 }\r
515                 /* It's a hit -- print out hit size */\r
516                 atackd = 1; /* We weren't going to check casualties, etc. if\r
517                                shields were down for some strange reason. This\r
518                                            doesn't make any sense, so I've fixed it */\r
519                 ihurt = 1;\r
520                 cramf(hit, 0, 2);\r
521                 proutn(" unit hit");\r
522                 if ((damage[DSRSENS] > 0 && itflag) || skill <= 2) {\r
523                         proutn(" on the ");\r
524                         crmshp();\r
525                 }\r
526                 if (damage[DSRSENS] <= 0.0 && itflag) {\r
527                         proutn(" from ");\r
528                         crmena(0, iquad, i, jx, jy);\r
529                 }\r
530                 skip(1);\r
531                 /* Decide if hit is critical */\r
532                 if (hit > hitmax) hitmax = hit;\r
533                 hittot += hit;\r
534                 fry(hit);\r
535                 printf("Hit %g energy %g\n", hit, energy);\r
536                 energy -= hit;\r
537         }\r
538         if (energy <= 0) {\r
539                 /* Returning home upon your shield, not with it... */\r
540                 finish(FBATTLE);\r
541                 return;\r
542         }\r
543         if (attempt == 0 && condit == IHDOCKED)\r
544                 prout("***Enemies decide against attacking your ship.");\r
545         if (atackd == 0) return;\r
546         percent = 100.0*pfac*shield+0.5;\r
547         if (ihurt==0) {\r
548                 /* Shields fully protect ship */\r
549                 proutn("Enemy attack reduces shield strength to ");\r
550         }\r
551         else {\r
552                 /* Print message if starship suffered hit(s) */\r
553                 skip(1);\r
554                 proutn("Energy left ");\r
555                 cramf(energy, 0, 2);\r
556                 proutn("    shields ");\r
557                 if (shldup) proutn("up, ");\r
558                 else if (damage[DSHIELD] == 0) proutn("down, ");\r
559                 else proutn("damaged, ");\r
560         }\r
561         crami(percent, 1);\r
562         proutn("%   torpedoes left ");\r
563         crami(torps, 1);\r
564         skip(1);\r
565         /* Check if anyone was hurt */\r
566         if (hitmax >= 200 || hittot >= 500) {\r
567                 int icas= hittot*Rand()*0.015;\r
568                 if (icas >= 2) {\r
569                         skip(1);\r
570                         proutn("Mc Coy-  \"Sickbay to bridge.  We suffered ");\r
571                         crami(icas, 1);\r
572                         prout(" casualties");\r
573                         prout("   in that last attack.\"");\r
574                         casual += icas;\r
575                 }\r
576         }\r
577         /* After attack, reset average distance to enemies */\r
578         for (l = 1; l <= nenhere; l++)\r
579                 kavgd[l] = kdist[l];\r
580         sortkl();\r
581         return;\r
582 }\r
583                 \r
584 void deadkl(int ix, int iy, int type, int ixx, int iyy) {\r
585         /* Added ixx and iyy allow enemy to "move" before dying */\r
586 \r
587         int i,j;\r
588         \r
589         crmena(1, type, 2, ixx, iyy);\r
590         /* Decide what kind of enemy it is and update approriately */\r
591         if (type == IHR) {\r
592                 /* chalk up a Romulan */\r
593                 d.newstuf[quadx][quady] -= 10;\r
594                 irhere--;\r
595                 d.nromkl++;\r
596                 d.nromrem--;\r
597         }\r
598         else if (type == IHT) {\r
599                 /* Killed a Tholian */\r
600                 ithere = 0;\r
601         }\r
602         else {\r
603                 /* Some type of a Klingon */\r
604                 d.galaxy[quadx][quady] -= 100;\r
605                 klhere--;\r
606                 d.remkl--;\r
607                 switch (type) {\r
608                         case IHC:\r
609                                 comhere = 0;\r
610                                 for (i=1; i<=d.remcom; i++)\r
611                                         if (d.cx[i]==quadx && d.cy[i]==quady) break;\r
612                                 d.cx[i] = d.cx[d.remcom];\r
613                                 d.cy[i] = d.cy[d.remcom];\r
614                                 d.cx[d.remcom] = 0;\r
615                                 d.cy[d.remcom] = 0;\r
616                                 d.remcom--;\r
617                                 future[FTBEAM] = 1e30;\r
618                                 if (d.remcom != 0)\r
619                                         future[FTBEAM] = d.date + expran(1.0*incom/d.remcom);\r
620                                 d.killc++;\r
621                                 break;\r
622                         case IHK:\r
623                                 d.killk++;\r
624                                 break;\r
625                         case IHS:\r
626                                 d.nscrem = ishere = d.isx = d.isy = isatb = iscate = 0;\r
627                                 d.nsckill = 1;\r
628                                 future[FSCMOVE] = future[FSCDBAS] = 1e30;\r
629                                 break;\r
630                 }\r
631         }\r
632 \r
633         /* For each kind of enemy, finish message to player */\r
634         prout(" destroyed.");\r
635         quad[ix][iy] = IHDOT;\r
636         if (d.remkl==0) return;\r
637 \r
638         d.remtime = d.remres/(d.remkl + 4*d.remcom);\r
639 \r
640         if (type == IHT) return;\r
641 \r
642         /* Remove enemy ship from arrays describing local conditions */\r
643 \r
644         for (i=1; i<=nenhere; i++)\r
645                 if (kx[i]==ix && ky[i]==iy) break;\r
646         nenhere--;\r
647         if (i <= nenhere)  {\r
648                 for (j=i; j<=nenhere; j++) {\r
649                         kx[j] = kx[j+1];\r
650                         ky[j] = ky[j+1];\r
651                         kpower[j] = kpower[j+1];\r
652                         kavgd[j] = kdist[j] = kdist[j+1];\r
653                 }\r
654         }\r
655         kx[nenhere+1] = 0;\r
656         ky[nenhere+1] = 0;\r
657         kdist[nenhere+1] = 0;\r
658         kavgd[nenhere+1] = 0;\r
659         kpower[nenhere+1] = 0;\r
660         return;\r
661 }\r
662 \r
663 static int targetcheck(double x, double y, double *course) {\r
664         double deltx, delty;\r
665         /* Return TRUE if target is invalid */\r
666         if (x < 1.0 || x > 10.0 || y < 1.0 || y > 10.0) {\r
667                 huh();\r
668                 return 1;\r
669         }\r
670         deltx = 0.1*(y - secty);\r
671         delty = 0.1*(sectx - x);\r
672         if (deltx==0 && delty== 0) {\r
673                 skip(1);\r
674                 prout("Spock-  \"Bridge to sickbay.  Dr. McCoy,");\r
675                 prout("  I recommend an immediate review of");\r
676                 prout("  the Captain's psychological profile.");\r
677                 chew();\r
678                 return 1;\r
679         }\r
680         *course = 1.90985932*atan2(deltx, delty);\r
681         return 0;\r
682 }\r
683 \r
684 void photon(void) {\r
685         double targ[4][3], course[4];\r
686         double r, dummy;\r
687         int key, n, i, osuabor;\r
688 \r
689         ididit = 0;\r
690 \r
691         if (damage[DPHOTON]) {\r
692                 prout("Photon tubes damaged.");\r
693                 chew();\r
694                 return;\r
695         }\r
696         if (torps == 0) {\r
697                 prout("No torpedoes left.");\r
698                 chew();\r
699                 return;\r
700         }\r
701         key = scan();\r
702         for (;;) {\r
703                 if (key == IHALPHA) {\r
704                         huh();\r
705                         return;\r
706                 }\r
707                 else if (key == IHEOL) {\r
708                         crami(torps,1);\r
709                         prout(" torpedoes left.");\r
710                         proutn("Number of torpedoes to fire- ");\r
711                         key = scan();\r
712                 }\r
713                 else /* key == IHREAL */ {\r
714                         n = aaitem + 0.5;\r
715                         if (n <= 0) { /* abort command */\r
716                                 chew();\r
717                                 return;\r
718                         }\r
719                         if (n > 3) {\r
720                                 chew();\r
721                                 prout("Maximum of 3 torpedoes per burst.");\r
722                                 key = IHEOL;\r
723                         }\r
724                         if (n <= torps) break;\r
725                         chew();\r
726                         key = IHEOL;\r
727                 }\r
728         }\r
729         for (i = 1; i <= n; i++) {\r
730                 key = scan();\r
731                 if (i==1 && key == IHEOL) {\r
732                         break;  /* we will try prompting */\r
733                 }\r
734                 if (i==2 && key == IHEOL) {\r
735                         /* direct all torpedoes at one target */\r
736                         while (i <= n) {\r
737                                 targ[i][1] = targ[1][1];\r
738                                 targ[i][2] = targ[1][2];\r
739                                 course[i] = course[1];\r
740                                 i++;\r
741                         }\r
742                         break;\r
743                 }\r
744                 if (key != IHREAL) {\r
745                         huh();\r
746                         return;\r
747                 }\r
748                 targ[i][1] = aaitem;\r
749                 key = scan();\r
750                 if (key != IHREAL) {\r
751                         huh();\r
752                         return;\r
753                 }\r
754                 targ[i][2] = aaitem;\r
755                 if (targetcheck(targ[i][1], targ[i][2], &course[i])) return;\r
756         }\r
757         chew();\r
758         if (i == 1 && key == IHEOL) {\r
759                 /* prompt for each one */\r
760                 for (i = 1; i <= n; i++) {\r
761                         proutn("Target sector for torpedo number");\r
762                         crami(i, 2);\r
763                         proutn("- ");\r
764                         key = scan();\r
765                         if (key != IHREAL) {\r
766                                 huh();\r
767                                 return;\r
768                         }\r
769                         targ[i][1] = aaitem;\r
770                         key = scan();\r
771                         if (key != IHREAL) {\r
772                                 huh();\r
773                                 return;\r
774                         }\r
775                         targ[i][2] = aaitem;\r
776                         chew();\r
777                         if (targetcheck(targ[i][1], targ[i][2], &course[i])) return;\r
778                 }\r
779         }\r
780         ididit = 1;\r
781         /* Loop for moving <n> torpedoes */\r
782         osuabor = 0;\r
783         for (i = 1; i <= n && !osuabor; i++) {\r
784                 if (condit != IHDOCKED) torps--;\r
785                 r = (Rand()+Rand())*0.5 -0.5;\r
786                 if (fabs(r) >= 0.47) {\r
787                         /* misfire! */\r
788                         r = (Rand()+1.2) * r;\r
789                         if (n>1) {\r
790                                 prouts("***TORPEDO NUMBER");\r
791                                 crami(i, 2);\r
792                                 prouts(" MISFIRES.");\r
793                         }\r
794                         else prouts("***TORPEDO MISFIRES.");\r
795                         skip(1);\r
796                         if (i < n)\r
797                                 prout("  Remainder of burst aborted.");\r
798                         osuabor=1;\r
799                         if (Rand() <= 0.2) {\r
800                                 prout("***Photon tubes damaged by misfire.");\r
801                                 damage[DPHOTON] = damfac*(1.0+2.0*Rand());\r
802                                 break;\r
803                         }\r
804                 }\r
805                 if (shldup != 0 || condit == IHDOCKED) r *= 1.0 + 0.0001*shield;\r
806                 if (n != 1) {\r
807                         skip(1);\r
808                         proutn("Track for torpedo number");\r
809                         crami(i, 2);\r
810                         proutn("-   ");\r
811                 }\r
812                 else {\r
813                         skip(1);\r
814                         proutn("Torpedo track- ");\r
815                 }\r
816                 torpedo(course[i], r, sectx, secty, &dummy);\r
817                 if (alldone || d.galaxy[quadx][quady]==1000) return;\r
818         }\r
819         if (d.remkl==0) finish(FWON);\r
820 }\r
821 \r
822         \r
823 \r
824 static void overheat(double rpow) {\r
825         if (rpow > 1500) {\r
826                 double chekbrn = (rpow-1500.)*0.00038;\r
827                 if (Rand() <= chekbrn) {\r
828                         prout("Weapons officer Sulu-  \"Phasers overheated, sir.\"");\r
829                         damage[DPHASER] = damfac*(1.0 + Rand()) * (1.0+chekbrn);\r
830                 }\r
831         }\r
832 }\r
833 \r
834 static int checkshctrl(double rpow) {\r
835         double hit;\r
836         int icas;\r
837         \r
838         skip(1);\r
839         if (Rand() < .998) {\r
840                 prout("Shields lowered.");\r
841                 return 0;\r
842         }\r
843         /* Something bad has happened */\r
844         prouts("***RED ALERT!  RED ALERT!");\r
845         skip(2);\r
846         hit = rpow*shield/inshld;\r
847         energy -= rpow+hit*0.8;\r
848         shield -= hit*0.2;\r
849         if (energy <= 0.0) {\r
850                 prouts("Sulu-  \"Captain! Shield malf***********************\"");\r
851                 skip(1);\r
852                 stars();\r
853                 finish(FPHASER);\r
854                 return 1;\r
855         }\r
856         prouts("Sulu-  \"Captain! Shield malfunction! Phaser fire contained!\"");\r
857         skip(2);\r
858         prout("Lt. Uhura-  \"Sir, all decks reporting damage.\"");\r
859         icas = hit*Rand()*0.012;\r
860         skip(1);\r
861         fry(0.8*hit);\r
862         if (icas) {\r
863                 skip(1);\r
864                 prout("McCoy to bridge- \"Severe radiation burns, Jim.");\r
865                 proutn("  ");\r
866                 crami(icas, 1);\r
867                 prout(" casualties so far.\"");\r
868                 casual -= icas;\r
869         }\r
870         skip(1);\r
871         prout("Phaser energy dispersed by shields.");\r
872         prout("Enemy unaffected.");\r
873         overheat(rpow);\r
874         return 1;\r
875 }\r
876         \r
877 \r
878 void phasers(void) {\r
879         double hits[21], rpow, extra, powrem, over, temp;\r
880         int kz = 0, k=1, i; /* Cheating inhibitor */\r
881         int ifast=0, no=0, ipoop=1, msgflag = 1;\r
882         enum {NOTSET, MANUAL, FORCEMAN, AUTOMATIC} automode = NOTSET;\r
883         int key;\r
884 \r
885         skip(1);\r
886         /* SR sensors and Computer */\r
887         if (damage[DSRSENS]+damage[DCOMPTR] > 0) ipoop = 0;\r
888         if (condit == IHDOCKED) {\r
889                 prout("Phasers can't be fired through base shields.");\r
890                 chew();\r
891                 return;\r
892         }\r
893         if (damage[DPHASER] != 0) {\r
894                 prout("Phaser control damaged.");\r
895                 chew();\r
896                 return;\r
897         }\r
898         if (shldup) {\r
899                 if (damage[DSHCTRL]) {\r
900                         prout("High speed shield control damaged.");\r
901                         chew();\r
902                         return;\r
903                 }\r
904                 if (energy <= 200.0) {\r
905                         prout("Insufficient energy to activate high-speed shield control.");\r
906                         chew();\r
907                         return;\r
908                 }\r
909                 prout("Weapons Officer Sulu-  \"High-speed shield control enabled, sir.\"");\r
910                 ifast = 1;\r
911                 \r
912         }\r
913         ididit = 1;\r
914         /* Original code so convoluted, I re-did it all */\r
915         while (automode==NOTSET) {\r
916                 key=scan();\r
917                 if (key == IHALPHA) {\r
918                         if (isit("manual")) {\r
919                                 if (nenhere==0) {\r
920                                         prout("There is no enemy present to select.");\r
921                                         chew();\r
922                                         key = IHEOL;\r
923                                         automode=AUTOMATIC;\r
924                                 }\r
925                                 else {\r
926                                         automode = MANUAL;\r
927                                         key = scan();\r
928                                 }\r
929                         }\r
930                         else if (isit("automatic")) {\r
931                                 if ((!ipoop) && nenhere != 0) {\r
932                                         automode = FORCEMAN;\r
933                                 }\r
934                                 else {\r
935                                         if (nenhere==0)\r
936                                                 prout("Energy will be expended into space.");\r
937                                         automode = AUTOMATIC;\r
938                                         key = scan();\r
939                                 }\r
940                         }\r
941                         else if (isit("no")) {\r
942                                 no = 1;\r
943                         }\r
944                         else {\r
945                                 huh();\r
946                                 ididit = 0;\r
947                                 return;\r
948                         }\r
949                 }\r
950                 else if (key == IHREAL) {\r
951                         if (nenhere==0) {\r
952                                 prout("Energy will be expended into space.");\r
953                                 automode = AUTOMATIC;\r
954                         }\r
955                         else if (!ipoop)\r
956                                 automode = FORCEMAN;\r
957                         else\r
958                                 automode = AUTOMATIC;\r
959                 }\r
960                 else {\r
961                         /* IHEOL */\r
962                         if (nenhere==0) {\r
963                                 prout("Energy will be expended into space.");\r
964                                 automode = AUTOMATIC;\r
965                         }\r
966                         else if (!ipoop)\r
967                                 automode = FORCEMAN;\r
968                         else \r
969                         proutn("Manual or automatic? ");\r
970                 }\r
971         }\r
972                                 \r
973         switch (automode) {\r
974                 case AUTOMATIC:\r
975                         if (key == IHALPHA && isit("no")) {\r
976                                 no = 1;\r
977                                 key = scan();\r
978                         }\r
979                         if (key != IHREAL && nenhere != 0) {\r
980                                 proutn("Phasers locked on target. Energy available =");\r
981                                 cramf(ifast?energy-200.0:energy,1,2);\r
982                                 skip(1);\r
983                         }\r
984                         do {\r
985                                 while (key != IHREAL) {\r
986                                         chew();\r
987                                         proutn("Units to fire=");\r
988                                         key = scan();\r
989                                 }\r
990                                 rpow = aaitem;\r
991                                 if (rpow >= (ifast?energy-200:energy)) {\r
992                                         proutn("Energy available= ");\r
993                                         cramf(ifast?energy-200:energy, 1,2);\r
994                                         skip(1);\r
995                                         key = IHEOL;\r
996                                 }\r
997                         } while (rpow >= (ifast?energy-200:energy));\r
998                         if (rpow<=0) {\r
999                                 /* chicken out */\r
1000                                 ididit = 0;\r
1001                                 chew();\r
1002                                 return;\r
1003                         }\r
1004                         if ((key=scan()) == IHALPHA && isit("no")) {\r
1005                                 no = 1;\r
1006                         }\r
1007                         if (ifast) {\r
1008                                 energy -= 200; /* Go and do it! */\r
1009                                 if (checkshctrl(rpow)) return;\r
1010                         }\r
1011                         chew();\r
1012                         energy -= rpow;\r
1013                         extra = rpow;\r
1014                         if (nenhere) {\r
1015                                 extra = 0.0;\r
1016                                 powrem = rpow;\r
1017                                 for (i = 1; i <= nenhere; i++) {\r
1018                                         hits[i] = 0.0;\r
1019                                         if (powrem <= 0) continue;\r
1020                                         hits[i] = fabs(kpower[i])/(phasefac*pow(0.90,kdist[i]));\r
1021                                         over = (0.01 + 0.05*Rand())*hits[i];\r
1022                                         temp = powrem;\r
1023                                         powrem -= hits[i] + over;\r
1024                                         if (powrem <= 0 && temp < hits[i]) hits[i] = temp;\r
1025                                         if (powrem <= 0) over = 0.0;\r
1026                                         extra += over;\r
1027                                 }\r
1028                                 if (powrem > 0.0) extra += powrem;\r
1029                                 hittem(hits);\r
1030                         }\r
1031                         if (extra > 0 && alldone == 0) {\r
1032                                 if (ithere) {\r
1033                                         proutn("*** Tholian web absorbs ");\r
1034                                         if (nenhere>0) proutn("excess ");\r
1035                                         prout("phaser energy.");\r
1036                                 }\r
1037                                 else {\r
1038                                         cramf(extra, 0, 2);\r
1039                                         prout(" expended on empty space.");\r
1040                                 }\r
1041                         }\r
1042                         break;\r
1043 \r
1044                 case FORCEMAN:\r
1045                         chew();\r
1046                         key = IHEOL;\r
1047                         if (damage[DCOMPTR]!=0)\r
1048                                 prout("Battle comuter damaged, manual file only.");\r
1049                         else {\r
1050                                 skip(1);\r
1051                                 prouts("---WORKING---");\r
1052                                 skip(1);\r
1053                                 prout("Short-range-sensors-damaged");\r
1054                                 prout("Insufficient-data-for-automatic-phaser-fire");\r
1055                                 prout("Manual-fire-must-be-used");\r
1056                                 skip(1);\r
1057                         }\r
1058                 case MANUAL:\r
1059                         rpow = 0.0;\r
1060                         for (k = 1; k <= nenhere;) {\r
1061                                 int ii = kx[k], jj = ky[k];\r
1062                                 int ienm = quad[ii][jj];\r
1063                                 if (msgflag) {\r
1064                                         proutn("Energy available= ");\r
1065                                         cramf(energy-.006-(ifast?200:0), 0, 2);\r
1066                                         skip(1);\r
1067                                         msgflag = 0;\r
1068                                         rpow = 0.0;\r
1069                                 }\r
1070                                 if (damage[DSRSENS] && !(abs(sectx-ii) < 2 && abs(secty-jj) < 2) &&\r
1071                                         (ienm == IHC || ienm == IHS)) {\r
1072                                         cramen(ienm);\r
1073                                         prout(" can't be located without short range scan.");\r
1074                                         chew();\r
1075                                         key = IHEOL;\r
1076                                         hits[k] = 0; /* prevent overflow -- thanks to Alexei Voitenko */\r
1077                                         k++;\r
1078                                         continue;\r
1079                                 }\r
1080                                 if (key == IHEOL) {\r
1081                                         chew();\r
1082                                         if (ipoop && k > kz) {\r
1083                                                 int irec=(fabs(kpower[k])/(phasefac*pow(0.9,kdist[k])))*\r
1084                                                                  (1.01+0.05*Rand()) + 1.0;\r
1085                                                 kz = k;\r
1086                                                 proutn("(");\r
1087                                                 crami(irec, 1);\r
1088                                                 proutn(")  ");\r
1089                                         }\r
1090                                         proutn("units to fire at ");\r
1091                                         crmena(0, ienm, 2, ii, jj);\r
1092                                         proutn("-  ");\r
1093                                         key = scan();\r
1094                                 }\r
1095                                 if (key == IHALPHA && isit("no")) {\r
1096                                         no = 1;\r
1097                                         key = scan();\r
1098                                         continue;\r
1099                                         }\r
1100                                 if (key == IHALPHA) {\r
1101                                         huh();\r
1102                                         ididit = 0;\r
1103                                         return;\r
1104                                 }\r
1105                                 if (key == IHEOL) {\r
1106                                         if (k==1) { /* Let me say I'm baffled by this */\r
1107                                                 msgflag = 1;\r
1108                                         }\r
1109                                         continue;\r
1110                                 }\r
1111                                 if (aaitem < 0) {\r
1112                                         /* abort out */\r
1113                                         ididit = 0;\r
1114                                         chew();\r
1115                                         return;\r
1116                                 }\r
1117                                 hits[k] = aaitem;\r
1118                                 rpow += aaitem;\r
1119                                 /* If total requested is too much, inform and start over */\r
1120                                 \r
1121                                 if (rpow >= (ifast?energy-200:energy)) {\r
1122                                         prout("Available energy exceeded -- try again.");\r
1123                                         chew();\r
1124                                         key = IHEOL;\r
1125                                         k = 1;\r
1126                                         msgflag = 1;\r
1127                                         continue;\r
1128                                 }\r
1129                                 key = scan(); /* scan for next value */\r
1130                                 k++;\r
1131                         }\r
1132                         if (rpow == 0.0) {\r
1133                                 /* zero energy -- abort */\r
1134                                 ididit = 0;\r
1135                                 chew();\r
1136                                 return;\r
1137                         }\r
1138                         if (key == IHALPHA & isit("no")) {\r
1139                                 no = 1;\r
1140                         }\r
1141                         energy -= rpow;\r
1142                         chew();\r
1143                         if (ifast) {\r
1144                                 energy -= 200.0;\r
1145                                 if (checkshctrl(rpow)) return;\r
1146                         }\r
1147                         hittem(hits);\r
1148                         ididit=1;\r
1149         }\r
1150         /* Say shield raised or malfunction, if necessary */\r
1151         if (alldone) return;\r
1152         if (ifast) {\r
1153                 skip(1);\r
1154                 if (no == 0) {\r
1155                         if (Rand() >= 0.99) {\r
1156                                 prout("Sulu-  \"Sir, the high-speed shield control has malfunctioned . . .");\r
1157                                 prouts("         CLICK   CLICK   POP  . . .");\r
1158                                 prout(" No  response, sir!");\r
1159                                 shldup = 0;\r
1160                         }\r
1161                         else\r
1162                                 prout("Shields raised.");\r
1163                 }\r
1164                 else\r
1165                         shldup = 0;\r
1166         }\r
1167         overheat(rpow);\r
1168 }\r
1169 \r
1170 void hittem(double *hits) {\r
1171         double kp, kpow, wham, hit, dustfac, kpini;\r
1172         int nenhr2=nenhere, k=1, kk=1, ii, jj, ienm;\r
1173 \r
1174         skip(1);\r
1175 \r
1176         for (; k <= nenhr2; k++, kk++) {\r
1177                 if ((wham = hits[k])==0) continue;\r
1178                 dustfac = 0.9 + 0.01*Rand();\r
1179                 hit = wham*pow(dustfac,kdist[kk]);\r
1180                 kpini = kpower[kk];\r
1181                 kp = fabs(kpini);\r
1182                 if (phasefac*hit < kp) kp = phasefac*hit;\r
1183                 kpower[kk] -= (kpower[kk] < 0 ? -kp: kp);\r
1184                 kpow = kpower[kk];\r
1185                 ii = kx[kk];\r
1186                 jj = ky[kk];\r
1187                 if (hit > 0.005) {\r
1188                         cramf(hit, 0, 2);\r
1189                         proutn(" unit hit on ");\r
1190                 }\r
1191                 else\r
1192                         proutn("Very small hit on ");\r
1193                 ienm = quad[ii][jj];\r
1194                 crmena(0,ienm,2,ii,jj);\r
1195                 skip(1);\r
1196                 if (kpow == 0) {\r
1197                         deadkl(ii, jj, ienm, ii, jj);\r
1198                         if (d.remkl==0) finish(FWON);\r
1199                         if (alldone) return;\r
1200                         kk--; /* don't do the increment */\r
1201                 }\r
1202                 else /* decide whether or not to emasculate klingon */\r
1203                         if (kpow > 0 && Rand() >= 0.9 &&\r
1204                                 kpow <= ((0.4 + 0.4*Rand())*kpini)) {\r
1205                                 proutn("***Mr. Spock-  \"Captain, the vessel at");\r
1206                                 cramlc(2,ii,jj);\r
1207                                 skip(1);\r
1208                                 prout("   has just lost its firepower.\"");\r
1209                                 kpower[kk] = -kpow;\r
1210                         }\r
1211         }\r
1212         return;\r
1213 }\r
1214 \r