ferry

Developer(s): D. J. Currie
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Game

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.

  1. Lines 10–20: Call the instruction subroutine and clear the screen.
  2. Lines 30–120: Set up game variables, life counter (t), score (x), berth widths (b, c, d), and graphical strings.
  3. Lines 130–270: Main ferry-descent loop — a PLOT-based pixel trajectory from y=160 down to y=2 with player steering.
  4. 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.
  5. Lines 380–470: Crash handling — lives decremented, berth widths clamped, game-over check.
  6. Lines 480–510: End-of-game prompt and replay logic.
  7. Lines 530–550: Instruction display subroutine using LIST 560 and PAUSE 0.
  8. Lines 570–660: REM lines holding the instruction text displayed by the LIST trick.

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.

BerthVariableX range (pixels)
Left cargob24–27
Centre cargoc104–107
Right cargod184–187
Home portg120–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 INPUT at line 480 followed by the check IF q$="" THEN GO TO 490 at 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 (e and g) 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

VariablePurpose
tLives remaining
xScore (successful return voyages)
b, c, dWidth of each cargo berth (0–4)
eFerry horizontal position (outbound)
gFerry horizontal position (return)
f$Block graphic marker for berth/port positions
b$, c$, d$Block graphic strings representing berth width
z, yLoop counters for vertical pixel plotting

Image Gallery

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 key

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.