866 lines
33 KiB
Markdown
866 lines
33 KiB
Markdown
---
|
||
created_at: '2014-04-08T23:41:03.000Z'
|
||
title: Star Trek 1971 Text Game (2008)
|
||
url: http://www.codeproject.com/Articles/28228/Star-Trek-Text-Game
|
||
author: deanmen
|
||
points: 93
|
||
story_text: ''
|
||
comment_text:
|
||
num_comments: 34
|
||
story_id:
|
||
story_title:
|
||
story_url:
|
||
parent_id:
|
||
created_at_i: 1397000463
|
||
_tags:
|
||
- story
|
||
- author_deanmen
|
||
- story_7556773
|
||
objectID: '7556773'
|
||
year: 2008
|
||
|
||
---
|
||
## A Bit of History
|
||
|
||
Two years after the original series was canceled in 1969, high school
|
||
senior Mike Mayfield was busy keeping the Star Trek universe alive by
|
||
feeding punched paper tape into a Sigma 7 in an effort to bring the crew
|
||
of the Enterprise and the Klingon Empire to life on a 10
|
||
character-per-second teletype terminal. Soon after Mike ported his game
|
||
to HP BASIC, it entered the public domain. From there, early computer
|
||
enthusiasts enhanced and rewrote the game for every flavor of mini and
|
||
microcomputer BASIC imaginable and beyond.
|
||
|
||
I remember encountering versions of the game back in the early 80s when
|
||
I was a little kid trying to learn BASIC on my IBM PCjr. Back then,
|
||
computer books and magazines distributed programs in printed form.
|
||
Meaning, you had to type them in to play the games. It was a pain in the
|
||
ass, but the process encouraged you to tinker. It motivated you to learn
|
||
to code and to tweak or even improve the programs you were entering in.
|
||
|
||
Every BASIC game book that I picked up contained some version of the
|
||
Star Trek game. I recall loading it up a few times, but each time I
|
||
ended up staring at the screen in utter confusion. "How the heck is this
|
||
Star Trek?" I remember thinking. I couldn’t figure out how to play it.
|
||
|
||
By the time I entered high school, I had graduated from BASIC and moved
|
||
onto to bigger and better things like C and C++. But, on occasion, I
|
||
often wondered about the Star Trek text game. What made it so popular?
|
||
After learning about the history that I touched upon above, I decided to
|
||
dig it up and take a second look.
|
||
|
||
After a bit of web surfing, I came across Mike Mayfield’s original port
|
||
to HP BASIC. Here’s a snippet of the
|
||
code:
|
||
|
||
100 REM *****************************************************************
|
||
110 REM *** ***
|
||
120 REM *** STAR TREK: BY MIKE MAYFIELD, CENTERLINE ENGINEERING ***
|
||
130 REM *** ***
|
||
140 REM *** TOTAL INTERACTION GAME - ORIG. 20 OCT 1972
|
||
150 REM *** ***
|
||
160 REM *****************************************************************
|
||
170 GOSUB 5460
|
||
180 PRINT " STAR TREK "
|
||
190 PRINT "DO YOU WANT INSTRUCTIONS (THEY'RE LONG!)";
|
||
200 INPUT A$
|
||
210 IF A$ <> "YES" THEN 230
|
||
220 GOSUB 5820
|
||
230 REM ***** PROGRAM STARTS HERE *****
|
||
|
||
Ah, good old line-numbered BASIC. It’s all coming back to me now. Those
|
||
line numbers were there to provide targets for GOTO and GOSUB
|
||
statements. But, line numbers made editing a tad difficult. It was
|
||
convention to enter in line numbers that were multiples of 10. That way,
|
||
as you developed the program, you could go back and insert up to 9
|
||
additional statements in between existing lines without reworking all
|
||
the GOTO/GOSUB references. If you needed to insert more than 9 lines, I
|
||
remember a special feature in the BASIC editor on my PCjr. It would
|
||
append a zero to all line numbers and all line number references
|
||
throughout the program. Meaning, you could now insert up to 99 lines.
|
||
Couldn’t they just renumber the program in multiples of 10? Nah. The
|
||
PCjr wasn’t powerful enough for that.
|
||
|
||
If you’re wondering about “Centerline Engineering,” it was an imaginary
|
||
company that Mike Mayfield coined to give his BASIC projects a level of
|
||
prominence to those reading the remarks section.
|
||
|
||
With code in hand, I really wanted to play the game. I’m sure that there
|
||
are HP BASIC interpreters out there for modern machines, but what fun
|
||
would that be. Before I played it, I wanted do my own port. This game
|
||
was born in the hobbyist era. It was made to be reinterpreted and
|
||
enhanced as it traded handed. I wanted to bring back part of those
|
||
long-lost magical days of type-in programs.
|
||
|
||
My first impression of the code was "what’s with all the single letter
|
||
variable names?" First I thought it was a limitation of HP BASIC, but
|
||
then I noticed the occasional 2-letter names. I guess 2 is better than
|
||
1. Everything is also in caps. Take a look at this line:
|
||
|
||
2140 T=T+1
|
||
|
||
That line increments T. But, due to the caps, I feel like the code is
|
||
screaming at me. ASIGN THE SUM OF T AND 1 BACK TO T DAMN IT\! Also, I’m
|
||
so used to writing `t++` or `t += x` that I forgot about the expanded
|
||
notation. In fact, entering 7th grade having mastered BASIC, I found
|
||
myself really confused when my math teacher introduced us to solving
|
||
simultaneous equations. For instance, find the value of X in this
|
||
equation:
|
||
|
||
X = 2X - 6
|
||
|
||
That was the first time I was introduced to the concept of operator
|
||
overloading. The equals-sign can mean variable assignment or numerical
|
||
equivalence depending on the context.
|
||
|
||
Here’s a cool block of code that I noticed:
|
||
|
||
4550 IMAGE 8(X,3A)
|
||
4560 IMAGE 8(X,3A),8X,"STARDATE",8X,5D
|
||
4570 IMAGE 8(X,3A),8X,"CONDITION",8X,6A
|
||
4580 IMAGE 8(X,3A),8X,"QUADRANT",9X,D,",",D
|
||
4590 IMAGE 8(X,3A),8X,"SECTOR",11X,D,",",D
|
||
4600 IMAGE 8(X,3A),8X,"ENERGY",9X,6D
|
||
4610 IMAGE 8(X,3A),8X,"PHOTON TORPEDOES",3D
|
||
4620 IMAGE 8(X,3A),8X,"SHIELDS",8X,6D
|
||
|
||
These are not executable statements. They’re strings that can be
|
||
referenced in PRINT commands. The unquoted symbols get substituted with
|
||
values of variables. It’s conceptually similar to C-style `printf()`
|
||
format placeholders. I didn’t realize that BASIC offered such a rich
|
||
numerical formatting notation.
|
||
|
||
As I continued to examine the source, I found some statements that
|
||
didn’t make sense. For instance, even though you don’t have to declare
|
||
variables before you use them, you still need to specify the dimensions
|
||
of arrays. I came across some arrays that were never allocated as such.
|
||
Ultimately, I decided to seek out a better basis for my port.
|
||
|
||
After a bit of Googling, I found a cleaned up version that maintained
|
||
the majority of Mike Mayfield’s code. Some of it was reworked, probably
|
||
to enable it to run on modern versions of BASIC. For instance, those
|
||
cool IMAGE statements were dropped and replaced with sets of simpler
|
||
PRINT commands. The variable names appear virtually identical, but at
|
||
least they are all accounted for in this version.
|
||
|
||
## Porting the Game
|
||
|
||
Next, I had to decide what language to port it to. Staring at that BASIC
|
||
code reminded me that C\# brought `goto` back into the mainstream. Would
|
||
it be possible to do an exact line-by-line port from BASIC to C\#?
|
||
Apparently so... and the result is some of the sickest code I’ve ever
|
||
keyed into a computer. Want a comparison? Here’s a segment of BASIC
|
||
code:
|
||
|
||
2950 PRINT "TORPEDO TRACK:"
|
||
2960 LET X=X+X[1]
|
||
2970 LET Y=Y+X[2]
|
||
2980 IF X<.5 OR X >= 8.5 OR Y<.5 OR Y >= 8.5 THEN 3420
|
||
2990 LET V[4]=X
|
||
2991 LET V[5]=Y
|
||
2992 GOSUB 9000
|
||
2993 PRINT
|
||
3020 IF A[INT(X+.5),INT(Y+.5)]#0 THEN 3080
|
||
3060 GOTO 2960
|
||
3080 IF A[INT(X+.5),INT(Y+.5)]#2 THEN 3230
|
||
3120 PRINT "*** KLINGON DESTROYED ***"
|
||
3130 LET P[1]=P[1]-1
|
||
3140 LET P[3]=P[3]-1
|
||
3150 IF P[3] <= 0 THEN 4040
|
||
3160 FOR I=1 TO 3
|
||
3170 IF INT(X+.5)#K[I,1] THEN 3190
|
||
3180 IF INT(Y+.5)=K[I,2] THEN 3200
|
||
3190 NEXT I
|
||
3200 LET K[I,3]=0
|
||
3210 GOTO 3370
|
||
3230 IF A[INT(X+.5),INT(Y+.5)]#4 THEN 3290
|
||
3270 PRINT "YOU CAN'T DESTROY STARS SILLY"
|
||
3280 GOTO 3420
|
||
|
||
And the C\# version:
|
||
|
||
``` cs
|
||
_2950: Console.WriteLine("TORPEDO TRACK:");
|
||
_2960: X = X + _X[1];
|
||
_2970: Y = Y + _X[2];
|
||
_2980: if (X < .5 || X >= 8.5 || Y < .5 || Y >= 8.5) goto _3420;
|
||
_2990: _V[4] = X;
|
||
_2991: _V[5] = Y;
|
||
_2992: _9000();
|
||
_2993: Console.WriteLine();
|
||
_3020: if (_A[(int)(X + .5), (int)(Y + .5)] != 0) goto _3080;
|
||
_3060: goto _2960;
|
||
_3080: if (_A[(int)(X + .5), (int)(Y + .5)] != 2) goto _3230;
|
||
_3120: Console.WriteLine("*** KLINGON DESTROYED ***");
|
||
_3130: _P[1] = _P[1] - 1;
|
||
_3140: _P[3] = _P[3] - 1;
|
||
_3150: if (_P[3] <= 0) goto _4040;
|
||
_3160: for(I = 1; I <= 3; I += 1) {
|
||
_3170: if ((int)(X + .5) != _K[(int)I, 1]) goto _3190;
|
||
_3180: if ((int)(Y + .5) == _K[(int)I, 2]) goto _3200;
|
||
_3190: ;} I = 3;
|
||
_3200: _K[(int)I, 3] = 0;
|
||
_3210: goto _3370;
|
||
_3230: if (_A[(int)(X + .5), (int)(Y + .5)] != 4) goto _3290;
|
||
_3270: Console.WriteLine("YOU CAN'T DESTROY STARS SILLY");
|
||
_3280: goto _3420;
|
||
```
|
||
|
||
To simulate line numbers, each line starts with a label consisting of an
|
||
underscore followed by a number. That works fine for GOTO, but what
|
||
about GOSUB? Examine line 2992. Subroutines were replaced with methods.
|
||
That almost worked. In BASIC, you’re not forced to RETURN from
|
||
subroutines. You can leave them via GOTO. That was used only in the case
|
||
that the player is destroyed to send them back to the beginning of the
|
||
program to start over. I replaced that GOTO with a return statement that
|
||
passes a flag back to the caller. The caller inspects the flag and jumps
|
||
back to the program start if need be. I also discovered that at one
|
||
point, there is a GOTO that jumps into a FOR loop. C\# won’t let you
|
||
jump to a label in a sub-block of code. I transformed the FOR loop into
|
||
a GOTO loop to make C\# happy.
|
||
|
||
All the variables in the BASIC program, including the arrays, are real
|
||
number type. However, in BASIC, an array and a scalar can share the same
|
||
name; the interpreter is able to sort it all out. But, C\# is less kind.
|
||
To solve the problem, I prefixed array names with underscores. Also,
|
||
arrays in BASIC are indexed from 1 instead of 0. To compensate, I
|
||
increased the length of all arrays by 1. Index 0 is never used.
|
||
|
||
When I started testing my port, I noticed some string formatting
|
||
problems. Examine the following BASIC line:
|
||
|
||
2726 PRINT TAB(41);"(";
|
||
|
||
That means: Print 41 spaces followed by left-parenthesis. That was easy
|
||
to translate, but the intension was to push the left-parenthesis onto
|
||
the next line by letting it wrap around the console. I cleaned some of
|
||
this stuff up. There are also some tables that get printed in the game.
|
||
I reformatted them a bit to make them easier to read.
|
||
|
||
One other thing: notice that in this type of BASIC, \# indicates
|
||
not-equal-to. It took me a while to realize why they chose that symbol.
|
||
\# resembles ≠.
|
||
|
||
## Entering the Star Trek Universe
|
||
|
||
Now, I was ready to play the game. As I mentioned above, I never
|
||
understood the rules before. Luckily, when you run the program, it gives
|
||
you the option of viewing instructions. I studied them carefully. But,
|
||
the only way to really understand what to do is to play the game. Here’s
|
||
a walkthrough:
|
||
|
||
```
|
||
STAR TREK
|
||
|
||
|
||
|
||
ENTER 1 OR 2 FOR INSTRUCTIONS (ENTER 2 TO PAGE)
|
||
|
||
ENTER SEED NUMBER
|
||
INITIALIZING...
|
||
|
||
YOU MUST DESTROY 17 KINGONS IN 30 STARDATES WITH 3 STARBASES
|
||
|
||
-=--=--=--=--=--=--=--=-
|
||
*
|
||
STARDATE 2100
|
||
* * CONDITION GREEN
|
||
<*> QUADRANT 5,2
|
||
* SECTOR 5,4
|
||
ENERGY 3000
|
||
SHIELDS 0
|
||
* PHOTON TORPEDOES 10
|
||
-=--=--=--=--=--=--=--=-
|
||
COMMAND
|
||
```
|
||
|
||
The game makes itself known by printing out its title. Then, it asks you
|
||
if you want to view instructions. Every prompt in the game demands a
|
||
number. If you hit Enter, zero is assumed. In this case, I hit Enter to
|
||
skip the instructions. Next, it asks for a seed number to initialize the
|
||
randomizer. This is an artifact of BASIC. It doesn’t really have an
|
||
effect in C\#. In BASIC, just as in C\#, the randomizer could have been
|
||
initialized based off the system time. If that was not an option, they
|
||
should have taken advantage of the instructions prompt. When the
|
||
instructions prompt appears, it could have entered a loop that timed how
|
||
long it took the user to enter a value. That duration could have been
|
||
used to initialize the randomizer. Again, I simply pressed Enter to skip
|
||
it.
|
||
|
||
Next, it prints out my mission. I have to destroy 17 Klingon (note the
|
||
game misspells it here) ships in 30 units of time with 3 starbases. Then
|
||
it runs the short range scanner. The short range scanner displays the
|
||
current quadrant. The game takes place in an 8×8 quadrant grid. Each row
|
||
and column is numbered 1 to 8. The text on the right indicates that I am
|
||
in quadrant (5,2). Each quadrant is partitioned into an 8×8 sector grid.
|
||
The Enterprise is located at sector (5,4). On the quadrant display,
|
||
`<*>` is the Enterprise. The remaining `*`’s are stars. Each = mark on
|
||
the top and bottom horizontal-line dividers indicates a column. If you
|
||
count, you’ll find that the Enterprise is in column 5. If you count the
|
||
rows, you’ll find it’s in row 4. Hence, within this quadrant, the
|
||
Enterprise is in sector (5,4) as specified.
|
||
|
||
The goal is seek out quadrants containing Klingon ships and destroy
|
||
them. Let’s begin by doing a long range sensor scan (option 2):
|
||
|
||
COMMAND 2
|
||
LONG RANGE SENSOR SCAN FOR QUADRANT 5,2
|
||
-------------------
|
||
| 008 | 008 | 004 |
|
||
-------------------
|
||
| 006 | 005 | 007 |
|
||
-------------------
|
||
| 001 | 104 | 113 |
|
||
-------------------
|
||
|
||
This table summarizes 9 quadrants. The center quadrant is your current
|
||
quadrant. The digits indicate the number of Klingon ships, the number of
|
||
starbases and the number of stars. In our quadrant, there are no Klingon
|
||
ships and no starbases, but there are 5 stars. Stars act as annoying
|
||
obstacles as I’ll demonstrate later on. South of us, there is a quadrant
|
||
containing 1 Klingon ship. Let’s head there. But, first we need to raise
|
||
shields (option 5):
|
||
|
||
COMMAND 5
|
||
ENERGY AVAILABLE = 3000
|
||
NUMBER OF UNITS TO SHIELDS 500
|
||
|
||
It asks me how much energy I want to devote to the shields. I entered
|
||
500. If I run out of energy, I lose the game. Starbases replenish
|
||
energy. They also restock photon torpedoes and repair damage. To see how
|
||
much energy I have left, I’ll run a short range scan again (option 1):
|
||
|
||
COMMAND 1
|
||
-=--=--=--=--=--=--=--=-
|
||
*
|
||
STARDATE 2100
|
||
* * CONDITION GREEN
|
||
<*> QUADRANT 5,2
|
||
* SECTOR 5,4
|
||
ENERGY 2500
|
||
SHIELDS 500
|
||
* PHOTON TORPEDOES 10
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
Now, let’s head south. Navigation requires 2 parameters: direction and
|
||
distance. It’s a polar coordinate system, but an unconventional one.
|
||
Direction is specified using this:
|
||
|
||
4 3 2
|
||
`. : .'
|
||
`.:.'
|
||
5---<*>---1
|
||
.':`.
|
||
.' : `.
|
||
6 7 8
|
||
|
||
Angle goes from 1.0 (inclusive) to 9.0 (exclusive). Note that the y-axis
|
||
points downwards. So, although it appears to be a counterclockwise angle
|
||
system, it’s actually clockwise. You also need to consider the aspect
|
||
ratio. Each column is 3 characters wide, but each row is only 1
|
||
character high. This means that it’s not a circular coordinate system.
|
||
Rather, it’s a swashed oval.
|
||
|
||
Distance is measured in warp factor units. Such a unit is equal to the
|
||
length/height of a quadrant. To move to an adjacent sector, you need to
|
||
move a distance of 1/8 = 0.125. I’m going to move south (angle 7.0) a
|
||
distance of 1 warp factor. Navigation is option 0:
|
||
|
||
COURSE (1-9) 7
|
||
WARP FACTOR (0-8) 1
|
||
|
||
DAMAGE CONTROL REPORT: WARP ENGINES DAMAGED
|
||
|
||
-=--=--=--=--=--=--=--=-
|
||
*
|
||
STARDATE 2101
|
||
* CONDITION RED
|
||
<*> QUADRANT 5,3
|
||
SECTOR 5,4
|
||
* ENERGY 2497
|
||
* SHIELDS 500
|
||
+++ PHOTON TORPEDOES 10
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
Navigation automatically runs a short range scan. Note that I moved from
|
||
quadrant (5,2) to quadrant (5,3). Also, notice that is says that my warp
|
||
engines are damaged. Parts of the Enterprise fail spontaneously. As you
|
||
navigate around, they slowly get repaired. Let’s get a damage report
|
||
(option 6):
|
||
|
||
COMMAND 6
|
||
|
||
DEVICE STATE OF REPAIR
|
||
WARP ENGINES -3
|
||
S.R. SENSORS 0
|
||
L.R. SENSORS 0
|
||
PHASER CNTRL 0
|
||
PHOTON TUBES 0
|
||
DAMAGE CNTRL 0
|
||
SHIELD CNTRL 0
|
||
COMPUTER 0
|
||
|
||
A value of 0 indicates normal operation. Less-than 0 is damage.
|
||
Greater-than 0 indicates that the component is working above normal.
|
||
|
||
The short range scan above shows a Klingon ship (the triple-plus). I’m
|
||
going to use the computer to help me target the ship (option 7 followed
|
||
by option 2):
|
||
|
||
COMMAND 7
|
||
COMPUTER ACTIVE AND AWAITING COMMAND 2
|
||
DIRECTION = 7
|
||
DISTANCE = 4
|
||
|
||
ENTER 1 TO USE THE CALCULATOR
|
||
|
||
Photon torpedoes are fired using the same direction and distance
|
||
coordinate system as is used for navigation. The computer gave me the
|
||
coordinates. Then it asks if I want to use the navigation calculator.
|
||
The navigation calculator asks you to enter the coordinates of 2
|
||
quadrants and it will output direction and distance between them. I’ll
|
||
press Enter to indicate I am not interested in doing this. Now, let’s
|
||
fire the torpedo (option 4):
|
||
|
||
COMMAND 4
|
||
TORPEDO COURSE (1-9) 7
|
||
TORPEDO TRACK:
|
||
5,5
|
||
5,6
|
||
5,7
|
||
5,8
|
||
*** KLINGON DESTROYED ***
|
||
COMMAND 1
|
||
-=--=--=--=--=--=--=--=-
|
||
*
|
||
STARDATE 2101
|
||
* CONDITION GREEN
|
||
<*> QUADRANT 5,3
|
||
SECTOR 5,4
|
||
* ENERGY 2497
|
||
* SHIELDS 500
|
||
PHOTON TORPEDOES 9
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
The game outputs the track of the torpedo. In this case, it hit the
|
||
target. If the computer gets damaged, you have to estimate the direction
|
||
of the Klingon ship yourself. It may take a few tries. The torpedo track
|
||
will help you refine the direction. Also, sometimes a torpedo randomly
|
||
diverts a bit from the specified direction.
|
||
|
||
Let’s get a status report using the computer (option 7, option 1):
|
||
|
||
COMMAND 7
|
||
COMPUTER ACTIVE AND AWAITING COMMAND 1
|
||
|
||
STATUS REPORT
|
||
|
||
NUMBER OF KLINGONS LEFT = 16
|
||
NUMBER OF STARDATES LEFT = 29
|
||
NUMBER OF STARBASES LEFT = 3
|
||
|
||
DEVICE STATE OF REPAIR
|
||
WARP ENGINES -3
|
||
S.R. SENSORS 0
|
||
L.R. SENSORS 0
|
||
PHASER CNTRL 0
|
||
PHOTON TUBES 0
|
||
DAMAGE CNTRL 0
|
||
SHIELD CNTRL 0
|
||
COMPUTER 0
|
||
|
||
One Klingon ship down, but my warp engine is still damaged. Let’s do a
|
||
long range scan:
|
||
|
||
COMMAND 2
|
||
LONG RANGE SENSOR SCAN FOR QUADRANT 5,3
|
||
-------------------
|
||
| 006 | 005 | 007 |
|
||
-------------------
|
||
| 001 | 004 | 113 |
|
||
-------------------
|
||
| 002 | 005 | 002 |
|
||
-------------------
|
||
|
||
I want to go east. The starbase there, indicated by the center 1, can
|
||
repair my warp drive. I’ll try to navigate there:
|
||
|
||
COMMAND 0
|
||
COURSE (1-9) 1
|
||
WARP FACTOR (0-8) 1
|
||
WARP ENGINES ARE DAMAGED, MAXIMUM SPEED = WARP .2
|
||
COURSE (1-9) 1
|
||
WARP FACTOR (0-8) .2
|
||
-=--=--=--=--=--=--=--=-
|
||
*
|
||
STARDATE 2101
|
||
* CONDITION GREEN
|
||
<*> QUADRANT 5,3
|
||
SECTOR 6,4
|
||
* ENERGY 2501
|
||
* SHIELDS 500
|
||
PHOTON TORPEDOES 9
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
As you can see, when the warp drive is damaged, I can only move 1 sector
|
||
at a time.
|
||
|
||
DAMAGE CONTROL REPORT: L.R. SENSORS DAMAGED
|
||
|
||
-=--=--=--=--=--=--=--=-
|
||
*
|
||
STARDATE 2101
|
||
* CONDITION GREEN
|
||
<*> QUADRANT 5,3
|
||
SECTOR 7,4
|
||
* ENERGY 2505
|
||
* SHIELDS 500
|
||
PHOTON TORPEDOES 9
|
||
-=--=--=--=--=--=--=--=-
|
||
COMMAND 0
|
||
COURSE (1-9) 1
|
||
WARP FACTOR (0-8) .2
|
||
-=--=--=--=--=--=--=--=-
|
||
*
|
||
STARDATE 2101
|
||
* CONDITION GREEN
|
||
<*> QUADRANT 5,3
|
||
SECTOR 8,4
|
||
* ENERGY 2509
|
||
* SHIELDS 500
|
||
PHOTON TORPEDOES 9
|
||
-=--=--=--=--=--=--=--=-
|
||
COMMAND 0
|
||
COURSE (1-9) 1
|
||
WARP FACTOR (0-8) .2
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
+++ STARDATE 2102
|
||
* * CONDITION RED
|
||
<*> QUADRANT 6,3
|
||
SECTOR 1,4
|
||
>!< ENERGY 2513
|
||
SHIELDS 500
|
||
* PHOTON TORPEDOES 9
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
I managed to get over there, but now my long range scanner is damaged.
|
||
Note that each time you cross a quadrant boundary, the stardate
|
||
advances. I have to destroy all the Klingons in the time restriction of
|
||
my mission.
|
||
|
||
The `>!<` symbol indicates a starbase. If I navigate next to it, the
|
||
Enterprise will automatically dock at which time I’ll get everything
|
||
repaired. But, if I try to navigate there, the Klingon ship will fire at
|
||
me. I can’t send out a photon torpedo because of the stars. The stars
|
||
will obstruct the track. Let me check on those repairs:
|
||
|
||
COMMAND 7
|
||
COMPUTER ACTIVE AND AWAITING COMMAND 1
|
||
|
||
STATUS REPORT
|
||
|
||
NUMBER OF KLINGONS LEFT = 16
|
||
NUMBER OF STARDATES LEFT = 28
|
||
NUMBER OF STARBASES LEFT = 3
|
||
|
||
DEVICE STATE OF REPAIR
|
||
WARP ENGINES 0
|
||
S.R. SENSORS 0
|
||
L.R. SENSORS 0
|
||
PHASER CNTRL 0
|
||
PHOTON TUBES 0
|
||
DAMAGE CNTRL 0
|
||
SHIELD CNTRL 0
|
||
COMPUTER 0
|
||
|
||
Nice. The Enterprise is back to normal. I’ll try using my phasers to hit
|
||
the Klingons (option 3):
|
||
|
||
COMMAND 3
|
||
PHASERS LOCKED ON TARGET. ENERGY AVAILABLE = 2513
|
||
NUMBER OF UNITS TO FIRE 500
|
||
19 UNIT HIT ON ENTERPRISE FROM SECTOR 7,2
|
||
(480 LEFT)
|
||
67 UNIT HIT ON KLINGON AT SECTOR 7,2
|
||
(132 LEFT)
|
||
|
||
The Enterprise was hit. My shields dropped a small amount. The Klingon
|
||
ship was damaged as well. I’ll fire again:
|
||
|
||
COMMAND 3
|
||
PHASERS LOCKED ON TARGET. ENERGY AVAILABLE = 2013
|
||
NUMBER OF UNITS TO FIRE 1000
|
||
16 UNIT HIT ON ENTERPRISE FROM SECTOR 7,2
|
||
(464 LEFT)
|
||
100 UNIT HIT ON KLINGON AT SECTOR 7,2
|
||
(31 LEFT)
|
||
COMMAND 3
|
||
PHASERS LOCKED ON TARGET. ENERGY AVAILABLE = 1013
|
||
NUMBER OF UNITS TO FIRE 300
|
||
5 UNIT HIT ON ENTERPRISE FROM SECTOR 7,2
|
||
(458 LEFT)
|
||
62 UNIT HIT ON KLINGON AT SECTOR 7,2
|
||
(0 LEFT)
|
||
*** KLINGON AT SECTOR 7,2 DESTROYED ***
|
||
COMMAND 1
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
STARDATE 2102
|
||
* * CONDITION GREEN
|
||
<*> QUADRANT 6,3
|
||
SECTOR 1,4
|
||
>!< ENERGY 713
|
||
SHIELDS 458
|
||
* PHOTON TORPEDOES 9
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
I fired twice, which severely lowered my energy level. Phaser strength
|
||
is a measure of the distance between the Enterprise the target. It
|
||
probably would have been better to navigate north for a clear path for a
|
||
photon torpedo. Luckily, I can dock with the starbase to replenish my
|
||
energy:
|
||
|
||
COMMAND 0
|
||
COURSE (1-9) 7
|
||
WARP FACTOR (0-8) .25
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
STARDATE 2102
|
||
* * CONDITION GREEN
|
||
QUADRANT 6,3
|
||
SECTOR 1,6
|
||
<*> >!< ENERGY 716
|
||
SHIELDS 458
|
||
* PHOTON TORPEDOES 9
|
||
-=--=--=--=--=--=--=--=-
|
||
COMMAND 0
|
||
COURSE (1-9) 1
|
||
WARP FACTOR (0-8) 1
|
||
WARP ENGINES SHUTDOWN AT SECTOR 6,6 DUE TO BAD NAVIGATION
|
||
SHIELDS DROPPED FOR DOCKING PURPOSES
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
STARDATE 2103
|
||
* * CONDITION DOCKED
|
||
QUADRANT 6,3
|
||
SECTOR 5,6
|
||
<*>>!< ENERGY 3000
|
||
SHIELDS 0
|
||
* PHOTON TORPEDOES 10
|
||
-=--=--=--=--=--=--=--=-
|
||
|
||
The starbase takes away all my shield energy before giving me back 3000.
|
||
If the game didn’t do this, the player could get infinite shield
|
||
strength by repeatedly docking and transferring energy to the shields.
|
||
|
||
Also note that I docked by crashing into the starbase. While you are
|
||
within a quadrant, you can’t pass through stars, ships and starbases.
|
||
However, after leaving the current quadrant, those are no longer
|
||
obstacles. In fact, the positions of stars, starbases and Klingon ships
|
||
within a quadrant is not determined at the start of the game. Rather,
|
||
the positions are invented at the time you enter a quadrant. It creates
|
||
the illusion that stars, starbases and Klingon ships can move around
|
||
within a quadrant. Note that they can never move out of a quadrant.
|
||
|
||
COMMAND 2
|
||
LONG RANGE SENSOR SCAN FOR QUADRANT 6,3
|
||
-------------------
|
||
| 005 | 007 | 007 |
|
||
-------------------
|
||
| 004 | 013 | 001 |
|
||
-------------------
|
||
| 005 | 002 | 016 |
|
||
-------------------
|
||
|
||
The values you see in a long range scan are the only values tracked by
|
||
the game. It doesn’t store the exact sectors of each entity within a
|
||
quadrant until you enter it. On a related note, the computer can show
|
||
you a table of all scanned quadrants (option 7, option 0):
|
||
|
||
COMMAND 7
|
||
COMPUTER ACTIVE AND AWAITING COMMAND 0
|
||
COMPUTER RECORD OF GALAXY FOR QUADRANT 6,3
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 008 | 008 | 004 | 000 | 000 |
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 006 | 005 | 007 | 007 | 000 |
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 001 | 004 | 013 | 001 | 000 |
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 002 | 005 | 002 | 016 | 000 |
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 000 | 000 | 000 | 000 | 000 |
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 000 | 000 | 000 | 000 | 000 |
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 000 | 000 | 000 | 000 | 000 |
|
||
-------------------------------------------------
|
||
| 000 | 000 | 000 | 000 | 000 | 000 | 000 | 000 |
|
||
-------------------------------------------------
|
||
|
||
Anyway, that’s the gist of the game.
|
||
|
||
So, what happens when you win?
|
||
|
||
THE LAST KLIGON BATTLE CRUISER IN THE GALAXY HAS BEEN DESTROYED
|
||
THE FEDERATION HAS BEEN SAVED !!!
|
||
|
||
YOUR EFFICIENCY RATING = ...
|
||
|
||
And then it just starts over again with a new mission. The efficiency
|
||
rating is a function of the time remaining. In Mike Mayfield’s original
|
||
version, the time remaining was actually in minutes. As mentioned, in
|
||
this version, it’s in turns.
|
||
|
||
## Super Star Trek
|
||
|
||
In 1976, Creative Computing published a modified version of Mike
|
||
Mayfield’s program titled Super Star Trek. It’s virtually identical to
|
||
the original game. However, the menus accept 3 letter mnemonics instead
|
||
of numbers. The computer offers a few more options. And, just for fun,
|
||
each quadrant has a name. With those ideas in mind, I decided to code my
|
||
own version of the game. I began by digging up some ancient ASCII art...
|
||
|
||
```
|
||
______ _______ ______ ______ _______ ______ ______ __ __
|
||
/ __ //__ __// __ // __ / /__ __// __ / / ____// / / /
|
||
/ / /_/ / / / /_/ // /_/ / / / / /_/ / / /__ / // /
|
||
_\ \ / / / __ // __/ / / / __/ / __ / / /
|
||
/ /_/ / / / / / / // /\ \ / / / /\ \ / /___ / /\ \
|
||
/_____/ /_/ /_/ /_//_/ \_\ /_/ /_/ \_\/_____//_/ \_\
|
||
|
||
________________ _
|
||
\__(=======/_=_/____.--'-`--.___
|
||
\ \ `,--,-.___.----'
|
||
.--`\\--'../
|
||
'---._____.|]
|
||
|
||
Mission: Destroy 20 Klingon ships in 46 stardates with 3 starbases.
|
||
|
||
Enter command:
|
||
|
||
--- Commands -----------------
|
||
nav = Navigation
|
||
srs = Short Range Scan
|
||
lrs = Long Range Scan
|
||
pha = Phaser Control
|
||
tor = Photon Torpedo Control
|
||
she = Shield Control
|
||
com = Access Computer
|
||
|
||
Enter command: srs
|
||
|
||
-=--=--=--=--=--=--=--=- Region: Altair IV
|
||
Quadrant: [2,5]
|
||
* Sector: [1,6]
|
||
Stardate: 2287
|
||
* Time remaining: 46
|
||
Condition: GREEN
|
||
<*> Energy: 3000
|
||
Shields: 0
|
||
* Photon Torpedoes: 10
|
||
-=--=--=--=--=--=--=--=- Docked: False
|
||
|
||
Enter command: lrs
|
||
|
||
-------------------
|
||
| 117 | 118 | 004 |
|
||
-------------------
|
||
| 006 | 003 | 008 |
|
||
-------------------
|
||
| 004 | 001 | 115 |
|
||
-------------------
|
||
|
||
Enter command: nav
|
||
|
||
Enter course (1.0--9.0): 3
|
||
Enter warp factor (0.1--8): 1
|
||
|
||
Warp engines engaged.
|
||
|
||
-=--=--=--=--=--=--=--=- Region: Risa
|
||
* * Quadrant: [2,4]
|
||
Sector: [1,6]
|
||
+++ * * Stardate: 2288
|
||
* Time remaining: 45
|
||
>!< Condition: RED
|
||
<*> * Energy: 3000
|
||
Shields: 0
|
||
* * Photon Torpedoes: 10
|
||
-=--=--=--=--=--=--=--=- Docked: True
|
||
|
||
Condition RED: Klingon ship detected.
|
||
|
||
Lowering shields as part of docking sequence...
|
||
Enterprise successfully docked with starbase.
|
||
|
||
Enter command: pha
|
||
|
||
Phasers locked on target.
|
||
Enter phaser energy (1--3000): 500
|
||
|
||
Firing phasers...
|
||
Hit ship at sector [5,3]. Klingon shield strength dropped to 206.
|
||
|
||
Enterprise hit by ship at sector [5,3]. No damage due to starbase shields.
|
||
|
||
Enter command: pha
|
||
|
||
Phasers locked on target.
|
||
Enter phaser energy (1--2500): 500
|
||
|
||
Firing phasers...
|
||
Klingon ship destroyed at sector [5,3].
|
||
|
||
Enter command: srs
|
||
|
||
-=--=--=--=--=--=--=--=- Region: Risa
|
||
* * Quadrant: [2,4]
|
||
Sector: [1,6]
|
||
* * Stardate: 2288
|
||
* Time remaining: 45
|
||
>!< Condition: GREEN
|
||
<*> * Energy: 2000
|
||
Shields: 0
|
||
* * Photon Torpedoes: 10
|
||
-=--=--=--=--=--=--=--=- Docked: True
|
||
|
||
Enter command:
|
||
```
|
||
|
||
There are many subtle nuances in the original game. How often do
|
||
different parts of the Enterprise malfunction? How and when do photon
|
||
torpedoes randomly deviate from their specified targets? And so on. It
|
||
doesn’t really matter. As I said above, this is the kind of game that
|
||
deserves to be reinvented everytime it trades hands. The exact
|
||
parameters of the Star Trek universe are up to the coder. For example,
|
||
in my version, different parts of the Enterprise malfunction depending
|
||
on how often you use them. If you rely on the computer for targeting
|
||
Klingon ships too much, the computer will start to fail.
|
||
|
||
Rewriting the game brought up an interesting aspect of the BASIC
|
||
version. Targeting is done using polar coordinates, but you won’t find
|
||
any trigonometric functions in the BASIC code. I assume the functions
|
||
were unavailable. Instead, the angle is converted into a direction
|
||
vector using different ratios that approximate the trigonometric
|
||
functions. That means even if you worked out perfect targeting using
|
||
trigonometry, when you entered in the angle, the actual trajectory will
|
||
be slightly off. Nonetheless, it’s a pretty clever math trick. As for
|
||
me, I took advantage of `Math.Sin()` and `Math.Cos()`.
|
||
|
||
Finally, if you’re ready to enter the ASCII Star Trek universe and save
|
||
the Federation from attacking Klingon plus-signs, download the attached
|
||
source code.
|
||
|
||
## References
|
||
|
||
- Star Trek Game History:
|
||
<http://www3.sympatico.ca/maury/games/space/star_trek.html>
|
||
- Wiki: <http://en.wikipedia.org/wiki/Star_Trek_%28text_game%29>
|
||
- Mike Mayfield’s Original Code:
|
||
<http://www.dunnington.u-net.com/public/startrek/STTR1>
|
||
- Enhanced Version: <http://newton.freehostia.com/hp/bas/TREKPT.txt>
|
||
- Super Star Trek:
|
||
<http://www.atariarchives.org/bcc1/showpage.php?page=275>
|