Roller-Ball is a ten-round carnival-style ball-rolling game where the player predicts a target position (1–100) and watches a ball animate up the screen toward a row of scoring zones. Each round, the ball’s horizontal drift is calculated using the formula C = C + D/F, where D is the player’s chosen number and F is a randomised divisor that changes slightly each roll, making the outcome unpredictable. The animated ball cycles through ASCII characters CHR$(44) to CHR$(61) as it travels up 18 rows, erasing its previous position each step. Scoring zones are checked after animation: landing in the central band awards 50 points, intermediate zones 9 points, and the edges 1 point, with a “WILD BALL” message if the ball drifts off-screen past column 31.
Program Analysis
Program Structure
The program is a short single-file game running from line 10 to line 320, with the main game loop spanning lines 40–280 (FOR G=1 TO 10). Lines 300–320 form a save/restart block that is never reached during normal play (line 290 is STOP), consistent with the common idiom of appending auto-save and auto-run lines after the main logic.
- Lines 10–30: Title display and initialisation of cumulative score (
H=3) and the randomised divisorF. - Lines 40–110: Per-roll setup — prompt, last-roll display, and validated
INPUT D. - Lines 120–210: Ball animation loop (
FOR E=1 TO 18) with horizontal drift. - Lines 220–280: Scoring evaluation, cumulative total display, and loop continuation.
Initialisation and Randomised Physics
The divisor F is seeded at line 30 as F = 10*(RND*5)+1, giving a value in the range (1, 51]. Each subsequent roll adds a small random increment at line 60 (F = F+3*RND), so F drifts upward over the game, meaning the same player choice D will produce a shorter horizontal travel in later rounds — a subtle difficulty mechanic. The cumulative score H is initialised to 3 rather than 0, which gives the player a small head-start but also means the total displayed from roll 2 onward is slightly inflated.
Animation Loop
The inner loop (lines 130–210) iterates E from 1 to 18, printing the ball character CHR$(43+E) — ranging from CHR$(44) (comma) to CHR$(61) (equals sign) — at row 18-E, column C. This gives the appearance of the ball travelling upward while changing shape. The previous ball position is erased at line 170 by printing a space, provided E<18. The background “scoreboard” graphic at line 140 uses inverse-video characters (the % escapes) and is reprinted each frame, which serves as the static lane display.
Horizontal Drift Calculation
Column position accumulates as C = C + D/F on each animation step (line 180). Since the loop runs 18 times, the total horizontal displacement is approximately 18 * D / F. With F in the range roughly 1–65 and D from 1–100, this can place the ball anywhere from near column 1 to well past column 31. If C exceeds 31, the “WILD BALL” message is shown and C is reset to 1 (lines 190–200), preventing an out-of-range PRINT AT error.
Scoring Logic
After the animation, the final column C is evaluated in three consecutive IF statements. The precedence of AND over OR in Sinclair BASIC is critical to how these compound conditions resolve:
| Lines | Condition (approximate) | Score K |
|---|---|---|
| 220 | Outside all better zones (edges/gaps) | 1 |
| 230 | Columns 6–9, 16–18, or 23–25 | 9 |
| 240 | Columns 19–22 | 50 |
Note that K is never initialised before the loop, so on the very first roll it will hold whatever value it had at program start (typically 0 or undefined). This is a latent bug: if none of the three conditions fire (e.g. after a WILD BALL reset to C=1), K retains its previous value and the wrong score is awarded.
Notable Techniques and Idioms
- The scoreboard row at line 140 is redrawn inside the animation loop using
PRINT AT 0,0, keeping the lane markers visible while the ball moves — a simple double-draw approach without any screen-save mechanism. - Line 110 uses a combined range check (
IF D<1 OR D>100 THEN GOTO 100) to enforce valid input, looping back to theINPUTstatement directly. - The variable
Cis reset to 1 at line 90 each roll, ensuring the ball always starts at the left edge regardless of where the previous roll ended. - Line 270 suppresses the cumulative total display on the first roll (
IF G>1), since with only one roll completed the “total from 1 roll” display would be redundant. Similarly, line 80 skips the last-roll reminder on the first iteration. - The
SAVE "1027%1"at line 310 uses an inverse-video digit in the filename as an auto-run flag, a standard ZX81/TS1000 technique.
Bugs and Anomalies
- Uninitialised
K: VariableKis never set before entering the game loop. On round 1, if the ball lands in the zone assigned at line 220 (score 1), this works correctly since line 220 always fires for edge columns. However, the ordering of lines 220–240 means all three may execute in sequence, with each overwritingK— the last matching condition wins. This is likely intentional (higher zones take priority), but is fragile. - Missing line 160: The loop increments from line 150 to 170, skipping line number 160. This is harmless but unusual — possibly a deleted debugging line.
- Score initialised to 3:
H=3at line 20 means the running total is always 3 points higher than the sum of earned scores, which is never explained to the player.
Content
Source Code
10 PRINT TAB 9;"ROLLER-BALL"
20 LET H=3
30 LET F=10*(RND*5)+1
40 FOR G=1 TO 10
50 PRINT "THIS IS ROLL NUMBER ";G
60 LET F=F+3*RND
70 PRINT AT 11,0;"WHERE WILL YOU ROLL(1 TO 100)?"
80 IF G>1 THEN PRINT AT 18,8;"LAST ROLL WAS TO ";D
90 LET C=1
100 INPUT D
110 IF D<1 OR D>100 THEN GOTO 100
120 CLS
130 FOR E=1 TO 18
140 PRINT AT 0,0;"%1%1%1%1%1%?%?%9%?%?%1%1%1%1%?%?%?%?%*%*%*%?%?%?%?%1%1%1%1%1%1"
150 PRINT AT 18-E,C;CHR$ (43+E)
170 IF E<18 THEN PRINT AT 18-E,C;" "
180 LET C=C+D/F
190 IF C>31 THEN PRINT AT 13,12;"% %W%I%L%D% %B%A%L%L% "
200 IF C>31 THEN LET C=1
210 NEXT E
220 IF C<6 OR C>9 AND C<16 OR C>25 THEN LET K=1
230 IF C>5 AND C<10 OR C>15 AND C<19 OR C>22 AND C<26 THEN LET K=9
240 IF C>18 AND C<23 THEN LET K=50
250 PRINT "YOU SCORED ";K
260 LET H=H+K
270 IF G>1 THEN PRINT "TOTAL SCORE: ";H;" FROM ";G;" ROLLS"
280 NEXT G
290 STOP
300 CLEAR
310 SAVE "1027%1"
320 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
