Better command suppression.
[super-star-trek.git] / sst.c
diff --git a/sst.c b/sst.c
index 5cba52ea154cc675bc71f5a390360149e9bd4756..89e069d51696293328651b8a716f6754a14e7120 100644 (file)
--- a/sst.c
+++ b/sst.c
@@ -1,19 +1,14 @@
 #define INCLUDED       // Define externs here
 #include <ctype.h>
 #include <getopt.h>
-#ifdef SERGEEV
-#include <conio.h>
 #include <time.h>
 #include "sstlinux.h"
-#endif /* SERGEEV */
 #include "sst.h"
 
 #ifndef SSTDOC
 #define SSTDOC "sst.doc"
 #endif
        
-static char line[128], *linep = line;
-
 /*
 
 Here are Tom Almy's changes:
@@ -51,139 +46,154 @@ 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.
 
-static char *commands[] = {
-#ifdef SERGEEV
-        "--",
-        "---",
-#else
-       "srscan",
-       "lrscan",
-#endif /* SERGEEV */
-       "phasers",
-#ifdef SERGEEV
-        "torpedo",
-#else
-       "photons",
-#endif /* SERGEEV */
-       "move",
-       "shields",
-       "dock",
-       "damages",
-       "chart",
-       "impulse",
-       "rest",
-       "warp",
-#ifdef SERGEEV
-        "score",
-        "----",
-#else
-       "status",
-       "sensors",
-#endif /* SERGEEV */
-       "orbit",
-       "transport",
-       "mine",
-       "crystals",
-       "shuttle",
-       "planets",
-#ifdef SERGEEV
-        "-----",
-#else
-       "request",
-#endif /* SERGEEV */
-       "report",
-       "computer",
-       "commands",
-       "emexit",
-       "probe",
-       "abandon",
-       "destruct",
-#ifdef SERGEEV
-        "save",
-#else
-       "freeze",
-#endif /* SERGEEV */
-       "deathray",
-       "debug",
-#ifdef SERGEEV
-        "sos",
-#else
-       "call",
-#endif /* SERGEEV */
-       "quit",
-       "help"
-};
+   13. Screen-oriented interface, with sensor scans always up.
 
-#ifdef SERGEEV
-wnd wnds[6]={{1,1,80,25},{1,1,25,12},{26,2,80,12},{65,1,80,10},{1,13,80,23},{1,24,80,25}};
-short curwnd;
-#endif /* SERGEEV */
+Eric Raymond's changes:
 
-#define NUMCOMMANDS    sizeof(commands)/sizeof(commands[0])
+   1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
+
+   2. Status report now indicates when dilithium crystals are on board.
+
+   */
+
+/* the input queue */
+static char line[128], *linep = line;
+static usecurses = TRUE;
 
-static void listCommands(int x) {
-        proutn   ("LEGAL COMMANDS ARE:\n\r"
-                  "   MOVE      PHASERS   SOS       PROBE\n\r"
-                  "   COMPUTER  IMPULSE   TORPEDO   ABANDON\n\r"
-                  "   EMEXIT    WARP      SHIELDS   DESTRUCT\n\r"
-                  "   CHART     REST      DOCK      QUIT\n\r"
-                  "   DAMAGES   REPORT    SCORE     ORBIT\n\r"
-                  "   TRANSPORT MINE      CRYSTALS  SHUTTLE\n\r"
-                  "   PLANETS   DEATHRAY  SAVE      COMMANDS\n\r");
-       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;
@@ -195,40 +205,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 (;;) {
@@ -241,7 +253,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;
            }
        }
@@ -253,210 +265,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;
-#ifdef SERGEEV
         clrscr();
-        setwnd(4);
-#endif /* SERGEEV */
+        setwnd(message_window);
        while (TRUE) { /* command loop */
-#ifdef SERGEEV
                 drawmaps(1);
-#endif /* SERGEEV */
                 while (TRUE)  { /* get a command */
                        hitme = FALSE;
                        justin = 0;
                        Time = 0.0;
                        i = -1;
                        chew();
-#ifdef SERGEEV
-                        setwnd(5);
+                        setwnd(prompt_window);
                         clrscr();
-#endif /* SERGEEV */
                        proutn("COMMAND> ");
-#ifdef SERGEEV
                         if (scan() == IHEOL) {
-                            _setcursortype(_NOCURSOR);
-                            setwnd(4);
-                            clrscr();
-                            chart(0);
-                            _setcursortype(_NORMALCURSOR);
+                           makechart();
                             continue;
                         }
                         ididit=0;
                         clrscr();
-                        setwnd(4);
+                        setwnd(message_window);
                         clrscr();
-#endif /* SERGEEV */
-                       for (i=0; i < 26; i++)
-                               if (isit(commands[i]))
-                                       break;
-                       if (i < 26) break;
+                       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;
-
-                       listCommands(TRUE);
+                       listCommands(usecurses);
                }
-               commandhook(commands[i], TRUE);
+               commandhook(commands[i].name, TRUE);
                switch (i) { /* command switch */
-#ifndef SERGEEV
-                        case 0:                 // srscan
-                               srscan(1);
+                        case SRSCAN:                 // srscan
+                               srscan(SCAN_FULL);
+                               break;
+                        case STATUS:                 // status
+                               srscan(SCAN_STATUS);
                                break;
-                       case 1:                 // lrscan
+                       case REQUEST:                   // status request 
+                               srscan(SCAN_REQUEST);
+                               break;
+                       case LRSCAN:                    // lrscan
                                lrscan();
                                 break;
-#endif /* SERGEEV */
-                       case 2:                 // phasers
+                       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) {
                                        hitme=TRUE;
                                        shldchg = 0;
                                }
                                break;
-                       case 6:                 // dock
+                       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:                // score
+                        case SCORE:                // score
                                 score();
                                break;
-#ifndef SERGEEV
-                       case 13:                        // sensors
+                       case SENSORS:                   // sensors
                                sensor();
                                break;
-#endif /* SERGEEV */
-                       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);
+                                clrscr();
                                if (skill > 3)
-                                       prout("WARNING--Frozen games produce no plaques!");
+                                        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
@@ -470,7 +458,6 @@ static void makemoves(void) {
                                atover(0);
                                continue;
                        }
-                       if (nenhere == 0) movetho();
                        if (hitme && justin==0) {
                                attack(2);
                                if (alldone) break;
@@ -488,7 +475,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':
@@ -500,21 +488,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);
 
@@ -527,15 +519,8 @@ 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 */
        prout("May the Great Bird of the Galaxy roost upon your home planet.");
        return 0;
 }
@@ -567,7 +552,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;
 }
 
@@ -636,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
@@ -691,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;
 
 }