--- title: "Block Art" id: 56853 type: "computer_media" slug: "broken-program-1" url: "http://localhost/computer_media/broken-program-1/" markdown_url: "http://localhost/computer_media/broken-program-1.md" published_at: "2024-09-29T07:44:51+00:00" modified_at: "2026-03-30T21:20:44+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/09/321_Unk.png" excerpt: "A self-contained rectangle generator that picks random dimensions, fills the interior with a character derived from its own height, and redraws on every keypress." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_contents: - id: 56738 title: "Timex Sinclair Public Domain Library Tape 1007" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1007/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/09/321_Unk.png" media_type_tags: "Demo" --- This program draws a randomly sized rectangle on screen using inverse-video block characters for the border and a fill character derived from the rectangle’s own height value. The dimensions are generated with RND: width T is scaled to 54 columns and height D to 8 rows, with a bias toward smaller heights (line 6 re-rolls D if it exceeds 4). The rectangle is rendered in three passes — a top border row, D middle rows each with side borders and an interior filled with CHR$ D, and a bottom border row — all positioned with AT and TAB expressions based on T and D. After drawing, the program waits for a keypress via CODE INKEY$ before looping back to draw a new rectangle. *** ## Program Analysis ### Program Structure The program is a tight loop spanning lines 4–110. Lines 4–6 generate random dimensions; lines 7–100 render the rectangle; line 105 provides a keypress gate; and line 110 restarts the loop. Lines 120–140 are bootstrap/save code that runs once on initial load. 1. **Line 4–6:** Randomise width `T` (0–54) and height `D` (0–8), re-rolling `D` if it exceeds 4 to bias toward shorter rectangles. 2. **Lines 7–35:** Position the cursor with `AT` and print the top border row of `T` inverse-space characters. 3. **Lines 50–70:** Print `D` middle rows, each starting and ending with an inverse-space border character, with `T-2` interior cells filled by `CHR$ D`. 4. **Lines 75–100:** Print the bottom border row, mirroring the top. 5. **Line 105:** Waits until no key is pressed (`NOT CODE INKEY$` is true when INKEY$ is empty), then returns — though there is no corresponding `GOSUB`, so `RETURN` here would cause an error; in practice the condition is reversed and the loop simply falls through to `GOTO 4`. ### Dimension Generation `RND**54` uses the exponentiation operator applied twice (i.e. `RND * *54` is parsed as `RND ^ 54` — raising a 0–1 random number to the 54th power), which strongly biases `T` toward very small values near zero. Similarly `RND**8` biases `D` toward small heights. The re-roll on line 6 (`IF D>4 THEN LET D=RND**8`) further skews the height distribution downward. ### Rendering Technique The border character is the inverse-video space (`%` in the source escaping), producing a solid block. The interior fill character is `CHR$ D`, meaning the actual character displayed depends on the rectangle’s own height — for small `D` values this will be a control or graphics character, giving the interior a somewhat unpredictable appearance. Positioning uses the expression `(1-T/2)` and `(1-D/2)` inside `AT` and `TAB`. Since these are likely to produce values between 0 and negative numbers (given `T` can reach 54 and the screen is 32 columns wide on ZX81/TS1000), the coordinate arithmetic is approximate centering that may wrap or clip on smaller screens. ### Key BASIC Idioms - `NOT CODE INKEY$` — tests whether `INKEY$` is the empty string (CODE of “” = 0, NOT 0 = 1), used as a “no key pressed” sentinel. - `RND**N` — raising RND to a power to shape the probability distribution toward smaller values. - Repeated `TAB (1-T/2)` calls before each row to re-establish the horizontal position after each `PRINT` statement. ### Bugs and Anomalies | Line | Issue | | --- | --- | | `105` | `RETURN` is used without a preceding `GOSUB`. When `NOT CODE INKEY$` is true the program will attempt to return from a non-existent subroutine call, causing a RETURN without GOSUB error. The intent was likely `IF CODE INKEY$ THEN GOTO 4` or similar. | | `4` | `RND**54` is parsed as `RND ^ 54`, not `RND * 54`. If the intent was a width scaled to 54, the correct expression would be `RND*54`. The power form produces values extremely close to zero nearly all the time. | | `7` | The `AT` row/column expressions `(1-D/2)` and `(1-T/2)` will frequently yield zero or negative values, which may be clamped or cause errors depending on the interpreter’s AT bounds checking. | ## Source Code ``` 4 LET T=RND**54 5 LET D=RND*8 6 IF D>4 THEN LET D=RND**8 7 PRINT AT (1-D/2),(1-T/2); 10 FOR X=1 TO T 20 PRINT "% "; 30 NEXT X 35 PRINT TAB (1-T/2); 50 FOR X=1 TO D 55 PRINT TAB (1-T/2); 56 PRINT "% "; 57 FOR U=1 TO T-2 60 PRINT CHR$ D; 65 NEXT U 66 PRINT "% "; 70 NEXT X 75 PRINT TAB (1-T/2); 80 FOR X=1 TO T 90 PRINT "% "; 100 NEXT X 105 IF NOT CODE INKEY$ THEN RETURN 110 GOTO 4 120 CLEAR 130 SAVE "1032%1" 140 RUN ```