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. There is a
\r
82 chance you might get timewarped instead.
\r
86 static char *commands[] = {
\r
122 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
\r
124 static void listCommands(int x) {
\r
125 prout(" SRSCAN MOVE PHASERS CALL\n"
\r
126 " STATUS IMPULSE PHOTONS ABANDON\n"
\r
127 " LRSCAN WARP SHIELDS DESTRUCT\n"
\r
128 " CHART REST DOCK QUIT\n"
\r
129 " DAMAGES REPORT SENSORS ORBIT\n"
\r
130 " TRANSPORT MINE CRYSTALS SHUTTLE\n"
\r
131 " PLANETS REQUEST DEATHRAY FREEZE\n"
\r
132 " COMPUTER EMEXIT PROBE COMMANDS");
\r
133 if (x) prout(" HELP");
\r
136 static void helpme(void) {
\r
138 char cmdbuf[32], *cp;
\r
141 /* Give help on commands */
\r
145 if (key == IHEOL) {
\r
146 proutn("Help on what command?");
\r
149 if (key == IHEOL) return;
\r
150 for (i = 0; i < NUMCOMMANDS; i++) {
\r
151 if (strcmp(commands[i], citem)==0) break;
\r
153 if (i != NUMCOMMANDS) break;
\r
155 prout("Valid commands:");
\r
156 listCommands(FALSE);
\r
162 strcpy(cmdbuf, " ABBREV");
\r
165 for (j = 0; commands[i][j]; j++)
\r
166 cmdbuf[j] = toupper(commands[i][j]);
\r
169 fp = fopen(SSTDOC, "r");
\r
171 prout("Spock- \"Captain, that information is missing from the");
\r
172 prout(" computer. You need to find SST.DOC and put it in the");
\r
173 prout(" current directory.\"");
\r
177 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
\r
178 prout("Spock- \"Captain, there is no information on that command.\"");
\r
182 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
\r
183 for (cp = linebuf+3; isspace(*cp); cp++)
\r
185 linebuf[strlen(linebuf)-1] = '\0';
\r
186 if (strcmp(cp, cmdbuf) == 0)
\r
192 prout("Spock- \"Captain, I've found the following information:\"");
\r
195 while (fgets(linebuf, sizeof(linebuf),fp)) {
\r
196 if (strstr(linebuf, "******"))
\r
204 void drawmaps(short l){
\r
205 _setcursortype(_NOCURSOR);
\r
206 if (l==1) sensor();
\r
207 if (l!=2) setwnd(1);
\r
219 _setcursortype(_NORMALCURSOR);
\r
222 #endif /* SERGEEV */
\r
224 static void makemoves(void) {
\r
226 while (TRUE) { /* command loop */
\r
231 while (TRUE) { /* get a command */
\r
234 proutn("COMMAND> ");
\r
235 if (scan() == IHEOL) continue;
\r
236 for (i=0; i < 26; i++)
\r
237 if (isit(commands[i]))
\r
240 for (; i < NUMCOMMANDS; i++)
\r
241 if (strcmp(commands[i], citem) == 0) break;
\r
242 if (i < NUMCOMMANDS) break;
\r
245 prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
\r
246 listCommands(TRUE);
\r
248 else prout("UNRECOGNIZED COMMAND.");
\r
250 commandhook(commands[i], TRUE);
\r
251 switch (i) { /* command switch */
\r
260 if (ididit) hitme = TRUE;
\r
264 if (ididit) hitme = TRUE;
\r
278 if (ididit) attack(0);
\r
291 if (ididit) hitme = TRUE;
\r
299 case 13: // sensors
\r
304 if (ididit) hitme = TRUE;
\r
306 case 15: // transport "beam"
\r
311 if (ididit) hitme = TRUE;
\r
313 case 17: // crystals
\r
316 case 18: // shuttle
\r
318 if (ididit) hitme = TRUE;
\r
320 case 19: // Planet list
\r
323 case 20: // Status information
\r
326 case 21: // Game Report
\r
329 case 22: // use COMPUTER!
\r
333 listCommands(TRUE);
\r
335 case 24: // Emergency exit
\r
336 clearscreen(); // Hide screen
\r
337 freeze(TRUE); // forced save
\r
338 exit(1); // And quick exit
\r
341 probe(); // Launch probe
\r
343 case 26: // Abandon Ship
\r
346 case 27: // Self Destruct
\r
349 case 28: // Save Game
\r
352 prout("WARNING--Frozen games produce no plaques!");
\r
354 case 29: // Try a desparation measure
\r
356 if (ididit) hitme = TRUE;
\r
358 case 30: // What do we want for debug???
\r
363 case 31: // Call for help
\r
367 alldone = 1; // quit the game
\r
369 if (idebug) score();
\r
373 helpme(); // get help
\r
376 commandhook(commands[i], FALSE);
\r
378 if (alldone) break; // Game has ended
\r
380 if (idebug) prout("2500");
\r
384 if (alldone) break; // Events did us in
\r
386 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
\r
390 if (nenhere == 0) movetho();
\r
391 if (hitme && justin==0) {
\r
393 if (alldone) break;
\r
394 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
\r
402 if (alldone) break;
\r
407 int main(int argc, char **argv) {
\r
408 int i, option, usecurses = TRUE;
\r
409 while ((option = getopt(argc, argv, "t")) != -1) {
\r
415 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
\r
420 iostart(usecurses);
\r
423 for (i = optind; i < argc; i++) {
\r
424 strcat(line, argv[i]);
\r
427 while (TRUE) { /* Play a game */
\r
428 setup(line[0] == '\0');
\r
438 if (tourn && alldone) {
\r
439 proutn("Do you want your score recorded?");
\r
445 proutn("Do you want to play again?");
\r
450 puts("May the Great Bird of the Galaxy roost upon your home planet.");
\r
455 void cramen(int i) {
\r
456 /* return an enemy */
\r
460 case IHR: s = "Romulan"; break;
\r
461 case IHK: s = "Klingon"; break;
\r
462 case IHC: s = "Commander"; break;
\r
463 case IHS: s = "Super-commander"; break;
\r
464 case IHSTAR: s = "Star"; break;
\r
465 case IHP: s = "Planet"; break;
\r
466 case IHB: s = "Starbase"; break;
\r
467 case IHBLANK: s = "Black hole"; break;
\r
468 case IHT: s = "Tholian"; break;
\r
469 case IHWEB: s = "Tholian web"; break;
\r
470 case IHQUEST: s = "Stranger"; break;
\r
471 default: s = "Unknown??"; break;
\r
476 char *cramlc(enum loctype key, int x, int y) {
\r
477 static char buf[32];
\r
479 if (key == quadrant) strcpy(buf, "Quadrant ");
\r
480 else if (key == sector) strcpy(buf, "Sector ");
\r
481 sprintf(buf+strlen(buf), "%d-%d", x, y);
\r
485 void crmena(int i, int enemy, int key, int x, int y) {
\r
486 if (i == 1) proutn("***");
\r
489 proutn(cramlc(key, x, y));
\r
492 void crmshp(void) {
\r
495 case IHE: s = "Enterprise"; break;
\r
496 case IHF: s = "Faerie Queene"; break;
\r
497 default: s = "Ship???"; break;
\r
503 prouts("******************************************************");
\r
507 double expran(double avrage) {
\r
508 return -avrage*log(1e-7 + Rand());
\r
511 double Rand(void) {
\r
512 return rand()/(1.0 + (double)RAND_MAX);
\r
515 void iran8(int *i, int *j) {
\r
516 *i = Rand()*8.0 + 1.0;
\r
517 *j = Rand()*8.0 + 1.0;
\r
520 void iran10(int *i, int *j) {
\r
521 *i = Rand()*10.0 + 1.0;
\r
522 *j = Rand()*10.0 + 1.0;
\r
531 /* return IHEOL next time */
\r
544 // Read a line if nothing here
\r
546 if (linep != line) {
\r
550 getline(line, sizeof(line));
\r
553 // Skip leading white space
\r
554 while (*linep == ' ') linep++;
\r
560 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
\r
561 // treat as a number
\r
563 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
\r
564 linep = line; // Invalid numbers are ignored
\r
576 while (*linep && *linep!=' ') {
\r
577 if ((cp - citem) < 9) *cp++ = tolower(*linep);
\r
589 if (*citem == 'y') return TRUE;
\r
590 if (*citem == 'n') return FALSE;
\r
591 proutn("Please answer with \"Y\" or \"N\":");
\r
598 prout("Beg your pardon, Captain?");
\r
601 int isit(char *s) {
\r
602 /* New function -- compares s to scaned citem and returns true if it
\r
603 matches to the length of s */
\r
605 return strncmp(s, citem, max(1, strlen(citem))) == 0;
\r
610 void debugme(void) {
\r
611 proutn("Reset levels? ");
\r
613 if (energy < inenrg) energy = inenrg;
\r
618 proutn("Reset damage? ");
\r
621 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
\r
624 proutn("Toggle idebug? ");
\r
627 if (idebug) prout("Debug output ON");
\r
628 else prout("Debug output OFF");
\r
630 proutn("Cause selective damage? ");
\r
633 for (i=1; i <= NDEVICES; i++) {
\r
639 if (key == IHALPHA && isit("y")) {
\r
641 if (i == DRADIO) stdamtim = game.state.date;
\r
645 proutn("Examine/change events? ");
\r
648 for (i = 1; i < NEVENTS; i++) {
\r
650 if (future[i] == 1e30) continue;
\r
652 case FSNOVA: proutn("Supernova "); break;
\r
653 case FTBEAM: proutn("T Beam "); break;
\r
654 case FSNAP: proutn("Snapshot "); break;
\r
655 case FBATTAK: proutn("Base Attack "); break;
\r
656 case FCDBAS: proutn("Base Destroy "); break;
\r
657 case FSCMOVE: proutn("SC Move "); break;
\r
658 case FSCDBAS: proutn("SC Base Destroy "); break;
\r
660 proutn("%.2f", future[i]-game.state.date);
\r
664 if (key == IHREAL) {
\r
665 future[i] = game.state.date + aaitem;
\r