1 #define INCLUDED // Define externs here
12 #define SSTDOC "sst.doc"
15 static char line[128], *linep = line;
19 Here are Tom Almy's changes:
21 Compared to original version, I've changed the "help" command to
22 "call" and the "terminate" command to "quit" to better match
23 user expectations. The DECUS version apparently made those changes
24 as well as changing "freeze" to "save". However I like "freeze".
26 When I got a later version of Super Star Trek that I was converting
27 from, I added the emexit command.
29 That later version also mentions srscan and lrscan working when
30 docked (using the starbase's scanners), so I made some changes here
31 to do this (and indicating that fact to the player), and then realized
32 the base would have a subspace radio as well -- doing a Chart when docked
33 updates the star chart, and all radio reports will be heard. The Dock
34 command will also give a report if a base is under attack.
36 Movecom no longer reports movement if sensors are damaged so you wouldn't
41 1. Better base positioning at startup
43 2. Deathray improvement (but keeping original failure alternatives)
47 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
48 move in Expert and Emeritus games. This code could use improvement.
50 5. The deep space probe looks interesting! DECUS version
52 6. Perhaps cloaking to be added later? BSD version
54 Here are Stas Sergeev's changes (controlled by the proprocessor symbol
55 SERGEEV, not yet completely merged):
57 1. The Space Thingy can be shoved, if you it ram, and can fire back if
60 1 The Tholian can be hit with phasers
62 2. When you are docked, base covers you with an almost invincible shields
63 (a commander can still ram you, or a Romulan can destroy the base,
64 or a SCom can even succeed with direct attack IIRC, but this rarely
67 3. SCom can't escape from you if no more enemies remain (without this,
68 chasing SCom can take an eternity).
70 4. Probe target you enter is now the destination quadrant. Before I don't
71 remember what it was, but it was something I had difficulty using)
73 5. Secret password is now autogenerated.
75 6. "Plaque" is adjusted for A4 paper:)
77 7. Phasers now tells you how much energy needed, but only if the computer
80 8. Planets are auto-scanned when you enter the quadrant.
82 9. Mining or using crystals in presense of enemy now yields an attack.
83 There are other minor adjustments to what yields an attack
86 10. Ramming a black hole is no longer instant death. There is a
87 chance you might get timewarped instead.
91 static char *commands[] = {
155 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}};
159 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
161 static void listCommands(int x) {
162 proutn ("LEGAL COMMANDS ARE:\n\r"
163 " MOVE PHASERS SOS PROBE\n\r"
164 " COMPUTER IMPULSE TORPEDO ABANDON\n\r"
165 " EMEXIT WARP SHIELDS DESTRUCT\n\r"
166 " CHART REST DOCK QUIT\n\r"
167 " DAMAGES REPORT SCORE ORBIT\n\r"
168 " TRANSPORT MINE CRYSTALS SHUTTLE\n\r"
169 " PLANETS DEATHRAY SAVE COMMANDS\n\r");
170 if (x) prout(" HELP");
173 static void helpme(void) {
175 char cmdbuf[32], *cp;
178 /* Give help on commands */
186 proutn("Help on what command? ");
192 if (key == IHEOL) return;
193 for (i = 0; i < NUMCOMMANDS; i++) {
194 if (strcmp(commands[i], citem)==0) break;
196 if (i != NUMCOMMANDS) break;
198 prout("Valid commands:");
205 strcpy(cmdbuf, " ABBREV");
208 for (j = 0; commands[i][j]; j++)
209 cmdbuf[j] = toupper(commands[i][j]);
212 fp = fopen(SSTDOC, "r");
214 prout("Spock- \"Captain, that information is missing from the");
215 prout(" computer.\"");
217 * This used to continue: "You need to find SST.DOC and put
218 * it in the current directory."
223 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
224 prout("Spock- \"Captain, there is no information on that command.\"");
228 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
229 for (cp = linebuf+3; isspace(*cp); cp++)
231 linebuf[strlen(linebuf)-1] = '\0';
232 if (strcmp(cp, cmdbuf) == 0)
238 prout("Spock- \"Captain, I've found the following information:\"");
241 while (fgets(linebuf, sizeof(linebuf),fp)) {
242 if (strstr(linebuf, "******"))
249 void drawmaps(short l) {
250 /* hook to be called after moving to redraw maps */
252 _setcursortype(_NOCURSOR);
266 _setcursortype(_NORMALCURSOR);
271 static void makemoves(void) {
277 while (TRUE) { /* command loop */
279 while (TRUE) { /* get a command */
290 if (scan() == IHEOL) {
292 _setcursortype(_NOCURSOR);
296 _setcursortype(_NORMALCURSOR);
306 for (i=0; i < 26; i++)
307 if (isit(commands[i]))
310 for (; i < NUMCOMMANDS; i++)
311 if (strcmp(commands[i], citem) == 0) break;
312 if (i < NUMCOMMANDS) break;
316 commandhook(commands[i], TRUE);
317 switch (i) { /* command switch */
328 if (ididit) hitme = TRUE;
332 if (ididit) hitme = TRUE;
346 if (ididit) attack(0);
359 if (ididit) hitme = TRUE;
374 if (ididit) hitme = TRUE;
376 case 15: // transport "beam"
381 if (ididit) hitme = TRUE;
385 if (ididit) hitme = TRUE;
389 if (ididit) hitme = TRUE;
391 case 19: // Planet list
394 case 20: // Status information
397 case 21: // Game Report
400 case 22: // use COMPUTER!
406 case 24: // Emergency exit
408 clrscr(); // Hide screen
410 freeze(TRUE); // forced save
411 exit(1); // And quick exit
414 probe(); // Launch probe
415 if (ididit) hitme = TRUE;
417 case 26: // Abandon Ship
420 case 27: // Self Destruct
423 case 28: // Save Game
429 prout("WARNING--Saved games produce no plaques!");
431 case 29: // Try a desparation measure
433 if (ididit) hitme = TRUE;
435 case 30: // What do we want for debug???
440 case 31: // Call for help
442 if (ididit) hitme = TRUE;
445 alldone = 1; // quit the game
451 helpme(); // get help
454 commandhook(commands[i], FALSE);
456 if (alldone) break; // Game has ended
458 if (idebug) prout("2500");
462 if (alldone) break; // Events did us in
464 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
468 if (hitme && justin==0) {
471 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
484 int main(int argc, char **argv) {
485 int i, option, usecurses = TRUE;
487 while ((option = getopt(argc, argv, "t")) != -1) {
493 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
507 for (i = optind; i < argc; i++) {
508 strcat(line, argv[i]);
511 while (TRUE) { /* Play a game */
513 setup(line[0] == '\0');
523 if (tourn && alldone) {
524 proutn("Do you want your score recorded?");
530 proutn("Do you want to play again? ");
541 prout("May the Great Bird of the Galaxy roost upon your home planet.");
547 /* return an enemy */
551 case IHR: s = "Romulan"; break;
552 case IHK: s = "Klingon"; break;
553 case IHC: s = "Commander"; break;
554 case IHS: s = "Super-commander"; break;
555 case IHSTAR: s = "Star"; break;
556 case IHP: s = "Planet"; break;
557 case IHB: s = "Starbase"; break;
558 case IHBLANK: s = "Black hole"; break;
559 case IHT: s = "Tholian"; break;
560 case IHWEB: s = "Tholian web"; break;
561 case IHQUEST: s = "Stranger"; break;
562 default: s = "Unknown??"; break;
567 char *cramlc(enum loctype key, int x, int y) {
570 if (key == quadrant) strcpy(buf, "Quadrant ");
571 else if (key == sector) strcpy(buf, "Sector ");
572 sprintf(buf+strlen(buf), "%d - %d", x, y);
576 void crmena(int i, int enemy, int key, int x, int y) {
577 if (i == 1) proutn("***");
580 proutn(cramlc(key, x, y));
586 case IHE: s = "Enterprise"; break;
587 case IHF: s = "Faerie Queene"; break;
588 default: s = "Ship???"; break;
594 prouts("******************************************************");
598 double expran(double avrage) {
599 return -avrage*log(1e-7 + Rand());
603 return rand()/(1.0 + (double)RAND_MAX);
606 void iran8(int *i, int *j) {
607 *i = Rand()*8.0 + 1.0;
608 *j = Rand()*8.0 + 1.0;
611 void iran10(int *i, int *j) {
612 *i = Rand()*10.0 + 1.0;
613 *j = Rand()*10.0 + 1.0;
622 /* return IHEOL next time */
635 // Read a line if nothing here
641 getline(line, sizeof(line));
652 // Skip leading white space
653 while (*linep == ' ') linep++;
659 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
662 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
663 linep = line; // Invalid numbers are ignored
675 while (*linep && *linep!=' ') {
676 if ((cp - citem) < 9) *cp++ = tolower(*linep);
688 if (*citem == 'y') return TRUE;
689 if (*citem == 'n') return FALSE;
690 proutn("Please answer with \"Y\" or \"N\": ");
697 prout("Beg your pardon, Captain?");
701 /* New function -- compares s to scaned citem and returns true if it
702 matches to the length of s */
704 return strncmp(s, citem, max(1, strlen(citem))) == 0;
710 proutn("Reset levels? ");
712 if (energy < inenrg) energy = inenrg;
717 proutn("Reset damage? ");
720 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
723 proutn("Toggle idebug? ");
726 if (idebug) prout("Debug output ON");
727 else prout("Debug output OFF");
729 proutn("Cause selective damage? ");
732 for (i=1; i <= NDEVICES; i++) {
738 if (key == IHALPHA && isit("y")) {
740 if (i == DRADIO) stdamtim = game.state.date;
744 proutn("Examine/change events? ");
747 for (i = 1; i < NEVENTS; i++) {
749 if (future[i] == 1e30) continue;
751 case FSNOVA: proutn("Supernova "); break;
752 case FTBEAM: proutn("T Beam "); break;
753 case FSNAP: proutn("Snapshot "); break;
754 case FBATTAK: proutn("Base Attack "); break;
755 case FCDBAS: proutn("Base Destroy "); break;
756 case FSCMOVE: proutn("SC Move "); break;
757 case FSCDBAS: proutn("SC Base Destroy "); break;
759 proutn("%.2f", future[i]-game.state.date);
764 future[i] = game.state.date + aaitem;