-#define INCLUDED // Define externs here\r
-#include "sst.h"\r
-#include <ctype.h>\r
-\r
-#ifndef SSTDOC\r
-#define SSTDOC "sst.doc"\r
-#endif\r
- \r
-static char line[128], *linep = line;\r
-\r
-/* Compared to original version, I've changed the "help" command to\r
- "call" and the "terminate" command to "quit" to better match\r
- user expectations. The DECUS version apparently made those changes\r
- as well as changing "freeze" to "save". However I like "freeze".\r
-\r
- When I got a later version of Super Star Trek that I was converting\r
- from, I added the emexit command.\r
-\r
- That later version also mentions srscan and lrscan working when\r
- docked (using the starbase's scanners), so I made some changes here\r
- to do this (and indicating that fact to the player), and then realized\r
- the base would have a subspace radio as well -- doing a Chart when docked\r
- updates the star chart, and all radio reports will be heard. The Dock\r
- command will also give a report if a base is under attack.\r
-\r
- Movecom no longer reports movement if sensors are damaged so you wouldn't\r
- otherwise know it.\r
-\r
- Also added:\r
-\r
- 1. Better base positioning at startup\r
-\r
- 2. deathray improvement (but keeping original failure alternatives)\r
-\r
- 3. Tholian Web\r
-s\r
- 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can\r
- move in Expert and Emeritus games. This code could use improvement.\r
-\r
- 5. The deep space probe looks interesting! DECUS version\r
-\r
- 6. Perhaps cloaking to be added later? BSD version\r
-\r
-\r
- */\r
-\r
-\r
-static char *commands[] = {\r
- "srscan",\r
- "lrscan",\r
- "phasers",\r
- "photons",\r
- "move",\r
- "shields",\r
- "dock",\r
- "damages",\r
- "chart",\r
- "impulse",\r
- "rest",\r
- "warp",\r
- "status",\r
- "sensors",\r
- "orbit",\r
- "transport",\r
- "mine",\r
- "crystals",\r
- "shuttle",\r
- "planets",\r
- "request",\r
- "report",\r
- "computer",\r
- "commands",\r
- "emexit",\r
- "probe",\r
- "abandon",\r
- "destruct",\r
- "freeze",\r
- "deathray",\r
- "debug",\r
- "call",\r
- "quit",\r
- "help"\r
-};\r
-#define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])\r
-\r
-static void listCommands(int x) {\r
- prout(" SRSCAN MOVE PHASERS CALL\n"\r
- " STATUS IMPULSE PHOTONS ABANDON\n"\r
- " LRSCAN WARP SHIELDS DESTRUCT\n"\r
- " CHART REST DOCK QUIT\n"\r
- " DAMAGES REPORT SENSORS ORBIT\n"\r
- " TRANSPORT MINE CRYSTALS SHUTTLE\n"\r
- " PLANETS REQUEST DEATHRAY FREEZE\n"\r
- " COMPUTER EMEXIT PROBE COMMANDS");\r
- if (x) prout(" HELP");\r
-}\r
-\r
-static void helpme(void) {\r
- int i, j;\r
- char cmdbuf[32], *cp;\r
- char linebuf[132];\r
- FILE *fp;\r
- /* Give help on commands */\r
- int key;\r
- key = scan();\r
- while (TRUE) {\r
- if (key == IHEOL) {\r
- proutn("Help on what command?");\r
- key = scan();\r
- }\r
- if (key == IHEOL) return;\r
- for (i = 0; i < NUMCOMMANDS; i++) {\r
- if (strcmp(commands[i], citem)==0) break;\r
- }\r
- if (i != NUMCOMMANDS) break;\r
- skip(1);\r
- prout("Valid commands:");\r
- listCommands(FALSE);\r
- key = IHEOL;\r
- chew();\r
- skip(1);\r
- }\r
- if (i == 23) {\r
- strcpy(cmdbuf, " ABBREV");\r
- }\r
- else {\r
- for (j = 0; commands[i][j]; j++)\r
- cmdbuf[j] = toupper(commands[i][j]);\r
- cmdbuf[j] = '\0';\r
- }\r
- fp = fopen(SSTDOC, "r");\r
- if (fp == NULL) {\r
- prout("Spock- \"Captain, that information is missing from the");\r
- prout(" computer. You need to find SST.DOC and put it in the");\r
- prout(" current directory.\"");\r
- return;\r
- }\r
- for (;;) {\r
- if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {\r
- prout("Spock- \"Captain, there is no information on that command.\"");\r
- fclose(fp);\r
- return;\r
- }\r
- if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {\r
- for (cp = linebuf+3; isspace(*cp); cp++)\r
- continue;\r
- linebuf[strlen(linebuf)-1] = '\0';\r
- if (strcmp(cp, cmdbuf) == 0)\r
- break;\r
- }\r
- }\r
-\r
- skip(1);\r
- prout("Spock- \"Captain, I've found the following information:\"");\r
- skip(1);\r
-\r
- while (fgets(linebuf, sizeof(linebuf),fp)) {\r
- if (strstr(linebuf, "******"))\r
- break;\r
- proutc(linebuf);\r
- }\r
- fclose(fp);\r
-}\r
-\r
-static void makemoves(void) {\r
- int i, hitme;\r
- char ch;\r
- while (TRUE) { /* command loop */\r
- hitme = FALSE;\r
- justin = 0;\r
- Time = 0.0;\r
- i = -1;\r
- while (TRUE) { /* get a command */\r
- chew();\r
- skip(1);\r
- proutn("COMMAND> ");\r
- if (scan() == IHEOL) continue;\r
- for (i=0; i < 26; i++)\r
- if (isit(commands[i]))\r
- break;\r
- if (i < 26) break;\r
- for (; i < NUMCOMMANDS; i++)\r
- if (strcmp(commands[i], citem) == 0) break;\r
- if (i < NUMCOMMANDS) break;\r
-\r
- if (skill <= 2) {\r
- prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");\r
- listCommands(TRUE);\r
- }\r
- else prout("UNRECOGNIZED COMMAND.");\r
- }\r
- switch (i) { /* command switch */\r
- case 0: // srscan\r
- srscan(1);\r
- break;\r
- case 1: // lrscan\r
- lrscan();\r
- break;\r
- case 2: // phasers\r
- phasers();\r
- if (ididit) hitme = TRUE;\r
- break;\r
- case 3: // photons\r
- photon();\r
- if (ididit) hitme = TRUE;\r
- break;\r
- case 4: // move\r
- warp(1);\r
- break;\r
- case 5: // shields\r
- doshield(1);\r
- if (ididit) {\r
- attack(2);\r
- shldchg = 0;\r
- }\r
- break;\r
- case 6: // dock\r
- dock();\r
- break;\r
- case 7: // damages\r
- dreprt();\r
- break;\r
- case 8: // chart\r
- chart(0);\r
- break;\r
- case 9: // impulse\r
- impuls();\r
- break;\r
- case 10: // rest\r
- wait();\r
- if (ididit) hitme = TRUE;\r
- break;\r
- case 11: // warp\r
- setwrp();\r
- break;\r
- case 12: // status\r
- srscan(3);\r
- break;\r
- case 13: // sensors\r
- sensor();\r
- break;\r
- case 14: // orbit\r
- orbit();\r
- if (ididit) hitme = TRUE;\r
- break;\r
- case 15: // transport "beam"\r
- beam();\r
- break;\r
- case 16: // mine\r
- mine();\r
- if (ididit) hitme = TRUE;\r
- break;\r
- case 17: // crystals\r
- usecrystals();\r
- break;\r
- case 18: // shuttle\r
- shuttle();\r
- if (ididit) hitme = TRUE;\r
- break;\r
- case 19: // Planet list\r
- preport();\r
- break;\r
- case 20: // Status information\r
- srscan(2);\r
- break;\r
- case 21: // Game Report \r
- report(0);\r
- break;\r
- case 22: // use COMPUTER!\r
- eta();\r
- break;\r
- case 23:\r
- listCommands(TRUE);\r
- break;\r
- case 24: // Emergency exit\r
- clearscreen(); // Hide screen\r
- freeze(TRUE); // forced save\r
- exit(1); // And quick exit\r
- break;\r
- case 25:\r
- probe(); // Launch probe\r
- break;\r
- case 26: // Abandon Ship\r
- abandn();\r
- break;\r
- case 27: // Self Destruct\r
- dstrct();\r
- break;\r
- case 28: // Save Game\r
- freeze(FALSE);\r
- if (skill > 3)\r
- prout("WARNING--Frozen games produce no plaques!");\r
- break;\r
- case 29: // Try a desparation measure\r
- deathray();\r
- if (ididit) hitme = TRUE;\r
- break;\r
- case 30: // What do we want for debug???\r
-#ifdef DEBUG\r
- debugme();\r
-#endif\r
- break;\r
- case 31: // Call for help\r
- help();\r
- break;\r
- case 32:\r
- alldone = 1; // quit the game\r
-#ifdef DEBUG\r
- if (idebug) score();\r
-#endif\r
- break;\r
- case 33:\r
- helpme(); // get help\r
- break;\r
- }\r
- for (;;) {\r
- if (alldone) break; // Game has ended\r
-#ifdef DEBUG\r
- if (idebug) prout("2500");\r
-#endif\r
- if (Time != 0.0) {\r
- events();\r
- if (alldone) break; // Events did us in\r
- }\r
- if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!\r
- atover(0);\r
- continue;\r
- }\r
- if (nenhere == 0) movetho();\r
- if (hitme && justin==0) {\r
- attack(2);\r
- if (alldone) break;\r
- if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA! \r
- atover(0);\r
- hitme = TRUE;\r
- continue;\r
- }\r
- }\r
- break;\r
- }\r
- if (alldone) break;\r
- }\r
-}\r
-\r
-\r
-int main(int argc, char **argv) {\r
- int i;\r
- int hitme;\r
- char ch;\r
-\r
- iostart();\r
- prelim(); \r
- line[0] = '\0';\r
- if (argc > 1) {\r
- while (--argc > 0) {\r
- strcat(line, *(++argv));\r
- strcat(line, " ");\r
- }\r
- }\r
-\r
- while (TRUE) { /* Play a game */\r
- setup(line[0] == '\0');\r
- if (alldone) {\r
- score();\r
- alldone = 0;\r
- }\r
- else makemoves();\r
- skip(2);\r
- stars();\r
- skip(1);\r
-\r
- if (tourn && alldone) {\r
- proutn("Do you want your score recorded?");\r
- if (ja()) {\r
- chew2();\r
- freeze(FALSE);\r
- }\r
- }\r
- proutn("Do you want to play again?");\r
- if (!ja()) break;\r
- }\r
- skip(1);\r
- ioend();\r
- puts("May the Great Bird of the Galaxy roost upon your home planet.");\r
-}\r
-\r
-\r
-void cramen(int i) {\r
- /* return an enemy */\r
- char *s;\r
- \r
- switch (i) {\r
- case IHR: s = "Romulan"; break;\r
- case IHK: s = "Klingon"; break;\r
- case IHC: s = "Commander"; break;\r
- case IHS: s = "Super-commander"; break;\r
- case IHSTAR: s = "Star"; break;\r
- case IHP: s = "Planet"; break;\r
- case IHB: s = "Starbase"; break;\r
- case IHBLANK: s = "Black hole"; break;\r
- case IHT: s = "Tholian"; break;\r
- case IHWEB: s = "Tholian web"; break;\r
- default: s = "Unknown??"; break;\r
- }\r
- proutn(s);\r
-}\r
-\r
-char *cramlc(enum loctype key, int x, int y) {\r
- static char buf[32];\r
- buf[0] = '\0';\r
- if (key == quadrant) strcpy(buf, "Quadrant ");\r
- else if (key == sector) strcpy(buf, "Sector ");\r
- sprintf(buf+strlen(buf), "%d-%d", x, y);\r
- return buf;\r
-}\r
-\r
-void crmena(int i, int enemy, int key, int x, int y) {\r
- if (i == 1) proutn("***");\r
- cramen(enemy);\r
- proutn(" at ");\r
- proutn(cramlc(key, x, y));\r
-}\r
-\r
-void crmshp(void) {\r
- char *s;\r
- switch (ship) {\r
- case IHE: s = "Enterprise"; break;\r
- case IHF: s = "Faerie Queene"; break;\r
- default: s = "Ship???"; break;\r
- }\r
- proutn(s);\r
-}\r
-\r
-void stars(void) {\r
- prouts("******************************************************");\r
- skip(1);\r
-}\r
-\r
-double expran(double avrage) {\r
- return -avrage*log(1e-7 + Rand());\r
-}\r
-\r
-double Rand(void) {\r
- return rand()/(1.0 + (double)RAND_MAX);\r
-}\r
-\r
-void iran8(int *i, int *j) {\r
- *i = Rand()*8.0 + 1.0;\r
- *j = Rand()*8.0 + 1.0;\r
-}\r
-\r
-void iran10(int *i, int *j) {\r
- *i = Rand()*10.0 + 1.0;\r
- *j = Rand()*10.0 + 1.0;\r
-}\r
-\r
-void chew(void) {\r
- linep = line;\r
- *linep = 0;\r
-}\r
-\r
-void chew2(void) {\r
- /* return IHEOL next time */\r
- linep = line+1;\r
- *linep = 0;\r
-}\r
-\r
-int scan(void) {\r
- int i;\r
- char *cp;\r
-\r
- // Init result\r
- aaitem = 0.0;\r
- *citem = 0;\r
-\r
- // Read a line if nothing here\r
- if (*linep == 0) {\r
- if (linep != line) {\r
- chew();\r
- return IHEOL;\r
- }\r
- getline(line, sizeof(line));\r
- line[strlen(line)-1] = '\0';\r
- linep = line;\r
- }\r
- // Skip leading white space\r
- while (*linep == ' ') linep++;\r
- // Nothing left\r
- if (*linep == 0) {\r
- chew();\r
- return IHEOL;\r
- }\r
- if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {\r
- // treat as a number\r
- if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {\r
- linep = line; // Invalid numbers are ignored\r
- *linep = 0;\r
- return IHEOL;\r
- }\r
- else {\r
- // skip to end\r
- linep += i;\r
- return IHREAL;\r
- }\r
- }\r
- // Treat as alpha\r
- cp = citem;\r
- while (*linep && *linep!=' ') {\r
- if ((cp - citem) < 9) *cp++ = tolower(*linep);\r
- linep++;\r
- }\r
- *cp = 0;\r
- return IHALPHA;\r
-}\r
-\r
-int ja(void) {\r
- chew();\r
- while (TRUE) {\r
- scan();\r
- chew();\r
- if (*citem == 'y') return TRUE;\r
- if (*citem == 'n') return FALSE;\r
- proutn("Please answer with \"Y\" or \"N\":");\r
- }\r
-}\r
-\r
-double square(double i) { return i*i; }\r
- \r
-void huh(void) {\r
- chew();\r
- skip(1);\r
- prout("Beg your pardon, Captain?");\r
-}\r
-\r
-int isit(char *s) {\r
- /* New function -- compares s to scaned citem and returns true if it\r
- matches to the length of s */\r
-\r
- return strncmp(s, citem, max(1, strlen(citem))) == 0;\r
-\r
-}\r
-\r
-#ifdef DEBUG\r
-void debugme(void) {\r
- proutn("Reset levels? ");\r
- if (ja() != 0) {\r
- if (energy < inenrg) energy = inenrg;\r
- shield = inshld;\r
- torps = intorps;\r
- lsupres = inlsr;\r
- }\r
- proutn("Reset damage? ");\r
- if (ja() != 0) {\r
- int i;\r
- for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;\r
- stdamtim = 1e30;\r
- }\r
- proutn("Toggle idebug? ");\r
- if (ja() != 0) {\r
- idebug = !idebug;\r
- if (idebug) prout("Debug output ON");\r
- else prout("Debug output OFF");\r
- }\r
- proutn("Cause selective damage? ");\r
- if (ja() != 0) {\r
- int i, key;\r
- for (i=1; i <= NDEVICES; i++) {\r
- proutn("Kill ");\r
- proutn(device[i]);\r
- proutn("? ");\r
- chew();\r
- key = scan();\r
- if (key == IHALPHA && isit("y")) {\r
- damage[i] = 10.0;\r
- if (i == DRADIO) stdamtim = game.state.date;\r
- }\r
- }\r
- }\r
- proutn("Examine/change events? ");\r
- if (ja() != 0) {\r
- int i;\r
- for (i = 1; i < NEVENTS; i++) {\r
- int key;\r
- if (future[i] == 1e30) continue;\r
- switch (i) {\r
- case FSNOVA: proutn("Supernova "); break;\r
- case FTBEAM: proutn("T Beam "); break;\r
- case FSNAP: proutn("Snapshot "); break;\r
- case FBATTAK: proutn("Base Attack "); break;\r
- case FCDBAS: proutn("Base Destroy "); break;\r
- case FSCMOVE: proutn("SC Move "); break;\r
- case FSCDBAS: proutn("SC Base Destroy "); break;\r
- }\r
- proutn("%.2f", future[i]-game.state.date);\r
- chew();\r
- proutn(" ?");\r
- key = scan();\r
- if (key == IHREAL) {\r
- future[i] = game.state.date + aaitem;\r
- }\r
- }\r
- chew();\r
- }\r
-}\r
- \r
-\r
-#endif\r
+#define INCLUDED // Define externs here
+#include <ctype.h>
+#include <getopt.h>
+#include <time.h>
+#include "conio.h"
+#include "sstlinux.h"
+#include "sst.h"
+
+#ifndef SSTDOC
+#define SSTDOC "sst.doc"
+#endif
+
+/*
+
+Here are Tom Almy's changes:
+
+ Compared to original version, I've changed the "help" command to
+ "call" and the "terminate" command to "quit" to better match
+ user expectations. The DECUS version apparently made those changes
+ as well as changing "freeze" to "save". However I like "freeze".
+
+ When I got a later version of Super Star Trek that I was converting
+ from, I added the emexit command.
+
+ That later version also mentions srscan and lrscan working when
+ docked (using the starbase's scanners), so I made some changes here
+ to do this (and indicating that fact to the player), and then realized
+ the base would have a subspace radio as well -- doing a Chart when docked
+ updates the star chart, and all radio reports will be heard. The Dock
+ command will also give a report if a base is under attack.
+
+ Movecom no longer reports movement if sensors are damaged so you wouldn't
+ otherwise know it.
+
+ Also added:
+
+ 1. Better base positioning at startup
+
+ 2. Deathray improvement (but keeping original failure alternatives)
+
+ 3. Tholian Web.
+
+ 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
+ move in Expert and Emeritus games. This code could use improvement.
+
+ 5. The deep space probe looks interesting! DECUS version
+
+ 6. Perhaps cloaking to be added later? BSD version
+
+Here are Stas Sergeev's changes:
+
+ 1. The Space Thingy can be shoved, if you it ram, and can fire back if
+ fired upon.
+
+ 2. The Tholian can be hit with phasers
+
+ 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).
+
+ 4. SCom can't escape from you if no more enemies remain (without this,
+ chasing SCom can take an eternity).
+
+ 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)
+
+ 6. Secret password is now autogenerated.
+
+ 7. "Plaque" is adjusted for A4 paper :-)
+
+ 8. Phasers now tells you how much energy needed, but only if the computer
+ is alive.
+
+ 9. Planets are auto-scanned when you enter the quadrant.
+
+ 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.
+
+ 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:
+
+ 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
+
+ */
+
+/* the input queue */
+static char line[128], *linep = line;
+
+static struct
+{
+ char *name;
+ int value;
+}
+commands[] = {
+#define SRSCAN 1
+ {"SRSCAN", SRSCAN},
+#define STATUS 2
+ {"STATUS", STATUS},
+#define REQUEST 3
+ {"REQUEST", REQUEST},
+#define LRSCAN 4
+ {"LRSCAN", LRSCAN},
+#define PHASERS 5
+ {"PHASERS", PHASERS},
+#define TORPEDO 6
+ {"TORPEDO", TORPEDO},
+ {"PHOTONS", TORPEDO},
+#define MOVE 7
+ {"MOVE", MOVE},
+#define SHIELDS 8
+ {"SHIELDS", SHIELDS},
+#define DOCK 9
+ {"DOCK", DOCK},
+#define DAMAGES 10
+ {"DAMAGES", DAMAGES},
+#define CHART 11
+ {"CHART", CHART},
+#define IMPULSE 12
+ {"IMPULSE", IMPULSE},
+#define REST 13
+ {"REST", REST},
+#define WARP 14
+ {"WARP", WARP},
+#define SCORE 15
+ {"SCORE", SCORE},
+#define SENSORS 16
+ {"SENSORS", SENSORS},
+#define ORBIT 17
+ {"ORBIT", ORBIT},
+#define TRANSPORT 18
+ {"TRANSPORT", TRANSPORT},
+#define MINE 19
+ {"MINE", MINE},
+#define CRYSTALS 20
+ {"CRYSTALS", CRYSTALS},
+#define SHUTTLE 21
+ {"SHUTTLE", SHUTTLE},
+#define PLANETS 22
+ {"PLANETS", PLANETS},
+#define REPORT 23
+ {"REPORT", REPORT},
+#define COMPUTER 24
+ {"COMPUTER", COMPUTER},
+#define COMMANDS 25
+ {"COMMANDS", COMMANDS},
+#define EMEXIT 26
+ {"EMEXIT", EMEXIT},
+#define PROBE 27
+ {"PROBE", PROBE},
+#define SAVE 28
+ {"SAVE", SAVE},
+ {"FREEZE", SAVE},
+#define ABANDON 29
+ {"ABANDON", ABANDON},
+#define DESTRUCT 30
+ {"DESTRUCT", DESTRUCT},
+#define DEATHRAY 31
+ {"DEATHRAY", DEATHRAY},
+#define DEBUGCMD 32
+ {"DEBUG", DEBUGCMD},
+#define MAYDAY 33
+ {"MAYDAY", MAYDAY},
+ {"SOS", MAYDAY},
+ {"CALL", MAYDAY},
+#define QUIT 34
+ {"QUIT", QUIT},
+#define HELP 35
+ {"HELP", HELP},
+};
+
+#define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
+
+static void listCommands(int x) {
+ int i;
+ prout("LEGAL COMMANDS ARE:");
+ for (i = 0; i < NUMCOMMANDS; i++) {
+ proutn("%-12s ", commands[i].name);
+ if (i % 5 == 4)
+ skip(1);
+ }
+ skip(1);
+}
+
+static void helpme(void) {
+ int i, j;
+ char cmdbuf[32], *cp;
+ char linebuf[132];
+ FILE *fp;
+ /* Give help on commands */
+ int key;
+ key = scan();
+ while (TRUE) {
+ if (key == IHEOL) {
+ setwnd(BOTTOM_WINDOW);
+ proutn("Help on what command? ");
+ key = scan();
+ }
+ setwnd(LOWER_WINDOW);
+ if (key == IHEOL) return;
+ for (i = 0; i < NUMCOMMANDS; i++) {
+ if (strcasecmp(commands[i].name, citem)==0) {
+ i = commands[i].value;
+ break;
+ }
+ }
+ if (i != NUMCOMMANDS) break;
+ skip(1);
+ prout("Valid commands:");
+ listCommands(FALSE);
+ key = IHEOL;
+ chew();
+ skip(1);
+ }
+ if (i == COMMANDS) {
+ strcpy(cmdbuf, " ABBREV");
+ }
+ else {
+ 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.\"");
+ /*
+ * This used to continue: "You need to find SST.DOC and put
+ * it in the current directory."
+ */
+ return;
+ }
+ for (;;) {
+ if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
+ prout("Spock- \"Captain, there is no information on that command.\"");
+ fclose(fp);
+ return;
+ }
+ if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
+ for (cp = linebuf+3; isspace(*cp); cp++)
+ continue;
+ linebuf[strlen(linebuf)-1] = '\0';
+ if (strcasecmp(cp, cmdbuf) == 0)
+ break;
+ }
+ }
+
+ skip(1);
+ prout("Spock- \"Captain, I've found the following information:\"");
+ skip(1);
+
+ while (fgets(linebuf, sizeof(linebuf),fp)) {
+ if (strstr(linebuf, "******"))
+ break;
+ proutc(linebuf);
+ }
+ fclose(fp);
+}
+
+void enqueue(char *s) {
+ strcpy(line, s);
+}
+
+static void makemoves(void) {
+ int i, hitme;
+ clrscr();
+ setwnd(LOWER_WINDOW);
+ while (TRUE) { /* command loop */
+ drawmaps(1);
+ while (TRUE) { /* get a command */
+ hitme = FALSE;
+ justin = 0;
+ Time = 0.0;
+ i = -1;
+ chew();
+ setwnd(BOTTOM_WINDOW);
+ clrscr();
+ proutn("COMMAND> ");
+ if (scan() == IHEOL) {
+ makechart();
+ continue;
+ }
+ ididit=0;
+ clrscr();
+ setwnd(LOWER_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 (strcasecmp(commands[i].name, citem) == 0) {
+ i = commands[i].value;
+ break;
+ }
+ if (i < NUMCOMMANDS) break;
+
+ listCommands(TRUE);
+ }
+ commandhook(commands[i].name, TRUE);
+ switch (i) { /* command switch */
+ 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 TORPEDO: // photons
+ photon();
+ if (ididit) hitme = TRUE;
+ break;
+ case MOVE: // move
+ warp(1);
+ break;
+ case SHIELDS: // shields
+ doshield(1);
+ if (ididit) {
+ hitme=TRUE;
+ shldchg = 0;
+ }
+ break;
+ case DOCK: // dock
+ dock(1);
+ if (ididit) attack(0);
+ break;
+ case DAMAGES: // damages
+ dreprt();
+ break;
+ case CHART: // chart
+ chart(0);
+ break;
+ case IMPULSE: // impulse
+ impuls();
+ break;
+ case REST: // rest
+ wait();
+ if (ididit) hitme = TRUE;
+ break;
+ case WARP: // warp
+ setwrp();
+ break;
+ case SCORE: // score
+ score();
+ break;
+ case SENSORS: // sensors
+ sensor();
+ break;
+ case ORBIT: // orbit
+ orbit();
+ if (ididit) hitme = TRUE;
+ break;
+ case TRANSPORT: // transport "beam"
+ beam();
+ break;
+ case MINE: // mine
+ mine();
+ if (ididit) hitme = TRUE;
+ break;
+ case CRYSTALS: // crystals
+ usecrystals();
+ if (ididit) hitme = TRUE;
+ break;
+ case SHUTTLE: // shuttle
+ shuttle();
+ if (ididit) hitme = TRUE;
+ break;
+ case PLANETS: // Planet list
+ preport();
+ break;
+ case REPORT: // Game Report
+ report();
+ break;
+ case COMPUTER: // use COMPUTER!
+ eta();
+ break;
+ case COMMANDS:
+ listCommands(TRUE);
+ break;
+ case EMEXIT: // Emergency exit
+ clrscr(); // Hide screen
+ freeze(TRUE); // forced save
+ exit(1); // And quick exit
+ break;
+ case PROBE:
+ probe(); // Launch probe
+ if (ididit) hitme = TRUE;
+ break;
+ case ABANDON: // Abandon Ship
+ abandn();
+ break;
+ case DESTRUCT: // Self Destruct
+ dstrct();
+ break;
+ case SAVE: // Save Game
+ freeze(FALSE);
+ clrscr();
+ if (skill > 3)
+ prout("WARNING--Saved games produce no plaques!");
+ break;
+ case DEATHRAY: // Try a desparation measure
+ deathray();
+ if (ididit) hitme = TRUE;
+ break;
+ case DEBUGCMD: // What do we want for debug???
+#ifdef DEBUG
+ debugme();
+#endif
+ break;
+ case MAYDAY: // Call for help
+ help();
+ if (ididit) hitme = TRUE;
+ break;
+ case QUIT:
+ alldone = 1; // quit the game
+#ifdef DEBUG
+ if (idebug) score();
+#endif
+ break;
+ case HELP:
+ helpme(); // get help
+ break;
+ }
+ commandhook(commands[i].name, FALSE);
+ for (;;) {
+ if (alldone) break; // Game has ended
+#ifdef DEBUG
+ if (idebug) prout("2500");
+#endif
+ if (Time != 0.0) {
+ events();
+ if (alldone) break; // Events did us in
+ }
+ if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
+ atover(0);
+ continue;
+ }
+ if (hitme && justin==0) {
+ attack(2);
+ if (alldone) break;
+ if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
+ atover(0);
+ hitme = TRUE;
+ continue;
+ }
+ }
+ break;
+ }
+ if (alldone) break;
+ }
+}
+
+
+int main(int argc, char **argv) {
+ int i, option, usecurses = TRUE;
+
+ while ((option = getopt(argc, argv, "t")) != -1) {
+ switch (option) {
+ case 't':
+ usecurses = FALSE;
+ break;
+ default:
+ fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
+ exit(0);
+ }
+ }
+
+ randomize();
+ iostart(usecurses);
+
+ line[0] = '\0';
+ for (i = optind; i < argc; i++) {
+ strcat(line, argv[i]);
+ strcat(line, " ");
+ }
+ while (TRUE) { /* Play a game */
+ prelim();
+ setup(line[0] == '\0');
+ if (alldone) {
+ score();
+ alldone = 0;
+ }
+ else makemoves();
+ skip(1);
+ stars();
+ skip(1);
+
+ if (tourn && alldone) {
+ proutn("Do you want your score recorded?");
+ if (ja()) {
+ chew2();
+ freeze(FALSE);
+ }
+ }
+ proutn("Do you want to play again? ");
+ if (!ja()) break;
+ setwnd(FULLSCREEN_WINDOW);
+ clrscr();
+ }
+ skip(1);
+ ioend();
+ prout("May the Great Bird of the Galaxy roost upon your home planet.");
+ return 0;
+}
+
+
+void cramen(int i) {
+ /* 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;
+ default: s = "Unknown??"; break;
+ }
+ proutn(s);
+}
+
+char *cramlc(enum loctype key, int x, int y) {
+ static char buf[32];
+ buf[0] = '\0';
+ if (key == quadrant) strcpy(buf, "Quadrant ");
+ else if (key == sector) strcpy(buf, "Sector ");
+ sprintf(buf+strlen(buf), "%d - %d", x, y);
+ return buf;
+}
+
+void crmena(int i, int enemy, int key, int x, int y) {
+ if (i == 1) proutn("***");
+ cramen(enemy);
+ proutn(" at ");
+ proutn(cramlc(key, x, y));
+}
+
+void crmshp(void) {
+ char *s;
+ switch (ship) {
+ case IHE: s = "Enterprise"; break;
+ case IHF: s = "Faerie Queene"; break;
+ default: s = "Ship???"; break;
+ }
+ proutn(s);
+}
+
+void stars(void) {
+ prouts("******************************************************");
+ skip(1);
+}
+
+double expran(double avrage) {
+ return -avrage*log(1e-7 + Rand());
+}
+
+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 chew(void) {
+ linep = line;
+ *linep = 0;
+}
+
+void chew2(void) {
+ /* return IHEOL next time */
+ linep = line+1;
+ *linep = 0;
+}
+
+int scan(void) {
+ int i;
+ char *cp;
+
+ // Init result
+ aaitem = 0.0;
+ *citem = 0;
+
+ // Read a line if nothing here
+ if (*linep == 0) {
+ if (linep != line) {
+ chew();
+ return IHEOL;
+ }
+ cgetline(line, sizeof(line));
+ fflush(stdin);
+ if (curwnd==BOTTOM_WINDOW){
+ clrscr();
+ setwnd(LOWER_WINDOW);
+ clrscr();
+ }
+ linep = line;
+ }
+ // Skip leading white space
+ while (*linep == ' ') linep++;
+ // Nothing left
+ if (*linep == 0) {
+ chew();
+ return IHEOL;
+ }
+ if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
+ // treat as a number
+ i = 0;
+ if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
+ linep = line; // Invalid numbers are ignored
+ *linep = 0;
+ return IHEOL;
+ }
+ else {
+ // skip to end
+ linep += i;
+ return IHREAL;
+ }
+ }
+ // Treat as alpha
+ cp = citem;
+ while (*linep && *linep!=' ') {
+ if ((cp - citem) < 9) *cp++ = tolower(*linep);
+ linep++;
+ }
+ *cp = 0;
+ return IHALPHA;
+}
+
+int ja(void) {
+ chew();
+ while (TRUE) {
+ scan();
+ chew();
+ if (*citem == 'y') return TRUE;
+ if (*citem == 'n') return FALSE;
+ proutn("Please answer with \"Y\" or \"N\": ");
+ }
+}
+
+void huh(void) {
+ chew();
+ skip(1);
+ prout("Beg your pardon, Captain?");
+}
+
+int isit(char *s) {
+ /* New function -- compares s to scaned citem and returns true if it
+ matches to the length of s */
+
+ return strncasecmp(s, citem, max(1, strlen(citem))) == 0;
+
+}
+
+#ifdef DEBUG
+void debugme(void) {
+ proutn("Reset levels? ");
+ if (ja() != 0) {
+ if (energy < inenrg) energy = inenrg;
+ shield = inshld;
+ torps = intorps;
+ lsupres = inlsr;
+ }
+ proutn("Reset damage? ");
+ if (ja() != 0) {
+ int i;
+ for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
+ stdamtim = 1e30;
+ }
+ proutn("Toggle idebug? ");
+ if (ja() != 0) {
+ idebug = !idebug;
+ if (idebug) prout("Debug output ON");
+ else prout("Debug output OFF");
+ }
+ proutn("Cause selective damage? ");
+ if (ja() != 0) {
+ int i, key;
+ for (i=1; i <= NDEVICES; i++) {
+ proutn("Kill ");
+ proutn(device[i]);
+ proutn("? ");
+ chew();
+ key = scan();
+ if (key == IHALPHA && isit("y")) {
+ damage[i] = 10.0;
+ if (i == DRADIO) stdamtim = game.state.date;
+ }
+ }
+ }
+ proutn("Examine/change events? ");
+ if (ja() != 0) {
+ int i;
+ for (i = 1; i < NEVENTS; i++) {
+ int key;
+ if (future[i] == 1e30) continue;
+ switch (i) {
+ case FSNOVA: proutn("Supernova "); break;
+ case FTBEAM: proutn("T Beam "); break;
+ case FSNAP: proutn("Snapshot "); break;
+ case FBATTAK: proutn("Base Attack "); break;
+ case FCDBAS: proutn("Base Destroy "); break;
+ case FSCMOVE: proutn("SC Move "); break;
+ case FSCDBAS: proutn("SC Base Destroy "); break;
+ }
+ proutn("%.2f", future[i]-game.state.date);
+ chew();
+ proutn(" ?");
+ key = scan();
+ if (key == IHREAL) {
+ future[i] = game.state.date + aaitem;
+ }
+ }
+ chew();
+ }
+}
+
+
+#endif