--- title: "Poetry 2" id: 55870 type: "computer_media" slug: "poetry2" url: "http://localhost/computer_media/poetry2/" markdown_url: "http://localhost/computer_media/poetry2.md" published_at: "2024-07-06T17:27:01+00:00" modified_at: "2026-03-30T21:44:45+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A random-poetry generator assembles surreal free verse from themed word lists, producing a new poem each time with subjects ranging from prophets to robots and mutants." 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: "Entertainment" slug: "entertainment" taxonomy: "genre" url: "http://localhost/type/entertainment/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/POETRY2%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" media_type_tags: "Entertainment" --- This program generates random free-verse poetry by selecting words from themed DATA lists and assembling them into a fixed template of four printed lines. Thirteen word categories (subject, verb, adverb, setting, participle, noun, infinitive, object, and several participial/abstract slots) are each populated by reading a randomly chosen item from a corresponding DATA block. The subroutine at line 40 uses RESTORE with a calculated line number (190+10*M) to seek directly to the correct DATA statement for each category, then skips a random number of entries before storing the chosen word. Variable-length strings are stored in a fixed-width DIM A$(15,12) array and retrieved using the saved length values in B() to trim trailing spaces. POKE 23692,0 prevents the “scroll?” prompt from interrupting display, and PAUSE VAL “198” provides a timed delay between poems. *** ## Program Analysis ### Program Structure The program is organized into three logical sections: initialization (lines 10–30), a word-selection subroutine (lines 40–80), a main display loop (lines 90–180), and thirteen DATA blocks (lines 200–320). Execution begins at line 90 via the `GO TO 90` at line 30, bypassing the subroutine. The main loop at lines 100–180 calls the subroutine 15 times (`H=1 TO 15`), printing a new poem on each iteration before pausing, then jumps to line 1 (non-existent) to halt after the run. ### Word Selection Subroutine (Lines 40–80) The subroutine iterates over 13 word categories (M=1 TO 13). For each category, it uses `RESTORE 190+10*M` to seek to the appropriate DATA line — lines 200, 210, 220, … 320 — and then reads and discards a random number of entries (`RND*14+1`, giving 1–15) before storing the final read value. This elegantly maps each value of M to a distinct DATA line without any lookup table. Note that the loop only populates slots M=1 to 13, leaving `A$(14)` and `A$(15)` empty, even though the DIM declares 15 rows and line 151 references `A$(14)`. This is an anomaly described further below. ### String Storage and Length Tracking Because the ZX Spectrum stores fixed-length strings in a DIM array (padded with spaces), the program saves each word’s true length in the numeric array `B(M)` via `LEN B$`. On retrieval, slices like `A$(M, TO B(M))` trim the padding. The DIM is declared as `A$(15,12)`, meaning each slot holds up to 12 characters — sufficient for the longest DATA items (“EXTERIORIZED” and “ROCK CONCERT” at 12 characters each). ### DATA Layout | M | DATA Line | Category / Role in Poem | | --- | --- | --- | | 1 | 200 | Subject (person/entity) | | 2 | 210 | Verb (past tense) | | 3 | 220 | Adverb | | 4 | 230 | Setting / location | | 5 | 240 | Participle (searching/hoping…) | | 6 | 250 | Noun (object of search) | | 7 | 260 | Infinitive verb | | 8 | 270 | Object (moon/pain/clowns…) | | 9 | 280 | Participial phrase word 1 | | 10 | 290 | Connective/transitional word | | 11 | 300 | Abstract gerund | | 12 | 310 | Participial phrase word 2 | | 13 | 320 | Abstract gerund (repeated/varied) | Each DATA line contains 16–17 items, allowing `RND*14+1` (range 1–15) to always land on a valid entry. ### Poem Template Lines 120–151 assemble four printed lines using the stored words: 1. `"THE " + A$(1) + " " + A$(2) + " " + A$(3)` followed by `"IN THE " + A$(4) + ","` 2. `A$(5) + " FOR A " + A$(6)` followed by `"TO " + A$(7) + " THE " + A$(8) + "...."` 3. `A$(9) + " " + A$(10) + " IN " + A$(11)` 4. `" ...." + A$(12) + ", " + A$(13) + "."` (followed by blank lines from `''''`) 5. Line 151: `" AS ...." + A$(13) + "," + A$(14) + "."` ### Notable Techniques - **Computed RESTORE:**`RESTORE 190+10*M` is an efficient way to index into multiple DATA blocks without an explicit dispatch table or nested conditionals. - **POKE 23692,0** (line 90): Resets the scroll counter to prevent the “scroll?” prompt from interrupting automatic display. - **PAUSE VAL “198”** (line 160): Using `VAL "198"` instead of a literal saves one byte in the stored program token stream — a common ZX Spectrum memory optimization. - **Trailing apostrophes on line 150:** The four `'` characters after the PRINT statement generate four blank lines, creating visual separation between poems. - **GO TO 1** (line 180): Branching to the non-existent line 1 is a deliberate halt technique; the interpreter reports an error and stops, effectively ending the program after the 15-poem run. ### Bugs and Anomalies - **A$(14) never populated:** The subroutine loop runs M=1 TO 13, so `A$(14)` is always an empty (space-padded) string. Line 151 references `A$(14, TO B(14))`, but `B(14)` will be 0, producing an empty string slice. This means the last line always ends with just a comma and period after the repeated 13th word. - **DATA line 200 starts at line number 200, not 190+10*1=200:** This is actually correct — the formula `190+10*M` yields 200 for M=1, 210 for M=2, etc., and all DATA lines are present and correctly numbered. - **Missing line 170:** Line numbers jump from 160 to 180; line 170 is absent, which is harmless but leaves a gap in the listing. - **“HALUCINATING”** in line 280 is a misspelling of “hallucinating” — likely intentional given the poem’s surreal aesthetic, but noteworthy. - **“RETREADING”** in line 310 is possibly a typo for “retreating” or may be deliberate wordplay. ## Source Code ``` 10 REM Poetry2, ADAPTIONS BY FRANK DAVIS 1989 20 DIM A$(15,12): DIM B(15) 30 RANDOMIZE : GO TO 90 40 FOR M=1 TO 13 50 RESTORE 190+10*M 60 FOR G=1 TO RND*14+1: READ B$: NEXT G: LET A$(M)=B$ 70 LET B(M)=LEN B$: NEXT M 80 RETURN 90 POKE 23692,0 100 FOR H=1 TO 15 110 GO SUB 40 120 PRINT '"THE ";A$(1, TO B(1));" ";A$(2, TO B(2));" ";A$(3, TO B(3))," IN THE ";A$(4, TO B(4));"," 130 PRINT A$(5, TO B(5));" FOR A ";A$(6, TO B(6))," TO ";A$(7, TO B(7));" THE ";A$(8, TO B(8));"...." 140 PRINT A$(9, TO B(9));" ";A$(10, TO B(10));" IN ";A$(11, TO B(11)) 150 PRINT " ....";A$(12, TO B(12));", ";A$(13, TO B(13));"."'''' 151 PRINT " AS ....";A$(13, TO B(13));",";A$(14, TO B(14));"." 160 PAUSE VAL "198" 180 NEXT H: GO TO 1 200 DATA "O.T.","MAN","BOY","WOMAN","CHILD","SHADOW","ECHO","GIRL","MUTANT","PROPHET","MARTYR","REPUBLICAN","ROBOT","PRINCESS","WITCH","ANCHORMAN","THETAN" 210 DATA "SANG","WAITED","SAID","SCREAMED","CRIED","PLEADED","PRAYED","STOOD","FELL","STUMBLED","READ","CURSED","CHANGED","MELTED","MOVED","EXTERIORIZED" 220 DATA "SADLY","GLADLY","SLOWLY","FAINTLY","MADLY","HUMBLY","LOUDLY","BITTERLY","QUIETLY","QUICKLY","CURIOUSLY","INTENTLY","SICKLY","POINTLESSLY","REASONABLY","RUDELY" 230 DATA "DARK","DOORWAY","GATEWAY","MORNING","EVENING","RUINED CITY","WASTELAND","MOTEL","CANYON","FOREST","ROCK CONCERT","ALIEN FILM","SWAMP","DESERT","FLYING SAUCER","THETA TRAP" 240 DATA "LOOKING","SEARCHING","HOPING","DESIRING","DESPAIRING","ASKING","PLEADING","WAITING","CRYING","REACHING","INTERESTED","DYING","WISHING","EVOLVING","MUTATING","AUDITING" 250 DATA "WAY","REASON","SIGN","FUTURE","WISH","BUS","DOOR","DEATH","TRUTH","LIFE","BOOK","TELEVISION","COKE","TELEPHONE","VOTER","PEPSI" 260 DATA "REACH","FEEL","MOVE","STEAL","SHARE","CHANGE","TWIST","FACE","DESIRE","BLAME","TOUCH","ABUSE","MOVE","CHANGE","CONSTRAIN","REMOVE" 270 DATA "MOON","MORNING","NIGHT","PAIN","FEAR","INSECTS","LIGHT","POWER","HATE","SUN","LAWYER","FISH","DEMOCRATS","RATS","CLOWNS" 280 DATA "TAKING","WATCHING","CHANGING","BLAMING","GETTING","TREMBLING","WONDERING","HOPING","SPEAKING","CALCULATING","HALUCINATING","RANTING","LOOKING","FEELING","ASPIRING" 290 DATA "HEART","PAST","HOW","WHY","DOWN","THROUGH","FOR","THEN","JUST","AS","NOW","WHEN","WHILST","ALMOST","LIKE","SIMULATING" 300 DATA "NOTHING","GIVING","FADING","DARING","LAUGHING","DYING","CRYING","CHANGING","BLAMING","GRASPING","ALL","FEARING","CAMPAIGNING","SELLING","RETREADING" 310 DATA "TAKING","WATCHING","CHANGING","BLAMING","GETTING","TREMBLING","WONDERING","HOPING","SPEAKING","CALCULATING","BORING","HIDING","BUILDING","WATCHING","FREAKING" 320 DATA "NOTHING","GIVING","FADING","DARING","LAUGHING","DYING","CRYING","CHANGING","BLAMING","GRASPING","SCHEMING","INSENSATE","EVOLVING","HURTING","LOVING","DRINKING" 9998 SAVE "POETRY2" LINE 20 ```