--- title: "Defense" id: 50611 type: "computer_media" slug: "defense" url: "http://localhost/computer_media/defense/" markdown_url: "http://localhost/computer_media/defense.md" published_at: "2023-06-23T11:26:00+00:00" modified_at: "2026-03-30T21:41:40+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A fast-paced single-alien shooter uses custom UDG graphics, hardware port reads for controls, and a PLOT/DRAW laser beam — how many aliens can you down?" category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Defense%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2023/06/SCR-20260329-pvhy.png" media_type_tags: "Arcade, Game" --- This BASIC program implements a single-alien Space Invaders-style shooter. Three UDG characters (A, B, C) are defined at startup via a DATA block that POKEs pixel patterns directly into UDG memory using USR, creating a player ship, an alien, and an explosion graphic. The player moves a ship along row 1 using keyboard inputs read through IN port addresses (61438, 63486, 65278, 32766), fires a laser represented by a PLOT/DRAW line, and must shoot a descending alien that drifts horizontally with bounded random movement. The game tracks score, hi-score, remaining lives (CO), and laser shots (LA), with a synthesized explosion sound loop using OUT 254 for border color flashing combined with BEEP commands. *** ## Program Analysis ### Program Structure The program is organized into several logical blocks. Lines 1–5 handle initialization: line 1 immediately redirects to line 6 (which doesn’t exist, causing a fall-through to line 2), bootstrapping the UDG setup loop before dropping to the game setup at line 10. Lines 10–80 set up the screen and game state. The main game loop runs from lines 92–170, with subroutines at lines 300–340 (laser fire) and 500–520 (alien landing / life loss). | Lines | Purpose | | --- | --- | | 1–5 | UDG definition via DATA/POKE; STOP halts after setup | | 10–80 | Screen/attribute setup, star field, HUD, game variable init | | 92–170 | Main game loop: alien movement, player movement, collision, laser trigger | | 200–224 | Explosion effect, hi-score update, INPUT display, restart | | 300–340 | Laser beam subroutine: PLOT/DRAW, hit detection, scoring | | 500–520 | Alien reaches bottom: deduct score/life, redraw life bar, loop back | ### UDG Initialization Lines 2–4 define three UDG characters. The loop reads three bytes at a time from the DATA statement — one byte each for UDGs B, A, and C — and POKEs them sequentially into the eight rows of each character using `USR "B"+F`, `USR "A"+F`, and `USR "C"+F` as base addresses offset by loop variable `F` (0–7). UDG B is the alien sprite, UDG A is the player ship, and UDG C is the explosion/hit graphic. Line 1 uses `RUN 6` to jump to a non-existent line, which causes execution to continue from the next available line (line 2) — a well-known BASIC trick to reach setup code without a direct `GO TO`. ### Hardware Port Input for Controls Player movement at line 110 uses `IN` port reads rather than `INKEY$`, which is more responsive in a tight loop. The ports read are the standard ZX Spectrum keyboard half-rows: - `IN 61438` — reads keys including the right-movement key - `IN 63486` — reads keys including the left-movement key - `IN 65278` and `IN 32766` — reads fire keys (line 160) The expression `C+(IN 61438<>255 AND C<31)-(IN 63486<>255 AND C>0)` is a compact idiom that moves the ship position by +1 or -1 while clamping it within the screen bounds (0–31), all in a single assignment. ### Alien Movement The alien descends one row per loop iteration (`I=I-1`, line 131) from row 20 toward row 1. Horizontal drift is computed on line 138 as `ST+INT(RND*3)-1+(3 AND ST<-30)-(3 AND ST>30)`. The boundary correction terms `(3 AND ST<-30)` and `-(3 AND ST>30)` nudge the alien back toward center when it strays near the screen edges, using Boolean-as-integer arithmetic (a characteristic Spectrum BASIC idiom where `AND` with a condition returns 0 or the left-hand value). Note that the boundary check compares against ±30 rather than 0/31, because `ST` can be a column position and the alien uses PRINT AT with potentially negative column values — the PRINT AT statement on this machine wraps or clips at the display edge, so negative columns are tolerated. ### Laser Beam Subroutine (Lines 300–340) The laser is drawn as a vertical line using `PLOT INVERSE 1` at the ship’s pixel X coordinate (`C*8+3`) and then `DRAW INK 5,0,-117` to extend downward 117 pixels from row 159 (near the top of the play area). The beam is erased by redrawing with `DRAW OVER 1`. Hit detection at line 320 checks whether the alien’s current row `I` is between 1 and 16, and whether its column `ST` equals the ship column `C`. A hit awards 100 points, restores one laser shot, triggers a short multi-BEEP flourish, and jumps to line 85 (a non-existent line, falling through to line 90 — another intentional non-existent-line jump to reset the alien). ### Scoring and Life System The game tracks score (`P`), hi-score (`HP`), lives (`CO`, starting at 5), and laser shots (`LA`, starting at 50). When an alien reaches the bottom, line 500 deducts 50 from the score and decrements `CO`. The remaining lives are displayed as a row of UDG B characters on the HUD at line 21. When `CO` reaches 0, line 93 diverts to the end-game sequence at line 210 rather than spawning another alien. The `INPUT` statement at line 222 uses the prompt suppression idiom (`INPUT ;`) to display score and hi-score inline without a cursor prompt. ### Explosion Effect Lines 200–208 produce a multi-frame explosion: a `FOR` loop of 30 iterations sends random values to `OUT 254` (the border/speaker port), flashing the border through random colors, while simultaneous `BEEP` calls with random pitch and duration create a noise burst. This is a common technique for dramatic audio-visual feedback without machine code. ### Notable Bugs and Anomalies - Line 138 checks `ST<-30` and `ST>30` — since columns run 0–31, the left boundary check (`ST<-30`) will never trigger for normal column values, meaning the alien can drift off the left edge. The right boundary check (`ST>30`) is also very permissive. This may be intentional to allow off-screen aliens. - Line 320 references `GO TO 85`, which does not exist; execution continues from line 92, effectively restarting the alien at a new position. This is a deliberate non-existent line jump. - Line 222 uses `INPUT` to display output — the semicolon suppresses the prompt and the expressions in parentheses print variable values without waiting for input, which is a BASIC display trick rather than true input gathering. - `CO=5` is initialized at line 70 but `CO=0` triggers game-over at line 93 only after all lives are spent in the subroutine at line 500; the life display logic at lines 505–508 correctly handles the 1-to-5 range. ## Source Code ``` 1 RUN 6 2 FOR f=0 TO 7: READ N,M,O: POKE USR "B"+F,N: POKE USR "A"+F,M: POKE USR "C"+F,O 3 NEXT F 4 DATA 16,165,165,16,189,24,56,255,165,124,255,90,186,126,90,254,36,165,254,60,24,170,24,165 5 STOP 10 PAPER 0: INK 7: BORDER 1: CLS 20 LET HP=0 50 CLS : FOR F=1 TO 50: PLOT INK RND*3+4,255.5*RND,175.5*RND: NEXT f 60 LET LA=50: LET L=1: PRINT AT 21,0;"ALIENS";TAB 12;"PLAYER";TAB 24;"LASER" 70 LET P=0: LET C=16: LET CO=5 80 GO SUB 504: LET L=0 92 LET I=20: LET ST=INT (RND*20)+5 93 IF CO=0 THEN GO TO 210 95 PRINT AT I,ST;"B" 100 PRINT AT 1,C;" " 110 LET C=C+(IN 61438<>255 AND C<31)-(IN 63486<>255 AND C>0) 115 PRINT AT 1,C;"A" 122 BEEP .005,C 125 PRINT OVER 1;AT I,ST;"B" 131 LET I=I-1 133 IF I=-1 THEN GO TO 500 138 LET ST=ST+INT (RND*3)-1+(3 AND ST<-30)-(3 AND ST>30) 140 PRINT OVER 1;AT I,ST;"B" 143 PRINT AT 21,19;P;" " 145 IF I=1 AND ST=C THEN PRINT AT 1,C;"C": GO TO 200 160 IF (IN 65278<>255 OR IN 32766<>255) AND LA>0 THEN LET LA=LA-1: PRINT AT 21,30;LA: GO SUB 300 165 IF LA<10 THEN PRINT AT 21,3;" " 170 GO TO 100 200 FOR G=1 TO 30 205 OUT 254,RND*255 206 BEEP RND*.05,RND*24-12 208 NEXT G 210 IF P>HP THEN LET HP=P 221 PRINT AT 21,0 222 INPUT ;"YOUR SCORE= ";(P)''"HI'SCORE= ";(HP): PAUSE 500: GO TO 1 224 GO TO 1 300 PLOT INVERSE 1,C*8+3,159 305 DRAW INK 5,0,-117 308 BEEP .05,12 309 PLOT INVERSE 1,C*8+3,159 310 DRAW OVER 1,0,-117 320 IF (I<17 AND I>1) AND ST=C THEN LET P=P+100: LET LA=LA+1: PRINT AT 21,30;LA: BEEP .1,2: PRINT OVER 1;AT I,C;"C": BEEP .2,3: PRINT OVER 1;AT I,C;"C": BEEP .1,4: PRINT AT I,C;" ": GO TO 85 340 RETURN 500 LET P=P-50: LET CO=CO-1 503 PRINT AT 21,19;P;" " 504 FOR F=1 TO 5 505 IF FCO THEN PRINT AT 21,5+F;" " 510 NEXT F: IF L=1 THEN RETURN 520 GO TO 90 ```