--- title: "Rainbow Riot" id: 70819 type: "computer_media" slug: "rainbow" url: "http://localhost/computer_media/rainbow/" markdown_url: "http://localhost/computer_media/rainbow.md" published_at: "2026-08-23T15:08:04+00:00" modified_at: "2026-08-23T20:56:27+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/rainbow.png" alt: "RAINBOW screen" excerpt: "A hypnotic four-way-symmetric arc drawing uses random curves and direct memory POKEs to flood the result with kaleidoscopic color." 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/RAINBOW%20%28198x%29%28-%29%28TS2068%29%28US%29%28Program%29.zip" tsrun_member: "RAINBOW (198x)(-)(TS2068)(US)(Program).tap" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/08/rainbow.png" alt: "RAINBOW screen" media_type_tags: "Demo" --- # Rainbow Riot Generates a symmetrical, multi-colored arc pattern on screen using the DRAW command with arc (angle) parameters. The program first calculates a series of random line segments and arc angles, storing them in a two-dimensional array, then renders the complete path four times using reflections across both axes (all four sign combinations of ±1) to produce a fourfold-symmetric figure. After drawing, it directly POKEs the display-file attribute bytes at address 22895 to colorize the image in random INK values, bypassing PAPER/INK BASIC statements for speed and granularity. A short two-note BEEP fanfare plays before the image pauses for display, then the program loops via RUN. *** ### Program Structure The program is organized into four logical phases: 1. **Initialization (lines 5–30):** Sets display attributes, dimensions an array `a(d,3)` to hold `d=15` line segments, and sets a starting plot position of (123, 84). 2. **Path generation (lines 50–100):** Randomly generates 15 displacement vectors and arc angles, validates them against screen bounds, and stores them. 3. **Drawing (lines 120–170):** Renders the stored path four times with all combinations of ±1 scale factors, producing fourfold symmetry. 4. **Colorization and display (lines 190–510):** POKEs random INK attribute values into the display file, plays a brief fanfare, pauses, then restarts. ### Path Generation and Validation Lines 60–90 generate each segment’s displacement `(x, y)` uniformly from ±212 and ±174 respectively, then reject any candidate that would push the accumulated position `(x1, y1)` outside the drawable area (38–213 horizontally, 1–168 vertically) via a `GO TO 60` retry loop. This is a standard rejection-sampling idiom in BASIC graphics programs. The arc angle `c` is computed on line 80 with a two-step formula. The first step initializes `c` as a value in [−6, 6] with a sign flip based on whether the current direction crosses the horizontal or vertical midline — this tends to keep arcs curving inward rather than spiraling outward. The second step dampens large arcs for short segments, dividing by up to 5 when both displacement components are large, which prevents visually chaotic tight spirals on long strokes. ### Fourfold Symmetry Drawing Lines 120–170 use nested `FOR` loops over `a` and `c` ranging from −1 to 1 step 2, giving the four sign pairs (−1,−1), (−1,+1), (+1,−1), (+1,+1). Each pass starts from the center point (123, 84) and replays the stored path with `DRAW a*a(b,1), c*a(b,2), a*c*a(b,3)`. Multiplying the arc angle by both `a` and `c` ensures the arc curvature is correctly mirrored (reversing one axis alone would flip the arc direction, so the product maintains geometric consistency). `OVER 1` is set at initialization so overlapping strokes XOR the pixel data rather than overwriting, creating additional visual complexity at intersections. ### Attribute Colorization via POKE Lines 190–230 directly write to the Spectrum attribute file. The base address `c=22895` is close to the center of the attribute area (the full attribute file starts at 22528). The loops iterate with `a` from 0 to 352 in steps of 32 (i.e., row offsets) and `b` from 0 to 13 (column offsets within a row), POKEing all four symmetric attribute cells simultaneously: - `c+b+a`, `c+b-a`, `c-b+a`, `c-b-a` This mirrors the fourfold symmetry of the drawn image in the color attributes. The attribute byte value is computed on lines 200–210: a random integer 0–7 is generated, values below 2 are bumped up by 5 (avoiding very dark colors 0 and 1), and then 64 is added to set the BRIGHT bit, ensuring vivid colors throughout. ### Notable Techniques - Reusing loop variable names (`a`, `b`, `c`) across different phases saves memory on a RAM-constrained machine. - The arc angle sign heuristic on line 80 uses a compact boolean arithmetic expression: `(y1>84 AND x<0 OR y1<84 AND x>0)` evaluates to 1 or 0, then is multiplied by −2 and added to 1, giving a sign factor without an `IF` branch. - `RUN` at line 510 restarts the program completely, re-executing `RANDOMIZE` to seed a new pattern each cycle. - The “THINKING” message printed at line 30 provides user feedback during the path-generation phase, which involves repeated rejection sampling and could otherwise appear frozen. ### Potential Anomalies The base POKE address 22895 is offset 367 bytes into the attribute file (22528 + 367), placing the center of the colorization at approximately row 15, column 15 of the attribute grid. This is not precisely the screen center (which would be row 11, col 16 = offset 368), but the difference is negligible visually. The colorization loops using `±a` offsets up to 352 can reach addresses outside the 768-byte attribute file, potentially POKEing into the printer buffer area above address 23295, though this is unlikely to cause a crash in normal operation. ## Source Code ``` 5 REM "RAINBOW RIOT" 10 RANDOMIZE : BORDER 0: PAPER 0: INK 7: OVER 1 20 LET d=15: DIM a(d,3) 30 LET y1=84: LET x1=123: PRINT AT 10,12;"THINKING" 50 FOR b=1 TO d 60 LET x=213-INT (RND*426): LET y=175-INT (RND*350) 70 IF x1+x>213 OR y1+y>168 OR x1+x<38 OR y1+y<=0 THEN GO TO 60 80 LET c=6*RND*(1-2*(y1>84 AND x<0 OR y1<84 AND x>0)): LET c=c*2/(2+(ABS c>4)*(ABS x>20 OR ABS y>20)+2*(ABS x>50 OR ABS y>50)) 90 LET x1=x1+x: LET y1=y1+y: LET a(b,1)=x: LET a(b,2)=y: LET a(b,3)=c 100 NEXT b 120 CLS : FOR a=-1 TO 1 STEP 2: FOR c=-1 TO 1 STEP 2 130 PLOT 123,84 140 FOR b=1 TO d 150 DRAW a*a(b,1),c*a(b,2),a*c*a(b,3) 160 NEXT b 170 NEXT c: NEXT a 190 LET p=0: LET c=22895: FOR a=0 TO 352 STEP 32: FOR b=0 TO 13 200 LET at=INT (RND*8) 210 LET at=at+5*(at<2)+64 220 POKE c+b+a,at: POKE c+b-a,at: POKE c-b+a,at: POKE c-b-a,at 230 NEXT b: NEXT a 235 BEEP .5,10: BEEP .5,5 500 PAUSE 180: CLS 510 RUN ```