--- title: "Ships Attack" id: 55729 type: "computer_media" slug: "ships-attack" url: "http://localhost/computer_media/ships-attack/" markdown_url: "http://localhost/computer_media/ships-attack.md" published_at: "2024-07-05T00:18:47+00:00" modified_at: "2026-03-30T21:45:19+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/07/SCR-20240704-ohcd.png" excerpt: "Four color-coded bombs rain down at ever-increasing speed — dodge them all with just two keys and watch the difficulty suddenly double at 25 points." 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: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 55711 title: "ISTUG Public Domain Library 8" type: "computer_media" url: "http://localhost/computer_media/istug-public-domain-library-8/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Ship%20Attack%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/07/SCR-20240704-ohcd.png" - url: "http://localhost/wp-content/uploads/2024/07/SCR-20240704-ohaw.png" media_type_tags: "Game" --- Ships Attack is a dodge-and-survive game in which the player moves a ship left and right along row 20 to avoid bombs falling from the top of the screen. Four bombs descend simultaneously, each tracked by parallel arrays b() and c() for row and column positions, and each rendered in a different INK color (1–4) to distinguish them visually. When 25 bombs have been successfully dodged, the variable s increments from 1 to 2, doubling the falling speed. Collision detection uses a simple arithmetic range check on the difference between bomb column c(i) and ship column v. The ship graphic is built from Spectrum block graphic characters stored in the string variable v$. *** ## Program Analysis ### Program Structure The program is organized into a main loop and a single initialization subroutine. Line 10 displays the title screen; line 15 shows instructions and waits for a keypress using `PAUSE NOT PI` (equivalent to `PAUSE 0`). Line 20 calls the initialization subroutine at line 200, after which the main game loop runs from lines 30–170. 1. **Lines 10–15:** Title and instructions screen. 2. **Lines 20–170:** Main game loop — erase old positions, read input, move player, move bombs, draw bombs, check collisions. 3. **Lines 199–270:** Initialization subroutine — sets paper color, defines graphic strings, initializes variables and arrays, seeds bomb positions from DATA. 4. **Line 280:** DATA for initial bomb row/column positions. ### Variable and Array Usage | Variable | Purpose | | --- | --- | | `v` | Player ship column position (starts at 13) | | `v$` | Ship graphic string (block graphics) | | `s$` | Bomb graphic string (block graphics) | | `s` | Bomb fall speed (1 normally, 2 after 25 points) | | `p` | Points scored (bombs that reached row 20 safely) | | `b(4)` | Row position of each bomb | | `c(4)` | Column position of each bomb | | `i` | Loop index for bomb processing | ### Key BASIC Idioms Player movement on line 40 uses a compact boolean arithmetic idiom common in Spectrum BASIC: `LET v=v+(INKEY$="8" AND v<23)-(INKEY$="5" AND v>3)`. Boolean expressions evaluate to 1 (true) or 0 (false), so this single statement both increments and decrements `v` with built-in boundary clamping — no IF statements needed. The wait for a keypress on line 15 uses `PAUSE NOT PI`. Since `PI` is non-zero, `NOT PI` evaluates to 0, making this equivalent to `PAUSE 0`, which pauses indefinitely until a key is pressed — a common idiomatic shorthand. ### Bomb Mechanics Each bomb is tracked as an index into the parallel arrays `b()` (row) and `c()` (column). On each pass through the loop, line 70 checks whether a bomb has reached or passed row 20. If so (lines 80–90), the bomb is recycled: reset to row 4 with a new random column near the player (`v-3+INT(RND*11)`), and the score increments. Otherwise (line 120), the bomb advances by `s` rows per frame. The speed variable `s` starts at 1 and jumps to 2 at line 100 when `p=25`, permanently doubling the descent rate for the rest of the game. ### Collision Detection Collision is checked on line 150 only when a bomb has reached row 20 (`b(i)<20` is false). The condition `(c(i)-v<5 AND c(i)-v>0)` tests whether the bomb column falls within a 4-column window to the right of the ship column. This is a simple but asymmetric check: it only detects hits when the bomb is 1–4 columns to the right of `v`, meaning bombs arriving to the left of center may not always trigger a collision as expected. On a hit, a two-second beep plays, the screen is reset, and the game restarts from line 10. ### Graphics Both the ship and bombs use Spectrum block graphic characters embedded directly in string variables. The ship string `v$` (line 210) is a multi-character pattern using `▖`, `▄`, and `▘` block elements forming a small vessel silhouette. The bomb string `s$` (line 220) uses a single `▖` block character. Each bomb is printed with `INK i` where `i` is 1–4, giving each bomb a distinct color. ### Notable Anomalies - The erase loop at line 30 prints a space at the current bomb position before movement, but since bombs move by up to 2 rows per frame at higher speed, a one-row erase may leave ghost characters on screen at speed 2. - The collision check on line 150 is asymmetric: it only detects bombs landing 1–4 columns *to the right* of `v`. Bombs landing at `c(i)=v` or to the left of `v` are not flagged as hits. - The scoring increments for every bomb that passes row 20 safely (line 90), but the reset column calculation `v-3+INT(RND*11)` is relative to the player’s current position, meaning bombs always respawn near the player rather than at a random screen column. - Lines 30 and 40 both call `INKEY$` in separate statements within a tight loop but without any intervening pause; this means input is sampled on every iteration without buffering, which is standard but can make very fast key taps easy to miss. ## Source Code ``` 10 CLS : PRINT ''TAB 10;"SHIPS ATTACK" 15 PRINT '''"USE 5 KEY TO MOVE SHIP TO LEFT AND 8 KEY TO MOVE SHIP TO RIGHT .. THIS WILL AVOID THE BOMBS AND BUILD UP YOUR SCORE."'''''"Press any key when ready": PAUSE NOT PI 20 GO SUB 200 30 FOR i=1 TO 4: PRINT AT b(i),c(i);" ";: NEXT i 40 LET v=v+(INKEY$="8" AND v<23)-(INKEY$="5" AND v>3) 50 PRINT AT 20,v; INK 6;v$; 60 FOR i=1 TO 4 70 IF b(i)<20 THEN GO TO 120 80 LET b(i)=4: LET c(i)=v-3+INT (RND*11) 90 LET p=p+1: PRINT AT 0,8;p; 100 IF p=25 THEN LET s=2 110 GO TO 130 120 LET b(i)=b(i)+s 130 PRINT AT b(i),c(i); INK i;s$; 140 IF b(i)<20 THEN GO TO 160 150 IF (c(i)-v<5 AND c(i)-v>0) THEN BEEP 2,20: INK 0: PAPER 7: CLS : GO TO 10 160 NEXT i 170 GO TO 30 199 REM init. 200 PAPER 5: CLS 210 LET v$=" \'.\..\..\.' " 220 LET s$="\.." 230 LET s=1: LET p=0: LET v=13 240 DIM b(4): DIM c(4) 250 FOR i=1 TO 4: READ b(i): READ c(i): NEXT i 260 PRINT AT 0,0;"POINTS: 0"; 270 RETURN 280 DATA 16,4,12,8,4,16,8,20 9999 SAVE "S. Attack" LINE 1 ```