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},
151 {"COMPUTER", COMPUTER},
153 {"COMMANDS", COMMANDS},
162 {"ABANDON", ABANDON},
164 {"DESTRUCT", DESTRUCT},
166 {"DEATHRAY", DEATHRAY},
179 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
181 static void listCommands(int x) {
183 prout("LEGAL COMMANDS ARE:");
184 for (i = 0; i < NUMCOMMANDS; i++) {
185 proutn("%-12s ", commands[i].name);
192 static void helpme(void) {
194 char cmdbuf[32], *cp;
197 /* Give help on commands */
203 setwnd(BOTTOM_WINDOW);
205 proutn("Help on what command? ");
209 setwnd(LOWER_WINDOW);
211 if (key == IHEOL) return;
212 for (i = 0; i < NUMCOMMANDS; i++) {
213 if (strcasecmp(commands[i].name, citem)==0) {
214 i = commands[i].value;
218 if (i != NUMCOMMANDS) break;
220 prout("Valid commands:");
227 strcpy(cmdbuf, " ABBREV");
230 for (j = 0; commands[i].name[j]; j++)
231 cmdbuf[j] = toupper(commands[i].name[j]);
234 fp = fopen(SSTDOC, "r");
236 prout("Spock- \"Captain, that information is missing from the");
237 prout(" computer.\"");
239 * This used to continue: "You need to find SST.DOC and put
240 * it in the current directory."
245 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
246 prout("Spock- \"Captain, there is no information on that command.\"");
250 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
251 for (cp = linebuf+3; isspace(*cp); cp++)
253 linebuf[strlen(linebuf)-1] = '\0';
254 if (strcasecmp(cp, cmdbuf) == 0)
260 prout("Spock- \"Captain, I've found the following information:\"");
263 while (fgets(linebuf, sizeof(linebuf),fp)) {
264 if (strstr(linebuf, "******"))
271 void drawmaps(short l) {
272 /* hook to be called after moving to redraw maps */
274 _setcursortype(_NOCURSOR);
276 if (l!=2) setwnd(LEFTUPPER_WINDOW);
281 setwnd(SRSCAN_WINDOW);
284 setwnd(LRSCAN_WINDOW);
288 _setcursortype(_NORMALCURSOR);
293 static void makemoves(void) {
297 setwnd(LOWER_WINDOW);
299 while (TRUE) { /* command loop */
301 while (TRUE) { /* get a command */
308 setwnd(BOTTOM_WINDOW);
312 if (scan() == IHEOL) {
314 _setcursortype(_NOCURSOR);
315 setwnd(LOWER_WINDOW);
318 _setcursortype(_NORMALCURSOR);
325 setwnd(LOWER_WINDOW);
328 for (i=0; i < ABANDON; i++)
329 if (isit(commands[i].name)) {
330 i = commands[i].value;
333 if (i < ABANDON) break;
334 for (; i < NUMCOMMANDS; i++)
335 if (strcasecmp(commands[i].name, citem) == 0) {
336 i = commands[i].value;
339 if (i < NUMCOMMANDS) break;
343 commandhook(commands[i].name, TRUE);
344 switch (i) { /* command switch */
346 case SRSCAN: // srscan
349 case LRSCAN: // lrscan
353 case PHASERS: // phasers
355 if (ididit) hitme = TRUE;
357 case TORPEDO: // photons
359 if (ididit) hitme = TRUE;
364 case SHIELDS: // shields
373 if (ididit) attack(0);
375 case DAMAGES: // damages
381 case IMPULSE: // impulse
386 if (ididit) hitme = TRUE;
395 case SENSORS: // sensors
401 if (ididit) hitme = TRUE;
403 case TRANSPORT: // transport "beam"
408 if (ididit) hitme = TRUE;
410 case CRYSTALS: // crystals
412 if (ididit) hitme = TRUE;
414 case SHUTTLE: // shuttle
416 if (ididit) hitme = TRUE;
418 case PLANETS: // Planet list
421 case REPORT: // Game Report
424 case COMPUTER: // use COMPUTER!
430 case EMEXIT: // Emergency exit
431 clrscr(); // Hide screen
432 freeze(TRUE); // forced save
433 exit(1); // And quick exit
436 probe(); // Launch probe
437 if (ididit) hitme = TRUE;
439 case ABANDON: // Abandon Ship
442 case DESTRUCT: // Self Destruct
445 case SAVE: // Save Game
451 prout("WARNING--Saved games produce no plaques!");
453 case DEATHRAY: // Try a desparation measure
455 if (ididit) hitme = TRUE;
457 case DEBUGCMD: // What do we want for debug???
462 case MAYDAY: // Call for help
464 if (ididit) hitme = TRUE;
467 alldone = 1; // quit the game
473 helpme(); // get help
476 commandhook(commands[i].name, FALSE);
478 if (alldone) break; // Game has ended
480 if (idebug) prout("2500");
484 if (alldone) break; // Events did us in
486 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
490 if (hitme && justin==0) {
493 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
506 int main(int argc, char **argv) {
507 int i, option, usecurses = TRUE;
509 while ((option = getopt(argc, argv, "t")) != -1) {
515 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
526 setwnd(FULLSCREEN_WINDOW);
529 for (i = optind; i < argc; i++) {
530 strcat(line, argv[i]);
533 while (TRUE) { /* Play a game */
535 setup(line[0] == '\0');
545 if (tourn && alldone) {
546 proutn("Do you want your score recorded?");
552 proutn("Do you want to play again? ");
555 setwnd(FULLSCREEN_WINDOW);
563 prout("May the Great Bird of the Galaxy roost upon your home planet.");
569 /* return an enemy */
573 case IHR: s = "Romulan"; break;
574 case IHK: s = "Klingon"; break;
575 case IHC: s = "Commander"; break;
576 case IHS: s = "Super-commander"; break;
577 case IHSTAR: s = "Star"; break;
578 case IHP: s = "Planet"; break;
579 case IHB: s = "Starbase"; break;
580 case IHBLANK: s = "Black hole"; break;
581 case IHT: s = "Tholian"; break;
582 case IHWEB: s = "Tholian web"; break;
583 case IHQUEST: s = "Stranger"; break;
584 default: s = "Unknown??"; break;
589 char *cramlc(enum loctype key, int x, int y) {
592 if (key == quadrant) strcpy(buf, "Quadrant ");
593 else if (key == sector) strcpy(buf, "Sector ");
594 sprintf(buf+strlen(buf), "%d - %d", x, y);
598 void crmena(int i, int enemy, int key, int x, int y) {
599 if (i == 1) proutn("***");
602 proutn(cramlc(key, x, y));
608 case IHE: s = "Enterprise"; break;
609 case IHF: s = "Faerie Queene"; break;
610 default: s = "Ship???"; break;
616 prouts("******************************************************");
620 double expran(double avrage) {
621 return -avrage*log(1e-7 + Rand());
625 return rand()/(1.0 + (double)RAND_MAX);
628 void iran8(int *i, int *j) {
629 *i = Rand()*8.0 + 1.0;
630 *j = Rand()*8.0 + 1.0;
633 void iran10(int *i, int *j) {
634 *i = Rand()*10.0 + 1.0;
635 *j = Rand()*10.0 + 1.0;
644 /* return IHEOL next time */
657 // Read a line if nothing here
663 cgetline(line, sizeof(line));
666 if (curwnd==BOTTOM_WINDOW){
668 setwnd(LOWER_WINDOW);
674 // Skip leading white space
675 while (*linep == ' ') linep++;
681 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
684 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
685 linep = line; // Invalid numbers are ignored
697 while (*linep && *linep!=' ') {
698 if ((cp - citem) < 9) *cp++ = tolower(*linep);
710 if (*citem == 'y') return TRUE;
711 if (*citem == 'n') return FALSE;
712 proutn("Please answer with \"Y\" or \"N\": ");
719 prout("Beg your pardon, Captain?");
723 /* New function -- compares s to scaned citem and returns true if it
724 matches to the length of s */
726 return strncasecmp(s, citem, max(1, strlen(citem))) == 0;
732 proutn("Reset levels? ");
734 if (energy < inenrg) energy = inenrg;
739 proutn("Reset damage? ");
742 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
745 proutn("Toggle idebug? ");
748 if (idebug) prout("Debug output ON");
749 else prout("Debug output OFF");
751 proutn("Cause selective damage? ");
754 for (i=1; i <= NDEVICES; i++) {
760 if (key == IHALPHA && isit("y")) {
762 if (i == DRADIO) stdamtim = game.state.date;
766 proutn("Examine/change events? ");
769 for (i = 1; i < NEVENTS; i++) {
771 if (future[i] == 1e30) continue;
773 case FSNOVA: proutn("Supernova "); break;
774 case FTBEAM: proutn("T Beam "); break;
775 case FSNAP: proutn("Snapshot "); break;
776 case FBATTAK: proutn("Base Attack "); break;
777 case FCDBAS: proutn("Base Destroy "); break;
778 case FSCMOVE: proutn("SC Move "); break;
779 case FSCDBAS: proutn("SC Base Destroy "); break;
781 proutn("%.2f", future[i]-game.state.date);
786 future[i] = game.state.date + aaitem;