Ships Attack is a dodge-and-survive game in which the player moves a ship left and right along the bottom of the screen to avoid falling bombs. Four bombs descend simultaneously at staggered starting rows, each assigned a different INK color (1–4) for visual distinction. When the score reaches 25 points, the variable `s` increments from 1 to 2, doubling the descent speed of all bombs. Collision detection is handled by checking whether the horizontal distance between a bomb column and the ship position falls within a five-cell window.
Program Structure
The program is divided into two logical sections. Lines 10–15 display the title screen and instructions, then line 20 calls the initialization subroutine at line 200. The main game loop runs from line 30 to line 170, with the subroutine (lines 200–270) and a DATA statement (line 280) sitting below the REM marker at line 199.
| Lines | Role |
|---|---|
| 10–15 | Title screen and instructions |
| 20 | GO SUB to initialization |
| 30 | Erase old bomb sprites |
| 40 | Read keyboard and update ship column v |
| 50 | Draw player ship at row 20 |
| 60–160 | FOR loop updating and drawing each bomb, checking collision |
| 170 | GO TO 30 (main loop back-edge) |
| 200–270 | Initialization subroutine |
| 280 | DATA for initial bomb positions |
Initialization Subroutine
The subroutine at line 200 sets PAPER color 5, clears the screen, defines sprite strings, resets game variables, dimensions the bomb arrays, reads starting row/column pairs from DATA, and prints the score header. Four bombs begin at rows 16, 12, 4, and 8 (columns 4, 8, 16, 20 respectively), giving them staggered vertical positions so they do not all arrive at the player simultaneously.
Sprite Representation
Both the player ship and the bombs are represented as string literals built from block graphics characters. v$ (line 210) is a multi-character ship sprite using block graphic tiles to form a wider visual. s$ (line 220) is the two-character bomb sprite. Each bomb is rendered with INK i where i is the loop index (1–4), giving each bomb a unique color without any extra variables.
Movement and Input
Line 40 uses a compact Boolean arithmetic idiom common in Sinclair BASIC:
LET v=v+(INKEY$="8" AND v<23)-(INKEY$="5" AND v>3)
The relational expressions evaluate to 1 (true) or 0 (false), so the addition and subtraction act as conditional increments/decrements. Boundary checks (v<23 and v>3) are embedded directly in the same expression, preventing the ship from moving off-screen.
Bomb Descent and Speed Increase
Each bomb’s row is stored in b(i) and its column in c(i). On each frame, if a bomb has not yet reached row 20 it is advanced by s rows (line 120). Initially s=1; when the score p reaches 25, line 100 sets s=2, doubling descent speed for all bombs simultaneously. When a bomb passes row 20 it is recycled (line 80): its row resets to 4 and its column is randomized near the current ship position (v-3 + INT(RND*11)), which creates mild homing behavior.
Scoring
A point is awarded each time any bomb is recycled (i.e., successfully dodged), incrementing p and immediately updating the display at line 90. The score is printed at position row 0, column 8 over the pre-printed “POINTS: 0” header established in the subroutine.
Collision Detection
Collision is tested only when a bomb reaches row 20 or beyond (line 140 guards line 150). The check on line 150 is:
IF (c(i)-v<5 AND c(i)-v>0)
This tests a five-column window to the right of the ship’s left edge. Notably, it does not catch cases where c(i)-v is zero or negative beyond the window (e.g., a bomb directly on or to the left of the ship anchor). This means bombs landing exactly on the ship column or slightly left may not trigger a game over, which is a minor collision detection anomaly. On a hit, a BEEP is sounded, colors are reset, and the program restarts at line 10.
Screen Erasure
Rather than clearing the entire screen each frame, line 30 erases only the previous bomb positions by printing a space at each stored b(i), c(i) coordinate before updating them. This avoids flicker from full-screen CLS calls during gameplay and is a standard sprite-erasure technique for this platform.
Notable Idioms
PAUSE NOT PIon line 15 — sincePIis non-zero,NOT PIevaluates to 0, soPAUSE 0waits indefinitely for a keypress.- Using
INK iinside the PRINT statement to color-code each bomb by loop index. - Recycling bombs near the player’s position to maintain game pressure as the player’s score climbs.
Content
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;\{19}\{0}\{19}\{0}\{19}\{0}"POINTS: 0";
270 RETURN
280 DATA 16,4,12,8,4,16,8,20
9999 SAVE "S. Attack"\{17}\{3} LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
