DROPABLOCK

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

DROPABLOCK is a block-dropping crane simulation game in which the player purchases a crane, orders blocks, and drops them onto a construction platform during a simulated workday. The game uses 14 User-Defined Graphics (UDGs A through N), defined via a DATA/POKE loop at line 710 that writes 112 bytes into UDG memory to render cranes, blocks, and platform tiles. Gameplay tracks money (M), days elapsed (D), and block inventory (A), with economic consequences for damage events and a high-score comparison at session end. The screen layout combines PRINT AT, INK, BRIGHT, FLASH, and OVER attributes to produce a layered construction-site scene with scrolling crane movement driven by a floating-point X/Y position increment variable I.


Program Structure

The program is organized as a main game loop with several distinct phases handled by line ranges:

  1. Lines 10–20: Title REM and initialization subroutine call (line 710).
  2. Lines 30–60: Session setup — initializes high score, money, day counter, and routes end-of-day logic.
  3. Lines 70–90: Scene drawing — renders the construction platform using UDG characters and sets up the backdrop string W$.
  4. Lines 100–150: Equipment selection — player chooses between two crane types with different capacities and costs.
  5. Lines 160–230: Block ordering — player inputs how many blocks to buy, with money and capacity validation.
  6. Lines 240–390: Main gameplay loop — moves the crane horizontally, renders it, and polls INKEY$ for block drops.
  7. Lines 400–510: Drop subroutine — animates a block falling from the crane to the platform level.
  8. Lines 520–570: End-of-day lorry sequence — a vehicle crosses the screen and triggers damage checks.
  9. Lines 580–670: Damage and lawsuit logic — handles collisions with yachts and falling lorry incidents.
  10. Lines 680–700: Profit/high-score reporting and replay.
  11. Lines 710–750: Initialization subroutine — sets display attributes, reads 112 bytes of UDG data, and POKEs them into UDG memory.
  12. Line 760: SAVE with autostart.

UDG Definitions

Line 710 uses a FOR N=0 TO 111 loop reading from DATA statements at lines 720–750, POKEing each byte into USR "[UDG-A]"+N. This defines 14 UDGs (A through N), covering crane arm parts ([UDG-A], [UDG-B]), truck/lorry shapes ([UDG-C], [UDG-D]), platform tiles ([UDG-E], [UDG-J]), and smaller crane type 2 graphics ([UDG-K], [UDG-L], [UDG-M], [UDG-N]).

Key Variables

VariableRole
MPlayer’s money (starts at 10000)
DDay counter (drives end-of-game condition at D=16)
ABlock inventory count
SCrane type chosen (1 = large, 2 = small)
IHorizontal movement increment (1.0 for type 1, 0.5 for type 2)
TIn-game clock (simulated minutes past 3:00 PM)
YCrane horizontal position (floating point)
XCrane row (fixed at 2)
NPlatform height (random, 2–14 rows from bottom)
HIHigh score (best profit across replays)
SUEFlag for yacht lawsuit event

Notable BASIC Idioms

  • NOT PI evaluates to 0 (since PI is non-zero, NOT PI = 0); used throughout as a compact zero literal — e.g., LET FU= NOT PI, PRINT AT NOT PI, NOT PI.
  • SGN PI evaluates to 1 (since PI > 0); used to initialize D=1 and set BRIGHT 1 at line 710.
  • FOR N= NOT PI TO VAL "RND*12+2" at line 70 uses VAL of a string expression for the upper bound — this defers evaluation and is a known memory/token optimization.
  • PAUSE NOT PI (i.e., PAUSE 0) followed by GO TO acts as a keypress wait without an explicit INKEY$ loop.

Gameplay Mechanics

The crane moves automatically from left to right across the screen; the player presses SPACE to drop a block. Block dropping is handled by the subroutine at line 400, which animates the block falling row by row using a FOR F loop with PRINT AT F,G, erasing the previous row each iteration. The crane type affects both the horizontal speed (I) and the time cost per block dropped (type 2 costs 2.5 time units vs. 0.5 for type 1).

The end-of-day trigger is when T >= 59 (representing 4:00 PM), after which a lorry animation runs across the screen at line 520. The lorry is randomly assigned one of several UDG patterns ([UDG-C], [UDG-D], or [UDG-G][UDG-H]), with the last variant only used when both platform inspection points show ATTR = 66 (INK 2, PAPER 0, BRIGHT 1 — a correctly loaded block attribute).

Damage and Economic Events

The damage subroutine at lines 580–670 uses both ATTR and SCREEN$ checks to detect collisions. If the lorry runs over a yacht (ATTR = 70), the player is fined $500 and sued for an additional $1500. If the lorry hits a block in its path (SCREEN$ non-space), it incurs $1500 damage. The falling subroutine at line 670 iterates from the platform top downward, calling line 580 for each row to check for obstructions.

Screen Layout and Attributes

The scene uses OVER 1 at line 90 to draw the road/ground overlay. FLASH 1 is used at end-of-day messages and the lower border status area (PRINT #1 writes to the lower screen). BRIGHT 0 at line 250 marks the lorry drop zones on the platform. The display column check at line 290 (IF INT Y>28) wraps the crane back to column 2 when it reaches the right edge.

Bugs and Anomalies

  • Line 550 has a potential infinite loop: IF P=3 AND ATTR(...) fails when the attribute condition is not met, causing GO TO 520 which may again pick P=3, repeating indefinitely if the platform blocks are not correctly loaded.
  • The variable INK is used as both a BASIC keyword and a numeric variable (e.g., LET INK= INT (RND*6)+2 at line 520). On the Spectrum, INK is a keyword/color modifier, so using it as a variable name this way is unconventional and may cause interpreter confusion depending on context.
  • Line 450 has IF f=19-n THEN GO SUB 510:RETURN — the RETURN after GO SUB exits the drop loop early when the block lands, which is intentional but means the NEXT F at line 500 is not reached in that case.
  • Variable FAL is set at line 590 but never subsequently read, making it a dead assignment.
  • The lowercase variable names s, x, y, i appear at lines 420–430, mixed with their uppercase equivalents elsewhere; on the Spectrum these are treated as distinct variables, which could cause unexpected behavior if the case is inconsistent.

Image Gallery

Source Code

  10 REM   DROP A BLOCK
  20 GO SUB 710
  30 LET HI=10000
  40 LET FU= NOT PI:LET A=fu:LET D= SGN PI:LET M=10000:LET V$="ANY KEY"
  50 IF D=16 AND M<10000 THEN PRINT AT NOT PI, NOT PI;"NO PROFIT WAS MADE.YOU ARE FIRED"''"ANY KEY TO REPLAY":PAUSE NOT PI:GO TO 40
  60 IF D=16 AND M >=10000 THEN GO SUB 680
  70 CLS :FOR N= NOT PI TO VAL "RND*12+2":PRINT AT 21-N,1; INK 2;"[UDG-E][UDG-E]     [UDG-E][UDG-E]     [UDG-E][UDG-E]     [UDG-E][UDG-E]     [UDG-E][UDG-E]":NEXT N
  80 PRINT AT 21-N-2,0;"[UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J][UDG-J]"; INK 2;"[UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-E][UDG-F][UDG-E][UDG-E][UDG-I]   [UDG-F][UDG-E][UDG-E][UDG-I]   [UDG-F][UDG-E][UDG-E][UDG-I]   [UDG-F][UDG-E][UDG-E][UDG-I]   [UDG-F][UDG-E][UDG-E][UDG-I]":LET W$="            "
  90 PRINT AT 21,0; INK 5; OVER 1;"                                ":LET W$=W$+"              "
 100 LET SUE= NOT PI:LET X=2:LET Y=x:LET T=15:IF D>1 THEN GO TO 160
 110 PRINT AT NOT PI, NOT PI;"1 [UDG-A][UDG-B] MAX CAPACITY 5 BLOCKS $3000"''"2 [UDG-K] MAX CAPACITY 3 BLOCKS  $1000"'"  [UDG-L]"
 120 INPUT "1 OR 2? ";S
 130 IF S>2 OR S<1 THEN GO TO 120
 140 IF S=1 THEN LET M=M-3000:LET I=1:LET W$=W$+"      "
 150 IF S=2 THEN LET M=M-1000:LET I=.5:LET W$=W$+"      "
 160 FOR W=0 TO 3:PRINT AT W,0;W$:NEXT W:PRINT AT 0,0;"$";M; AT 0,10;"DAYS:";D; AT 0,20;"BLOCKS:";A:INPUT "HOW MANY BLOCKS:";AW
 170 LET JK= INT (RND*2)+1:IF JK=1 THEN LET JK=5
 180 IF JK=2 THEN LET JK=12
 190 LET A=A+AW
 200 IF S=1 AND A>5 THEN LET A=A-AW:GO TO 160
 210 IF S=2 AND A>3 THEN LET A=A-AW:GO TO 160
 220 LET M=M-AW*100
 230 IF M<0 THEN PRINT AT 3,0;"YOU HAVEN'T ENOUGH MONEY":LET M=M+AW*100:LET A=A-AW:PAUSE 100:GO TO 160
 240 LET J= INT (RND*25)+4:LET J1= INT (RND*25)+4
 250 PRINT AT 21-N-1,J; BRIGHT 0;" "; AT 21-N-1,J1;" "
 260 PRINT AT 0,0;"$";M;"  "; AT 0,10;"DAYS:";D; AT 0,20;"BLOCKS:";A
 270 PRINT AT 20,JK; INK 6;"[UDG-M][UDG-N]"; AT 20,JK+7;"[UDG-M][UDG-N]"
 280 PRINT AT 0,0;"$";M;"  "; AT 0,10;"DAYS:";D; AT 0,20;"BLOCKS:";A
 290 IF INT Y>28 THEN PRINT AT X,Y;"  ":LET Y=2
 300 IF S=1 THEN PRINT AT X,Y; INK 5;" [UDG-A][UDG-B]":GO TO 330
 310 IF S=2 THEN PRINT AT X,Y; INK 4;" [UDG-K]"; AT X+1,Y;" [UDG-L]"
 320 IF S=2 THEN LET T=T+.4
 330 PRINT AT 1,0;"TIME: 3:"; INT T
 340 LET Y=Y+I
 350 IF S=1 THEN LET T=T+.45
 360 IF T >=59 THEN PRINT AT 1,6; FLASH 1;"4:00":GO TO 520
 370 PRINT AT 3,30;" "
 380 IF INKEY$=" " AND A <>0 THEN GO SUB 400
 390 GO TO 290
 400 LET A=A-1:LET G=Y:FOR F=X+2 TO 20:PRINT AT F,G; INK 2;"[UDG-E]"; AT F-1,G;" "
 410 IF Y >=28 THEN PRINT AT X,Y;"   ":LET Y=2
 420 IF s=1 THEN PRINT AT x,y; INK 5;" [UDG-A][UDG-B]":LET y=y+i
 430 IF s=2 THEN PRINT AT x,y; INK 4;" [UDG-K]"; AT x+1,y;" [UDG-L]":LET y=y+i
 440 PRINT AT 3,29;" "
 450 IF f=19-n THEN GO SUB 510:RETURN 
 460 PRINT AT 0,20;"BLOCKS:";A
 470 IF S=1 THEN LET T=T+.5
 480 IF S=2 THEN LET T=T+2.5
 490 IF T >=59 THEN PRINT AT 1,6; FLASH 1;"4:00":GO TO 520
 500 PRINT AT 1,0;"TIME: 3:"; INT T:NEXT F:RETURN 
 510 PRINT AT F+1,G; INK 2;"[UDG-E]"; AT F,G; INK 7;"[UDG-J]";:RETURN 
 520 LET P= INT (RND*3)+1:IF P=1 THEN LET A$="[UDG-C]":LET INK= INT (RND*6)+2:GO TO 560
 530 IF P=2 THEN LET A$="[UDG-D]":LET INK= INT (RND*6)+2:GO TO 560
 540 IF P=3 AND ATTR (21-N-1,J)=66 AND ATTR (21-N-1,J1)=66 THEN LET A$="[UDG-G][UDG-H]":LET INK=2:GO TO 560
 550 GO TO 520
 560 FOR T=1 TO 31:PRINT  AT 21-N-2,T; INK INK;A$; AT 21-N-2,T-1; INK 7;"[UDG-J]":BEEP .05,10:IF SCREEN$ (21-N-1,T)=" " THEN GO SUB 670
 570 NEXT T:LET D=D+1:LET M=M+1000:PRINT #1; TAB 12; FLASH 1;V$; FLASH 0:PAUSE 0:GO TO 50
 580 IF ATTR (U,T)=70 THEN LET M=M-500:PRINT  AT 19,T;" "; AT 20,T;"[UDG-D]"; AT 20,T; FLASH 1; OVER 1;"[UDG-E]":LET SUE=1:GO SUB 610
 590 IF SCREEN$ (U,T) <>" " THEN PRINT AT 21-N-1,T; INK INK;A$; AT 21-N-2,T; INK 7;"[UDG-J]":LET FAL=1:GO TO 610
 600 PRINT AT U-1,T;" ":RETURN 
 610 PRINT AT 1,0;"$1500 WORTH OF DAMAGE.":LET D=D+1:LET M=M-1500
 620 IF U=20 OR U=21 THEN PRINT AT 20,T; INK 5; PAPER 7;"[UDG-A]"; AT 20,T; OVER 1;"[UDG-B]"
 630  IF SUE=1 THEN PRINT AT 3,0;"YACHTSMAN SUES YOU FOR $500"
 640 IF M <=0 THEN GO TO 660
 650 PRINT #1; AT 1,12; FLASH 1;"ANY KEY":PAUSE 0:CLS :GO TO 50
 660 CLS :PRINT AT 0,0;"YOU RAN OUT OF MONEY"''"PRESS ANY KEY TO REPLAY":PAUSE 0:CLS :GO TO 40
 670 FOR U=21-N-1 TO 20:GO SUB 580:PRINT AT U,T; INK INK;A$; AT 21-N-2,T; INK 7;"[UDG-J]":BEEP .005,21-U:NEXT U:GO TO 610
 680 PRINT "WELL DONE !!! YOU MADE A PROFIT OF ";M-10000;:IF M<HI THEN PRINT " ANY KEY TO REPLAY":GO TO 700
 690 PRINT  " YOU ARE THE BEST WORKER TODAY":LET HI=M:PRINT '"ANY KEY TO REPLAY"
 700 PAUSE 0:CLS :GO TO 40
 710 BORDER NOT PI:PAPER NOT PI:INK 7:BRIGHT SGN PI:CLS :RESTORE 720:FOR N=0 TO 111:READ A:POKE USR "[UDG-A]"+N,A:NEXT N:RETURN 
 720 DATA 129,192,255,131,0,0,0,0,255,16,252,226,241,62,36,255
 730 DATA 0,0,0,56,36,255,153,102,0,0,254,255,241,255,153,102
 740 DATA 247,247,247,0,127,127,127,0,247,119,55,0,31,15,7,0
 750 DATA 255,255,255,255,255,153,102,102,224,108,106,106,255,201,54,54,247,246,244,0,112,96,64,0,0,0,0,255,16,16,16,16,60,94,191,191,94,94,60,36,36,60,60,60,0,0,0,0,0,0,12,12,8,127,63,31,128,192,224,240,128,254,252,248
 760 SAVE "DROPABLOCK" LINE 2

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