--- title: "Alien Gunner" id: 57432 type: "computer_media" slug: "alien-gunner" url: "http://localhost/computer_media/alien-gunner/" markdown_url: "http://localhost/computer_media/alien-gunner.md" published_at: "2024-10-05T13:25:07+00:00" modified_at: "2026-03-30T21:17:57+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/233_AG.png" excerpt: "A 15-shot arcade gallery game uses a computed GOSUB to award row-dependent scores — the higher the alien, the bigger the points prize." 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 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56736 title: "Timex Sinclair Public Domain Library Tape 1005" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1005/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/233_AG.png" media_type_tags: "Game" --- # Alien Gunner “Alien Gunner” is a ZX81/TS1000 shooting gallery game where the player fires a bullet across the screen to hit alien targets displayed at randomised row and column positions. The game uses PLOT/UNPLOT pairs to animate a scanning crosshair along row 2 and a rising bullet, with the player triggering the shot by pressing any key during the scan. Target scoring is determined by a computed GOSUB — `GOSUB (F+2)*100` — dispatching to one of four subroutines at lines 300, 400, 500, or 600 that award 1000, 500, 250, or 100 points respectively, depending on which of the four random rows the alien occupied. A miss flag variable `W` prevents a new alien from being placed until the current one is cleared, and UNPLOT removes a peg from the bottom score-bar for each of the 15 shots in the game loop. *** ## Program Analysis ### Program Structure The program is organised into a main game loop and four small scoring subroutines: 1. **Initialisation (lines 5–45):** Sets up a bottom border of dots using PLOT, initialises score `K` and miss-flag `W`. 2. **Outer shot loop (lines 50–280):** Iterates `Z` from 0 to 14 (15 shots total), placing aliens and handling the scan/fire sequence. 3. **Scanning crosshair (lines 90–140):** Loops `I` from 0 to 63, PLOT/UNPLOT-ing on row 2 to simulate left-to-right movement; pressing any key exits to the fire sequence. 4. **Bullet flight (lines 150–180):** Loops `J` from 2 to 41, PLOT/UNPLOT-ing at column `I` to animate the bullet rising. 5. **Hit/miss resolution (lines 190–280):** Removes a pip from the bottom bar, tests for a hit, branches to scoring or miss handling, and updates the display. 6. **Scoring subroutines (lines 300–610):** Four RETURN-terminated blocks awarding 1000, 500, 250, or 100 points. 7. **End-of-game / save (lines 290, 620–630):** Line 290 jumps to the non-existent line 700 to halt; lines 620–630 handle saving and restarting. ### Computed GOSUB Dispatch The most technically notable idiom is on line 220: `GOSUB (F+2)*100` Because `F` is a random integer in the range 1–4 (the alien’s row), `(F+2)*100` evaluates to 300, 400, 500, or 600, jumping directly to the corresponding scoring subroutine. This is an elegant way to implement a jump table without IF/THEN chains, exploiting the ZX81’s ability to use arbitrary numeric expressions as line-number targets in GOSUB. ### Scoring Table | Row (F) | GOSUB target | Points awarded | | --- | --- | --- | | 1 (highest) | 300 | 1000 | | 2 | 400 | 500 | | 3 | 500 | 250 | | 4 (lowest) | 600 | 100 | ### Miss Flag and Alien Persistence Variable `W` acts as a miss-flag. When a shot misses (lines 205–210), `W` is set to 1 and the outer loop continues without calling line 55’s alien-placement block. Line 55 checks `IF W<>0 THEN GOTO 90`, causing subsequent shots to fire at the same alien until it is hit. `W` is only cleared to 0 at line 225, after a successful hit. This means a missed alien stays on screen and must be hit eventually — though the loop counter still advances, so a persistent miss consumes remaining shots. ### PLOT/UNPLOT Animation All motion — the scanning crosshair and the rising bullet — is achieved with back-to-back PLOT/UNPLOT pairs rather than PRINT AT, keeping the display manipulation at pixel level. The crosshair scans across row 2 (y-coordinate 2 in ZX81 pixel space), and the bullet travels from row 2 up to row 41 along column `I`, the column frozen at the moment the key was pressed. ### Hit Detection Line 200 tests `IF I=2*S OR I=2*S+1`. Because aliens are PRINTed at character column `S-1` and each character is 2 pixels wide, the alien occupies pixel columns `2*(S-1)` through `2*S+1`. The check covers only the two central pixel columns `2*S` and `2*S+1`, making the hit window deliberately narrow (one character wide rather than the full three-character sprite). ### Score Bar Lines 10–30 draw 15 dots at even x-coordinates along y=0 by stepping `I` from 0 to 28 in steps of 2. Line 190 UNPLOTs `(28-2*Z, 0)` on each iteration, removing one pip per shot consumed — a simple graphical ammunition counter that counts down from right to left. ### Notable Techniques - Computed GOSUB as a jump table (`GOSUB (F+2)*100`). - PLOT/UNPLOT pairs for flicker-free single-pixel animation without clearing the whole screen. - Miss-flag variable `W` controlling alien re-placement without a dedicated subroutine. - The alien sprite uses block graphic escapes: `"\..%X\.."` renders a small inverse-video alien shape; on a hit, it is replaced with `"\,,\##\,,"` (an explosion pattern) before being erased. - GOTO 700 at line 290 targets a non-existent line, causing the program to halt cleanly at end of game. ### Potential Bugs and Anomalies - If the player does not press a key before `I` reaches 63, the scan loop exits at line 140 via `GOTO 90`, restarting the scan but *not* advancing `Z`. The shot counter is therefore not consumed on a time-out, which may be intentional as a grace mechanic but is not documented. - The hit check covers only two of the six pixel columns under the three-character sprite, making hits harder than the visual size implies. - Score display at line 270 (`PRINT AT 21,27;K`) is only updated after a successful hit, not after a miss, so the score display is never updated on a miss shot. ## Source Code ``` 5 REM "ALIEN GUNNER" 10 FOR I=0 TO 28 STEP 2 20 PLOT I,0 30 NEXT I 40 LET K=0 45 LET W=0 50 FOR Z=0 TO 14 55 IF W<>0 THEN GOTO 90 60 LET F=INT (RND*4+1) 70 LET S=INT (RND*29+2) 80 PRINT AT F,S-1;"\..%X\.." 90 FOR I=0 TO 63 100 PLOT I,2 110 UNPLOT I,2 120 IF INKEY$<>"" THEN GOTO 150 130 NEXT I 140 GOTO 90 150 FOR J=2 TO 41 160 PLOT I,J 170 UNPLOT I,J 180 NEXT J 190 UNPLOT 28-2*Z,0 200 IF I=2*S OR I=2*S+1 THEN GOTO 220 205 LET W=1 210 GOTO 280 220 GOSUB (F+2)*100 225 LET W=0 230 PRINT AT F,S-1;"\,,\##\,," 240 PAUSE 50 250 PRINT AT F,S-1;" " 260 PAUSE 50 270 PRINT AT 21,27;K 280 NEXT Z 290 GOTO 700 300 LET K=K+1000 350 RETURN 400 LET K=K+500 450 RETURN 500 LET K=K+250 550 RETURN 600 LET K=K+100 610 RETURN 620 SAVE "1023%3" 630 RUN ```