Reorganize documentation of changes, Add some stuff from Tom Almy's web page.
[super-star-trek.git] / sst.c
1 #define INCLUDED        // Define externs here
2 #include <ctype.h>
3 #include <getopt.h>
4 #include <time.h>
5 #include "sstlinux.h"
6 #include "sst.h"
7
8 #ifndef SSTDOC
9 #define SSTDOC  "sst.doc"
10 #endif
11         
12 /*
13
14 Dave Matuszek says:
15
16    SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON,
17    LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE
18    were in the original non-"super" version of UT FORTRAN Star Trek.
19
20    Tholians weren't in the original. Dave is dubious about their merits.
21    (They are now controlled by OPTION_THOLIAN and turned off if the game
22    type is "plain".)
23
24    Planets and dilithium crystals weren't in the original.  Dave is OK
25    with this idea. (It's now controlled by OPTION_PLANETS and turned 
26    off if the game type is "plain".)
27
28    Dave says the bit about the Galileo getting turned into a
29    McDonald's is "consistant with our original vision".  (This has been
30    left permanently enabled, as it can only happen if OPTION_PLANETS
31    is on.)
32
33    Dave also says the Space Thingy should not be preserved across saved
34    games, so you can't prove to others that you've seen it.  He says it
35    shouldn't fire back, either.  It should do nothing except scream and
36    disappear when hit by photon torpedos.  It's OK that it may move
37    when attacked, but it didn't in the original.  (Whether the Thingy
38    can fire back is now controlled by OPTION_THINGY and turned off if the
39    game type is "plain" or "almy".  The no-save behavior has been restored.)
40
41    The Faerie Queen, black holes, and time warping were in the original.
42
43 Here are Tom Almy's changes:
44
45    In early 1997, I got the bright idea to look for references to
46    "Super Star Trek" on the World Wide Web. There weren't many hits,
47    but there was one that came up with 1979 Fortran sources! This
48    version had a few additional features that mine didn't have,
49    however mine had some feature it didn't have. So I merged its
50    features that I liked. I also took a peek at the DECUS version (a
51    port, less sources, to the PDP-10), and some other variations.
52
53    1, Compared to the original UT version, I've changed the "help" command to
54       "call" and the "terminate" command to "quit" to better match
55       user expectations. The DECUS version apparently made those changes
56       as well as changing "freeze" to "save". However I like "freeze".
57       (Both "freeze" and "save" work in SST2K.)
58
59    2. The experimental deathray originally had only a 5% chance of
60       success, but could be used repeatedly. I guess after a couple
61       years of use, it was less "experimental" because the 1979
62       version had a 70% success rate. However it was prone to breaking
63       after use. I upgraded the deathray, but kept the original set of
64       failure modes (great humor!).  (Now controlled by OPTION_DEATHRAY
65       and turned off if game type is "plain".)
66
67    3. The 1979 version also mentions srscan and lrscan working when
68       docked (using the starbase's scanners), so I made some changes here
69       to do this (and indicating that fact to the player), and then realized
70       the base would have a subspace radio as well -- doing a Chart when docked
71       updates the star chart, and all radio reports will be heard. The Dock
72       command will also give a report if a base is under attack.
73
74    4. Tholian Web from the 1979 version.  (Now controlled by
75       OPTION_THOLIAN and turned off if game type is "plain".)
76
77    5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING
78       and turned off if game type is "plain".)
79
80    6. Regular Klingons and Romulans can move in Expert and Emeritus games. 
81       This code could use improvement. (Now controlled by OPTION_MVBADDY
82       and turned off if game type is "plain".)
83
84    7. The deep-space probe feature from the DECUS version.  (Now controlled
85       by OPTION_PROBE and turned off if game type is "plain").
86
87    8. 'emexit' command from the 1979 version.
88
89    9. Bugfix: Klingon commander movements are no longer reported if long-range 
90       sensors are damaged.
91
92    10. Bugfix: Better base positioning at startup (more spread out).
93       That made sense to add because most people abort games with 
94       bad base placement.
95
96    In June 2002, I fixed two known bugs and a documentation typo.
97    In June 2004 I fixed a number of bugs involving: 1) parsing invalid
98    numbers, 2) manual phasers when SR scan is damaged and commander is
99    present, 3) time warping into the future, 4) hang when moving
100    klingons in crowded quadrants.  (These fixes are in SST2K.)
101
102 Here are Stas Sergeev's changes:
103
104    1. The Space Thingy can be shoved, if you ram it, and can fire back if 
105       fired upon. (Now controlled by OPTION_THINGY and turned off if game 
106       type is "plain" or "almy".)
107
108    2. When you are docked, base covers you with an almost invincible shield. 
109       (A commander can still ram you, or a Romulan can destroy the base,
110       or a SCom can even succeed with direct attack IIRC, but this rarely 
111       happens.)  (Now controlled by OPTION_BASE and turned off if game 
112       type is "plain" or "almy".)
113
114    3. Ramming a black hole is no longer instant death.  There is a
115       chance you might get timewarped instead. (Now controlled by 
116       OPTION_BLKHOLE and turned off if game type is "plain" or "almy".)
117
118    4. The Tholian can be hit with phasers.
119
120    5. SCom can't escape from you if no more enemies remain 
121       (without this, chasing SCom can take an eternity).
122
123    6. Probe target you enter is now the destination quadrant. Before I don't 
124       remember what it was, but it was something I had difficulty using.
125
126    7. Secret password is now autogenerated.
127
128    8. "Plaque" is adjusted for A4 paper :-)
129
130    9. Phasers now tells you how much energy needed, but only if the computer 
131       is alive.
132
133    10. Planets are auto-scanned when you enter the quadrant.
134
135    11. Mining or using crystals in presense of enemy now yields an attack.
136        There are other minor adjustments to what yields an attack
137        and what does not.
138
139    12. "freeze" command reverts to "save", most people will understand this
140        better anyway. (SST2K recognizes both.)
141
142    13. Screen-oriented interface, with sensor scans always up.  (SST2K
143        supports both screen-oriented and TTY modes.)
144
145 Eric Raymond's changes:
146
147 Mainly, I translated this C code out of FORTRAN into C -- created #defines
148 for a lot of magic numbers and refactored the heck out of it.
149
150    1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
151
152    2. Status report now indicates when dilithium crystals are on board.
153
154    3. Per Dave Matuszek's remarks, Thingy state is never saved across games.
155
156    4. Added game option selection so you can play a close (but not bug-for-
157       bug identical) approximation of older versions.
158 */
159
160 /* the input queue */
161 static char line[128], *linep = line;
162
163 static struct 
164 {
165     char *name;
166     int value;
167     unsigned long option;
168 }
169 commands[] = {
170 #define SRSCAN  0
171         {"SRSCAN",      SRSCAN,         OPTION_TTY},
172 #define STATUS  1
173         {"STATUS",      STATUS,         OPTION_TTY},
174 #define REQUEST 2
175         {"REQUEST",     REQUEST,        OPTION_TTY},
176 #define LRSCAN  3
177         {"LRSCAN",      LRSCAN,         OPTION_TTY},
178 #define PHASERS 4
179         {"PHASERS",     PHASERS,        0},
180 #define TORPEDO 5
181         {"TORPEDO",     TORPEDO,        0},
182         {"PHOTONS",     TORPEDO,        0},
183 #define MOVE    6
184         {"MOVE",        MOVE,           0},
185 #define SHIELDS 7
186         {"SHIELDS",     SHIELDS,        0},
187 #define DOCK    8
188         {"DOCK",        DOCK,           0},
189 #define DAMAGES 9
190         {"DAMAGES",     DAMAGES,        0},
191 #define CHART   10
192         {"CHART",       CHART,          0},
193 #define IMPULSE 11
194         {"IMPULSE",     IMPULSE,        0},
195 #define REST    12
196         {"REST",        REST,           0},
197 #define WARP    13
198         {"WARP",        WARP,           0},
199 #define SCORE   14
200         {"SCORE",       SCORE,          0},
201 #define SENSORS 15
202         {"SENSORS",     SENSORS,        OPTION_PLANETS},
203 #define ORBIT   16
204         {"ORBIT",       ORBIT,          OPTION_PLANETS},
205 #define TRANSPORT       17
206         {"TRANSPORT",   TRANSPORT,      OPTION_PLANETS},
207 #define MINE    18
208         {"MINE",        MINE,           OPTION_PLANETS},
209 #define CRYSTALS        19
210         {"CRYSTALS",    CRYSTALS,       OPTION_PLANETS},
211 #define SHUTTLE 20
212         {"SHUTTLE",     SHUTTLE,        OPTION_PLANETS},
213 #define PLANETS 21
214         {"PLANETS",     PLANETS,        OPTION_PLANETS},
215 #define REPORT  22
216         {"REPORT",      REPORT,         0},
217 #define COMPUTER        23
218         {"COMPUTER",    COMPUTER,       0},
219 #define COMMANDS        24
220         {"COMMANDS",    COMMANDS,       0},
221 #define EMEXIT  25
222         {"EMEXIT",      EMEXIT,         0},
223 #define PROBE   26
224         {"PROBE",       PROBE,          OPTION_PROBE},
225 #define SAVE    27
226         {"SAVE",        SAVE,           0},
227         {"FREEZE",      SAVE,           0},
228 #define ABANDON 28
229         {"ABANDON",     ABANDON,        0},
230 #define DESTRUCT        29
231         {"DESTRUCT",    DESTRUCT,       0},
232 #define DEATHRAY        30
233         {"DEATHRAY",    DEATHRAY,       0},
234 #define DEBUGCMD        31
235         {"DEBUG",       DEBUGCMD,       0},
236 #define MAYDAY  32
237         {"MAYDAY",      MAYDAY,         0},
238         //{"SOS",               MAYDAY,         0},
239         //{"CALL",      MAYDAY,         0},
240 #define QUIT    33
241         {"QUIT",        QUIT,           0},
242 #define HELP    34
243         {"HELP",        HELP,           0},
244 };
245
246 #define NUMCOMMANDS     sizeof(commands)/sizeof(commands[0])
247 #define ACCEPT(i)       (!commands[i].option || (commands[i].option & game.options))
248
249 static void listCommands(void) {
250     int i, k = 0;
251     proutn("LEGAL COMMANDS ARE:");
252     for (i = 0; i < NUMCOMMANDS; i++) {
253         if (!ACCEPT(i))
254             continue;
255         if (k % 5 == 0)
256             skip(1);
257         proutn("%-12s ", commands[i].name); 
258         k++;
259     }
260     skip(1);
261 }
262
263 static void helpme(void) 
264 {
265     int i, j;
266     char cmdbuf[32], *cp;
267     char linebuf[132];
268     FILE *fp;
269     /* Give help on commands */
270     int key;
271     key = scan();
272     while (TRUE) {
273         if (key == IHEOL) {
274             setwnd(prompt_window);
275             proutn("Help on what command? ");
276             key = scan();
277         }
278         setwnd(message_window);
279         if (key == IHEOL) return;
280         for (i = 0; i < NUMCOMMANDS; i++) {
281             if (ACCEPT(i) && strcasecmp(commands[i].name, citem)==0) {
282                 i = commands[i].value;
283                 break;
284             }
285         }
286         if (i != NUMCOMMANDS) break;
287         skip(1);
288         prout("Valid commands:");
289         listCommands();
290         key = IHEOL;
291         chew();
292         skip(1);
293     }
294     if (i == COMMANDS) {
295         strcpy(cmdbuf, " ABBREV");
296     }
297     else {
298         for (j = 0; commands[i].name[j]; j++)
299             cmdbuf[j] = toupper(commands[i].name[j]);
300         cmdbuf[j] = '\0';
301     }
302     fp = fopen(SSTDOC, "r");
303     if (fp == NULL) {
304         prout("Spock-  \"Captain, that information is missing from the");
305         prout("   computer.\"");
306         /*
307          * This used to continue: "You need to find SST.DOC and put 
308          * it in the current directory."
309          */
310         return;
311     }
312     for (;;) {
313         if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
314             prout("Spock- \"Captain, there is no information on that command.\"");
315             fclose(fp);
316             return;
317         }
318         if (linebuf[0] == '%' && linebuf[1] == '%'&& linebuf[2] == ' ') {
319             for (cp = linebuf+3; isspace(*cp); cp++)
320                 continue;
321             linebuf[strlen(linebuf)-1] = '\0';
322             if (strcasecmp(cp, cmdbuf) == 0)
323                 break;
324         }
325     }
326
327     skip(1);
328     prout("Spock- \"Captain, I've found the following information:\"");
329     skip(1);
330
331     while (fgets(linebuf, sizeof(linebuf),fp)) {
332         if (strstr(linebuf, "******"))
333             break;
334         proutn(linebuf);
335     }
336     fclose(fp);
337 }
338
339 void enqueue(char *s) 
340 {
341     strcpy(line, s);
342 }
343
344 static void makemoves(void) 
345 {
346     int i, v = 0, hitme;
347     clrscr();
348     setwnd(message_window);
349     while (TRUE) { /* command loop */
350         drawmaps(1);
351         while (TRUE)  { /* get a command */
352             hitme = FALSE;
353             justin = 0;
354             Time = 0.0;
355             i = -1;
356             chew();
357             setwnd(prompt_window);
358             clrscr();
359             proutn("COMMAND> ");
360             if (scan() == IHEOL) {
361                 makechart();
362                 continue;
363             }
364             ididit=0;
365             clrscr();
366             setwnd(message_window);
367             clrscr();
368             for (i=0; i < ABANDON; i++)
369                 if (ACCEPT(i) && isit(commands[i].name)) {
370                     v = commands[i].value;
371                     break;
372                 }
373             if (i < ABANDON && (!commands[i].option || (commands[i].option & game.options))) 
374                 break;
375             for (; i < NUMCOMMANDS; i++)
376                 if (ACCEPT(i) && strcasecmp(commands[i].name, citem) == 0) {
377                     v = commands[i].value;
378                     break;
379                 }
380             if (i < NUMCOMMANDS && (!commands[i].option || (commands[i].option & game.options))) 
381                 break;
382             listCommands();
383         }
384         commandhook(commands[i].name, TRUE);
385         switch (v) { /* command switch */
386         case SRSCAN:                 // srscan
387             srscan(SCAN_FULL);
388             break;
389         case STATUS:                 // status
390             srscan(SCAN_STATUS);
391             break;
392         case REQUEST:                   // status request 
393             srscan(SCAN_REQUEST);
394             break;
395         case LRSCAN:                    // lrscan
396             lrscan();
397             break;
398         case PHASERS:                   // phasers
399             phasers();
400             if (ididit) hitme = TRUE;
401             break;
402         case TORPEDO:                   // photons
403             photon();
404             if (ididit) hitme = TRUE;
405             break;
406         case MOVE:                      // move
407             warp(1);
408             break;
409         case SHIELDS:                   // shields
410             doshield(1);
411             if (ididit) {
412                 hitme=TRUE;
413                 shldchg = 0;
414             }
415             break;
416         case DOCK:                      // dock
417             dock(1);
418             if (ididit) attack(0);
419             break;
420         case DAMAGES:                   // damages
421             dreprt();
422             break;
423         case CHART:                     // chart
424             chart(0);
425             break;
426         case IMPULSE:                   // impulse
427             impuls();
428             break;
429         case REST:                      // rest
430             wait();
431             if (ididit) hitme = TRUE;
432             break;
433         case WARP:                      // warp
434             setwrp();
435             break;
436         case SCORE:                     // score
437             score();
438             break;
439         case SENSORS:                   // sensors
440             sensor();
441             break;
442         case ORBIT:                     // orbit
443             orbit();
444             if (ididit) hitme = TRUE;
445             break;
446         case TRANSPORT:                 // transport "beam"
447             beam();
448             break;
449         case MINE:                      // mine
450             mine();
451             if (ididit) hitme = TRUE;
452             break;
453         case CRYSTALS:                  // crystals
454             usecrystals();
455             if (ididit) hitme = TRUE;
456             break;
457         case SHUTTLE:                   // shuttle
458             shuttle();
459             if (ididit) hitme = TRUE;
460             break;
461         case PLANETS:                   // Planet list
462             preport();
463             break;
464         case REPORT:                    // Game Report 
465             report();
466             break;
467         case COMPUTER:                  // use COMPUTER!
468             eta();
469             break;
470         case COMMANDS:
471             listCommands();
472             break;
473         case EMEXIT:                    // Emergency exit
474             clrscr();                   // Hide screen
475             freeze(TRUE);               // forced save
476             exit(1);                    // And quick exit
477             break;
478         case PROBE:
479             probe();                    // Launch probe
480             if (ididit) hitme = TRUE;
481             break;
482         case ABANDON:                   // Abandon Ship
483             abandn();
484             break;
485         case DESTRUCT:                  // Self Destruct
486             dstrct();
487             break;
488         case SAVE:                      // Save Game
489             freeze(FALSE);
490             clrscr();
491             if (skill > SKILL_GOOD)
492                 prout("WARNING--Saved games produce no plaques!");
493             break;
494         case DEATHRAY:                  // Try a desparation measure
495             deathray();
496             if (ididit) hitme = TRUE;
497             break;
498         case DEBUGCMD:                  // What do we want for debug???
499 #ifdef DEBUG
500             debugme();
501 #endif
502             break;
503         case MAYDAY:                    // Call for help
504             help();
505             if (ididit) hitme = TRUE;
506             break;
507         case QUIT:
508             alldone = 1;                // quit the game
509 #ifdef DEBUG
510             if (idebug) score();
511 #endif
512             break;
513         case HELP:
514             helpme();   // get help
515             break;
516         }
517         commandhook(commands[i].name, FALSE);
518         for (;;) {
519             if (alldone) break;         // Game has ended
520 #ifdef DEBUG
521             if (idebug) prout("2500");
522 #endif
523             if (Time != 0.0) {
524                 events();
525                 if (alldone) break;     // Events did us in
526             }
527             if (game.state.galaxy[quadx][quady].supernova) { // Galaxy went Nova!
528                 atover(0);
529                 continue;
530             }
531             if (hitme && justin==0) {
532                 attack(2);
533                 if (alldone) break;
534                 if (game.state.galaxy[quadx][quady].supernova) {        // went NOVA! 
535                     atover(0);
536                     hitme = TRUE;
537                     continue;
538                 }
539             }
540             break;
541         }
542         if (alldone) break;
543     }
544 }
545
546
547 int main(int argc, char **argv) 
548 {
549     int i, option;
550
551     game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY);
552     if (getenv("TERM"))
553         game.options |= OPTION_CURSES | OPTION_SHOWME;
554     else
555         game.options |= OPTION_TTY;
556
557     while ((option = getopt(argc, argv, "t")) != -1) {
558         switch (option) {
559         case 't':
560             game.options |= OPTION_TTY;
561             game.options &=~ OPTION_CURSES;
562             break;
563         default:
564             fprintf(stderr, "usage: sst [-t] [startcommand...].\n");
565             exit(0);
566         }
567     }
568
569     randomize();
570     iostart();
571
572     line[0] = '\0';
573     for (i = optind; i < argc;  i++) {
574         strcat(line, argv[i]);
575         strcat(line, " ");
576     }
577     while (TRUE) { /* Play a game */
578         setwnd(fullscreen_window);
579 #ifdef DEBUG
580         prout("INITIAL OPTIONS: %0lx", game.options);
581 #endif /* DEBUG */
582         clrscr();
583         prelim();
584         setup(line[0] == '\0');
585         if (alldone) {
586             score();
587             alldone = 0;
588         }
589         else makemoves();
590         skip(1);
591         stars();
592         skip(1);
593
594         if (tourn && alldone) {
595             proutn("Do you want your score recorded?");
596             if (ja()) {
597                 chew2();
598                 freeze(FALSE);
599             }
600         }
601         proutn("Do you want to play again? ");
602         if (!ja()) break;
603     }
604     skip(1);
605     prout("May the Great Bird of the Galaxy roost upon your home planet.");
606     return 0;
607 }
608
609
610 void cramen(int i) 
611 {
612     /* return an enemy */
613     char *s;
614         
615     switch (i) {
616     case IHR: s = "Romulan"; break;
617     case IHK: s = "Klingon"; break;
618     case IHC: s = "Commander"; break;
619     case IHS: s = "Super-commander"; break;
620     case IHSTAR: s = "Star"; break;
621     case IHP: s = "Planet"; break;
622     case IHB: s = "Starbase"; break;
623     case IHBLANK: s = "Black hole"; break;
624     case IHT: s = "Tholian"; break;
625     case IHWEB: s = "Tholian web"; break;
626     case IHQUEST: s = "Stranger"; break;
627     default: s = "Unknown??"; break;
628     }
629     proutn(s);
630 }
631
632 char *cramlc(enum loctype key, int x, int y)
633 {
634     static char buf[32];
635     buf[0] = '\0';
636     if (key == quadrant) strcpy(buf, "Quadrant ");
637     else if (key == sector) strcpy(buf, "Sector ");
638     sprintf(buf+strlen(buf), "%d - %d", x, y);
639     return buf;
640 }
641
642 void crmena(int i, int enemy, int key, int x, int y) 
643 {
644     if (i == 1) proutn("***");
645     cramen(enemy);
646     proutn(" at ");
647     proutn(cramlc(key, x, y));
648 }
649
650 void crmshp(void) 
651 {
652     char *s;
653     switch (ship) {
654     case IHE: s = "Enterprise"; break;
655     case IHF: s = "Faerie Queene"; break;
656     default:  s = "Ship???"; break;
657     }
658     proutn(s);
659 }
660
661 void stars(void) 
662 {
663     prouts("******************************************************");
664     skip(1);
665 }
666
667 double expran(double avrage) 
668 {
669     return -avrage*log(1e-7 + Rand());
670 }
671
672 double Rand(void) {
673         return rand()/(1.0 + (double)RAND_MAX);
674 }
675
676 void iran(int size, int *i, int *j) 
677 {
678     *i = Rand()*(size*1.0) + 1.0;
679     *j = Rand()*(size*1.0) + 1.0;
680 }
681
682 void chew(void)
683 {
684     linep = line;
685     *linep = 0;
686 }
687
688 void chew2(void) 
689 {
690     /* return IHEOL next time */
691     linep = line+1;
692     *linep = 0;
693 }
694
695 int scan(void) 
696 {
697     int i;
698     char *cp;
699
700     // Init result
701     aaitem = 0.0;
702     *citem = 0;
703
704     // Read a line if nothing here
705     if (*linep == 0) {
706         if (linep != line) {
707             chew();
708             return IHEOL;
709         }
710         cgetline(line, sizeof(line));
711         fflush(stdin);
712         if (curwnd==prompt_window){
713             clrscr();
714             setwnd(message_window);
715             clrscr();
716         }
717         linep = line;
718     }
719     // Skip leading white space
720     while (*linep == ' ') linep++;
721     // Nothing left
722     if (*linep == 0) {
723         chew();
724         return IHEOL;
725     }
726     if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
727         // treat as a number
728         i = 0;
729         if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
730             linep = line; // Invalid numbers are ignored
731             *linep = 0;
732             return IHEOL;
733         }
734         else {
735             // skip to end
736             linep += i;
737             return IHREAL;
738         }
739     }
740     // Treat as alpha
741     cp = citem;
742     while (*linep && *linep!=' ') {
743         if ((cp - citem) < 9) *cp++ = tolower(*linep);
744         linep++;
745     }
746     *cp = 0;
747     return IHALPHA;
748 }
749
750 int ja(void) 
751 {
752     chew();
753     while (TRUE) {
754         scan();
755         chew();
756         if (*citem == 'y') return TRUE;
757         if (*citem == 'n') return FALSE;
758         proutn("Please answer with \"Y\" or \"N\": ");
759     }
760 }
761
762 void huh(void) 
763 {
764     chew();
765     skip(1);
766     prout("Beg your pardon, Captain?");
767 }
768
769 int isit(char *s) 
770 {
771     /* New function -- compares s to scanned citem and returns true if it
772        matches to the length of s */
773
774     return strncasecmp(s, citem, max(1, strlen(citem))) == 0;
775
776 }
777
778 #ifdef DEBUG
779 void debugme(void) 
780 {
781     proutn("Reset levels? ");
782     if (ja() != 0) {
783         if (energy < inenrg) energy = inenrg;
784         shield = inshld;
785         torps = intorps;
786         lsupres = inlsr;
787     }
788     proutn("Reset damage? ");
789     if (ja() != 0) {
790         int i;
791         for (i=0; i < NDEVICES; i++) 
792             if (game.damage[i] > 0.0) 
793                 game.damage[i] = 0.0;
794     }
795     proutn("Toggle idebug? ");
796     if (ja() != 0) {
797         idebug = !idebug;
798         if (idebug) prout("Debug output ON");
799         else prout("Debug output OFF");
800     }
801     proutn("Cause selective damage? ");
802     if (ja() != 0) {
803         int i, key;
804         for (i=0; i < NDEVICES; i++) {
805             proutn("Kill ");
806             proutn(device[i]);
807             proutn("? ");
808             chew();
809             key = scan();
810             if (key == IHALPHA &&  isit("y")) {
811                 game.damage[i] = 10.0;
812             }
813         }
814     }
815     proutn("Examine/change events? ");
816     if (ja() != 0) {
817         int i;
818         for (i = 1; i < NEVENTS; i++) {
819             int key;
820             if (game.future[i] == FOREVER) continue;
821             switch (i) {
822             case FSNOVA:  proutn("Supernova       "); break;
823             case FTBEAM:  proutn("T Beam          "); break;
824             case FSNAP:   proutn("Snapshot        "); break;
825             case FBATTAK: proutn("Base Attack     "); break;
826             case FCDBAS:  proutn("Base Destroy    "); break;
827             case FSCMOVE: proutn("SC Move         "); break;
828             case FSCDBAS: proutn("SC Base Destroy "); break;
829             }
830             proutn("%.2f", game.future[i]-game.state.date);
831             chew();
832             proutn("  ?");
833             key = scan();
834             if (key == IHREAL) {
835                 game.future[i] = game.state.date + aaitem;
836             }
837         }
838         chew();
839     }
840     proutn("Induce supernova here? ");
841     if (ja() != 0) {
842         game.state.galaxy[quadx][quady].supernova = TRUE;
843         atover(1);
844     }
845 }
846 #endif