printfs have been banished. All outputnow goes through prout/proutn/prouts.
[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 (game.state.date+Time >= game.future[FTBEAM]) {\r
28                 trbeam = 1;\r
29                 condit = IHRED;\r
30                 dist = dist*(game.future[FTBEAM]-game.state.date)/Time + 0.1;\r
31                 Time = game.future[FTBEAM] - game.state.date + 1e-5;\r
32         }\r
33         /* Move within the quadrant */\r
34         game.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-game.kx[l])*(double)(ix-game.kx[l]) +\r
50                                                                           (iy-game.ky[l])*(double)(iy-game.ky[l]));\r
51                                                 game.kavgd[l] = 0.5 * (finald+game.kdist[l]);\r
52                                         }\r
53                                         if (game.state.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                                 game.quad[sectx][secty] = ship;\r
105                                 newqad(0);\r
106                                 return;\r
107                         }\r
108                         iquad = game.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         game.quad[sectx][secty] = ship;\r
174         if (nenhere) {\r
175                 for (l = 1; l <= nenhere; l++) {\r
176                         finald = sqrt((ix-game.kx[l])*(double)(ix-game.kx[l]) +\r
177                                                   (iy-game.ky[l])*(double)(iy-game.ky[l]));\r
178                         game.kavgd[l] = 0.5 * (finald+game.kdist[l]);\r
179                         game.kdist[l] = finald;\r
180                 }\r
181                 sortkl();\r
182                 if (game.state.galaxy[quadx][quady] != 1000 && iattak == 0)\r
183                         attack(0);\r
184                 for (l = 1 ; l <= nenhere; l++) game.kavgd[l] = game.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                 (game.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 (game.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 (game.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 >= game.state.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 (game.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 (game.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 %d", iwarp);\r
504                                         if (shldup) {\r
505                                                 prout(",");\r
506                                                 prout("if you'll lower the shields.");\r
507                                         }\r
508                                         else\r
509                                                 prout(".");\r
510                                 }\r
511                         }\r
512                         else\r
513                                 prout("We haven't the energy to go that far with the shields up.");\r
514                         return;\r
515                 }\r
516                                                 \r
517                 /* Make sure enough time is left for the trip */\r
518                 Time = 10.0*dist/wfacsq;\r
519                 if (Time >= 0.8*game.state.remtime) {\r
520                         skip(1);\r
521                         prout("First Officer Spock- \"Captain, I compute that such");\r
522                         proutn("  a trip would require approximately ");\r
523                         cramf(100.0*Time/game.state.remtime, 0, 2);\r
524                         prout(" percent of our");\r
525                         prout(" remaining time.  Are you sure this is wise?\"");\r
526                         if (ja() == 0) { ididit = 0; return;}\r
527                 }\r
528         }\r
529         /* Entry WARPX */\r
530         if (warpfac > 6.0) {\r
531                 /* Decide if engine damage will occur */\r
532                 double prob = dist*(6.0-warpfac)*(6.0-warpfac)/66.666666666;\r
533                 if (prob > Rand()) {\r
534                         blooey = 1;\r
535                         dist = Rand()*dist;\r
536                 }\r
537                 /* Decide if time warp will occur */\r
538                 if (0.5*dist*pow(7.0,warpfac-10.0) > Rand()) twarp=1;\r
539 #ifdef DEBUG\r
540                 if (idebug &&warpfac==10 && twarp==0) {\r
541                         blooey=0;\r
542                         proutn("Force time warp? ");\r
543                         if (ja()==1) twarp=1;\r
544                 }\r
545 #endif\r
546                 if (blooey || twarp) {\r
547                         /* If time warp or engine damage, check path */\r
548                         /* If it is obstructed, don't do warp or damage */\r
549                         double angle = ((15.0-direc)*0.5235998);\r
550                         double deltax = -sin(angle);\r
551                         double deltay = cos(angle);\r
552                         double bigger, x, y;\r
553                         int n, l, ix, iy;\r
554                         if (fabs(deltax) > fabs(deltay))\r
555                                 bigger = fabs(deltax);\r
556                         else\r
557                                 bigger = fabs(deltay);\r
558                         \r
559                         deltax /= bigger;\r
560                         deltay /= bigger;\r
561                         n = 10.0 * dist * bigger +0.5;\r
562                         x = sectx;\r
563                         y = secty;\r
564                         for (l = 1; l <= n; l++) {\r
565                                 x += deltax;\r
566                                 ix = x + 0.5;\r
567                                 if (ix < 1 || ix > 10) break;\r
568                                 y += deltay;\r
569                                 iy = y +0.5;\r
570                                 if (iy < 1 || iy > 10) break;\r
571                                 if (game.quad[ix][iy] != IHDOT) {\r
572                                         blooey = 0;\r
573                                         twarp = 0;\r
574                                 }\r
575                         }\r
576                 }\r
577         }\r
578                                 \r
579 \r
580         /* Activate Warp Engines and pay the cost */\r
581         move();\r
582         if (alldone) return;\r
583         energy -= dist*warpfac*warpfac*warpfac*(shldup+1);\r
584         if (energy <= 0) finish(FNRG);\r
585         Time = 10.0*dist/wfacsq;\r
586         if (twarp) timwrp();\r
587         if (blooey) {\r
588                 game.damage[DWARPEN] = damfac*(3.0*Rand()+1.0);\r
589                 skip(1);\r
590                 prout("Engineering to bridge--");\r
591                 prout("  Scott here.  The warp engines are damaged.");\r
592                 prout("  We'll have to reduce speed to warp 4.");\r
593         }\r
594         ididit = 1;\r
595         return;\r
596 }\r
597 \r
598 \r
599 \r
600 void setwrp(void) {\r
601         int key;\r
602         double oldfac;\r
603         \r
604         while ((key=scan()) == IHEOL) {\r
605                 chew();\r
606                 proutn("Warp factor-");\r
607         }\r
608         chew();\r
609         if (key != IHREAL) {\r
610                 huh();\r
611                 return;\r
612         }\r
613         if (game.damage[DWARPEN] > 10.0) {\r
614                 prout("Warp engines inoperative.");\r
615                 return;\r
616         }\r
617         if (game.damage[DWARPEN] > 0.0 && aaitem > 4.0) {\r
618                 prout("Engineer Scott- \"I'm doing my best, Captain,\n"\r
619                           "  but right now we can only go warp 4.\"");\r
620                 return;\r
621         }\r
622         if (aaitem > 10.0) {\r
623                 prout("Helmsman Sulu- \"Our top speed is warp 10, Captain.\"");\r
624                 return;\r
625         }\r
626         if (aaitem < 1.0) {\r
627                 prout("Helmsman Sulu- \"We can't go below warp 1, Captain.\"");\r
628                 return;\r
629         }\r
630         oldfac = warpfac;\r
631         warpfac = aaitem;\r
632         wfacsq=warpfac*warpfac;\r
633         if (warpfac <= oldfac || warpfac <= 6.0) {\r
634                 proutn("Helmsman Sulu- \"Warp factor ");\r
635                 cramf(warpfac, 0, 1);\r
636                 prout(", Captain.\"");\r
637                 return;\r
638         }\r
639         if (warpfac < 8.00) {\r
640                 prout("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\"");\r
641                 return;\r
642         }\r
643         if (warpfac == 10.0) {\r
644                 prout("Engineer Scott- \"Aye, Captain, we'll try it.\"");\r
645                 return;\r
646         }\r
647         prout("Engineer Scott- \"Aye, Captain, but our engines may not take it.\"");\r
648         return;\r
649 }\r
650 \r
651 void atover(int igrab) {\r
652         double power, distreq;\r
653 \r
654         chew();\r
655         /* is captain on planet? */\r
656         if (landed==1) {\r
657                 if (game.damage[DTRANSP]) {\r
658                         finish(FPNOVA);\r
659                         return;\r
660                 }\r
661                 prout("Scotty rushes to the transporter controls.");\r
662                 if (shldup) {\r
663                         prout("But with the shields up it's hopeless.");\r
664                         finish(FPNOVA);\r
665                 }\r
666                 prouts("His desperate attempt to rescue you . . .");\r
667                 if (Rand() <= 0.5) {\r
668                         prout("fails.");\r
669                         finish(FPNOVA);\r
670                         return;\r
671                 }\r
672                 prout("SUCCEEDS!");\r
673                 if (imine) {\r
674                         imine = 0;\r
675                         proutn("The crystals mined were ");\r
676                         if (Rand() <= 0.25) {\r
677                                 prout("lost.");\r
678                         }\r
679                         else {\r
680                                 prout("saved.");\r
681                                 icrystl = 1;\r
682                         }\r
683                 }\r
684         }\r
685         if (igrab) return;\r
686 \r
687         /* Check to see if captain in shuttle craft */\r
688         if (icraft) finish(FSTRACTOR);\r
689         if (alldone) return;\r
690 \r
691         /* Inform captain of attempt to reach safety */\r
692         skip(1);\r
693         do {\r
694                 if (justin) {\r
695                         prouts("***RED ALERT!  READ ALERT!");\r
696                         skip(1);\r
697                         proutn("The ");\r
698                         crmshp();\r
699                         prout(" has stopped in a quadrant containing");\r
700                         prouts("   a supernova.");\r
701                         skip(2);\r
702                 }\r
703                 proutn("***Emergency automatic override attempts to hurl ");\r
704                 crmshp();\r
705                 skip(1);\r
706                 prout("safely out of quadrant.");\r
707                 game.starch[quadx][quady] = game.damage[DRADIO] > 0.0 ? game.state.galaxy[quadx][quady]+1000:1;\r
708 \r
709                 /* Try to use warp engines */\r
710                 if (game.damage[DWARPEN]) {\r
711                         skip(1);\r
712                         prout("Warp engines damaged.");\r
713                         finish(FSNOVAED);\r
714                         return;\r
715                 }\r
716                 warpfac = 6.0+2.0*Rand();\r
717                 wfacsq = warpfac * warpfac;\r
718                 proutn("Warp factor set to ");\r
719                 cramf(warpfac, 1, 1);\r
720                 skip(1);\r
721                 power = 0.75*energy;\r
722                 dist = power/(warpfac*warpfac*warpfac*(shldup+1));\r
723                 distreq = 1.4142+Rand();\r
724                 if (distreq < dist) dist = distreq;\r
725                 Time = 10.0*dist/wfacsq;\r
726                 direc = 12.0*Rand();    /* How dumb! */\r
727                 justin = 0;\r
728                 inorbit = 0;\r
729                 warp(2);\r
730                 if (justin == 0) {\r
731                         /* This is bad news, we didn't leave quadrant. */\r
732                         if (alldone) return;\r
733                         skip(1);\r
734                         prout("Insufficient energy to leave quadrant.");\r
735                         finish(FSNOVAED);\r
736                         return;\r
737                 }\r
738                 /* Repeat if another snova */\r
739         } while (game.state.galaxy[quadx][quady] == 1000);\r
740         if (game.state.remkl==0) finish(FWON); /* Snova killed remaining enemy. */\r
741 }\r
742 \r
743 void timwrp() {\r
744         int l, ll, gotit;\r
745         prout("***TIME WARP ENTERED.");\r
746         if (game.state.snap && Rand() < 0.5) {\r
747                 /* Go back in time */\r
748                 proutn("You are traveling backwards in time ");\r
749                 cramf(game.state.date-game.snapsht.date, 0, 2);\r
750                 prout(" stardates.");\r
751                 game.state = game.snapsht;\r
752                 game.state.snap = 0;\r
753                 if (game.state.remcom) {\r
754                         game.future[FTBEAM] = game.state.date + expran(intime/game.state.remcom);\r
755                         game.future[FBATTAK] = game.state.date + expran(0.3*intime);\r
756                 }\r
757                 game.future[FSNOVA] = game.state.date + expran(0.5*intime);\r
758                 game.future[FSNAP] = game.state.date +expran(0.25*game.state.remtime); /* next snapshot will\r
759                                                                                                            be sooner */\r
760                 if (game.state.nscrem) game.future[FSCMOVE] = 0.2777;\r
761                 isatb = 0;\r
762                 game.future[FCDBAS] = game.future[FSCDBAS] = 1e30;\r
763                 batx = baty = 0;\r
764 \r
765                 /* Make sure Galileo is consistant -- Snapshot may have been taken\r
766                    when on planet, which would give us two Galileos! */\r
767                 gotit = 0;\r
768                 for (l = 0; l < inplan; l++) {\r
769                         if (game.state.plnets[l].known == shuttle_down) {\r
770                                 gotit = 1;\r
771                                 if (iscraft==1 && ship==IHE) {\r
772                                         prout("Checkov-  \"Security reports the Galileo has disappeared, Sir!");\r
773                                         iscraft = 0;\r
774                                 }\r
775                         }\r
776                 }\r
777                 /* Likewise, if in the original time the Galileo was abandoned, but\r
778                    was on ship earlier, it would have vanished -- lets restore it */\r
779                 if (iscraft==0 && gotit==0 && game.damage[DSHUTTL] >= 0.0) {\r
780                         prout("Checkov-  \"Security reports the Galileo has reappeared in the dock!\"");\r
781                         iscraft = 1;\r
782                 }\r
783 \r
784                 /* Revert star chart to earlier era, if it was known then*/\r
785                 if (game.damage[DRADIO]==0.0 || stdamtim > game.state.date) {\r
786                         for (l = 1; l <= 8; l++)\r
787                                 for (ll = 1; ll <= 8; ll++)\r
788                                         if (game.starch[l][ll] > 1)\r
789                                                 game.starch[l][ll]=game.damage[DRADIO]>0.0 ? game.state.galaxy[l][ll]+1000 :1;\r
790                         prout("Spock has reconstructed a correct star chart from memory");\r
791                         if (game.damage[DRADIO] > 0.0) stdamtim = game.state.date;\r
792                 }\r
793         }\r
794         else {\r
795                 /* Go forward in time */\r
796                 Time = -0.5*intime*log(Rand());\r
797                 proutn("You are traveling forward in time ");\r
798                 cramf(Time, 1, 2);\r
799                 prout(" stardates.");\r
800                 /* cheat to make sure no tractor beams occur during time warp */\r
801                 game.future[FTBEAM] += Time;\r
802                 game.damage[DRADIO] += Time;\r
803         }\r
804         newqad(0);\r
805 }\r
806 \r
807 void probe(void) {\r
808         double angle, bigger;\r
809         int key;\r
810         /* New code to launch a deep space probe */\r
811         if (nprobes == 0) {\r
812                 chew();\r
813                 skip(1);\r
814                 if (ship == IHE) \r
815                         prout("Engineer Scott- \"We have no more deep space probes, Sir.\"");\r
816                 else\r
817                         prout("Ye Faerie Queene has no deep space probes.");\r
818                 return;\r
819         }\r
820         if (game.damage[DDSP] != 0.0) {\r
821                 chew();\r
822                 skip(1);\r
823                 prout("Engineer Scott- \"The probe launcher is damaged, Sir.\"");\r
824                 return;\r
825         }\r
826         if (game.future[FDSPROB] != 1e30) {\r
827                 chew();\r
828                 skip(1);\r
829                 if (game.damage[DRADIO] != 0 && condit != IHDOCKED) {\r
830                         prout("Spock-  \"Records show the previous probe has not yet");\r
831                         prout("   reached its destination.\"");\r
832                 }\r
833                 else\r
834                         prout("Uhura- \"The previous probe is still reporting data, Sir.\"");\r
835                 return;\r
836         }\r
837         key = scan();\r
838 \r
839         if (key == IHEOL) {\r
840                 /* slow mode, so let Kirk know how many probes there are left */\r
841                 prout(nprobes==1 ? "%d probe left." : "%d probes left.", nprobes);\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         game.future[FDSPROB] = game.state.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 (game.damage[DRADIO] != 0) {\r
890                 prout("Subspace radio damaged.");\r
891                 return;\r
892         }\r
893         if (game.state.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 <= game.state.rembase; l++) {\r
912                         xdist=10.0*sqrt(square(game.state.baseqx[l]-quadx)+square(game.state.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 = game.state.baseqx[line];\r
920                 quady = game.state.baseqy[line];\r
921                 newqad(1);\r
922         }\r
923         /* dematerialize starship */\r
924         game.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 && game.quad[ix][iy]==IHDOT) {\r
953                         /* found one -- finish up */\r
954                         prout("succeeds.");\r
955                         sectx=ix;\r
956                         secty=iy;\r
957                         game.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