--- title: "Racer" id: 55877 type: "computer_media" slug: "racer" url: "http://localhost/computer_media/racer/" markdown_url: "http://localhost/computer_media/racer.md" published_at: "2024-07-06T17:27:02+00:00" modified_at: "2026-03-30T21:44:53+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/07/SCR-20240706-iitj.png" excerpt: "Pick your racer, place your bet, and watch nine competitors sprint across the screen in this BASIC racing game with UDG sprites, sound effects, and a world-record timer." 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 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 55879 title: "ISTUG Public Domain Library 7" type: "computer_media" url: "http://localhost/computer_media/istug-public-domain-library-7/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Racer%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/07/SCR-20240706-iitj.png" media_type_tags: "Game" --- # Racer This program simulates a nine-lane racing game with betting mechanics, where the player wagers dollars on one of nine numbered racers. It defines six UDG characters (spanning character slots “a” through “m” and “h”) by POKEing 48 bytes of bitmap data to represent racer sprites, track graphics, and animation frames. The main race loop uses computed GO TO via the expression `r*1000` to dispatch randomly to one of nine racer-advance routines (lines 1000–9030), each of which moves a different racer across its screen row until it reaches column 31. SOUND commands with multiple channel parameters provide engine noise and race atmosphere, while BEEP produces pitch-varying tones tied to each racer’s current position. A world-record timer tracks elapsed tenths-of-seconds, and a short melody plays from DATA statements at race end using a READ/BEEP loop. *** ## Program Analysis ### Program Structure The program divides into several logical phases: 1. **Initialization (lines 1–110):** Sets paper/border/bright attributes, then POKEs UDG bitmap data for six character definitions covering slots `"a"` through `"f"` (48 bytes, 6 UDGs), `"m"` (8 bytes), and `"h"` (8 bytes). 2. **Track setup and betting (lines 132–138):** Draws lane dividers with dashes, prompts for a chosen racer (1–9), and accepts a wager with a guard preventing over-betting. 3. **Race animation intro (lines 140–208):** Displays a starting grid graphic, animates a flashing start sequence using UDG characters with SOUND effects, plots side boundary lines, and draws lane numbers. 4. **Main race loop (lines 209–220):** Maintains a seconds/tenths timer, plays tick sounds, and uses `GO TO r*1000` to randomly dispatch to one of nine racer routines. 5. **Racer advance routines (lines 1000–9030):** Nine blocks, each handling one racer lane, advancing its sprite one column and checking for a finish at column 32. 6. **Finish sequence and scoring (lines 9500–9730):** Announces the winner, plays a melody from DATA, checks/updates the world record, evaluates the bet, and offers replay. ### UDG Definitions Three separate FOR/READ/POKE loops load custom character bitmaps: | Loop (lines) | Slots covered | Bytes | | --- | --- | --- | | 10–70 | `"a"` through `"f"` | 48 | | 80–90 | `"m"` | 8 | | 100–110 | `"h"` | 8 | The DATA statements use a variable `n` at several positions, but `n` is never initialized before the READ loops execute. This is a latent bug: `n` will default to 0 in most implementations, so those entries silently become 0, likely giving correct zero-byte rows intentionally or by convention. ### Computed GO TO Dispatch The core routing mechanism at line 220 is `GO TO r*1000`, where `r` is an integer from 1 to 9 produced by `INT(RND*9+1)` at line 210. This jumps to lines 1000, 2000, …, 9000 — one block per racer. Each block prints the racer’s UDG sprite at its current column, increments the column counter, checks for reaching column 32 (finish), and loops back to line 210. This is an efficient alternative to a long IF/THEN chain. ### Race Timer Lines 209–214 implement a software timer. Variable `t` counts tenths and `s` counts whole seconds. Each pass through the main loop increments `t`; when `t` reaches 9, it resets and `s` increments. The elapsed time is assembled at line 9508 as `rt = s + (t/10)`, giving a single decimal value used for world-record comparison and display. ### SOUND and BEEP Usage SOUND commands appear extensively with multi-channel parameters (channels 6–13) to produce engine noise during race startup and running. BEEP is used for per-tick clicks and for the victory melody. The melody at lines 9521–9528 reads pairs of duration/pitch values from DATA, divides the duration by 16 to get fractional seconds, and calls BEEP in a loop until sentinel value 999 is encountered. The DATA spans five lines (9524–9528) covering two melodic phrases plus a terminating `999,999`. ### Betting and Scoring The player’s bankroll is held in `o` (initialized to 10 at line 1). Variable `l` is the bet amount, validated at line 137. Winnings are calculated at line 9515 as `b = INT((l*5) - (3*RND))`, giving approximately 5× the stake with slight random variation. Line 9600 adds winnings if the chosen racer `k` equals `r`; line 9601 deducts the bet otherwise. Line 9610 stops the program if `o` drops to zero or below. ### World Record Tracking Variables `wr` (initialized to 100) and `w` track the best race time and winning racer number across games. Line 9530 updates the record if the current race time `rt` beats `wr`. The condition at line 9520 (`IF wr>=rt THEN GO SUB 9509`) triggers a celebratory UDG animation routine whenever a record is equaled or beaten. ### Notable Techniques and Anomalies - Line 132 uses `FOR x=PI TO 19 STEP 2`, starting the loop at approximately 3.14159. Since the loop variable is used only as an AT row index, this effectively starts at row 3 (truncated), which is an unusual but functional choice. - The `RESTORE 9529` / `GO TO 9529` / `RESTORE 9524` sequence at lines 9529 means the melody DATA is re-read from line 9524 after the first play, enabling replay across multiple race rounds. - Line 9511 contains `NEXT g: RETURN`, but the FOR loop for `g` at line 9509 has no corresponding NEXT that would be reached normally — line 9510 NEXTs and line 9511’s NEXT would fire only if control falls through, which it cannot due to PAUSE. The RETURN suggests this block was intended as a subroutine, but it is only ever reached via GO SUB 9509 which calls into the middle of a FOR loop structure — a structural oddity. - The replay loop at lines 9720–9730 animates a wipe effect then prints 350 space-asterisk pairs before clearing the screen and saving the program with `SAVE "RACER" LINE 1`, ensuring auto-restart on reload. - Variable reuse is notable: `f`, `g`, and `b` are used both as racer position counters in the mid-race routines and as general loop/calculation variables in the finish sequence, relying on the race being over before those variables are reused. ## Source Code ``` 1 LET o=10: LET wr=100 5 PAPER 7: BORDER 7: BRIGHT 0: CLS 10 FOR x=0 TO 47: READ n: POKE USR "a"+x,n: NEXT x 20 DATA 12,n,120,94,90,48,36,n 30 DATA 48,n,30,120,90,24,36,n 40 DATA 48,n,31,249,24,120,78,194 50 DATA 24,n,189,219,24,n,n,60 60 DATA 153,n,255,24,n,36,66,195 70 DATA 28,12,8,60,n,254,24,60 80 FOR x=0 TO 7: READ n: POKE USR "m"+x,n: NEXT x 90 DATA 12,n,248,159,24,30,114,67 100 FOR x=0 TO 7: READ n: POKE USR "h"+x,n: NEXT x 110 DATA 0,6,n,60,n,36,228,132 132 FOR x=PI TO 19 STEP 2: PRINT AT x,0; BRIGHT 0; INK 0;"------------------------------": NEXT x 134 INPUT "Who do you want to win 1 TO 9 ";k 135 PRINT AT 0,0;"You have ";o;" dollars to bet.",,, 136 INPUT "PLACE YOUR BETTS ";l 137 IF l>o THEN GO TO 135 138 PRINT AT 1,0;"YOU BET ";l;" on ";k;" ", 140 PRINT AT 0,0; BRIGHT 0; INK 2;"\: \..\..\..\: \..\..\..\..\..\..\: \..\..\..\.:\..\..\..\.:\..\..\..\.:\..\..\..\.:\..\..\..\.:\:.\..\..\..\..\.:\..\..\..\..\.:\..\..\..\..\.:\..\..\..\.:\..\..\..\.:\..\..\..\.:\..\..\..\.:": PAUSE 100 190 RANDOMIZE : LET j=3: LET a=j: LET b=j: LET c=j: LET d=j: LET e=j: LET f=j: LET g=j: LET h=j: LET i=j 200 FOR x=30 TO 0 STEP -1: SOUND 6,20;7,7;8,16-(x/2);9,16-(x/2);10,16-(x/2);12,255;13,1: PAUSE 10 201 PAPER 6: PRINT AT 0,x;"\c";AT 1,30-x;"\a": PAUSE 5: PRINT AT 0,x;"\d";AT 1,30-x;"\d": PRINT AT 1,30-x*RND;"\f";AT 0,x*RND;"\f";AT 0,30-x*RND;"\f";AT 1,x*RND;"\f": NEXT x 202 FOR x=1 TO 31: PAPER 6: BRIGHT 1: PRINT AT 0,x*RND;"\f";AT 1,x*RND;"\f": RANDOMIZE : PRINT AT 0,x*RND;"\f";AT 1,x*RND;"\f": NEXT x 203 PRINT AT 0,0; BRIGHT 0; PAPER 6;"\:.\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\.:";AT 1,0;"\:.\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\.:_" 205 FOR x=2 TO 18 STEP 2: PRINT AT x,0; INK x/6; PAPER 7; BRIGHT 1;x/2;" \d",,: PAUSE 5: NEXT x 206 FOR y=10 TO 159: PLOT 24,y: PLOT 245,y: NEXT y 207 FOR x=2 TO 18 STEP 2: PRINT AT x,0; INK x/6; PAPER 7; BRIGHT 1;x/2;" \h": NEXT x 208 PAUSE 40: SOUND 6,15;7,7;8,16;9,16;10,16;12,10;13,0 209 LET t=0: LET s=t 210 LET r=INT (RND*9+1) 211 LET t=t+1: IF t=9 THEN LET t=0: LET s=s+1 212 PRINT AT 20,0;"SEC. TENTHS " 213 PRINT AT 21,0;" \.'";s;" : ";t;"\.'" 214 IF t=9 THEN LET t=0: LET s=s+1 215 BEEP .001,50 216 SOUND 6,20;7,7;8,5;9,3;10,8;12,255;13,1: 217 PRINT AT 0,31*RND; BRIGHT 0; PAPER 6; FLASH 1;"\f";AT 1,31*RND;"\f" 218 PRINT AT 0,31*RND; BRIGHT 0; PAPER 6; FLASH 0;"\f";AT 1,31*RND;"\f" 220 GO TO r*1000 1000 PAPER 7: BRIGHT 1: INK 0: PRINT AT 2,a-1;"\m": BEEP .001,60-a: PRINT AT 2,a-1;" \a" 1020 LET a=a+1: IF a=32 THEN GO TO 9500 1030 GO TO 210 2000 INK 3: PAPER 7: BRIGHT 1: PRINT AT 4,b-1;"\m": BEEP .001,60-b: PRINT AT 4,b-1;" \a" 2020 LET b=b+1: IF b=32 THEN GO TO 9500 2030 GO TO 210 3000 INK 1: PAPER 7: BRIGHT 1: PRINT AT 6,c-1;"\m": BEEP .001,60-c: PRINT AT 6,c-1;" \a" 3020 LET c=c+1: IF c=32 THEN GO TO 9500 3030 GO TO 210 4000 INK 3: PAPER 7: BRIGHT 1: PRINT AT 8,d-1;"\m": BEEP .001,40: PRINT AT 8,d-1; INK 0;" \a" 4020 LET d=d+1: IF d=32 THEN GO TO 9500 4030 GO TO 210 5000 INK 0: PAPER 7: BRIGHT 1: PRINT AT 10,e-1;"\m": BEEP .001,45: PRINT AT 10,e-1;" \a" 5020 LET e=e+1: IF e=32 THEN GO TO 9500 5030 GO TO 210 6000 PAPER 7: INK 2: BRIGHT 1: PRINT AT 12,f-1;"\m": BEEP .001,35: PRINT AT 12,f-1;" \a" 6020 LET f=f+1: IF f=32 THEN GO TO 9500 6030 GO TO 210 7000 INK 1: PAPER 7: BRIGHT 1: PRINT AT 14,g-1;"\m": BEEP .001,60: PRINT AT 14,g-1;" \a" 7020 LET g=g+1: IF g=32 THEN GO TO 9500 7030 GO TO 210 8000 INK 3: PAPER 7: BRIGHT 1: PRINT AT 16,h-1;"\m": BEEP .001,50-h: PRINT AT 16,h-1;" \a" 8020 LET h=h+1: IF h=32 THEN GO TO 9500 8030 GO TO 210 9000 PAPER 7: BRIGHT 1: PRINT AT 18,j-1; INK 2;"\m": BEEP .001,60-j: PRINT AT 18,j-1;" \a" 9020 LET j=j+1: IF j=32 THEN GO TO 9500 9030 GO TO 210 9500 BEEP .1,45: PRINT AT r*2,31; FLASH 1;"\m": PAUSE 30 9501 PRINT AT r*2,31;" ": LET x=r*2: FOR u=x TO 21 9502 BEEP .001,u+30: PRINT AT u,31;"\m": PAUSE 10: BEEP .001,u+33: PRINT AT u,31;"\a": BEEP .001,50: PAUSE 10: PRINT AT u,31;" " 9505 NEXT u 9507 FOR y=30 TO 16 STEP -1: PRINT AT 21,y;"\b ": BEEP .001,y+30: PAUSE 10: PRINT AT 21,y;"\c ": BEEP .001,40: PAUSE 10: NEXT y 9508 LET rt=s+(t/10): GO TO 9512 9509 PRINT AT 0,0;"\a";:: FOR g=0 TO 17: PRINT ; INK RND*3; PAPER 6; BRIGHT 1*RND; FLASH 1*RND;"\a\b\e \c\c\a\m\c \a\b\c\d\e\d\c \b\b \b\b\c\c\d\d\a\a\e\m\a\e\b\d\a"; 9510 PAUSE 10: SOUND 6,13;7,7;8,16;9,16;10,16;12,255;13,1: NEXT g 9511 PAUSE 10: SOUND 6,15;7,7;8,16;9,16;10,16;12,255;13,1: NEXT g: RETURN 9512 LET rt=s+(t/10) 9514 FOR f=1 TO 10: PRINT AT 20,16;"\e";AT 21,16;" ": BEEP .1,20+(f*3): PRINT AT 21,0;".The winner is \d ";r;" in ";rt;"sec";AT 20,16;" ": BEEP .1,40: NEXT f 9515 LET b=INT ((l*5)-(3*RND)) 9520 IF wr>=rt THEN GO SUB 9509 9521 READ d,p: LET d=d/16 9522 IF p=999 THEN GO TO 9529 9523 BEEP d,p: GO TO 9521 9524 DATA 4,7,8,7,2,4,4,4,4,7,8,7,2,2,4,2,4,4,4,5,4,7,4,9,4,11,8,7,8,69 9525 DATA 4,7,8,7,2,4,4,4,4,7,8,7,2,2,4,2,4,14,4,13,4,14,4,16,4,9,8,14,8,69 9526 DATA 4,7,8,16,2,16,4,14,4,12,8,12,2,11,4,11,4,12,4,14,4,11,4,9,4,7,8,12,8,69 9527 DATA 4,12,8,12,2,9,4,9,4,12,8,12,2,7,4,7,4,7,4,9,4,12,4,7,4,14,16,12 9528 DATA 999,999 9529 RESTORE 9524: PAUSE 100 9530 IF wr>rt THEN LET wr=rt: PRINT AT 19,0; FLASH 1;"#";r;" has set a World Record": LET w=r 9540 PRINT AT 20,0;"The WORLD RECORD IS ";wr;" by #";w: PAUSE 200 9600 IF r=k THEN PRINT AT 0,0;"YOU HAVE WON- ";b;" ": LET o=o+b 9601 IF r<>k THEN PRINT AT 0,0;"You lost $";l;".You have ";o-l;" left.": LET o=o-l 9610 IF o<=0 THEN PRINT AT 0,10; FLASH 1;"You are busted!!!": STOP 9700 INPUT "Do you want to play again? ";i$ 9711 IF i$="n" THEN STOP 9720 PRINT AT 21,0; INK 2;"________________" 9721 FOR y=16 TO 0 STEP -1: PRINT AT 21,y;"\b ": BEEP .001,y+30: PAUSE 10: PRINT AT 21,y;"\c ": BEEP .001,40: PAUSE 10: NEXT y: 9730 PRINT AT 0,0;" ";: FOR x=0 TO 350: PRINT " *";: BEEP .001,50: NEXT x: CLS 9740 SAVE "RACER" LINE 1 ```