Snakewinder is a scrolling catch game where the player moves a paddle (represented by “V”) horizontally to intercept a falling block graphic character. The screen scrolls upward each iteration via the SCROLL command, creating the illusion of continuous downward motion. A three-variable delay chain (B, C, D) tracks the block’s column position across three scroll steps, compensating for the time the target takes to fall to the paddle row. The player scores a point each time the paddle position matches the delayed column, and the game ends after ten misses.
Program Analysis
Program Structure
The program is compact, fitting into a tight main loop between lines 70 and 160, with initialisation at lines 10–60 and an end-game display at line 170. Line 190 is a SAVE with an auto-run flag, and line 200 restarts the program on load.
| Lines | Purpose |
|---|---|
| 10–60 | Initialise all variables to 0; set paddle position P=12 |
| 70 | Choose a random column A for the falling block (10–13) |
| 80 | SCROLL the display up one line |
| 90 | Read keys “8”/”5″ and adjust paddle position P within bounds |
| 100 | Print the falling block at the top and the paddle at row 18 |
| 110–140 | Delay chain: check hit, then shift A→B→C→D |
| 150 | Increment step counter S |
| 160 | Loop back if fewer than 10 misses accumulated in N |
| 170–180 | Game over: print paddle area blanked and final score |
The Three-Step Delay Chain
The most technically interesting aspect is the pipeline used to track where a falling block will land. Each iteration, the block is printed at the top of the visible area. Because the screen is 19 rows tall and SCROLL moves everything up one line, the block takes approximately 18 iterations to reach the paddle at row 18. Rather than store a full array of past positions, the program uses a three-variable shift register:
- Line 70 generates a new column in
A. - Line 140:
B=A— one step old. - Line 130:
C=B— two steps old. - Line 120:
D=C— three steps old. - Line 110: hit is detected when
D=P.
This means the hit check is actually against the column value from three iterations ago, not from when the block visually arrives at the paddle row. The effective catch depth is only three scroll steps, making the game more a test of quick reaction than anticipation.
Scoring Logic — Bug or Design?
The variable N is incremented at line 110 whenever D=P (a hit), and the game ends when N>=10 at line 160. However, N counts hits, not misses — the condition IF N<10 THEN GOTO 70 loops while hits are below 10 and terminates (falls through to line 170) once 10 hits are achieved. The variable S (step counter, not a true score) is displayed as “SCORE”. This is arguably a design quirk: the game ends on 10 successful catches, not on 10 misses as one might initially assume.
Key BASIC Idioms
- Boolean arithmetic in line 90:
P=P+(INKEY$="8" AND P<13)-(INKEY$="5" AND P>10)uses the ZX81/TS1000 convention that a true logical expression evaluates to 1 and false to 0, allowing branchless bounded increment/decrement of the paddle position. - Mass initialisation via LET S=0 and LET x=S: Lines 20–50 set
N,D,C, andBall toS(which is 0), saving token space compared to repeatingLET x=0. - Block graphic in PRINT: The
"\##"in line 100 renders as a solid two-cell block graphic character, visually representing the falling object.
Display and Movement Bounds
The random column A is restricted to the range 10–13 (four possible columns), and the paddle P is also constrained between 10 and 13 by the boolean guards in line 90. This means both the block and the paddle always appear in the same narrow central band of the screen, keeping gameplay focused but very constrained.
Anomalies and Observations
- The “SCORE” displayed at game over is actually
S, the total number of loop iterations, not the number of catches. A player who catches all 10 blocks quickly will have a lower “score” than one who lingers. - The delay chain depth of 3 is far shorter than the 18 rows the block travels visually, so the hit detection window does not correspond to the block visually touching the paddle — there is a perceptible mismatch.
- Line 100 uses
AT 18,Pfor the paddle, meaning it is always printed at the bottom visible row regardless of how many SCROLLs have occurred, which is correct behaviour.
Content
Source Code
5 REM "SNAKEWINDER"
10 LET S=0
20 LET N=S
30 LET D=S
40 LET C=S
50 LET B=S
60 LET P=12
70 LET A=INT (RND*4)+10
80 SCROLL
90 LET P=P+(INKEY$="8" AND P<13)-(INKEY$="5" AND P>10)
100 PRINT TAB A;"\##";AT 18,P;"V"
110 IF D=P THEN LET N=N+1
120 LET D=C
130 LET C=B
140 LET B=A
150 LET S=S+1
160 IF N<10 THEN GOTO 70
170 PRINT AT 18,10;"XXXX";AT 10,8;"SCORE";S
180 STOP
190 SAVE "1023%0"
200 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
