This program generates three-dimensional fractal terrain using the midpoint displacement algorithm, iteratively refining a height-field stored in a 65×33 array D(65,33) across up to six levels of detail. The terrain is projected onto the screen using isometric-style rotation and tilt transformations (GOSUB 3500 and GOSUB 3700), with configurable X, Y, and Z scale factors and a 30-degree horizontal rotation angle. A sea-level rendering mode (SL flag) clips geometry at Z=0, drawing coastline intersection points by interpolating between above- and below-water vertices. The program relies on machine code routines accessed via USR HR (at address 20000) for high-resolution 256×192 pixel line drawing using a DRAW command issued through LPRINT, and uses a second routine at address SC (9950) for a custom SCROLL/PRINT AT sequence. Screen output can be saved to tape by name, re-viewed, or reversed using the menu at line 6080.
Adapted to ZX81 from an article in Creative Computing.
Hardware Requirements
You will need a ZX81 (or TS1500) with 64K RAM (RAM from 16K to 64K). You also have to have 8K of static RAM, mapped 8-16K, for the high-res display file and associated data.
The program was tested on the EightOne, sx81 and NO$ZX emulators.
How To Run The Program
Turn on your computer or start your emulator. Type the following:
POKE 16389,192
NEW
LOAD ""
Program Analysis
Program Structure
The program is organized into several clearly delineated functional blocks, navigated primarily by GOSUB calls. The main entry point is line 10 (GOSUB 4900) followed immediately by GOTO 3000. The blocks are:
- Lines 1000–1040: Read a height value from the 2D array
D(BX,BY), remapping array coordinates from logical (AX,AY) space. - Lines 1200–1240: Write a height value back into
D(BX,BY)using the same coordinate remapping. - Lines 1300–1700: Sea-level clipping routine — interpolates line segments that cross Z=0, marking the transition with flag
F1. - Lines 3000–3430: Main plotting loop — iterates across three sweep directions (along X, along Y, and along the diagonal) to draw the projected terrain.
- Lines 3500–3760: 3D transformation — rotation around the vertical axis (
RH) followed by tilt downward (VT), using ATN, SQR, COS, and SIN. - Lines 4000–4300: Move/plot dispatcher — applies scale factors, calls rotation/tilt, computes screen coordinates, and issues the DRAW command via LPRINT to the machine code routine.
- Lines 4500–4530: Keypress pause handler used in FAST mode.
- Lines 4900–5910: Initialization — allocates
D(65,33), sets parameters, runs the midpoint displacement fractal generation loop, and prompts for user options. - Lines 6000–6540: Post-render menu for viewing, reversing, copying, saving to tape, or restarting.
- Lines 9900–9970: SAVE entry point and the
SCsubroutine (SCROLL + PRINT AT to reposition the cursor).
Fractal Terrain Generation
The terrain is built using a midpoint displacement algorithm across up to six refinement levels (input LE, 1–6). At each level N, the displacement magnitude L is scaled as 10000/1.8^N, producing progressively finer detail. Three passes per level interpolate heights along the X axis, the Y axis, and the diagonal respectively, each adding a random perturbation of RND*L/2-L/4 to the average of two neighbors.
The grid size grows as DS = 2 + sum(2^(n-1), n=1..LE), giving MX = DS-1. At six levels this yields MX=65, matching the array declaration DIM D(65,33) where the second dimension is MX/2+1.
Coordinate Remapping in Array Access
Lines 1010–1020 and 1210–1220 apply a non-trivial index transformation:
BY = 1+AY + (MX+1-2*AY AND AY>MY)BX = 1+AX + (MX-2*AX AND AY>MY)
When AY > MY (i.e., past the midpoint row), the indices are reflected, folding the triangular logical grid into the rectangular array. The AND keyword here functions as a conditional multiplier — a standard Sinclair BASIC idiom where a boolean result (0 or 1) is multiplied by the left-hand operand.
3D Projection and Rendering
The projection is isometric with configurable rotation (RH = PI*30/180 radians) and tilt (VT = RH*1.2). The rotation subroutine (line 3500) converts XX,YY to polar form, adds RH, and converts back. The tilt subroutine (line 3700) similarly operates in the ZZ,XX plane, subtracting VT. The final screen mapping at lines 4150–4160 applies:
XP = XP * 0.625(horizontal compression)YP = 33.14 - 0.663*YP(vertical inversion and scaling)- Screen Y:
Y = 191 - INT Y8(flipping to raster order)
Machine Code Interface
All high-resolution drawing is delegated to a machine code routine loaded at address HR = VAL "20000". It is called in two ways:
IF USR HR THEN ...— used as a conditional; the routine returns a value used as a boolean (nonzero = true). This pattern appears throughout lines 3010–6070 for state checks (e.g., whether the hi-res screen is active).IF USR HR THEN LPRINT DRAW;X,Y,P,Q— passes draw commands with start and end pixel coordinates to the machine code via LPRINT redirection.
A second machine code entry point at SC = VAL "9950" is called repeatedly as GOSUB SC. This resolves to lines 9950–9970, which perform a SCROLL followed by PRINT AT 21,31;" ";AT 21,0; to manage the display text area during setup.
The VAL "20000" and VAL "9950" forms for numeric constants in GOSUB targets are a memory optimization — storing the number as a string rather than a 5-byte floating point value saves bytes in the program area.
Sea Level Clipping
When sea level mode is enabled (SL=1), the routine at line 1300 detects line segments that cross Z=0. It interpolates the crossing point using W3 = ZZ/(ZZ-Z2) and calls GOSUB 4020 to draw the segment endpoint at the water surface. Flag F1 tracks whether the current point is below water (1) or above (0), suppressing submerged segments in the LPRINT DRAW call at line 4260.
User Interaction and FAST/SLOW Modes
After fractal generation, the user selects FAST or SLOW rendering mode. In FAST mode, the flag FA is set and the program enters FAST mode before drawing; pressing any key during rendering triggers a pause via GOSUB 4500 (lines 4290–4300). The PAUSE 0 / INKEY$ pattern is not used here; instead, INKEY$ <>"" at line 4290 detects a keypress inline during the draw loop.
Post-Render Menu
Lines 6080–6540 present a numeric menu. Option 2 triggers a display reverse via LPRINT I; (passing an invert command to the machine code). Option 3 issues COPY for printer output. Option 4 saves the named screen to tape via SAVE A$,S (saving the screen area). Option 5 restarts with RUN.
Notable Anomalies
- Line 3740 reads
LET XX=RD*COS R1+XX— the+XXterm looks like it may be a bug or an intentional perspective offset; a pure tilt would set XX to RD*COS R1 only. This would introduce a cumulative horizontal drift with repeated calls. - The bounds check at line 4250 tests
X>255 OR P>255 OR Y>191 OR Q>191but does not separately guard the starting point (X8, Y8) from the previous iteration, meaning the first segment after a move could still have an out-of-range start if not caught by theXO=-999sentinel reset. - Lines 0 (REM block) and 2 (REM block with embedded graphics data) are large data/bootstrap blocks not executed as normal BASIC — line 0 contains the machine code loader and line 2 appears to embed hi-res font or display data encoded as BASIC token bytes.
Content
Source Code
0 REM [C][O][R][E]█[V][3][.][0][1]## GOSUB # <> DIM LN F? CLEAR#OUORND[S]C IF TAN LN [M]RNDY2 GOSUB #<>5▟▝TAN CLEARACS #▚/▖ CLEARACS #LEN LN [M]RND<>5<>RNDTAN NEXT CLEARACS #: NEXT Y▘4▒ CLEARACS #LEN : PRINT Y▘# ( CLEAR▟W4 CLEAR▞"" CLEARACS ##C▝▞[K])4 5 4<>5:INKEY$ /▒)4 ▌ASN 1INKEY$ ;# GOSUB ###[:]"" GOSUB # E£RND) RUN ▙;Y2 GOSUB #Y PRINT ▘▛▝ CLEARACS ##CODE [P]▝LN [>]▝LN 4▝<>5<>RND#[8]▝ PRINT # RETURN,C▝INT / LET TAN SCROLLLN #? FASTLN LN + LPRINT TAN SCROLLLN #?#[B]:LN #INKEY$ PRINT LN #INKEY$ 7LN #INKEY$ # LET #TAN SCROLL RETURN#C▀ RETURN;""6-RNDTAN TO / PAUSE Y3[)]K▝INT (Y[Z][(]SQR INT 2LN #INKEY$ LN #INKEY$ / INPUT LN #INKEY$ /[H]LN #INKEY$ / SLOW5 6 RETURNZA4##<▘ COPY*Q GOSUB [K]TAN A ##▞▌ACS 9ACS =( IF ,,▘ 4,,TAN LN [~~]INKEY$ ##ACS ZACS ZACS Z##STR$ LN [J]INKEY$ LET J NEW▛W#TAN LN [>]INKEY$ ##LN #INKEY$ VAL LN #INKEY$ AT LN [J]INKEY$ #TAN 2 COPY/▝2 STR$ LN [*]INKEY$ SGN GOSUB # UNPLOT ZLN CODE INKEY$ ##?( CLEARACS .*PI▌4▝▞▒▛( CLEAR#TAN Y COPY/▘[J] CLEARACS #[:]MWRNDLN [*]INKEY$ # RETURN,4▛ GOSUB # UNPLOT ZLN [*]INKEY$ ## GOSUB # UNPLOT Z6 UNPLOT ZVAL #[)]-▘K▖ GOSUB #- COPY4▝- FAST# CLEAR#Y LET [(]2▘K▖ GOSUB #2 COPY4▝2 CLEAR#X#[W]S▞##- /▝2 GOSUB #ZRND84▘96INKEY$ RND#[B]3#A 6#RNDAT VAL Y[Z][(] CLEAR#W CLEARACS ##4▌LN IF INKEY$ /▀LN 7# CLEAR#INKEY$ ▞ CLEAR###,, CLEAR## GOSUB #ZRND CLEAR#PI GOSUB PIS▛ CLEAR## GOSUB #XRNDAT #▙##▄# CLEARO#UPIRND CLEAR[Y]#4[U]TAN LN #INKEY$ LN 4+ LOAD K LET $[M]H?▖O#[~~]+▞(## FOR 5 ACS TACS 3K▘; FOR D FOR ( POKE TAN Y COPY/▘[J]MWRND CLEARACS #[-]7LN [>]INKEY$ 5[+]▘6#RNDI 6#RND#6INKEY$ RND GOSUB # UNPLOT Z GOSUB ##RND FASTLN #INKEY$ LPRINT #6#RND6#RNDLN #INKEY$ CBLN #INKEY$ LN #INKEY$ M#RNDLN #INKEY$ C;LN #INKEY$ LN AT PI GOSUB ##RND TO LN #INKEY$ LN AT PI CLEARACS #CHR$ GOSUB ##RNDE#RND FASTEINKEY$ RND GOSUB ##RND▞▞ACS EACS .( IF GOSUB #6INKEY$ RND FOR E#RND▞▞ACS EACS .( IF GOSUB #6#RND GOSUB ##RNDLN PEEK PIU#RND##ACS +[£] PRINT ACS <[0]MRNDRNDEINKEY$ RND GOSUB ##RNDLN PEEK PIU#RND##ACS +[£]MZRND##ACS <[0]AT # CLEARACS ##C)E#RND#[P]C▞F6#RND/? CLEARACS #[-]Y[Z][(]S▞ CLEAR#WLN IF INKEY$ LPRINT F#[P]4█TAN CLEARQX▘LN #INKEY$ COS LN #INKEY$ MXRNDLN #INKEY$ COS LN [>]INKEY$ LN #INKEY$ [S]S▀#INKEY$ #LN ▜INKEY$ #INKEY$ LN ▜INKEY$ #PI GOSUB #YRND[)]W PRINT LN #INKEY$ [S]K▀#INKEY$ # GOSUB #RNDRND[(]W4▘XSGN # GOSUB #PIRND CLEAR#INKEY$ CLEAR#ZLN ▜INKEY$ LN CODE INKEY$ 6#RND CLEAR## CLEAR#RND CLEAR#ZLN ▜INKEY$ LN CODE INKEY$ 6#RND CLEAR##TAN GOSUB ##RNDE#RND CLEAR##[J]R*( UNPLOT M#RND CLEAR##[J]▌C▖R*( UNPLOT J CLEAR##▌TAN #[A] FOR ##J[A][K]# FOR TAN #VAL ▘4 ##,,#LN ###AT ( LET [J][5]/ SLOWLN ACS #4*) 4544▘ STEP * GOSUB [K]▞4F#( UNPLOT CLEARPX4 REM TAN LN R# FAST[B] GOSUB # LPRINT C: FASTVAL STR$ LN ##Y COPYSGN AT LPRINT F/ FOR CLEAR[A]#LN ## CLEARPX4<>TAN VAL 5 )4 ;( CLEAR FOR E#RND; FASTE#RND;SGN AT TAN #VAL ▘4 ##[B] GOSUB PI#LN ###AT ( LOAD [J]###LN ACS #4*) COPYR5 TO R▘ STEP * GOSUB [S]▞47#( UNPLOT CLEARPX4 REM TAN LN R#LN [T]# FAST[B] GOSUB # LPRINT C: FASTVAL STR$ LN SQR #Y COPYSGN AT LPRINT F/ FOR CLEAR[A]#LN SQR # CLEARPX4 AND TAN LN ACS #4+5 COPYR▞4#[B]ACS -F( CLS[8]4 POKE CLEARPX4 GOTO TAN LN R##▖U#RNDVAL PRINT FASTSTR$ INKEY$ # PRINT FAST[B] GOSUB # LPRINT C+#[4]# LET #ACS * PRINT #J[A]# LET PRINT [K]#▞ COPYF/ SLOW#[4]### LET #ACS *[4] PRINT #J[A]# LET [K]#SGN LPRINT ▘4 FOR ,, FOR ,, LET AT ([Y] CLEARPX4[L]TAN LN ACS #4-5 4[B]▞4ACS 27( CLSYS[W]4 NEXT CLEARPX4 FOR TAN LN R##▖U#RND FOR VAL PRINT FASTSTR$ # PRINT FAST[B] GOSUB # LPRINT C+#[4]# LET #ACS 3 PRINT #J[A]# LET PRINT [K]#▞ COPY7/ SLOW#[4]### LET #ACS 3[4] PRINT #J[A]# LET [K]#SGN LPRINT ▘4 FOR ,, FOR ,, LET AT ([Z] CLEARPX4[L]TAN ###Y[Z][(]STR$ VAL PRINT LN IF INKEY$ LET AT SGN TAN 2 COPY/▝2 STR$ LN <>#SGN CLEAR##UINKEY$ RND5ZRND PRINT FASTLN RETURN#+C▞WLN ▖#/ RUN CLEAR#PI LPRINT LET F FASTLN RETURN#+C▞£LN ▖#/ RUN CLEAR## LPRINT URNDRND PRINT FASTLN RETURN#+C▞XLN ▖#/ RUN CLEAR#PI LPRINT LET 7LN RETURN#+COS $LN ▖#/ SAVE ##[A]##J##J[6][N]#)4 ;( LOAD TAN LN ACS #4+5 4▘ /#J#7YS[W]4 RUN CLEARPX4 GOTO TAN LN R#▖J FAST[B] GOSUB # LPRINT C: FASTVAL STR$ LN ##Y COPYSGN AT LPRINT F/ REM U#RNDJLN ## CLEARPX4 AND TAN A$( LN [J]INKEY$ FAST TO FAST5[X]#6-RNDLN 0)AT GOSUB #-RNDK▝INT 6777# RETURN▝4 PLOT 7#Y""[>]S LOAD 77#Y4[)]S SCROLL77 CLEAR#X▞ SGN TAN LN [>]INKEY$ ##Y4[)]MYRNDLN #INKEY$ SCROLLM[X]# SCROLL RETURN$4SIN ##INKEY$ VAL [J]# FOR GOSUB PI FOR AT TAN LN RAND # PRINT LN AT # LET ▞# FASTC0 RETURN,4[E] SCROLL RETURNA▞[A]C£ RETURNO▞[Q]C▞ RETURNX▞[I]4[*]LN #INKEY$ 4 CLS#M## LPRINT UYRNDINKEY$ :4VAL PRINT STR$ YS[U]4▖SGN -4STR$ ,#>7< CLEARPYATN <#( REM FOR LPRINT ,, FOR LET AT MYRND CLEARPX4 OR TAN Y /▝Y>M[4]#LN RAND #4[S]LN AT #UYRNDINKEY$ :4VAL PRINT STR$ YS[U]4▖SGN -4STR$ # PRINT ,# LET >7< CLEARPYATN <#( SCROLL FOR LPRINT ,, FOR LET AT MYRND CLEARPX4CHR$ TAN 7# RETURN0K▝INT 1 RETURNGK IF CHR$ 0TAN LN [U]##ACS 4ACS 4ACS 4ACS 4LN [U]#█#7# RETURN"#TAN SCROLL RETURN"TAB 9#7#ACS #C▝CHR$ RND) 77 FAST▞▒## FOR ;( CLEAR FOR 5 S; FOR LPRINT TAN LN STEP #7LN TAN #>4▀## </ POKE ##[B]4## CLEAROY CLEARACS Y#4/7#[B]C LET ACS #4?▞ COPY[B]*S▖ACS // SAVE #J[5][Q]# FOR F CLEARPZ CLEARACS Z#""#[B]4▀#/ LIST ACS #""▞ COPY[B]ACS 3S▖ACS (/ RUN #J[5][Q]#TAN VAL #Y,,[(]#ACS )S▌( IF AT /[P]AT ##ACS ;S/( IF CLEAR#WLN ## CLEAROY CLEARACS Y#""7 CLEAR#W##/[-] CLEARACS #CHR$ ##VAL ACS ;( UNPLOT AT ** CLEARACS #[-] CLEAR#WVAL Y,,[(]#[J]#ACS >ACS <ACS ▘W( RUN ACS >ACS <ACS ▘WK RUN ACS .ACS ,,XACS .ACS ;X4 RAND #AT Y,,#[(]ACS ;+( CLSACS ,,+K CLS#PIACS <ACS ▘( IF PIACS ;ACS .( IF #TAN LN [~~]INKEY$ VAL PRINT LN 1+Y▒LN 1+LN R0LN LN +LN [B]:Y▛[)]# GOSUB ##RND LET AT #ACS UACS UACS U5YRND#7#7#LN CODE INKEY$ FASTVAL LN #INKEY$ MINKEY$ RNDLN #INKEY$ LN STEP ##LN #INKEY$ TAB *# FOR ▘▛ ,,6#RND GOSUB ##RND GOSUB PI6PIRNDAT SGN CLEARACS #[-] CLEAR##Y▒[)]#/▝:▒STR$ VAL EPIRND#F6PIRNDMWRND CLEARACS ##TAB [A]▝##LN =# CLEARPINKEY$ ASN [A]▝AT LPRINT [B])4 GOSUB ## RETURN3COS URNDRNDMYRNDMZRND$ FOR 4COS E#RND6PIRND/[Y]LN #INKEY$ ##▘▘COS CLEARACS V#""( RAND $4 PLOT .#[N]4 INPUT TAN SCROLL RETURN#4,,LN ,,#LN 0#/K SCROLL RETURN,C> RETURN;CG RETURN#C# RETURNAT C# RETURNTAB C#/# GOSUB # RETURNZ# NEW LIST LEN ( RETURNRNDCODE FAST#ATN STEP #/CHR$ #LEN ▒#[J]# GOSUB # RETURNZTAN ▞ COPY SCROLL RETURN#COS RETURN,4▖Y▖/" RETURN;4LEN ▖# RETURN▀ASN 9#M CLSZ/ SLOW GOSUB # RETURNZ/SGN LN #INKEY$ ## RETURN[T]ABS [▒]INKEY$ # RETURNRNDABS ▙INKEY$ GOSUB # RETURNZ TO /[)]LN #INKEY$ NEWZ GOSUB # RETURNZ[T]#K GOTO Y▒█#/ NEWLN #? CLEARACS ▘#CODE STR$ .LN SAVE <#[L]C OR ,VAL STR$ LN ##SGN AT <"/ LIST RETURN""4▖Y"/U PRINT NEW# RETURNRNDK▛ LET CLEARACS ▘LEN /G CLEARACS ▘#C~~[J] CLEARACS ▘▚LN [/]#/▖ CLEARACS ▘LEN LET LN #,,~~ PRINT VAL NEW#LN [/]#AT ▀ LET RETURN█S LET CLEARACS ▘▚[J] GOSUB # RETURNZ PRINT YZ[)]>= STEP #LN 0# LET VAL M#RND[B]*[B]**- ACS >#5 2; FASTACS TLN [J]INKEY$ SGN U CLSZ RETURN▖ASN ▐# RETURN▝CPI RETURN▘CEY▒ PRINT STR$ , PRINT U CLSZ[B]4~~ CLEARACS ##C▖ LET J/▘ LET #)4 ;SGN LET <X4 STEP AT ££ GOSUB # RETURNZTAN U#RND RETURNASINT RETURN[A]KACS FAST5 2; FOR LPRINT /TAB U#RND▛ FAST5 0S LET A,/ GOSUB CLEARACS ##Y[S]C▝Y[C][S]SQR ## NEW▛▙#VAL ) 45 5ACS SACS SACS S# GOSUB [K]F#( UNPLOT AT TAN ▘ ""LN 0## NEW# PRINT SCROLLLN 0) AND #$ASN 9#7 FAST▞▌[J]#7( UNPLOT SGN LET TAN LN AT INKEY$ #?( CLEARLN ##SQR Y▟>TAN LN AT INKEY$ ##LN 4+ FASTLN ## LPRINT LN PLOT ;#[~~]+LN AT INKEY$ #▞ / REM <># PRINT LN SCROLL▝2"" CLEARACS ##C▝2[K]5 4[J]PEEK CLSLN #?ABS ▐▒<= CLS*K CLS-4▞▒#<= CLS3K CLS# NEW█PEEK CLSACS )( PAUSE 7+4 FOR <= CLS3K CLS14PEEK Y▖PEEK CLS LET RETURN GOSUB ASN ▛▝#STR$ RNDLN #INKEY$ Y*C▀LN #INKEY$ ) WE RETURNZ FAST GOSUB # RETURNZ GOSUB #£RND< PRINT ▞4,VAL STR$ LN [/]#SGN AT <( PRINT LET X4 GOSUB LPRINT 6 RETURNZTAN LN #INKEY$ CATN LN #INKEY$ W PRINT #Y""CHR$ ▒( UNPLOT ## LET /LEN )[(]RNDLN #INKEY$ C>STR$ LN #INKEY$ #LN #INKEY$ ▖SGN ,LEN █><( RAND TAN ▞4[J]><( UNPLOT TAN LN #INKEY$ RETURN4) ▞K▞LN NEXT ##▛#INT .▘4 ,,# RETURNS**#TAN LN #INKEY$ RETURN4K GOSUB LN #INKEY$ [B]***- #5 Y;6#RND##INKEY$ LN ## GOSUB # UNPLOT ZY[Z][(]K▝CHR$ RND##ACS WACS 1ACS WACS 1ACS WACS 1ACS GOTO 6 DIM Z#J NEW▛WM#RND) FOR Z GOSUB ##RNDY▒ PRINT #>~~VAL #U#RND RETURN▌S)JLEN ,,[B]##: C:3ACS ;( CLS/▛#[J]ACS )*( CLS[Q]#7<#>#[Q]#FLN ##<AT ▀ LET X4SIN TAN LN #INKEY$ TAB *#E DIM Z) FOR Z▞▒VAL ,#7<,#FLN ##<AT ( LET TAN CLEARACS #EXP LN ## TO RETURN,4▞LN █#LN #INKEY$ E UNPLOT Z[B] GOSUB PICOS #FPIVAL LN #?ABS [▒]▒5ORND##[S]C UNPLOT CLEAR[-] CONT M#RNDLN LOAD #AT LN ▜#U#RND CLEAR[Y]O4 CLSTAN LN #INKEY$ Y C▀LN #INKEY$ M CONT ZTAN GOSUB # UNPLOT Z# RETURN COPY4▖▞[Z]/▞ RETURN""4▝▞ Y[Z][(] GOSUB # UNPLOT ZTAN LN IF INKEY$ )[4] .#[N]4 CLSTAN LN [~~]INKEY$ GOSUB # UNPLOT ZLN #INKEY$ M## CLEARACS #CHR$ LN ##VAL PRINT LN CODE INKEY$ #2 COPY LET AT STR$ VAL PRINT LN ## LET AT LN ##SGN #E9RND##GC THENLN [X]▛#:£)VAL ##M# CLEARACS #CHR$ /ATN CLEARQW COPY CLEARACS #[-]/£ CLEARQW / POKE CLEARO CLEAR CLEARP UNPLOT LN ## CLEAR#W CLEARACS ##4[E]LN IF INKEY$ /[9] CLEARO CLEAR/ REM CLEARO UNPLOT / PLOT CLEARO UNPLOT / STEP CLEARP CLEAR/ PLOT CLEARP CLEAR/CHR$ CLEARP UNPLOT / PLOT CLEARP UNPLOT /ATN TO RETURN;CM RETURN#C▝INT + LPRINT ▘ ## TO RETURN THENC▝INT ) FAST SCROLL);#STR$ :(),#▞ FOR GOSUB [5]C▌77 REM P##7# FOR VAL TAN SGN ):#STR$ :?) FOR # SCROLL# SCROLL RETURN#CSQR RETURN;4 RUN F#7 RETURN$C▘#/INT :▌)[.]#F#7/VAL :▖)[G]#/ POKE FF#77:▀)[U]#/[M]YX: GOSUB [T]77#:▀)[(]#/[6]C GOTO PID=PIR>#9#D##E DIM #M▛#P##S##9#D NEW#LD#R[<]#U##9#G##P0#S##9#C[W]#DTAB #EATN #R##1ABS #2 INPUT #3 SAVE #4▝#5▛#6 CLEAR#7 DIM #8 NEXT #[:]#X█#A##B OR INKEY$ C CONT PID(PIF CONT #I##L▚#P##R:#S##T##U▖#W##$##9# LPRINT ## LLIST :# SCROLL## LOAD [=]# LIST >=# PAUSE [)]# PRINT [D]# PLOT FOR INKEY$ RUN ACS RND SAVE ## RAND 8# CLS[0]INKEY$ UNPLOT LOAD INKEY$ CLEARSGN RND RETURN[Z]RND COPY[:]#9#
1 REM FAST SAVE LOAD [V][.][2][.][0]##LN SCROLL▝ SCROLLLN #?LN SAVE <#[K]C+ RETURN/K) TO RETURN#COS SCROLL RETURNSCOS RETURNVCOS RETURNCODE COS RETURNHCOS # POKE ▝, RETURN,C▖ RETURNCODE 4▝AT TAN .CHR$ 1**W,,X4 UNPLOT TAN FOR 5 .▘▘ LN [+]#:~~LN [+]#:#LN [+]#▘ CONT ▀LN [+]#▘(BLN [+]#TAN ▘▘COS ( RETURN$4 CLS.#[N]4 NEXT TAN ▞▛ACS 5>=,,#USR SAVE #Y▀X4 CLEAR GOSUB #▌TAB >=#ACS 5>=,,#USR SAVE #TAN PEEK COPYY-X4 CLEAR<= RETURNY:X4 CLEAR#1##£#PEEK COPYY9X4 CLEAR<= RETURNY0X4 CLEARF7RTAN ▘ █VAL LN AND #AT ▌TAB 5#▀ GOSUB #LN AND #LN ##$LN AND # CLEAR FAST LET #:[E]LN AND #LN ###LN AND #LN ###LN AND # CLEAR FAST LET ##LN AND #7.#[N]4 PLOT TAN LN ## RETURNHASN [>]#STR$ VAL PRINT LN LLIST ▒) ▝LN ATN # LET M#RND RETURNS4£5 4 6#RND5 //) RETURNV4>E(RND6#RND FOR E=RND[B] GOSUB #6#RND/O RETURNCODE C▌5,,RND/ CONT SCROLL RETURN,C£ RETURN0 AND POKE ▝ RETURNAABS POKE ▝/ LOAD LN [E]#6#RND SCROLL RETURN#C~~ RETURN0S SCROLL RETURNAK CONT / LET LN [E]#/SIN AT LPRINT )WRNDSTR$ GOSUB [K][J]E#RND GOSUB ##RND▚7.##[N]#4 RUN M#RNDF#M#RND LPRINT )4 LN 2# GOSUB ##RND GOSUB ##RNDE#RNDLN 2#/0 F#[J]E#RND GOSUB ##RND▚7.##[N]#4 RUN [T]C▝INT =LN LLIST ▒LN ▛▝TAN <= RETURN*S CLS: £<= RETURN*K IF #LEN FOR ACS <TAN 2 ▞▒LN H#( CLSTAN - =PEEK COPY# RETURNRNDK)2 LN H#LN #?ABS [A]▀#[B]4 SCROLL/ SCROLL2 PEEK COPYLN H##[B]C PRINT LN RND#04CHR$ LN RND## RETURN[E]4EXP LN RND##LN RND#STR$ PEEK COPYLN RND##SGN 7.#[N]4 PAUSE TAN FASTLN ## RETURNHASN 5# PRINT STR$ VAL 5WRNDLN ##AT SGN /£-▝LN ATN # LET LPRINT 6-RND/ THEN5WRND,[Y]4 GOSUB 7<"#[L]4 PRINT LET LPRINT E#RND FAST RETURNS4:5 4 6#RNDLN ##AT #:# RETURNV4/E(RND6#RNDLN ##AT FASTLN :# LPRINT FLN [1]=SGN LPRINT ##▞ RETURN#4▌5,,RND/ LLIST SCROLL RETURN#4?E#RND/SIN SCROLL RETURN#4▌LN [E]#/[X] RETURN0 AND POKE ▝ RETURNAABS POKE ▝/ REM LET ▘4 5WRNDLN ##U#RND RETURNCODE 4▖YC/▞ RETURN#4▝YP INPUT █M#RND▞;5WRND#NOT 7( CLSY#E#RND GOSUB ##RNDSTR$ FAST;LN ## LPRINT Y-LN ## LPRINT Y=LN ##Y#NOT #A#NOT ##LN 4+LN <=+TAN
2 REM [6][4][-][C][O][L] PRINT ## LIST LIST LIST LIST LIST LIST LIST LIST WWWW LIST LIST LIST LIST #### LIST LIST LIST LIST ???? LIST LIST LIST LIST LIST LIST LIST LIST WWWWWWWWWWWW####WWWW????WWWW#[9]#[9]#[9]#[9] LIST LIST LIST LIST #[9]#[9]#[9]#[9] LIST LIST LIST LIST ##RND RNDRNDRND [4]E##[:][E] ##[▒]#▙## RND8 ▖ ##PI# # 6##CODE #PI4 ▜PIPI#PI#█ ▒▖#[8]▒ ▝▖▒▖▝ LIST ##RND#RND# #USR [Y]▜# #4I44# E# INPUT #E ▙▙##CC RND[8]RNDRND#▖▒ RND█ ▖▖▒ £# (-,,,,0(█▜[£]▜▜▜[:]█ LIST ▖~~▝▖▒: LIST [:]▙▜▙[~~]▜█ LIST >-,2>>(█[:][▒][£]▙[~~]▜ LIST (=/0,,= LIST █[:]PIPI8C/((=E8##▜█ ▖[~~] IF [A][6][8] RND[8][6] NEW[E][A] COS [C]ATN [E][E]ATN #▜[~~][▒][▒]# TAB [6][A][E][E]LEN STEP ▜ASN [:][▒] NEW LLIST ▜EXP ▜▜▜ RND[8][~~][E][A]#£ [C][C] GOTO [E][E][E] SLOWRND### SLOW #4A6[6]#▖ [C][C]ASN ATN [E][E] ▜▜▜▜▜ LLIST [4] REM INPUT [I][E][E] ""[G][E][E][E][E] RND[8][E][E][E]# ""[G][E]ASN [£][▒]▒ RND[A][E][E][A]PI7 ""[G][E]COS [C][C] #▚#86ATN SLOW####PI [4][E][E][E][E]# [4][E][E][E]## [4][E][E][E] INPUT [E] [4][E]##[E][E] [4][E]##PIPI▖ STEP IPI#[▒] INPUT FAST5▐O; FOR LPRINT U#RND NEW█U RETURNZ?▞▒VAL PRINT ,#CGS0 NEW LIST PRINT # NEW?# LET [K]#<STR$ )4 ;SGN LET AT ( STOPAT £ GOSUB # RETURNZTAN ACS ZACS ZACS ZACS Z PRINT # NEW LIST />=S~~ACS BACS BACS BACS B/ATN NEW?/ REM
5 REM 3D FRACTALS, CREATIVE COMPUTING V. 11, NO. 7
10 GOSUB 4900
20 GOTO 3000
1000 REM [G][E][T]█[D][A][T][A]█[F][R][O][M]█[A][R][R][A][Y]
1010 LET BY=1+AY+(MX+1-2*AY AND AY>MY)
1020 LET BX=1+AX+(MX-2*AX AND AY>MY)
1030 LET D=D(BX,BY)
1040 RETURN
1200 REM [P][U][T]█[D][A][T][A]█[I][N][T][O]█[A][R][R][A][Y]
1210 LET BY=1+AY+(MX+1-2*AY AND AY>MY)
1220 LET BX=1+AX+(MX-2*AX AND AY>MY)
1230 LET D(BX,BY)=D
1240 RETURN
1300 REM [S][E][A]█[L][E][V][E][L]
1310 IF XO<>-999 THEN GOTO 1360
1312 IF NOT (ZZ<0) THEN GOTO 1320
1314 LET F1=1
1316 LET Z2=ZZ
1318 LET ZZ=0
1319 GOTO 1680
1320 LET F1=0
1350 GOTO 1670
1360 IF Z2>0 AND ZZ>0 THEN GOTO 1670
1370 IF NOT (Z2<0 AND ZZ<0) THEN GOTO 1410
1371 LET Z2=ZZ
1372 LET ZZ=0
1380 GOTO 1680
1410 LET W3=ZZ/(ZZ-Z2)
1420 LET X3=(X2-XX)*W3+XX
1430 LET Y3=(Y2-YY)*W3+YY
1440 LET Z3=0
1450 LET ZT=ZZ
1460 LET YT=YY
1470 LET XT=XX
1480 IF ZZ>0 THEN GOTO 1590
1490 REM [G][O][I][N][G]█[I][N][T][O]█[W][A][T][E][R]
1500 LET ZZ=Z3
1510 LET YY=Y3
1520 LET XX=X3
1530 GOSUB 4020
1531 LET F1=1
1540 LET ZZ=0
1550 LET YY=YT
1560 LET XX=XT
1570 LET Z2=ZT
1580 GOTO 1680
1590 REM [C][O][M][I][N][G]█[O][U][T]█[O][F]█[W][A][T][E][R]
1600 LET ZZ=Z3
1610 LET YY=Y3
1620 LET XX=X3
1630 GOSUB 4020
1631 LET F1=0
1640 LET ZZ=ZT
1650 LET YY=YT
1660 LET XX=XT
1670 LET Z2=ZZ
1680 LET X2=XX
1690 LET Y2=YY
1700 RETURN
3000 REM [S][E][T][-][U][P]
3010 IF USR HR THEN CLS
3020 IF NOT FA THEN IF USR HR THEN RUN
3080 FOR A=0 TO MX
3090 LET AX=A
3100 LET XO=-999
3110 FOR B=0 TO AX
3120 LET AY=B
3130 GOSUB 1000
3140 LET ZZ=D
3145 LET YY=AY/MX*10000
3150 LET XX=AX/MX*10000-YY/2
3160 GOSUB 4000
3170 NEXT B
3180 NEXT A
3190 FOR A=0 TO MX
3200 LET AY=A
3210 LET XO=-999
3220 FOR B=AY TO MX
3230 LET AX=B
3240 GOSUB 1000
3250 LET ZZ=D
3260 LET YY=AY/MX*10000
3270 LET XX=AX/MX*10000-YY/2
3280 GOSUB 4000
3290 NEXT B
3300 NEXT A
3310 FOR E=0 TO MX
3320 LET XO=-999
3330 FOR F=0 TO MX-E
3340 LET AX=E+F
3350 LET AY=F
3360 GOSUB 1000
3370 LET ZZ=D
3380 LET YY=AY/MX*10000
3390 LET XX=AX/MX*10000-YY/2
3400 GOSUB 4000
3410 NEXT F
3420 NEXT E
3430 GOTO 6000
3500 REM [R][O][T][A][T][E]
3510 IF XX<>0 THEN GOTO 3540
3515 IF NOT (YY<=0) THEN GOTO 3530
3520 LET RA=-PI/2
3522 GOTO 3550
3530 LET RA=PI/2
3535 GOTO 3550
3540 LET RA=ATN (YY/XX)
3545 IF XX<0 THEN LET RA=RA+PI
3550 LET R1=RA+RH
3560 LET RD=SQR (XX*XX+YY*YY)
3570 LET XX=RD*COS R1
3580 LET YY=RD*SIN R1
3700 REM [T][I][L][T]█[D][O][W][N]
3710 LET RD=SQR (ZZ*ZZ+XX*XX)
3720 IF XX<>0 THEN GOTO 3728
3724 LET RA=PI/2
3726 GOTO 3730
3728 LET RA=ATN (ZZ/XX)
3729 IF XX<0 THEN LET RA=RA+PI
3730 LET R1=RA-VT
3740 LET XX=RD*COS R1+XX
3750 LET ZZ=RD*SIN R1
3760 RETURN
4000 REM [M][O][V][E]█[O][R]█[P][L][O][T]█[X][P][,][Y][P]
4010 GOSUB 1300
4020 LET XX=XX*XS
4030 LET YY=YY*YS
4050 LET ZZ=ZZ*ZS
4060 REM [R][O][T][A][T][E]█[T][H][E][N]█[T][I][L][T]
4070 GOSUB 3500
4090 LET P$=("M" AND XO=-999)+("D" AND XO<>-999)
4100 LET XP=INT YY
4110 LET YP=INT ZZ
4140 REM [D][R][A][W]█[L][I][N][E]█[H][E][R][E]
4150 LET XP=XP*0.625
4160 LET YP=33.14-0.663*YP
4170 IF P$="D" THEN GOTO 4210
4180 LET X8=XP
4190 LET Y8=YP
4200 LET XO=XP
4210 LET X=INT X8
4220 LET Y=191-INT Y8
4230 LET P=INT XP
4240 LET Q=191-INT YP
4250 IF X<0 OR P<0 OR Y<0 OR Q<0 OR X>255 OR P>255 OR Y>191 OR Q>191 THEN RETURN
4260 IF SL THEN IF NOT F1 THEN IF USR HR THEN LPRINT DRAW;X,Y,P,Q
4265 IF NOT SL THEN IF USR HR THEN LPRINT DRAW;X,Y,P,Q
4270 LET X8=XP
4280 LET Y8=YP
4290 IF FA AND INKEY$ <>"" THEN GOSUB 4500
4300 RETURN
4500 IF USR HR THEN RUN
4510 IF USR HR THEN PAUSE 300
4520 FAST
4530 RETURN
4900 DIM D(65,33)
4910 FAST
4920 LET HR=VAL "20000"
4925 LET SC=VAL "9950"
4930 CLS
4940 PRINT ,," 3D FRACTALS--VERSION 2",,,"CREATIVE COMPUTING V. 11, NO. 7",,,"█████[E][N][A][B][L][E]█[S][C][R][A][M]█[B][O][A][R][D]█[N][O][W]█████"
4945 PRINT ,," PROGRAMMED FOR ZX81 BY",,," GREGORY C. HARDER",,," SHREB V3.01 WITH V2.00 FSAVE."
4990 SCROLL
5000 PRINT " INPUT NUMBER OF LEVELS?(1 TO 6)"
5010 INPUT LE
5020 RAND
5030 IF LE<0 OR LE>6 THEN GOTO 5030
5040 LET DS=2
5050 FOR N=1 TO LE
5060 LET DS=DS+2**(N-1)
5070 NEXT N
5080 LET MX=DS-1
5090 LET MY=MX/2
5100 LET RH=PI*30/180
5110 LET VT=RH*1.2
5120 FOR N=1 TO LE
5130 LET L=10000/1.8**N
5132 GOSUB SC
5134 GOSUB SC
5140 PRINT "WORKING ON LEVEL ";N
5145 PAUSE 100
5150 LET IB=MX/2**N
5160 LET SK=IB*2
5170 REM [H][E][I][G][H][T][S]█[A][L][O][N][G]█[X]
5180 FOR Y=0 TO MX-1 STEP SK
5190 FOR X=IB+Y TO MX STEP SK
5200 LET AX=X-IB
5210 LET AY=Y
5220 GOSUB 1000
5230 LET D1=D
5240 LET AX=X+IB
5250 GOSUB 1000
5260 LET D2=D
5270 LET D=(D1+D2)/2+RND*L/2-L/4
5280 LET AX=X
5290 LET AY=Y
5300 GOSUB 1200
5310 NEXT X
5320 NEXT Y
5330 REM [H][E][I][G][H][T][S]█[A][L][O][N][G]█[Y]
5340 FOR X=MX TO 1 STEP -SK
5350 FOR Y=IB TO X STEP SK
5360 LET AX=X
5370 LET AY=Y+IB
5380 GOSUB 1000
5390 LET D1=D
5400 LET AY=Y-IB
5410 GOSUB 1000
5420 LET D2=D
5430 LET D=(D1+D2)/2+RND*L/2-L/4
5440 LET AX=X
5450 LET AY=Y
5460 GOSUB 1200
5470 NEXT Y
5480 NEXT X
5490 REM [H][E][I][G][H][T][S]█[A][L][O][N][G]█[D][I][A][G][.]
5500 FOR X=0 TO MX-1 STEP SK
5510 FOR Y=IB TO MX-X STEP SK
5520 LET AX=X+Y-IB
5530 LET AY=Y-IB
5540 GOSUB 1000
5550 LET D1=D
5560 LET AX=X+Y+IB
5570 LET AY=Y+IB
5580 GOSUB 1000
5590 LET D2=D
5600 LET AX=X+Y
5610 LET AY=Y
5620 LET D=(D1+D2)/2+RND*L/2-L/4
5630 GOSUB 1200
5640 NEXT Y
5650 NEXT X
5660 NEXT N
5670 GOSUB SC
5675 GOSUB SC
5680 SLOW
5690 PRINT " FAST OR SLOWMODE?"
5700 LET A$=INKEY$
5710 IF A$="" THEN GOTO 5700
5720 IF A$<>"F" AND A$<>"S" THEN GOTO 5700
5730 LET FA=(A$="F")
5732 IF FA THEN GOSUB SC
5734 IF FA THEN GOSUB SC
5740 IF FA THEN PRINT "PRESS A KEY TO PEEK AT PLOT "
5760 GOSUB SC
5765 GOSUB SC
5770 PRINT "DRAW WITH SEA LEVEL? (Y/N)"
5780 LET A$=INKEY$
5790 IF A$<>"Y" AND A$<>"N" THEN GOTO 5780
5800 LET SL=(A$="Y")
5820 GOSUB SC
5822 GOSUB SC
5825 REM [S][C][A][L][E]█[F][A][C][T][O][R][S]
5830 PRINT " INPUT X SCALE"
5840 INPUT XS
5842 LET XS=XS/25
5845 GOSUB SC
5847 GOSUB SC
5850 PRINT " INPUT Y SCALE"
5860 INPUT YS
5862 LET YS=YS/25
5865 GOSUB SC
5868 GOSUB SC
5870 PRINT " INPUT Z SCALE"
5880 INPUT ZS
5882 LET ZS=ZS/25
5890 IF FA THEN FAST
5900 CLS
5910 RETURN
6000 REM [P][L][O][T][T][I][N][G]█[L][O][O][P]█[D][O][N][E]
6010 IF USR HR THEN RUN
6020 FOR N=0 TO 9
6030 IF USR HR THEN RAND 31
6040 NEXT N
6050 IF USR HR THEN RUN
6060 IF INKEY$ ="" THEN GOTO 6060
6070 IF USR HR THEN RETURN
6080 CLS
6090 PRINT "LEVELS =";LE;TAB 0;"X SCALE=";XS*25;TAB 0;"Y SCALE=";YS*25;TAB 0;"Z SCALE=";ZS*25;;TAB 0,,"1. VIEW",,,,"2. REVERSE",,,,"3. COPY",,,,"4. SAVE SCREEN",,,,"5. ANOTHER RUN ",,,,"[E][N][T][E][R]█[N][U][M][B][E][R]"
6100 INPUT B
6110 IF B=1 THEN GOTO 6050
6120 IF B=2 THEN IF USR HR THEN LPRINT I;
6130 IF B=3 THEN IF USR HR THEN COPY
6140 IF B=4 THEN GOTO 6500
6150 IF B=5 THEN RUN
6160 IF USR HR THEN RETURN
6170 GOTO 6100
6500 CLS
6510 PRINT " INPUT NAME, START TAPE BEFORE PRESSING ENTER."
6520 INPUT A$
6530 IF USR HR THEN SAVE A$,S
6540 GOTO 6080
9900 SAVE "3DFRA[C]"
9910 RUN
9950 SCROLL
9960 PRINT AT 21,31;" ";AT 21,0;
9970 RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


