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 completely 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
137 void setwnd(short wndnum){
\r
139 cury=wherey()+wnds[curwnd].wndtop-wnds[wndnum].wndtop;
\r
140 if ((curwnd==0)&&(wndnum!=0)) clrscr();
\r
141 window(wnds[wndnum].wndleft, wnds[wndnum].wndtop, wnds[wndnum].wndright, wnds[wndnum].wndbottom);
\r
142 if ((curwnd==wndnum)&&(cury>wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1)){
\r
143 gotoxy(wnds[wndnum].wndright-wnds[wndnum].wndleft+1,wnds[wndnum].wndbottom-wnds[wndnum].wndtop+1);
\r
149 #endif /* SERGEEV */
\r
151 static void helpme(void) {
\r
153 char cmdbuf[32], *cp;
\r
156 /* Give help on commands */
\r
160 if (key == IHEOL) {
\r
163 #endif /* SERGEEV */
\r
164 proutn("Help on what command? ");
\r
169 #endif /* SERGEEV */
\r
170 if (key == IHEOL) return;
\r
171 for (i = 0; i < NUMCOMMANDS; i++) {
\r
172 if (strcmp(commands[i], citem)==0) break;
\r
174 if (i != NUMCOMMANDS) break;
\r
176 prout("Valid commands:");
\r
177 listCommands(FALSE);
\r
183 strcpy(cmdbuf, " ABBREV");
\r
186 for (j = 0; commands[i][j]; j++)
\r
187 cmdbuf[j] = toupper(commands[i][j]);
\r
190 fp = fopen(SSTDOC, "r");
\r
192 prout("Spock- \"Captain, that information is missing from the");
\r
193 prout(" computer. You need to find SST.DOC and put it in the");
\r
194 prout(" current directory.\"");
\r
198 if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
\r
199 prout("Spock- \"Captain, there is no information on that command.\"");
\r
203 if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
\r
204 for (cp = linebuf+3; isspace(*cp); cp++)
\r
206 linebuf[strlen(linebuf)-1] = '\0';
\r
207 if (strcmp(cp, cmdbuf) == 0)
\r
213 prout("Spock- \"Captain, I've found the following information:\"");
\r
216 while (fgets(linebuf, sizeof(linebuf),fp)) {
\r
217 if (strstr(linebuf, "******"))
\r
225 void drawmaps(short l){
\r
226 _setcursortype(_NOCURSOR);
\r
227 if (l==1) sensor();
\r
228 if (l!=2) setwnd(1);
\r
240 _setcursortype(_NORMALCURSOR);
\r
243 #endif /* SERGEEV */
\r
245 static void makemoves(void) {
\r
247 while (TRUE) { /* command loop */
\r
252 while (TRUE) { /* get a command */
\r
255 proutn("COMMAND> ");
\r
256 if (scan() == IHEOL) continue;
\r
257 for (i=0; i < 26; i++)
\r
258 if (isit(commands[i]))
\r
261 for (; i < NUMCOMMANDS; i++)
\r
262 if (strcmp(commands[i], citem) == 0) break;
\r
263 if (i < NUMCOMMANDS) break;
\r
266 prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
\r
267 listCommands(TRUE);
\r
269 else prout("UNRECOGNIZED COMMAND.");
\r
271 commandhook(commands[i], TRUE);
\r
272 switch (i) { /* command switch */
\r
281 if (ididit) hitme = TRUE;
\r
285 if (ididit) hitme = TRUE;
\r
299 if (ididit) attack(0);
\r
312 if (ididit) hitme = TRUE;
\r
320 case 13: // sensors
\r
325 if (ididit) hitme = TRUE;
\r
327 case 15: // transport "beam"
\r
332 if (ididit) hitme = TRUE;
\r
334 case 17: // crystals
\r
337 case 18: // shuttle
\r
339 if (ididit) hitme = TRUE;
\r
341 case 19: // Planet list
\r
344 case 20: // Status information
\r
347 case 21: // Game Report
\r
350 case 22: // use COMPUTER!
\r
354 listCommands(TRUE);
\r
356 case 24: // Emergency exit
\r
357 clearscreen(); // Hide screen
\r
358 freeze(TRUE); // forced save
\r
359 exit(1); // And quick exit
\r
362 probe(); // Launch probe
\r
364 case 26: // Abandon Ship
\r
367 case 27: // Self Destruct
\r
370 case 28: // Save Game
\r
373 prout("WARNING--Frozen games produce no plaques!");
\r
375 case 29: // Try a desparation measure
\r
377 if (ididit) hitme = TRUE;
\r
379 case 30: // What do we want for debug???
\r
384 case 31: // Call for help
\r
388 alldone = 1; // quit the game
\r
390 if (idebug) score();
\r
394 helpme(); // get help
\r
397 commandhook(commands[i], FALSE);
\r
399 if (alldone) break; // Game has ended
\r
401 if (idebug) prout("2500");
\r
405 if (alldone) break; // Events did us in
\r
407 if (game.state.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
\r
411 if (nenhere == 0) movetho();
\r
412 if (hitme && justin==0) {
\r
414 if (alldone) break;
\r
415 if (game.state.galaxy[quadx][quady] == 1000) { // went NOVA!
\r
423 if (alldone) break;
\r
428 int main(int argc, char **argv) {
\r
429 int i, option, usecurses = TRUE;
\r
430 while ((option = getopt(argc, argv, "t")) != -1) {
\r
436 fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
\r
441 iostart(usecurses);
\r
444 for (i = optind; i < argc; i++) {
\r
445 strcat(line, argv[i]);
\r
448 while (TRUE) { /* Play a game */
\r
449 setup(line[0] == '\0');
\r
459 if (tourn && alldone) {
\r
460 proutn("Do you want your score recorded?");
\r
466 proutn("Do you want to play again? ");
\r
471 #endif /* SERGEEV */
\r
476 #endif /* SERGEEV */
\r
477 puts("May the Great Bird of the Galaxy roost upon your home planet.");
\r
482 void cramen(int i) {
\r
483 /* return an enemy */
\r
487 case IHR: s = "Romulan"; break;
\r
488 case IHK: s = "Klingon"; break;
\r
489 case IHC: s = "Commander"; break;
\r
490 case IHS: s = "Super-commander"; break;
\r
491 case IHSTAR: s = "Star"; break;
\r
492 case IHP: s = "Planet"; break;
\r
493 case IHB: s = "Starbase"; break;
\r
494 case IHBLANK: s = "Black hole"; break;
\r
495 case IHT: s = "Tholian"; break;
\r
496 case IHWEB: s = "Tholian web"; break;
\r
497 case IHQUEST: s = "Stranger"; break;
\r
498 default: s = "Unknown??"; break;
\r
503 char *cramlc(enum loctype key, int x, int y) {
\r
504 static char buf[32];
\r
506 if (key == quadrant) strcpy(buf, "Quadrant ");
\r
507 else if (key == sector) strcpy(buf, "Sector ");
\r
508 sprintf(buf+strlen(buf), "%d-%d", x, y);
\r
512 void crmena(int i, int enemy, int key, int x, int y) {
\r
513 if (i == 1) proutn("***");
\r
516 proutn(cramlc(key, x, y));
\r
519 void crmshp(void) {
\r
522 case IHE: s = "Enterprise"; break;
\r
523 case IHF: s = "Faerie Queene"; break;
\r
524 default: s = "Ship???"; break;
\r
530 prouts("******************************************************");
\r
534 double expran(double avrage) {
\r
535 return -avrage*log(1e-7 + Rand());
\r
538 double Rand(void) {
\r
539 return rand()/(1.0 + (double)RAND_MAX);
\r
542 void iran8(int *i, int *j) {
\r
543 *i = Rand()*8.0 + 1.0;
\r
544 *j = Rand()*8.0 + 1.0;
\r
547 void iran10(int *i, int *j) {
\r
548 *i = Rand()*10.0 + 1.0;
\r
549 *j = Rand()*10.0 + 1.0;
\r
558 /* return IHEOL next time */
\r
571 // Read a line if nothing here
\r
573 if (linep != line) {
\r
577 getline(line, sizeof(line));
\r
580 // Skip leading white space
\r
581 while (*linep == ' ') linep++;
\r
587 if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
\r
588 // treat as a number
\r
590 if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
\r
591 linep = line; // Invalid numbers are ignored
\r
603 while (*linep && *linep!=' ') {
\r
604 if ((cp - citem) < 9) *cp++ = tolower(*linep);
\r
616 if (*citem == 'y') return TRUE;
\r
617 if (*citem == 'n') return FALSE;
\r
618 proutn("Please answer with \"Y\" or \"N\": ");
\r
625 prout("Beg your pardon, Captain?");
\r
628 int isit(char *s) {
\r
629 /* New function -- compares s to scaned citem and returns true if it
\r
630 matches to the length of s */
\r
632 return strncmp(s, citem, max(1, strlen(citem))) == 0;
\r
637 void debugme(void) {
\r
638 proutn("Reset levels? ");
\r
640 if (energy < inenrg) energy = inenrg;
\r
645 proutn("Reset damage? ");
\r
648 for (i=0; i <= NDEVICES; i++) if (damage[i] > 0.0) damage[i] = 0.0;
\r
651 proutn("Toggle idebug? ");
\r
654 if (idebug) prout("Debug output ON");
\r
655 else prout("Debug output OFF");
\r
657 proutn("Cause selective damage? ");
\r
660 for (i=1; i <= NDEVICES; i++) {
\r
666 if (key == IHALPHA && isit("y")) {
\r
668 if (i == DRADIO) stdamtim = game.state.date;
\r
672 proutn("Examine/change events? ");
\r
675 for (i = 1; i < NEVENTS; i++) {
\r
677 if (future[i] == 1e30) continue;
\r
679 case FSNOVA: proutn("Supernova "); break;
\r
680 case FTBEAM: proutn("T Beam "); break;
\r
681 case FSNAP: proutn("Snapshot "); break;
\r
682 case FBATTAK: proutn("Base Attack "); break;
\r
683 case FCDBAS: proutn("Base Destroy "); break;
\r
684 case FSCMOVE: proutn("SC Move "); break;
\r
685 case FSCDBAS: proutn("SC Base Destroy "); break;
\r
687 proutn("%.2f", future[i]-game.state.date);
\r
691 if (key == IHREAL) {
\r
692 future[i] = game.state.date + aaitem;
\r