--- title: "Bubbles" id: 50602 type: "computer_media" slug: "bubbles" url: "http://localhost/computer_media/bubbles/" markdown_url: "http://localhost/computer_media/bubbles.md" published_at: "2023-06-23T11:26:00+00:00" modified_at: "2026-03-30T21:29:17+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "An endlessly looping art program draws random circles with boundary checking, randomized border colors, and a pitch-shifted beep tied to each circle's radius." 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 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Bubbles%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2023/06/SCR-20260329-pqia.png" media_type_tags: "Demo" --- This program draws randomly sized and positioned circles on screen in an infinite loop, occasionally clearing the screen when a circle’s radius falls within a narrow range. Each iteration picks random coordinates and a radius, validates them against boundary conditions to prevent the circle from running off-screen, and plays a short BEEP whose pitch is derived from the radius value. The BORDER color is also randomized on every iteration, producing a constantly shifting frame color. The boundary check at line 25 uses four conditions to keep the circle within the display area before committing to drawing it. *** ## Program Analysis ### Program Structure The program is a tight, six-line infinite loop with no subroutines. Control flows linearly from line 2 through line 40, which jumps back to line 2, creating a perpetual display cycle. Line 25 acts as a guard, redirecting to line 10 to pick new random values whenever the proposed circle would violate boundary conditions. 1. **Line 2** — Randomizes the border color (0–7). 2. **Line 10** — Picks random screen coordinates `x` (0–255) and `y` (0–175). 3. **Line 20** — Picks a random radius `z` (0–99). 4. **Line 24** — Sounds a BEEP with a random duration and a pitch offset from `z`. 5. **Line 25** — Validates the circle fits on screen; retries from line 10 if not. 6. **Line 30** — Draws the circle. 7. **Line 35** — Conditionally clears the screen when `z` is between 50 and 59 inclusive. 8. **Line 40** — Loops back to line 2. ### Variable Usage | Variable | Range | Purpose | | --- | --- | --- | | `x` | 0–255 | Circle center X coordinate | | `y` | 0–175 | Circle center Y coordinate | | `z` | 0–99 | Circle radius; also controls BEEP pitch | ### Boundary Checking Line 25 tests four conditions before allowing the circle to be drawn. The conditions `z>=x` and `z>=y` prevent the circle from overflowing the left or top edges, while `z+x>=255` and `z+y>=175` prevent overflow past the right and bottom edges. If any condition is true, the loop retries with new random values. Note that this check is slightly conservative — the Spectrum’s CIRCLE command can tolerate the center being closer to an edge than the radius by a small margin — but it reliably avoids errors. ### Audio Integration The BEEP at line 24 uses `RND*.7` for duration (up to 0.7 seconds) and `z-45` for pitch, mapping the radius (0–99) to a semitone offset of roughly −45 to +54. This ties the audio character of each beep directly to the size of the circle about to be drawn, creating an informal audio-visual correlation. ### Screen Clearing Mechanism The CLS at line 35 fires only when `z` is strictly between 50 and 59 (inclusive). Because `z` is derived from `RND*100`, this condition has approximately a 10% probability per valid circle, giving the display periodic resets without an explicit counter variable. This is an economical way to prevent the screen from becoming completely saturated without adding extra state. ### Notable Techniques - Chaining multiple `LET` assignments on a single line (line 10) saves memory compared to splitting them across separate numbered lines. - Reusing `z` for both the boundary guard and the BEEP pitch avoids introducing an additional variable. - The loop re-entry point at line 2 rather than line 10 means the border color changes on every complete iteration, including after retries are avoided by the guard — the border only changes when a circle is successfully drawn and the loop completes fully. ### Potential Anomalies Because `z` is computed before the boundary check, the BEEP at line 24 always sounds, even for parameter sets that will be rejected at line 25. This means a beep may play followed by an immediate retry without any visible circle, potentially producing orphaned audio events. Moving line 24 to after line 25 (or between lines 25 and 30) would ensure audio only accompanies a drawn circle. ## Source Code ``` 2 BORDER RND*7 10 LET x=RND*256: LET y=RND*176 20 LET z=RND*100 24 BEEP RND*.7,z-45 25 IF z>=x OR z>=y OR z+x>=255 OR z+y>=175 THEN GO TO 10 30 CIRCLE x,y,z 35 IF z>50 AND z<60 THEN CLS 40 GO TO 2 ```