This program implements a simple slalom skiing game on a 64×44 pixel display. A dot travels diagonally down the screen, and the player steers it left or right using keys 5 and 8. Gates are drawn using the string “X X” placed at fixed screen positions with AT coordinates, and a “FINISH” label marks the bottom. The game uses PLOT and UNPLOT to animate the moving dot, with POKE 16437,255 resetting the display file pointer each frame to prevent the system from scrolling. The program halts with STOP when the dot’s Y coordinate reaches zero.
Program Analysis
Program Structure
The program is short and linear, divided into two phases: setup and game loop.
- Lines 10–30: Title display and static course layout — gates drawn with
A$and a “FINISH” label. - Lines 40–50: Initialise pixel coordinates:
A(X position) = 0,B(Y position) = 43. - Lines 60–150: Main game loop — erase, move, read input, draw, check end condition, pause, and loop.
- Lines 160–180: Post-game housekeeping and save/run stub (not reached during normal play).
Display and Course Layout
The course is drawn entirely with PRINT AT statements in line 30. Each gate is the string "X X", stored in A$ to save memory. Gates are placed at rows 4, 8, 11, 17, and 20 at varying column offsets, creating an offset slalom pattern. The word “FINISH” is printed at row 21, column 8.
The pixel graphics use the ZX81’s 64×44 coordinate system (PLOT/UNPLOT), while the gates use the character grid — the two coordinate systems are independent, so gate collision is visual only; there is no programmatic collision detection.
Animation Technique
The moving dot is animated using the classic UNPLOT/PLOT erase-then-draw idiom:
- Line 60:
UNPLOT A,B— erases the dot at its current position. - Lines 70–80: Advance
Aby +1 (rightward) andBby -1 (downward), giving diagonal motion. - Lines 90–100: Apply player input correction to
A. - Line 110:
PLOT A,B— draws the dot at its new position.
Input Handling
Key 5 moves the dot left (A=A-4) and key 8 moves it right (A=A+2). Note the asymmetry: leftward correction is twice as strong as rightward, which may reflect an attempt to counterbalance the inherent rightward drift of the automatic A=A+1 each frame. Both INKEY$ checks are polled independently in lines 90 and 100, so both could theoretically fire in the same frame if somehow both were pressed simultaneously — not an issue on real hardware but a minor logical inconsistency.
POKE 16437 Trick
Line 140 contains POKE 16437,255. Address 16437 on the ZX81 holds the system variable DF_SZ, the number of lines in the lower display area. Poking it to 255 is a common technique to prevent the BASIC interpreter from expanding the lower screen and causing unwanted scrolling or display corruption during animation loops.
Timing
Line 130 uses PAUSE 40 to control game speed. At 50 Hz this gives approximately 0.8 seconds per step — relatively slow, making the game quite forgiving in terms of reaction time.
Termination
Line 120 checks IF B=0 THEN STOP. Because B decrements by exactly 1 each frame from 43, it will reliably reach 0 after 43 iterations, ending the game cleanly.
Potential Issues
- No boundary checking on
A: the player can steer the dot off the left or right edge of the 64-pixel-wide display, which will cause an error. - No collision detection with the “X X” gate markers — passing through a gate is purely cosmetic.
- Lines 160–180 (
CLEAR,SAVE,RUN) are unreachable during normal execution since line 120 STOPs the program; they appear to be development/distribution artifacts.
Content
Source Code
10 PRINT ,"SLALOM COURSE"
20 LET A$="X X"
30 PRINT AT 21,8;"FINISH";AT 4,1;A$;AT 8,12;A$;AT 11,8;A$;AT 17,22;A$;AT 20,17;A$
40 LET A=0
50 LET B=43
60 UNPLOT A,B
70 LET A=A+1
80 LET B=B-1
90 IF INKEY$="5" THEN LET A=A-4
100 IF INKEY$="8" THEN LET A=A+2
110 PLOT A,B
120 IF B=0 THEN STOP
130 PAUSE 40
140 POKE 16437,255
150 GOTO 60
160 CLEAR
170 SAVE "1030%2"
180 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
