--- title: "Bowling" id: 57619 type: "computer_media" slug: "bowling-2" url: "http://localhost/computer_media/bowling-2/" markdown_url: "http://localhost/computer_media/bowling-2.md" published_at: "2024-10-06T00:46:53+00:00" modified_at: "2026-04-03T07:58:13+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/bowling-average.png" excerpt: "A complete team bowling-season tracker storing three-game weekly scores per player, with menu-driven entry, statistics display, data editing, and tape save." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Gene G. Buza" slug: "gene-g-buza" taxonomy: "indiv" url: "http://localhost/indiv/gene-g-buza/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" - name: "Hobby" slug: "hobby" taxonomy: "genre" url: "http://localhost/type/hobby/" media_contents: - id: 56725 title: "Synchro-Sette March 1984" type: "computer_media" url: "http://localhost/computer_media/synchro-sette-march-1984/" media_type: "Program" programmers: - name: "Gene G. Buza" slug: "gene-g-buza" taxonomy: "indiv" url: "http://localhost/indiv/gene-g-buza/" mediadate: "March 1984" images: - url: "http://localhost/wp-content/uploads/2024/10/bowling-average.png" media_type_tags: "Game, Hobby" --- # Bowling This program is a bowling average tracker for a team. It maintains a season’s worth of scores for multiple players across multiple weeks, storing three games per week per player in a three-dimensional array S(PLAYERS,WEEKS,3). The menu-driven interface uses inverse-video characters throughout for highlighted display, and navigation is handled by reading INKEY$ keycodes (29–32 correspond to ZX81 digit characters 1–4) to branch via GOTO VAL Y$*1000. Player statistics including high game, high series, and a rounded average are calculated on demand, with an optional COPY command to print the display. Data can be saved to tape under a user-supplied filename. *** ## Program Analysis ### Program Structure The program is organized as a menu-driven application with five functional modules, each beginning at a round-thousand line number. The main menu loop lives at lines 100–250, and each menu option jumps to its module via `GOTO VAL Y$*1000`. All modules return to the main menu at line 100 when finished. | Line range | Module | Function | | --- | --- | --- | | 100–250 | Main menu | Display options, read keypress, dispatch | | 1000–1260 | Initialize | Set up season dimensions and player names | | 2000–2250 | Enter scores | Input three games per player per week | | 3000–3420 | Display player data | Show high game, high series, average | | 4000–4920 | Edit data | Change scores or player name | | 5000–5050 | Save to tape | SAVE under user-supplied filename | | 9997–9999 | Bootstrap | Initial SAVE of the program itself, then GO TO 1 | ### Data Storage Three arrays are allocated dynamically after the user supplies season parameters. The core score store is a three-dimensional numeric array `S(PLAYERS,WEEKS,3)`, holding all three games for every player and every week. Player names are held in the string array `P$(PLAYERS,32)`, and weekly series totals in `T(WEEKS)`. The variable `R1`, initialized to 0 at line 10 and incremented at line 2010, serves as the current-week counter and is tested at lines 3000 and 2020 as a guard against accessing uninitialized data. ### Menu Dispatch Idiom The main menu reads a single keypress into `Y$` at line 200. Line 220 validates it by checking `CODE Y$` against the range 29–32, which are the ZX81 internal codes for the digit characters “1” through “4” (not ASCII). The dispatch at line 250 uses `GOTO VAL Y$*1000`: `VAL Y$` converts the character to its numeric value (1–4), multiplied by 1000 to reach the correct module entry point. Option “5” (save) is listed on the menu but the code range check excludes code 33 (“5”), so saving can only be reached if the validation is relaxed — this is a latent bug: the guard at line 220 allows codes 29–32 only, excluding the “5” option shown on screen. ### Player Name Matching Both the display (line 3040) and edit (line 4050) modules search for a player by comparing the user’s input `N$` against a leading substring of each stored name: `IF N$=P$(A, TO LEN N$)`. This allows partial-name lookup, so entering just the first few letters is sufficient to identify a player. ### Statistics Calculation The display module (lines 3130–3340) makes a single pass through all recorded weeks for the selected player. It tracks high single game (`HIGAME`), high three-game series (`HISERIES`), total pins (`TPINS`), and total games played (`TGAMES`). The average is computed as `TPINS/TGAMES` and rounded to two decimal places using the expression `INT(100*AVERAGE+.05)/100` at line 3330, which implements standard rounding by adding half a unit before truncating. ### Notable Techniques - **FAST/SLOW bracketing:** Computationally intensive sections (screen build, array allocation) are wrapped in `FAST`/`SLOW` pairs to suppress display flicker during processing while still accepting input in SLOW mode. - **PAUSE 40000 as a display hold:** Used after showing statistics and series totals, giving the user time to read before the program continues. The value 40000 is close to the maximum (65535 would be the absolute limit) and provides a very long wait. - **Optional COPY at line 3410:** After the statistics pause, pressing “Z” triggers a `COPY` to print the screen contents, allowing a paper record of a player’s data. - **VAL Y$*1000 dispatch:** A compact idiom avoiding a chain of IF statements for menu routing. - **Bootstrap lines 9997–9999:** Line 9998 saves the program under the name “BOWLIN`%G`” (the `%G` renders as inverse “G” on screen), and line 9999 `GOTO 1` — since line 1 does not exist, this is the well-known technique of jumping to a non-existent line, which in practice falls through to the next available line (line 10), effectively auto-starting after the save. ## Source Code ``` 0 % % % %B%O%W%L%I%N%G% % % % %W%R%I%T%T%E%N% % %B%Y% % % %G%E%N%E% %B%U%Z%A% % 10 LET R1=0 100 FAST 110 CLS 120 PRINT AT 1,7;"% %B%O%W%L%I%N%G% %A%V%E%R%A%G%E% " 130 PRINT AT 4,0;"% %T%O% %I%N%I%T%I%A%L%I%Z%E% ";TAB 31;"%1" 140 PRINT AT 6,0;"% %T%O% %E%N%T%E%R% %S%C%O%R%E%S% ";TAB 31;"%2" 150 PRINT AT 8,0;"% %T%O% %D%I%S%P%L%A%Y% %P%L%A%Y%E%R% %D%A%T%A% ";TAB 31;"%3" 160 PRINT AT 10,0;"% %T%O% %E%D%I%T% %D%A%T%A% ";TAB 31;"%4" 170 PRINT AT 12,0;"% %T%O% %S%A%V%E% %O%N% %T%A%P%E% ";TAB 31;"%5" 190 SLOW 200 LET Y$=INKEY$ 210 PRINT AT 21,4;"ENTER ONE OF ABOVE ::";AT 21,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:" 220 IF CODE Y$<29 OR CODE Y$>32 THEN GOTO 200 230 FAST 240 CLS 250 GOTO VAL Y$*1000 1000 PRINT "HOW MANY WEEKS IS THE SEASON? "; 1010 SLOW 1020 INPUT WEEKS 1030 PRINT WEEKS 1040 PRINT ,,"HOW MANY PLAYERS ON THE TEAM? "; 1050 INPUT PLAYERS 1060 PRINT PLAYERS 1100 DIM S(PLAYERS,WEEKS,3) 1110 DIM P$(PLAYERS,32) 1120 DIM T(WEEKS) 1190 CLS 1200 FOR N=1 TO PLAYERS 1210 PRINT "NAME OF PLAYER NO.";N 1220 INPUT P$(N) 1230 PRINT P$(N) 1240 PRINT 1250 NEXT N 1260 GOTO 100 2000 SLOW 2010 LET R1=R1+1 2020 IF R1=WEEKS THEN GOTO 2500 2100 FOR N=1 TO PLAYERS 2110 CLS 2120 PRINT "SCORE FOR WEEK NO.";R1;" FOR" 2130 PRINT P$(N) 2140 FOR I=1 TO 3 2150 PRINT "GAME NO.";I; 2160 INPUT S(N,R1,I) 2170 PRINT TAB 29;S(N,R1,I) 2180 PRINT 2190 NEXT I 2200 LET T(R1)=S(N,R1,1)+S(N,R1,2)+S(N,R1,3) 2210 PRINT "SERIES =";TAB 29;T(R1) 2220 PAUSE 40000 2230 CLS 2240 NEXT N 2250 GOTO 100 3000 IF R1=0 THEN GOTO 100 3010 PRINT AT 1,2;"% %W%H%A%T% %I%S% %T%H%E% %P%L%A%Y%E%R:.%S% %N%A%M%E% " 3015 SLOW 3020 INPUT N$ 3025 FAST 3030 FOR A=1 TO PLAYERS 3040 IF N$=P$(A, TO LEN N$) THEN GOTO 3100 3050 NEXT A 3060 PRINT ,,N$;" NOT IN FILE." 3070 PAUSE 40000 3080 GOTO 100 3100 CLS 3110 PRINT "BOWLING DATA FOR :::",P$(A) 3120 FAST 3130 LET HIGAME=0 3135 LET TPINS=0 3136 LET TGAMES=0 3140 LET HISERIES=0 3150 FOR B=1 TO R1 3160 LET SERIES=0 3170 FOR C=1 TO 3 3175 LET TGAMES=TGAMES+1 3180 LET GAME=S(A,B,C) 3185 LET TPINS=TPINS+GAME 3190 IF GAME>HIGAME THEN LET HIGAME=GAME 3200 LET SERIES=SERIES+GAME 3210 NEXT C 3220 IF SERIES>HISERIES THEN LET HISERIES=SERIES 3230 NEXT B 3300 PRINT ,,"% %H%I%G%H% %G%A%M%E% %=% ",HIGAME 3310 PRINT ,,"% %H%I%G%H% %S%E%R%I%E%S% %=",HISERIES 3320 LET AVERAGE=TPINS/TGAMES 3330 LET AVERAGE=INT (100*AVERAGE+.05)/100 3340 PRINT ,,"% %A%V%E%R%A%G%E% %=% ",AVERAGE 3400 PAUSE 40000 3410 IF INKEY$="Z" THEN COPY 3420 GOTO 100 4000 PRINT ,,"% %W%H%A%T% %I%S% %T%H%E% %P%L%A%Y%E%R%S% %N%A%M%E%?% " 4010 SLOW 4020 INPUT N$ 4030 FAST 4040 FOR A=1 TO PLAYERS 4050 IF N$=P$(A, TO LEN N$) THEN GOTO 4100 4060 NEXT A 4070 GOTO 3060 4100 CLS 4110 PRINT ,,P$(A) 4120 PRINT ,,"% %C%H%A%N%G%E% %N%A%M%E%?% " 4130 PAUSE 40000 4140 IF INKEY$="Y" THEN GOTO 4900 4150 CLS 4160 PRINT ,,"WHAT WEEK?" 4170 SLOW 4180 INPUT WW 4190 FAST 4220 PRINT 4230 FOR N=1 TO 3 4240 PRINT N,S(A,WW,N) 4250 NEXT N 4260 PRINT ,,"WHICH GAME (1, 2,3 OR 0 TO EXIT)DO YOU WANT TO CHANGE?" 4265 SLOW 4270 LET W$=INKEY$ 4271 IF CODE W$<28 OR CODE W$>31 THEN GOTO 4270 4272 IF W$="0" THEN GOTO 100 4275 FAST 4276 LET WG=VAL W$ 4280 IF WG>3 OR WG<1 THEN GOTO 4270 4290 PRINT ,,"NEW GAME TOTAL?" 4295 SLOW 4300 INPUT NG 4305 FAST 4310 IF NG<0 OR NG>300 THEN GOTO 4295 4320 LET S(A,WW,WG)=NG 4330 GOTO 100 4900 PRINT ,,"WHAT IS THE NEW NAME?" 4905 SLOW 4910 INPUT P$(A) 4920 GOTO 100 5000 PRINT ,,"ENTER THE FILE NAME, PEPARE THE RECORDER AND PRESS ENTER :::" 5010 SLOW 5020 INPUT F$ 5030 FAST 5040 SAVE F$ 5050 GOTO 100 9997 STOP 9998 SAVE "BOWLIN%G" 9999 GOTO 1 ```