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
205 while (TRUE) { /* command loop */
\r
210 while (TRUE) { /* get a command */
\r
213 proutn("COMMAND> ");
\r
214 if (scan() == IHEOL) continue;
\r
215 for (i=0; i < 26; i++)
\r
216 if (isit(commands[i]))
\r
219 for (; i < NUMCOMMANDS; i++)
\r
220 if (strcmp(commands[i], citem) == 0) break;
\r
221 if (i < NUMCOMMANDS) break;
\r
224 prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
\r
225 listCommands(TRUE);
\r
227 else prout("UNRECOGNIZED COMMAND.");
\r
229 commandhook(commands[i], TRUE);
\r
230 switch (i) { /* command switch */
\r
239 if (ididit) hitme = TRUE;
\r
243 if (ididit) hitme = TRUE;
\r
257 if (ididit) attack(0);
\r
270 if (ididit) hitme = TRUE;
\r
278 case 13: // sensors
\r
283 if (ididit) hitme = TRUE;
\r
285 case 15: // transport "beam"
\r
290 if (ididit) hitme = TRUE;
\r
292 case 17: // crystals
\r
295 case 18: // shuttle
\r
297 if (ididit) hitme = TRUE;
\r
299 case 19: // Planet list
\r
302 case 20: // Status information
\r
305 case 21: // Game Report
\r
308 case 22: // use COMPUTER!
\r
312 listCommands(TRUE);
\r
314 case 24: // Emergency exit
\r
315 clearscreen(); // Hide screen
\r
316 freeze(TRUE); // forced save
\r
317 exit(1); // And quick exit
\r
320 probe(); // Launch probe
\r
322 case 26: // Abandon Ship
\r
325 case 27: // Self Destruct
\r
328 case 28: // Save Game
\r
331 prout("WARNING--Frozen games produce no plaques!");
\r
333 case 29: // Try a desparation measure
\r
335 if (ididit) hitme = TRUE;
\r
337 case 30: // What do we want for debug???
\r
342 case 31: // Call for help
\r
346 alldone = 1; // quit the game
\r
348 if (idebug) score();
\r
352 helpme(); // get help
\r
355 commandhook(commands[i], FALSE);
\r
357 if (alldone) break; // Game has ended
\r
359 if (idebug) prout("2500");
\r
363 if (alldone) break; // Events did us in
\r
365 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
\r
369 if (nenhere == 0) movetho();
\r
370 if (hitme && justin==0) {
\r
372 if (alldone) break;
\r
373 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
\r
381 if (alldone) break;
\r
386 int main(int argc, char **argv) {
\r
387 int i, option, usecurses = TRUE;
\r
391 while ((option = getopt(argc, argv, "t")) != -1) {
\r
397 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
\r
402 iostart(usecurses);
\r
405 for (i = optind; i < argc; i++) {
\r
406 strcat(line, argv[i]);
\r
409 while (TRUE) { /* Play a game */
\r
410 setup(line[0] == '\0');
\r
420 if (tourn && alldone) {
\r
421 proutn("Do you want your score recorded?");
\r
427 proutn("Do you want to play again?");
\r
432 puts("May the Great Bird of the Galaxy roost upon your home planet.");
\r
436 void cramen(int i) {
\r
437 /* return an enemy */
\r
441 case IHR: s = "Romulan"; break;
\r
442 case IHK: s = "Klingon"; break;
\r
443 case IHC: s = "Commander"; break;
\r
444 case IHS: s = "Super-commander"; break;
\r
445 case IHSTAR: s = "Star"; break;
\r
446 case IHP: s = "Planet"; break;
\r
447 case IHB: s = "Starbase"; break;
\r
448 case IHBLANK: s = "Black hole"; break;
\r
449 case IHT: s = "Tholian"; break;
\r
450 case IHWEB: s = "Tholian web"; break;
\r
451 case IHQUEST: s = "Stranger"; break;
\r
452 default: s = "Unknown??"; break;
\r
457 char *cramlc(enum loctype key, int x, int y) {
\r
458 static char buf[32];
\r
460 if (key == quadrant) strcpy(buf, "Quadrant ");
\r
461 else if (key == sector) strcpy(buf, "Sector ");
\r
462 sprintf(buf+strlen(buf), "%d-%d", x, y);
\r
466 void crmena(int i, int enemy, int key, int x, int y) {
\r
467 if (i == 1) proutn("***");
\r
470 proutn(cramlc(key, x, y));
\r
473 void crmshp(void) {
\r
476 case IHE: s = "Enterprise"; break;
\r
477 case IHF: s = "Faerie Queene"; break;
\r
478 default: s = "Ship???"; break;
\r
484 prouts("******************************************************");
\r
488 double expran(double avrage) {
\r
489 return -avrage*log(1e-7 + Rand());
\r
492 double Rand(void) {
\r
493 return rand()/(1.0 + (double)RAND_MAX);
\r
496 void iran8(int *i, int *j) {
\r
497 *i = Rand()*8.0 + 1.0;
\r
498 *j = Rand()*8.0 + 1.0;
\r
501 void iran10(int *i, int *j) {
\r
502 *i = Rand()*10.0 + 1.0;
\r
503 *j = Rand()*10.0 + 1.0;
\r
512 /* return IHEOL next time */
\r
525 // Read a line if nothing here
\r
527 if (linep != line) {
\r
531 getline(line, sizeof(line));
\r
534 // Skip leading white space
\r
535 while (*linep == ' ') linep++;
\r
541 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
\r
542 // treat as a number
\r
544 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
\r
545 linep = line; // Invalid numbers are ignored
\r
557 while (*linep && *linep!=' ') {
\r
558 if ((cp - citem) < 9) *cp++ = tolower(*linep);
\r
570 if (*citem == 'y') return TRUE;
\r
571 if (*citem == 'n') return FALSE;
\r
572 proutn("Please answer with \"Y\" or \"N\":");
\r
579 prout("Beg your pardon, Captain?");
\r
582 int isit(char *s) {
\r
583 /* New function -- compares s to scaned citem and returns true if it
\r
584 matches to the length of s */
\r
586 return strncmp(s, citem, max(1, strlen(citem))) == 0;
\r
591 void debugme(void) {
\r
592 proutn("Reset levels? ");
\r
594 if (energy < inenrg) energy = inenrg;
\r
599 proutn("Reset damage? ");
\r
602 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
\r
605 proutn("Toggle idebug? ");
\r
608 if (idebug) prout("Debug output ON");
\r
609 else prout("Debug output OFF");
\r
611 proutn("Cause selective damage? ");
\r
614 for (i=1; i <= NDEVICES; i++) {
\r
620 if (key == IHALPHA && isit("y")) {
\r
622 if (i == DRADIO) stdamtim = game.state.date;
\r
626 proutn("Examine/change events? ");
\r
629 for (i = 1; i < NEVENTS; i++) {
\r
631 if (future[i] == 1e30) continue;
\r
633 case FSNOVA: proutn("Supernova "); break;
\r
634 case FTBEAM: proutn("T Beam "); break;
\r
635 case FSNAP: proutn("Snapshot "); break;
\r
636 case FBATTAK: proutn("Base Attack "); break;
\r
637 case FCDBAS: proutn("Base Destroy "); break;
\r
638 case FSCMOVE: proutn("SC Move "); break;
\r
639 case FSCDBAS: proutn("SC Base Destroy "); break;
\r
641 proutn("%.2f", future[i]-game.state.date);
\r
645 if (key == IHREAL) {
\r
646 future[i] = game.state.date + aaitem;
\r