On Stas Sergeev's suggestion, change where the logfile is written.
[super-star-trek.git] / src / sst.c
index 7fbbfc2ef558af029e37e827537410314a35ef4f..ccf7470b64ea04fc4f39152e0fa75ff6e272f5a5 100644 (file)
--- a/src/sst.c
+++ b/src/sst.c
@@ -162,6 +162,17 @@ for a lot of magic numbers and refactored the heck out of it.
       type is "plain" or "almy".)
 
    6. User input is now logged so we can do regression testing.
+
+   7. More BSD-Trek features: You can now lose if your entire crew
+      dies in battle.  When abandoning ship in a game with inhabited
+      worlds enabled, they must have one in the quadrant to beam down
+      to; otherwise they die in space and this counts heavily against
+      your score.  Docking at a starbase replenishes your crew.
+
+   8. Still more BSD-Trek: we now have a weighted damage table.
+      Also, the nav subsystem (enabling automatic course
+      setting) can be damaged separately from the main computer (which
+      handles weapons targeting, ETA calculation, and self-destruct).
 */
 
 /* the input queue */
@@ -169,7 +180,7 @@ static char line[128], *linep = line;
 
 struct game game;
 coord thing;
-int iqhere, iqengry;
+bool iqhere, iqengry;
 int iscore, iskill;    // Common PLAQ
 double aaitem;
 double perdate;
@@ -178,22 +189,8 @@ int seed;          // the random-number seed
 bool idebug;           // debug mode
 FILE *logfp, *replayfp;
 
-char *device[NDEVICES] = {
-       "S. R. Sensors",
-       "L. R. Sensors",
-       "Phasers",
-       "Photon Tubes",
-       "Life Support",
-       "Warp Engines",
-       "Impulse Engines",
-       "Shields",
-       "Subspace Radio",
-       "Shuttle Craft",
-       "Computer",
-       "Transporter",
-       "Shield Control",
-       "Death Ray",
-       "D. S. Probe"};                                                                 
+char *systnames[NINHAB + 1];
+char *device[NDEVICES];
 
 static struct 
 {
@@ -279,14 +276,20 @@ commands[] = {
        {"HELP",        HELP,           0},
 #define SEED   37
        {"SEED",        SEED,           0},
+#if BSD_BUG_FOR_BUG
+#define VISUAL 38
+       {"VISUAL",      VISUAL,         0},
+#endif
 };
 
 #define NUMCOMMANDS    sizeof(commands)/sizeof(commands[0])
 #define ACCEPT(i)      (!commands[i].option || (commands[i].option & game.options))
 
-static void listCommands(void) {
+static void listCommands(void) 
+/* generate a list of legal commands */
+{
     int i, k = 0;
-    proutn("LEGAL COMMANDS ARE:");
+    proutn(_("LEGAL COMMANDS ARE:"));
     for (i = 0; i < NUMCOMMANDS; i++) {
        if (!ACCEPT(i))
            continue;
@@ -298,7 +301,8 @@ static void listCommands(void) {
     skip(1);
 }
 
-static void helpme(void) 
+static void helpme(void)
+/* browse on-line help */
 {
     int i, j;
     char cmdbuf[32], *cp;
@@ -310,7 +314,7 @@ static void helpme(void)
     for(;;) {
        if (key == IHEOL) {
            setwnd(prompt_window);
-           proutn("Help on what command? ");
+           proutn(_("Help on what command? "));
            key = scan();
        }
        setwnd(message_window);
@@ -323,7 +327,6 @@ static void helpme(void)
        }
        if (i != NUMCOMMANDS) break;
        skip(1);
-       prout("Valid commands:");
        listCommands();
        key = IHEOL;
        chew();
@@ -341,9 +344,13 @@ static void helpme(void)
     if (fp == NULL)
         fp = fopen(DOC_NAME, "r");
     if (fp == NULL) {
-       prout("Spock-  \"Captain, that information is missing from the");
-        prout("   computer. You need to find "DOC_NAME" and put it in the");
-        prout("   current directory or to "SSTDOC".\"");
+       prout(_("Spock-  \"Captain, that information is missing from the"));
+        proutn(_("   computer. You need to find "));
+        proutn(DOC_NAME);
+        prout(_(" and put it in the"));
+        proutn(_("   current directory or to "));
+        proutn(SSTDOC);
+        prout(".\"");
        /*
         * This used to continue: "You need to find SST.DOC and put 
         * it in the current directory."
@@ -352,7 +359,7 @@ static void helpme(void)
     }
     for (;;) {
        if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
-           prout("Spock- \"Captain, there is no information on that command.\"");
+           prout(_("Spock- \"Captain, there is no information on that command.\""));
            fclose(fp);
            return;
        }
@@ -366,23 +373,29 @@ static void helpme(void)
     }
 
     skip(1);
-    prout("Spock- \"Captain, I've found the following information:\"");
+    prout(_("Spock- \"Captain, I've found the following information:\""));
     skip(1);
 
-    while (fgets(linebuf, sizeof(linebuf),fp)) {
+    while (fgets(linebuf, sizeof(linebuf), fp)) {
+       char *eol;
        if (strstr(linebuf, "******"))
            break;
-       proutn(linebuf);
+       if ((eol = strpbrk(linebuf, "\r\n")))
+           *eol = 0;
+       prout(linebuf);
     }
     fclose(fp);
 }
 
-void enqueue(char *s) 
+void enqueue(char *s)
+/* enqueue input for the command parser */
 {
+    chew();
     strcpy(line, s);
 }
 
-static void makemoves(void) 
+static void makemoves(void)
+/* command-interpretation loop */
 {
     int key, i, v = 0;
     bool hitme;
@@ -392,7 +405,7 @@ static void makemoves(void)
        drawmaps(1);
        for(;;)  { /* get a command */
            hitme = false;
-           game.justin = 0;
+           game.justin = false;
            game.optime = 0.0;
            i = -1;
            chew();
@@ -403,7 +416,7 @@ static void makemoves(void)
                makechart();
                continue;
            }
-           game.ididit=0;
+           game.ididit = false;
            clrscr();
            setwnd(message_window);
            clrscr();
@@ -449,21 +462,21 @@ static void makemoves(void)
            warp(false);
            break;
        case SHIELDS:                   // shields
-           doshield(1);
+           doshield(false);
            if (game.ididit) {
-               hitme=true;
-               game.shldchg = 0;
+               hitme = true;
+               game.shldchg = false;
            }
            break;
        case DOCK:                      // dock
-           dock(1);
-           if (game.ididit) attack(0);
+           dock(true);
+           if (game.ididit) attack(false);
            break;
        case DAMAGES:                   // damages
            dreprt();
            break;
        case CHART:                     // chart
-           chart(0);
+           chart(false);
            break;
        case IMPULSE:                   // impulse
            impuls();
@@ -525,13 +538,13 @@ static void makemoves(void)
            abandn();
            break;
        case DESTRUCT:                  // Self Destruct
-           dstrct();
+           selfdestruct();
            break;
        case SAVE:                      // Save Game
            freeze(false);
            clrscr();
            if (game.skill > SKILL_GOOD)
-               prout("WARNING--Saved games produce no plaques!");
+               prout(_("WARNING--Saved games produce no plaques!"));
            break;
        case DEATHRAY:                  // Try a desparation measure
            deathray();
@@ -545,7 +558,7 @@ static void makemoves(void)
            if (game.ididit) hitme = true;
            break;
        case QUIT:
-           game.alldone = 1;           // quit the game
+           game.alldone = true;                // quit the game
            break;
        case HELP:
            helpme();                   // get help
@@ -555,6 +568,11 @@ static void makemoves(void)
            if (key == IHREAL)
                seed = (int)aaitem;
            break;
+#if BSD_BUG_FOR_BUG
+       case VISUAL:
+           visual();                   // perform visual scan
+           break;
+#endif
        }
        commandhook(commands[i].name, false);
        for (;;) {
@@ -564,14 +582,14 @@ static void makemoves(void)
                if (game.alldone) break;        // Events did us in
            }
            if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) { // Galaxy went Nova!
-               atover(0);
+               atover(false);
                continue;
            }
-           if (hitme && game.justin==0) {
-               attack(2);
+           if (hitme && !game.justin) {
+               attack(true);
                if (game.alldone) break;
                if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) {    // went NOVA! 
-                   atover(0);
+                   atover(false);
                    hitme = true;
                    continue;
                }
@@ -621,7 +639,7 @@ int main(int argc, char **argv)
        }
     }
     /* where to save the input in case of bugs */
-    logfp = fopen("sst-input.log", "w");
+    logfp = fopen("/usr/tmp/sst-input.log", "w");
     setlinebuf(logfp);
     fprintf(logfp, "seed %d\n", seed);
     srand(seed);
@@ -641,7 +659,7 @@ int main(int argc, char **argv)
        setup(line[0] == '\0');
        if (game.alldone) {
            score();
-           game.alldone = 0;
+           game.alldone = false;
        }
        else makemoves();
        skip(1);
@@ -649,73 +667,79 @@ int main(int argc, char **argv)
        skip(1);
 
        if (game.tourn && game.alldone) {
-           proutn("Do you want your score recorded?");
-           if (ja()) {
+           proutn(_("Do you want your score recorded?"));
+           if (ja() == true) {
                chew2();
                freeze(false);
            }
        }
-       proutn("Do you want to play again? ");
+       proutn(_("Do you want to play again? "));
        if (!ja()) break;
     }
     skip(1);
-    prout("May the Great Bird of the Galaxy roost upon your home planet.");
+    prout(_("May the Great Bird of the Galaxy roost upon your home planet."));
     return 0;
 }
 
 
-void cramen(int i) 
+void cramen(feature i) 
+/* print the name of an enemy */
 {
     /* return an enemy */
     char *s;
        
     switch (i) {
-    case IHR: s = "Romulan"; break;
-    case IHK: s = "Klingon"; break;
-    case IHC: s = "Commander"; break;
-    case IHS: s = "Super-commander"; break;
-    case IHSTAR: s = "Star"; break;
-    case IHP: s = "Planet"; break;
-    case IHB: s = "Starbase"; break;
-    case IHBLANK: s = "Black hole"; break;
-    case IHT: s = "Tholian"; break;
-    case IHWEB: s = "Tholian web"; break;
-    case IHQUEST: s = "Stranger"; break;
+    case IHR: s = _("Romulan"); break;
+    case IHK: s = _("Klingon"); break;
+    case IHC: s = _("Commander"); break;
+    case IHS: s = _("Super-commander"); break;
+    case IHSTAR: s = _("Star"); break;
+    case IHP: s = _("Planet"); break;
+    case IHB: s = _("Starbase"); break;
+    case IHBLANK: s = _("Black hole"); break;
+    case IHT: s = _("Tholian"); break;
+    case IHWEB: s = _("Tholian web"); break;
+    case IHQUEST: s = _("Stranger"); break;
+    case IHW: s = _("Inhabited World"); break;
     default: s = "Unknown??"; break;
     }
     proutn(s);
 }
 
 char *cramlc(enum loctype key, coord w)
+/* name a location */
 {
     static char buf[32];
     buf[0] = '\0';
-    if (key == quadrant) strcpy(buf, "Quadrant ");
-    else if (key == sector) strcpy(buf, "Sector ");
+    if (key == quadrant) strcpy(buf, _("Quadrant "));
+    else if (key == sector) strcpy(buf, _("Sector "));
     sprintf(buf+strlen(buf), "%d - %d", w.x, w.y);
     return buf;
 }
 
-void crmena(int i, int enemy, int key, coord w) 
+void crmena(bool stars, feature enemy, enum loctype key, coord w) 
+/* print an enemy and his location */
 {
-    if (i == 1) proutn("***");
+    if (stars) proutn("***");
     cramen(enemy);
-    proutn(" at ");
+    proutn(_(" at "));
     proutn(cramlc(key, w));
 }
 
-void crmshp(void) 
+void crmshp(void)
+/* print our ship name */
 {
     char *s;
     switch (game.ship) {
-    case IHE: s = "Enterprise"; break;
-    case IHF: s = "Faerie Queene"; break;
+    case IHE: s = _("Enterprise"); break;
+    case IHF: s = _("Faerie Queene"); break;
     default:  s = "Ship???"; break;
     }
     proutn(s);
 }
 
-void stars(void) 
+void stars(void)
+/* print a line of stars */
 {
     prouts("******************************************************");
     skip(1);
@@ -731,10 +755,13 @@ double Rand(void)
     return rand()/(1.0 + (double)RAND_MAX);
 }
 
-void iran(int size, int *i, int *j) 
+coord randplace(int size)
+/* choose a random location */ 
 {
-    *i = Rand()*(size*1.0) + 1.0;
-    *j = Rand()*(size*1.0) + 1.0;
+    coord w;
+    w.x = Rand()*(size*1.0) + 1.0;
+    w.y = Rand()*(size*1.0) + 1.0;
+    return w;
 }
 
 void chew(void)
@@ -805,7 +832,8 @@ int scan(void)
     return IHALPHA;
 }
 
-bool ja(void) 
+bool ja(void)
+/* yes-or-no confirmation */
 {
     chew();
     for(;;) {
@@ -813,50 +841,49 @@ bool ja(void)
        chew();
        if (*citem == 'y') return true;
        if (*citem == 'n') return false;
-       proutn("Please answer with \"Y\" or \"N\": ");
+       proutn(_("Please answer with \"y\" or \"n\": "));
     }
 }
 
-void huh(void) 
+void huh(void)
+/* complain about unparseable input */
 {
     chew();
     skip(1);
-    prout("Beg your pardon, Captain?");
+    prout(_("Beg your pardon, Captain?"));
 }
 
-int isit(char *s) 
+bool isit(char *s) 
+/* compares s to citem and returns true if it matches to the length of s */
 {
-    /* New function -- compares s to scanned citem and returns true if it
-       matches to the length of s */
-
     return strncasecmp(s, citem, max(1, strlen(citem))) == 0;
-
 }
 
-void debugme(void) 
+void debugme(void)
+/* access to the internals for debugging */
 {
     proutn("Reset levels? ");
-    if (ja() != 0) {
+    if (ja() == true) {
        if (game.energy < game.inenrg) game.energy = game.inenrg;
        game.shield = game.inshld;
        game.torps = game.intorps;
        game.lsupres = game.inlsr;
     }
     proutn("Reset damage? ");
-    if (ja() != 0) {
+    if (ja() == true) {
        int i;
        for (i=0; i < NDEVICES; i++) 
            if (game.damage[i] > 0.0) 
                game.damage[i] = 0.0;
     }
     proutn("Toggle debug flag? ");
-    if (ja() != 0) {
+    if (ja() == true) {
        idebug = !idebug;
        if (idebug) prout("Debug output ON");
        else prout("Debug output OFF");
     }
     proutn("Cause selective damage? ");
-    if (ja() != 0) {
+    if (ja() == true) {
        int i, key;
        for (i=0; i < NDEVICES; i++) {
            proutn("Kill ");
@@ -870,7 +897,7 @@ void debugme(void)
        }
     }
     proutn("Examine/change events? ");
-    if (ja() != 0) {
+    if (ja() == true) {
        event *ev;
        coord w;
        int i;
@@ -909,28 +936,31 @@ void debugme(void)
                    chew();
                    proutn("In quadrant- ");
                    key = scan();
-                   if (key != IHREAL) {
-                       prout("Event %d canceled, no y coordinate.", i);
-                       unschedule(i);
-                       continue;
-                   }
-                   w.y = (int)aaitem;
-                   key = scan();
-                   if (key != IHREAL) {
-                       prout("Event %d canceled, no x coordinate.", i);
-                       unschedule(i);
-                       continue;
+                   /* IHEOL says to leave coordinates as they are */
+                   if (key != IHEOL) {
+                       if (key != IHREAL) {
+                           prout("Event %d canceled, no x coordinate.", i);
+                           unschedule(i);
+                           continue;
+                       }
+                       w.x = (int)aaitem;
+                       key = scan();
+                       if (key != IHREAL) {
+                           prout("Event %d canceled, no y coordinate.", i);
+                           unschedule(i);
+                           continue;
+                       }
+                       w.y = (int)aaitem;
+                       ev->quadrant = w;
                    }
-                   w.x = (int)aaitem;
-                   ev->quadrant = w;
                }
            }
        }
        chew();
     }
     proutn("Induce supernova here? ");
-    if (ja()) {
+    if (ja() == true) {
        game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = true;
-       atover(1);
+       atover(true);
     }
 }