--- title: "3-D Fractals" id: 51366 type: "computer_media" slug: "3-d-fractals" url: "http://localhost/computer_media/3-d-fractals/" markdown_url: "http://localhost/computer_media/3-d-fractals.md" published_at: "2023-07-29T13:05:26+00:00" modified_at: "2026-04-03T07:59:22+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2023/07/3-D-Fractals-1.png" excerpt: "A fractal landscape generator that builds 3D terrain through iterative midpoint displacement, then renders it with rotation, tilt, and optional sea-level clipping onto a high-resolution display." 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 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Gregory Harder" slug: "gregory-harder" taxonomy: "indiv" url: "http://localhost/indiv/gregory-harder/" genre: - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_type: "Cassette" programmers: - name: "Gregory Harder" slug: "gregory-harder" taxonomy: "indiv" url: "http://localhost/indiv/gregory-harder/" download_url: "https://archive.org/download/Sinclair_ZX81_TOSEC_2012_04_23/Sinclair_ZX81_TOSEC_2012_04_23.zip/Sinclair%20ZX81%20%5BTOSEC%5D%2FSinclair%20ZX81%20-%20Demos%20%28TOSEC-v2011-09-24_CM%29%2F3D%20Fractals%20v2.0%20%2819xx%29%28Gregory%20C.%20Harder%29.zip" mediadate: "1986" images: - url: "http://localhost/wp-content/uploads/2023/07/3-D-Fractals-1.png" - url: "http://localhost/wp-content/uploads/2023/07/3-D-Fractals-3.png" - url: "http://localhost/wp-content/uploads/2023/07/3-D-Fractals-2.png" media_type_tags: "Demo" --- # 3-D Fractals 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. ## 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▀## ACS ACS 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 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 ###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 -,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]#=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 ```