This program implements a scrolling asteroid-field dodge game in which the player steers a spacecraft left and right using keys 5 and 8, and can deploy an energy screen (key 0) to destroy nearby asteroids. The spacecraft is rendered using a set of 21 User-Defined Graphics (UDGs “a” through “u”), whose bitmaps are loaded at startup via a DATA/POKE USR routine starting at line 9000. Collision detection is handled entirely through the ATTR function, checking the paper/ink color code 15 (white on white) at the three cells the ship occupies in row 8. The game tracks score as elapsed ticks, maintains a persistent best-ever score in variable e, and includes a two-letter initials entry for a Hall of Fame when the best score is beaten; a computed GO TO expression at line 405 branches to play-again, save, or quit paths.
Program Analysis
Program Structure
The program is divided into four logical phases:
- Introduction (line 1): Displays a flashing title, instructions, and waits for key 8 to start.
- Game loop (lines 4–100): Initializes variables, then repeatedly reads input, moves the ship, checks for collisions via
ATTR, draws the ship and scrolling asteroids, and loops back to line 50. - Death sequence and scoring (lines 400–460): Plays a three-frame explosion animation, calculates the score, handles the Hall of Fame entry, and offers play-again/save/quit.
- UDG loader subroutine (lines 9000–9270): RESTOREs to line 9070 and POKEs bitmap data for 21 UDGs (“a”–”u”) via
POKE USR p$+n,a.
User-Defined Graphics
Twenty-one UDGs are defined, covering a rich set of spacecraft parts, asteroid fragments, and explosion frames. The loader at lines 9020–9060 iterates over each character label in p$ and writes eight bytes of bitmap data. In the game loop at line 100, CHR$ (RND*11+144) selects a random UDG from the range 144–154 (UDGs “a”–”k”) to render asteroids scrolling onto row 21. The spacecraft body and wings are drawn with UDGs \s/\t (row 7) and \p/\q/\r (row 8), while the explosion uses UDGs \n, \o, \u etc.
Collision Detection via ATTR
Rather than tracking asteroid positions in an array, collision detection exploits the display attribute system. Asteroids are printed in INK 7 on PAPER 1 (blue background), giving an attribute byte of 15. The ship occupies columns l, l+1, and l+2 on row 8. Lines 64–66 check:
ATTR (8,l)=15orATTR (8,l+2)=15→ wing hit,p=p-1ATTR (8,l+1)=15→ body hit,p=p-2
This approach is compact but means any cell with attribute 15 registers as a hit, tying game logic directly to the display state.
Energy Screen Mechanic
Pressing key 0 costs one energy unit (f=f-1) and prints a three-cell energy graphic in INK 6 at ship row 8 via PRINT AT 8,l; INK 6;"\p\q\r". Because the energy screen is rendered in INK 6 (yellow) rather than INK 7, it overwrites any asteroid attribute at that cell, preventing a collision detection hit on the next iteration. The energy check appears twice — at line 50 (integrated into the movement/scroll path) and at line 62 — to handle both the normal and post-screen-flash code paths.
Scrolling Asteroid Field
Asteroids are produced by printing two random UDG characters at random column positions on row 21 each tick (line 100). The display naturally scrolls upward because the PRINT at the end of line 100 causes the screen to scroll when the cursor reaches row 21. This is a classic Sinclair BASIC scroll-by-printing idiom: AT 21,31;"" positions the cursor at the last cell; the following bare PRINT triggers the scroll, pushing all rows up by one.
Score and Hall of Fame
Score is measured as the tick counter t minus 13 (a calibration offset for setup ticks). Variable b holds the best score for the current session and e the best-ever score, both persisting across plays via GO TO 4 (not GO TO 1), which skips the initialization of b and e at line 1. When e is beaten, the player enters two-letter initials: a loop at line 403 reads INKEY$ twice with PAUSE 0 as a keypress-wait idiom, appending each letter plus a period separator into n$.
Computed GO TO
Line 405 ends with a computed branch:
GO TO (5 AND INKEY$="p")+(430 AND INKEY$="s")+(450 AND INKEY$="f")
Because PAUSE 0 precedes it, exactly one of INKEY$ comparisons will be true (evaluating to 1), so the expression yields 5, 430, or 450. A value of 0 (no matching key) would jump to a non-existent line 0, but in practice PAUSE 0 ensures a key is held when execution reaches the GO TO.
Variable Summary
| Variable | Purpose |
|---|---|
t | Tick counter (raw score) |
p | Hit points remaining (starts at 5) |
l | Current ship column position |
l1 | Previous ship column (for erasing) |
f | Energy screen units remaining (starts at 6) |
b | Best score this session |
e | Best-ever score across sessions |
n$ | Player initials for Hall of Fame |
m, n | Loop counters (UDG loader, animation, etc.) |
p$ | UDG character label in loader |
a | Single bitmap byte in loader |
Notable Anomalies
POKE 23692,255at line 50 resets the scroll counter to suppress the “scroll?” prompt, a standard Sinclair BASIC technique for uninterrupted scrolling programs.- Line 9065 (
BORDER 1: PAPER 1: CLS : INK 7: GO TO 2) is unreachable dead code — there is no line 2 and nothing branches to 9065. - The energy variable
fis initialized to 6 at line 10 despite the instructions stating “5 energy units.” With each activation decrementing before the check (f=f-1: IF f>0), activations 1–5 succeed and activation 6 fails, so the player effectively gets exactly 5 uses — the off-by-one is intentional. - Lines 9998–9999 (
SAVE/VERIFY) are developer utilities left in the listing and are only reachable if execution falls through from the UDG loader, which never happens during normal play.
Content
Source Code
1 BORDER 1: PAPER 1: CLS : INK 7: PRINT AT 0,8; FLASH 1;"ASTEROIDS AHEAD!": PAUSE 100: PRINT FLASH 0;''" Steer your spacecraft through the swarm of asteroids"''"Press 5 for Left or 8 for Right."''"Press 0 to activate your craft'sEnergy Screen to destroy asteroids you cannot avoid"''"But BEWARE - the Screen has onlya short range and you have only 5 energy units left"''" Your craft will disintegrate after 5 hits (wings=1,body=2)"''" HOW LONG CAN YOU SURVIVE?": GO SUB 9000: PRINT '" Press 8 to start": PAUSE 0: LET b=0
4 LET e=0
10 INK 0: CLS : LET t=0: LET p=5: LET l=15: LET l1=l: LET f=6
50 POKE 23692,255: LET l=l+(INKEY$="8" AND l<29)-(INKEY$="5" AND l>0): IF INKEY$="0" THEN LET f=f-1: IF f>0 THEN PRINT AT 8,l; INK 6;"\p\q\r": GO TO 64
62 IF INKEY$="0" THEN LET f=f-1: IF f>0 THEN PRINT AT 8,l; INK 6;"\p\q\r"
64 IF ATTR (8,l+2)=15 OR ATTR (8,l)=15 THEN LET p=p-1
66 IF ATTR (8,l+1)=15 THEN LET p=p-2
67 IF p<1 THEN GO TO 400
100 PRINT AT 7,l1;" ";AT 21,31;"": PRINT : PRINT AT 7,l; INK 6;"\s"; INVERSE 1;p; INVERSE 0;"\t": LET t=t+1: LET l1=l: PRINT AT 21,RND*31; INK 7;CHR$ (RND*11+144);AT 21,RND*31;CHR$ (RND*11+144): GO TO 50
400 FOR n=1 TO 3: PRINT AT 6,l1;" ";AT 7,l1; INK 2;" \m ";AT 8,l1;" ": PAUSE 2: PRINT AT 6,l1; INK 6;"\o\q\u";AT 7,l1;"\n \n";AT 8,l1;"\p\q\r": PAUSE 2: NEXT n: FOR n=6 TO 8: PRINT AT n,l1;" ": NEXT n
402 CLS : IF b<t-13 THEN LET b=t-13
403 INK 7: IF e<b THEN LET e=b: PRINT AT 6,0;"You have beaten the best ever score. Enter the HALL OF FAME"''"Press the two letters of your initials": LET n$="": FOR n=1 TO 2: PAUSE 0: LET n$=n$+INKEY$+".": NEXT n: CLS
405 PRINT ;" Score=";t-13,"Best Score=";b''" Best ever Score=";: PRINT FLASH 1;e;" by ";n$''': FOR n=1 TO 150: NEXT n: PRINT FLASH 0;" Press P to play again"''" s to save"''" f to finish": PAUSE 0: GO TO (5 AND INKEY$="p")+(430 AND INKEY$="s")+(450 AND INKEY$="f")
430 SAVE "ASTEROIDS" LINE 1
450 PRINT ''''" Thank you for playing. 'Bye"
460 GO TO 460
9000
9020 RESTORE 9070: FOR m=1 TO 21
9030 READ p$
9040 FOR n=0 TO 7
9050 READ a: POKE USR p$+n,a
9060 NEXT n: NEXT m: RETURN
9065 BORDER 1: PAPER 1: CLS : INK 7: GO TO 2
9070 DATA "a",62,33,255,129,129,65,37,26
9080 DATA "b",112,148,138,65,129,65,37,26
9090 DATA "c",0,0,24,36,36,56,0,0
9100 DATA "d",0,0,48,40,48,32,0,0
9110 DATA "e",0,24,40,40,16,0,0,0
9120 DATA "f",112,136,136,68,40,48,0,0
9130 DATA "g",0,0,0,56,44,16,0,0
9140 DATA "h",0,0,30,18,34,84,232,0
9150 DATA "i",94,177,130,228,34,65,66,60
9160 DATA "j",0,62,65,66,34,17,14,0
9170 DATA "k",96,144,144,116,10,49,65,126
9180 DATA "l",62,65,242,9,247,126,144,88
9190 DATA "m",145,82,16,7,244,8,74,127
9200 DATA "n",100,24,198,0,222,0,24,102
9210 DATA "o",0,4,34,18,1,68,50,0
9220 DATA "p",9,50,68,1,18,34,4,0
9230 DATA "q",0,8,170,42,73,65,137,137
9240 DATA "r",144,76,34,128,72,68,32,0
9250 DATA "s",0,3,15,15,120,200,255,56
9260 DATA "t",0,192,240,240,30,19,255,28
9270 DATA "u",0,32,68,72,128,36,76,144
9998 SAVE "Asteroids" LINE 1: BEEP .4,15
9999 VERIFY ""
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

