Star Trek

This file is part of and Timex Sinclair Public Domain Library Tape 1007. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Game

This is a space combat strategy game in the style of Star Trek, played on a 10×10 grid. Two parallel arrays, A() and B(), track game state and display state respectively: A() holds logical values (0=empty, 1=alien, 2=player) while B() drives the map rendering with additional codes for misses (3) and kills (4). The player chooses between scanning, moving, and firing each turn, with an energy budget that depletes by 10, 50, or 100 units depending on the action. Sector names are derived by multiplying the player’s grid coordinates and mapping the product to one of ten star names. The program uses FAST/SLOW mode switching around the map redraw routine at line 8000 to speed up screen output.


Program Analysis

Program Structure

The program is organized into a main loop and a set of subroutines identified by line-number ranges:

Line RangePurpose
10–500Main loop: initialisation calls, command menu, dispatch
1000–1700Scanner (close and long-range)
2000–2300Move command
3000–3460Fire command
3800–3890Game-over / energy exhausted
5000–5900Ship collision / stop
6950–6970Clear message area (lines 13+)
7000–7490Status display
7500–7900Random crew-member voice prefix
8000–8490Map redraw
8500–8740Sector name lookup
9000–9900Initialisation (arrays, position, energy, alien name)

Command Dispatch

Line 160 uses the expression GOSUB 1000*D where D is 1, 2, or 3, dispatching to subroutines at lines 1000, 2000, or 3000 respectively. This is a compact computed-GOSUB idiom that avoids an IF/GOTO ladder. Input validation at line 150 ensures D is always in range before the multiplication.

Dual-Array Map Design

Two 10×10 arrays serve distinct roles:

  • A(Q,P) — logical state: 0 = empty, 1 = alien ship, 2 = player ship
  • B(Q,P) — display state: 0 = empty, 2 = player, 3 = missed shot marker, 4 = destroyed alien

The map renderer at line 8000 iterates over B() exclusively, printing inverse-video characters for each cell code. This separation means the game logic can query A() cleanly without display artefacts interfering.

Map Rendering and FAST/SLOW

The subroutine at line 8000 wraps its output between FAST (line 8002) and SLOW (line 8225) to minimise flicker and speed up the 10×10 grid draw. A compass rose (N/+/W·E/S) is printed at a fixed position (lines 8220–8223) using AT coordinates to the right of the grid. Each row also prints a cursor-reset sequence (AT Q,13;"\@@" then AT Q,13;" ") before printing cell contents, likely to handle line-wrap artefacts.

Sector Name Calculation

Line 8520 computes Q=B*C (player row × column) and maps the product to one of ten sector names via a chain of IF comparisons spanning lines 8540–8720. This gives a positionally-derived name that changes as the player moves, though the mapping is not bijective — many coordinate pairs yield the same product and thus the same sector name. Note line 8700 contains a typo: STRIUS instead of SIRIUS.

Random Crew Voice

Subroutine 7500 picks R=INT(RND*5) and prints one of five crew-member prefixes (Spock, Scott, Uhura, Chekov, Sulu) before any message. This is called before nearly every player-facing PRINT to simulate crew reporting, adding narrative flavour without additional logic.

Energy Economy

ActionEnergy Cost
Close scanner (K=1)10
Long-range scanner (K=2)20
Move50
Fire (hit or miss)100
Enemy return fire hit100 × RND (additional)

Starting energy is 1000 + 2000*RND (line 9340), giving a range of 1000–3000. Energy is checked at line 7030; if it drops below 1, execution jumps to the game-over sequence at line 3800.

Initialisation and Variable Reuse

The initialisation subroutine at line 9000 uses the loop variable A for its FOR loop (lines 9060–9140) even though A is also the name of the 2D array A(). In Sinclair BASIC, a simple variable and an array variable share the same name space only if they have the same name but differ in dimension; here the loop variable A and array A() coexist because array access always uses parentheses. However, this is a risky naming choice that could confuse maintenance.

Collision Detection

After a move, line 2260 checks IF A(B,C)=1 (new cell contains an alien) and branches to line 5500, which enters an alternating inverse/normal print loop displaying a collision message — effectively a terminal game-over state that loops indefinitely without a clean exit.

Bugs and Anomalies

  • Line 3400 is referenced by GOTO 3400 at line 3340 but does not exist; the branch falls through to line 3420 which prints the miss message. This is intentional ZX81 behaviour: branching to a non-existent line runs the next available line.
  • Line 1020 is the effective entry point for the scanner subroutine, but the dispatch at line 160 calls GOSUB 1000 — line 1000 does not exist, so execution begins at 1020. Same technique as above.
  • The game-over loop at line 3890 jumps back to 3805 (a SCROLL statement), creating an infinite scroll that cannot be escaped without a manual break.
  • Typo at line 8700: STRIUS should be SIRIUS.
  • The FOR G=1 TO 30: NEXT G loops at lines 3315–3317 and 3330–3335 serve as busy-wait delays with no body, a common ZX81 timing technique.
  • Line 9260 sets E=RND (a value between 0 and 1) solely to drive the alien-name selection at lines 9280–9320 before being overwritten by the actual energy value at line 9340. This is a valid but potentially confusing reuse of the energy variable.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10294-10335.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

  10 FAST 
  20 GOSUB 9000
  25 GOSUB 8000
  30 GOSUB 6950
  40 GOSUB 7000
  50 GOSUB 6950
  80 GOSUB 7500
 100 PRINT "WHAT IS YOUR ORDER,"
 120 PRINT TAB 5;"SIR ?",,TAB 12;"1-SCAN";TAB 12;"2-MOVE";TAB 12;"3-FIRE"
 140 INPUT D
 150 IF D<1 OR D>3 THEN GOTO 140
 155 GOSUB 6950
 160 GOSUB 1000*D
 170 FOR W=1 TO 30
 180 PRINT AT 20,5;" : : : : :";AT 20,5;"     "
 190 NEXT W
 500 GOTO 30
 1020 PRINT TAB 4;"% %  SCANNER % % "
 1030 GOSUB 7500
 1040 PRINT "CLOSE (1) OR ","LONG-RANGE (2), SIR ?"
 1060 INPUT K
 1080 LET E=E-10*K
 1090 GOSUB 6950
 1100 IF K=2 THEN GOTO 1500
 1120 IF A(B+1,C)=1 OR A(B+1,C+1)=1 OR A(B,C+1)=1 OR A(B-1,C)=1 OR A(B-1,C-1)=1 OR A(B,C-1)=1 OR A(B+1,C-1)=1 OR A(B-1,C+1)=1 THEN PRINT Z$;" IN VICINITY,","SIR"
 1140 RETURN 
 1500 GOSUB 7500
 1520 PRINT AT 15,0;"DIRECTION: N-1, S-2, E-3, W-4 ?"
 1525 PRINT TAB 8;"(ENTER A NUMBER)"
 1530 INPUT N
 1540 LET Z=0
 1560 IF N=1 AND A(B-2,C)=1 THEN LET Z=1
 1580 IF N=2 AND A(B+2,C)=1 THEN LET Z=1
 1600 IF N=3 AND A(B,C+2)=1 THEN LET Z=1
 1620 IF N=4 AND A(B,C-2)=1 THEN LET Z=1
 1630 GOSUB 7500
 1640 PRINT "LONG-RANGE SCANNER REPORT IS"
 1660 IF Z=1 THEN PRINT "POSITIVE"
 1680 IF Z=0 THEN PRINT "NEGATIVE"
 1700 RETURN 
 2020 LET E=E-50
 2040 LET A(B,C)=0
 2050 LET B(B,C)=0
 2060 PRINT "DIRECTION (N/S)?"
 2080 INPUT A$
 2100 LET B=B-1
 2120 IF A$="S" THEN LET B=B+2
 2130 GOSUB 7500
 2140 PRINT "NOW AT ";B;",";C
 2160 PRINT TAB 12;"(E/W)?"
 2180 INPUT A$
 2200 LET C=C-1
 2220 IF A$="E" THEN LET C=C+2
 2240 PRINT "NOW AT ";B;",";C
 2260 IF A(B,C)=1 THEN GOTO 5500
 2270 LET A(B,C)=2
 2280 LET B(B,C)=2
 2290 GOSUB 8000
 2300 RETURN 
 3000 REM FIRE
 3010 GOSUB 7500
 3020 PRINT "DIRECTION OF FIRE (N/S)?"
 3040 INPUT A$
 3060 LET G=B-1
 3080 IF A$="S" THEN LET G=G+2
 3100 PRINT TAB 12;"(E/W)?"
 3120 LET F=C-1
 3140 INPUT A$
 3160 IF A$="E" THEN LET F=F+2
 3180 LET E=E-100
 3190 IF A(G,F)<>1 THEN GOTO 3300
 3195 GOSUB 7500
 3200 PRINT "YOU HIT THE ";Z$
 3220 LET AL=AL+1
 3260 LET B(G,F)=4
 3290 RETURN 
 3300 GOSUB 7500
 3305 LET B(G,F)=3
 3310 PRINT "YOU MISSED, SIR"
 3315 FOR G=1 TO 30
 3317 NEXT G
 3320 PRINT "THE ";Z$;" ARE","SHOOTING BACK"
 3330 FOR G=1 TO 30
 3335 NEXT G
 3337 GOSUB 6950
 3340 IF RND>.6 THEN GOTO 3400
 3360 PRINT "THEY HIT US, SIR"
 3370 GOSUB 8000
 3380 LET E=E-100*RND
 3390 RETURN 
 3420 PRINT "THE ";Z$;" MISSED, SIR"
 3460 RETURN 
 3800 GOSUB 6950
 3805 SCROLL 
 3810 PRINT "ENERGY BANKS EXHAUSTED"
 3815 SCROLL 
 3820 PRINT "YOU KILLED ";AL;" ALIEN";
 3830 IF AL<>1 THEN PRINT "S"
 3850 SCROLL 
 3860 PRINT "ON THIS MISSION"
 3870 SCROLL 
 3880 PRINT "YOUR COMMANDER RATING IS ";INT (AL/8*100)
 3890 GOTO 3805
 5000 REM END
 5500 GOSUB 6950
 5520 PRINT AT 15,0;"YOUR SHIP HAS LANDED ON A",Z$;" VESSEL"
 5540 PRINT AT 15,0;"%Y%O%U%R% %S%H%I%P% %H%A%S% %L%A%N%D%E%D% %O%N% %A"
 5560 GOTO 5520
 5900 STOP 
 6950 PRINT AT 13,0;"                                                                                                                                                                                                                               "
 6955 PRINT AT 13,0;
 6970 RETURN 
 7000 REM STATUS
 7020 PRINT AT 2,14;"ENERGY BANK: ";INT E;" "
 7030 IF E<1 THEN GOTO 3800
 7040 IF AL>0 THEN PRINT AT 3,14;"ALIEN KILL";AT 4,17;"TALLY: ";AL
 7060 PRINT AT 7,14;"YOU ARE AT ";B;",";C
 7070 PRINT AT 8,14;"                 " 
 7075 PRINT AT 8,14;"IN ";
 7080 GOSUB 8500
 7100 PRINT " SECTOR"
 7120 PRINT AT 12,0;
 7490 RETURN 
 7500 LET R=INT (RND*5)
 7520 IF R=0 THEN PRINT "SPOCK: AS YOU HUMANS SAY,"
 7540 IF R=1 THEN PRINT "SCOTT: ";
 7560 IF R=2 THEN PRINT "LT. UHURA: ";
 7580 IF R=3 THEN PRINT "CHEKOV: ";
 7600 IF R=4 THEN PRINT "SULU: ";
 7900 RETURN 
 7999 STOP 
 8000 REM PRINT OUT
 8002 FAST 
 8005 PRINT AT 0,0;
 8010 PRINT "  1234567890"
 8020 FOR Q=1 TO 10
 8025 PRINT AT Q,13;"@@";AT Q,13;" "
 8030 IF Q<10 THEN PRINT Q;" ";
 8035 IF Q=10 THEN PRINT Q;
 8040 FOR P=1 TO 10
 8060 IF B(Q,P)=0 THEN PRINT "% ";
 8080 IF B(Q,P)=2 THEN PRINT "%$";
 8100 IF B(Q,P)=3 THEN PRINT "%X";
 8120 IF B(Q,P)=4 THEN PRINT "%*";
 8160 NEXT P
 8200 NEXT Q
 8210 PRINT 
 8220 PRINT AT 4,15;"N"
 8221 PRINT AT 5,15;"+"
 8222 PRINT AT 5,14;"W";AT 5,16;"E"
 8223 PRINT AT 6,15;"S"
 8225 SLOW 
 8490 RETURN 
 8500 REM SECTOR
 8520 LET Q=B*C
 8540 IF Q<10 THEN PRINT "ANTARES";
 8560 IF Q>9 AND Q<20 THEN PRINT "RIGEL";
 8580 IF Q>19 AND Q<30 THEN PRINT "PROCYON";
 8600 IF Q>29 AND Q<40 THEN PRINT "VEGA";
 8620 IF Q>39 AND Q<50 THEN PRINT "CANOPUS";
 8640 IF Q>49 AND Q<60 THEN PRINT "ALTAIR";
 8660 IF Q>59 AND Q<70 THEN PRINT "SAGITTARIUS";
 8680 IF Q>69 AND Q<80 THEN PRINT "POLLUX";
 8700 IF Q>79 AND Q<90 THEN PRINT "STRIUS";
 8720 IF Q>89 THEN PRINT "BETELGEUSE";
 8740 RETURN 
 8999 STOP 
 9000 DIM A(10,10)
 9020 DIM B(10,10)
 9060 FOR A=1 TO 20
 9080 LET X=INT (RND*10+1)
 9100 LET Y=INT (RND*10+1)
 9120 LET A(X,Y)=1
 9140 NEXT A
 9160 LET B=5
 9180 LET C=5
 9200 LET A(B,C)=2
 9220 LET B(B,C)=2
 9240 LET AL=0
 9260 LET E=RND
 9280 IF E<.33 THEN LET Z$="BRARKONS "
 9300 IF E>.33 AND E<.66 THEN LET Z$="WRERKTONIONS "
 9320 IF E>.66 THEN LET Z$="POLLUXIANS "
 9340 LET E=1000+2000*RND
 9900 RETURN 
 9910 CLEAR 
 9920 SAVE "1031%6"
 9930 RUN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top