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.\"");
232 * This used to continue: "You need to find SST.DOC and put
233 * it in the current directory."
238 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
239 prout("Spock- \"Captain, there is no information on that command.\"");
243 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
244 for (cp = linebuf+3; isspace(*cp); cp++)
246 linebuf[strlen(linebuf)-1] = '\0';
247 if (strcmp(cp, cmdbuf) == 0)
253 prout("Spock- \"Captain, I've found the following information:\"");
256 while (fgets(linebuf, sizeof(linebuf),fp)) {
257 if (strstr(linebuf, "******"))
264 void drawmaps(short l) {
265 /* hook to be called after moving to redraw maps */
267 _setcursortype(_NOCURSOR);
281 _setcursortype(_NORMALCURSOR);
286 static void makemoves(void) {
292 while (TRUE) { /* command loop */
294 while (TRUE) { /* get a command */
305 if (scan() == IHEOL) {
307 _setcursortype(_NOCURSOR);
311 _setcursortype(_NORMALCURSOR);
321 for (i=0; i < 26; i++)
322 if (isit(commands[i]))
325 for (; i < NUMCOMMANDS; i++)
326 if (strcmp(commands[i], citem) == 0) break;
327 if (i < NUMCOMMANDS) break;
331 commandhook(commands[i], TRUE);
332 switch (i) { /* command switch */
343 if (ididit) hitme = TRUE;
347 if (ididit) hitme = TRUE;
361 if (ididit) attack(0);
374 if (ididit) hitme = TRUE;
389 if (ididit) hitme = TRUE;
391 case 15: // transport "beam"
396 if (ididit) hitme = TRUE;
400 if (ididit) hitme = TRUE;
404 if (ididit) hitme = TRUE;
406 case 19: // Planet list
409 case 20: // Status information
412 case 21: // Game Report
415 case 22: // use COMPUTER!
421 case 24: // Emergency exit
423 clrscr(); // Hide screen
425 freeze(TRUE); // forced save
426 exit(1); // And quick exit
429 probe(); // Launch probe
430 if (ididit) hitme = TRUE;
432 case 26: // Abandon Ship
435 case 27: // Self Destruct
438 case 28: // Save Game
444 prout("WARNING--Saved games produce no plaques!");
446 case 29: // Try a desparation measure
448 if (ididit) hitme = TRUE;
450 case 30: // What do we want for debug???
455 case 31: // Call for help
457 if (ididit) hitme = TRUE;
460 alldone = 1; // quit the game
466 helpme(); // get help
469 commandhook(commands[i], FALSE);
471 if (alldone) break; // Game has ended
473 if (idebug) prout("2500");
477 if (alldone) break; // Events did us in
479 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
483 if (hitme && justin==0) {
486 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
499 int main(int argc, char **argv) {
500 int i, option, usecurses = TRUE;
502 while ((option = getopt(argc, argv, "t")) != -1) {
508 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
522 for (i = optind; i < argc; i++) {
523 strcat(line, argv[i]);
526 while (TRUE) { /* Play a game */
528 setup(line[0] == '\0');
538 if (tourn && alldone) {
539 proutn("Do you want your score recorded?");
545 proutn("Do you want to play again? ");
556 prout("May the Great Bird of the Galaxy roost upon your home planet.");
562 /* return an enemy */
566 case IHR: s = "Romulan"; break;
567 case IHK: s = "Klingon"; break;
568 case IHC: s = "Commander"; break;
569 case IHS: s = "Super-commander"; break;
570 case IHSTAR: s = "Star"; break;
571 case IHP: s = "Planet"; break;
572 case IHB: s = "Starbase"; break;
573 case IHBLANK: s = "Black hole"; break;
574 case IHT: s = "Tholian"; break;
575 case IHWEB: s = "Tholian web"; break;
576 case IHQUEST: s = "Stranger"; break;
577 default: s = "Unknown??"; break;
582 char *cramlc(enum loctype key, int x, int y) {
585 if (key == quadrant) strcpy(buf, "Quadrant ");
586 else if (key == sector) strcpy(buf, "Sector ");
587 sprintf(buf+strlen(buf), "%d - %d", x, y);
591 void crmena(int i, int enemy, int key, int x, int y) {
592 if (i == 1) proutn("***");
595 proutn(cramlc(key, x, y));
601 case IHE: s = "Enterprise"; break;
602 case IHF: s = "Faerie Queene"; break;
603 default: s = "Ship???"; break;
609 prouts("******************************************************");
613 double expran(double avrage) {
614 return -avrage*log(1e-7 + Rand());
618 return rand()/(1.0 + (double)RAND_MAX);
621 void iran8(int *i, int *j) {
622 *i = Rand()*8.0 + 1.0;
623 *j = Rand()*8.0 + 1.0;
626 void iran10(int *i, int *j) {
627 *i = Rand()*10.0 + 1.0;
628 *j = Rand()*10.0 + 1.0;
637 /* return IHEOL next time */
650 // Read a line if nothing here
656 getline(line, sizeof(line));
667 // Skip leading white space
668 while (*linep == ' ') linep++;
674 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
677 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
678 linep = line; // Invalid numbers are ignored
690 while (*linep && *linep!=' ') {
691 if ((cp - citem) < 9) *cp++ = tolower(*linep);
703 if (*citem == 'y') return TRUE;
704 if (*citem == 'n') return FALSE;
705 proutn("Please answer with \"Y\" or \"N\": ");
712 prout("Beg your pardon, Captain?");
716 /* New function -- compares s to scaned citem and returns true if it
717 matches to the length of s */
719 return strncmp(s, citem, max(1, strlen(citem))) == 0;
725 proutn("Reset levels? ");
727 if (energy < inenrg) energy = inenrg;
732 proutn("Reset damage? ");
735 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
738 proutn("Toggle idebug? ");
741 if (idebug) prout("Debug output ON");
742 else prout("Debug output OFF");
744 proutn("Cause selective damage? ");
747 for (i=1; i <= NDEVICES; i++) {
753 if (key == IHALPHA && isit("y")) {
755 if (i == DRADIO) stdamtim = game.state.date;
759 proutn("Examine/change events? ");
762 for (i = 1; i < NEVENTS; i++) {
764 if (future[i] == 1e30) continue;
766 case FSNOVA: proutn("Supernova "); break;
767 case FTBEAM: proutn("T Beam "); break;
768 case FSNAP: proutn("Snapshot "); break;
769 case FBATTAK: proutn("Base Attack "); break;
770 case FCDBAS: proutn("Base Destroy "); break;
771 case FSCMOVE: proutn("SC Move "); break;
772 case FSCDBAS: proutn("SC Base Destroy "); break;
774 proutn("%.2f", future[i]-game.state.date);
779 future[i] = game.state.date + aaitem;