Dam Buster

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

Dam Buster is a side-scrolling bomber game in which the player pilots an aircraft across a landscape and drops bombs onto a dam. The plane sprite is composed of four UDGs (A–D), with additional UDGs for bomb drop animation (E, F, G) and the dam structure (H, I), all defined by 72 bytes of DATA POKEd into USR memory at lines 630–740. Joystick input is read via STICK to trigger bomb release, and SCREEN$ collision detection is used both to detect dam hits and to track whether the bomb has cleared the structure. Scoring increments each horizontal step, with a 100-point bonus awarded for completing a full pass, and a persistent high-score variable survives between games within the same session.


Program Structure

The program is organized into a main loop and several subroutines. Execution begins at line 10, which calls the UDG initialization routine (line 630) and sets the high-score variable hi to zero. Lines 20–160 form the core game loop, iterating over rows (v, 1–15) and columns (h, 0–31) to scroll the plane across the screen. Key subroutines are:

  • Line 170 – Draws the plane sprite (four UDGs A–D) at position (v, h).
  • Line 180–420 – Handles bomb drop animation and collision with the dam.
  • Line 430–460 – Handles the plane-hits-dam explosion sequence.
  • Line 470 – Awards a 100-point completion bonus and displays “GAME OVER”.
  • Line 480–520 – Displays scores and waits for joystick restart.
  • Line 540–600 – Draws the dam using UDGs H and I with PAPER coloring.
  • Line 610–620 – Initializes display and resets per-game variables.
  • Line 630–650 – POKEs all nine UDG bitmaps into memory.
  • Lines 660–750 – DATA statements for UDG bitmaps, with a REM at line 750 mapping letter labels to UDG characters.

UDG Definition and Sprite Design

Nine UDGs (A through I) are defined by 72 bytes of DATA across lines 660–740. The subroutine at line 630 uses a FOR loop from 0 to 71, READing each byte and POKEing it to USR "[UDG-A]" + a, which fills UDGs A–I sequentially since each UDG occupies 8 bytes. UDGs A–D form the four-character-wide plane body; E and F are used for the bomb-drop entry frames; G is the falling bomb; H and I construct the dam wall. The DATA contains several entries labeled u — these appear to be a placeholder or token artifact and would read as the value of an uninitialized or re-used variable u at runtime, likely evaluating to 0, effectively producing blank rows in some sprite frames.

Collision Detection via SCREEN$

The game relies entirely on SCREEN$ for collision detection rather than coordinate mathematics. At line 80, SCREEN$(v, h+6) is tested: if it is not a space, the plane has struck the dam and execution jumps to the explosion handler at line 430. During the bomb drop (lines 270–330), SCREEN$(b+2, b1) is checked each row to detect whether the bomb has hit the dam structure below. This approach is straightforward but ties gameplay logic directly to screen state, meaning any stray character could trigger a false collision.

Bomb Drop Mechanics

When the player fires (STICK input at line 90), the subroutine at line 180 is called. The bomb is animated downward in a FOR b loop (lines 260–330), printing the bomb UDG one row at a time while simultaneously advancing the plane position (h and v are incremented at lines 200, 230, 300). A BEEP with pitch b provides audio feedback on each row of descent. If the bomb reaches the bottom without hitting anything, the loop exits cleanly at line 340–360; if a collision is detected, lines 370–420 handle a small secondary animation and return. The horizontal bomb position b1 is fixed at the release column, while the plane continues moving.

Scoring and State Management

The score variable sc is incremented by 1 at line 100 for every column the plane advances, rewarding survival distance. A bonus of 100 is added at line 470 for completing a full pass. The high score hi persists across games in the same session (set once at line 10, updated at line 490). The variable ch acts as a one-shot flag: initialized to 1 at line 620, it is cleared to 0 at line 130 when the dam opening is detected, gating a sound effect at line 110 using the AND idiom (.008 AND ch=1).

Key BASIC Idioms

  • Boolean AND arithmetic: Lines 110 uses (.008 AND ch=1)+(.01 AND ch=0) to select a BEEP duration based on the flag, avoiding an IF/THEN branch.
  • Inline screen clearing: PRINT strings of spaces with PAPER attributes erase sprites without CLS, preserving other screen content.
  • STICK polling: Lines 90 and 510 read joystick port 2 direction 2 to detect fire/action input.
  • Trailing comma in PRINT: Line 580 ends with a comma to suppress the newline, and line 600 uses PRINT PAPER 2,, with double commas for tab advancement when drawing the dam’s base rows.

Anomalies and Notable Points

  • The DATA values labeled u at lines 660–740 are syntactically valid BASIC — u is read as a numeric variable. If u is never assigned, it defaults to 0, making those sprite rows blank. This is likely intentional for padding but could be confusing as source code.
  • Line 530 (INPUT "Press ENTER to play again."; LINE a$: GO TO 20) is unreachable — execution never falls through to it because line 520 loops back to 510 indefinitely. The restart path goes through line 510’s STICK check directly to line 20.
  • The plane position variables v and h are modified inside the bomb-drop subroutine (lines 200, 230, 300), causing the plane to advance while the bomb is in flight. This produces a realistic offset but means the outer loop’s NEXT h at line 140 continues from the already-advanced h value.
  • Line 80 checks SCREEN$(v, h+6) rather than h itself, accounting for the four-UDG width of the plane sprite to detect the leading edge of the dam.

Image Gallery

Source Code

  10 GO SUB 630:LET hi=0
  20 GO SUB 610
  30 GO SUB 540
  40 FOR v=1 TO 15
  50 PRINT AT v-1,0; PAPER 8;"     "
  60 FOR h=0 TO 31
  70 GO SUB 170
  80 IF SCREEN$ (v,h+6) <>" " THEN GO TO 430
  90 IF STICK (2,2)=1 THEN GO SUB 180
 100 LET sc=sc+1
 110 BEEP (.008 AND ch=1)+(.01 AND ch=0),0
 120 IF ch=0 THEN GO TO 140
 130 IF (SCREEN$ (13,16)=" " AND SCREEN$ (13,17)=" " AND SCREEN$ (13,18)=" ") THEN LET ch=0:PRINT AT 13,0;"                  "; AT 14,20; INK 2; PAPER 1;"[UDG-H]           "; AT 13,16; PAPER 0;"  "
 140 NEXT h
 150 NEXT v
 160 GO TO 470
 170 PRINT AT v,h; INK 6; PAPER 8;" [UDG-A][UDG-B][UDG-C][UDG-D]":RETURN 
 180 PRINT AT v+1,h; INK 5; PAPER 8;" [UDG-E]"
 190 GO SUB 170
 200 LET h=h+1:IF h>30 THEN LET v=v+1:LET h=0
 210 PRINT AT v+1,h; INK 5; PAPER 8;" [UDG-F]"
 220 GO SUB 170
 230 LET h=h+1:IF h>30 THEN LET v=v+1:LET h=0
 240 PRINT AT v+2,h; PAPER 8; INK 6;" "
 250 LET b1=h
 260 FOR b=v+1 TO 14
 270 BEEP .01,b
 280 PRINT AT b,b1; PAPER 8; INK 5;" "; AT b+1,b1;"[UDG-G]"
 290 GO SUB 170
 300 LET h=h+1:IF h>30 THEN LET v=v+1:LET h=0
 310 IF SCREEN$ (b+2,b1) <>" " THEN GO TO 370
 320 PRINT AT v-1,31;" "
 330 NEXT b
 340 PRINT AT b,b1; PAPER 8;" "
 350 LET h=h-1
 360 RETURN 
 370 FOR b=b TO b+1
 380 PRINT AT b,b1; PAPER 8;" "; AT b+1,b1; INK 5;"[UDG-G]"
 390 NEXT b
 400 BEEP .005,-b
 410 LET h=h-1:PRINT AT b,b1; PAPER 8;" "
 420 RETURN 
 430 FOR a=v TO 15
 440 PRINT AT a,h+1; PAPER 1;"    "; AT a+1,h+1; INK 6;"[UDG-A][UDG-B][UDG-C][UDG-D]"
 450 BEEP .5,-a:NEXT a
 460 GO TO 480
 470 LET sc=sc+100:PRINT AT 0,12;"GAME OVER"
 480 PRINT AT 5,10;"You Scored  ";sc
 490 IF sc>hi THEN LET hi=sc
 500 PRINT AT 10,6;"Highest Score ";hi
 510 IF STICK (2,2)=1 THEN GO TO 20
 520 GO TO 510
 530 INPUT "Press ENTER to play again."; LINE a$:GO TO 20
 540 CLS 
 550 PRINT AT 12,16; INK 2;"[UDG-I][UDG-H]"
 560 PRINT PAPER 1;"                "; INK 2;"[UDG-I][UDG-I]"; PAPER 0;"[UDG-H]"
 570 PRINT PAPER 1;"                "; INK 2;"[UDG-I][UDG-I][UDG-I][UDG-I]"; PAPER 0;"[UDG-H]"
 580 PRINT PAPER 1;"                "; INK 2;"[UDG-I][UDG-I][UDG-I][UDG-I][UDG-I][UDG-H]",
 590 FOR a=1 TO 4
 600 PRINT PAPER 2,,:NEXT a:RETURN 
 610 BORDER 0:PAPER 0:INK 9:CLS 
 620 LET sc=0:LET ch=1:RETURN 
 630 FOR a=0 TO 71
 640 READ u:POKE USR "[UDG-A]"+a,u
 650 NEXT a:RETURN 
 660 DATA 56,60,63,u,u,7,0,u
 670 DATA 0,u,128,255,u,u,u,0
 680 DATA 0,u,63,255,u,u,u,0
 690 DATA 0,u,224,248,u,u,240,0
 700 DATA 0,u,220,126,u,220,0,u
 710 DATA 8,u,28,254,30,14,0,u
 720 DATA 36,60,24,60,u,24,0,u
 730 DATA 128,192,224,240,248,252,254,255
 740 DATA 254,255,u,u,u,u,u,u
 750 REM a=[UDG-A] b=[UDG-B] c=[UDG-C] d=[UDG-D] e=[UDG-E] f=[UDG-F] g=[UDG-G] h=[UDG-H] i=[UDG-I]

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