5. Half the quadrants now have inhabited planets, from which one
cannot mine dilithium (there will still be the same additional number
- of dilithium-bearing planets). Right now this is just color, but
- eventually we'll fold in BSD-Trek-like logic for Klingons to attack
- and enslave inhabited worlds.
+ of dilithium-bearing planets). Torpedoing an inhabited world is *bad*.
+ There is BSD-Trek-like logic for Klingons to attack and enslave
+ inhabited worlds, producing more ships (only is skill is 'good' or
+ better). (Controlled by OPTION_WORLDS and turned off if game
+ type is "plain" or "almy".)
+
+ 6. User input is now logged so we can do regression testing.
*/
/* the input queue */
static char line[128], *linep = line;
struct game game;
-int thingx, thingy, iqhere, iqengry;
-int iscore, iskill; // Common PLAQ
+coord thing;
+int iqhere, iqengry;
+int iscore, iskill; // Common PLAQ
double aaitem;
double perdate;
char citem[10];
+int seed; // the random-number seed
+bool idebug; // debug mode
+FILE *logfp, *replayfp;
char *device[NDEVICES] = {
"S. R. Sensors",
{"QUIT", QUIT, 0},
#define HELP 36
{"HELP", HELP, 0},
+#define SEED 37
+ {"SEED", SEED, 0},
};
#define NUMCOMMANDS sizeof(commands)/sizeof(commands[0])
/* Give help on commands */
int key;
key = scan();
- while (TRUE) {
+ for(;;) {
if (key == IHEOL) {
setwnd(prompt_window);
proutn("Help on what command? ");
static void makemoves(void)
{
- int i, v = 0, hitme;
+ int key, i, v = 0;
+ bool hitme;
clrscr();
setwnd(message_window);
- while (TRUE) { /* command loop */
+ for(;;) { /* command loop */
drawmaps(1);
- while (TRUE) { /* get a command */
- hitme = FALSE;
+ for(;;) { /* get a command */
+ hitme = false;
game.justin = 0;
game.optime = 0.0;
i = -1;
break;
listCommands();
}
- commandhook(commands[i].name, TRUE);
+ commandhook(commands[i].name, true);
switch (v) { /* command switch */
case SRSCAN: // srscan
srscan(SCAN_FULL);
break;
case PHASERS: // phasers
phasers();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case TORPEDO: // photons
photon();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case MOVE: // move
- warp(1);
+ warp(false);
break;
case SHIELDS: // shields
doshield(1);
if (game.ididit) {
- hitme=TRUE;
+ hitme=true;
game.shldchg = 0;
}
break;
break;
case REST: // rest
wait();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case WARP: // warp
setwrp();
break;
case ORBIT: // orbit
orbit();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case TRANSPORT: // transport "beam"
beam();
break;
case MINE: // mine
mine();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case CRYSTALS: // crystals
usecrystals();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case SHUTTLE: // shuttle
shuttle();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case PLANETS: // Planet list
preport();
break;
case EMEXIT: // Emergency exit
clrscr(); // Hide screen
- freeze(TRUE); // forced save
+ freeze(true); // forced save
exit(1); // And quick exit
break;
case PROBE:
probe(); // Launch probe
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case ABANDON: // Abandon Ship
abandn();
dstrct();
break;
case SAVE: // Save Game
- freeze(FALSE);
+ freeze(false);
clrscr();
if (game.skill > SKILL_GOOD)
prout("WARNING--Saved games produce no plaques!");
break;
case DEATHRAY: // Try a desparation measure
deathray();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case DEBUGCMD: // What do we want for debug???
-#ifdef DEBUG
debugme();
-#endif
break;
case MAYDAY: // Call for help
mayday();
- if (game.ididit) hitme = TRUE;
+ if (game.ididit) hitme = true;
break;
case QUIT:
game.alldone = 1; // quit the game
-#ifdef DEBUG
- if (game.idebug) score();
-#endif
break;
case HELP:
- helpme(); // get help
+ helpme(); // get help
+ break;
+ case SEED: // set random-number seed
+ key = scan();
+ if (key == IHREAL)
+ seed = (int)aaitem;
break;
}
- commandhook(commands[i].name, FALSE);
+ commandhook(commands[i].name, false);
for (;;) {
if (game.alldone) break; // Game has ended
-#ifdef DEBUG
- if (game.idebug) prout("2500");
-#endif
if (game.optime != 0.0) {
events();
if (game.alldone) break; // Events did us in
}
- if (game.state.galaxy[game.quadx][game.quady].supernova) { // Galaxy went Nova!
+ if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) { // Galaxy went Nova!
atover(0);
continue;
}
if (hitme && game.justin==0) {
attack(2);
if (game.alldone) break;
- if (game.state.galaxy[game.quadx][game.quady].supernova) { // went NOVA!
+ if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) { // went NOVA!
atover(0);
- hitme = TRUE;
+ hitme = true;
continue;
}
}
}
if (game.alldone) break;
}
+ if (idebug) prout("=== Ending");
}
else
game.options |= OPTION_TTY;
- while ((option = getopt(argc, argv, "t")) != -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;
break;
+ case 'x':
+ idebug = true;
+ break;
default:
- fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
+ fprintf(stderr, "usage: sst [-t] [-x] [startcommand...].\n");
exit(0);
}
}
+ /* where to save the input in case of bugs */
+ logfp = fopen("sst-input.log", "w");
+ setlinebuf(logfp);
+ fprintf(logfp, "seed %d\n", seed);
+ srand(seed);
- randomize();
+ srand(seed);
iostart();
line[0] = '\0';
strcat(line, argv[i]);
strcat(line, " ");
}
- while (TRUE) { /* Play a game */
+ for(;;) { /* Play a game */
setwnd(fullscreen_window);
-#ifdef DEBUG
- prout("INITIAL OPTIONS: %0lx", game.options);
-#endif /* DEBUG */
clrscr();
prelim();
setup(line[0] == '\0');
proutn("Do you want your score recorded?");
if (ja()) {
chew2();
- freeze(FALSE);
+ freeze(false);
}
}
proutn("Do you want to play again? ");
proutn(s);
}
-char *cramlc(enum loctype key, int x, int y)
+char *cramlc(enum loctype key, coord w)
{
static char buf[32];
buf[0] = '\0';
if (key == quadrant) strcpy(buf, "Quadrant ");
else if (key == sector) strcpy(buf, "Sector ");
- sprintf(buf+strlen(buf), "%d - %d", x, y);
+ sprintf(buf+strlen(buf), "%d - %d", w.x, w.y);
return buf;
}
-void crmena(int i, int enemy, int key, int x, int y)
+void crmena(int i, int enemy, int key, coord w)
{
if (i == 1) proutn("***");
cramen(enemy);
proutn(" at ");
- proutn(cramlc(key, x, y));
+ proutn(cramlc(key, w));
}
void crmshp(void)
return -avrage*log(1e-7 + Rand());
}
-double Rand(void) {
- return rand()/(1.0 + (double)RAND_MAX);
+double Rand(void)
+{
+ return rand()/(1.0 + (double)RAND_MAX);
}
void iran(int size, int *i, int *j)
return IHALPHA;
}
-int ja(void)
+bool ja(void)
{
chew();
- while (TRUE) {
+ for(;;) {
scan();
chew();
- if (*citem == 'y') return TRUE;
- if (*citem == 'n') return FALSE;
+ if (*citem == 'y') return true;
+ if (*citem == 'n') return false;
proutn("Please answer with \"Y\" or \"N\": ");
}
}
}
-#ifdef DEBUG
void debugme(void)
{
proutn("Reset levels? ");
if (ja() != 0) {
- if (energy < game.inenrg) energy = game.inenrg;
- shield = game.inshld;
- torps = game.intorps;
+ 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 (game.damage[i] > 0.0)
game.damage[i] = 0.0;
}
- proutn("Toggle game.idebug? ");
+ proutn("Toggle debug flag? ");
if (ja() != 0) {
- game.idebug = !game.idebug;
- if (game.idebug) prout("Debug output ON");
+ idebug = !idebug;
+ if (idebug) prout("Debug output ON");
else prout("Debug output OFF");
}
proutn("Cause selective damage? ");
}
proutn("Examine/change events? ");
if (ja() != 0) {
+ event *ev;
+ coord w;
int i;
for (i = 1; i < NEVENTS; i++) {
int key;
- if (game.future[i] == FOREVER) continue;
switch (i) {
case FSNOVA: proutn("Supernova "); break;
case FTBEAM: proutn("T Beam "); break;
case FCDBAS: proutn("Base Destroy "); break;
case FSCMOVE: proutn("SC Move "); break;
case FSCDBAS: proutn("SC Base Destroy "); break;
+ case FDSPROB: proutn("Probe Move "); break;
+ case FDISTR: proutn("Distress Call "); break;
+ case FENSLV: proutn("Enlavement "); break;
+ case FREPRO: proutn("Klingon Build "); break;
}
- proutn("%.2f", game.future[i]-game.state.date);
+ if (is_scheduled(i)) {
+ proutn("%.2f", scheduled(i)-game.state.date);
+ if (i == FENSLV || i == FREPRO) {
+ ev = findevent(i);
+ proutn(" in %d-%d", ev->quadrant.x,ev->quadrant.y);
+ }
+ } else
+ proutn("never");
+ proutn("? ");
chew();
- proutn(" ?");
key = scan();
- if (key == IHREAL) {
- game.future[i] = game.state.date + aaitem;
+ if (key == 'n') {
+ unschedule(i);
+ chew();
+ } else if (key == IHREAL) {
+ ev = schedule(i, aaitem);
+ if (i == FENSLV || i == FREPRO) {
+ chew();
+ proutn("In quadrant- ");
+ key = scan();
+ /* 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;
+ }
+ }
}
}
chew();
}
proutn("Induce supernova here? ");
- if (ja() != 0) {
- game.state.galaxy[game.quadx][game.quady].supernova = TRUE;
+ if (ja()) {
+ game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = true;
atover(1);
}
}
-#endif