Skip to content

Break one brick

Separate a brick picture, its rectangle and its stored live state.

  • Sinclair ZX Spectrum
  • BASIC

One brick is enough to test destruction. Put it in the lower-right part of the future wall, give it an alive flag, and end this small challenge when it disappears.

Replace lines 100, 300, 390, 1010, 7000.

Add lines 440, 450, 460, 470, 480, 1040, 2000, 2010, 2020, 2030, 2500, 2510, 2520, 7010, 7200, 7210, 7220.

changes.bas
 100 LET alive=1: LET left=1: LET p=14: LET x=127: LET y=40
 300 IF k$=" " THEN LET served=1: PRINT AT 1,2;"Clear every brick.     ": GO TO 350
 390 IF ny>=32 THEN GO TO 440
 440 LET tx=nx: LET ty=y: GO SUB 2000
 450 IF hit=1 THEN LET dx=-dx: LET nx=x: GO SUB 2500
 460 LET tx=nx: LET ty=ny: GO SUB 2000
 470 IF hit=1 THEN LET dy=-dy: LET ny=y: GO SUB 2500
 480 IF left=0 THEN LET e$="Brick cleared! Nicely done.": GO TO 4000
1010 PRINT AT 0,2; INK 5;"BRICK BASH";AT 0,21; INK 7;"BRICKS 1"
1040 PRINT AT 8,24; INK 5;b$
2000 LET hit=0
2010 IF alive=0 THEN RETURN
2020 IF tx+1 <192 OR tx>215 OR ty+1 <104 OR ty>111 THEN RETURN
2030 LET hit=1: RETURN
2500 LET alive=0: LET left=0
2510 PRINT AT 8,24;"   ";AT 0,28; INK 7;left;" "
2520 RETURN
7000 RESTORE 7200: FOR j=0 TO 47: READ v: POKE USR "a"+j,v: NEXT j
7010 LET b$=CHR$ 144 +CHR$ 145 +CHR$ 146
7200 DATA 127,255,255,255,255,255,255,127
7210 DATA 255,255,255,255,255,255,255,255
7220 DATA 254,255,255,255,255,255,255,254

RUN the changed program.

Complete source at this checkpoint
brick-bash.bas
  10 GO SUB 7000
 100 LET alive=1: LET left=1: LET p=14: LET x=127: LET y=40
 110 LET dx=4: LET dy=4: LET served=0: LET steps=0
 130 GO SUB 1000: GO SUB 3000
 200 LET k$=INKEY$
 210 IF k$="q" OR k$="Q" THEN GO TO 9000
 220 IF k$="r" OR k$="R" THEN GO TO 100
 230 LET oldp=p
 240 IF k$="o" OR k$="O" THEN LET p=p-1
 250 IF k$="p" OR k$="P" THEN LET p=p+1
 260 IF p<2 THEN LET p=2
 270 IF p>26 THEN LET p=26
 280 IF p<>oldp THEN PRINT AT 18,oldp;"    ";AT 18,p; INK 7;p$
 290 IF served=1 THEN GO TO 350
 300 IF k$=" " THEN LET served=1: PRINT AT 1,2;"Clear every brick.     ": GO TO 350
 310 IF p=oldp THEN GO TO 200
 320 GO SUB 3000: LET x=8 *p+15: GO SUB 3000: GO TO 200
 350 LET nx=x+dx: LET ny=y+dy
 360 IF nx<16 THEN LET nx=32 -nx: LET dx=ABS dx
 370 IF nx>238 THEN LET nx=476 -nx: LET dx=-ABS dx
 380 IF ny>149 THEN LET ny=298 -ny: LET dy=-ABS dy
 390 IF ny>=32 THEN GO TO 440
 400 IF nx+1 <8 *p OR nx>8 *p+31 THEN LET e$="Missed! R for another go.": GO TO 4000
 410 LET ny=64 -ny: LET dy=4
 440 LET tx=nx: LET ty=y: GO SUB 2000
 450 IF hit=1 THEN LET dx=-dx: LET nx=x: GO SUB 2500
 460 LET tx=nx: LET ty=ny: GO SUB 2000
 470 IF hit=1 THEN LET dy=-dy: LET ny=y: GO SUB 2500
 480 IF left=0 THEN LET e$="Brick cleared! Nicely done.": GO TO 4000
 490 GO SUB 3000
 500 LET x=nx: LET y=ny: LET steps=steps+1
 510 GO SUB 3000: GO TO 200
1000 BORDER 0: PAPER 0: INK 7: CLS
1010 PRINT AT 0,2; INK 5;"BRICK BASH";AT 0,21; INK 7;"BRICKS 1"
1020 PRINT AT 1,2;"SPACE serves. O/P move."
1030 PLOT INK 1;15,16: DRAW INK 1;0,136: DRAW INK 1;225,0: DRAW INK 1;0,-136
1040 PRINT AT 8,24; INK 5;b$
1080 PRINT AT 18,p; INK 7;p$
1090 PRINT AT 21,2; INK 5;"O/P move  R retry  Q quit";
1100 RETURN
2000 LET hit=0
2010 IF alive=0 THEN RETURN
2020 IF tx+1 <192 OR tx>215 OR ty+1 <104 OR ty>111 THEN RETURN
2030 LET hit=1: RETURN
2500 LET alive=0: LET left=0
2510 PRINT AT 8,24;"   ";AT 0,28; INK 7;left;" "
2520 RETURN
3000 PLOT INK 7; OVER 1;x,y: DRAW INK 7; OVER 1;1,0: DRAW INK 7; OVER 1;0,1: DRAW INK 7; OVER 1;-1,0: RETURN
4000 PRINT AT 1,0;"                                ";AT 1,2; INK 6;e$
4010 PRINT AT 21,2; INK 7;"R plays again       Q quits   ";
4020 IF INKEY$<>"" THEN GO TO 4020
4030 LET k$=INKEY$
4040 IF k$="q" OR k$="Q" THEN GO TO 9000
4050 IF k$="r" OR k$="R" THEN GO TO 100
4060 GO TO 4030
7000 RESTORE 7200: FOR j=0 TO 47: READ v: POKE USR "a"+j,v: NEXT j
7010 LET b$=CHR$ 144 +CHR$ 145 +CHR$ 146
7020 LET p$=CHR$ 147 +CHR$ 148 +CHR$ 148 +CHR$ 149: RETURN
7200 DATA 127,255,255,255,255,255,255,127
7210 DATA 255,255,255,255,255,255,255,255
7220 DATA 254,255,255,255,255,255,255,254
7230 DATA 63,127,127,63,0,0,0,0
7240 DATA 255,255,255,255,0,0,0,0
7250 DATA 252,254,254,252,0,0,0,0
9000 PAPER 0: INK 7: PRINT AT 21,0;"Finished. RUN to try again.     ";: STOP

Three characters, one rectangle

The brick uses custom characters a, b and c, codes 144–146. The middle is eight rows of 255. The left end uses 127 for its first and last rows and 255 between them; the right uses 254 at its ends. Those missing outer corner pixels soften the shape.

The loader now begins at DATA line 7200 and fills all 48 bytes for the six characters. The existing paddle data follows the three new brick characters. b$ joins the brick’s left, middle and right pieces.

PRINT AT 8,24 places this brick at character row 8, column 24. Its logical rectangle is x=192–215, y=104–111. Collision includes the tiny unlit corners. That is a choice about the game’s shape, not a test of ink colour.

Ask before changing

alive=1 means the brick remains. The query routine at 2000 accepts a candidate ball position in tx and ty. It starts with hit=0, returns immediately if the brick is gone, and rejects separation on either axis. If none of those rejections applies, hit becomes 1.

For the vertical check, the ball spans ty to ty+1. For the horizontal check, it spans tx to tx+1. RETURN leaves the query with its answer; the query itself does not erase the brick or alter the ball.

Resolve one axis, then the other

Line 440 tests the proposed horizontal position at the old height: tx=nx, ty=y. On contact, line 450 reverses dx, rejects that horizontal displacement by restoring nx=x, and removes the brick.

Line 460 then tests the resolved horizontal position at the proposed height. On contact, line 470 reverses dy and restores ny=y before removing the brick.

This order settles diagonal corners. Suppose the ball is at (191,100) and proposes (195,104). The horizontal test at (195,100) is below the brick. The vertical test at (195,104) hits, so y stays 100 and dy reverses. This is a discrete game rule, not an exact calculation of a billiard ball’s path.

If the horizontal test removes the brick, can the vertical test remove it again?

Show the explanation

No. Removal sets alive to 0. The next query returns with hit=0 before testing the rectangle, so the same brick cannot be removed twice.

Make removal visible

Routine 2500 changes the stored flag and remaining count, prints three spaces over the brick and updates the count. State and display change together. The result check at 480 runs before the next ball position is committed, so a win freezes the previous valid ball position.

One-brick challenge completed, with BRICKS 0 and a retry prompt.
Removing the one stored brick completes this small challenge.

RUN, serve and break the brick. Retry and serve from another paddle position to change the approach. Watch the count become zero once. A miss should still offer R/Q, and retry must restore the brick.

If an invisible brick keeps bouncing the ball, check alive at removal. If the picture stays after a win, check the erase position at line 2510. Keep the movement size at four pixels while testing these rules; larger steps would need a fresh check for jumping across objects.

Sources

Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 6, 14 and 17. The court dimensions, collision rules and artwork are choices made for this game.

Run it here

This unit's program, built for you.

Program
brick-bash.tap
Machine
ZX Spectrum 48K (PAL)

Download brick-bash.tap