Program 1/2: RMmbrot.z80
The Mandelbrot set came to prominence in the 1980s and justifiably so!
The classic 'ink blot' shape is rendered above in glorious black and grey. In the above screen-shot, centred on the origin (i.e. x, y both 0), the x-axis is shown from around -2 to +2 and and the y-axis from around -1.4 to +1..4, ie. it represents the complex plane from -2 - 1.4i at the bottom left to 2 +1.4i at the upper right.
The program iterates the function (z**2) + c for each point on the screen representing the complex plane. c is the number at that point and the initial value of z is 0.
A point is considered to be not part of the set if |z**2| is greater than 4, ie has a radius of escape of 2. If after the maximum number of iterations, we've not shown the point is not in the set, then we assume it is in the set.
I've made some changes recently to make it easier to vary parameters, but the core of the program is unchanged from the 1980s. It consists of only a few steps, yet it produces such intricate graphics. Be warned, though, it takes many hours to produce an image, although it may be possible to increase the clock speed, depending on the emulator being used. If I have the time, I'll try to rewrite the main part in assembly language to speed it up. *
The program can be edited by following the comments in it, to produce countours instead, referred to as 'contour mode' below.
There are 5 settings in the program that can be varied (by editing the appropriate lines) to show different areas of interest:
The magnification (called umag in the program), which is set to 1 in the program.
The x-coordinate of the centre of the screen (a0), set to 0.
The y-coordinate of the centre of the screen (b0), set to 0.
The number of iterations (iters), set to 50. In the unedited program, this is used to decide if a point is part of the set and the higher the value, the greater the degree of accuracy. In contour mode, this can be much lower and is used along with the value below to decide if a point is part of the contour.
The width of the contour (width) , which is only used with mode 2 and is set to 5. If iters is set to 20 say, then with depth set to 5, a point is included in the contour of it takes between 15 and 19 iterations to decide a point is NOT in the Mandelbrot set.
An example of a contour map is shown here. The number of iterations is 10 and the depth is 5. (The horizontal line at the bottom is a progress bar, a later addition to the program).
Another contour is shown below. This time, the magnification is 20, the number of iterations is 20, the depth is 5 and the graph is centred on (-0.05, 1).
* This may not be easy for me, as the algorithm needs non-integer 16-bit multiplication and division, but the z80 does not provide any native multiplication and division operations at all! In my GoL z80 routine, I do a simple multiplication of two 8-bit integers, but 16-bit non-integer operations will be more complicated again, I think. I'm hoping I'll be able to re-use a ROM routine or to copy the required code from elsewhere!
Program 2/2: RMmbrot2.z80
Prompted by colourful pictures I'd seen in magazines, I tried to assign different colours to different contours on the same screen. The machine is called a Spectrum after all. I discovered unfortunately, this is only possible using low resolution graphics (32 x 22 blocks per screen) and not the high resolution (ie 256 x 176 dots per screen) that I was using for the program. However, to be fair, this limitation wasn't just confined to the Spectrum, as I found out when checking the graphics on an IBM PC around 1990 and seeing the same issue.
Recently however, I've seen impressive monochrome images that are otherwise as detailed as colour images, showing alternate contours only (e.g. for iterations 5 - 10, 15 - 20, 25 - 30 etc) , ie bands of black separated by white. It's a shame I didn't think of doing this at the time - not only would it have been an excellent enhancement, but I would probably have tried to speed up the program using assembly language. I may well have succeeded then, but I'm not so sure I could do so now!
Anyway, I've now written a new program that really I should have written back then, albeit just in BASIC for now. It determines the contour number, e.g. 0 for iterations 1 to 4, 1 for 5 to 9, 2 for 10 to 14, etc. It does this with code
LET tmp=INT(s/width),
where s is the number of iterations it takes to determine a point is not in the set. It then checks to see if this number is odd and if so, plots a point. This is done with code
IF INT (tmp/2) <> (tmp/2) THEN PLOT ... .
This can be changed to plot a point if the number is even, thereby inverting the image, by substituting = for <>.
The image below has magnification 1, is centred on (0, 0), has a contour width of 2 and max. number of iterations of 49. Note that the image is now black and white, not black and grey! All I had to do was to enter BRIGHT 1 - something I'd not known until now.
The series of images below is centred on (-0.1, 0.9), and also has a contour width of 2 and max. number of iterations of 49.
The first is magnified 10x, the second 20x, then 40x, 80x, 160x, 320x and finally 640x.