0,0 → 1,818 |
|
#include <ctype.h> |
#ifdef MSDOS |
#include <dos.h> |
#endif |
|
#ifndef KOS32 |
#include <time.h> |
#else |
#include <conio.h> |
#include <kos32sys1.h> |
#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?"); |
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:"); |
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.\""); |
return; |
} |
i = strlen(cmdbuf); |
do { |
if (fgets(linebuf, 132, fp) == NULL) { |
prout("Spock- \"Captain, there is no information on that command.\""); |
fclose(fp); |
return; |
} |
} while (strncmp(linebuf, cmdbuf, i) != 0); |
|
skip(1); |
prout("Spock- \"Captain, I've found the following information:\""); |
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:"); |
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!"); |
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!"); |
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!"); |
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 |
|
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?"); |
if (ja()) { |
chew2(); |
freeze(FALSE); |
} |
} |
printf("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(int i) { |
/* 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 = "Tholean"; break; |
case IHWEB: s = "Tholean web"; break; |
default: s = "Unknown??"; break; |
} |
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 = "Enterprise"; break; |
case IHF: s = "Faerie Queene"; break; |
default: s = "Ship???"; break; |
} |
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(); |
#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\":"); |
} |
} |
|
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]"); |
getchar(); |
} |
else { |
if (skill > SFAIR) |
proutn("[CONTINUE?]"); |
else |
proutn("[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?"); |
} |
|
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 |