X-Git-Url: https://jxself.org/git/?p=super-star-trek.git;a=blobdiff_plain;f=src%2Fsst.c;h=ccf7470b64ea04fc4f39152e0fa75ff6e272f5a5;hp=90b2b307a6ba536b964e2b89cf00621e93633248;hb=b45b4cfdbae07f0103fae675c2f8d17cdbab2352;hpb=dc45b3ccf42344c238ddb146d79dc62086624848 diff --git a/src/sst.c b/src/sst.c index 90b2b30..ccf7470 100644 --- a/src/sst.c +++ b/src/sst.c @@ -162,6 +162,17 @@ for a lot of magic numbers and refactored the heck out of it. type is "plain" or "almy".) 6. User input is now logged so we can do regression testing. + + 7. More BSD-Trek features: You can now lose if your entire crew + dies in battle. When abandoning ship in a game with inhabited + worlds enabled, they must have one in the quadrant to beam down + to; otherwise they die in space and this counts heavily against + your score. Docking at a starbase replenishes your crew. + + 8. Still more BSD-Trek: we now have a weighted damage table. + Also, the nav subsystem (enabling automatic course + setting) can be damaged separately from the main computer (which + handles weapons targeting, ETA calculation, and self-destruct). */ /* the input queue */ @@ -169,32 +180,17 @@ static char line[128], *linep = line; struct game game; coord thing; -int iqhere, iqengry; +bool iqhere, iqengry; int iscore, iskill; // Common PLAQ double aaitem; double perdate; char citem[10]; int seed; // the random-number seed bool idebug; // debug mode -bool randready; // Has the random-number generator initialized? -FILE *logfp; - -char *device[NDEVICES] = { - "S. R. Sensors", - "L. R. Sensors", - "Phasers", - "Photon Tubes", - "Life Support", - "Warp Engines", - "Impulse Engines", - "Shields", - "Subspace Radio", - "Shuttle Craft", - "Computer", - "Transporter", - "Shield Control", - "Death Ray", - "D. S. Probe"}; +FILE *logfp, *replayfp; + +char *systnames[NINHAB + 1]; +char *device[NDEVICES]; static struct { @@ -280,14 +276,20 @@ commands[] = { {"HELP", HELP, 0}, #define SEED 37 {"SEED", SEED, 0}, +#if BSD_BUG_FOR_BUG +#define VISUAL 38 + {"VISUAL", VISUAL, 0}, +#endif }; #define NUMCOMMANDS sizeof(commands)/sizeof(commands[0]) #define ACCEPT(i) (!commands[i].option || (commands[i].option & game.options)) -static void listCommands(void) { +static void listCommands(void) +/* generate a list of legal commands */ +{ int i, k = 0; - proutn("LEGAL COMMANDS ARE:"); + proutn(_("LEGAL COMMANDS ARE:")); for (i = 0; i < NUMCOMMANDS; i++) { if (!ACCEPT(i)) continue; @@ -299,7 +301,8 @@ static void listCommands(void) { skip(1); } -static void helpme(void) +static void helpme(void) +/* browse on-line help */ { int i, j; char cmdbuf[32], *cp; @@ -311,7 +314,7 @@ static void helpme(void) for(;;) { if (key == IHEOL) { setwnd(prompt_window); - proutn("Help on what command? "); + proutn(_("Help on what command? ")); key = scan(); } setwnd(message_window); @@ -324,7 +327,6 @@ static void helpme(void) } if (i != NUMCOMMANDS) break; skip(1); - prout("Valid commands:"); listCommands(); key = IHEOL; chew(); @@ -342,9 +344,13 @@ static void helpme(void) if (fp == NULL) fp = fopen(DOC_NAME, "r"); if (fp == NULL) { - prout("Spock- \"Captain, that information is missing from the"); - prout(" computer. You need to find "DOC_NAME" and put it in the"); - prout(" current directory or to "SSTDOC".\""); + prout(_("Spock- \"Captain, that information is missing from the")); + proutn(_(" computer. You need to find ")); + proutn(DOC_NAME); + prout(_(" and put it in the")); + proutn(_(" current directory or to ")); + proutn(SSTDOC); + prout(".\""); /* * This used to continue: "You need to find SST.DOC and put * it in the current directory." @@ -353,7 +359,7 @@ static void helpme(void) } for (;;) { if (fgets(linebuf, sizeof(linebuf), fp) == NULL) { - prout("Spock- \"Captain, there is no information on that command.\""); + prout(_("Spock- \"Captain, there is no information on that command.\"")); fclose(fp); return; } @@ -367,23 +373,29 @@ static void helpme(void) } skip(1); - prout("Spock- \"Captain, I've found the following information:\""); + prout(_("Spock- \"Captain, I've found the following information:\"")); skip(1); - while (fgets(linebuf, sizeof(linebuf),fp)) { + while (fgets(linebuf, sizeof(linebuf), fp)) { + char *eol; if (strstr(linebuf, "******")) break; - proutn(linebuf); + if ((eol = strpbrk(linebuf, "\r\n"))) + *eol = 0; + prout(linebuf); } fclose(fp); } -void enqueue(char *s) +void enqueue(char *s) +/* enqueue input for the command parser */ { + chew(); strcpy(line, s); } -static void makemoves(void) +static void makemoves(void) +/* command-interpretation loop */ { int key, i, v = 0; bool hitme; @@ -393,7 +405,7 @@ static void makemoves(void) drawmaps(1); for(;;) { /* get a command */ hitme = false; - game.justin = 0; + game.justin = false; game.optime = 0.0; i = -1; chew(); @@ -404,7 +416,7 @@ static void makemoves(void) makechart(); continue; } - game.ididit=0; + game.ididit = false; clrscr(); setwnd(message_window); clrscr(); @@ -450,21 +462,21 @@ static void makemoves(void) warp(false); break; case SHIELDS: // shields - doshield(1); + doshield(false); if (game.ididit) { - hitme=true; - game.shldchg = 0; + hitme = true; + game.shldchg = false; } break; case DOCK: // dock - dock(1); - if (game.ididit) attack(0); + dock(true); + if (game.ididit) attack(false); break; case DAMAGES: // damages dreprt(); break; case CHART: // chart - chart(0); + chart(false); break; case IMPULSE: // impulse impuls(); @@ -526,13 +538,13 @@ static void makemoves(void) abandn(); break; case DESTRUCT: // Self Destruct - dstrct(); + selfdestruct(); break; case SAVE: // Save Game freeze(false); clrscr(); if (game.skill > SKILL_GOOD) - prout("WARNING--Saved games produce no plaques!"); + prout(_("WARNING--Saved games produce no plaques!")); break; case DEATHRAY: // Try a desparation measure deathray(); @@ -546,7 +558,7 @@ static void makemoves(void) if (game.ididit) hitme = true; break; case QUIT: - game.alldone = 1; // quit the game + game.alldone = true; // quit the game break; case HELP: helpme(); // get help @@ -556,6 +568,11 @@ static void makemoves(void) if (key == IHREAL) seed = (int)aaitem; break; +#if BSD_BUG_FOR_BUG + case VISUAL: + visual(); // perform visual scan + break; +#endif } commandhook(commands[i].name, false); for (;;) { @@ -565,14 +582,14 @@ static void makemoves(void) if (game.alldone) break; // Events did us in } if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) { // Galaxy went Nova! - atover(0); + atover(false); continue; } - if (hitme && game.justin==0) { - attack(2); + if (hitme && !game.justin) { + attack(true); if (game.alldone) break; if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) { // went NOVA! - atover(0); + atover(false); hitme = true; continue; } @@ -595,8 +612,20 @@ int main(int argc, char **argv) else game.options |= OPTION_TTY; - while ((option = getopt(argc, argv, "tx")) != -1) { + seed = (int)time(NULL); + while ((option = getopt(argc, argv, "r:tx")) != -1) { switch (option) { + case 'r': + replayfp = fopen(optarg, "r"); + if (replayfp == NULL) { + fprintf(stderr, "sst: can't open replay file %s\n", optarg); + exit(1); + } + if (fscanf(replayfp, "seed %d\n", &seed) != 1) { + fprintf(stderr, "sst: replay file %s is ill-formed\n", optarg); + exit(1); + } + /* FALL THROUGH */ case 't': game.options |= OPTION_TTY; game.options &=~ OPTION_CURSES; @@ -610,10 +639,12 @@ int main(int argc, char **argv) } } /* where to save the input in case of bugs */ - logfp = fopen("sst-input.log", "w"); + logfp = fopen("/usr/tmp/sst-input.log", "w"); setlinebuf(logfp); + fprintf(logfp, "seed %d\n", seed); + srand(seed); - randomize(); + srand(seed); iostart(); line[0] = '\0'; @@ -628,7 +659,7 @@ int main(int argc, char **argv) setup(line[0] == '\0'); if (game.alldone) { score(); - game.alldone = 0; + game.alldone = false; } else makemoves(); skip(1); @@ -636,73 +667,79 @@ int main(int argc, char **argv) skip(1); if (game.tourn && game.alldone) { - proutn("Do you want your score recorded?"); - if (ja()) { + proutn(_("Do you want your score recorded?")); + if (ja() == true) { chew2(); freeze(false); } } - proutn("Do you want to play again? "); + proutn(_("Do you want to play again? ")); if (!ja()) break; } skip(1); - prout("May the Great Bird of the Galaxy roost upon your home planet."); + prout(_("May the Great Bird of the Galaxy roost upon your home planet.")); return 0; } -void cramen(int i) +void cramen(feature i) +/* print the name of an enemy */ { /* return an enemy */ char *s; switch (i) { - case IHR: s = "Romulan"; break; - case IHK: s = "Klingon"; break; - case IHC: s = "Commander"; break; - case IHS: s = "Super-commander"; break; - case IHSTAR: s = "Star"; break; - case IHP: s = "Planet"; break; - case IHB: s = "Starbase"; break; - case IHBLANK: s = "Black hole"; break; - case IHT: s = "Tholian"; break; - case IHWEB: s = "Tholian web"; break; - case IHQUEST: s = "Stranger"; break; + case IHR: s = _("Romulan"); break; + case IHK: s = _("Klingon"); break; + case IHC: s = _("Commander"); break; + case IHS: s = _("Super-commander"); break; + case IHSTAR: s = _("Star"); break; + case IHP: s = _("Planet"); break; + case IHB: s = _("Starbase"); break; + case IHBLANK: s = _("Black hole"); break; + case IHT: s = _("Tholian"); break; + case IHWEB: s = _("Tholian web"); break; + case IHQUEST: s = _("Stranger"); break; + case IHW: s = _("Inhabited World"); break; default: s = "Unknown??"; break; } proutn(s); } char *cramlc(enum loctype key, coord w) +/* name a location */ { static char buf[32]; buf[0] = '\0'; - if (key == quadrant) strcpy(buf, "Quadrant "); - else if (key == sector) strcpy(buf, "Sector "); + if (key == quadrant) strcpy(buf, _("Quadrant ")); + else if (key == sector) strcpy(buf, _("Sector ")); sprintf(buf+strlen(buf), "%d - %d", w.x, w.y); return buf; } -void crmena(int i, int enemy, int key, coord w) +void crmena(bool stars, feature enemy, enum loctype key, coord w) +/* print an enemy and his location */ { - if (i == 1) proutn("***"); + if (stars) proutn("***"); cramen(enemy); - proutn(" at "); + proutn(_(" at ")); proutn(cramlc(key, w)); } -void crmshp(void) +void crmshp(void) +/* print our ship name */ { char *s; switch (game.ship) { - case IHE: s = "Enterprise"; break; - case IHF: s = "Faerie Queene"; break; + case IHE: s = _("Enterprise"); break; + case IHF: s = _("Faerie Queene"); break; default: s = "Ship???"; break; } proutn(s); } -void stars(void) +void stars(void) +/* print a line of stars */ { prouts("******************************************************"); skip(1); @@ -715,21 +752,16 @@ double expran(double avrage) double Rand(void) { - if (!randready) { - if (seed == 0) - seed = (unsigned)time(NULL); - if (logfp) - fprintf(logfp, "seed %d\n", seed); - srand(seed); - randready = true; - } return rand()/(1.0 + (double)RAND_MAX); } -void iran(int size, int *i, int *j) +coord randplace(int size) +/* choose a random location */ { - *i = Rand()*(size*1.0) + 1.0; - *j = Rand()*(size*1.0) + 1.0; + coord w; + w.x = Rand()*(size*1.0) + 1.0; + w.y = Rand()*(size*1.0) + 1.0; + return w; } void chew(void) @@ -800,7 +832,8 @@ int scan(void) return IHALPHA; } -bool ja(void) +bool ja(void) +/* yes-or-no confirmation */ { chew(); for(;;) { @@ -808,50 +841,49 @@ bool ja(void) chew(); if (*citem == 'y') return true; if (*citem == 'n') return false; - proutn("Please answer with \"Y\" or \"N\": "); + proutn(_("Please answer with \"y\" or \"n\": ")); } } -void huh(void) +void huh(void) +/* complain about unparseable input */ { chew(); skip(1); - prout("Beg your pardon, Captain?"); + prout(_("Beg your pardon, Captain?")); } -int isit(char *s) +bool isit(char *s) +/* compares s to citem and returns true if it matches to the length of s */ { - /* New function -- compares s to scanned citem and returns true if it - matches to the length of s */ - return strncasecmp(s, citem, max(1, strlen(citem))) == 0; - } -void debugme(void) +void debugme(void) +/* access to the internals for debugging */ { proutn("Reset levels? "); - if (ja() != 0) { + if (ja() == true) { if (game.energy < game.inenrg) game.energy = game.inenrg; game.shield = game.inshld; game.torps = game.intorps; game.lsupres = game.inlsr; } proutn("Reset damage? "); - if (ja() != 0) { + if (ja() == true) { int i; for (i=0; i < NDEVICES; i++) if (game.damage[i] > 0.0) game.damage[i] = 0.0; } proutn("Toggle debug flag? "); - if (ja() != 0) { + if (ja() == true) { idebug = !idebug; if (idebug) prout("Debug output ON"); else prout("Debug output OFF"); } proutn("Cause selective damage? "); - if (ja() != 0) { + if (ja() == true) { int i, key; for (i=0; i < NDEVICES; i++) { proutn("Kill "); @@ -865,7 +897,7 @@ void debugme(void) } } proutn("Examine/change events? "); - if (ja() != 0) { + if (ja() == true) { event *ev; coord w; int i; @@ -884,12 +916,16 @@ void debugme(void) case FENSLV: proutn("Enlavement "); break; case FREPRO: proutn("Klingon Build "); break; } - if (is_scheduled(i)) + if (is_scheduled(i)) { proutn("%.2f", scheduled(i)-game.state.date); - else + if (i == FENSLV || i == FREPRO) { + ev = findevent(i); + proutn(" in %d-%d", ev->quadrant.x,ev->quadrant.y); + } + } else proutn("never"); - chew(); proutn("? "); + chew(); key = scan(); if (key == 'n') { unschedule(i); @@ -900,28 +936,31 @@ void debugme(void) chew(); proutn("In quadrant- "); key = scan(); - if (key != IHREAL) { - prout("Event %d canceled, no y coordinate.", i); - unschedule(i); - continue; - } - w.y = (int)aaitem; - key = scan(); - if (key != IHREAL) { - prout("Event %d canceled, no x coordinate.", i); - unschedule(i); - continue; + /* IHEOL says to leave coordinates as they are */ + if (key != IHEOL) { + if (key != IHREAL) { + prout("Event %d canceled, no x coordinate.", i); + unschedule(i); + continue; + } + w.x = (int)aaitem; + key = scan(); + if (key != IHREAL) { + prout("Event %d canceled, no y coordinate.", i); + unschedule(i); + continue; + } + w.y = (int)aaitem; + ev->quadrant = w; } - w.x = (int)aaitem; - ev->quadrant = w; } } } chew(); } proutn("Induce supernova here? "); - if (ja()) { + if (ja() == true) { game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = true; - atover(1); + atover(true); } }