Get rid of FORTRANisms.
[super-star-trek.git] / sst.c
diff --git a/sst.c b/sst.c
index b31200ecece75d2d857a83983d970aa208a57a35..23e10016f42312fd7c8994f33b0ecffe3b5f9f58 100644 (file)
--- a/sst.c
+++ b/sst.c
@@ -1,14 +1,14 @@
 #define INCLUDED       // Define externs here
 #include <ctype.h>
 #include <getopt.h>
+#include <time.h>
+#include "sstlinux.h"
 #include "sst.h"
 
 #ifndef SSTDOC
 #define SSTDOC "sst.doc"
 #endif
        
-static char line[128], *linep = line;
-
 /*
 
 Here are Tom Almy's changes:
@@ -46,107 +46,159 @@ Here are Tom Almy's changes:
 
    6. Perhaps cloaking to be added later? BSD version
 
-Here are Stas Sergeev's changes (controlled by the proprocessor symbol
-SERGEEV, not yet completely merged):
+Here are Stas Sergeev's changes:
 
    1. The Space Thingy can be shoved, if you it ram, and can fire back if 
       fired upon.
 
-   1 The Tholian can be hit with phasers
+   2. The Tholian can be hit with phasers
 
-   2. When you are docked, base covers you with an almost invincible shields 
+   3. When you are docked, base covers you with an almost invincible shields 
       (a commander can still ram you, or a Romulan can destroy the base,
       or a SCom can even succeed with direct attack IIRC, but this rarely 
       happens).
 
-    3. SCom can't escape from you if no more enemies remain (without this, 
-       chasing SCom can take an eternity).
+   4. SCom can't escape from you if no more enemies remain (without this, 
+      chasing SCom can take an eternity).
 
-    4. Probe target you enter is now the destination quadrant. Before I don't 
-       remember what it was, but it was something I had difficulty using)
+   5. Probe target you enter is now the destination quadrant. Before I don't 
+      remember what it was, but it was something I had difficulty using)
 
-    5. Secret password is now autogenerated.
+   6. Secret password is now autogenerated.
 
-    6. "Plaque" is adjusted for A4 paper:)
+   7. "Plaque" is adjusted for A4 paper :-)
 
-    7. Phasers now tells you how much energy needed, but only if the computer 
+   8. Phasers now tells you how much energy needed, but only if the computer 
        is alive.
 
-    8. Planets are auto-scanned when you enter the quadrant.
+   9. Planets are auto-scanned when you enter the quadrant.
 
-    9. Mining or using crystals in presense of enemy now yields an attack.
+   10. Mining or using crystals in presense of enemy now yields an attack.
        There are other minor adjustments to what yields an attack
        and what does not.
 
-    10. Ramming a black hole is no longer instant death.  There is a
-        chance you might get timewarped instead.
+   11. Ramming a black hole is no longer instant death.  There is a
+       chance you might get timewarped instead.
+
+   12. "freeze" command reverts to "save", most people will understand this
+        better anyway.
+
+   13. Screen-oriented interface, with sensor scans always up.
+
+Eric Raymond's changes:
+
+ Mainly, I translated this C code out of FORTRAN into C -- created #defines
+   for a lot of magic numbers.
+
+   1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
+
+   2. Status report now indicates when dilithium crystals are on board.
+
+   3. Can now report starbases left in scrscan.
 
    */
 
-static char *commands[] = {
-       "srscan",
-       "lrscan",
-       "phasers",
-       "photons",
-       "move",
-       "shields",
-       "dock",
-       "damages",
-       "chart",
-       "impulse",
-       "rest",
-       "warp",
-       "status",
-       "sensors",
-       "orbit",
-       "transport",
-       "mine",
-       "crystals",
-       "shuttle",
-       "planets",
-       "request",
-       "report",
-       "computer",
-       "commands",
-    "emexit",
-    "probe",
-       "abandon",
-       "destruct",
-       "freeze",
-       "deathray",
-       "debug",
-       "call",
-       "quit",
-       "help"
-};
-#define NUMCOMMANDS    sizeof(commands)/sizeof(commands[0])
+/* the input queue */
+static char line[128], *linep = line;
+static int usecurses = TRUE;
 
-static void listCommands(int x) {
-       prout("   SRSCAN    MOVE      PHASERS   CALL\n"
-                 "   STATUS    IMPULSE   PHOTONS   ABANDON\n"
-                 "   LRSCAN    WARP      SHIELDS   DESTRUCT\n"
-                 "   CHART     REST      DOCK      QUIT\n"
-                 "   DAMAGES   REPORT    SENSORS   ORBIT\n"
-                 "   TRANSPORT MINE      CRYSTALS  SHUTTLE\n"
-                 "   PLANETS   REQUEST   DEATHRAY  FREEZE\n"
-                 "   COMPUTER  EMEXIT    PROBE     COMMANDS");
-       if (x) prout("   HELP");
+static struct 
+{
+    char *name;
+    int value;
 }
+commands[] = {
+#define SRSCAN 0
+       {"SRSCAN",      SRSCAN},
+#define STATUS 1
+       {"STATUS",      STATUS},
+#define REQUEST        2
+       {"REQUEST",     REQUEST},
+#define LRSCAN 3
+       {"LRSCAN",      LRSCAN},
+#define PHASERS        4
+       {"PHASERS",     PHASERS},
+#define TORPEDO        5
+        {"TORPEDO",    TORPEDO},
+       {"PHOTONS",     TORPEDO},
+#define MOVE   6
+       {"MOVE",        MOVE},
+#define SHIELDS        7
+       {"SHIELDS",     SHIELDS},
+#define DOCK   8
+       {"DOCK",        DOCK},
+#define DAMAGES        9
+       {"DAMAGES",     DAMAGES},
+#define CHART  10
+       {"CHART",       CHART},
+#define IMPULSE        11
+       {"IMPULSE",     IMPULSE},
+#define REST   12
+       {"REST",        REST},
+#define WARP   13
+       {"WARP",        WARP},
+#define SCORE  14
+       {"SCORE",       SCORE},
+#define SENSORS        15
+       {"SENSORS",     SENSORS},
+#define ORBIT  16
+       {"ORBIT",       ORBIT},
+#define TRANSPORT      17
+       {"TRANSPORT",   TRANSPORT},
+#define MINE   18
+       {"MINE",        MINE},
+#define CRYSTALS       19
+       {"CRYSTALS",    CRYSTALS},
+#define SHUTTLE        20
+       {"SHUTTLE",     SHUTTLE},
+#define PLANETS        21
+       {"PLANETS",     PLANETS},
+#define REPORT 22
+       {"REPORT",      REPORT},
+#define COMPUTER       23
+       {"COMPUTER",    COMPUTER},
+#define COMMANDS       24
+       {"COMMANDS",    COMMANDS},
+#define EMEXIT 25
+       {"EMEXIT",      EMEXIT},
+#define PROBE  26
+       {"PROBE",       PROBE},
+#define SAVE   27
+       {"SAVE",        SAVE},
+       {"FREEZE",      SAVE},
+#define ABANDON        28
+       {"ABANDON",     ABANDON},
+#define DESTRUCT       29
+       {"DESTRUCT",    DESTRUCT},
+#define DEATHRAY       30
+       {"DEATHRAY",    DEATHRAY},
+#define DEBUGCMD       31
+       {"DEBUG",       DEBUGCMD},
+#define MAYDAY 32
+       {"MAYDAY",      MAYDAY},
+       {"SOS",         MAYDAY},
+       {"CALL",        MAYDAY},
+#define QUIT   33
+       {"QUIT",        QUIT},
+#define HELP   34
+       {"HELP",        HELP},
+};
 
-#ifdef SERGEEV
-void setwnd(short wndnum){
-     int cury;
-     cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
-     if ((curwnd==0)&&(wndnum!=0)) clrscr();
-     window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
-     if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
-        gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
-       skip(1);
-     }
-     curwnd=wndnum;
-     gotoxy(1,cury);
+#define NUMCOMMANDS    sizeof(commands)/sizeof(commands[0])
+
+#define MIN_CURSES_COMMAND     PHASERS         /* might change someday */
+
+static void listCommands(int usecurses) {
+    int i, k = 0;
+    proutn("LEGAL COMMANDS ARE:");
+    for (i = usecurses ? MIN_CURSES_COMMAND : 0; i < NUMCOMMANDS; i++) {
+       if (k % 5 == 0)
+           skip(1);
+       proutn("%-12s ", commands[i].name); 
+       k++;
+    }
+    skip(1);
 }
-#endif /* SERGEEV */
 
 static void helpme(void) {
        int i, j;
@@ -158,40 +210,42 @@ static void helpme(void) {
        key = scan();
        while (TRUE) {
                if (key == IHEOL) {
-#ifdef SERGEEV
-                        setwnd(5);
-#endif /* SERGEEV */
+                        setwnd(prompt_window);
                         proutn("Help on what command? ");
                        key = scan();
                }
-#ifdef SERGEEV
-                setwnd(4);
-#endif /* SERGEEV */
+                setwnd(message_window);
                if (key == IHEOL) return;
                for (i = 0; i < NUMCOMMANDS; i++) {
-                       if (strcmp(commands[i], citem)==0) break;
+                   if (strcasecmp(commands[i].name, citem)==0) {
+                       i = commands[i].value;
+                       break;
+                   }
                }
                if (i != NUMCOMMANDS) break;
                skip(1);
                prout("Valid commands:");
-               listCommands(FALSE);
+               listCommands(usecurses);
                key = IHEOL;
                chew();
                skip(1);
        }
-       if (i == 23) {
+       if (i == COMMANDS) {
                strcpy(cmdbuf, " ABBREV");
        }
        else {
-           for (j = 0; commands[i][j]; j++)
-               cmdbuf[j] = toupper(commands[i][j]);
+           for (j = 0; commands[i].name[j]; j++)
+               cmdbuf[j] = toupper(commands[i].name[j]);
            cmdbuf[j] = '\0';
        }
        fp = fopen(SSTDOC, "r");
        if (fp == NULL) {
                prout("Spock-  \"Captain, that information is missing from the");
-               prout("   computer. You need to find SST.DOC and put it in the");
-               prout("   current directory.\"");
+               prout("   computer.\"");
+               /*
+                * This used to continue: "You need to find SST.DOC and put 
+                * it in the current directory."
+                */
                return;
        }
        for (;;) {
@@ -204,7 +258,7 @@ static void helpme(void) {
                for (cp = linebuf+3; isspace(*cp); cp++)
                        continue;
                linebuf[strlen(linebuf)-1] = '\0';
-               if (strcmp(cp, cmdbuf) == 0)
+               if (strcasecmp(cp, cmdbuf) == 0)
                    break;
            }
        }
@@ -216,185 +270,186 @@ static void helpme(void) {
        while (fgets(linebuf, sizeof(linebuf),fp)) {
                if (strstr(linebuf, "******"))
                        break;
-               proutc(linebuf);
+               proutn(linebuf);
        }
        fclose(fp);
 }
 
-#ifdef SERGEEV
-void drawmaps(short l){
-     _setcursortype(_NOCURSOR);
-     if (l==1) sensor();
-     if (l!=2) setwnd(1);
-     gotoxy(1,1);
-     strcpy(line,"s");
-     srscan(1);
-     if (l!=2){
-        setwnd(2);
-        clrscr();
-        srscan(2);
-        setwnd(3);
-        clrscr();
-        strcpy(line,"l");
-        lrscan();
-        _setcursortype(_NORMALCURSOR);
-     }
+void enqueue(char *s) {
+    strcpy(line, s);
 }
-#endif /* SERGEEV */
 
 static void makemoves(void) {
        int i, hitme;
+        clrscr();
+        setwnd(message_window);
        while (TRUE) { /* command loop */
-               hitme = FALSE;
-               justin = 0;
-               Time = 0.0;
-               i = -1;
-               while (TRUE)  { /* get a command */
+                drawmaps(1);
+                while (TRUE)  { /* get a command */
+                       hitme = FALSE;
+                       justin = 0;
+                       Time = 0.0;
+                       i = -1;
                        chew();
-                       skip(1);
+                        setwnd(prompt_window);
+                        clrscr();
                        proutn("COMMAND> ");
-                       if (scan() == IHEOL) continue;
-                       for (i=0; i < 26; i++)
-                               if (isit(commands[i]))
-                                       break;
-                       if (i < 26) break;
+                        if (scan() == IHEOL) {
+                           makechart();
+                            continue;
+                        }
+                        ididit=0;
+                        clrscr();
+                        setwnd(message_window);
+                        clrscr();
+                       for (i=0; i < ABANDON; i++)
+                           if (isit(commands[i].name)) {
+                               i = commands[i].value;
+                               break;
+                           }
+                       if (i < ABANDON) break;
                        for (; i < NUMCOMMANDS; i++)
-                               if (strcmp(commands[i], citem) == 0) break;
+                           if (strcasecmp(commands[i].name, citem) == 0) {
+                                   i = commands[i].value;
+                                   break;
+                           }
                        if (i < NUMCOMMANDS) break;
-
-                       if (skill <= 2)  {
-                               prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
-                               listCommands(TRUE);
-                       }
-                       else prout("UNRECOGNIZED COMMAND.");
+                       listCommands(usecurses);
                }
-               commandhook(commands[i], TRUE);
+               commandhook(commands[i].name, TRUE);
                switch (i) { /* command switch */
-                       case 0:                 // srscan
-                               srscan(1);
-                               break;
-                       case 1:                 // lrscan
-                               lrscan();
-                               break;
-                       case 2:                 // phasers
+                        case SRSCAN:                 // srscan
+                               srscan(SCAN_FULL);
+                               break;
+                        case STATUS:                 // status
+                               srscan(SCAN_STATUS);
+                               break;
+                       case REQUEST:                   // status request 
+                               srscan(SCAN_REQUEST);
+                               break;
+                       case LRSCAN:                    // lrscan
+                               lrscan();
+                                break;
+                       case PHASERS:                   // phasers
                                phasers();
                                if (ididit) hitme = TRUE;
                                break;
-                       case 3:                 // photons
+                       case TORPEDO:                   // photons
                                photon();
                                if (ididit) hitme = TRUE;
                                break;
-                       case 4:                 // move
+                       case MOVE:                      // move
                                warp(1);
                                break;
-                       case 5:                 // shields
+                       case SHIELDS:                   // shields
                                doshield(1);
                                if (ididit) {
-                                       attack(2);
+                                       hitme=TRUE;
                                        shldchg = 0;
                                }
                                break;
-                       case 6:                 // dock
-                               dock(1);
+                       case DOCK:                      // dock
+                                dock(1);
                                 if (ididit) attack(0);
                                break;
-                       case 7:                 // damages
+                       case DAMAGES:                   // damages
                                dreprt();
                                break;
-                       case 8:                 // chart
+                       case CHART:                     // chart
                                chart(0);
                                break;
-                       case 9:                 // impulse
+                       case IMPULSE:                   // impulse
                                impuls();
                                break;
-                       case 10:                // rest
+                       case REST:              // rest
                                wait();
                                if (ididit) hitme = TRUE;
                                break;
-                       case 11:                // warp
+                       case WARP:              // warp
                                setwrp();
                                break;
-                       case 12:                // status
-                               srscan(3);
+                        case SCORE:                // score
+                                score();
                                break;
-                       case 13:                        // sensors
+                       case SENSORS:                   // sensors
                                sensor();
                                break;
-                       case 14:                        // orbit
+                       case ORBIT:                     // orbit
                                orbit();
                                if (ididit) hitme = TRUE;
                                break;
-                       case 15:                        // transport "beam"
+                       case TRANSPORT:                 // transport "beam"
                                beam();
                                break;
-                       case 16:                        // mine
+                       case MINE:                      // mine
                                mine();
                                if (ididit) hitme = TRUE;
                                break;
-                       case 17:                        // crystals
+                       case CRYSTALS:                  // crystals
                                usecrystals();
+                                if (ididit) hitme = TRUE;
                                break;
-                       case 18:                        // shuttle
+                       case SHUTTLE:                   // shuttle
                                shuttle();
                                if (ididit) hitme = TRUE;
                                break;
-                       case 19:                        // Planet list
+                       case PLANETS:                   // Planet list
                                preport();
                                break;
-                       case 20:                        // Status information
-                               srscan(2);
+                       case REPORT:                    // Game Report 
+                               report();
                                break;
-                       case 21:                        // Game Report 
-                               report(0);
-                               break;
-                       case 22:                        // use COMPUTER!
+                       case COMPUTER:                  // use COMPUTER!
                                eta();
                                break;
-                       case 23:
-                               listCommands(TRUE);
+                       case COMMANDS:
+                               listCommands(usecurses);
                                break;
-                       case 24:                // Emergency exit
-                               clearscreen();  // Hide screen
+                       case EMEXIT:            // Emergency exit
+                               clrscr();       // Hide screen
                                freeze(TRUE);   // forced save
                                exit(1);                // And quick exit
                                break;
-                       case 25:
+                       case PROBE:
                                probe();                // Launch probe
+                                if (ididit) hitme = TRUE;
                                break;
-                       case 26:                        // Abandon Ship
+                       case ABANDON:                   // Abandon Ship
                                abandn();
                                break;
-                       case 27:                        // Self Destruct
+                       case DESTRUCT:                  // Self Destruct
                                dstrct();
                                break;
-                       case 28:                        // Save Game
+                       case SAVE:                      // Save Game
                                freeze(FALSE);
-                               if (skill > 3)
-                                       prout("WARNING--Frozen games produce no plaques!");
+                                clrscr();
+                               if (skill > SKILL_GOOD)
+                                        prout("WARNING--Saved games produce no plaques!");
                                break;
-                       case 29:                        // Try a desparation measure
+                       case DEATHRAY:          // Try a desparation measure
                                deathray();
                                if (ididit) hitme = TRUE;
                                break;
-                       case 30:                        // What do we want for debug???
+                       case DEBUGCMD:          // What do we want for debug???
 #ifdef DEBUG
                                debugme();
 #endif
                                break;
-                       case 31:                // Call for help
+                       case MAYDAY:            // Call for help
                                help();
+                                if (ididit) hitme = TRUE;
                                break;
-                       case 32:
+                       case QUIT:
                                alldone = 1;    // quit the game
 #ifdef DEBUG
                                if (idebug) score();
 #endif
                                break;
-                       case 33:
+                       case HELP:
                                helpme();       // get help
                                break;
                }
-               commandhook(commands[i], FALSE);
+               commandhook(commands[i].name, FALSE);
                for (;;) {
                        if (alldone) break;             // Game has ended
 #ifdef DEBUG
@@ -404,15 +459,14 @@ static void makemoves(void) {
                                events();
                                if (alldone) break;             // Events did us in
                        }
-                       if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
+                       if (game.state.galaxy[quadx][quady] == SUPERNOVA_PLACE) { // Galaxy went Nova!
                                atover(0);
                                continue;
                        }
-                       if (nenhere == 0) movetho();
                        if (hitme && justin==0) {
                                attack(2);
                                if (alldone) break;
-                               if (game.state.galaxy[quadx][quady] == 1000) {  // went NOVA! 
+                               if (game.state.galaxy[quadx][quady] == SUPERNOVA_PLACE) {       // went NOVA! 
                                        atover(0);
                                        hitme = TRUE;
                                        continue;
@@ -426,7 +480,8 @@ static void makemoves(void) {
 
 
 int main(int argc, char **argv) {
-    int i, option, usecurses = TRUE;
+    int i, option;
+
        while ((option = getopt(argc, argv, "t")) != -1) {
            switch (option) {
            case 't':
@@ -438,21 +493,25 @@ int main(int argc, char **argv) {
            }
        }
 
+       randomize();
        iostart(usecurses);
-       prelim(); 
+
        line[0] = '\0';
        for (i = optind; i < argc;  i++) {
                strcat(line, argv[i]);
                strcat(line, " ");
        }
        while (TRUE) { /* Play a game */
+               setwnd(fullscreen_window);
+               clrscr();
+               prelim();
                setup(line[0] == '\0');
                if (alldone) {
                        score();
                        alldone = 0;
                }
                else makemoves();
-               skip(2);
+               skip(1);
                stars();
                skip(1);
 
@@ -465,17 +524,10 @@ int main(int argc, char **argv) {
                }
                proutn("Do you want to play again? ");
                if (!ja()) break;
-#ifdef SERGEEV
-               setwnd(0);
-               clrscr();
-#endif /* SERGEEV */
        }
        skip(1);
-#ifndef SERGEEV
-       ioend();
-#endif /* SERGEEV */
-       puts("May the Great Bird of the Galaxy roost upon your home planet.");
-       exit(0);
+       prout("May the Great Bird of the Galaxy roost upon your home planet.");
+       return 0;
 }
 
 
@@ -505,7 +557,7 @@ char *cramlc(enum loctype key, int x, int y) {
        buf[0] = '\0';
        if (key == quadrant) strcpy(buf, "Quadrant ");
        else if (key == sector) strcpy(buf, "Sector ");
-       sprintf(buf+strlen(buf), "%d-%d", x, y);
+       sprintf(buf+strlen(buf), "%d - %d", x, y);
        return buf;
 }
 
@@ -539,14 +591,9 @@ double Rand(void) {
        return rand()/(1.0 + (double)RAND_MAX);
 }
 
-void iran8(int *i, int *j) {
-       *i = Rand()*8.0 + 1.0;
-       *j = Rand()*8.0 + 1.0;
-}
-
-void iran10(int *i, int *j) {
-       *i = Rand()*10.0 + 1.0;
-       *j = Rand()*10.0 + 1.0;
+void iran(int size, int *i, int *j) {
+    *i = Rand()*(size*1.0) + 1.0;
+    *j = Rand()*(size*1.0) + 1.0;
 }
 
 void chew(void) {
@@ -574,7 +621,13 @@ int scan(void) {
                        chew();
                        return IHEOL;
                }
-               getline(line, sizeof(line));
+               cgetline(line, sizeof(line));
+                fflush(stdin);
+                if (curwnd==prompt_window){
+                   clrscr();
+                   setwnd(message_window);
+                   clrscr();
+                }
                linep = line;
        }
        // Skip leading white space
@@ -629,7 +682,7 @@ int isit(char *s) {
        /* New function -- compares s to scaned citem and returns true if it
           matches to the length of s */
 
-       return strncmp(s, citem, max(1, strlen(citem))) == 0;
+       return strncasecmp(s, citem, max(1, strlen(citem))) == 0;
 
 }