Demolish

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Game

Demolish is a Breakout-style ball-and-paddle game in which the player deflects a bouncing ball to knock out a row of blocks displayed across the screen. The paddle is controlled by pressing “5” (left) and “8” (right), the standard cursor keys, and the ball reflects off the walls, the paddle, and the block row using sign-flipped direction variables. Two UDGs are defined at startup via POKE USR: one for the ball sprite and one for paddle segments. Speed is user-selectable at the start of each game (1 = fast, 10 = extra slow), implemented as a FOR-NEXT delay loop. The game tracks a block-hit counter and ends after 10 missed balls, then offers a replay prompt.


Program Structure

The program is organized into a main game loop and several subroutines, initialized by a chain of GO SUBs at lines 30–50:

  1. Line 380–400 — UDG loader: reads DATA and POKEs two custom character shapes.
  2. Lines 290–370 — Initialization: sets border/paper/ink colors, initializes all game variables, and prompts for speed.
  3. Lines 260–280 — Screen setup: prints the score/ball header and draws the block row using a FOR loop over PI (i.e., 3 iterations, rows of underscores in INK and INVERSE).
  4. Lines 60–170 — Main game loop: moves paddle, scrolls score, erases ball, moves ball, handles collisions, redraws ball, detects loss conditions, and loops back to line 60.
  5. Lines 190–220 — Ball-lost subroutine: resets ball position and increments miss count.
  6. Lines 230–250 — Game-over screen with replay logic.

UDG Definition

Lines 380–420 define two UDGs using READ and POKE USR. UDG-A (the ball) is a filled circle shape (DATA: 60,126,255,…). UDG-B (paddle segments) is a mostly-solid bar shape. Notably the DATA at lines 410–420 contains the literal token u as a placeholder in several byte positions — these would resolve to whatever value BASIC assigns to the variable u at that point, which is uninitialized and therefore 0, so the UDG bytes at those positions are effectively zero (empty rows). This is an anomaly: the programmer likely intended specific byte values rather than the variable u.

Ball Physics

The ball position is tracked by row e and column f, with direction controlled by c (vertical, ±1) and d (horizontal, ±1). Collision detection is entirely SCREEN$-based:

  • Line 100: if e < 2, reverse vertical direction (top wall).
  • Line 110: if f < 1 or f > 30, reverse horizontal direction (side walls).
  • Line 120: if the character at the ball’s position is "_" (a block), increment score, reverse vertical direction, and beep.
  • Line 130: same block-hit condition also increments count; when count equals 32+s (all blocks cleared, accounting for speed value), reset and redraw the block row.
  • Line 140: if the position is a space (the paddle area), reverse vertical direction — this is how paddle contact is detected.

Paddle Movement

Line 70 moves the paddle variable v in a single compound expression: v = v + 2*(INKEY$="8" AND v<27) - 2*(INKEY$="5" AND v>0). Boolean expressions in Spectrum BASIC evaluate to 1 (true) or 0 (false), making this an efficient branchless movement idiom. The paddle moves two columns per frame. There is a minor anomaly: the second part of line 70 checks v<0 for a boundary print correction, but the earlier guard already prevents v from going below 0, so that branch is unreachable.

Speed Control

The user enters a speed value s (1–10) at line 350. This feeds directly into a FOR a=1 TO s: NEXT a delay loop at line 80, run once per game-loop iteration. Higher values of s create longer delays and slower ball movement. The same variable also adjusts the block-clear threshold at line 130 (count=(32+s)), meaning a slower-speed game requires more hits to clear the row — a side effect rather than intentional design.

Game-Over and Replay

Line 160 checks b=10 (ten missed balls) and jumps to the game-over routine at line 230. The INPUT prompt at line 250 uses IF NOT a$="" THEN STOP — pressing ENTER (empty string) falls through to GO TO 40 to restart, while typing anything causes a STOP. This is an unusual replay idiom: most programs treat any keypress as “continue.”

Notable Anomalies

  • The DATA statements (lines 410–420) use the bare token u, which is interpreted as the variable u (value 0) rather than a numeric constant, producing incorrect UDG bitmaps for those byte positions.
  • Line 70’s boundary print correction (v<0) is unreachable because the movement expression already clamps v to ≥ 0.
  • Line 130’s block-clear threshold 32+s unintentionally couples game speed to the number of hits required to clear blocks.
  • The FOR loop at line 260 iterates FOR a=1 TO PI; since BASIC truncates PI to 3, this draws exactly three rows of blocks.

Source Code

  10 REM DEMOLISH from Games for Your Timex-Sinclair 2000, p.44
  20 REM "5" moves left, "8" moves right
  30 GO SUB 380
  40 GO SUB 290
  50 GO SUB 260
  60 PRINT AT 20,v;"  [UDG-B][UDG-B][UDG-B]  "
  70 LET v=v+2*(INKEY$="8" AND v<27)-2*(INKEY$="5" AND v>0):IF INKEY$="5" AND v<0 THEN PRINT AT 20,1;"__  "
  80 PRINT AT 0,0;"SCORE ";sc:FOR a=1 TO s:NEXT a
  90 PRINT AT e,f;" "
 100 LET e=e+c:IF e<2 THEN LET c=-c:BEEP .008,20
 110 LET f=f+d:IF f<1 OR f>30 THEN LET d=-d:BEEP .008,10
 120 IF SCREEN$ (e,f)="_" THEN LET sc=sc+1:LET c=-c:BEEP .008,15
 130 IF SCREEN$ (e,f)="_" THEN LET count=count+1:IF count=(32+s) THEN LET count=0:LET s=s-(s+1):GO TO 50
 140 IF SCREEN$ (e,f)="" THEN LET c=-c:BEEP .008,15
 150 PRINT AT e,f; INK 6;"[UDG-A]":IF e>20 THEN LET b=b+1:GO SUB 190
 160 IF b=10 THEN GO TO 230
 170 GO TO 60
 180 STOP 
 190 PRINT AT e,f;" "
 200 LET e=20:LET f= INT (RND*16)+10:LET c=-1
 210 PRINT AT 0,25;"BALL ";b
 220 RETURN 
 230 PRINT AT 10,12;"GAME OVER"
 240 PRINT ''"           You scored ";sc
 250 INPUT "Press ENTER to play again ";a$:IF NOT a$="" THEN STOP :GO TO 40
 260 PRINT AT 0,0;"SCORE 0"; AT 0,25;"BALL 1":FOR a=1 TO PI
 270 PRINT ' INK a+2; INVERSE 1;"________________________________"
 280 NEXT a:RETURN 
 290 BORDER 0:PAPER 1:INK 7:CLS 
 300 LET v=15
 310 LET c=-1:LET d=1
 320 LET sc=0
 330 LET e=20:LET f= INT (RND*15)+10
 340 LET b=1
 350 INPUT "           WHAT SPEED?"'''"   (1- FAST,  10- EXTRA SLOW) ";s
 360 LET count=0
 370 RETURN 
 380 FOR a=0 TO 15
 390 READ u:POKE USR "[UDG-A]"+a,u
 400 NEXT a:RETURN 
 410 DATA 60,126,255,u,u,u,126,60
 420 DATA 0,u,u,u,u,u,255,u
 430 REM a=[UDG-A] b=[UDG-B]
 440 SAVE "demo" LINE 10:BEEP .4,15

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