3-D Fractals

Developer(s): Gregory Harder
Date: 1986
Type: Cassette
Platform(s): TS 1000
Tags: Demo

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:

  1. Lines 1000–1040: Read a height value from the 2D array D(BX,BY), remapping array coordinates from logical (AX,AY) space.
  2. Lines 1200–1240: Write a height value back into D(BX,BY) using the same coordinate remapping.
  3. Lines 1300–1700: Sea-level clipping routine — interpolates line segments that cross Z=0, marking the transition with flag F1.
  4. Lines 3000–3430: Main plotting loop — iterates across three sweep directions (along X, along Y, and along the diagonal) to draw the projected terrain.
  5. Lines 3500–3760: 3D transformation — rotation around the vertical axis (RH) followed by tilt downward (VT), using ATN, SQR, COS, and SIN.
  6. 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.
  7. Lines 4500–4530: Keypress pause handler used in FAST mode.
  8. Lines 4900–5910: Initialization — allocates D(65,33), sets parameters, runs the midpoint displacement fractal generation loop, and prompts for user options.
  9. Lines 6000–6540: Post-render menu for viewing, reversing, copying, saving to tape, or restarting.
  10. Lines 9900–9970: SAVE entry point and the SC subroutine (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 +XX term 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>191 but 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 the XO=-999 sentinel 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

Appears On

Related Products

Related Articles

Related Content

Image Gallery

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.

Scroll to Top