--- title: "Galaxian" id: 57423 type: "computer_media" slug: "galaxian" url: "http://localhost/computer_media/galaxian/" markdown_url: "http://localhost/computer_media/galaxian.md" published_at: "2024-10-05T13:14:14+00:00" modified_at: "2026-03-30T21:18:04+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/224_Glxn.png" excerpt: "A one-screen BASIC shoot-'em-up where you dodge descending aliens and fire back — all rendered with block graphics and a surprisingly compact loop structure." 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: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" - 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/224_Glxn.png" media_type_tags: "Arcade, Game" --- # Galaxian This program implements a simple Galaxian-style shoot-’em-up in BASIC. The player controls a cannon (rendered with block graphics) at the bottom of the screen using Z and C keys to move left and right, and M to fire. A single alien descends from the top of the screen, occasionally firing back at the player. The program uses PI/PI as a constant 1 throughout, a common memory-saving idiom, and employs block graphic characters to render the cannon, alien, and laser bolts. The score variable S increments each time an alien is hit, and the game ends—displaying the score and restarting—when the player is destroyed or five aliens are defeated. *** ## Program Analysis ### Program Structure The program is a compact, single-file action game with no subroutines. Execution flows mostly through a main loop centred on lines 19–30, with branching to an end/reset block at lines 36–41. The overall structure is: 1. **Initialisation (lines 5–14):** Sets up speed constant `V=10` (player row), score `S=1` (via `PI/PI`), gun column `G=5`, and alien position `X`, `Y`. 2. **Draw alien row header (lines 15–18):** Prints a row of block-graphic shapes at the top. 3. **Main loop (lines 19–30):** Reads keys, moves the gun, moves the alien down, optionally fires an alien shot, and checks collisions. 4. **Player fire (lines 31–34):** Animates a bullet upward when M is pressed and tests for a hit. 5. **Score/reset block (lines 35–41):** Increments score, clears screen, checks win/death condition, prints score, pauses, and restarts. ### Key Variables | Variable | Role | | --- | --- | | `V` | Player’s fixed row (10) | | `S` | Score / kill count (starts at 1 via `PI/PI`) | | `G` | Gun column position | | `X` | Alien column position | | `Y` | Alien row (counts down from 0 to V) | | `I` | Loop counter / bullet row | ### PI/PI Idiom The constant `1` is never written as a numeric literal; instead `PI/PI` is used throughout (lines 11, 13, 16, 22, 26, 31, 35, 37). On this platform, numeric literals are stored with a 5-byte floating-point value inline in the BASIC line, whereas a variable reference or expression reuses the existing FP value. Using `PI/PI` avoids storing multiple copies of the float value for `1`, saving a small amount of RAM per occurrence. This is a well-known Sinclair BASIC size-optimisation idiom. ### Movement and Control Logic Line 19 updates the gun column in a single expression: `LET G=G+(INKEY$="C")-(INKEY$="Z")*(G>PI/PI)` Boolean expressions evaluate to 1 (true) or 0 (false), so pressing C increments `G` and pressing Z decrements it, but only when `G>1`, preventing movement off the left edge. There is no equivalent right-edge guard, so the gun can move off-screen to the right. Line 21 steers the alien horizontally: `LET X=X+(Y>3)-(Y<4)`. When `Y>3` and `Y<4` are simultaneously true (impossible for integer Y), the alien moves diagonally. For integer Y, if `Y>3` it moves right; if `Y<4` (i.e., Y≤3) it moves left. This creates a simple triangular zigzag as Y increases through 4. ### Block Graphic Rendering All sprites are built from ZX Spectrum block graphics characters: - `"\.'\. "` — the decorative alien row at the top (lines 17–18) - `"\.:\. "` — the player’s cannon sprite (line 20) - `"\'.\' "` — the descending alien sprite (line 23) - `"\ :"` — the laser bolt (lines 27, 32), immediately overwritten with `" "` to animate movement ### Alien Fire Mechanic Line 25 gives the alien a 20% chance each iteration to fire: `IF RND<.8 THEN GOTO 30`. When it does fire (the 20% case), lines 26–28 animate a descending bolt from `Y+1` to `V` using a FOR loop, printing and immediately erasing each row. Line 29 then checks if the bolt’s column `X` matches the gun column `G`; if so, it jumps to line 38 (game over / score display). ### Player Fire Mechanic Line 30 checks for the M key. If pressed, lines 31–33 animate a bolt upward from `V-1` to `1` (step `-PI/PI` = -1). Line 34 tests a hit: `IF G<>X AND G<>X+PI/PI THEN GOTO 19`. The two-column hit test (`G=X` or `G=X+1`) accounts for the alien sprite being two characters wide. ### Win and Death Conditions Line 37 is the critical branching point after a shot event: `IF S<>5 AND (ABS(X-G)>PI/PI OR Y<>V) THEN GOTO 13` This continues the game (spawning a new alien at line 13) if the score is not yet 5 AND the player was not hit (the alien column is not adjacent to the gun, or the alien hasn’t reached the player row). If `S=5`, or if the alien reached row `V` directly above the gun, execution falls through to line 38 to display the score. ### Bugs and Anomalies - **No right-edge guard on gun:** The left-movement guard `(G>PI/PI)` on line 19 protects the left boundary, but there is no equivalent for the right, allowing `G` to exceed the screen width. - **Score starts at 1:**`S` is initialised to `PI/PI` (=1) on line 11, so the first kill gives `S=2` and the win condition `S=5` is reached after four kills, not five. - **Alien fire collision uses alien column, not bullet column:** Line 29 tests `X=G`, where `X` is the alien’s column — which is also where the shot was fired from — so this check is correctly positioned for a vertically falling shot. - **Initial TAB on line 15 is not cleaned up:** Line 15 prints `TAB X` without a following PRINT statement to finish the line, meaning the cursor is left mid-line before the FOR loop on lines 16–18 begins printing. ## Source Code ``` 5 REM "GALAXIAN" 10 LET V=10 11 LET S=PI/PI 12 LET G=5 13 LET X=4+S*3 14 LET Y=PI-PI 15 PRINT TAB X; 16 FOR I=PI/PI TO 5-S 17 PRINT "\.'\. "; 18 NEXT I 19 LET G=G+(INKEY$="C")-(INKEY$="Z")*(G>PI/PI) 20 PRINT AT V,G;" \.:\. ";AT Y,X;" " 21 LET X=X+(Y>3)-(Y<4) 22 LET Y=Y+PI/PI 23 PRINT AT Y,X;"\'.\' " 24 IF Y=V THEN GOTO 36 25 IF RND<.8 THEN GOTO 30 26 FOR I=Y+PI/PI TO V 27 PRINT AT I,X;"\ :";AT I,X;" " 28 NEXT I 29 IF X=G THEN GOTO 38 30 IF INKEY$<>"M" THEN GOTO 19 31 FOR I=V-PI/PI TO PI/PI STEP -PI/PI 32 PRINT AT I,G;"\ :";AT I,G;" " 33 NEXT I 34 IF G<>X AND G<>X+PI/PI THEN GOTO 19 35 LET S=S+PI/PI 36 CLS 37 IF S<>5 AND (ABS (X-G)>PI/PI OR Y<>V) THEN GOTO 13 38 PRINT S 39 PAUSE 50 40 CLS 41 RUN 42 SAVE "1022%4" 43 RUN ```