This program simulates a simplified ten-pin bowling alley game in BASIC. It tracks ten frames, two balls per frame, and uses a 10-element array A() to represent the ten pins. Pins are set by storing character code 52 (the digit “4”, used as a standing-pin marker) and knocked down by switching to code 23 when a random number exceeds 0.5. The triangular pin layout is rendered using CHR$ codes and TAB positioning across four PRINT lines, giving a visual triangle arrangement. A running high score Y persists across games by looping back to line 30 rather than restarting the program, and a strike on the first ball is detected at line 220, jumping to a special handler that awards a bonus.
Program Analysis
Program Structure
The program is organized into a main game loop (lines 20–290), a post-game summary (lines 300–350), and a strike handler subroutine (lines 370–400). The outer FOR B=1 TO 10 loop iterates over frames, and the inner FOR E=1 TO 2 loop covers the two balls per frame. High score tracking persists by looping to line 30 (which resets only the frame score S) rather than rerunning the program, so Y accumulates across games.
Pin Representation
The ten pins are stored in array A(10). A standing pin is represented by character code 52 (the ASCII/BASIC character 4), and a knocked-down pin is represented by code 23 (a graphic block character). On the first ball (E=1), all pins are reset to 52 at line 110. On the second ball, line 100 skips the reset so remaining pins keep their knocked-down state. Each pin is randomly knocked down at line 120 if RND>0.5, giving roughly a 50% per-pin probability.
Pin Layout Display
Lines 150–180 render the classic triangular pin layout using TAB and CHR$ A(n). The pins are arranged as:
- Row 1 (back): pins 10, 9, 8, 7 — TAB 8
- Row 2: pins 6, 5, 4 — TAB 9
- Row 3: pins 3, 2 — TAB 10
- Row 4 (front): pin 1 — TAB 11
This produces a visually correct inverted triangle. The characters displayed are either 4 (standing) or the code-23 block graphic (fallen).
Scoring Logic
The knocked-down count Z is accumulated in the loop at lines 90–140 by counting pins with code 23. On the second ball, S is incremented by 1 at line 240 regardless of how many pins were knocked down — this is a notable simplification rather than true ten-pin scoring. A strike (all 10 pins on ball 1, detected at line 220) jumps to the strike handler, which sets S=3+15=18 at line 390, a hard-coded bonus. Line 230 then caps Z at 15 if it exceeds 9, though this is used more to signal “full rack” than as a standard spare/strike score.
Ball Label Using CHR$
Line 60 prints CHR$ (E+156) for the ball label. When E=1, this gives CHR$ 157 and when E=2, CHR$ 158 — these are UDG characters \n and \o on the TS2068, so the ball number is displayed as a UDG rather than a plain digit, likely unintentionally producing graphic characters unless those UDGs happen to be defined.
Input Handling
Line 260 polls INKEY$ in a tight loop waiting for CHR$ 118, which is the NEWLINE/ENTER key, before advancing to the next ball. This is a standard busy-wait keypress idiom in Sinclair BASIC.
Bugs and Anomalies
- The scoring at line 240 increments
Sby only 1 per frame completion, ignoring the actual number of pins knocked down. True bowling scoring is not implemented. - The strike handler at line 390 uses
LET S=3+15(evaluating to 18), which overwrites the current total score rather than adding a bonus to it — a significant scoring bug. - After a strike,
Eis set to 2 at line 380 and execution falls into line 230, but theFOR Eloop state is now inconsistent; theNEXT Eat line 280 will still try to execute, potentially causing issues depending on interpreter behaviour. - Line numbers 200 and 210 are absent (jumped over), suggesting deleted or renumbered lines.
- The
CHR$ (E+156)ball label produces UDG characters rather than the digits 1 and 2, which appears unintentional.
Content
Source Code
5 REM "BOWLING ALLEY"
10 DIM A(10)
20 LET Y=0
30 LET S=0
40 FOR B=1 TO 10
50 FOR E=1 TO 2
60 PRINT "FRAME";B,"BALL";CHR$ (E+156)
70 PRINT
80 LET Z=0
90 FOR C=1 TO 10
100 IF E=2 THEN GOTO 120
110 LET A(C)=52
120 IF A(C)=52 AND RND>.5 THEN LET A(C)=23
130 IF A(C)=23 THEN LET Z=Z+1
140 NEXT C
150 PRINT TAB 8;CHR$ A(10);" ";CHR$ A(9);" ";CHR$ A(8);" ";CHR$ A(7)
160 PRINT TAB 9;CHR$ A(6);" ";CHR$ A(5);" ";CHR$ A(4)
170 PRINT TAB 10;CHR$ A(3);" ";CHR$ A(2)
180 PRINT TAB 11;CHR$ A(1)
190 PRINT ,,,,"SCORE THIS FRAME IS ";Z
220 IF E=1 AND Z=10 THEN GOTO 370
230 IF Z>9 THEN LET Z=15
240 IF E=2 THEN LET S=S+1
250 PRINT "SCORE SO FAR ";S,,"PRESS N/L FOR NEXT BALL"
260 IF INKEY$<>CHR$ 118 THEN GOTO 260
270 CLS
280 NEXT E
290 NEXT B
300 PRINT "SCORE THAT WAS ";S
310 IF S<Y THEN GOTO 330
320 LET Y=S
330 PRINT "HIGHEST SCORE SO FAR"
340 PRINT
350 GOTO 30
370 PRINT "STRIKE"
380 LET E=2
390 LET S=3+15
400 GOTO 230
410 SAVE "1023%1"
420 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
