1 #define INCLUDED // Define externs here
\r
7 #define SSTDOC "sst.doc"
\r
10 static char line[128], *linep = line;
\r
14 Here are Tom Almy's changes:
\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
49 Here are Stas Sergeev's changes (controlled by the proprocessor symbol
\r
50 SERGEEV, not yet merged):
\r
52 1. The Space Thingy can be shoved, if you it ram, and can fire back if
\r
55 1 The Tholian can be hit with phasers
\r
57 2. When you are docked, base covers you with an almost invincible shields
\r
58 (a commander can still ram you, or a Romulan can destroy the base,
\r
59 or a SCom can even succeed with direct attack IIRC, but this rarely
\r
62 3. SCom can't escape from you if no more enemies remain (without this,
\r
63 chasing SCom can take an eternity).
\r
65 4. Probe target you enter is now the destination quadrant. Before I don't
\r
66 remember what it was, but it was something I had difficulty using)
\r
68 5. Secret password is now autogenerated.
\r
70 6. "Plaque" is adjusted for A4 paper:)
\r
72 7. Phasers now tells you how much energy needed, but only if the computer
\r
75 8. Planets are auto-scanned when you enter the quadrant.
\r
77 9. Mining or using crystals in presense of enemy now yields an attack.
\r
78 There are other minor adjustments to what yields an attack
\r
81 10. Ramming a black hole is no longer instant death.
\r
85 static char *commands[] = {
\r
121 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
\r
123 static void listCommands(int x) {
\r
124 prout(" SRSCAN MOVE PHASERS CALL\n"
\r
125 " STATUS IMPULSE PHOTONS ABANDON\n"
\r
126 " LRSCAN WARP SHIELDS DESTRUCT\n"
\r
127 " CHART REST DOCK QUIT\n"
\r
128 " DAMAGES REPORT SENSORS ORBIT\n"
\r
129 " TRANSPORT MINE CRYSTALS SHUTTLE\n"
\r
130 " PLANETS REQUEST DEATHRAY FREEZE\n"
\r
131 " COMPUTER EMEXIT PROBE COMMANDS");
\r
132 if (x) prout(" HELP");
\r
135 static void helpme(void) {
\r
137 char cmdbuf[32], *cp;
\r
140 /* Give help on commands */
\r
144 if (key == IHEOL) {
\r
145 proutn("Help on what command?");
\r
148 if (key == IHEOL) return;
\r
149 for (i = 0; i < NUMCOMMANDS; i++) {
\r
150 if (strcmp(commands[i], citem)==0) break;
\r
152 if (i != NUMCOMMANDS) break;
\r
154 prout("Valid commands:");
\r
155 listCommands(FALSE);
\r
161 strcpy(cmdbuf, " ABBREV");
\r
164 for (j = 0; commands[i][j]; j++)
\r
165 cmdbuf[j] = toupper(commands[i][j]);
\r
168 fp = fopen(SSTDOC, "r");
\r
170 prout("Spock- \"Captain, that information is missing from the");
\r
171 prout(" computer. You need to find SST.DOC and put it in the");
\r
172 prout(" current directory.\"");
\r
176 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
\r
177 prout("Spock- \"Captain, there is no information on that command.\"");
\r
181 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
\r
182 for (cp = linebuf+3; isspace(*cp); cp++)
\r
184 linebuf[strlen(linebuf)-1] = '\0';
\r
185 if (strcmp(cp, cmdbuf) == 0)
\r
191 prout("Spock- \"Captain, I've found the following information:\"");
\r
194 while (fgets(linebuf, sizeof(linebuf),fp)) {
\r
195 if (strstr(linebuf, "******"))
\r
202 static void makemoves(void) {
\r
204 while (TRUE) { /* command loop */
\r
209 while (TRUE) { /* get a command */
\r
212 proutn("COMMAND> ");
\r
213 if (scan() == IHEOL) continue;
\r
214 for (i=0; i < 26; i++)
\r
215 if (isit(commands[i]))
\r
218 for (; i < NUMCOMMANDS; i++)
\r
219 if (strcmp(commands[i], citem) == 0) break;
\r
220 if (i < NUMCOMMANDS) break;
\r
223 prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
\r
224 listCommands(TRUE);
\r
226 else prout("UNRECOGNIZED COMMAND.");
\r
228 commandhook(commands[i], TRUE);
\r
229 switch (i) { /* command switch */
\r
238 if (ididit) hitme = TRUE;
\r
242 if (ididit) hitme = TRUE;
\r
256 if (ididit) attack(0);
\r
269 if (ididit) hitme = TRUE;
\r
277 case 13: // sensors
\r
282 if (ididit) hitme = TRUE;
\r
284 case 15: // transport "beam"
\r
289 if (ididit) hitme = TRUE;
\r
291 case 17: // crystals
\r
294 case 18: // shuttle
\r
296 if (ididit) hitme = TRUE;
\r
298 case 19: // Planet list
\r
301 case 20: // Status information
\r
304 case 21: // Game Report
\r
307 case 22: // use COMPUTER!
\r
311 listCommands(TRUE);
\r
313 case 24: // Emergency exit
\r
314 clearscreen(); // Hide screen
\r
315 freeze(TRUE); // forced save
\r
316 exit(1); // And quick exit
\r
319 probe(); // Launch probe
\r
321 case 26: // Abandon Ship
\r
324 case 27: // Self Destruct
\r
327 case 28: // Save Game
\r
330 prout("WARNING--Frozen games produce no plaques!");
\r
332 case 29: // Try a desparation measure
\r
334 if (ididit) hitme = TRUE;
\r
336 case 30: // What do we want for debug???
\r
341 case 31: // Call for help
\r
345 alldone = 1; // quit the game
\r
347 if (idebug) score();
\r
351 helpme(); // get help
\r
354 commandhook(commands[i], FALSE);
\r
356 if (alldone) break; // Game has ended
\r
358 if (idebug) prout("2500");
\r
362 if (alldone) break; // Events did us in
\r
364 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
\r
368 if (nenhere == 0) movetho();
\r
369 if (hitme && justin==0) {
\r
371 if (alldone) break;
\r
372 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
\r
380 if (alldone) break;
\r
385 int main(int argc, char **argv) {
\r
386 int i, option, usecurses = TRUE;
\r
387 while ((option = getopt(argc, argv, "t")) != -1) {
\r
393 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
\r
398 iostart(usecurses);
\r
401 for (i = optind; i < argc; i++) {
\r
402 strcat(line, argv[i]);
\r
405 while (TRUE) { /* Play a game */
\r
406 setup(line[0] == '\0');
\r
416 if (tourn && alldone) {
\r
417 proutn("Do you want your score recorded?");
\r
423 proutn("Do you want to play again?");
\r
428 puts("May the Great Bird of the Galaxy roost upon your home planet.");
\r
433 void cramen(int i) {
\r
434 /* return an enemy */
\r
438 case IHR: s = "Romulan"; break;
\r
439 case IHK: s = "Klingon"; break;
\r
440 case IHC: s = "Commander"; break;
\r
441 case IHS: s = "Super-commander"; break;
\r
442 case IHSTAR: s = "Star"; break;
\r
443 case IHP: s = "Planet"; break;
\r
444 case IHB: s = "Starbase"; break;
\r
445 case IHBLANK: s = "Black hole"; break;
\r
446 case IHT: s = "Tholian"; break;
\r
447 case IHWEB: s = "Tholian web"; break;
\r
448 case IHQUEST: s = "Stranger"; break;
\r
449 default: s = "Unknown??"; break;
\r
454 char *cramlc(enum loctype key, int x, int y) {
\r
455 static char buf[32];
\r
457 if (key == quadrant) strcpy(buf, "Quadrant ");
\r
458 else if (key == sector) strcpy(buf, "Sector ");
\r
459 sprintf(buf+strlen(buf), "%d-%d", x, y);
\r
463 void crmena(int i, int enemy, int key, int x, int y) {
\r
464 if (i == 1) proutn("***");
\r
467 proutn(cramlc(key, x, y));
\r
470 void crmshp(void) {
\r
473 case IHE: s = "Enterprise"; break;
\r
474 case IHF: s = "Faerie Queene"; break;
\r
475 default: s = "Ship???"; break;
\r
481 prouts("******************************************************");
\r
485 double expran(double avrage) {
\r
486 return -avrage*log(1e-7 + Rand());
\r
489 double Rand(void) {
\r
490 return rand()/(1.0 + (double)RAND_MAX);
\r
493 void iran8(int *i, int *j) {
\r
494 *i = Rand()*8.0 + 1.0;
\r
495 *j = Rand()*8.0 + 1.0;
\r
498 void iran10(int *i, int *j) {
\r
499 *i = Rand()*10.0 + 1.0;
\r
500 *j = Rand()*10.0 + 1.0;
\r
509 /* return IHEOL next time */
\r
522 // Read a line if nothing here
\r
524 if (linep != line) {
\r
528 getline(line, sizeof(line));
\r
531 // Skip leading white space
\r
532 while (*linep == ' ') linep++;
\r
538 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
\r
539 // treat as a number
\r
541 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
\r
542 linep = line; // Invalid numbers are ignored
\r
554 while (*linep && *linep!=' ') {
\r
555 if ((cp - citem) < 9) *cp++ = tolower(*linep);
\r
567 if (*citem == 'y') return TRUE;
\r
568 if (*citem == 'n') return FALSE;
\r
569 proutn("Please answer with \"Y\" or \"N\":");
\r
576 prout("Beg your pardon, Captain?");
\r
579 int isit(char *s) {
\r
580 /* New function -- compares s to scaned citem and returns true if it
\r
581 matches to the length of s */
\r
583 return strncmp(s, citem, max(1, strlen(citem))) == 0;
\r
588 void debugme(void) {
\r
589 proutn("Reset levels? ");
\r
591 if (energy < inenrg) energy = inenrg;
\r
596 proutn("Reset damage? ");
\r
599 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
\r
602 proutn("Toggle idebug? ");
\r
605 if (idebug) prout("Debug output ON");
\r
606 else prout("Debug output OFF");
\r
608 proutn("Cause selective damage? ");
\r
611 for (i=1; i <= NDEVICES; i++) {
\r
617 if (key == IHALPHA && isit("y")) {
\r
619 if (i == DRADIO) stdamtim = game.state.date;
\r
623 proutn("Examine/change events? ");
\r
626 for (i = 1; i < NEVENTS; i++) {
\r
628 if (future[i] == 1e30) continue;
\r
630 case FSNOVA: proutn("Supernova "); break;
\r
631 case FTBEAM: proutn("T Beam "); break;
\r
632 case FSNAP: proutn("Snapshot "); break;
\r
633 case FBATTAK: proutn("Base Attack "); break;
\r
634 case FCDBAS: proutn("Base Destroy "); break;
\r
635 case FSCMOVE: proutn("SC Move "); break;
\r
636 case FSCDBAS: proutn("SC Base Destroy "); break;
\r
638 proutn("%.2f", future[i]-game.state.date);
\r
642 if (key == IHREAL) {
\r
643 future[i] = game.state.date + aaitem;
\r