More uses of distance() macro. Eliminate some magic numbers.
[super-star-trek.git] / src / planets.c
1 #include "sst.h"
2
3 static char *classes[] = {"M","N","O"};
4
5 static bool consumeTime(void)
6 /* abort a lengthy operation if an event interrupts it */
7 {
8     game.ididit = true;
9     events();
10     if (game.alldone || game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova || game.justin) 
11         return true;
12     return false;
13 }
14
15 void preport(void) 
16 /* report on (uninhabited) planets in the galaxy */
17 {
18     bool iknow = false;
19     int i;
20     skip(1);
21     chew();
22     prout(_("Spock-  \"Planet report follows, Captain.\""));
23     skip(1);
24     for (i = 0; i < game.inplan; i++) {
25         if ((game.state.plnets[i].known != unknown
26             && game.state.plnets[i].crystals != 0)
27             || (idebug && game.state.plnets[i].w.x !=0)
28             ) {
29             iknow = true;
30             if (idebug && game.state.plnets[i].known==unknown)
31                 proutn("(Unknown) ");
32             proutn(cramlc(quadrant, game.state.plnets[i].w));
33             proutn(_("   class "));
34             proutn(classes[game.state.plnets[i].pclass]);
35             proutn("   ");
36             if (game.state.plnets[i].crystals <= 0) proutn(_("no "));
37             prout(_("dilithium crystals present."));
38             if (game.state.plnets[i].known==shuttle_down) 
39                 prout(_("    Shuttle Craft Galileo on surface."));
40         }
41     }
42     if (!iknow) prout(_("No information available."));
43 }
44
45 void orbit(void)
46 /* enter standard orbit */
47 {
48     skip(1);
49     chew();
50     if (game.inorbit) {
51         prout(_("Already in standard orbit."));
52         return;
53     }
54     if (damaged(DWARPEN) && damaged(DIMPULS)) {
55         prout(_("Both warp and impulse engines damaged."));
56         return;
57     }
58     if (game.plnet.x == 0 || abs(game.sector.x-game.plnet.x) > 1 || abs(game.sector.y-game.plnet.y) > 1) {
59         crmshp();
60         prout(_(" not adjacent to planet."));
61         skip(1);
62         return;
63     }
64     game.optime = 0.02+0.03*Rand();
65     prout(_("Helmsman Sulu-  \"Entering standard orbit, Sir.\""));
66     newcnd();
67     if (consumeTime()) return;
68     game.height = (1400.0+7200.0*Rand());
69     prout(_("Sulu-  \"Entered orbit at altitude %.2f kilometers.\""), game.height);
70     game.inorbit = true;
71     game.ididit = true;
72 }
73
74 void sensor(void)
75 /* examine planets in this quadrant */
76 {
77     skip(1);
78     chew();
79     if (damaged(DSRSENS)) {
80         prout(_("Short range sensors damaged."));
81         return;
82     }
83     if (!game.plnet.x && (game.options & OPTION_TTY)) {
84         prout(_("Spock- \"No planet in this quadrant, Captain.\""));
85         return;
86     }
87     if ((game.plnet.x != 0)&& (game.state.plnets[game.iplnet].known == unknown)) {
88         prout(_("Spock-  \"Sensor scan for %s-"), cramlc(quadrant, game.quadrant));
89         skip(1);
90         prout(_("         Planet at %s is of class %s."),
91               cramlc(sector,game.plnet),
92               classes[game.state.plnets[game.iplnet].pclass]);
93         if (game.state.plnets[game.iplnet].known==shuttle_down) 
94             prout(_("         Sensors show Galileo still on surface."));
95         proutn(_("         Readings indicate"));
96         if (game.state.plnets[game.iplnet].crystals == 0) proutn(_(" no"));
97         prout(_(" dilithium crystals present.\""));
98         if (game.state.plnets[game.iplnet].known == unknown) game.state.plnets[game.iplnet].known = known;
99     }
100 }
101
102 void beam(void) 
103 /* use the transporter */
104 {
105     chew();
106     skip(1);
107     if (damaged(DTRANSP)) {
108         prout(_("Transporter damaged."));
109         if (!damaged(DSHUTTL) && (game.state.plnets[game.iplnet].known==shuttle_down || game.iscraft == 1)) {
110             skip(1);
111             proutn(_("Spock-  \"May I suggest the shuttle craft, Sir?\" "));
112             if (ja() == true) shuttle();
113         }
114         return;
115     }
116     if (!game.inorbit) {
117         crmshp();
118         prout(_(" not in standard orbit."));
119         return;
120     }
121     if (game.shldup) {
122         prout(_("Impossible to transport through shields."));
123         return;
124     }
125     if (game.state.plnets[game.iplnet].known==unknown) {
126         prout(_("Spock-  \"Captain, we have no information on this planet"));
127         prout(_("  and Starfleet Regulations clearly state that in this situation"));
128         prout(_("  you may not go down.\""));
129         return;
130     }
131     if (game.landed==1) {
132         /* Coming from planet */
133         if (game.state.plnets[game.iplnet].known==shuttle_down) {
134             proutn(_("Spock-  \"Wouldn't you rather take the Galileo?\" "));
135             if (ja() == true) {
136                 chew();
137                 return;
138             }
139             prout(_("Your crew hides the Galileo to prevent capture by aliens."));
140         }
141         prout(_("Landing party assembled, ready to beam up."));
142         skip(1);
143         prout(_("Kirk whips out communicator..."));
144         prouts(_("BEEP  BEEP  BEEP"));
145         skip(2);
146         prout(_("\"Kirk to enterprise-  Lock on coordinates...energize.\""));
147     }
148     else {
149         /* Going to planet */
150         if (game.state.plnets[game.iplnet].crystals==0) {
151             prout(_("Spock-  \"Captain, I fail to see the logic in"));
152             prout(_("  exploring a planet with no dilithium crystals."));
153             proutn(_("  Are you sure this is wise?\" "));
154             if (ja() == false) {
155                 chew();
156                 return;
157             }
158         }
159         prout(_("Scotty-  \"Transporter room ready, Sir.\""));
160         skip(1);
161         prout(_("Kirk and landing party prepare to beam down to planet surface."));
162         skip(1);
163         prout(_("Kirk-  \"Energize.\""));
164     }
165     game.ididit = true;
166     skip(1);
167     prouts("WWHOOOIIIIIRRRRREEEE.E.E.  .  .  .  .   .    .");
168     skip(2);
169     if (Rand() > 0.98) {
170         prouts("BOOOIIIOOOIIOOOOIIIOIING . . .");
171         skip(2);
172         prout(_("Scotty-  \"Oh my God!  I've lost them.\""));
173         finish(FLOST);
174         return;
175     }
176     prouts(".    .   .  .  .  .  .E.E.EEEERRRRRIIIIIOOOHWW");
177     skip(2);
178     prout(_("Transport complete."));
179     game.landed = -game.landed;
180     if (game.landed==1 && game.state.plnets[game.iplnet].known==shuttle_down) {
181         prout(_("The shuttle craft Galileo is here!"));
182     }
183     if (game.landed!=1 && game.imine) {
184         game.icrystl = true;
185         game.cryprob = 0.05;
186     }
187     game.imine = false;
188     return;
189 }
190
191 void mine(void) 
192 /* strip-mine a world for dilithium */
193 {
194     skip(1);
195     chew();
196     if (game.landed!= 1) {
197         prout(_("Mining party not on planet."));
198         return;
199     }
200     if (game.state.plnets[game.iplnet].crystals == MINED) {
201         prout(_("This planet has already been strip-mined for dilithium."));
202         return;
203     }
204     else if (game.state.plnets[game.iplnet].crystals == 0) {
205         prout(_("No dilithium crystals on this planet."));
206         return;
207     }
208     if (game.imine) {
209         prout(_("You've already mined enough crystals for this trip."));
210         return;
211     }
212     if (game.icrystl && game.cryprob == 0.05) {
213         proutn(_("With all those fresh crystals aboard the "));
214         crmshp();
215         skip(1);
216         prout(_("there's no reason to mine more at this time."));
217         return;
218     }
219     game.optime = (0.1+0.2*Rand())*game.state.plnets[game.iplnet].pclass;
220     if (consumeTime()) return;
221     prout(_("Mining operation complete."));
222     game.state.plnets[game.iplnet].crystals = MINED;
223     game.imine = game.ididit = true;
224 }
225
226 void usecrystals(void)
227 /* use dilithium crystals */
228 {
229     game.ididit = false;
230     skip(1);
231     chew();
232     if (!game.icrystl) {
233         prout(_("No dilithium crystals available."));
234         return;
235     }
236     if (game.energy >= 1000) {
237         prout(_("Spock-  \"Captain, Starfleet Regulations prohibit such an operation"));
238         prout(_("  except when condition Yellow exists."));
239         return;
240     }
241     prout(_("Spock- \"Captain, I must warn you that loading"));
242     prout(_("  raw dilithium crystals into the ship's power"));
243     prout(_("  system may risk a severe explosion."));
244     proutn(_("  Are you sure this is wise?\" "));
245     if (ja() == false) {
246         chew();
247         return;
248     }
249     skip(1);
250     prout(_("Engineering Officer Scott-  \"(GULP) Aye Sir."));
251     prout(_("  Mr. Spock and I will try it.\""));
252     skip(1);
253     prout(_("Spock-  \"Crystals in place, Sir."));
254     prout(_("  Ready to activate circuit.\""));
255     skip(1);
256     prouts(_("Scotty-  \"Keep your fingers crossed, Sir!\""));
257     skip(1);
258     if (Rand() <= game.cryprob) {
259         prouts(_("  \"Activating now! - - No good!  It's***"));
260         skip(2);
261         prouts(_("***RED ALERT!  RED A*L********************************"));
262         skip(1);
263         stars();
264         prouts(_("******************   KA-BOOM!!!!   *******************"));
265         skip(1);
266         kaboom();
267         return;
268     }
269     game.energy += 5000.0*(1.0 + 0.9*Rand());
270     prouts(_("  \"Activating now! - - "));
271     prout(_("The instruments"));
272     prout(_("   are going crazy, but I think it's"));
273     prout(_("   going to work!!  Congratulations, Sir!\""));
274     game.cryprob *= 2.0;
275     game.ididit = true;
276 }
277
278 void shuttle(void) 
279 /* use shuttlecraft for planetary jaunt */
280 {
281     chew();
282     skip(1);
283     if(damaged(DSHUTTL)) {
284         if (game.damage[DSHUTTL] == -1.0) {
285             if (game.inorbit && game.state.plnets[game.iplnet].known == shuttle_down)
286                 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."));
287             else
288                 prout(_("Ye Faerie Queene had no shuttle craft."));
289         }
290         else if (game.damage[DSHUTTL] > 0)
291             prout(_("The Galileo is damaged."));
292         else /* game.damage[DSHUTTL] < 0 */ 
293             prout(_("Shuttle craft is now serving Big Macs."));
294         return;
295     }
296     if (!game.inorbit) {
297         crmshp();
298         prout(_(" not in standard orbit."));
299         return;
300     }
301     if ((game.state.plnets[game.iplnet].known != shuttle_down) && game.iscraft != 1) {
302         prout(_("Shuttle craft not currently available."));
303         return;
304     }
305     if (game.landed==-1 && game.state.plnets[game.iplnet].known==shuttle_down) {
306         prout(_("You will have to beam down to retrieve the shuttle craft."));
307         return;
308     }
309     if (game.shldup || game.condit == IHDOCKED) {
310         prout(_("Shuttle craft cannot pass through shields."));
311         return;
312     }
313     if (game.state.plnets[game.iplnet].known==unknown) {
314         prout(_("Spock-  \"Captain, we have no information on this planet"));
315         prout(_("  and Starfleet Regulations clearly state that in this situation"));
316         prout(_("  you may not fly down.\""));
317         return;
318     }
319     game.optime = 3.0e-5*game.height;
320     if (game.optime >= 0.8*game.state.remtime) {
321         prout(_("First Officer Spock-  \"Captain, I compute that such"));
322         proutn(_("  a maneuver would require approximately %2d%% of our"),
323                (int)(100*game.optime/game.state.remtime));
324         prout(_("remaining time."));
325         proutn(_("Are you sure this is wise?\" "));
326         if (ja() == false) {
327             game.optime = 0.0;
328             return;
329         }
330     }
331     if (game.landed == 1) {
332         /* Kirk on planet */
333         if (game.iscraft==1) {
334             /* Galileo on ship! */
335             if (!damaged(DTRANSP)) {
336                 proutn(_("Spock-  \"Would you rather use the transporter?\" "));
337                 if (ja() == true) {
338                     beam();
339                     return;
340                 }
341                 proutn(_("Shuttle crew"));
342             }
343             else
344                 proutn(_("Rescue party"));
345             prout(_(" boards Galileo and swoops toward planet surface."));
346             game.iscraft = 0;
347             skip(1);
348             if (consumeTime()) return;
349             game.state.plnets[game.iplnet].known=shuttle_down;
350             prout(_("Trip complete."));
351             return;
352         }
353         else {
354             /* Ready to go back to ship */
355             prout(_("You and your mining party board the"));
356             prout(_("shuttle craft for the trip back to the Enterprise."));
357             skip(1);
358             prout(_("The short hop begins . . ."));
359             game.state.plnets[game.iplnet].known=known;
360             game.icraft = true;
361             skip(1);
362             game.landed = -1;
363             if (consumeTime()) return;
364             game.iscraft = 1;
365             game.icraft = false;
366             if (game.imine) {
367                 game.icrystl = true;
368                 game.cryprob = 0.05;
369             }
370             game.imine = false;
371             prout(_("Trip complete."));
372             return;
373         }
374     }
375     else {
376         /* Kirk on ship */
377         /* and so is Galileo */
378         prout(_("Mining party assembles in the hangar deck,"));
379         prout(_("ready to board the shuttle craft \"Galileo\"."));
380         skip(1);
381         prouts(_("The hangar doors open; the trip begins."));
382         skip(1);
383         game.icraft = true;
384         game.iscraft = 0;
385         if (consumeTime()) return;
386         game.state.plnets[game.iplnet].known = shuttle_down;
387         game.landed = 1;
388         game.icraft = false;
389         prout(_("Trip complete"));
390         return;
391     }
392 }
393
394 void deathray(void)
395 /* use the big zapper */
396 {
397     double dprob, r = Rand();
398         
399     game.ididit = false;
400     skip(1);
401     chew();
402     if (game.ship != IHE) {
403         prout(_("Ye Faerie Queene has no death ray."));
404         return;
405     }
406     if (game.nenhere==0) {
407         prout(_("Sulu-  \"But Sir, there are no enemies in this quadrant.\""));
408         return;
409     }
410     if (damaged(DDRAY)) {
411         prout(_("Death Ray is damaged."));
412         return;
413     }
414     prout(_("Spock-  \"Captain, the 'Experimental Death Ray'"));
415     prout(_("  is highly unpredictible.  Considering the alternatives,"));
416     proutn(_("  are you sure this is wise?\" "));
417     if (ja() == false) return;
418     prout(_("Spock-  \"Acknowledged.\""));
419     skip(1);
420     game.ididit = true;
421     prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"));
422     skip(1);
423     prout(_("Crew scrambles in emergency preparation."));
424     prout(_("Spock and Scotty ready the death ray and"));
425     prout(_("prepare to channel all ship's power to the device."));
426     skip(1);
427     prout(_("Spock-  \"Preparations complete, sir.\""));
428     prout(_("Kirk-  \"Engage!\""));
429     skip(1);
430     prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"));
431     skip(1);
432     dprob = .30;
433     if (game.options & OPTION_PLAIN)
434         dprob = .5;
435     if (r > dprob) {
436         prouts(_("Sulu- \"Captain!  It's working!\""));
437         skip(2);
438         while (game.nenhere > 0)
439             deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1].x,game.ks[1].y);
440         prout(_("Ensign Chekov-  \"Congratulations, Captain!\""));
441         if (KLINGREM == 0) finish(FWON);
442         if ((game.options & OPTION_PLAIN) == 0) {
443             prout(_("Spock-  \"Captain, I believe the `Experimental Death Ray'"));
444             if (Rand() <= 0.05) {
445                 prout(_("   is still operational.\""));
446             }
447             else {
448                 prout(_("   has been rendered nonfunctional.\""));
449                 game.damage[DDRAY] = 39.95;
450             }
451         }
452         return;
453     }
454     r = Rand(); // Pick failure method 
455     if (r <= .30) {
456         prouts(_("Sulu- \"Captain!  It's working!\""));
457         skip(1);
458         prouts(_("***RED ALERT!  RED ALERT!"));
459         skip(1);
460         prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"));
461         skip(1);
462         prouts(_("***RED ALERT!  RED A*L********************************"));
463         skip(1);
464         stars();
465         prouts(_("******************   KA-BOOM!!!!   *******************"));
466         skip(1);
467         kaboom();
468         return;
469     }
470     if (r <= .55) {
471         prouts(_("Sulu- \"Captain!  Yagabandaghangrapl, brachriigringlanbla!\""));
472         skip(1);
473         prout(_("Lt. Uhura-  \"Graaeek!  Graaeek!\""));
474         skip(1);
475         prout(_("Spock-  \"Fascinating!  . . . All humans aboard"));
476         prout(_("  have apparently been transformed into strange mutations."));
477         prout(_("  Vulcans do not seem to be affected."));
478         skip(1);
479         prout(_("Kirk-  \"Raauch!  Raauch!\""));
480         finish(FDRAY);
481         return;
482     }
483     if (r <= 0.75) {
484         int i,j;
485         prouts(_("Sulu- \"Captain!  It's   --WHAT?!?!\""));
486         skip(2);
487         proutn(_("Spock-  \"I believe the word is"));
488         prouts(_(" *ASTONISHING*"));
489         prout(_(" Mr. Sulu."));
490         for_sectors(i)
491             for_sectors(j)
492                 if (game.quad[i][j] == IHDOT) game.quad[i][j] = IHQUEST;
493         prout(_("  Captain, our quadrant is now infested with"));
494         prouts(_(" - - - - - -  *THINGS*."));
495         skip(1);
496         prout(_("  I have no logical explanation.\""));
497         return;
498     }
499     prouts(_("Sulu- \"Captain!  The Death Ray is creating tribbles!\""));
500     skip(1);
501     prout(_("Scotty-  \"There are so many tribbles down here"));
502     prout(_("  in Engineering, we can't move for 'em, Captain.\""));
503     finish(FTRIBBLE);
504     return;
505 }
506
507 char *systemname(int pindx)
508 /* return the name of a given solar system */
509 {
510     static char copy[BUFSIZ];
511     /* the below array should not be static, or it won't gettextize
512      * because of the early initialization. */
513     char *names[NINHAB+1] =
514     {
515         /*
516          * I used <http://www.memory-alpha.org> to find planets
517          * with references in ST:TOS.  Eath and the Alpha Centauri
518          * Colony have been omitted.
519          *
520          * Some planets marked Class G and P here will be displayed as class M
521          * because of the way planets are generated. This is a known bug.
522          */
523         "ERROR",
524         // Federation Worlds
525         _("Andoria (Fesoan)"),  /* several episodes */
526         _("Tellar Prime (Miracht)"),    /* TOS: "Journey to Babel" */
527         _("Vulcan (T'Khasi)"),  /* many episodes */
528         _("Medusa"),            /* TOS: "Is There in Truth No Beauty?" */
529         _("Argelius II (Nelphia)"),/* TOS: "Wolf in the Fold" ("IV" in BSD) */
530         _("Ardana"),            /* TOS: "The Cloud Minders" */
531         _("Catulla (Cendo-Prae)"),      /* TOS: "The Way to Eden" */
532         _("Gideon"),            /* TOS: "The Mark of Gideon" */
533         _("Aldebaran III"),     /* TOS: "The Deadly Years" */
534         _("Alpha Majoris I"),   /* TOS: "Wolf in the Fold" */
535         _("Altair IV"),         /* TOS: "Amok Time */
536         _("Ariannus"),          /* TOS: "Let That Be Your Last Battlefield" */
537         _("Benecia"),           /* TOS: "The Conscience of the King" */
538         _("Beta Niobe I (Sarpeidon)"),  /* TOS: "All Our Yesterdays" */
539         _("Alpha Carinae II"),  /* TOS: "The Ultimate Computer" */
540         _("Capella IV (Kohath)"),       /* TOS: "Friday's Child" (Class G) */
541         _("Daran V"),           /* TOS: "For the World is Hollow and I Have Touched the Sky" */
542         _("Deneb II"),          /* TOS: "Wolf in the Fold" ("IV" in BSD) */
543         _("Eminiar VII"),               /* TOS: "A Taste of Armageddon" */
544         _("Gamma Canaris IV"),  /* TOS: "Metamorphosis" */
545         _("Gamma Tranguli VI (Vaalel)"),        /* TOS: "The Apple" */
546         _("Ingraham B"),                /* TOS: "Operation: Annihilate" */
547         _("Janus IV"),          /* TOS: "The Devil in the Dark" */
548         _("Makus III"),         /* TOS: "The Galileo Seven" */
549         _("Marcos XII"),                /* TOS: "And the Children Shall Lead", */
550         _("Omega IV"),          /* TOS: "The Omega Glory" */
551         _("Regulus V"),         /* TOS: "Amok Time */
552         _("Deneva"),            /* TOS: "Operation -- Annihilate!" */
553         /* Worlds from BSD Trek */
554         _("Rigel II"),          /* TOS: "Shore Leave" ("III" in BSD) */
555         _("Beta III"),          /* TOS: "The Return of the Archons" */
556         _("Triacus"),           /* TOS: "And the Children Shall Lead", */
557         _("Exo III"),           /* TOS: "What Are Little Girls Made Of?" (Class P) */
558 #if 0
559         // Others
560         _("Hansen's Planet"),   /* TOS: "The Galileo Seven" */
561         _("Taurus IV"),         /* TOS: "The Galileo Seven" (class G) */
562         _("Antos IV (Doraphane)"),      /* TOS: "Whom Gods Destroy", "Who Mourns for Adonais?" */
563         _("Izar"),                      /* TOS: "Whom Gods Destroy" */
564         _("Tiburon"),           /* TOS: "The Way to Eden" */
565         _("Merak II"),          /* TOS: "The Cloud Minders" */ 
566         _("Coridan (Desotriana)"),      /* TOS: "Journey to Babel" */
567         _("Iotia"),             /* TOS: "A Piece of the Action" */
568 #endif
569     };
570
571     strcpy(copy, names[pindx]);
572     return copy;
573 }