Ferry is a docking simulation game in which the player steers a ferry toward one of three cargo berths and then returns it to a home port. The ferry is represented as a single pixel plotted via PLOT, traveling vertically across the screen from top to bottom and then bottom to top, with the player using keys ‘5’ and ‘8’ to nudge the horizontal position during each pass. Three cargo bays are displayed as block-graphic bars that shorten by one character each time the ferry successfully docks, and the player loses a life when the ferry overshoots all three bays. The program uses BORDER, PAPER, INK, and AT/TAB print controls for colored output. A REM-based instruction screen is displayed via LIST 560 followed by PAUSE 0 before the game starts, exploiting the LIST command to show formatted text without a separate print routine.
Program Structure
The program is organized into a main game loop and a small initialization subroutine. Control flow is managed almost entirely with GO TO rather than structured loops, which is typical for BASIC games of this era.
- Lines 10–20: Call the instruction subroutine and clear the screen.
- Lines 30–120: Set up game variables, life counter (
t), score (x), berth widths (b,c,d), and graphical strings. - Lines 130–270: Main ferry-descent loop — a PLOT-based pixel trajectory from y=160 down to y=2 with player steering.
- Lines 280–370: Return voyage — the ferry travels from y=2 back up to y=160, and a successful docking at the home port (
g≈ 120–123) increments the score. - Lines 380–470: Crash handling — lives decremented, berth widths clamped, game-over check.
- Lines 480–510: End-of-game prompt and replay logic.
- Lines 530–550: Instruction display subroutine using
LIST 560andPAUSE 0. - Lines 570–660: REM lines holding the instruction text displayed by the
LISTtrick.
Instruction Display Technique
The subroutine at line 530 calls LIST 560, which causes the BASIC editor to scroll to and display the REM statements beginning at line 570. This is a well-known Spectrum BASIC trick to present formatted text to the player without writing a dedicated PRINT routine. PAUSE 0 at line 540 then waits for a keypress before RETURN drops back into the main program. Note that line 530 lists from 560 but the first meaningful REM is at 570, so line 560 is absent — a minor anomaly that doesn’t affect functionality.
Ferry Movement Model
The ferry is rendered as a single pixel using PLOT. On the outbound trip (lines 180–220), a FOR loop decrements z from 160 to 2 (top of play area to bottom), plotting one pixel per iteration at horizontal position e. The player presses ‘5’ to decrement e or ‘8’ to increment it, giving proportional steering. The return trip (lines 290–330) mirrors this, with a separate horizontal variable g.
Collision Detection
Docking is checked by comparing the final horizontal pixel coordinate against hard-coded ranges for each berth. The three cargo berths are at approximately x=24–27, x=104–107, and x=184–187. The home port is at approximately x=120–123. These ranges are narrow (four pixels wide), making precise docking a genuine challenge.
| Berth | Variable | X range (pixels) |
|---|---|---|
| Left cargo | b | 24–27 |
| Centre cargo | c | 104–107 |
| Right cargo | d | 184–187 |
| Home port | g | 120–123 |
Berth Width as Progress Indicator
Each cargo berth is displayed as a substring of b$, c$, or d$ (each initialized to four block characters) using a slice expression such as b$( TO b) at line 160. Each successful docking decrements the corresponding counter (b, c, or d), visually shrinking the berth graphic and making subsequent dockings progressively harder. When all three reach zero and lives remain, the round resets via line 130’s condition check.
Life and Crash Handling
The player starts with t=2 lives (incremented to 3 at line 50, so effectively three lives). A crash at any berth triggers line 410 onward: a “CRASH” message is printed, t is decremented, and the game either restarts the round or ends. Lines 380–400 clamp berth variables that went to -1 back to 0, preventing negative slice expressions which would cause a BASIC error.
Notable Bugs and Anomalies
- Line 530 calls
LIST 560, but line 560 does not exist in the listing. The LIST command will display from the next available line (570 onward), which is the intended behavior but is slightly imprecise. - The
INPUTat line 480 followed by the checkIF q$="" THEN GO TO 490at line 490 creates an explicit loop to reject an empty response, but this also means pressing Enter with no input loops forever rather than defaulting to “no.” - The random starting x-position (
eandg) is recalculated each round (lines 170 and 280), so the player cannot predict the ferry’s starting column. - Line 520 (
SAVE "ferry" LINE 10) is reachable by direct execution but is placed outside the normal flow, serving as a developer utility line.
Key Variables
| Variable | Purpose |
|---|---|
t | Lives remaining |
x | Score (successful return voyages) |
b, c, d | Width of each cargo berth (0–4) |
e | Ferry horizontal position (outbound) |
g | Ferry horizontal position (return) |
f$ | Block graphic marker for berth/port positions |
b$, c$, d$ | Block graphic strings representing berth width |
z, y | Loop counters for vertical pixel plotting |
Source Code
1 REM Adapted from 1982 ZX Computing ?month for the ZX81 by D.J. Currie
10 GO SUB 530
20 CLS
30 BORDER 1:PAPER 1:INK 6:CLS
40 LET t=2:LET x=0
50 LET t=t+1:LET g=100
60 LET b=4:LET c=b:LET d=c
70 LET f$="▗"
80 LET e=100
90 LET b$="████"
100 LET c$=b$
110 LET d$=b$
120 CLS
130 IF b=0 AND c=0 AND d=0 AND t>0 THEN GO TO 50
140 PRINT INK 4; TAB 0;t; TAB 14;"▌█"; TAB 25;x
150 PRINT INK 3; AT 1,15;f$; AT 20,3;f$; AT 20,13;f$; AT 20,23;f$
160 PRINT INK 4; AT 21,3;b$( TO b); AT 21,13;c$( TO c); AT 21,23;d$( TO d)
170 LET e= INT (RND*200)+1
180 FOR z=160 TO 2 STEP -1
190 IF INKEY$="5" THEN LET e=e-1
200 IF INKEY$="8" THEN LET e=e+1
210 PLOT INK 4;e,z
220 NEXT z
230 IF e=24 OR e=25 OR e=26 OR e=27 THEN LET b=b-1:GO TO 280
240 IF e=104 OR e=105 OR e=106 OR e=107 THEN LET c=c-1:GO TO 280
250 IF e=184 OR e=185 OR e=186 OR e=187 THEN LET d=d-1:GO TO 280
260 IF b=-1 OR c=-1 OR d=-1 THEN GO TO 380
270 GO TO 410
280 LET g= INT (RND*200)+1
290 FOR y=2 TO 160
300 IF INKEY$="5" THEN LET g=g-1
310 IF INKEY$="8" THEN LET g=g+1
320 PLOT INK 4;g,y
330 NEXT y
340 IF g=120 OR g=121 OR g=122 OR g=123 THEN GO TO 360
350 GO TO 410
360 LET x=x+1
370 GO TO 120
380 IF b=-1 THEN LET b=0
390 IF c=-1 THEN LET c=0
400 IF d=-1 THEN LET d=0
410 PRINT AT 10,16;"CRASH"
420 LET t=t-1
430 PAUSE 50
440 IF t=0 THEN CLS
450 IF t=0 THEN PRINT "Game ended. Score: ";x
460 IF t=0 THEN GO TO 480
470 GO TO 120
480 INPUT "Want to play again? ";q$
490 IF q$="" THEN GO TO 490
500 IF q$(1)="y" OR q$(1)="Y" THEN RUN
510 STOP
520 SAVE "ferry" LINE 10
530 LIST 560
540 PAUSE 0
550 RETURN
570 REM ------- FERRY -----------
580 REM Adapted from 1982 ZX Computing ?month for the ZX81 by D.J. Currie
610 REM Use cursor keys '5' and '8' to accurately dock your ferry and bring back cargo to your home port without crashing.
660 REM To begin press any keyNote: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
