1 #define INCLUDED // Define externs here
7 #define SSTDOC "sst.doc"
10 static char line[128], *linep = line;
14 Here are Tom Almy's changes:
16 Compared to original version, I've changed the "help" command to
17 "call" and the "terminate" command to "quit" to better match
18 user expectations. The DECUS version apparently made those changes
19 as well as changing "freeze" to "save". However I like "freeze".
21 When I got a later version of Super Star Trek that I was converting
22 from, I added the emexit command.
24 That later version also mentions srscan and lrscan working when
25 docked (using the starbase's scanners), so I made some changes here
26 to do this (and indicating that fact to the player), and then realized
27 the base would have a subspace radio as well -- doing a Chart when docked
28 updates the star chart, and all radio reports will be heard. The Dock
29 command will also give a report if a base is under attack.
31 Movecom no longer reports movement if sensors are damaged so you wouldn't
36 1. Better base positioning at startup
38 2. Deathray improvement (but keeping original failure alternatives)
42 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
43 move in Expert and Emeritus games. This code could use improvement.
45 5. The deep space probe looks interesting! DECUS version
47 6. Perhaps cloaking to be added later? BSD version
49 Here are Stas Sergeev's changes (controlled by the proprocessor symbol
50 SERGEEV, not yet completely merged):
52 1. The Space Thingy can be shoved, if you it ram, and can fire back if
55 1 The Tholian can be hit with phasers
57 2. When you are docked, base covers you with an almost invincible shields
58 (a commander can still ram you, or a Romulan can destroy the base,
59 or a SCom can even succeed with direct attack IIRC, but this rarely
62 3. SCom can't escape from you if no more enemies remain (without this,
63 chasing SCom can take an eternity).
65 4. Probe target you enter is now the destination quadrant. Before I don't
66 remember what it was, but it was something I had difficulty using)
68 5. Secret password is now autogenerated.
70 6. "Plaque" is adjusted for A4 paper:)
72 7. Phasers now tells you how much energy needed, but only if the computer
75 8. Planets are auto-scanned when you enter the quadrant.
77 9. Mining or using crystals in presense of enemy now yields an attack.
78 There are other minor adjustments to what yields an attack
81 10. Ramming a black hole is no longer instant death. There is a
82 chance you might get timewarped instead.
86 static char *commands[] = {
122 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
124 static void listCommands(int x) {
125 prout(" SRSCAN MOVE PHASERS CALL\n"
126 " STATUS IMPULSE PHOTONS ABANDON\n"
127 " LRSCAN WARP SHIELDS DESTRUCT\n"
128 " CHART REST DOCK QUIT\n"
129 " DAMAGES REPORT SENSORS ORBIT\n"
130 " TRANSPORT MINE CRYSTALS SHUTTLE\n"
131 " PLANETS REQUEST DEATHRAY FREEZE\n"
132 " COMPUTER EMEXIT PROBE COMMANDS");
133 if (x) prout(" HELP");
137 void setwnd(short wndnum){
139 cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
140 if ((curwnd==0)&&(wndnum!=0)) clrscr();
141 window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
142 if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
143 gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
151 static void helpme(void) {
153 char cmdbuf[32], *cp;
156 /* Give help on commands */
164 proutn("Help on what command? ");
170 if (key == IHEOL) return;
171 for (i = 0; i < NUMCOMMANDS; i++) {
172 if (strcmp(commands[i], citem)==0) break;
174 if (i != NUMCOMMANDS) break;
176 prout("Valid commands:");
183 strcpy(cmdbuf, " ABBREV");
186 for (j = 0; commands[i][j]; j++)
187 cmdbuf[j] = toupper(commands[i][j]);
190 fp = fopen(SSTDOC, "r");
192 prout("Spock- \"Captain, that information is missing from the");
193 prout(" computer. You need to find SST.DOC and put it in the");
194 prout(" current directory.\"");
198 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
199 prout("Spock- \"Captain, there is no information on that command.\"");
203 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
204 for (cp = linebuf+3; isspace(*cp); cp++)
206 linebuf[strlen(linebuf)-1] = '\0';
207 if (strcmp(cp, cmdbuf) == 0)
213 prout("Spock- \"Captain, I've found the following information:\"");
216 while (fgets(linebuf, sizeof(linebuf),fp)) {
217 if (strstr(linebuf, "******"))
225 void drawmaps(short l){
226 _setcursortype(_NOCURSOR);
240 _setcursortype(_NORMALCURSOR);
245 static void makemoves(void) {
247 while (TRUE) { /* command loop */
252 while (TRUE) { /* get a command */
256 if (scan() == IHEOL) continue;
257 for (i=0; i < 26; i++)
258 if (isit(commands[i]))
261 for (; i < NUMCOMMANDS; i++)
262 if (strcmp(commands[i], citem) == 0) break;
263 if (i < NUMCOMMANDS) break;
266 prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
269 else prout("UNRECOGNIZED COMMAND.");
271 commandhook(commands[i], TRUE);
272 switch (i) { /* command switch */
281 if (ididit) hitme = TRUE;
285 if (ididit) hitme = TRUE;
299 if (ididit) attack(0);
312 if (ididit) hitme = TRUE;
325 if (ididit) hitme = TRUE;
327 case 15: // transport "beam"
332 if (ididit) hitme = TRUE;
339 if (ididit) hitme = TRUE;
341 case 19: // Planet list
344 case 20: // Status information
347 case 21: // Game Report
350 case 22: // use COMPUTER!
356 case 24: // Emergency exit
357 clearscreen(); // Hide screen
358 freeze(TRUE); // forced save
359 exit(1); // And quick exit
362 probe(); // Launch probe
364 case 26: // Abandon Ship
367 case 27: // Self Destruct
370 case 28: // Save Game
373 prout("WARNING--Frozen games produce no plaques!");
375 case 29: // Try a desparation measure
377 if (ididit) hitme = TRUE;
379 case 30: // What do we want for debug???
384 case 31: // Call for help
388 alldone = 1; // quit the game
394 helpme(); // get help
397 commandhook(commands[i], FALSE);
399 if (alldone) break; // Game has ended
401 if (idebug) prout("2500");
405 if (alldone) break; // Events did us in
407 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
411 if (nenhere == 0) movetho();
412 if (hitme && justin==0) {
415 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
428 int main(int argc, char **argv) {
429 int i, option, usecurses = TRUE;
430 while ((option = getopt(argc, argv, "t")) != -1) {
436 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
444 for (i = optind; i < argc; i++) {
445 strcat(line, argv[i]);
448 while (TRUE) { /* Play a game */
449 setup(line[0] == '\0');
459 if (tourn && alldone) {
460 proutn("Do you want your score recorded?");
466 proutn("Do you want to play again? ");
477 puts("May the Great Bird of the Galaxy roost upon your home planet.");
483 /* return an enemy */
487 case IHR: s = "Romulan"; break;
488 case IHK: s = "Klingon"; break;
489 case IHC: s = "Commander"; break;
490 case IHS: s = "Super-commander"; break;
491 case IHSTAR: s = "Star"; break;
492 case IHP: s = "Planet"; break;
493 case IHB: s = "Starbase"; break;
494 case IHBLANK: s = "Black hole"; break;
495 case IHT: s = "Tholian"; break;
496 case IHWEB: s = "Tholian web"; break;
497 case IHQUEST: s = "Stranger"; break;
498 default: s = "Unknown??"; break;
503 char *cramlc(enum loctype key, int x, int y) {
506 if (key == quadrant) strcpy(buf, "Quadrant ");
507 else if (key == sector) strcpy(buf, "Sector ");
508 sprintf(buf+strlen(buf), "%d-%d", x, y);
512 void crmena(int i, int enemy, int key, int x, int y) {
513 if (i == 1) proutn("***");
516 proutn(cramlc(key, x, y));
522 case IHE: s = "Enterprise"; break;
523 case IHF: s = "Faerie Queene"; break;
524 default: s = "Ship???"; break;
530 prouts("******************************************************");
534 double expran(double avrage) {
535 return -avrage*log(1e-7 + Rand());
539 return rand()/(1.0 + (double)RAND_MAX);
542 void iran8(int *i, int *j) {
543 *i = Rand()*8.0 + 1.0;
544 *j = Rand()*8.0 + 1.0;
547 void iran10(int *i, int *j) {
548 *i = Rand()*10.0 + 1.0;
549 *j = Rand()*10.0 + 1.0;
558 /* return IHEOL next time */
571 // Read a line if nothing here
577 getline(line, sizeof(line));
580 // Skip leading white space
581 while (*linep == ' ') linep++;
587 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
590 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
591 linep = line; // Invalid numbers are ignored
603 while (*linep && *linep!=' ') {
604 if ((cp - citem) < 9) *cp++ = tolower(*linep);
616 if (*citem == 'y') return TRUE;
617 if (*citem == 'n') return FALSE;
618 proutn("Please answer with \"Y\" or \"N\": ");
625 prout("Beg your pardon, Captain?");
629 /* New function -- compares s to scaned citem and returns true if it
630 matches to the length of s */
632 return strncmp(s, citem, max(1, strlen(citem))) == 0;
638 proutn("Reset levels? ");
640 if (energy < inenrg) energy = inenrg;
645 proutn("Reset damage? ");
648 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
651 proutn("Toggle idebug? ");
654 if (idebug) prout("Debug output ON");
655 else prout("Debug output OFF");
657 proutn("Cause selective damage? ");
660 for (i=1; i <= NDEVICES; i++) {
666 if (key == IHALPHA && isit("y")) {
668 if (i == DRADIO) stdamtim = game.state.date;
672 proutn("Examine/change events? ");
675 for (i = 1; i < NEVENTS; i++) {
677 if (future[i] == 1e30) continue;
679 case FSNOVA: proutn("Supernova "); break;
680 case FTBEAM: proutn("T Beam "); break;
681 case FSNAP: proutn("Snapshot "); break;
682 case FBATTAK: proutn("Base Attack "); break;
683 case FCDBAS: proutn("Base Destroy "); break;
684 case FSCMOVE: proutn("SC Move "); break;
685 case FSCDBAS: proutn("SC Base Destroy "); break;
687 proutn("%.2f", future[i]-game.state.date);
692 future[i] = game.state.date + aaitem;