Crasher

This file is part of and Timex Sinclair Public Domain Library Tape 1004. Download the collection to get this file.
Developer(s): Tim Hartnell, Tony Willing
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Arcade, Game

CRASHER is a scrolling-screen arcade game in which the player steers a “V” character left and right using the 5 and 8 keys, crashing into alphanumeric characters to score points while avoiding inverse-video characters that end the game. The game loop uses SCROLL to advance the play field upward and places random characters on the bottom row using CHR$ with a probability-weighted inverse-video flag (128 AND RND<0.2). Player collision detection is performed by PEEKing the display file address stored at system variables 16398–16399, checking the ASCII value of whatever character occupies the player’s screen position. The title screen animates the word “CRASHER” scrolling in from both the top and bottom of the screen simultaneously, using FAST/SLOW toggling for a flicker effect, and the game tracks a high score across multiple plays in variable HS.


Program Analysis

Program Structure

The program is divided into several functional blocks:

  • Lines 0–10: Initialisation and jump to the animated title sequence at line 9000.
  • Lines 20–55: Instructions prompt and routing (Y/N input loop).
  • Lines 60–155: Instructions display with delays via the GOSUB 9900 delay routine.
  • Lines 160–290: Main game loop — player movement, scrolling, random character placement, and collision detection.
  • Lines 290–420: Game-over screen, high score update, and replay prompt.
  • Lines 2000–2699: Quit/end animation sequence with a “crash” graphic and STOP.
  • Lines 2700–2740: Subroutine called on hitting an inverse character — FAST/SLOW flicker and “CRASH” message.
  • Lines 9000–9130: Animated intro: “CRASHER” scrolls in from top and bottom simultaneously, then jumps to line 11 (which routes to line 20, the instructions prompt).
  • Lines 9900–9920: General-purpose delay loop (50 iterations).
  • Lines 9990–9993: Utility lines: STOP, CLEAR, SAVE, RUN.

Game Loop Logic

The main loop runs from line 210 to 280. Each iteration:

  1. Prints a random character at the bottom of the screen (line 220). The character is either a normal printable character (CHR$ 1–63) or an inverse-video version if RND<0.2, achieved by adding 128 using the Boolean expression (128 AND RND<0.2).
  2. Calls SCROLL to advance the field upward (line 230).
  3. Reads the 5 and 8 keys to update horizontal position X (line 240), using Boolean arithmetic to clamp within columns 0–19.
  4. Prints the player “V” and positions the cursor at Y+1,X (line 250).
  5. PEEKs the display file to detect collision (lines 260–279).
  6. Increments frame counter F and loops until F=100 (lines 200–280).

Collision Detection via PEEK

Collision is detected at line 260 using the ZX81 system variables at addresses 16398 and 16399, which together hold the start address of the display file (D_FILE). The expression PEEK 16398 + 256*PEEK 16399 reconstructs the 16-bit pointer. PEEKing that address reads the character code of whatever is at the top-left of the display file, but because the cursor was left positioned at AT Y+1,X after printing the “V”, this effectively reads the character immediately below the player sprite — the cell into which the player is about to scroll.

  • If the value is less than 64 (a normal printable character), its code is added to the score S (line 270).
  • If the value is greater than 127, it is an inverse-video character; the flash/crash subroutine at 2700 is called (line 274) and the game ends (line 279 jumps to 290).

Notable Techniques

Boolean arithmetic for movement and character generation: Line 240 uses (INKEY$="8" AND X<19) and (INKEY$="5" AND X>0) as 1/0 values to increment or decrement X, a compact idiom. Line 220 uses (128 AND RND<0.2) similarly to conditionally set the inverse-video bit.

FAST/SLOW toggling for visual effect: The crash subroutine (lines 2700–2730) and parts of the quit animation (lines 2060–2090) toggle between FAST and SLOW modes in a loop, producing a screen-flicker effect that simulates an alarm or explosion.

Simultaneous top/bottom title animation: Lines 9020–9050 use a single FOR G loop to print “CRASHER” at both AT G,11 and AT 20-G,11, moving the two copies toward the centre of the screen symmetrically.

POKE 16384,74: At line 2150, the program POKEs the value 74 into address 16384. On the ZX81, address 16384 is the first byte of the system variable area (ERR_NR). Writing 74 sets the error code to 73 (value is stored as error−1), which corresponds to a specific system state; this is used here as a programmatic way to leave a particular condition before the subsequent STOP.

Flow Control and Routing

Line 9130 executes GOTO 11, which is a non-existent line number. The interpreter advances to the next higher line, which is line 20 (the instructions prompt). This is a deliberate and well-known ZX81 technique for falling through to the next defined line without hard-coding its number.

The GO TO VAL "number" idiom is not used here; all GOTO and GOSUB targets are literal. The replay prompt at line 400 sends the player back to line 155 (skipping the instructions display but still performing the delay and “READY??” message) rather than line 60, saving the full instructions re-display on replay.

Bugs and Anomalies

  • Line 51 is referenced in line 40 (IF U$="Y" THEN GOTO 51) but does not exist. Execution falls through to line 55, then to line 60 if U$ is not empty. The effect is that entering “Y” also shows instructions, which appears to be intended, but the GOTO 51 is slightly misleading — it should arguably read GOTO 60.
  • The player’s Y position is fixed at 10 (line 180) and never changes, meaning the player always occupies row 10. With SCROLL moving everything upward, the effective collision row stays constant.
  • The score accumulation at line 270 adds the raw character code (1–63) rather than a game-meaningful point value, so different characters score wildly different amounts based purely on their ASCII codes.
  • The input loop at lines 380–420 has no GOTO 380 fallback for invalid input, so entering anything other than “Y”, “N”, or “INS” silently loops back to the INPUT statement by the implicit behaviour of the INPUT line being re-executed — but only because the interpreter re-executes line 390 after lines 400–420 all fail their conditions and execution falls off the end of the program block back to the prompt. This is effectively a hidden loop.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10176 – 10210.

Related Products

Related Articles

Related Content

Image Gallery

Crasher

Source Code

   0 REM "CRASHER"                        PROGRAM CORE BY TIM             HARTNELL                        REVISIONS, INSTRUCTION          AND MOVING GRAPHIC              SCREENS BY                      ANTHONY WILLING
   3 CLS 
   5 LET HS=0
  10 GOTO 9000
  20 PRINT "%I%N%S%T%R%U%C%T%I%O%N%S%? (Y/N)"
  30 INPUT U$
  40 IF U$="Y" THEN GOTO 51
  50 IF U$="N" THEN GOTO 155
  55 IF U$="" THEN GOTO 20
  60 CLS 
  70 PRINT AT 0,0;"%C%R%A%S%H%E%R";AT 1,0;"-------"
  80 PRINT 
  85 PRINT 
  90 PRINT "YOU ARE THE ""V"".  YOUR JOB--"
  95 PRINT "CRASH INTO LETTERS AND NUMBERS,"
 100 PRINT "WHICH SCORES POINTS."
 105 PRINT 
 110 PRINT "YOU STEER WITH THE ""5"" AND ""8"""
 115 PRINT "KEYS"
 120 PRINT 
 125 PRINT "AVOID THE %I%N%V%E%R%S%E CHARACTERS--"
 130 PRINT "THEY ARE A MUTATED LIFE FORM,"
 135 PRINT "AND HITTING ONE OF THEM HEAD ON"
 137 PRINT "WILL END THE GAME"
 140 PRINT 
 141 PRINT "THE SCREEN WILL SHIFT 100 TIMES,"
 142 PRINT "THEN THE GAME ENDS."
 145 GOSUB 9900
 147 PRINT 
 148 PRINT 
 150 GOSUB 9900
 155 GOSUB 9900
 156 PRINT AT 20,11;"%R%E%A%D%Y%?%?"
 157 GOSUB 9900
 160 CLS 
 170 LET X=10
 180 LET Y=10
 190 LET S=0
 200 LET F=S
 210 LET F=F+1
 220 PRINT AT 20,INT (RND*20);CHR$ (INT (RND*63+1)+(128 AND RND<.2));AT Y,X;" "
 230 SCROLL 
 240 LET X=X+(INKEY$="8" AND X<19)-(INKEY$="5" AND X>0)
 250 PRINT AT Y,X;"V";AT Y+1,X;
 260 LET A=PEEK (PEEK 16398+256*PEEK 16399)
 270 IF A<64 THEN LET S=S+A
 274 IF A>127 THEN GOSUB 2700
 279 IF A>127 THEN GOTO 290
 280 IF F<100 THEN GOTO 210
 290 CLS 
 310 IF S>HS THEN LET HS=S
 330 PRINT "%G%A%M%E% %O%V%E%R","%S%C%O%R%E" 
 340 PRINT " ",S
 350 PRINT 
 360 PRINT "%H%I%G%H% %S%C%O%R%E ";HS
 370 PRINT 
 380 PRINT AT 11,0;"%L%I%K%E% %A%N%O%T%H%E%R% %T%R%Y%?%? (Y/N)"
 385 PRINT AT 15,0;"(%E%N%T%E%R INS %F%O%R% %I%N%S%T%R%U%C%T%I%O%N%S)"
 390 INPUT U$
 400 IF U$="Y" THEN GOTO 155
 410 IF U$="N" THEN GOTO 2000
 420 IF U$="INS" THEN GOTO 60
\n2000 CLS 
\n2009 PRINT AT 11,0;"% ";AT 11,30;"% "
\n2010 FOR E=1 TO 15
\n2015 PRINT AT 11,E-1;" ";AT 11,31-E;" "
\n2020 PRINT AT 11,E;"% ";AT 11,30-E;"% "
\n2030 NEXT E
\n2050 FOR Q=1 TO 20
\n2060 FAST 
\n2070 PRINT AT 11,14;"%  % "
\n2080 SLOW 
\n2090 NEXT Q
\n2100 PRINT AT 11,13;"%    % "
\n2110 PRINT AT 10,13;"/   /"
\n2115 PRINT AT 9,14;"*   *"
\n2120 PRINT AT 12,14;"OWW"
\n2125 GOSUB 9900
\n2130 CLS 
\n2135 PRINT AT 11,11;"%C%R%A%S%H%E%R"
\n2140 GOSUB 9900
\n2145 PRINT AT 11,10;"%G%A%M%E% %O%V%E%R"
\n2150 POKE 16384,74
\n2699 STOP 
\n2700 FOR Q=1 TO 20
\n2710 FAST 
\n2720 SLOW 
\n2730 NEXT Q
\n2735 PRINT AT 11,10;"%C%R%A%S%H"
\n2736 GOSUB 9900
\n2740 RETURN 
\n8999 STOP 
\n9000 PRINT AT 0,11;"%C%R%A%S%H%E%R";AT 20,11;"%C%R%A%S%H%E%R"
\n9010 GOSUB 9900
\n9020 FOR G=0 TO 9
\n9025 PRINT AT G-1,11;"       ";AT 21-G,11;"       "
\n9030 PRINT AT G,11;"%C%R%A%S%H%E%R";AT 20-G,11;"%C%R%A%S%H%E%R"
\n9045 PRINT AT 9,11;"       ";AT 11,11;"       "
\n9050 NEXT G
\n9060 PRINT AT 10,11;"%C%R%A%S%H%E%R"
\n9070 FOR Q=1 TO 20
\n9080 FAST 
\n9090 SLOW 
\n9100 NEXT Q
\n9110 GOSUB 9900
\n9115 GOSUB 9900
\n9120 PRINT AT 10,11;"       "
\n9130 GOTO 11
\n9900 FOR P=1 TO 50
\n9910 NEXT P
\n9920 RETURN 
\n9990 STOP 
\n9991 CLEAR 
\n9992 SAVE "1019%5"
\n9993 RUN 

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

Scroll to Top