1 #define INCLUDED // Define externs here
\r
11 static char line[128], *linep = line;
\r
12 static int linecount; /* for paging */
\r
14 static void clearscreen(void);
\r
16 /* Compared to original version, I've changed the "help" command to
\r
17 "call" and the "terminate" command to "quit" to better match
\r
18 user expectations. The DECUS version apparently made those changes
\r
19 as well as changing "freeze" to "save". However I like "freeze".
\r
21 When I got a later version of Super Star Trek that I was converting
\r
22 from, I added the emexit command.
\r
24 That later version also mentions srscan and lrscan working when
\r
25 docked (using the starbase's scanners), so I made some changes here
\r
26 to do this (and indicating that fact to the player), and then realized
\r
27 the base would have a subspace radio as well -- doing a Chart when docked
\r
28 updates the star chart, and all radio reports will be heard. The Dock
\r
29 command will also give a report if a base is under attack.
\r
31 Movecom no longer reports movement if sensors are damaged so you wouldn't
\r
36 1. Better base positioning at startup
\r
38 2. deathray improvement (but keeping original failure alternatives)
\r
42 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
\r
43 move in Expert and Emeritus games. This code could use improvement.
\r
45 5. The deep space probe looks interesting! DECUS version
\r
47 6. Perhaps cloaking to be added later? BSD version
\r
53 static char *commands[] = {
\r
89 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
\r
91 static void listCommands(int x) {
\r
92 prout(" SRSCAN MOVE PHASERS CALL\n"
\r
93 " STATUS IMPULSE PHOTONS ABANDON\n"
\r
94 " LRSCAN WARP SHIELDS DESTRUCT\n"
\r
95 " CHART REST DOCK QUIT\n"
\r
96 " DAMAGES REPORT SENSORS ORBIT\n"
\r
97 " TRANSPORT MINE CRYSTALS SHUTTLE\n"
\r
98 " PLANETS REQUEST DEATHRAY FREEZE\n"
\r
99 " COMPUTER EMEXIT PROBE COMMANDS");
\r
100 if (x) prout(" HELP");
\r
103 static void helpme(void) {
\r
108 /* Give help on commands */
\r
112 if (key == IHEOL) {
\r
113 proutn("Help on what command?");
\r
116 if (key == IHEOL) return;
\r
117 for (i = 0; i < NUMCOMMANDS; i++) {
\r
118 if (strcmp(commands[i], citem)==0) break;
\r
120 if (i != NUMCOMMANDS) break;
\r
122 prout("Valid commands:");
\r
123 listCommands(FALSE);
\r
129 strcpy(cmdbuf, " ABBREV");
\r
132 strcpy(cmdbuf, " Mnemonic: ");
\r
134 while ((cmdbuf[j+13] = toupper(commands[i][j])) != 0) j++;
\r
136 fp = fopen("sst.doc", "r");
\r
138 prout("Spock- \"Captain, that information is missing from the");
\r
139 prout(" computer. You need to find SST.DOC and put it in the");
\r
140 prout(" current directory.\"");
\r
143 i = strlen(cmdbuf);
\r
145 if (fgets(linebuf, 132, fp) == NULL) {
\r
146 prout("Spock- \"Captain, there is no information on that command.\"");
\r
150 } while (strncmp(linebuf, cmdbuf, i) != 0);
\r
153 prout("Spock- \"Captain, I've found the following information:\"");
\r
157 if (linebuf[0]!=12) { // ignore page break lines
\r
158 linebuf[strlen(linebuf)-1] = '\0'; // No \n at end
\r
161 fgets(linebuf,132,fp);
\r
162 } while (strstr(linebuf, "******")==NULL);
\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 switch (i) { /* command switch */
\r
202 if (ididit) hitme = TRUE;
\r
206 if (ididit) hitme = TRUE;
\r
232 if (ididit) hitme = TRUE;
\r
240 case 13: // sensors
\r
245 if (ididit) hitme = TRUE;
\r
247 case 15: // transport "beam"
\r
252 if (ididit) hitme = TRUE;
\r
254 case 17: // crystals
\r
257 case 18: // shuttle
\r
259 if (ididit) hitme = TRUE;
\r
261 case 19: // Planet list
\r
264 case 20: // Status information
\r
267 case 21: // Game Report
\r
270 case 22: // use COMPUTER!
\r
274 listCommands(TRUE);
\r
276 case 24: // Emergency exit
\r
277 clearscreen(); // Hide screen
\r
278 freeze(TRUE); // forced save
\r
279 exit(1); // And quick exit
\r
282 probe(); // Launch probe
\r
284 case 26: // Abandon Ship
\r
287 case 27: // Self Destruct
\r
290 case 28: // Save Game
\r
293 prout("WARNING--Frozen games produce no plaques!");
\r
295 case 29: // Try a desparation measure
\r
297 if (ididit) hitme = TRUE;
\r
299 case 30: // What do we want for debug???
\r
304 case 31: // Call for help
\r
308 alldone = 1; // quit the game
\r
310 if (idebug) score();
\r
314 helpme(); // get help
\r
318 if (alldone) break; // Game has ended
\r
320 if (idebug) prout("2500");
\r
324 if (alldone) break; // Events did us in
\r
326 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
\r
330 if (nenhere == 0) movetho();
\r
331 if (hitme && justin==0) {
\r
333 if (alldone) break;
\r
334 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
\r
342 if (alldone) break;
\r
347 int main(int argc, char **argv) {
\r
354 fromcommandline = 1;
\r
356 while (--argc > 0) {
\r
357 strcat(line, *(++argv));
\r
361 else fromcommandline = 0;
\r
364 while (TRUE) { /* Play a game */
\r
375 if (tourn && alldone) {
\r
376 printf("Do you want your score recorded?");
\r
382 printf("Do you want to play again?");
\r
386 prout("May the Great Bird of the Galaxy roost upon your home planet.");
\r
390 void cramen(int i) {
\r
391 /* return an enemy */
\r
395 case IHR: s = "Romulan"; break;
\r
396 case IHK: s = "Klingon"; break;
\r
397 case IHC: s = "Commander"; break;
\r
398 case IHS: s = "Super-commander"; break;
\r
399 case IHSTAR: s = "Star"; break;
\r
400 case IHP: s = "Planet"; break;
\r
401 case IHB: s = "Starbase"; break;
\r
402 case IHBLANK: s = "Black hole"; break;
\r
403 case IHT: s = "Tholian"; break;
\r
404 case IHWEB: s = "Tholian web"; break;
\r
405 default: s = "Unknown??"; break;
\r
410 void cramlc(int key, int x, int y) {
\r
411 if (key == 1) proutn(" Quadrant");
\r
412 else if (key == 2) proutn(" Sector");
\r
419 void crmena(int i, int enemy, int key, int x, int y) {
\r
420 if (i == 1) proutn("***");
\r
426 void crmshp(void) {
\r
429 case IHE: s = "Enterprise"; break;
\r
430 case IHF: s = "Faerie Queene"; break;
\r
431 default: s = "Ship???"; break;
\r
437 prouts("******************************************************");
\r
441 double expran(double avrage) {
\r
442 return -avrage*log(1e-7 + Rand());
\r
445 double Rand(void) {
\r
446 return rand()/(1.0 + (double)RAND_MAX);
\r
449 void iran8(int *i, int *j) {
\r
450 *i = Rand()*8.0 + 1.0;
\r
451 *j = Rand()*8.0 + 1.0;
\r
454 void iran10(int *i, int *j) {
\r
455 *i = Rand()*10.0 + 1.0;
\r
456 *j = Rand()*10.0 + 1.0;
\r
466 /* return IHEOL next time */
\r
482 // Read a line if nothing here
\r
484 if (linep != line) {
\r
488 fgets(line, sizeof(line), stdin);
\r
489 line[strlen(line)-1] = '\0';
\r
492 // Skip leading white space
\r
493 while (*linep == ' ') linep++;
\r
499 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
\r
500 // treat as a number
\r
501 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
\r
502 linep = line; // Invalid numbers are ignored
\r
514 while (*linep && *linep!=' ') {
\r
515 if ((cp - citem) < 9) *cp++ = tolower(*linep);
\r
527 if (*citem == 'y') return TRUE;
\r
528 if (*citem == 'n') return FALSE;
\r
529 proutn("Please answer with \"Y\" or \"N\":");
\r
533 void cramf(double x, int w, int d) {
\r
535 sprintf(buf, "%*.*f", w, d, x);
\r
539 void crami(int i, int w) {
\r
541 sprintf(buf, "%*d", w, i);
\r
545 double square(double i) { return i*i; }
\r
547 static void clearscreen(void) {
\r
548 /* Somehow we need to clear the screen */
\r
549 #ifdef __BORLANDC__
\r
550 extern void clrscr(void);
\r
553 proutn("\033[2J"); /* Hope for an ANSI display */
\r
557 /* We will pull these out in case we want to do something special later */
\r
559 void pause(int i) {
\r
563 prout("[ANOUNCEMENT ARRIVING...]");
\r
565 prout("[IMPORTANT ANNOUNCEMENT ARRIVING -- HIT SPACE BAR TO CONTINUE]");
\r
570 proutn("[CONTINUE?]");
\r
572 proutn("[HIT SPACE BAR TO CONTINUE]");
\r
586 if (linecount >= 23)
\r
594 void proutn(char *s) {
\r
598 void prout(char *s) {
\r
603 void prouts(char *s) {
\r
605 /* print slowly! */
\r
607 endTime = clock() + CLOCKS_PER_SEC*0.05;
\r
608 while (clock() < endTime) ;
\r
617 prout("Beg your pardon, Captain?");
\r
620 int isit(char *s) {
\r
621 /* New function -- compares s to scaned citem and returns true if it
\r
622 matches to the length of s */
\r
624 return strncmp(s, citem, max(1, strlen(citem))) == 0;
\r
629 void debugme(void) {
\r
630 proutn("Reset levels? ");
\r
632 if (energy < inenrg) energy = inenrg;
\r
637 proutn("Reset damage? ");
\r
640 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
\r
643 proutn("Toggle idebug? ");
\r
646 if (idebug) prout("Debug output ON");
\r
647 else prout("Debug output OFF");
\r
649 proutn("Cause selective damage? ");
\r
652 for (i=1; i <= NDEVICES; i++) {
\r
658 if (key == IHALPHA && isit("y")) {
\r
660 if (i == DRADIO) stdamtim = game.state.date;
\r
664 proutn("Examine/change events? ");
\r
667 for (i = 1; i < NEVENTS; i++) {
\r
669 if (future[i] == 1e30) continue;
\r
671 case FSNOVA: proutn("Supernova "); break;
\r
672 case FTBEAM: proutn("T Beam "); break;
\r
673 case FSNAP: proutn("Snapshot "); break;
\r
674 case FBATTAK: proutn("Base Attack "); break;
\r
675 case FCDBAS: proutn("Base Destroy "); break;
\r
676 case FSCMOVE: proutn("SC Move "); break;
\r
677 case FSCDBAS: proutn("SC Base Destroy "); break;
\r
679 cramf(future[i]-game.state.date, 8, 2);
\r
683 if (key == IHREAL) {
\r
684 future[i] = game.state.date + aaitem;
\r