1 #define INCLUDED // Define externs here
\r
7 #define SSTDOC "sst.doc"
\r
10 static char line[128], *linep = line;
\r
12 /* Compared to original version, I've changed the "help" command to
\r
13 "call" and the "terminate" command to "quit" to better match
\r
14 user expectations. The DECUS version apparently made those changes
\r
15 as well as changing "freeze" to "save". However I like "freeze".
\r
17 When I got a later version of Super Star Trek that I was converting
\r
18 from, I added the emexit command.
\r
20 That later version also mentions srscan and lrscan working when
\r
21 docked (using the starbase's scanners), so I made some changes here
\r
22 to do this (and indicating that fact to the player), and then realized
\r
23 the base would have a subspace radio as well -- doing a Chart when docked
\r
24 updates the star chart, and all radio reports will be heard. The Dock
\r
25 command will also give a report if a base is under attack.
\r
27 Movecom no longer reports movement if sensors are damaged so you wouldn't
\r
32 1. Better base positioning at startup
\r
34 2. deathray improvement (but keeping original failure alternatives)
\r
38 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
\r
39 move in Expert and Emeritus games. This code could use improvement.
\r
41 5. The deep space probe looks interesting! DECUS version
\r
43 6. Perhaps cloaking to be added later? BSD version
\r
49 static char *commands[] = {
\r
85 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
\r
87 static void listCommands(int x) {
\r
88 prout(" SRSCAN MOVE PHASERS CALL\n"
\r
89 " STATUS IMPULSE PHOTONS ABANDON\n"
\r
90 " LRSCAN WARP SHIELDS DESTRUCT\n"
\r
91 " CHART REST DOCK QUIT\n"
\r
92 " DAMAGES REPORT SENSORS ORBIT\n"
\r
93 " TRANSPORT MINE CRYSTALS SHUTTLE\n"
\r
94 " PLANETS REQUEST DEATHRAY FREEZE\n"
\r
95 " COMPUTER EMEXIT PROBE COMMANDS");
\r
96 if (x) prout(" HELP");
\r
99 static void helpme(void) {
\r
101 char cmdbuf[32], *cp;
\r
104 /* Give help on commands */
\r
108 if (key == IHEOL) {
\r
109 proutn("Help on what command?");
\r
112 if (key == IHEOL) return;
\r
113 for (i = 0; i < NUMCOMMANDS; i++) {
\r
114 if (strcmp(commands[i], citem)==0) break;
\r
116 if (i != NUMCOMMANDS) break;
\r
118 prout("Valid commands:");
\r
119 listCommands(FALSE);
\r
125 strcpy(cmdbuf, " ABBREV");
\r
128 for (j = 0; commands[i][j]; j++)
\r
129 cmdbuf[j] = toupper(commands[i][j]);
\r
132 fp = fopen(SSTDOC, "r");
\r
134 prout("Spock- \"Captain, that information is missing from the");
\r
135 prout(" computer. You need to find SST.DOC and put it in the");
\r
136 prout(" current directory.\"");
\r
140 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
\r
141 prout("Spock- \"Captain, there is no information on that command.\"");
\r
145 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
\r
146 for (cp = linebuf+3; isspace(*cp); cp++)
\r
148 linebuf[strlen(linebuf)-1] = '\0';
\r
149 if (strcmp(cp, cmdbuf) == 0)
\r
155 prout("Spock- \"Captain, I've found the following information:\"");
\r
158 while (fgets(linebuf, sizeof(linebuf),fp)) {
\r
159 if (strstr(linebuf, "******"))
\r
166 static void makemoves(void) {
\r
169 while (TRUE) { /* command loop */
\r
174 while (TRUE) { /* get a command */
\r
177 proutn("COMMAND> ");
\r
178 if (scan() == IHEOL) continue;
\r
179 for (i=0; i < 26; i++)
\r
180 if (isit(commands[i]))
\r
183 for (; i < NUMCOMMANDS; i++)
\r
184 if (strcmp(commands[i], citem) == 0) break;
\r
185 if (i < NUMCOMMANDS) break;
\r
188 prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
\r
189 listCommands(TRUE);
\r
191 else prout("UNRECOGNIZED COMMAND.");
\r
193 commandhook(commands[i], TRUE);
\r
194 switch (i) { /* command switch */
\r
203 if (ididit) hitme = TRUE;
\r
207 if (ididit) hitme = TRUE;
\r
233 if (ididit) hitme = TRUE;
\r
241 case 13: // sensors
\r
246 if (ididit) hitme = TRUE;
\r
248 case 15: // transport "beam"
\r
253 if (ididit) hitme = TRUE;
\r
255 case 17: // crystals
\r
258 case 18: // shuttle
\r
260 if (ididit) hitme = TRUE;
\r
262 case 19: // Planet list
\r
265 case 20: // Status information
\r
268 case 21: // Game Report
\r
271 case 22: // use COMPUTER!
\r
275 listCommands(TRUE);
\r
277 case 24: // Emergency exit
\r
278 clearscreen(); // Hide screen
\r
279 freeze(TRUE); // forced save
\r
280 exit(1); // And quick exit
\r
283 probe(); // Launch probe
\r
285 case 26: // Abandon Ship
\r
288 case 27: // Self Destruct
\r
291 case 28: // Save Game
\r
294 prout("WARNING--Frozen games produce no plaques!");
\r
296 case 29: // Try a desparation measure
\r
298 if (ididit) hitme = TRUE;
\r
300 case 30: // What do we want for debug???
\r
305 case 31: // Call for help
\r
309 alldone = 1; // quit the game
\r
311 if (idebug) score();
\r
315 helpme(); // get help
\r
318 commandhook(commands[i], FALSE);
\r
320 if (alldone) break; // Game has ended
\r
322 if (idebug) prout("2500");
\r
326 if (alldone) break; // Events did us in
\r
328 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
\r
332 if (nenhere == 0) movetho();
\r
333 if (hitme && justin==0) {
\r
335 if (alldone) break;
\r
336 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
\r
344 if (alldone) break;
\r
349 int main(int argc, char **argv) {
\r
350 int i, option, usecurses = TRUE;
\r
354 while ((option = getopt(argc, argv, "t")) != -1) {
\r
360 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
\r
365 iostart(usecurses);
\r
368 for (i = optind; i < argc; i++) {
\r
369 strcat(line, argv[i]);
\r
372 while (TRUE) { /* Play a game */
\r
373 setup(line[0] == '\0');
\r
383 if (tourn && alldone) {
\r
384 proutn("Do you want your score recorded?");
\r
390 proutn("Do you want to play again?");
\r
395 puts("May the Great Bird of the Galaxy roost upon your home planet.");
\r
399 void cramen(int i) {
\r
400 /* return an enemy */
\r
404 case IHR: s = "Romulan"; break;
\r
405 case IHK: s = "Klingon"; break;
\r
406 case IHC: s = "Commander"; break;
\r
407 case IHS: s = "Super-commander"; break;
\r
408 case IHSTAR: s = "Star"; break;
\r
409 case IHP: s = "Planet"; break;
\r
410 case IHB: s = "Starbase"; break;
\r
411 case IHBLANK: s = "Black hole"; break;
\r
412 case IHT: s = "Tholian"; break;
\r
413 case IHWEB: s = "Tholian web"; break;
\r
414 default: s = "Unknown??"; break;
\r
419 char *cramlc(enum loctype key, int x, int y) {
\r
420 static char buf[32];
\r
422 if (key == quadrant) strcpy(buf, "Quadrant ");
\r
423 else if (key == sector) strcpy(buf, "Sector ");
\r
424 sprintf(buf+strlen(buf), "%d-%d", x, y);
\r
428 void crmena(int i, int enemy, int key, int x, int y) {
\r
429 if (i == 1) proutn("***");
\r
432 proutn(cramlc(key, x, y));
\r
435 void crmshp(void) {
\r
438 case IHE: s = "Enterprise"; break;
\r
439 case IHF: s = "Faerie Queene"; break;
\r
440 default: s = "Ship???"; break;
\r
446 prouts("******************************************************");
\r
450 double expran(double avrage) {
\r
451 return -avrage*log(1e-7 + Rand());
\r
454 double Rand(void) {
\r
455 return rand()/(1.0 + (double)RAND_MAX);
\r
458 void iran8(int *i, int *j) {
\r
459 *i = Rand()*8.0 + 1.0;
\r
460 *j = Rand()*8.0 + 1.0;
\r
463 void iran10(int *i, int *j) {
\r
464 *i = Rand()*10.0 + 1.0;
\r
465 *j = Rand()*10.0 + 1.0;
\r
474 /* return IHEOL next time */
\r
487 // Read a line if nothing here
\r
489 if (linep != line) {
\r
493 getline(line, sizeof(line));
\r
496 // Skip leading white space
\r
497 while (*linep == ' ') linep++;
\r
503 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
\r
504 // treat as a number
\r
505 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
\r
506 linep = line; // Invalid numbers are ignored
\r
518 while (*linep && *linep!=' ') {
\r
519 if ((cp - citem) < 9) *cp++ = tolower(*linep);
\r
531 if (*citem == 'y') return TRUE;
\r
532 if (*citem == 'n') return FALSE;
\r
533 proutn("Please answer with \"Y\" or \"N\":");
\r
537 double square(double i) { return i*i; }
\r
542 prout("Beg your pardon, Captain?");
\r
545 int isit(char *s) {
\r
546 /* New function -- compares s to scaned citem and returns true if it
\r
547 matches to the length of s */
\r
549 return strncmp(s, citem, max(1, strlen(citem))) == 0;
\r
554 void debugme(void) {
\r
555 proutn("Reset levels? ");
\r
557 if (energy < inenrg) energy = inenrg;
\r
562 proutn("Reset damage? ");
\r
565 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
\r
568 proutn("Toggle idebug? ");
\r
571 if (idebug) prout("Debug output ON");
\r
572 else prout("Debug output OFF");
\r
574 proutn("Cause selective damage? ");
\r
577 for (i=1; i <= NDEVICES; i++) {
\r
583 if (key == IHALPHA && isit("y")) {
\r
585 if (i == DRADIO) stdamtim = game.state.date;
\r
589 proutn("Examine/change events? ");
\r
592 for (i = 1; i < NEVENTS; i++) {
\r
594 if (future[i] == 1e30) continue;
\r
596 case FSNOVA: proutn("Supernova "); break;
\r
597 case FTBEAM: proutn("T Beam "); break;
\r
598 case FSNAP: proutn("Snapshot "); break;
\r
599 case FBATTAK: proutn("Base Attack "); break;
\r
600 case FCDBAS: proutn("Base Destroy "); break;
\r
601 case FSCMOVE: proutn("SC Move "); break;
\r
602 case FSCDBAS: proutn("SC Base Destroy "); break;
\r
604 proutn("%.2f", future[i]-game.state.date);
\r
608 if (key == IHREAL) {
\r
609 future[i] = game.state.date + aaitem;
\r