Funnily enough, I have been writing the Mandelbrot in a BASIC program on the ZX Spectrum recently as I am a member of a facebook group called BASIC on the ZX Spectrum.

My code includes a zoom rectangle, three dithering methods (to avoid the famous Spectrum colour clash it is in monochrome) - simple alternating black/white iteration bands, black, checkerboard, white, opposite checkerboard,black (and so on), or smoothed between bands alternating from solid black to solid white, then back to solid black but with dithering in between. Only thing I haven't included is saving and loading of locations.

Needless to say, the code is pretty slow, but it has progressed as far as I wish it to for now. I tweak now and then to add another bit of functionality.

Does anyone wish to see the code and/or samples of the generated fractals. I'm not sure if links to the images on facebook's servers would display inline in the post, so here's hoping:

Those are a few samples of the output. Here's the code:

Code: Select all

```
10 REM \{vi}Hires Mandelbrot\{vn}
20 REM \{vi}\*2016 Simon Ferre'\{vn}
30 RANDOMIZE
40 LET fg=0: LET bg=7
50 BORDER 7: PAPER bg: INK fg: CLS : LET k$=""
60 LET l=LN 2
70 LET dither=0
80 LET smooth=1
90 LET iter=64
100 LET width=4
110 LET height=2.75
120 LET bailout=64
130 LET b=LN (LN (bailout))
140 LET xstart=width/2-width
150 LET ystart=height/2-height
160 LET xstep=width/255
170 LET ystep=height/175
180 LET res=8
190 LET k$="": IF INKEY$<>"" THEN GO TO 190
200 FOR y=0 TO 175 STEP res
210 PRINT #0;AT 0,0;"\{vi}z\{vn}oom \{vi}i\{vn}ters \{vi}d\{vn}ither \{vi}s\{vn}mooth \{vi}b\{vn}ailout";AT 1,0;"\{vi}f\{vn}/g \{vi}b\{vn}/g cols"
220 IF res=1 THEN PRINT #0;AT 1,28;INT (y/1.75);"%";
230 FOR x=0 TO 255 STEP res
240 REM \{vi}Iterate\{vn}
250 IF POINT (x,y) THEN GO TO 640
260 LET i=1: LET it=1: REM Iter count and Iter type
270 LET zr=xstart+x*xstep: LET JuliaR=zr
280 LET zi=ystart+y*ystep: LET JuliaI=zi
290 REM \{vi}Inner iterations\{vn}
300 IF k$="" THEN LET k$=INKEY$: IF k$="" THEN GO TO 380
310 IF k$="d" THEN INPUT "Dither (y/n)? "; LINE k$: LET dither=0+(1 AND k$="y"): CLS : LET k$="": GO TO 180
320 IF k$="s" THEN INPUT "Smooth (y/n)? "; LINE k$: LET smooth=0+(1 AND k$="y"): CLS : LET k$="": GO TO 180
330 IF k$="f" THEN LET fg=fg+1: LET fg=fg-8*(fg=8): LET fg=fg+1*(fg=bg): LET fg=fg-8*(fg=8): GO SUB 1020: LET k$=""
340 IF k$="b" THEN LET bg=bg+1: LET bg=bg-8*(bg=8): LET bg=bg+1*(bg=fg): LET bg=bg-8*(bg=8): GO SUB 1020: LET k$=""
350 IF k$="z" THEN GO TO 670
360 IF k$="i" THEN INPUT ("Old=";iter;", new (same=cancel)=");niter: IF niter<>iter THEN CLS : LET k$="": LET iter=niter: GO TO 180
370 LET k$=""
380 LET zrsqr=zr*zr
390 LET zisqr=zi*zi
400 IF zisqr+zrsqr>bailout OR i>=iter THEN GO TO 450
410 LET zi=zr*zi*2+JuliaI
420 LET zr=zrsqr-zisqr+JuliaR
430 LET i=i+1: LET it=it+1: IF it=5 THEN LET it=1
440 GO TO 290
450 REM \{vi}Escaped or max iter\{vn}
460 IF i>=iter THEN LET it=5
470 IF dither THEN GO TO 580
480 IF NOT smooth THEN GO TO 550
490 REM Smooth colouring method
500 IF it=5 THEN GO TO 640: REM no plot for inside points
510 LET s=(b-LN ABS (LN ABS (SQR ABS (zisqr+zrsqr))))/l
520 IF it=1 OR it=3 THEN IF s<RND THEN PLOT x,y: REM band from white to black
530 IF it=2 OR it=4 THEN IF s>RND THEN PLOT x,y: REM band from black to white
540 GO TO 640
550 REM Alternating black/white method
560 IF i/2=INT (i/2) THEN PLOT x,y
570 GO TO 640
580 REM Checkerboard dithering method
590 IF it=1 OR it=5 THEN GO TO 640
600 IF it=3 THEN PLOT x,y: GO TO 640
610 LET p=0: LET xy=x+y: IF xy/2=INT (xy/2) THEN LET p=1
620 IF it=2 THEN PLOT INVERSE NOT p;x,y
630 IF it=4 THEN PLOT INVERSE p;x,y
640 NEXT x
650 NEXT y
660 LET res=res/2: IF res>=1 THEN GO TO 200
670 LET xl=0: LET xr=255: LET yb=0: LET yt=175: LET ratio=175/255
680 PRINT #0;AT 0,0;" "
690 PRINT #0;AT 0,0;"\{vi}zZ\{vn}oom, \{vi}Enter\{vn}=zoom in \{vi}f\{vn}g/\{vi}b\{vn}g cols": PRINT #0;AT 1,0;"\{vi}QAOP\{vn} move box, \{vi}Delete\{vn}=zoom out"
700 PLOT OVER 1;xl,yb: DRAW OVER 1;xr-xl,0: DRAW OVER 1;0,yt-yb: DRAW OVER 1;-(xr-xl),0: DRAW OVER 1;0,-(yt-yb): PLOT OVER 1;xl,yb
710 LET k$=INKEY$: IF k$="" THEN GO TO 710
720 PLOT OVER 1;xl,yb: DRAW OVER 1;xr-xl,0: DRAW OVER 1;0,yt-yb: DRAW OVER 1;-(xr-xl),0: DRAW OVER 1;0,-(yt-yb): PLOT OVER 1;xl,yb
730 IF k$="f" THEN LET fg=fg+1: LET fg=fg-8*(fg=8): LET fg=fg+1*(fg=bg): LET fg=fg-8*(fg=8): GO SUB 1020: LET k$=""
740 IF k$="b" THEN LET bg=bg+1: LET bg=bg-8*(bg=8): LET bg=bg+1*(bg=fg): LET bg=bg-8*(bg=8): GO SUB 1020: LET k$=""
750 IF k$="z" AND xr-xl>16 THEN LET xl=xl+2: LET xr=xr-2: LET yb=yb+2*ratio: LET yt=yt-2*ratio: GO TO 700
760 IF k$<>"Z" THEN GO TO 820
770 IF xl>1 THEN LET xl=xl-2: LET xr=xr+2: LET yb=yb-2*ratio: LET yt=yt+2*ratio
780 IF xl<0 THEN LET o=0-xl: LET xl=0: IF xr+o<=255 THEN LET xr=xr+o
790 IF xr>255 THEN LET o=xr-255: LET xr=255: IF xl-o>=0 THEN LET xl=xl-o
800 IF yb<0 THEN LET o=0-yb: LET yb=0: IF yt+o<=175 THEN LET yt=yt+o
810 IF yt>175 THEN LET o=yt-175: LET yt=175: IF yb-o>=0 THEN LET yb=yb-o
820 IF k$="o" AND xl>2 THEN LET xl=xl-2: LET xr=xr-2
830 IF k$="p" AND xr<253 THEN LET xl=xl+2: LET xr=xr+2
840 IF k$="q" AND yt<173 THEN LET yb=yb+2: LET yt=yt+2
850 IF k$="a" AND yb>2 THEN LET yb=yb-2: LET yt=yt-2
860 IF k$<>CHR$ 13 THEN GO TO 930
870 REM set new offsets and redraw
880 LET width=(xr-xl)*xstep
890 LET height=(yt-yb)*ystep
900 LET xstart=xstart+xl*xstep
910 LET ystart=ystart+yb*ystep
920 CLS : LET k$="": GO TO 160
930 IF k$<>CHR$ 12 THEN GO TO 1000
940 REM Zoom out
950 LET width=width*256/(xr-xl)
960 LET height=height*176/(yt-yb)
970 LET xstart=xstart-xl*xstep
980 LET ystart=ystart-yb*ystep
990 CLS : LET k$="": GO TO 160
1000 IF k$="0" THEN PAUSE 0
1010 GO TO 700
1020 REM colours
1030 PAPER bg: INK fg: FOR n=0 TO 21: PRINT AT n,0; OVER 1; INK fg; PAPER bg;TAB 31;" ";: NEXT n: RETURN
```

The codes like \{vi} or \{vn} are ZX BASIC codes for setting inverse video or normal video, and \* (in line 20) is the copyright character, so can safely be ignored. There is a programming environment that runs in Windows, called BasinC which allows one window to edit code, another to see the output (e.g. an emulator) and is very complete. Installing it and pasting in my code is sufficient to run the program. There is a turbo mode within BasinC which activates on a press of the F1 key (which makes program execution in this case almost bearable).

The whole code is a bit spaghetti-like and could be improved, but Sinclair BASIC doesn't have PROCedures and REPEAT UNTIL etc.

I'm writing a game where you can change your character from a Wizard to a monkey to a cat.

Well, Imogen that!