---
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>
