This program is a shoot-the-saucers game in which the player maneuvers a crosshair cursor around the screen and fires at an alien saucer before it descends far enough to trigger a “landing” and ultimately conquer Earth. The saucer is drawn using a custom UDG character (“\p”) defined at line 5000 via DATA and POKEd into USR memory, depicting a classic flying-saucer silhouette with BIN literals. The playing field is rendered entirely with PLOT/DRAW commands that outline runways, city boundaries, and a border before gameplay begins. Difficulty increases dynamically: once the score exceeds 1000, the saucer’s descent rate doubles, and after 1000 it can triple; after ten landings the game ends with an animated block-graphic alien city built line by line using Spectrum block characters. The crosshair is erased and redrawn each frame using PRINT AT with spaces followed by “+” characters, giving smooth movement without flicker-clearing the whole screen.
Program Analysis
Program Structure
The program is organized into several distinct sections accessed via GO SUB:
- Lines 1–9: Variable initialization — crosshair position (
l,k), saucer position (m,n), score, and landing counter. - Line 3:
GO SUB 5000— UDG definition routine. - Line 4:
GO SUB 4000— title screen, instructions, and startup animation. - Lines 10–120: One-time screen drawing using
PLOT/DRAWto lay out the playfield geometry and border. - Lines 125–999: Main game loop — erase crosshair, read keys, move saucer, check collisions, play tones, update display, repeat via
GO TO 125. - Lines 1020–1080: Hit subroutine — explosion effect, score increment, saucer reset.
- Lines 2000–2020: Landing subroutine — increments
lan, ends game after 10 landings, resets saucer. - Lines 4000–4050: Title/instructions screen with coloured text and a starfield animation.
- Lines 5000–5040: UDG loader — reads BIN values into the UDG slot for character
\p. - Lines 7000–7150: Game-over sequence with animated block-graphic city and score display.
- Line 9999:
SAVEline for persistence.
UDG Definition
Lines 5000–5040 define a custom UDG for the saucer sprite. Eight bytes are stored with DATA BIN ... statements and read into USR "\p" (UDG “P”) via POKE in a FOR loop. The bit pattern:
| Byte | BIN Value | Pattern |
|---|---|---|
| 0 | 00000000 | blank |
| 1 | 00011000 | central dot |
| 2 | 01111110 | wide body |
| 3 | 11011011 | hull detail |
| 4 | 11111111 | full width |
| 5 | 01100110 | landing legs |
| 6 | 00000000 | blank |
| 7 | 00000000 | blank |
Note that BIN 0 is used as a shorthand for BIN 00000000, which is valid BASIC syntax on this platform.
Main Game Loop Mechanics
The crosshair is a four-character “+” pattern printed at offsets around (k, l). Each frame, it is first erased by printing spaces (lines 125–128), then movement keys are checked (lines 130–160), then the crosshair is redrawn (lines 200–230). This erase-move-redraw technique avoids clearing the whole screen and preserves the PLOT/DRAW playfield.
Key mapping uses numeric keys typical for this era:
"5"— move left"8"— move right"6"— move down"7"— move up"0"— fire
The saucer’s column n drifts each frame by INT (RND*3)-1 (lines 245–247), clamped to stay between 3 and 29. Its row m is a floating-point variable incremented by 0.2 per frame (line 250); INT m is used for all display and collision checks, giving smooth sub-row descent.
Difficulty Scaling
Line 252 implements a two-stage speed increase. Once score>1000, an additional +0.2 is added to m each frame. A second condition checks m>2000 — which, given m resets to 3 on each new saucer, will never actually be true during normal play. This appears to be a bug: the intended second threshold was likely score>2000.
Firing and Hit Detection
Line 240 checks INKEY$="0". If pressed, it plays a brief four-beep sound, then tests k=INT m AND l=INT n — a simple exact-match collision requiring the crosshair center to align precisely with the saucer’s character cell. On a hit, GO SUB 1000 is called; however, the subroutine actually begins at line 1020. Since GO SUB to a non-existent line jumps to the next higher line, this is intentional behavior. The hit routine prints the saucer UDG at the crosshair position, then overlays a block graphic (\.', i.e., ▞) using OVER 1 for a brief explosion flash.
Audio
Line 248 plays a random-pitch tone every frame using BEEP 0.005,(RND*35)+15, creating a continuous engine-noise effect. The fire sound (line 240) is a short 40-semitone beep repeated four times. The hit sound (line 1030) sweeps from pitch 50 down to 45 in 0.5 steps, producing a descending explosion tone. The game-over sequence (lines 7000–7075) plays five descending single notes as each row of the alien city graphic is revealed.
Game Over — Animated City
Lines 7030–7070 build an alien city using Spectrum block graphics characters (\:: = █, \:. = ▙, \.: = ▟, \: = ▌, \ : = ▐) printed row by row with a BEEP between each row, giving a dramatic construction animation. INK INT 2 at line 7030 contains a subtle bug: INT 2 evaluates to 2 (red), which happens to work, but the expression is redundant — INT of an integer literal is unnecessary.
Notable Idioms and Anomalies
- Line 255 redraws the screen border if
ngoes out of range, guarding against the saucer drifting into the border area overwriting the frame. PRINT AT INT m, INT nis used throughout rather than rounding, causing the saucer to appear to snap to cell positions.- The landing counter variable is declared as
LAN(line 9) but referenced aslan(lines 2000, 2010) — BASIC on this platform treats variable names case-insensitively for numeric variables, so this is not a bug. - Line 4050 uses
GO TO 5instead ofRETURN, bypassing the subroutine return mechanism after the title screen. This works because the title screen is always the last initialization step before the main game setup at line 5. - Line 3005 (
FOR n=0 TO 100: BEEP 0.1,40: NEXT n) defines a long beep loop that is never called by anyGO SUBorGO TOin the program — it is dead code.
Content
Image Gallery
Source Code
1 REM saucers
3 GO SUB 5000
4 GO SUB 4000
5 LET l=16: LET k=11: LET pos=10
6 LET m=3: LET n=INT (RND*26)+2
8 LET score=0
9 LET LAN=0
10 PLOT 0,0: DRAW 97,50
20 PLOT 255,0: DRAW -97,50
30 PLOT 137,50: DRAW 50,-50
40 PLOT 117,50: DRAW -50,-50
50 PLOT 70,50: DRAW -70,-15
60 PLOT 185,50: DRAW 70,-15
70 PLOT 0,50: DRAW 255,0
80 PLOT 127,50: DRAW 0,-50
90 PLOT 0,40: DRAW 255,0
100 PLOT 0,15: DRAW 255,0
110 PLOT 0,14: DRAW 255,0
120 INK 7: PLOT 0,0: DRAW 0,175: DRAW 255,0: DRAW 0,-175: DRAW -255,0
125 PRINT AT k,l-1;" "
126 PRINT AT k,l+1;" "
127 PRINT AT k-1,l;" "
128 PRINT AT k+1,l;" "
130 IF INKEY$="8" AND l<29 THEN LET l=l+1
140 IF INKEY$="5" AND l>2 THEN LET l=l-1
150 IF INKEY$="6" AND k<13 THEN LET k=k+1
160 IF INKEY$="7" AND k>2 THEN LET k=k-1
180 PRINT AT INT m,INT n;" "
200 PRINT AT k,l-1;"+"
210 PRINT AT k-1,l;"+"
220 PRINT AT k+1,l;"+"
230 PRINT AT k,l+1;"+"
240 IF INKEY$="0" THEN FOR t=0 TO 3: BEEP 0.02,40: NEXT t: IF k=INT m AND l=INT n THEN GO SUB 1000
245 LET n=n+INT (RND*3)-1
246 IF n<3 THEN LET n=n+1
247 IF n>29 THEN LET n=n-1
248 BEEP 0.005,(RND*35)+15
250 LET m=m+0.2
252 IF score>1000 THEN LET m=m+0.2: IF m>2000 THEN LET m=m+0.2
255 IF n<1 OR n>31 THEN PLOT 0,0: DRAW 0,175: DRAW 255,0: DRAW 0,-175: DRAW -255,0
260 IF m>15 THEN GO SUB 2000
300 INK INT (RND*7)+2: PRINT AT INT m,INT n;"\p": INK 7
310 PRINT AT 1,1;"SCORE:";score;" "
999 GO TO 125
1020 PRINT AT k,l;"\p": PRINT ; OVER 1;AT k,l;"\.'"
1030 FOR h=50 TO 45 STEP -0.5: BEEP 0.01,h: NEXT h
1040 PRINT AT k,l;" "
1050 LET m=3: LET n=INT (RND*26)+2
1060 LET score=score+100
1080 RETURN
2000 LET lan=lan+1
2010 IF lan>10 THEN GO TO 7000
2015 LET m=3: LET n=INT (RND*26)+2
2020 RETURN
3005 FOR n=0 TO 100: BEEP 0.1,40: NEXT n
4000 PAPER 1: INK 7: BORDER 1: CLS
4010 PRINT AT 0,10; FLASH 1;"SAUCER"; FLASH 0
4020 INK 6: PRINT : PRINT "Save the Earth,the aliens are invading and are trying to buildcities on the Earth.": PRINT : PRINT "Shoot them before they build their cities and conquer EARTH and use you for toothpicks."
4030 INK 7: PRINT : PRINT : PRINT " 5 FOR LEFT": PRINT : PRINT " 8 FOR RIGHT": PRINT : PRINT " 6 FOR DOWN": PRINT : PRINT " 7 FOR UP": PRINT : PRINT " 0 TO FIRE"
4040 PRINT AT 21,1; FLASH 1;"Good Luck.......": FLASH 0
4045 PAUSE 9999
4050 BORDER 0: PAPER 0: INK 6: CLS : FOR n=0 TO 50: BEEP 0.005,(RND*35)+15: INK INT (RND*7)+1: PLOT INT (RND*250)+5,INT (RND*120)+50: NEXT n: INK 4: GO TO 5
5000 DATA BIN 0,BIN 00011000,BIN 01111110,BIN 11011011,BIN 11111111,BIN 01100110,BIN 0,BIN 0
5010 FOR n=0 TO 7: READ j
5030 POKE USR "\p"+n,j: NEXT n
5040 RETURN
7000 BEEP 0.7,1: BEEP 0.5,1: BEEP 1,6
7010 PRINT AT 1,1;"THEY HAVE CONQUERED EARTH"
7020 PRINT AT 2,3;"AND ARE BUILDING THEIR CITY"
7025 PAUSE 100
7030 INK INT 2: PRINT AT 12,10;"\::"
7035 BEEP 0.5,5
7040 PRINT AT 13,9;"\.:\::\:."
7045 BEEP 0.5,4
7050 PRINT AT 14,9;"\: \::\ :"
7055 BEEP 0.5,3
7060 PRINT AT 15,9;"\::\::\::"
7065 BEEP 0.5,2
7070 PRINT AT 16,8;"\.:\::\::\::\:."
7075 BEEP 0.5,1
7076 INK 6
7080 PRINT AT 8,1;"YOU HAVE LOST EARTH, THE "
7090 PRINT AT 9,1;"ALIENS HAVE DOOMED MANKIND"
7100 PRINT AT 10,1;"TO BECOME TOOTH PICKS"
7110 PRINT AT 18,1;"ENTER 'RUN' TO GO BACK INTO "
7120 PRINT AT 19,1;"TIME TO TRY AND SAVE THE"
7130 PRINT AT 20,1;"EARTH AGAIN !!!!"
7140 FLASH 1: PRINT AT 5,1;"YOUR SCORE WAS ";score: FLASH 0
7150 STOP
9999 SAVE "saucers" LINE 1: BEEP 1,32
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.