1 #define INCLUDED // Define externs here
10 #define SSTDOC "sst.doc"
13 static char line[128], *linep = line;
17 Here are Tom Almy's changes:
19 Compared to original version, I've changed the "help" command to
20 "call" and the "terminate" command to "quit" to better match
21 user expectations. The DECUS version apparently made those changes
22 as well as changing "freeze" to "save". However I like "freeze".
24 When I got a later version of Super Star Trek that I was converting
25 from, I added the emexit command.
27 That later version also mentions srscan and lrscan working when
28 docked (using the starbase's scanners), so I made some changes here
29 to do this (and indicating that fact to the player), and then realized
30 the base would have a subspace radio as well -- doing a Chart when docked
31 updates the star chart, and all radio reports will be heard. The Dock
32 command will also give a report if a base is under attack.
34 Movecom no longer reports movement if sensors are damaged so you wouldn't
39 1. Better base positioning at startup
41 2. Deathray improvement (but keeping original failure alternatives)
45 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
46 move in Expert and Emeritus games. This code could use improvement.
48 5. The deep space probe looks interesting! DECUS version
50 6. Perhaps cloaking to be added later? BSD version
52 Here are Stas Sergeev's changes (controlled by the proprocessor symbol
53 SERGEEV, not yet completely merged):
55 1. The Space Thingy can be shoved, if you it ram, and can fire back if
58 1 The Tholian can be hit with phasers
60 2. When you are docked, base covers you with an almost invincible shields
61 (a commander can still ram you, or a Romulan can destroy the base,
62 or a SCom can even succeed with direct attack IIRC, but this rarely
65 3. SCom can't escape from you if no more enemies remain (without this,
66 chasing SCom can take an eternity).
68 4. Probe target you enter is now the destination quadrant. Before I don't
69 remember what it was, but it was something I had difficulty using)
71 5. Secret password is now autogenerated.
73 6. "Plaque" is adjusted for A4 paper:)
75 7. Phasers now tells you how much energy needed, but only if the computer
78 8. Planets are auto-scanned when you enter the quadrant.
80 9. Mining or using crystals in presense of enemy now yields an attack.
81 There are other minor adjustments to what yields an attack
84 10. Ramming a black hole is no longer instant death. There is a
85 chance you might get timewarped instead.
87 11. "freeze" command reverts to "save", most people will understand this
90 Eric Raymond's changes:
92 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
110 {"PHASERS", PHASERS},
112 {"TORPEDO", TORPEDO},
113 {"PHOTONS", TORPEDO},
117 {"SHIELDS", SHIELDS},
121 {"DAMAGES", DAMAGES},
125 {"IMPULSE", IMPULSE},
134 {"SENSORS", SENSORS},
139 {"TRANSPORT", TRANSPORT},
143 {"CRYSTALS", CRYSTALS},
145 {"SHUTTLE", SHUTTLE},
147 {"PLANETS", PLANETS},
150 {"REQUEST", REQUEST},
155 {"COMPUTER", COMPUTER},
157 {"COMMANDS", COMMANDS},
166 {"ABANDON", ABANDON},
168 {"DESTRUCT", DESTRUCT},
170 {"DEATHRAY", DEATHRAY},
183 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
185 static void listCommands(int x) {
187 prout("LEGAL COMMANDS ARE:");
188 for (i = 0; i < NUMCOMMANDS; i++) {
189 proutn("%-12s ", commands[i].name);
196 static void helpme(void) {
198 char cmdbuf[32], *cp;
201 /* Give help on commands */
207 setwnd(BOTTOM_WINDOW);
209 proutn("Help on what command? ");
213 setwnd(LOWER_WINDOW);
215 if (key == IHEOL) return;
216 for (i = 0; i < NUMCOMMANDS; i++) {
217 if (strcasecmp(commands[i].name, citem)==0) {
218 i = commands[i].value;
222 if (i != NUMCOMMANDS) break;
224 prout("Valid commands:");
231 strcpy(cmdbuf, " ABBREV");
234 for (j = 0; commands[i].name[j]; j++)
235 cmdbuf[j] = toupper(commands[i].name[j]);
238 fp = fopen(SSTDOC, "r");
240 prout("Spock- \"Captain, that information is missing from the");
241 prout(" computer.\"");
243 * This used to continue: "You need to find SST.DOC and put
244 * it in the current directory."
249 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
250 prout("Spock- \"Captain, there is no information on that command.\"");
254 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
255 for (cp = linebuf+3; isspace(*cp); cp++)
257 linebuf[strlen(linebuf)-1] = '\0';
258 if (strcasecmp(cp, cmdbuf) == 0)
264 prout("Spock- \"Captain, I've found the following information:\"");
267 while (fgets(linebuf, sizeof(linebuf),fp)) {
268 if (strstr(linebuf, "******"))
275 void drawmaps(short l) {
276 /* hook to be called after moving to redraw maps */
278 _setcursortype(_NOCURSOR);
280 if (l!=2) setwnd(LEFTUPPER_WINDOW);
285 setwnd(SRSCAN_WINDOW);
288 setwnd(LRSCAN_WINDOW);
292 _setcursortype(_NORMALCURSOR);
297 static void makemoves(void) {
301 setwnd(LOWER_WINDOW);
303 while (TRUE) { /* command loop */
305 while (TRUE) { /* get a command */
312 setwnd(BOTTOM_WINDOW);
316 if (scan() == IHEOL) {
318 _setcursortype(_NOCURSOR);
319 setwnd(LOWER_WINDOW);
322 _setcursortype(_NORMALCURSOR);
329 setwnd(LOWER_WINDOW);
332 for (i=0; i < ABANDON; i++)
333 if (isit(commands[i].name)) {
334 i = commands[i].value;
337 if (i < ABANDON) break;
338 for (; i < NUMCOMMANDS; i++)
339 if (strcasecmp(commands[i].name, citem) == 0) {
340 i = commands[i].value;
343 if (i < NUMCOMMANDS) break;
347 commandhook(commands[i].name, TRUE);
348 switch (i) { /* command switch */
350 case SRSCAN: // srscan
353 case LRSCAN: // lrscan
357 case PHASERS: // phasers
359 if (ididit) hitme = TRUE;
361 case TORPEDO: // photons
363 if (ididit) hitme = TRUE;
368 case SHIELDS: // shields
377 if (ididit) attack(0);
379 case DAMAGES: // damages
385 case IMPULSE: // impulse
390 if (ididit) hitme = TRUE;
399 case SENSORS: // sensors
405 if (ididit) hitme = TRUE;
407 case TRANSPORT: // transport "beam"
412 if (ididit) hitme = TRUE;
414 case CRYSTALS: // crystals
416 if (ididit) hitme = TRUE;
418 case SHUTTLE: // shuttle
420 if (ididit) hitme = TRUE;
422 case PLANETS: // Planet list
425 case REPORT: // Game Report
428 case COMPUTER: // use COMPUTER!
434 case EMEXIT: // Emergency exit
435 clrscr(); // Hide screen
436 freeze(TRUE); // forced save
437 exit(1); // And quick exit
440 probe(); // Launch probe
441 if (ididit) hitme = TRUE;
443 case ABANDON: // Abandon Ship
446 case DESTRUCT: // Self Destruct
449 case SAVE: // Save Game
455 prout("WARNING--Saved games produce no plaques!");
457 case DEATHRAY: // Try a desparation measure
459 if (ididit) hitme = TRUE;
461 case DEBUGCMD: // What do we want for debug???
466 case MAYDAY: // Call for help
468 if (ididit) hitme = TRUE;
471 alldone = 1; // quit the game
477 helpme(); // get help
480 commandhook(commands[i].name, FALSE);
482 if (alldone) break; // Game has ended
484 if (idebug) prout("2500");
488 if (alldone) break; // Events did us in
490 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
494 if (hitme && justin==0) {
497 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
510 int main(int argc, char **argv) {
511 int i, option, usecurses = TRUE;
513 while ((option = getopt(argc, argv, "t")) != -1) {
519 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
530 setwnd(FULLSCREEN_WINDOW);
533 for (i = optind; i < argc; i++) {
534 strcat(line, argv[i]);
537 while (TRUE) { /* Play a game */
539 setup(line[0] == '\0');
549 if (tourn && alldone) {
550 proutn("Do you want your score recorded?");
556 proutn("Do you want to play again? ");
559 setwnd(FULLSCREEN_WINDOW);
567 prout("May the Great Bird of the Galaxy roost upon your home planet.");
573 /* return an enemy */
577 case IHR: s = "Romulan"; break;
578 case IHK: s = "Klingon"; break;
579 case IHC: s = "Commander"; break;
580 case IHS: s = "Super-commander"; break;
581 case IHSTAR: s = "Star"; break;
582 case IHP: s = "Planet"; break;
583 case IHB: s = "Starbase"; break;
584 case IHBLANK: s = "Black hole"; break;
585 case IHT: s = "Tholian"; break;
586 case IHWEB: s = "Tholian web"; break;
587 case IHQUEST: s = "Stranger"; break;
588 default: s = "Unknown??"; break;
593 char *cramlc(enum loctype key, int x, int y) {
596 if (key == quadrant) strcpy(buf, "Quadrant ");
597 else if (key == sector) strcpy(buf, "Sector ");
598 sprintf(buf+strlen(buf), "%d - %d", x, y);
602 void crmena(int i, int enemy, int key, int x, int y) {
603 if (i == 1) proutn("***");
606 proutn(cramlc(key, x, y));
612 case IHE: s = "Enterprise"; break;
613 case IHF: s = "Faerie Queene"; break;
614 default: s = "Ship???"; break;
620 prouts("******************************************************");
624 double expran(double avrage) {
625 return -avrage*log(1e-7 + Rand());
629 return rand()/(1.0 + (double)RAND_MAX);
632 void iran8(int *i, int *j) {
633 *i = Rand()*8.0 + 1.0;
634 *j = Rand()*8.0 + 1.0;
637 void iran10(int *i, int *j) {
638 *i = Rand()*10.0 + 1.0;
639 *j = Rand()*10.0 + 1.0;
648 /* return IHEOL next time */
661 // Read a line if nothing here
667 getline(line, sizeof(line));
670 if (curwnd==BOTTOM_WINDOW){
672 setwnd(LOWER_WINDOW);
678 // Skip leading white space
679 while (*linep == ' ') linep++;
685 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
688 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
689 linep = line; // Invalid numbers are ignored
701 while (*linep && *linep!=' ') {
702 if ((cp - citem) < 9) *cp++ = tolower(*linep);
714 if (*citem == 'y') return TRUE;
715 if (*citem == 'n') return FALSE;
716 proutn("Please answer with \"Y\" or \"N\": ");
723 prout("Beg your pardon, Captain?");
727 /* New function -- compares s to scaned citem and returns true if it
728 matches to the length of s */
730 return strncasecmp(s, citem, max(1, strlen(citem))) == 0;
736 proutn("Reset levels? ");
738 if (energy < inenrg) energy = inenrg;
743 proutn("Reset damage? ");
746 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
749 proutn("Toggle idebug? ");
752 if (idebug) prout("Debug output ON");
753 else prout("Debug output OFF");
755 proutn("Cause selective damage? ");
758 for (i=1; i <= NDEVICES; i++) {
764 if (key == IHALPHA && isit("y")) {
766 if (i == DRADIO) stdamtim = game.state.date;
770 proutn("Examine/change events? ");
773 for (i = 1; i < NEVENTS; i++) {
775 if (future[i] == 1e30) continue;
777 case FSNOVA: proutn("Supernova "); break;
778 case FTBEAM: proutn("T Beam "); break;
779 case FSNAP: proutn("Snapshot "); break;
780 case FBATTAK: proutn("Base Attack "); break;
781 case FCDBAS: proutn("Base Destroy "); break;
782 case FSCMOVE: proutn("SC Move "); break;
783 case FSCDBAS: proutn("SC Base Destroy "); break;
785 proutn("%.2f", future[i]-game.state.date);
790 future[i] = game.state.date + aaitem;