Demolition is a single-player arcade game in which the player launches a ball from the top of the screen to demolish a scrolling brick wall advancing from the bottom. The game supports five selectable difficulty levels, controlled by the variable `d`, which affects how many button presses are required before the wall advances. A high-score table stores the top ten entries across five difficulty levels using parallel string and numeric arrays (`s$` and `s`), with names entered via LINE input. User-defined graphics (UDGs A, B, and C) are used for the brick, ball-trail, and ball characters respectively, and a machine code routine is POKEd into low memory at startup (addresses 0–41) to perform collision detection, with its result read via `USR USR “d”`. The program uses `ATTR` reads at lines 380–390 to detect when the ball contacts the wall, awarding points by calculating the blast radius left and right of the impact column.
Program Analysis
Program Structure
The program is organized into clearly separated functional blocks:
- Lines 10–80: Initialization — sound, system setup, subroutine calls, and jump to title/difficulty screen.
- Lines 90–130: Game setup — screen colors, wall drawing, score display, and random ball start direction.
- Lines 140–200: Ball movement loop — bouncing the ball across the top row, waiting for a keypress to launch.
- Lines 210–270: Wall advance logic — incrementing the wall counter
cand updating the wall display, then checking for collision via machine code. - Lines 280–470: Ball drop and demolition — the ball falls from the top, hits the wall, and the blast radius is calculated left and right to award points.
- Lines 480–530: Game-over sequence — the wall reaches the player; an animated sweep plays across row 0.
- Lines 540–600: High-score table insertion — comparison and sorting into the parallel arrays.
- Lines 610–690: High-score display — scores shown interleaved by difficulty level.
- Lines 700–730: Wall-draw subroutine — prints five rows of UDG-A bricks in random ink colors on a black paper background.
- Lines 740–840: Title and difficulty selection screen.
- Lines 850–880: One-time initialization subroutine — POKEs machine code, dimensions score arrays, and sets default name strings.
- Lines 890–920: Machine code DATA.
- Line 930: CLEAR and SAVE with auto-run.
Machine Code Usage
Lines 850 and 890–920 load 42 bytes of machine code into addresses 0–41 via a READ/POKE loop. The routine is invoked at line 270 with the idiom USR USR "d". The inner USR "d" returns the address of UDG “D” in the UDG table, and the outer USR calls the machine code at that address. The return value is compared to 65535 (t<>65535) to detect a collision condition — when the wall has reached the ball’s row. The DATA at line 920 includes a Z80 loop: LD HL,nn, LD BC,nn, AND A, SBC HL,BC, JR NZ, LD BC,0FFFFh, RET — a countdown-style scan returning a sentinel value.
Note: the DATA lines use x as a variable in the DATA statements (lines 890–920), which at runtime holds the last value assigned to x in the ball-movement loop. This is an unusual technique — the machine code bytes that happen to coincide with x‘s current value are inserted dynamically rather than being fixed constants. This could cause subtle bugs if x has an unexpected value during initialization, since GO SUB 850 is called before the game loop sets x.
Difficulty and Wall Mechanics
The difficulty value d (1–5, where 1 is hardest) is selected at line 820. The counter b is incremented each time the player fires (line 190), and the wall only advances when b >= d (line 210). A lower d means the wall advances more frequently. The wall position counter c runs from 0 to 9, wrapping back to 0 at 10 (line 220). When c=5, the wall string w$ is set to a full row of UDG-A bricks; when c=0, it is reset to a color-control-character sequence (line 240), producing a new randomly colored wall row.
Ball Movement and ATTR-Based Collision
The ball bounces horizontally across row 0 using dx (+1 or -1) and reflects at the screen edges (line 170). On a keypress, the ball drops vertically in a loop (lines 300–350), checking ATTR(y,x) at each row. The attribute value a=48 (PAPER 6, INK 0 — the wall’s attribute) is used as the wall-detection sentinel. When the ball lands on the wall, the blast radius is expanded left (lx) and right (rx) simultaneously (lines 380–470), awarding 5 points per brick destroyed and playing a tone pitched by distance from center.
High Score Table
The score table uses two parallel arrays: s$(10,10) for names (10 entries of up to 10 characters) and s(10) for numeric scores. Odd indices (1,3,5,7,9) store the top score for each of the five difficulty levels; even indices store the second score per level. Insertion at lines 590–600 performs a simple two-slot comparison. The display at lines 630–680 uses two interleaved FOR loops with OVER 1 printing to overlay the level labels printed earlier.
Key BASIC Idioms
LET dx=(r>5)-(r<=5)— Boolean arithmetic to set direction: evaluates to +1 or -1 depending on the random value ofr.POKE 23692,255— Disables the scroll prompt by setting the system variable SCRCT to 255, preventing “scroll?” interruptions during wall updates.POKE 23658,8/POKE 23658,0— Enables and disables CAPS LOCK for name entry.LET lx=lx-(lx>0)andLET rx=rx+(rx<31)— Boundary-clamped left/right expansion using Boolean expressions as increments.PRINT AT PI,0at line 650 —PItruncates to 3, so this positions the cursor at row 3. An unconventional but valid use of a floating-point constant as a row index.LINE w$in theINPUTat line 560 — accepts the entire line including spaces without requiring quotes.
UDG Usage
| UDG | Role |
|---|---|
[UDG-A] | Brick tile, used to fill the wall rows |
[UDG-B] | Ball-trail or sweep graphic used in the game-over animation |
[UDG-C] | Ball character, displayed moving along row 0 and dropping |
[UDG-D] | Not displayed; its USR address is used to call the machine code routine |
Bugs and Anomalies
- The DATA statements at lines 890–920 use the variable
xfor several byte values. SinceGO SUB 850is called at line 30 beforexis ever assigned in the game loop,xwill be 0 at that point, so those bytes are written as 0. This is likely intentional — 0 is a valid Z80 NOP or padding byte in those positions — but it is fragile and not self-documenting. - At line 220, when
c>=10, it is set tob, which was just reset to 0. This is equivalent toLET c=0but is an indirect and potentially confusing assignment. - Line 570 checks
LEN w$ > 10and displays an error at row 7, column 4. However, theINPUTat line 560 usesLINEinput which can accept any length; the error message instructs the user to re-enter, but theGO TO 560loops back to the full INPUT prompt correctly.
Source Code
10 BEEP .5,10
20 POKE 23658,0
30 GO SUB 850
40 PAPER 7:INK 0:BORDER 7:CLS
50 PRINT #1; AT 0,0; TAB 8;"PRESS ANY KEY",
60 PAUSE 0
70 LET s=0:LET b=s:LET c=-1:LET a=48
80 GO TO 740
90 INK 0:PAPER 6:BORDER 7:CLS
100 GO SUB 700
110 PRINT #1; AT 0,0;"SCORE:0","HIGH SCORE:";s(d*2-1)
120 LET r= INT (RND*10+1)
130 LET dx=(r>5)-(r <=5):LET x=31*(r <=5)
140 LET x1=x
150 LET k$= INKEY$
160 LET x=x+dx
170 IF x>31 OR x<0 THEN LET dx=-dx:GO TO 160
180 PRINT AT 0,x;"[UDG-C]"; AT 0,x1;" "
190 IF k$ <>"" THEN LET b=b+1:GO TO 210
200 GO TO 140
210 IF b<d THEN GO TO 280
220 LET b=0:LET c=c+1:IF c >=10 THEN LET c=b
230 IF c=5 THEN LET w$="[UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A]"
240 IF c=0 THEN LET w$= CHR$ 17+ CHR$ 6+ CHR$ 16+ CHR$ 0+ CHR$ 6+ CHR$ 6
250 POKE 23692,255:PRINT #1; AT 0,0,,#2; AT 21,0' PAPER 0; INK INT (RND*6+1);w$;#1; AT 0,0;"SCORE:";s,"HIGH SCORE:";s(d*2-1)
260 PRINT AT 0,x;"[UDG-C]"
270 LET t= USR USR "d":IF t <>65535 THEN GO TO 480
280 BEEP .03,12
290 LET y=0
300 LET y1=y
310 LET y=y+1
320 IF y>21 THEN PRINT AT y1,x;" ":GO TO 120
330 IF ATTR (y,x) <>a THEN GO TO 360
340 PRINT AT y,x;"[UDG-C]"; AT y1,x;" "
350 GO TO 300
360 PRINT AT y1,x;" "
370 LET lx=x:LET rx=x
380 LET l= ATTR (y,lx)
390 LET r= ATTR (y,rx)
400 IF l=a AND r=a THEN GO TO 120
410 IF l <>a AND lx <>rx THEN LET s=s+5:BEEP .01,10+x-lx
420 IF r <>a THEN LET s=s+5:BEEP .01,10+rx-x
430 PRINT #1; AT 0,6;s
440 PRINT AT y,lx;" "; AT y,rx;" "
450 LET lx=lx-(lx>0):LET rx=rx+(rx<31):LET y=y-1
460 IF y<0 THEN GO TO 120
470 GO TO 380
480 FOR i=0 TO 31-t
490 PRINT INK 0; PAPER 7; AT 0,i; OVER 0;"[UDG-B]"
500 BEEP .05,31-i
510 NEXT i
520 PRINT AT 0,i; OVER 1; INK 8;" "
530 LET x=d*2:LET y=x-1
540 IF s<s(x) THEN GO TO 610
550 POKE 23658,8
560 INPUT PAPER 7; INK 0; AT 0,0;"You made it to the SCORE TABLE","ENTER NAME: ? ", AT 1,12; LINE w$
570 IF LEN w$>10 THEN PRINT AT 7,4;"ONLY 10 Letters PLEASE!":GO TO 560
580 POKE 23658,0
590 IF s >=s(y) THEN LET s$(x)=s$(y):LET s(x)=s(y):LET s$(y)=w$:LET s(y)=s:GO TO 610
600 IF s >=s(x) THEN LET s$(x)=w$:LET s(x)=s
610 CLS
620 PRINT AT 1,10;"HIGH SCORES:"
630 PRINT AT 4,0;
640 FOR i=1 TO 5:PRINT TAB 5;"LEVEL ";i''':NEXT i
650 PRINT AT PI,0
660 FOR i=1 TO 10 STEP 2:PRINT OVER 1; TAB 14; BRIGHT 1;s$(i); TAB 25;s(i)''':NEXT i
670 PRINT AT 4,0
680 FOR i=2 TO 10 STEP 2:PRINT OVER 1; TAB 14;s$(i); TAB 25;s(i)''':NEXT i
690 GO TO 50
700 LET w$="[UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A][UDG-A]"
710 FOR i=17 TO 21
720 PRINT PAPER 0; INK INT (RND*6+1); AT i,0;w$
730 NEXT i:RETURN
740 PAPER 7:INK 0:BORDER 7:CLS
750 PRINT AT 1,11; INK 0; PAPER 7;"DEMOLITION"
760 PRINT ''" Try to gain points as you"''" DEMOLISH the advancing wall"''" before it reaches you."
770 PRINT '''" To launch the ball-"
780 PRINT '" PRESS the SPACEBAR"
790 PRINT #1; AT 0,0; INK 0; PAPER 6;"SELECT DIFFICULTY ? (1-5):1=HARD"
800 LET w$= INKEY$
810 IF w$<"1" OR w$>"5" THEN GO TO 790
820 LET d= VAL w$(1)
830 PRINT #1; AT 0,0; INK 0; PAPER 6;" PRESS ANY KEY TO START GAME ":PAUSE 0
840 GO TO 90
850 RESTORE 890:FOR i=0 TO 41:READ x:POKE i,x:NEXT i
860 DIM s$(10,10):DIM s(10)
870 FOR i=1 TO 10:LET s$(i)="..........":NEXT i
880 RETURN
890 DATA 0,126,x,x,x,x,x,0
900 DATA 96,24,06,255,x,06,24,96
910 DATA 24,36,24,60,126,x,60,24
920 DATA 33,0,65,1,32,0,126,254,126,200,35,13,32,-8,1,255,x,201
930 CLEAR :SAVE "Demolition" LINE 10:BEEP .2,15Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

