Night Race

This file is part of and ISTUG Public Domain Library 5. Download the collection to get this file.
Date: 1982
Type: Program
Platform(s): TS 2068
Tags: Game

Night Race is a scrolling driving game in which the player steers a car sprite down a winding road, dodging oncoming traffic while the road continuously shifts direction. The player’s car is built from four user-defined graphics characters (UDGs \a through \d), each an 8×8 pixel tile that together form a 2×2 character vehicle; oncoming cars use the same four UDGs displayed in different arrangements. Collision detection is handled by reading screen character data with SCREEN$ at row 11, triggering a crash sequence with descending BEEP tones when the road edge overlaps the player’s column. The road scrolls by printing a 10-character-wide colored strip that oscillates left and right using a simple direction flag, and game speed increases implicitly as the score grows because the BEEP pitch formula references the score variable. A high score table of one entry is maintained in memory across rounds, prompting for the winner’s name via INPUT.


Program Analysis

Program Structure

The program is organized into a main initialization block, a primary game loop, a crash/scoring handler, and two subroutines:

  1. Lines 1–9: REM header and global variable initialization.
  2. Lines 9–30: Per-game setup — screen attributes, road center c, player column b, score reset, and initial road drawing.
  3. Lines 101–200: Main game loop. Draws road strip, checks for collision via SCREEN$, optionally draws oncoming car, increments score, draws player car, handles input, scrolls road.
  4. Lines 1000–1050: Crash handler — plays crash sound, displays score, handles high score entry, then restarts.
  5. Lines 8000–8080: Title/instructions screen subroutine.
  6. Lines 9000–9500: UDG definition subroutine using POKE USR with BIN literals.
  7. Lines 9998–9999: Save/verify block.

User-Defined Graphics

Five UDGs are defined in the subroutine at line 9000. UDGs \a through \d form the two-character-wide, two-character-tall car sprite. UDG \e is a simple vertical stripe (all rows BIN 00011000), used as a road-edge marker in the road strip printed at lines 101–102. The four car tiles are carefully mirrored: \a/\b are the top-left/top-right halves and \c/\d are the bottom-left/bottom-right halves, with \b and \d being the bitwise horizontal mirrors of \a and \c respectively.

Collision Detection

Collision is detected by sampling the screen character at row 11, columns b and b+1 using SCREEN$ (lines 103–108). An empty string from SCREEN$ indicates a blank cell — i.e., outside the road strip — so a non-empty result in the road-edge zone triggers a branch to the crash handler at line 1000. The check is performed both before and after the oncoming car is drawn (lines 103–104 and 107–108), providing a slightly asymmetric but functional hit test. Line 1000 uses the pattern of which screen cell was empty to select a scrambled car sprite as a visual crash effect.

Road Scrolling and Direction Logic

The road is represented as a 10-character-wide colored strip (INK 6 row 20, INK 5 row 21) printed starting at column c. The road position oscillates using direction flag y (0 or 1): if y=1 and c<19 then c increments; if y=0 and c>1 then c decrements. The direction reverses at the boundary values (c=1 or c=19) or randomly when RND>0.9 (line 197). This produces a winding road effect on the scrolling display.

Oncoming Traffic

An oncoming car is drawn at line 105 with a probability that increases as the score rises: RND > 50/(score+80). At score 0 the probability is about 37.5%; as score grows, the threshold approaches 1 and cars appear more frequently. The oncoming car is placed at column c+x where x is a random value 1–8 (line 145), keeping it within the road strip. The oncoming car uses the same four UDGs as the player car but in a different arrangement (\a\b top row, \c\d bottom row) with a random ink color m chosen from INK 3–7.

Input Handling

Four movement keys are supported, tested sequentially with INKEY$ at lines 150–158:

KeyAction
rMove left 1 column
tMove right 1 column
R (CAPS+r)Move left 2 columns
T (CAPS+t)Move right 2 columns

Line 159 checks for h or H and issues PAUSE 9999 as a pause function. Because INKEY$ is polled without waiting, steering is responsive only when the loop executes fast enough.

Score and Sound

The score increments by 5 each main loop iteration (line 115). The BEEP at line 135 uses the score in both duration and pitch calculations: 10/(score+40) makes beeps shorter as the score grows, and (1-100/(score+100))*50-50 raises pitch over time, providing audio feedback of increasing speed. The crash sound (lines 1005–1010) plays 30 short low-pitch beeps followed by a descending tone sweep.

High Score Persistence

The high score (hi) and holder name (c$) persist in variables across game rounds within the same session. On a new high score, the program re-displays the score table (via GO TO 1020), then prompts for the player’s name with INPUT "Your name? ";c$ and updates hi. The initial value of c$ is "__________" (10 underscores), set at line 9.

Notable Techniques and Anomalies

  • POKE 23692,5 at line 110 resets the “scroll?” counter (system variable SCRCT), suppressing the “scroll?” prompt that would otherwise appear after 22 printed lines.
  • Line 200 reads GO TO 100 but the main loop begins printing at line 101. Line 100 itself does not exist, so execution falls through to line 101 — a deliberate technique to skip any hypothetical line 100 code.
  • The PRINT ''' at line 120 prints three blank lines, which combined with the road strip PRINTs and the AT-addressed car, drives the screen scrolling that creates the forward-motion illusion.
  • Variable c is reused: it is initially set as an ink color constant (LET c=4 at line 9) but is reassigned as the road column at line 18 (LET c=4 again). The ink usage at line 9 precedes the road-column usage, so this does not cause a conflict.
  • The LET x=RND*8+1 at line 145 is placed after the player movement and before the loop restarts — x controls oncoming car lateral position and is randomized every cycle.
  • The title screen subroutine (line 8000) is called after the UDG subroutine (line 9000) in line 9, ensuring UDGs are ready before any game graphics are displayed.

Content

Appears On

Library tape of the Indiana Sinclair Timex User’s Group.

Related Products

Related Articles

Related Content

Image Gallery

Night Race

Source Code

    1 REM -----------------------
    2 REM 
    3 REM        Night Race
    4 REM 
    5 REM       Blane Bramble                       1982
    6 REM 
    7 REM -----------------------
    8 LET k=0
    9 INK 4: PAPER 0: BORDER 0: CLS : LET x=10: LET c=4: LET score=0: LET hi=0: LET c$="__________": GO SUB 9000: GO SUB 8000
   10 PRINT : FOR i=1 TO 6: PRINT '"    \e          \e"'"    \e          \e": NEXT i
   18 LET a=9: LET b=10: LET c=4
   20 LET y=1
   30 LET m=RND*4+3
  101 PRINT INK 6;AT 20,c;"\e          \e"
  102 PRINT INK 5;AT 21,c;"\e          \e"
  103 LET b$=SCREEN$ (11,b): IF b$="" THEN GO TO 1000
  104 LET a$=SCREEN$ (11,b+1): IF a$="" THEN GO TO 1000
  105 IF RND>50/(score+80) THEN PRINT INK m;AT 20,c+x;"\a\b";AT 21,c+x;"\c\d"
  107 LET a$=SCREEN$ (11,b+1): IF a$="" THEN GO TO 1000
  108 LET b$=SCREEN$ (11,b): IF b$="" THEN GO TO 1000
  110 POKE 23692,5
  115 LET score=score+5
  120 PRINT '''
  130 PRINT INK 2;AT a,b;"\a\b";AT a+1,b;"\c\d"
  133 LET m=RND*5+3
  135 BEEP 10/(score+40),(1-100/(score+100))*50-50
  140 PRINT AT a,b;"  ";AT a+1,b;"  "
  145 LET x=RND*8+1
  150 IF INKEY$="T" AND b<29 THEN LET b=b+2
  153 IF INKEY$="R" AND b>0 THEN LET b=b-2
  156 IF INKEY$="t" AND b<29 THEN LET b=b+1
  158 IF INKEY$="r" AND b>0 THEN LET b=b-1
  159 IF INKEY$="h" OR INKEY$="H" THEN PAUSE 9999
  160 PRINT AT 20,0;""
  190 IF y=1 AND c<19 THEN LET c=c+1
  195 IF y=0 AND c>1 THEN LET c=c-1
  197 IF c=1 OR c=19 OR RND>.9 THEN LET y=1-y
  200 GO TO 100
 1000 IF a$="" AND b$<>"" THEN PRINT INK 2;AT a,b;"\a\d";AT a+1,b;"\c\b"
 1003 IF b$="" AND a$<>"" THEN PRINT INK 2;AT a,b;"\c\b";AT a+1,b;"\a\d"
 1005 FOR a=1 TO 30: BEEP 0.1,-30: NEXT a
 1010 FOR a=30 TO 0 STEP -1: BEEP 0.01,a: NEXT a
 1020 CLS 
 1030 PRINT "Score ";score;';"High score is ";hi;';"By ";c$
 1031 IF hi<score THEN PRINT "You have the new high score"
 1032 IF hi<score THEN INPUT "Your name? ";c$
 1033 IF hi<score THEN LET hi=score: GO TO 1020
 1034 LET score=0
 1037 PAUSE 50
 1040 PRINT AT 21,3;"PRESS ANY KEY TO CONTINUE"
 1043 BEEP 0.01,RND*40: IF INKEY$="" THEN GO TO 1043
 1045 CLS 
 1050 GO TO 10
 8000 PRINT AT 0,10; INK 6;"NIGHT RACE"
 8010 PRINT AT 2,8; INK 2;"by Blane Bramble"
 8020 PRINT ''"The Controls are:-"
 8030 PRINT '"r---------1 space left"
 8040 PRINT "t---------1 space right"
 8050 PRINT "R---------2 spaces left"
 8060 PRINT "T---------2 spaces right"
 8070 PRINT '"The last two controls are CAPS  SHIFT and the r or t key"
 8072 PRINT FLASH 1; INK 2;AT 21,10;"Press a key"
 8074 PAUSE 0
 8076 CLS 
 8080 RETURN 
 9000 POKE USR "a"+0,BIN 00001111
 9010 POKE USR "a"+1,BIN 00000111
 9020 POKE USR "a"+2,BIN 00011111
 9030 POKE USR "a"+3,BIN 00111100
 9040 POKE USR "a"+4,BIN 00111100
 9050 POKE USR "a"+5,BIN 00111111
 9060 POKE USR "a"+6,BIN 00111111
 9070 POKE USR "a"+7,BIN 00011000
 9100 POKE USR "c"+0,BIN 00011000
 9110 POKE USR "c"+1,BIN 00011000
 9120 POKE USR "c"+2,BIN 00011111
 9130 POKE USR "c"+3,BIN 00111111
 9140 POKE USR "c"+4,BIN 00111111
 9150 POKE USR "c"+5,BIN 00111111
 9160 POKE USR "c"+6,BIN 00010011
 9170 POKE USR "c"+7,BIN 00001111
 9200 POKE USR "b"+0,BIN 11110000
 9210 POKE USR "b"+1,BIN 11100000
 9220 POKE USR "b"+2,BIN 11111000
 9230 POKE USR "b"+3,BIN 00111100
 9240 POKE USR "b"+4,BIN 00111100
 9250 POKE USR "b"+5,BIN 11111100
 9260 POKE USR "b"+6,BIN 11111100
 9270 POKE USR "b"+7,BIN 00011000
 9300 POKE USR "d"+0,BIN 00011000
 9310 POKE USR "d"+1,BIN 00011000
 9320 POKE USR "d"+2,BIN 11111000
 9330 POKE USR "d"+3,BIN 11111100
 9340 POKE USR "d"+4,BIN 11111100
 9350 POKE USR "d"+5,BIN 11111100
 9360 POKE USR "d"+6,BIN 11001000
 9370 POKE USR "d"+7,BIN 11110000
 9400 POKE USR "e"+0,BIN 00011000
 9410 POKE USR "e"+1,BIN 00011000
 9420 POKE USR "e"+2,BIN 00011000
 9430 POKE USR "e"+3,BIN 00011000
 9440 POKE USR "e"+4,BIN 00011000
 9450 POKE USR "e"+5,BIN 00011000
 9460 POKE USR "e"+6,BIN 00011000
 9470 POKE USR "e"+7,BIN 00011000
 9500 RETURN 
 9998 SAVE "Night Race" LINE 1: BEEP .4,15
 9999 VERIFY ""

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top