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:
"THE " + A$(1) + " " + A$(2) + " " + A$(3)followed by"IN THE " + A$(4) + ","A$(5) + " FOR A " + A$(6)followed by"TO " + A$(7) + " THE " + A$(8) + "...."A$(9) + " " + A$(10) + " IN " + A$(11)" ...." + A$(12) + ", " + A$(13) + "."(followed by blank lines from'''')- Line 151:
" AS ...." + A$(13) + "," + A$(14) + "."
Notable Techniques
- Computed RESTORE:
RESTORE 190+10*Mis 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 referencesA$(14, TO B(14)), butB(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*Myields 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.
Content
Image Gallery
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
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.