#include #ifdef MSDOS #include #endif #ifdef WINDOWS #include #endif #include #ifdef KOS32 #include #include #endif #define INCLUDED // Define externs here #include "sst.h" /*int getch(void); */ static char line[128], *linep = line; static int linecount; /* for paging */ static void clearscreen(void); /* Compared to original version, I've changed the "help" command to "call" and the "terminate" command to "quit" to better match user expectations. The DECUS version apparently made those changes as well as changing "freeze" to "save". However I like "freeze". When I got a later version of Super Star Trek that I was converting from, I added the emexit command. That later version also mentions srscan and lrscan working when docked (using the starbase's scanners), so I made some changes here to do this (and indicating that fact to the player), and then realized the base would have a subspace radio as well -- doing a Chart when docked updates the star chart, and all radio reports will be heard. The Dock command will also give a report if a base is under attack. Movecom no longer reports movement if sensors are damaged so you wouldn't otherwise know it. Also added: 1. Better base positioning at startup 2. deathray improvement (but keeping original failure alternatives) 3. Tholian Web 4. Enemies can ram the Enterprise. Regular Klingons and Romulans can move in Expert and Emeritus games. This code could use improvement. 5. The deep space probe looks interesting! DECUS version 6. Cloaking (with contributions from Erik Olofsen) and Capturing (BSD version). */ // I don't like the way this is done, relying on an index. But I don't // want to invest the time to make this nice and table driven. static char *commands[] = { "srscan", "lrscan", "phasers", "photons", "move", "shields", "dock", "damages", "chart", "impulse", "rest", "warp", "status", "sensors", "orbit", "transport", "mine", "crystals", "shuttle", "planets", "request", "report", "computer", "commands", "emexit", "probe", "cloak", "capture", "score", "abandon", "destruct", "freeze", "deathray", "debug", "call", "quit", "help" }; #define NUMCOMMANDS (sizeof(commands)/sizeof(char *)) static void listCommands(int x) { prout(" SRSCAN MOVE PHASERS CALL\n" " STATUS IMPULSE PHOTONS ABANDON\n" " LRSCAN WARP SHIELDS DESTRUCT\n" " CHART REST DOCK QUIT\n" " DAMAGES REPORT SENSORS ORBIT\n" " TRANSPORT MINE CRYSTALS SHUTTLE\n" " PLANETS REQUEST DEATHRAY FREEZE\n" " COMPUTER EMEXIT PROBE COMMANDS"); proutn(" "); #ifdef SCORE proutn("SCORE "); #endif #ifdef CLOAKING proutn("CLOAK "); #endif #ifdef CAPTURE proutn("CAPTURE "); #endif if (x) proutn("HELP "); prout(""); } static void helpme(void) { int i, j; char cmdbuf[32]; char linebuf[132]; FILE *fp; /* Give help on commands */ int key; key = scan(); while (TRUE) { if (key == IHEOL) { /* proutn("Help on what command?"); */ proutn("Справку по какой команде?"); key = scan(); } if (key == IHEOL) return; for (i = 0; i < NUMCOMMANDS; i++) { if (strcmp(commands[i], citem)==0) break; } if (i != NUMCOMMANDS) break; skip(1); /* prout("Valid commands:"); */ prout("Перечень команд:"); listCommands(FALSE); key = IHEOL; chew(); skip(1); } if (i == 23) { strcpy(cmdbuf, " ABBREV"); } else { strcpy(cmdbuf, " Mnemonic: "); j = 0; while ((cmdbuf[j+13] = toupper(commands[i][j])) != 0) j++; } fp = fopen("sst.doc", "r"); if (fp == NULL) { /* prout("Spock- \"Captain, that information is missing from the"); prout(" computer. You need to find SST.DOC and put it in the"); prout(" current directory.\""); */ prout("Спок- \"Капитан, вся справочная информация пропала с нашего компьютера."); prout(" Найдите файл SST.DOC и положите в текущую папку.\""); return; } i = strlen(cmdbuf); do { if (fgets(linebuf, 132, fp) == NULL) { /* prout("Spock- \"Captain, there is no information on that command.\""); */ prout("Спок- \"Капитан, по этой команде справочная информация не найдена.\""); fclose(fp); return; } } while (strncmp(linebuf, cmdbuf, i) != 0); skip(1); /* prout("Spock- \"Captain, I've found the following information:\""); */ prout("Спок- \"Капитан, я нашел следующую информацию:\""); skip(1); do { if (linebuf[0]!=12) { // ignore page break lines linebuf[strlen(linebuf)-1] = '\0'; // No \n at end prout(linebuf); } fgets(linebuf,132,fp); } while (strstr(linebuf, "******")==NULL); fclose(fp); } static void makemoves(void) { int i, hitme; char ch; while (TRUE) { /* command loop */ hitme = FALSE; justin = 0; Time = 0.0; i = -1; while (TRUE) { /* get a command */ chew(); skip(1); proutn("COMMAND> "); if (scan() == IHEOL) continue; for (i=0; i < 29; i++) // Abbreviations allowed for the first 29 commands, only. if (isit(commands[i])) break; if (i < 29) break; for (; i < NUMCOMMANDS; i++) if (strcmp(commands[i], citem) == 0) break; if (i < NUMCOMMANDS #ifndef CLOAKING && i != 26 // ignore the CLOAK command #endif #ifndef CAPTURE && i != 27 // ignore the CAPTURE command #endif #ifndef SCORE && i != 28 // ignore the SCORE command #endif #ifndef DEBUG && i != 33 // ignore the DEBUG command #endif ) break; if (skill <= SFAIR) { /* prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:"); */ prout("КОМАНДА НЕ РАСПОЗНАНА. ДЕЙСТВУЮЩИЕ КОМАНДЫ:"); listCommands(TRUE); } else prout("КОМАНДА НЕ РАСПОЗНАНА.");/*UNRECOGNIZED COMMAND*/ } switch (i) { /* command switch */ case 0: // srscan srscan(1); break; case 1: // lrscan lrscan(); break; case 2: // phasers phasers(); if (ididit) { #ifdef CLOAKING if (irhere && d.date >= ALGERON && !isviolreported && iscloaked) { /* prout("The Romulan ship discovers you are breaking the Treaty of Algeron!"); */ prout("Корабль ромуланцев заметил ваше нарушение Алгеронского соглашения!"); ncviol++; isviolreported = TRUE; } #endif hitme = TRUE; } break; case 3: // photons photon(); if (ididit) { #ifdef CLOAKING if (irhere && d.date >= ALGERON && !isviolreported && iscloaked) { /* prout("The Romulan ship discovers you are breaking the Treaty of Algeron!"); */ prout("Корабль ромуланцев заметил ваше нарушение Алгеронского соглашения!"); ncviol++; isviolreported = TRUE; } #endif hitme = TRUE; } break; case 4: // move warp(1); break; case 5: // shields sheild(1); if (ididit) { attack(2); shldchg = 0; } break; case 6: // dock dock(); break; case 7: // damages dreprt(); break; case 8: // chart chart(0); break; case 9: // impulse impuls(); break; case 10: // rest waiting(); if (ididit) hitme = TRUE; break; case 11: // warp setwrp(); break; case 12: // status srscan(3); break; case 13: // sensors sensor(); break; case 14: // orbit orbit(); if (ididit) hitme = TRUE; break; case 15: // transport "beam" beam(); break; case 16: // mine mine(); if (ididit) hitme = TRUE; break; case 17: // crystals usecrystals(); break; case 18: // shuttle shuttle(); if (ididit) hitme = TRUE; break; case 19: // Planet list preport(); break; case 20: // Status information srscan(2); break; case 21: // Game Report report(0); break; case 22: // use COMPUTER! eta(); break; case 23: listCommands(TRUE); break; case 24: // Emergency exit clearscreen(); // Hide screen freeze(TRUE); // forced save #ifdef KOS32 con_exit(1); #endif exit(1); // And quick exit break; case 25: probe(); // Launch probe break; #ifdef CLOAKING case 26: cloak(); // turn on/off cloaking if (iscloaking) { attack(2); // We will be seen while we cloak iscloaking = FALSE; iscloaked = TRUE; } break; #endif #ifdef CAPTURE case 27: capture(); // Attempt to get Klingon ship to surrender if (ididit) hitme = TRUE; break; #endif #ifdef SCORE case 28: score(1); // get the score break; #endif case 29: // Abandon Ship abandn(); break; case 30: // Self Destruct dstrct(); break; case 31: // Save Game freeze(FALSE); if (skill > SGOOD) /* prout("WARNING--Frozen games produce no plaques!"); */ prout("ВНИМАНИЕ--Сохраненные игры не дают наград!"); break; case 32: // Try a desparation measure deathray(); if (ididit) hitme = TRUE; break; #ifdef DEBUG case 33: // What do we want for debug??? debugme(); break; #endif case 34: // Call for help help(); break; case 35: alldone = 1; // quit the game #ifdef DEBUG if (idebug) score(0); #endif break; case 36: helpme(); // get help break; } for (;;) { if (alldone) break; // Game has ended #ifdef DEBUG if (idebug) prout("2500"); #endif if (Time != 0.0) { events(); if (alldone) break; // Events did us in } if (d.galaxy[quadx][quady] == 1000) { // Galaxy went Nova! atover(0); continue; } if (nenhere == 0) movetho(); if (hitme && justin==0) { attack(2); if (alldone) break; if (d.galaxy[quadx][quady] == 1000) { // went NOVA! atover(0); hitme = TRUE; continue; } } break; } if (alldone) break; } } int main(int argc, char **argv) { int i; int hitme; char ch; #ifdef KOS32 if (con_init_console_dll()) return 1; // init fail con_set_title("-SUPER- STAR TREK"); con_set_flags(CON_COLOR_GREEN); #endif #ifdef WINDOWS HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Get handle to standard output SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); #endif prelim(); if (argc > 1) { // look for -f option if (strcmp(argv[1], "-f")== 0) { coordfixed = 1; argc--; argv++; } } if (argc > 1) { fromcommandline = 1; line[0] = '\0'; while (--argc > 0) { strcat(line, *(++argv)); strcat(line, " "); } } else fromcommandline = 0; while (TRUE) { /* Play a game */ setup(); if (alldone) { score(0); alldone = 0; } else makemoves(); skip(2); stars(); skip(1); if (tourn && alldone) { /* printf("Do you want your score recorded?"); */ printf("Вы хотите записать свои достижения?"); if (ja()) { chew2(); freeze(FALSE); } } /* printf("Do you want to play again?"); */ printf("Желаете сыграть заново?"); if (!ja()) break; } skip(1); /* prout("May the Great Bird of the Galaxy roost upon your home planet."); */ prout("Пусть Великая Галактическая Птица совьет гнездо на Вашей родной планете."); return 0; } void cramen(int i) { /* return an enemy */ char *s; switch (i) { case IHR: s = "Ромуланец"; break;/*Romulan*/ case IHK: s = "Клингон"; break;/*Klingon*/ case IHC: s = "Коммандер"; break;/*Commander*/ case IHS: s = "СуперКоммандер"; break;/*Super-commander*/ case IHSTAR: s = "Звезда"; break;/*Star*/ case IHP: s = "Планета"; break;/*Planet*/ case IHB: s = "Станция"; break;/*Starbase*/ case IHBLANK: s = "Черная дыра"; break;/*Black hole*/ case IHT: s = "Толиан"; break;/*Tholean*/ case IHWEB: s = "Толианская сеть"; break;/*Tholean web*/ default: s = "НЛО??"; break;/*Unknown*/ } proutn(s); } void cramlc(int key, int x, int y) { if (key == 1) proutn(" Квадрант");/*Quadrant*/ else if (key == 2) proutn(" Сектор");/*Sector*/ proutn(" "); crami(x, 1); proutn(" - "); crami(y, 1); } void crmena(int i, int enemy, int key, int x, int y) { if (i == 1) proutn("***"); cramen(enemy); proutn(" at"); cramlc(key, x, y); } void crmshp(void) { char *s; switch (ship) { case IHE: s = "Энтерпрайз"; break;/*Enterprise*/ case IHF: s = "Королева Фей"; break;/*Faerie Queene*/ default: s = "Корабль???"; break;/*Ship*/ } proutn(s); } void stars(void) { prouts("******************************************************"); skip(1); } double expran(double avrage) { return -avrage*log(1e-7 + Rand()); } double Rand(void) { return rand()/(1.0 + (double)RAND_MAX); } void iran8(int *i, int *j) { *i = Rand()*8.0 + 1.0; *j = Rand()*8.0 + 1.0; } void iran10(int *i, int *j) { *i = Rand()*10.0 + 1.0; *j = Rand()*10.0 + 1.0; } void chew(void) { linecount = 0; linep = line; *linep = 0; } void chew2(void) { /* return IHEOL next time */ linecount = 0; linep = line+1; *linep = 0; } int scan(void) { int i; char *cp; linecount = 0; // Init result aaitem = 0.0; *citem = 0; // Read a line if nothing here if (*linep == 0) { if (linep != line) { chew(); return IHEOL; } #ifdef KOS32 cp = gets(line); if (!cp) exit(1); #else // We should really be using fgets fgets(line,sizeof(line),stdin); #endif if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; linep = line; } // Skip leading white space while (*linep == ' ') linep++; // Nothing left if (*linep == 0) { chew(); return IHEOL; } if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') { // treat as a number if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) { linep = line; // Invalid numbers are ignored *linep = 0; return IHEOL; } else { // skip to end linep += i; return IHREAL; } } // Treat as alpha cp = citem; while (*linep && *linep!=' ') { if ((cp - citem) < 9) *cp++ = tolower(*linep); linep++; } *cp = 0; return IHALPHA; } int ja(void) { chew(); while (TRUE) { scan(); chew(); if (*citem == 'y') return TRUE; if (*citem == 'n') return FALSE; /* proutn("Please answer with \"Y\" or \"N\":"); */ proutn("Пожалуйста ответьте \"y\" or \"n\":"); } } void cramf(double x, int w, int d) { char buf[64]; sprintf(buf, "%*.*f", w, d, x); proutn(buf); } void crami(int i, int w) { char buf[16]; sprintf(buf, "%*d", w, i); proutn(buf); } double square(double i) { return i*i; } static void clearscreen(void) { /* Somehow we need to clear the screen */ proutn("\033[2J\033[0;0H"); /* Hope for an ANSI display */ } /* We will pull these out in case we want to do something special later */ void pause(int i) { #ifdef CLOAKING if (iscloaked) return; #endif putchar('\n'); if (i==1) { if (skill > SFAIR) prout("[ПОЛУЧЕНО ОБЪЯВЛЕНИЕ...]");/*ANNOUNCEMENT ARRIVING*/ else /* prout("[IMPORTANT ANNOUNCEMENT ARRIVING -- HIT ENTER TO CONTINUE]"); */ prout("[ПОЛУЧЕНО ВАЖНОЕ ОБЪЯВЛЕНИЕ -- НАЖМИТЕ ENTER ДЛЯ ПРОДОЛЖЕНИЯ]"); getchar(); } else { if (skill > SFAIR) proutn("[ПРОДОЛЖИТЬ?]");/*CONTINUE*/ else proutn("[НАЖМИТЕ ENTER ДЛЯ ПРОДОЛЖЕНИЯ]");/*HIT ENTER TO CONTINUE*/ getchar(); proutn("\r \r"); } if (i != 0) { clearscreen(); } linecount = 0; } void skip(int i) { while (i-- > 0) { linecount++; if (linecount >= 23) pause(0); else putchar('\n'); } } void proutn(char *s) { #ifndef KOS32 fputs(s, stdout); #else con_write_asciiz(s); #endif } void prout(char *s) { proutn(s); skip(1); } void prouts(char *s) { #ifdef KOS32 #define clock_t long int #define clock() get_tick_count() #define CLOCKS_PER_SEC 100 #endif clock_t endTime; /* print slowly! */ while (*s) { endTime = clock() + CLOCKS_PER_SEC*0.05; while (clock() < endTime) ; putchar(*s++); #ifndef KOS32 fflush(stdout); #endif } } void huh(void) { chew(); skip(1); /* prout("Beg your pardon, Captain?"); */ prout("Простите, не понял, Капитан?"); } int isit(char *s) { /* New function -- compares s to scaned citem and returns true if it matches to the length of s */ return strncmp(s, citem, max(1, strlen(citem))) == 0; } #ifdef DEBUG void debugme(void) { proutn("Reset levels? "); if (ja() != 0) { if (energy < inenrg) energy = inenrg; shield = inshld; torps = intorps; lsupres = inlsr; } proutn("Reset damage? "); if (ja() != 0) { int i; for (i=0; i <= ndevice; i++) if (damage[i] > 0.0) damage[i] = 0.0; stdamtim = 1e30; } proutn("Toggle idebug? "); if (ja() != 0) { idebug = !idebug; if (idebug) prout("Debug output ON"); else prout("Debug output OFF"); } proutn("Cause selective damage? "); if (ja() != 0) { int i, key; for (i=1; i <= ndevice; i++) { proutn("Kill "); proutn(device[i]); proutn("? "); chew(); key = scan(); if (key == IHALPHA && isit("y")) { damage[i] = 10.0; if (i == DRADIO) stdamtim = d.date; } } } proutn("Examine/change events? "); if (ja() != 0) { int i; for (i = 1; i < NEVENTS; i++) { int key; if (future[i] == 1e30) continue; switch (i) { case FSNOVA: proutn("Supernova "); break; case FTBEAM: proutn("T Beam "); break; case FSNAP: proutn("Snapshot "); break; case FBATTAK: proutn("Base Attack "); break; case FCDBAS: proutn("Base Destroy "); break; case FSCMOVE: proutn("SC Move "); break; case FSCDBAS: proutn("SC Base Destroy "); break; } cramf(future[i]-d.date, 8, 2); chew(); proutn(" ?"); key = scan(); if (key == IHREAL) { future[i] = d.date + aaitem; } } chew(); } proutn("Make universe visible? "); if (ja() != 0) { int i, j; for (i = 1; i < 9; i++) { for (j = 1; j < 9; j++) { starch[i][j] = 1; } } } } #endif