Code, comment, and documentation typo fixes.
[super-star-trek.git] / moving.c
1 #include "sst.h"\r
2 \r
3 static void getcd(int, int);\r
4 \r
5 void move(void) {\r
6         double angle, deltax, deltay, bigger, x, y,\r
7         finald, finalx, finaly, stopegy;\r
8         int trbeam = 0, n, l, ix, iy, kink, kinks, iquad;\r
9 \r
10         if (inorbit) {\r
11                 prout("Helmsman Sulu- \"Leaving standard orbit.\"");\r
12                 inorbit = 0;\r
13         }\r
14 \r
15         angle = ((15.0 - direc) * 0.5235988);\r
16         deltax = -sin(angle);\r
17         deltay = cos(angle);\r
18         if (fabs(deltax) > fabs(deltay))\r
19                 bigger = fabs(deltax);\r
20         else\r
21                 bigger = fabs(deltay);\r
22                 \r
23         deltay /= bigger;\r
24         deltax /= bigger;\r
25 \r
26         /* If tractor beam is to occur, don't move full distance */\r
27         if (d.date+Time >= future[FTBEAM]) {\r
28                 trbeam = 1;\r
29                 condit = IHRED;\r
30                 dist = dist*(future[FTBEAM]-d.date)/Time + 0.1;\r
31                 Time = future[FTBEAM] - d.date + 1e-5;\r
32         }\r
33         /* Move within the quadrant */\r
34         quad[sectx][secty] = IHDOT;\r
35         x = sectx;\r
36         y = secty;\r
37         n = 10.0*dist*bigger+0.5;\r
38 \r
39         if (n > 0) {\r
40                 for (l = 1; l <= n; l++) {\r
41                         ix = (x += deltax) + 0.5;\r
42                         iy = (y += deltay) + 0.5;\r
43                         if (ix < 1 || ix > 10 || iy < 1 || iy > 10) {\r
44                                 /* Leaving quadrant -- allow final enemy attack */\r
45                                 /* Don't do it if being pushed by Nova */\r
46                                 if (nenhere != 0 && iattak != 2) {\r
47                                         newcnd();\r
48                                         for (l = 1; l <= nenhere; l++) {\r
49                                                 finald = sqrt((ix-kx[l])*(double)(ix-kx[l]) +\r
50                                                                           (iy-ky[l])*(double)(iy-ky[l]));\r
51                                                 kavgd[l] = 0.5 * (finald+kdist[l]);\r
52                                         }\r
53                                         if (d.galaxy[quadx][quady] != 1000) attack(0);\r
54                                         if (alldone) return;\r
55                                 }\r
56                                 /* compute final position -- new quadrant and sector */\r
57                                 x = 10*(quadx-1)+sectx;\r
58                                 y = 10*(quady-1)+secty;\r
59                                 ix = x+10.0*dist*bigger*deltax+0.5;\r
60                                 iy = y+10.0*dist*bigger*deltay+0.5;\r
61                                 /* check for edge of galaxy */\r
62                                 kinks = 0;\r
63                                 do {\r
64                                         kink = 0;\r
65                                         if (ix <= 0) {\r
66                                                 ix = -ix + 1;\r
67                                                 kink = 1;\r
68                                         }\r
69                                         if (iy <= 0) {\r
70                                                 iy = -iy + 1;\r
71                                                 kink = 1;\r
72                                         }\r
73                                         if (ix > 80) {\r
74                                                 ix = 161 - ix;\r
75                                                 kink = 1;\r
76                                         }\r
77                                         if (iy > 80) {\r
78                                                 iy = 161 - iy;\r
79                                                 kink = 1;\r
80                                         }\r
81                                         if (kink) kinks = 1;\r
82                                 } while (kink);\r
83 \r
84                                 if (kinks) {\r
85                                         nkinks += 1;\r
86                                         if (nkinks == 3) {\r
87                                                 /* Three strikes -- you're out! */\r
88                                                 finish(FNEG3);\r
89                                                 return;\r
90                                         }\r
91                                         prout("\nYOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER\n"\r
92                                                  "AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,\n"\r
93                                                  "YOU WILL BE DESTROYED.\n");\r
94                                 }\r
95                                 /* Compute final position in new quadrant */\r
96                                 if (trbeam) return; /* Don't bother if we are to be beamed */\r
97                                 quadx = (ix+9)/10;\r
98                                 quady = (iy+9)/10;\r
99                                 sectx = ix - 10*(quadx-1);\r
100                                 secty = iy - 10*(quady-1);\r
101                                 proutn("\nEntering");\r
102                                 cramlc(1, quadx, quady);\r
103                                 skip(1);\r
104                                 quad[sectx][secty] = ship;\r
105                                 newqad(0);\r
106                                 return;\r
107                         }\r
108                         iquad = quad[ix][iy];\r
109                         if (iquad != IHDOT) {\r
110                                 /* object encountered in flight path */\r
111                                 stopegy = 50.0*dist/Time;\r
112                                 dist=0.1*sqrt((sectx-ix)*(double)(sectx-ix) +\r
113                                                           (secty-iy)*(double)(secty-iy));\r
114                                 switch (iquad) {\r
115                                         case IHT: /* Ram a Tholian */\r
116                                         case IHK: /* Ram enemy ship */\r
117                                         case IHC:\r
118                                         case IHS:\r
119                                         case IHR:\r
120                                                 sectx = ix;\r
121                                                 secty = iy;\r
122                                                 ram(0, iquad, sectx, secty);\r
123                                                 finalx = sectx;\r
124                                                 finaly = secty;\r
125                                                 break;\r
126                                         case IHBLANK:\r
127                                                 skip(1);\r
128                                                 prouts("***RED ALERT!  RED ALERT!");\r
129                                                 skip(1);\r
130                                                 proutn("***");\r
131                                                 crmshp();\r
132                                                 proutn(" pulled into black hole at");\r
133                                                 cramlc(2, ix, iy);\r
134                                                 skip(1);\r
135                                                 finish(FHOLE);\r
136                                                 return;\r
137                                         default:\r
138                                                 /* something else */\r
139                                                 skip(1);\r
140                                                 crmshp();\r
141                                                 if (iquad == IHWEB)\r
142                                                         proutn(" encounters Tholian web at");\r
143                                                 else\r
144                                                         proutn(" blocked by object at");\r
145                                                 cramlc(2, ix,iy);\r
146                                                 prout(";");\r
147                                                 proutn("Emergency stop required ");\r
148                                                 cramf(stopegy, 0, 2);\r
149                                                 prout(" units of energy.");\r
150                                                 energy -= stopegy;\r
151                                                 finalx = x-deltax+0.5;\r
152                                                 sectx = finalx;\r
153                                                 finaly = y-deltay+0.5;\r
154                                                 secty = finaly;\r
155                                                 if (energy <= 0) {\r
156                                                         finish(FNRG);\r
157                                                         return;\r
158                                                 }\r
159                                                 break;\r
160                                 }\r
161                                 goto label100;  /* sorry! */\r
162                         }\r
163                 }\r
164                 dist = 0.1*sqrt((sectx-ix)*(double)(sectx-ix) +\r
165                                                 (secty-iy)*(double)(secty-iy));\r
166                 sectx = ix;\r
167                 secty = iy;\r
168         }\r
169         finalx = sectx;\r
170         finaly = secty;\r
171 label100:\r
172         /* No quadrant change -- compute new avg enemy distances */\r
173         quad[sectx][secty] = ship;\r
174         if (nenhere) {\r
175                 for (l = 1; l <= nenhere; l++) {\r
176                         finald = sqrt((ix-kx[l])*(double)(ix-kx[l]) +\r
177                                                   (iy-ky[l])*(double)(iy-ky[l]));\r
178                         kavgd[l] = 0.5 * (finald+kdist[l]);\r
179                         kdist[l] = finald;\r
180                 }\r
181                 sortkl();\r
182                 if (d.galaxy[quadx][quady] != 1000 && iattak == 0)\r
183                         attack(0);\r
184                 for (l = 1 ; l <= nenhere; l++) kavgd[l] = kdist[l];\r
185         }\r
186         newcnd();\r
187         iattak = 0;\r
188         return;\r
189 }\r
190 \r
191 void dock(void) {\r
192         chew();\r
193         if (condit == IHDOCKED) {\r
194                 prout("Already docked.");\r
195                 return;\r
196         }\r
197         if (inorbit) {\r
198                 prout("You must first leave standard orbit.");\r
199                 return;\r
200         }\r
201         if (basex==0 || abs(sectx-basex) > 1 || abs(secty-basey) > 1) {\r
202                 crmshp();\r
203                 prout(" not adjacent to base.");\r
204                 return;\r
205         }\r
206         condit = IHDOCKED;\r
207         prout("Docked.");\r
208         if (energy < inenrg) energy = inenrg;\r
209         shield = inshld;\r
210         torps = intorps;\r
211         lsupres = inlsr;\r
212         if (stdamtim != 1e30 &&\r
213                 (future[FCDBAS] < 1e30 || isatb == 1) && iseenit == 0) {\r
214                 /* get attack report from base */\r
215                 prout("Lt. Uhura- \"Captain, an important message from the starbase:\"");\r
216                 attakreport();\r
217                 iseenit = 1;\r
218         }\r
219 }\r
220 \r
221 static void getcd(int isprobe, int akey) {\r
222         /* This program originally required input in terms of a (clock)\r
223            direction and distance. Somewhere in history, it was changed to\r
224            cartesian coordinates. So we need to convert. I think\r
225            "manual" input should still be done this way -- it's a real\r
226            pain if the computer isn't working! Manual mode is still confusing\r
227            because it involves giving x and y motions, yet the coordinates\r
228            are always displayed y - x, where +y is downward! */\r
229 \r
230         \r
231         int irowq=quadx, icolq=quady, irows, icols, itemp=0, iprompt=0, key;\r
232         double xi, xj, xk, xl;\r
233         double deltax, deltay;\r
234         int automatic = -1;\r
235 \r
236         /* Get course direction and distance. If user types bad values, return\r
237            with DIREC = -1.0. */\r
238 \r
239         direc = -1.0;\r
240         \r
241         if (landed == 1 && !isprobe) {\r
242                 prout("Dummy! You can't leave standard orbit until you");\r
243                 proutn("are back abourt the ");\r
244                 crmshp();\r
245                 prout(".");\r
246                 chew();\r
247                 return;\r
248         }\r
249         while (automatic == -1) {\r
250                 if (damage[DCOMPTR]) {\r
251                         if (isprobe)\r
252                                 prout("Computer damaged; manual navigation only");\r
253                         else\r
254                                 prout("Computer damaged; manual movement only");\r
255                         chew();\r
256                         automatic = 0;\r
257                         key = IHEOL;\r
258                         break;\r
259                 }\r
260                 if (isprobe && akey != -1) {\r
261                         /* For probe launch, use pre-scaned value first time */\r
262                         key = akey;\r
263                         akey = -1;\r
264                 }\r
265                 else \r
266                         key = scan();\r
267 \r
268                 if (key == IHEOL) {\r
269                         proutn("Manual or automatic- ");\r
270                         iprompt = 1;\r
271                         chew();\r
272                 }\r
273                 else if (key == IHALPHA) {\r
274                         if (isit("manual")) {\r
275                                 automatic =0;\r
276                                 key = scan();\r
277                                 break;\r
278                         }\r
279                         else if (isit("automatic")) {\r
280                                 automatic = 1;\r
281                                 key = scan();\r
282                                 break;\r
283                         }\r
284                         else {\r
285                                 huh();\r
286                                 chew();\r
287                                 return;\r
288                         }\r
289                 }\r
290                 else { /* numeric */\r
291                         if (isprobe)\r
292                                 prout("(Manual navigation assumed.)");\r
293                         else\r
294                                 prout("(Manual movement assumed.)");\r
295                         automatic = 0;\r
296                         break;\r
297                 }\r
298         }\r
299 \r
300         if (automatic) {\r
301                 while (key == IHEOL) {\r
302                         if (isprobe)\r
303                                 proutn("Target quadrant or quadrant&sector- ");\r
304                         else\r
305                                 proutn("Destination sector or quadrant&sector- ");\r
306                         chew();\r
307                         iprompt = 1;\r
308                         key = scan();\r
309                 }\r
310 \r
311                 if (key != IHREAL) {\r
312                         huh();\r
313                         return;\r
314                 }\r
315                 xi = aaitem;\r
316                 key = scan();\r
317                 if (key != IHREAL){\r
318                         huh();\r
319                         return;\r
320                 }\r
321                 xj = aaitem;\r
322                 key = scan();\r
323                 if (key == IHREAL) {\r
324                         /* both quadrant and sector specified */\r
325                         xk = aaitem;\r
326                         key = scan();\r
327                         if (key != IHREAL) {\r
328                                 huh();\r
329                                 return;\r
330                         }\r
331                         xl = aaitem;\r
332 \r
333                         irowq = xi + 0.5;\r
334                         icolq = xj + 0.5;\r
335                         irows = xk + 0.5;\r
336                         icols = xl + 0.5;\r
337                 }\r
338                 else {\r
339                         if (isprobe) {\r
340                                 /* only quadrant specified -- go to center of dest quad */\r
341                                 irowq = xi + 0.5;\r
342                                 icolq = xj + 0.5;\r
343                                 irows = icols = 5;\r
344                         }\r
345                         else {\r
346                                 irows = xi + 0.5;\r
347                                 icols = xj + 0.5;\r
348                         }\r
349                         itemp = 1;\r
350                 }\r
351                 if (irowq<1 || irowq > 8 || icolq<1 || icolq > 8 ||\r
352                         irows<1 || irows > 10 || icols<1 || icols > 10) {\r
353                                 huh();\r
354                                 return;\r
355                         }\r
356                 skip(1);\r
357                 if (!isprobe) {\r
358                         if (itemp) {\r
359                                 if (iprompt) {\r
360                                         proutn("Helmsman Sulu- \"Course locked in for");\r
361                                         cramlc(2, irows, icols);\r
362                                         prout(".\"");\r
363                                 }\r
364                         }\r
365                         else prout("Ensign Chekov- \"Course laid in, Captain.\"");\r
366                 }\r
367                 deltax = icolq - quady + 0.1*(icols-secty);\r
368                 deltay = quadx - irowq + 0.1*(sectx-irows);\r
369         }\r
370         else { /* manual */\r
371                 while (key == IHEOL) {\r
372                         proutn("X and Y displacements- ");\r
373                         chew();\r
374                         iprompt = 1;\r
375                         key = scan();\r
376                 }\r
377                 itemp = 2;\r
378                 if (key != IHREAL) {\r
379                         huh();\r
380                         return;\r
381                 }\r
382                 deltax = aaitem;\r
383                 key = scan();\r
384                 if (key != IHREAL) {\r
385                         huh();\r
386                         return;\r
387                 }\r
388                 deltay = aaitem;\r
389         }\r
390         /* Check for zero movement */\r
391         if (deltax == 0 && deltay == 0) {\r
392                 chew();\r
393                 return;\r
394         }\r
395         if (itemp == 2 && !isprobe) {\r
396                 skip(1);\r
397                 prout("Helmsman Sulu- \"Aye, Sir.\"");\r
398         }\r
399         dist = sqrt(deltax*deltax + deltay*deltay);\r
400         direc = atan2(deltax, deltay)*1.90985932;\r
401         if (direc < 0.0) direc += 12.0;\r
402         chew();\r
403         return;\r
404 \r
405 }\r
406                 \r
407 \r
408 \r
409 void impuls(void) {\r
410         double power;\r
411 \r
412         ididit = 0;\r
413         if (damage[DIMPULS]) {\r
414                 chew();\r
415                 skip(1);\r
416                 prout("Engineer Scott- \"The impulse engines are damaged, Sir.\"");\r
417                 return;\r
418         }\r
419 \r
420         if (energy > 30.0) {\r
421                 getcd(FALSE, 0);\r
422                 if (direc == -1.0) return;\r
423                 power = 20.0 + 100.0*dist;\r
424         }\r
425         else\r
426                 power = 30.0;\r
427 \r
428         if (power >= energy) {\r
429                 /* Insufficient power for trip */\r
430                 skip(1);\r
431                 prout("First Officer Spock- \"Captain, the impulse engines");\r
432                 prout("require 20.0 units to engage, plus 100.0 units per");\r
433                 if (energy > 30) {\r
434                         proutn("quadrant.  We can go, therefore, a maximum of ");\r
435                         cramf(0.01 * (energy-20.0)-0.05, 0, 1);\r
436                         prout(" quadrants.\"");\r
437                 }\r
438                 else {\r
439                         prout("quadrant.  They are, therefore, useless.\"");\r
440                 }\r
441                 chew();\r
442                 return;\r
443         }\r
444         /* Make sure enough time is left for the trip */\r
445         Time = dist/0.095;\r
446         if (Time >= d.remtime) {\r
447                 prout("First Officer Spock- \"Captain, our speed under impulse");\r
448                 prout("power is only 0.95 sectors per stardate. Are you sure");\r
449                 prout("we dare spend the time?\"");\r
450                 if (ja() == 0) return;\r
451         }\r
452         /* Activate impulse engines and pay the cost */\r
453         move();\r
454         ididit = 1;\r
455         if (alldone) return;\r
456         power = 20.0 + 100.0*dist;\r
457         energy -= power;\r
458         Time = dist/0.095;\r
459         if (energy <= 0) finish(FNRG);\r
460         return;\r
461 }\r
462 \r
463 \r
464 void warp(int i) {\r
465         int blooey=0, twarp=0, iwarp;\r
466         double power;\r
467 \r
468         if (i!=2) { /* Not WARPX entry */\r
469                 ididit = 0;\r
470                 if (damage[DWARPEN] > 10.0) {\r
471                         chew();\r
472                         skip(1);\r
473                         prout("Engineer Scott- \"The impulse engines are damaged, Sir.\"");\r
474                         return;\r
475                 }\r
476                 if (damage[DWARPEN] > 0.0 && warpfac > 4.0) {\r
477                         chew();\r
478                         skip(1);\r
479                         prout("Engineer Scott- \"Sorry, Captain. Until this damage");\r
480                         prout("  is repaired, I can only give you warp 4.\"");\r
481                         return;\r
482                 }\r
483                         \r
484                 /* Read in course and distance */\r
485                 getcd(FALSE, 0);\r
486                 if (direc == -1.0) return;\r
487 \r
488                 /* Make sure starship has enough energy for the trip */\r
489                 power = (dist+0.05)*warpfac*warpfac*warpfac*(shldup+1);\r
490 \r
491 \r
492                 if (power >= energy) {\r
493                         /* Insufficient power for trip */\r
494                         ididit = 0;\r
495                         skip(1);\r
496                         prout("Engineering to bridge--");\r
497                         if (shldup==0 || 0.5*power > energy) {\r
498                                 iwarp = pow((energy/(dist+0.05)), 0.333333333);\r
499                                 if (iwarp <= 0) {\r
500                                         prout("We can't do it, Captain. We haven't the energy.");\r
501                                 }\r
502                                 else {\r
503                                         proutn("We haven't the energy, but we could do it at warp ");\r
504                                         crami(iwarp, 1);\r
505                                         if (shldup)\r
506                                                 prout(",\nif you'll lower the shields.");\r
507                                         else\r
508                                                 prout(".");\r
509                                 }\r
510                         }\r
511                         else\r
512                                 prout("We haven't the energy to go that far with the shields up.");\r
513                         return;\r
514                 }\r
515                                                 \r
516                 /* Make sure enough time is left for the trip */\r
517                 Time = 10.0*dist/wfacsq;\r
518                 if (Time >= 0.8*d.remtime) {\r
519                         skip(1);\r
520                         prout("First Officer Spock- \"Captain, I compute that such");\r
521                         proutn("  a trip would require approximately ");\r
522                         cramf(100.0*Time/d.remtime, 0, 2);\r
523                         prout(" percent of our");\r
524                         prout(" remaining time.  Are you sure this is wise?\"");\r
525                         if (ja() == 0) { ididit = 0; return;}\r
526                 }\r
527         }\r
528         /* Entry WARPX */\r
529         if (warpfac > 6.0) {\r
530                 /* Decide if engine damage will occur */\r
531                 double prob = dist*(6.0-warpfac)*(6.0-warpfac)/66.666666666;\r
532                 if (prob > Rand()) {\r
533                         blooey = 1;\r
534                         dist = Rand()*dist;\r
535                 }\r
536                 /* Decide if time warp will occur */\r
537                 if (0.5*dist*pow(7.0,warpfac-10.0) > Rand()) twarp=1;\r
538 #ifdef DEBUG\r
539                 if (idebug &&warpfac==10 && twarp==0) {\r
540                         blooey=0;\r
541                         proutn("Force time warp? ");\r
542                         if (ja()==1) twarp=1;\r
543                 }\r
544 #endif\r
545                 if (blooey || twarp) {\r
546                         /* If time warp or engine damage, check path */\r
547                         /* If it is obstructed, don't do warp or damage */\r
548                         double angle = ((15.0-direc)*0.5235998);\r
549                         double deltax = -sin(angle);\r
550                         double deltay = cos(angle);\r
551                         double bigger, x, y;\r
552                         int n, l, ix, iy;\r
553                         if (fabs(deltax) > fabs(deltay))\r
554                                 bigger = fabs(deltax);\r
555                         else\r
556                                 bigger = fabs(deltay);\r
557                         \r
558                         deltax /= bigger;\r
559                         deltay /= bigger;\r
560                         n = 10.0 * dist * bigger +0.5;\r
561                         x = sectx;\r
562                         y = secty;\r
563                         for (l = 1; l <= n; l++) {\r
564                                 x += deltax;\r
565                                 ix = x + 0.5;\r
566                                 if (ix < 1 || ix > 10) break;\r
567                                 y += deltay;\r
568                                 iy = y +0.5;\r
569                                 if (iy < 1 || iy > 10) break;\r
570                                 if (quad[ix][iy] != IHDOT) {\r
571                                         blooey = 0;\r
572                                         twarp = 0;\r
573                                 }\r
574                         }\r
575                 }\r
576         }\r
577                                 \r
578 \r
579         /* Activate Warp Engines and pay the cost */\r
580         move();\r
581         if (alldone) return;\r
582         energy -= dist*warpfac*warpfac*warpfac*(shldup+1);\r
583         if (energy <= 0) finish(FNRG);\r
584         Time = 10.0*dist/wfacsq;\r
585         if (twarp) timwrp();\r
586         if (blooey) {\r
587                 damage[DWARPEN] = damfac*(3.0*Rand()+1.0);\r
588                 skip(1);\r
589                 prout("Engineering to bridge--");\r
590                 prout("  Scott here.  The warp engines are damaged.");\r
591                 prout("  We'll have to reduce speed to warp 4.");\r
592         }\r
593         ididit = 1;\r
594         return;\r
595 }\r
596 \r
597 \r
598 \r
599 void setwrp(void) {\r
600         int key;\r
601         double oldfac;\r
602         \r
603         while ((key=scan()) == IHEOL) {\r
604                 chew();\r
605                 proutn("Warp factor-");\r
606         }\r
607         chew();\r
608         if (key != IHREAL) {\r
609                 huh();\r
610                 return;\r
611         }\r
612         if (damage[DWARPEN] > 10.0) {\r
613                 prout("Warp engines inoperative.");\r
614                 return;\r
615         }\r
616         if (damage[DWARPEN] > 0.0 && aaitem > 4.0) {\r
617                 prout("Engineer Scott- \"I'm doing my best, Captain,\n"\r
618                           "  but right now we can only go warp 4.\"");\r
619                 return;\r
620         }\r
621         if (aaitem > 10.0) {\r
622                 prout("Helmsman Sulu- \"Our top speed is warp 10, Captain.\"");\r
623                 return;\r
624         }\r
625         if (aaitem < 1.0) {\r
626                 prout("Helmsman Sulu- \"We can't go below warp 1, Captain.\"");\r
627                 return;\r
628         }\r
629         oldfac = warpfac;\r
630         warpfac = aaitem;\r
631         wfacsq=warpfac*warpfac;\r
632         if (warpfac <= oldfac || warpfac <= 6.0) {\r
633                 proutn("Helmsman Sulu- \"Warp factor ");\r
634                 cramf(warpfac, 0, 1);\r
635                 prout(", Captain.\"");\r
636                 return;\r
637         }\r
638         if (warpfac < 8.00) {\r
639                 prout("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\"");\r
640                 return;\r
641         }\r
642         if (warpfac == 10.0) {\r
643                 prout("Engineer Scott- \"Aye, Captain, we'll try it.\"");\r
644                 return;\r
645         }\r
646         prout("Engineer Scott- \"Aye, Captain, but our engines may not take it.\"");\r
647         return;\r
648 }\r
649 \r
650 void atover(int igrab) {\r
651         double power, distreq;\r
652 \r
653         chew();\r
654         /* is captain on planet? */\r
655         if (landed==1) {\r
656                 if (damage[DTRANSP]) {\r
657                         finish(FPNOVA);\r
658                         return;\r
659                 }\r
660                 prout("Scotty rushes to the transporter controls.");\r
661                 if (shldup) {\r
662                         prout("But with the shields up it's hopeless.");\r
663                         finish(FPNOVA);\r
664                 }\r
665                 prouts("His desperate attempt to rescue you . . .");\r
666                 if (Rand() <= 0.5) {\r
667                         prout("fails.");\r
668                         finish(FPNOVA);\r
669                         return;\r
670                 }\r
671                 prout("SUCCEEDS!");\r
672                 if (imine) {\r
673                         imine = 0;\r
674                         proutn("The crystals mined were ");\r
675                         if (Rand() <= 0.25) {\r
676                                 prout("lost.");\r
677                         }\r
678                         else {\r
679                                 prout("saved.");\r
680                                 icrystl = 1;\r
681                         }\r
682                 }\r
683         }\r
684         if (igrab) return;\r
685 \r
686         /* Check to see if captain in shuttle craft */\r
687         if (icraft) finish(FSTRACTOR);\r
688         if (alldone) return;\r
689 \r
690         /* Inform captain of attempt to reach safety */\r
691         skip(1);\r
692         do {\r
693                 if (justin) {\r
694                         prouts("***RED ALERT!  READ ALERT!");\r
695                         skip(1);\r
696                         proutn("The ");\r
697                         crmshp();\r
698                         prout(" has stopped in a quadrant containing");\r
699                         prouts("   a supernova.");\r
700                         skip(2);\r
701                 }\r
702                 proutn("***Emergency automatic override attempts to hurl ");\r
703                 crmshp();\r
704                 skip(1);\r
705                 prout("safely out of quadrant.");\r
706                 starch[quadx][quady] = damage[DRADIO] > 0.0 ? d.galaxy[quadx][quady]+1000:1;\r
707 \r
708                 /* Try to use warp engines */\r
709                 if (damage[DWARPEN]) {\r
710                         skip(1);\r
711                         prout("Warp engines damaged.");\r
712                         finish(FSNOVAED);\r
713                         return;\r
714                 }\r
715                 warpfac = 6.0+2.0*Rand();\r
716                 wfacsq = warpfac * warpfac;\r
717                 proutn("Warp factor set to ");\r
718                 cramf(warpfac, 1, 1);\r
719                 skip(1);\r
720                 power = 0.75*energy;\r
721                 dist = power/(warpfac*warpfac*warpfac*(shldup+1));\r
722                 distreq = 1.4142+Rand();\r
723                 if (distreq < dist) dist = distreq;\r
724                 Time = 10.0*dist/wfacsq;\r
725                 direc = 12.0*Rand();    /* How dumb! */\r
726                 justin = 0;\r
727                 inorbit = 0;\r
728                 warp(2);\r
729                 if (justin == 0) {\r
730                         /* This is bad news, we didn't leave quadrant. */\r
731                         if (alldone) return;\r
732                         skip(1);\r
733                         prout("Insufficient energy to leave quadrant.");\r
734                         finish(FSNOVAED);\r
735                         return;\r
736                 }\r
737                 /* Repeat if another snova */\r
738         } while (d.galaxy[quadx][quady] == 1000);\r
739         if (d.remkl==0) finish(FWON); /* Snova killed remaining enemy. */\r
740 }\r
741 \r
742 void timwrp() {\r
743         int l, ll, gotit;\r
744         prout("***TIME WARP ENTERED.");\r
745         if (d.snap && Rand() < 0.5) {\r
746                 /* Go back in time */\r
747                 proutn("You are traveling backwards in time ");\r
748                 cramf(d.date-snapsht.date, 0, 2);\r
749                 prout(" stardates.");\r
750                 d = snapsht;\r
751                 d.snap = 0;\r
752                 if (d.remcom) {\r
753                         future[FTBEAM] = d.date + expran(intime/d.remcom);\r
754                         future[FBATTAK] = d.date + expran(0.3*intime);\r
755                 }\r
756                 future[FSNOVA] = d.date + expran(0.5*intime);\r
757                 future[FSNAP] = d.date +expran(0.25*d.remtime); /* next snapshot will\r
758                                                                                                            be sooner */\r
759                 if (d.nscrem) future[FSCMOVE] = 0.2777;\r
760                 isatb = 0;\r
761                 future[FCDBAS] = future[FSCDBAS] = 1e30;\r
762                 batx = baty = 0;\r
763 \r
764                 /* Make sure Galileo is consistant -- Snapshot may have been taken\r
765                    when on planet, which would give us two Galileos! */\r
766                 gotit = 0;\r
767                 for (l = 1; l <= inplan; l++) {\r
768                         if (d.plnets[l].known == 2) {\r
769                                 gotit = 1;\r
770                                 if (iscraft==1 && ship==IHE) {\r
771                                         prout("Checkov-  \"Security reports the Galileo has disappeared, Sir!");\r
772                                         iscraft = 0;\r
773                                 }\r
774                         }\r
775                 }\r
776                 /* Likewise, if in the original time the Galileo was abandoned, but\r
777                    was on ship earlier, it would have vanished -- lets restore it */\r
778                 if (iscraft==0 && gotit==0 && damage[DSHUTTL] >= 0.0) {\r
779                         prout("Checkov-  \"Security reports the Galileo has reappeared in the dock!\"");\r
780                         iscraft = 1;\r
781                 }\r
782 \r
783                 /* Revert star chart to earlier era, if it was known then*/\r
784                 if (damage[DRADIO]==0.0 || stdamtim > d.date) {\r
785                         for (l = 1; l <= 8; l++)\r
786                                 for (ll = 1; ll <= 8; ll++)\r
787                                         if (starch[l][ll] > 1)\r
788                                                 starch[l][ll]=damage[DRADIO]>0.0 ? d.galaxy[l][ll]+1000 :1;\r
789                         prout("Spock has reconstructed a correct star chart from memory");\r
790                         if (damage[DRADIO] > 0.0) stdamtim = d.date;\r
791                 }\r
792         }\r
793         else {\r
794                 /* Go forward in time */\r
795                 Time = -0.5*intime*log(Rand());\r
796                 proutn("You are traveling forward in time ");\r
797                 cramf(Time, 1, 2);\r
798                 prout(" stardates.");\r
799                 /* cheat to make sure no tractor beams occur during time warp */\r
800                 future[FTBEAM] += Time;\r
801                 damage[DRADIO] += Time;\r
802         }\r
803         newqad(0);\r
804 }\r
805 \r
806 void probe(void) {\r
807         double angle, bigger;\r
808         int key;\r
809         /* New code to launch a deep space probe */\r
810         if (nprobes == 0) {\r
811                 chew();\r
812                 skip(1);\r
813                 if (ship == IHE) \r
814                         prout("Engineer Scott- \"We have no more deep space probes, Sir.\"");\r
815                 else\r
816                         prout("Ye Faerie Queene has no deep space probes.");\r
817                 return;\r
818         }\r
819         if (damage[DDSP] != 0.0) {\r
820                 chew();\r
821                 skip(1);\r
822                 prout("Engineer Scott- \"The probe launcher is damaged, Sir.\"");\r
823                 return;\r
824         }\r
825         if (future[FDSPROB] != 1e30) {\r
826                 chew();\r
827                 skip(1);\r
828                 if (damage[DRADIO] != 0 && condit != IHDOCKED) {\r
829                         prout("Spock-  \"Records show the previous probe has not yet");\r
830                         prout("   reached its destination.\"");\r
831                 }\r
832                 else\r
833                         prout("Uhura- \"The previous probe is still reporting data, Sir.\"");\r
834                 return;\r
835         }\r
836         key = scan();\r
837 \r
838         if (key == IHEOL) {\r
839                 /* slow mode, so let Kirk know how many probes there are left */\r
840                 crami(nprobes,1);\r
841                 prout(nprobes==1 ? " probe left." : " probes left.");\r
842                 proutn("Are you sure you want to fire a probe? ");\r
843                 if (ja()==0) return;\r
844         }\r
845 \r
846         isarmed = FALSE;\r
847         if (key == IHALPHA && strcmp(citem,"armed") == 0) {\r
848                 isarmed = TRUE;\r
849                 key = scan();\r
850         }\r
851         else if (key == IHEOL) {\r
852                 proutn("Arm NOVAMAX warhead?");\r
853                 isarmed = ja();\r
854         }\r
855         getcd(TRUE, key);\r
856         if (direc == -1.0) return;\r
857         nprobes--;\r
858                 angle = ((15.0 - direc) * 0.5235988);\r
859         probeinx = -sin(angle);\r
860         probeiny = cos(angle);\r
861         if (fabs(probeinx) > fabs(probeiny))\r
862                 bigger = fabs(probeinx);\r
863         else\r
864                 bigger = fabs(probeiny);\r
865                 \r
866         probeiny /= bigger;\r
867         probeinx /= bigger;\r
868         proben = 10.0*dist*bigger +0.5;\r
869         probex = quadx*10 + sectx - 1;  // We will use better packing than original\r
870         probey = quady*10 + secty - 1;\r
871         probecx = quadx;\r
872         probecy = quady;\r
873         future[FDSPROB] = d.date + 0.01; // Time to move one sector\r
874         prout("Ensign Chekov-  \"The deep space probe is launched, Captain.\"");\r
875         return;\r
876 }\r
877 \r
878 void help(void) {\r
879         /* There's more than one way to move in this game! */\r
880         double ddist, xdist, probf;\r
881         int line, l, ix, iy;\r
882 \r
883         chew();\r
884         /* Test for conditions which prevent calling for help */\r
885         if (condit == IHDOCKED) {\r
886                 prout("Lt. Uhura-  \"But Captain, we're already docked.\"");\r
887                 return;\r
888         }\r
889         if (damage[DRADIO] != 0) {\r
890                 prout("Subspace radio damaged.");\r
891                 return;\r
892         }\r
893         if (d.rembase==0) {\r
894                 prout("Lt. Uhura-  \"Captain, I'm not getting any response from Starbase.\"");\r
895                 return;\r
896         }\r
897         if (landed == 1) {\r
898                 proutn("You must be aboard the ");\r
899                 crmshp();\r
900                 prout(".");\r
901                 return;\r
902         }\r
903         /* OK -- call for help from nearest starbase */\r
904         nhelp++;\r
905         if (basex!=0) {\r
906                 /* There's one in this quadrant */\r
907                 ddist = sqrt(square(basex-sectx)+square(basey-secty));\r
908         }\r
909         else {\r
910                 ddist = 1e30;\r
911                 for (l = 1; l <= d.rembase; l++) {\r
912                         xdist=10.0*sqrt(square(d.baseqx[l]-quadx)+square(d.baseqy[l]-quady));\r
913                         if (xdist < ddist) {\r
914                                 ddist = xdist;\r
915                                 line = l;\r
916                         }\r
917                 }\r
918                 /* Since starbase not in quadrant, set up new quadrant */\r
919                 quadx = d.baseqx[line];\r
920                 quady = d.baseqy[line];\r
921                 newqad(1);\r
922         }\r
923         /* dematerialize starship */\r
924         quad[sectx][secty]=IHDOT;\r
925         proutn("Starbase in");\r
926         cramlc(1, quadx, quady);\r
927         proutn(" responds--");\r
928         crmshp();\r
929         prout(" dematerializes.");\r
930         /* Give starbase three chances to rematerialize starship */\r
931         probf = pow((1.0 - pow(0.98,ddist)), 0.33333333);\r
932         for (l = 1; l <= 3; l++) {\r
933                 switch (l) {\r
934                         case 1: proutn("1st"); break;\r
935                         case 2: proutn("2nd"); break;\r
936                         case 3: proutn("3rd"); break;\r
937                 }\r
938                 proutn(" attempt to re-materialize ");\r
939                 crmshp();\r
940                 prouts(" . . . . . ");\r
941                 if (Rand() > probf) break;\r
942                 prout("fails.");\r
943         }\r
944         if (l > 3) {\r
945                 finish(FMATERIALIZE);\r
946                 return;\r
947         }\r
948         /* Rematerialization attempt should succeed if can get adj to base */\r
949         for (l = 1; l <= 5; l++) {\r
950                 ix = basex+3.0*Rand()-1;\r
951                 iy = basey+3.0*Rand()-1;\r
952                 if (ix>=1 && ix<=10 && iy>=1 && iy<=10 && quad[ix][iy]==IHDOT) {\r
953                         /* found one -- finish up */\r
954                         prout("succeeds.");\r
955                         sectx=ix;\r
956                         secty=iy;\r
957                         quad[ix][iy]=ship;\r
958                         dock();\r
959                         skip(1);\r
960                         prout("Lt. Uhura-  \"Captain, we made it!\"");\r
961                         return;\r
962                 }\r
963         }\r
964         finish(FMATERIALIZE);\r
965         return;\r
966 }\r