1 #define INCLUDED // Define externs here
12 #define SSTDOC "sst.doc"
15 static char line[128], *linep = line;
19 Here are Tom Almy's changes:
21 Compared to original version, I've changed the "help" command to
22 "call" and the "terminate" command to "quit" to better match
23 user expectations. The DECUS version apparently made those changes
24 as well as changing "freeze" to "save". However I like "freeze".
26 When I got a later version of Super Star Trek that I was converting
27 from, I added the emexit command.
29 That later version also mentions srscan and lrscan working when
30 docked (using the starbase's scanners), so I made some changes here
31 to do this (and indicating that fact to the player), and then realized
32 the base would have a subspace radio as well -- doing a Chart when docked
33 updates the star chart, and all radio reports will be heard. The Dock
34 command will also give a report if a base is under attack.
36 Movecom no longer reports movement if sensors are damaged so you wouldn't
41 1. Better base positioning at startup
43 2. Deathray improvement (but keeping original failure alternatives)
47 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
48 move in Expert and Emeritus games. This code could use improvement.
50 5. The deep space probe looks interesting! DECUS version
52 6. Perhaps cloaking to be added later? BSD version
54 Here are Stas Sergeev's changes (controlled by the proprocessor symbol
55 SERGEEV, not yet completely merged):
57 1. The Space Thingy can be shoved, if you it ram, and can fire back if
60 1 The Tholian can be hit with phasers
62 2. When you are docked, base covers you with an almost invincible shields
63 (a commander can still ram you, or a Romulan can destroy the base,
64 or a SCom can even succeed with direct attack IIRC, but this rarely
67 3. SCom can't escape from you if no more enemies remain (without this,
68 chasing SCom can take an eternity).
70 4. Probe target you enter is now the destination quadrant. Before I don't
71 remember what it was, but it was something I had difficulty using)
73 5. Secret password is now autogenerated.
75 6. "Plaque" is adjusted for A4 paper:)
77 7. Phasers now tells you how much energy needed, but only if the computer
80 8. Planets are auto-scanned when you enter the quadrant.
82 9. Mining or using crystals in presense of enemy now yields an attack.
83 There are other minor adjustments to what yields an attack
86 10. Ramming a black hole is no longer instant death. There is a
87 chance you might get timewarped instead.
91 static char *commands[] = {
155 wnd wnds[6]={{1,1,80,25},{1,1,25,12},{26,2,80,12},{65,1,80,10},{1,13,80,23},{1,24,80,25}};
159 #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
161 static void listCommands(int x) {
162 proutn ("LEGAL COMMANDS ARE:\n\r"
163 " MOVE PHASERS SOS PROBE\n\r"
164 " COMPUTER IMPULSE TORPEDO ABANDON\n\r"
165 " EMEXIT WARP SHIELDS DESTRUCT\n\r"
166 " CHART REST DOCK QUIT\n\r"
167 " DAMAGES REPORT SCORE ORBIT\n\r"
168 " TRANSPORT MINE CRYSTALS SHUTTLE\n\r"
169 " PLANETS DEATHRAY SAVE COMMANDS\n\r");
170 if (x) prout(" HELP");
174 void setwnd(short wndnum){
176 cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
177 if ((curwnd==0)&&(wndnum!=0)) clrscr();
178 window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
179 if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
180 gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
188 static void helpme(void) {
190 char cmdbuf[32], *cp;
193 /* Give help on commands */
201 proutn("Help on what command? ");
207 if (key == IHEOL) return;
208 for (i = 0; i < NUMCOMMANDS; i++) {
209 if (strcmp(commands[i], citem)==0) break;
211 if (i != NUMCOMMANDS) break;
213 prout("Valid commands:");
220 strcpy(cmdbuf, " ABBREV");
223 for (j = 0; commands[i][j]; j++)
224 cmdbuf[j] = toupper(commands[i][j]);
227 fp = fopen(SSTDOC, "r");
229 prout("Spock- \"Captain, that information is missing from the");
230 prout(" computer. You need to find SST.DOC and put it in the");
231 prout(" current directory.\"");
235 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
236 prout("Spock- \"Captain, there is no information on that command.\"");
240 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
241 for (cp = linebuf+3; isspace(*cp); cp++)
243 linebuf[strlen(linebuf)-1] = '\0';
244 if (strcmp(cp, cmdbuf) == 0)
250 prout("Spock- \"Captain, I've found the following information:\"");
253 while (fgets(linebuf, sizeof(linebuf),fp)) {
254 if (strstr(linebuf, "******"))
262 void drawmaps(short l){
263 _setcursortype(_NOCURSOR);
277 _setcursortype(_NORMALCURSOR);
282 static void makemoves(void) {
288 while (TRUE) { /* command loop */
292 while (TRUE) { /* get a command */
303 if (scan() == IHEOL) {
305 _setcursortype(_NOCURSOR);
309 _setcursortype(_NORMALCURSOR);
319 for (i=0; i < 26; i++)
320 if (isit(commands[i]))
323 for (; i < NUMCOMMANDS; i++)
324 if (strcmp(commands[i], citem) == 0) break;
325 if (i < NUMCOMMANDS) break;
329 commandhook(commands[i], TRUE);
330 switch (i) { /* command switch */
341 if (ididit) hitme = TRUE;
345 if (ididit) hitme = TRUE;
359 if (ididit) attack(0);
372 if (ididit) hitme = TRUE;
387 if (ididit) hitme = TRUE;
389 case 15: // transport "beam"
394 if (ididit) hitme = TRUE;
398 if (ididit) hitme = TRUE;
402 if (ididit) hitme = TRUE;
404 case 19: // Planet list
407 case 20: // Status information
410 case 21: // Game Report
413 case 22: // use COMPUTER!
419 case 24: // Emergency exit
421 clrscr(); // Hide screen
423 freeze(TRUE); // forced save
424 exit(1); // And quick exit
427 probe(); // Launch probe
428 if (ididit) hitme = TRUE;
430 case 26: // Abandon Ship
433 case 27: // Self Destruct
436 case 28: // Save Game
442 prout("WARNING--Saved games produce no plaques!");
444 case 29: // Try a desparation measure
446 if (ididit) hitme = TRUE;
448 case 30: // What do we want for debug???
453 case 31: // Call for help
455 if (ididit) hitme = TRUE;
458 alldone = 1; // quit the game
464 helpme(); // get help
467 commandhook(commands[i], FALSE);
469 if (alldone) break; // Game has ended
471 if (idebug) prout("2500");
475 if (alldone) break; // Events did us in
477 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
481 if (hitme && justin==0) {
484 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
497 int main(int argc, char **argv) {
498 int i, option, usecurses = TRUE;
500 while ((option = getopt(argc, argv, "t")) != -1) {
506 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
520 for (i = optind; i < argc; i++) {
521 strcat(line, argv[i]);
524 while (TRUE) { /* Play a game */
526 setup(line[0] == '\0');
536 if (tourn && alldone) {
537 proutn("Do you want your score recorded?");
543 proutn("Do you want to play again? ");
554 prout("May the Great Bird of the Galaxy roost upon your home planet.");
560 /* return an enemy */
564 case IHR: s = "Romulan"; break;
565 case IHK: s = "Klingon"; break;
566 case IHC: s = "Commander"; break;
567 case IHS: s = "Super-commander"; break;
568 case IHSTAR: s = "Star"; break;
569 case IHP: s = "Planet"; break;
570 case IHB: s = "Starbase"; break;
571 case IHBLANK: s = "Black hole"; break;
572 case IHT: s = "Tholian"; break;
573 case IHWEB: s = "Tholian web"; break;
574 case IHQUEST: s = "Stranger"; break;
575 default: s = "Unknown??"; break;
580 char *cramlc(enum loctype key, int x, int y) {
583 if (key == quadrant) strcpy(buf, "Quadrant ");
584 else if (key == sector) strcpy(buf, "Sector ");
585 sprintf(buf+strlen(buf), "%d - %d", x, y);
589 void crmena(int i, int enemy, int key, int x, int y) {
590 if (i == 1) proutn("***");
593 proutn(cramlc(key, x, y));
599 case IHE: s = "Enterprise"; break;
600 case IHF: s = "Faerie Queene"; break;
601 default: s = "Ship???"; break;
607 prouts("******************************************************");
611 double expran(double avrage) {
612 return -avrage*log(1e-7 + Rand());
616 return rand()/(1.0 + (double)RAND_MAX);
619 void iran8(int *i, int *j) {
620 *i = Rand()*8.0 + 1.0;
621 *j = Rand()*8.0 + 1.0;
624 void iran10(int *i, int *j) {
625 *i = Rand()*10.0 + 1.0;
626 *j = Rand()*10.0 + 1.0;
635 /* return IHEOL next time */
648 // Read a line if nothing here
654 getline(line, sizeof(line));
665 // Skip leading white space
666 while (*linep == ' ') linep++;
672 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
675 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
676 linep = line; // Invalid numbers are ignored
688 while (*linep && *linep!=' ') {
689 if ((cp - citem) < 9) *cp++ = tolower(*linep);
701 if (*citem == 'y') return TRUE;
702 if (*citem == 'n') return FALSE;
703 proutn("Please answer with \"Y\" or \"N\": ");
710 prout("Beg your pardon, Captain?");
714 /* New function -- compares s to scaned citem and returns true if it
715 matches to the length of s */
717 return strncmp(s, citem, max(1, strlen(citem))) == 0;
723 proutn("Reset levels? ");
725 if (energy < inenrg) energy = inenrg;
730 proutn("Reset damage? ");
733 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
736 proutn("Toggle idebug? ");
739 if (idebug) prout("Debug output ON");
740 else prout("Debug output OFF");
742 proutn("Cause selective damage? ");
745 for (i=1; i <= NDEVICES; i++) {
751 if (key == IHALPHA && isit("y")) {
753 if (i == DRADIO) stdamtim = game.state.date;
757 proutn("Examine/change events? ");
760 for (i = 1; i < NEVENTS; i++) {
762 if (future[i] == 1e30) continue;
764 case FSNOVA: proutn("Supernova "); break;
765 case FTBEAM: proutn("T Beam "); break;
766 case FSNAP: proutn("Snapshot "); break;
767 case FBATTAK: proutn("Base Attack "); break;
768 case FCDBAS: proutn("Base Destroy "); break;
769 case FSCMOVE: proutn("SC Move "); break;
770 case FSCDBAS: proutn("SC Base Destroy "); break;
772 proutn("%.2f", future[i]-game.state.date);
777 future[i] = game.state.date + aaitem;