' Mandelbrot set renderer: fractal exploration
#COMPILE EXE
#DIM ALL

FUNCTION MandelIter(BYVAL cx AS DOUBLE, BYVAL cy AS DOUBLE) AS LONG
    LOCAL x  AS DOUBLE
    LOCAL y  AS DOUBLE
    LOCAL xtemp  AS DOUBLE
    LOCAL iter AS LONG
    x = 0.0
    y = 0.0
    FOR iter = 0 TO 255
        IF x * x + y * y > 4.0 THEN
            FUNCTION = iter
        END IF
        xtemp = x * x - y * y + cx
        y = 2.0 * x * y + cy
        x = xtemp
    NEXT iter
    FUNCTION = 255
END FUNCTION

FUNCTION MandelColor(BYVAL iter AS LONG) AS LONG
    LOCAL r  AS LONG
    LOCAL g  AS LONG
    LOCAL b  AS LONG
    IF iter = 255 THEN
        FUNCTION = 0
    END IF
    r = (iter * 8) MOD 256
    g = (iter * 16) MOD 256
    b = (iter * 4) MOD 256
    FUNCTION = r OR (g * 256) OR (b * 65536)
END FUNCTION

SUB RenderMandelText()
    LOCAL py  AS LONG
    LOCAL px  AS LONG
    LOCAL iter  AS LONG
    LOCAL mx  AS DOUBLE
    LOCAL my  AS DOUBLE
    PRINT "Mandelbrot set (text preview 60x30):"
    PRINT ""
    FOR py = 0 TO 29
        my = (py / 30.0) * 3.0 - 1.5
        LOCAL line AS STRING
        line = ""
        FOR px = 0 TO 59
            mx = (px / 60.0) * 3.5 - 2.5
            iter = MandelIter(mx, my)
            IF iter = 255 THEN
                line = line + "#"
            ELSEIF iter > 100 THEN
                line = line + "."
            ELSEIF iter > 20 THEN
                line = line + "*"
            ELSE
                line = line + " "
            END IF
        NEXT px
        PRINT line
    NEXT py
END SUB

SUB ZoomPreview(BYVAL cx AS DOUBLE, BYVAL cy AS DOUBLE, BYVAL radius AS DOUBLE, BYVAL steps AS LONG)
    PRINT "Zooming to ("; cx; ","; cy; ") radius="; radius
    LOCAL i AS LONG
    LOCAL r AS DOUBLE
    r = radius
    FOR i = 1 TO steps
        r = r * 0.5
        PRINT "  step "; i; ": radius="; r
    NEXT i
END SUB

SUB JuliaPreview(BYVAL cx AS DOUBLE, BYVAL cy AS DOUBLE)
    PRINT "Julia set preview at ("; cx; ","; cy; "):"
    LOCAL py  AS LONG
    LOCAL px  AS LONG
    LOCAL iter  AS LONG
    LOCAL mx  AS LONG
    LOCAL jx  AS DOUBLE
    LOCAL jy  AS DOUBLE
    LOCAL zx  AS DOUBLE
    LOCAL zy  AS DOUBLE
    LOCAL zxt  AS DOUBLE
    FOR py = 0 TO 19
        jy = (py / 20.0) * 4.0 - 2.0
        LOCAL line AS STRING
        line = ""
        FOR px = 0 TO 39
            jx = (px / 40.0) * 4.0 - 2.0
            zx = jx
            zy = jy
            iter = 0
            FOR mx = 0 TO 127
                IF zx * zx + zy * zy > 4.0 THEN
                    iter = mx
                END IF
                zxt = zx * zx - zy * zy + cx
                zy = 2.0 * zx * zy + cy
                zx = zxt
            NEXT mx
            IF iter > 100 THEN
                line = line + "."
            ELSE
                line = line + " "
            END IF
        NEXT px
        PRINT line
    NEXT py
END SUB

SUB BurnShipPreview()
    PRINT "Burning Ship fractal preview:"
    LOCAL py  AS LONG
    LOCAL px  AS LONG
    LOCAL iter  AS LONG
    LOCAL mx  AS LONG
    LOCAL zx  AS DOUBLE
    LOCAL zy  AS DOUBLE
    LOCAL zxt  AS DOUBLE
    FOR py = 0 TO 19
        zy = (py / 20.0) * 4.0 - 2.0
        LOCAL line AS STRING
        line = ""
        FOR px = 0 TO 39
            zx = (px / 40.0) * 4.0 - 2.0
            LOCAL a  AS DOUBLE
            LOCAL b  AS DOUBLE
            a = zx
            b = zy
            iter = 0
            FOR mx = 0 TO 127
                IF a * a + b * b > 4.0 THEN
                    iter = mx
                END IF
                zxt = a * a - b * b + zx
                b = 2.0 * ABS(a * b) + zy
                a = zxt
            NEXT mx
            IF iter = 0 THEN
                line = line + "#"
            ELSE
                line = line + "."
            END IF
        NEXT px
        PRINT line
    NEXT py
END SUB

FUNCTION PBMAIN() AS LONG
    PRINT "=== Mandelbrot & Julia Fractal Explorer ==="
    PRINT ""
    RenderMandelText()
    PRINT ""
    ZoomPreview(-0.5, 0.0, 2.0, 6)
    PRINT ""
    JuliaPreview(-0.7, 0.27)
    PRINT ""
    BurnShipPreview()
    PRINT ""
    PRINT "=== End Mandelbrot Demo ==="
    FUNCTION = 0
END FUNCTION
