X-Git-Url: https://jxself.org/git/?p=super-star-trek.git;a=blobdiff_plain;f=c-version%2Fsrc%2Fsst.c;fp=c-version%2Fsrc%2Fsst.c;h=c9bf9f4402ff41dbd8ecd436e3c03b85bd97950a;hp=0000000000000000000000000000000000000000;hb=1dc3e2e56bd836aa1c9d45417222b4fed6d34c0e;hpb=16a5bbd86d12644c1a613e61e990f76b16a567f0 diff --git a/c-version/src/sst.c b/c-version/src/sst.c new file mode 100644 index 0000000..c9bf9f4 --- /dev/null +++ b/c-version/src/sst.c @@ -0,0 +1,983 @@ +#include +#include +#include +#include "sstlinux.h" +#include "sst.h" + +#define DOC_NAME "sst.doc" + +/* + +Dave Matuszek says: + + SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON, + LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE + were in the original non-"super" version of UT FORTRAN Star Trek. + + Tholians weren't in the original. Dave is dubious about their merits. + (They are now controlled by OPTION_THOLIAN and turned off if the game + type is "plain".) + + Planets and dilithium crystals weren't in the original. Dave is OK + with this idea. (It's now controlled by OPTION_PLANETS and turned + off if the game type is "plain".) + + Dave says the bit about the Galileo getting turned into a + McDonald's is "consistant with our original vision". (This has been + left permanently enabled, as it can only happen if OPTION_PLANETS + is on.) + + Dave also says the Space Thingy should not be preserved across saved + games, so you can't prove to others that you've seen it. He says it + shouldn't fire back, either. It should do nothing except scream and + disappear when hit by photon torpedos. It's OK that it may move + when attacked, but it didn't in the original. (Whether the Thingy + can fire back is now controlled by OPTION_THINGY and turned off if the + game type is "plain" or "almy". The no-save behavior has been restored.) + + The Faerie Queen, black holes, and time warping were in the original. + +Here are Tom Almy's changes: + + In early 1997, I got the bright idea to look for references to + "Super Star Trek" on the World Wide Web. There weren't many hits, + but there was one that came up with 1979 Fortran sources! This + version had a few additional features that mine didn't have, + however mine had some feature it didn't have. So I merged its + features that I liked. I also took a peek at the DECUS version (a + port, less sources, to the PDP-10), and some other variations. + + 1, Compared to the original UT 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". + (Both "freeze" and "save" work in SST2K.) + + 2. The experimental deathray originally had only a 5% chance of + success, but could be used repeatedly. I guess after a couple + years of use, it was less "experimental" because the 1979 + version had a 70% success rate. However it was prone to breaking + after use. I upgraded the deathray, but kept the original set of + failure modes (great humor!). (Now controlled by OPTION_DEATHRAY + and turned off if game type is "plain".) + + 3. The 1979 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. + + 4. Tholian Web from the 1979 version. (Now controlled by + OPTION_THOLIAN and turned off if game type is "plain".) + + 5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING + and turned off if game type is "plain".) + + 6. Regular Klingons and Romulans can move in Expert and Emeritus games. + This code could use improvement. (Now controlled by OPTION_MVBADDY + and turned off if game type is "plain".) + + 7. The deep-space probe feature from the DECUS version. (Now controlled + by OPTION_PROBE and turned off if game type is "plain"). + + 8. 'emexit' command from the 1979 version. + + 9. Bugfix: Klingon commander movements are no longer reported if long-range + sensors are damaged. + + 10. Bugfix: Better base positioning at startup (more spread out). + That made sense to add because most people abort games with + bad base placement. + + In June 2002, I fixed two known bugs and a documentation typo. + In June 2004 I fixed a number of bugs involving: 1) parsing invalid + numbers, 2) manual phasers when SR scan is damaged and commander is + present, 3) time warping into the future, 4) hang when moving + klingons in crowded quadrants. (These fixes are in SST2K.) + +Here are Stas Sergeev's changes: + + 1. The Space Thingy can be shoved, if you ram it, and can fire back if + fired upon. (Now controlled by OPTION_THINGY and turned off if game + type is "plain" or "almy".) + + 2. When you are docked, base covers you with an almost invincible shield. + (A commander can still ram you, or a Romulan can destroy the base, + or a SCom can even succeed with direct attack IIRC, but this rarely + happens.) (Now controlled by OPTION_BASE and turned off if game + type is "plain" or "almy".) + + 3. Ramming a black hole is no longer instant death. There is a + chance you might get timewarped instead. (Now controlled by + OPTION_BLKHOLE and turned off if game type is "plain" or "almy".) + + 4. The Tholian can be hit with phasers. + + 5. SCom can't escape from you if no more enemies remain + (without this, chasing SCom can take an eternity). + + 6. Probe target you enter is now the destination quadrant. Before I don't + remember what it was, but it was something I had difficulty using. + + 7. Secret password is now autogenerated. + + 8. "Plaque" is adjusted for A4 paper :-) + + 9. Phasers now tells you how much energy needed, but only if the computer + is alive. + + 10. Planets are auto-scanned when you enter the quadrant. + + 11. Mining or using crystals in presense of enemy now yields an attack. + There are other minor adjustments to what yields an attack + and what does not. + + 12. "freeze" command reverts to "save", most people will understand this + better anyway. (SST2K recognizes both.) + + 13. Screen-oriented interface, with sensor scans always up. (SST2K + supports both screen-oriented and TTY modes.) + +Eric Raymond's changes: + +Mainly, I translated this C code out of FORTRAN into C -- created #defines +for a lot of magic numbers and refactored the heck out of it. + + 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good. + + 2. Status report now indicates when dilithium crystals are on board. + + 3. Per Dave Matuszek's remarks, Thingy state is never saved across games. + + 4. Added game option selection so you can play a close (but not bug-for- + bug identical) approximation of older versions. + + 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). 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. + + 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 */ +static char line[128], *linep = line; + +struct game game; +coord thing; +bool iqhere, iqengry; +int iscore, iskill; // Common PLAQ +double aaitem; +double perdate; +char citem[12]; +int seed; // the random-number seed +bool idebug; // debug mode +FILE *logfp, *replayfp; + +char *systnames[NINHAB]; +char *device[NDEVICES]; + +static struct +{ + char *name; + int value; + unsigned long option; +} + +commands[] = { +#define SRSCAN 0 + {"SRSCAN", SRSCAN, OPTION_TTY}, +#define STATUS 1 + {"STATUS", STATUS, OPTION_TTY}, +#define REQUEST 2 + {"REQUEST", REQUEST, OPTION_TTY}, +#define LRSCAN 3 + {"LRSCAN", LRSCAN, OPTION_TTY}, +#define PHASERS 4 + {"PHASERS", PHASERS, 0}, +#define TORPEDO 5 + {"TORPEDO", TORPEDO, 0}, + {"PHOTONS", TORPEDO, 0}, +#define MOVE 7 + {"MOVE", MOVE, 0}, +#define SHIELDS 8 + {"SHIELDS", SHIELDS, 0}, +#define DOCK 9 + {"DOCK", DOCK, 0}, +#define DAMAGES 10 + {"DAMAGES", DAMAGES, 0}, +#define CHART 11 + {"CHART", CHART, 0}, +#define IMPULSE 12 + {"IMPULSE", IMPULSE, 0}, +#define REST 13 + {"REST", REST, 0}, +#define WARP 14 + {"WARP", WARP, 0}, +#define SCORE 15 + {"SCORE", SCORE, 0}, +#define SENSORS 16 + {"SENSORS", SENSORS, OPTION_PLANETS}, +#define ORBIT 17 + {"ORBIT", ORBIT, OPTION_PLANETS}, +#define TRANSPORT 18 + {"TRANSPORT", TRANSPORT, OPTION_PLANETS}, +#define MINE 19 + {"MINE", MINE, OPTION_PLANETS}, +#define CRYSTALS 20 + {"CRYSTALS", CRYSTALS, OPTION_PLANETS}, +#define SHUTTLE 21 + {"SHUTTLE", SHUTTLE, OPTION_PLANETS}, +#define PLANETS 22 + {"PLANETS", PLANETS, OPTION_PLANETS}, +#define REPORT 23 + {"REPORT", REPORT, 0}, +#define COMPUTER 24 + {"COMPUTER", COMPUTER, 0}, +#define COMMANDS 25 + {"COMMANDS", COMMANDS, 0}, +#define EMEXIT 26 + {"EMEXIT", EMEXIT, 0}, +#define PROBE 27 + {"PROBE", PROBE, OPTION_PROBE}, +#define SAVE 28 + {"SAVE", SAVE, 0}, + {"FREEZE", SAVE, 0}, +#define ABANDON 30 + {"ABANDON", ABANDON, 0}, +#define DESTRUCT 31 + {"DESTRUCT", DESTRUCT, 0}, +#define DEATHRAY 32 + {"DEATHRAY", DEATHRAY, 0}, +#define DEBUGCMD 33 + {"DEBUG", DEBUGCMD, 0}, +#define MAYDAY 34 + {"MAYDAY", MAYDAY, 0}, + //{"SOS", MAYDAY, 0}, + //{"CALL", MAYDAY, 0}, +#define QUIT 35 + {"QUIT", QUIT, 0}, +#define HELP 36 + {"HELP", HELP, 0}, +#define SEED 37 + {"SEED", SEED, 0}, +#ifdef BSD_BUG_FOR_BUG +#define VISUAL 38 + {"VISUAL", VISUAL, 0}, +#endif +}; + +#define NUMCOMMANDS ARRAY_SIZE(commands) +#define ACCEPT(i) (!commands[i].option || (commands[i].option & game.options)) + +static void listCommands(void) +/* generate a list of legal commands */ +{ + int i, k = 0; + proutn(_("LEGAL COMMANDS ARE:")); + for (i = 0; i < NUMCOMMANDS; i++) { + if (!ACCEPT(i)) + continue; + if (k % 5 == 0) + skip(1); + proutn("%-12s ", commands[i].name); + k++; + } + skip(1); +} + +static void helpme(void) +/* browse on-line help */ +{ + int i, j; + char cmdbuf[32], *cp; + char linebuf[132]; + FILE *fp; + /* Give help on commands */ + int key; + key = scan(); + for(;;) { + if (key == IHEOL) { + setwnd(prompt_window); + proutn(_("Help on what command? ")); + key = scan(); + } + setwnd(message_window); + if (key == IHEOL) + return; + for (i = 0; i < NUMCOMMANDS; i++) { + if (ACCEPT(i) && strcasecmp(commands[i].name, citem)==0) { + i = commands[i].value; + break; + } + } + if (i != NUMCOMMANDS) + break; + skip(1); + listCommands(); + key = IHEOL; + chew(); + skip(1); + } + if (i == COMMANDS) { + strcpy(cmdbuf, " ABBREV"); + } + else { + for (j = 0; commands[i].name[j]; j++) + cmdbuf[j] = toupper(commands[i].name[j]); + cmdbuf[j] = '\0'; + } + fp = fopen(SSTDOC, "r"); + if (fp == NULL) + fp = fopen(DOC_NAME, "r"); + if (fp == NULL) { + 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." + */ + return; + } + for (;;) { + if (fgets(linebuf, sizeof(linebuf), fp) == NULL) { + prout(_("Spock- \"Captain, there is no information on that command.\"")); + fclose(fp); + return; + } + if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') { + for (cp = linebuf+3; isspace(*cp); cp++) + continue; + linebuf[strlen(linebuf)-1] = '\0'; + if (strcasecmp(cp, cmdbuf) == 0) + break; + } + } + + skip(1); + prout(_("Spock- \"Captain, I've found the following information:\"")); + skip(1); + + while (fgets(linebuf, sizeof(linebuf), fp)) { + char *eol; + if (strstr(linebuf, "******")) + break; + if ((eol = strpbrk(linebuf, "\r\n"))) + *eol = 0; + prout(linebuf); + } + fclose(fp); +} + +static void makemoves(void) +/* command-interpretation loop */ +{ + int key, i, v = 0; + bool hitme; + clrscr(); + setwnd(message_window); + for(;;) { /* command loop */ + drawmaps(1); + for(;;) { /* get a command */ + hitme = false; + game.justin = false; + game.optime = 0.0; + i = -1; + chew(); + setwnd(prompt_window); + clrscr(); + proutn("COMMAND> "); + if (scan() == IHEOL) { + if (game.options & OPTION_CURSES) + makechart(); + continue; + } + game.ididit = false; + clrscr(); + setwnd(message_window); + clrscr(); + for (i=0; i < ABANDON; i++) + if (ACCEPT(i) && isit(commands[i].name)) { + v = commands[i].value; + break; + } + if (i < ABANDON && (!commands[i].option || (commands[i].option & game.options))) + break; + for (; i < NUMCOMMANDS; i++) + if (ACCEPT(i) && strcasecmp(commands[i].name, citem) == 0) { + v = commands[i].value; + break; + } + if (i < NUMCOMMANDS && (!commands[i].option || (commands[i].option & game.options))) + break; + listCommands(); + } + commandhook(commands[i].name, true); + switch (v) { /* command switch */ + case SRSCAN: // srscan + srscan(); + break; + case STATUS: // status + status(0); + break; + case REQUEST: // status request + request(); + break; + case LRSCAN: // lrscan + lrscan(); + break; + case PHASERS: // phasers + phasers(); + if (game.ididit) + hitme = true; + break; + case TORPEDO: // photon torpedoes + torps(); + if (game.ididit) + hitme = true; + break; + case MOVE: // move + warp(false); + break; + case SHIELDS: // shields + doshield(false); + if (game.ididit) { + hitme = true; + game.shldchg = false; + } + break; + case DOCK: // dock + dock(true); + if (game.ididit) + attack(false); + break; + case DAMAGES: // damages + damagereport(); + break; + case CHART: // chart + makechart(); + break; + case IMPULSE: // impulse + impulse(); + break; + case REST: // rest + wait(); + if (game.ididit) + hitme = true; + break; + case WARP: // warp + setwarp(); + break; + case SCORE: // score + score(); + break; + case SENSORS: // sensors + sensor(); + break; + case ORBIT: // orbit + orbit(); + if (game.ididit) + hitme = true; + break; + case TRANSPORT: // transport "beam" + beam(); + break; + case MINE: // mine + mine(); + if (game.ididit) + hitme = true; + break; + case CRYSTALS: // crystals + usecrystals(); + if (game.ididit) + hitme = true; + break; + case SHUTTLE: // shuttle + shuttle(); + if (game.ididit) + hitme = true; + break; + case PLANETS: // Planet list + survey(); + break; + case REPORT: // Game Report + report(); + break; + case COMPUTER: // use COMPUTER! + eta(); + break; + case COMMANDS: + listCommands(); + break; + case EMEXIT: // Emergency exit + clrscr(); // Hide screen + freeze(true); // forced save + exit(1); // And quick exit + break; + case PROBE: + probe(); // Launch probe + if (game.ididit) + hitme = true; + break; + case ABANDON: // Abandon Ship + abandon(); + break; + case DESTRUCT: // Self Destruct + selfdestruct(); + break; + case SAVE: // Save Game + 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; + break; + case DEBUGCMD: // What do we want for debug??? + debugme(); + break; + case MAYDAY: // Call for help + mayday(); + if (game.ididit) + hitme = true; + break; + case QUIT: + game.alldone = true; // quit the game + break; + case HELP: + helpme(); // get help + break; + case SEED: // set random-number seed + key = scan(); + if (key == IHREAL) + seed = (int)aaitem; + break; +#ifdef BSD_BUG_FOR_BUG + case VISUAL: + visual(); // perform visual scan + break; +#endif + } + commandhook(commands[i].name, false); + for (;;) { + if (game.alldone) + break; // Game has ended + if (game.optime != 0.0) { + events(); + if (game.alldone) + break; // Events did us in + } + if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) { // Galaxy went Nova! + atover(false); + continue; + } + if (hitme && !game.justin) { + attack(true); + if (game.alldone) + break; + if (game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova) { // went NOVA! + atover(false); + hitme = true; + continue; + } + } + break; + } + if (game.alldone) + break; + } + if (idebug) + prout("=== Ending"); +} + + +int main(int argc, char **argv) +{ + int i, option; + + game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY); + if (getenv("TERM")) + game.options |= OPTION_CURSES | OPTION_SHOWME; + else + game.options |= OPTION_TTY; + + 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] [-x] [startcommand...].\n"); + exit(0); + } + } + /* where to save the input in case of bugs */ + logfp = fopen("/usr/tmp/sst-input.log", "w"); + if (logfp) { + setlinebuf(logfp); + fprintf(logfp, "seed %d\n", seed); + } + srand(seed); + + iostart(); + + line[0] = '\0'; + for (i = optind; i < argc; i++) { + strcat(line, argv[i]); + strcat(line, " "); + } + for(;;) { /* Play a game */ + setwnd(fullscreen_window); + clrscr(); + prelim(); + setup(line[0] == '\0'); + if (game.alldone) { + score(); + game.alldone = false; + } + else + makemoves(); + skip(1); + stars(); + skip(1); + + if (game.tourn && game.alldone) { + proutn(_("Do you want your score recorded?")); + if (ja() == true) { + chew2(); + freeze(false); + } + } + 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.")); + return 0; +} + + +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 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 ")); + sprintf(buf+strlen(buf), "%d - %d", w.x, w.y); + return buf; +} + +void crmena(bool stars, feature enemy, enum loctype key, coord w) +/* print an enemy and his location */ +{ + if (stars) + proutn("***"); + cramen(enemy); + proutn(_(" at ")); + proutn(cramlc(key, w)); +} + +void crmshp(void) +/* print our ship name */ +{ + char *s; + switch (game.ship) { + case IHE: s = _("Enterprise"); break; + case IHF: s = _("Faerie Queene"); break; + default: s = "Ship???"; break; + } + proutn(s); +} + +void stars(void) +/* print a line of stars */ +{ + prouts("******************************************************"); + skip(1); +} + +double expran(double avrage) +{ + return -avrage*log(1e-7 + Rand()); +} + +double Rand(void) +{ + return rand()/(1.0 + (double)RAND_MAX); +} + +coord randplace(int size) +/* choose a random location */ +{ + coord w; + w.x = Rand()*(size*1.0) + 1.0; + w.y = Rand()*(size*1.0) + 1.0; + return w; +} + +void chew(void) +{ + linep = line; + *linep = 0; +} + +void chew2(void) +{ + /* return IHEOL next time */ + linep = line+1; + *linep = 0; +} + +int scan(void) +{ + int i; + char *cp; + + // Init result + aaitem = 0.0; + *citem = 0; + + // Read a line if nothing here + if (*linep == 0) { + if (linep != line) { + chew(); + return IHEOL; + } + cgetline(line, sizeof(line)); + fflush(stdin); + if (curwnd==prompt_window){ + clrscr(); + setwnd(message_window); + clrscr(); + } + linep = line; + } + // Skip leading white space + while (*linep == ' ') linep++; + // Nothing left + if (*linep == 0) { + chew(); + return IHEOL; + } + i = 0; + // try a number + if (sscanf(linep, "%lf%n", &aaitem, &i) > 0) { + // 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; +} + +bool ja(void) +/* yes-or-no confirmation */ +{ + chew(); + for(;;) { + scan(); + chew(); + if (*citem == 'y') + return true; + if (*citem == 'n') + return false; + proutn(_("Please answer with \"y\" or \"n\": ")); + } +} + +void huh(void) +/* complain about unparseable input */ +{ + chew(); + skip(1); + prout(_("Beg your pardon, Captain?")); +} + +bool isit(char *s) +/* compares s to citem and returns true if it matches to the length of s */ +{ + return strncasecmp(s, citem, max(1, strlen(citem))) == 0; +} + +void debugme(void) +/* access to the internals for debugging */ +{ + proutn("Reset levels? "); + 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() == 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() == true) { + idebug = !idebug; + if (idebug) + prout("Debug output ON"); + else + prout("Debug output OFF"); + } + proutn("Cause selective damage? "); + if (ja() == true) { + int i, key; + for (i=0; i < NDEVICES; i++) { + proutn("Kill "); + proutn(device[i]); + proutn("? "); + chew(); + key = scan(); + if (key == IHALPHA && isit("y")) { + game.damage[i] = 10.0; + } + } + } + proutn("Examine/change events? "); + if (ja() == true) { + event *ev; + coord w; + int i; + for (i = 1; i < NEVENTS; i++) { + int key; + 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; + case FDSPROB: proutn("Probe Move "); break; + case FDISTR: proutn("Distress Call "); break; + case FENSLV: proutn("Enlavement "); break; + case FREPRO: proutn("Klingon Build "); break; + } + 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(); + key = scan(); + 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() == true) { + game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = true; + atover(true); + } +}