Module Buddhabrot
	private width as integer
	private height as integer
	private truewidth as double
	private trueheight as double
	
	private xcenter as double
	private ycenter as double
	private leftedge as double
	private topedge as double
		
	// upper escape limits
	private rlimit as integer
	private glimit as integer
	private blimit as integer
	private maxlimit as integer
	
	// lower escape limits
	private rlower as integer
	private glower as integer
	private blower as integer
	private minlimit as integer
	
	// color component scalrs
	private rscale as double
	private gscale as double
	private bscale as double
	
	// accumulators
	private racc(-1, -1) as integer
	private gacc(-1, -1) as integer
	private bacc(-1, -1) as integer

	Private Function lerpx( x as Integer ) as Double
		return (x / width) * truewidth + leftedge
	End Function
	
	Private Function lerpy( y as Integer ) as Double
		return (y / height) * -1 * trueheight + topedge
	End Function
	
	Private Function delerpx( x as Double ) as Integer
		return ((x - leftedge) / truewidth) * width
	End Function
	
	Private Function delerpy( y as Double ) as Integer
		return ((y - topedge) / (-1 * trueheight)) * height
	End Function
	
	Private Function Colorize( x as integer, y as integer) as color
		dim red, green, blue as integer
		red = min(255, racc(x, y) * rscale)
		green = min(255, gacc(x, y) * gscale)
		blue = min(255, bacc(x, y) * bscale)
		return rgb(red, green, blue)
	End Function
	
	Private Function Escapes( x0 as Double, y0 as Double ) as Integer
		dim x, y, x2, y2 as double
		x = x0
		y = y0
		x2 = pow(x, 2.0)
		y2 = pow(y, 2.0)
		
		dim i as integer 
		while i < maxlimit and (x2 + y2 < 4.0)
			y = 2.0 * x * y + y0
			x = x2 - y2 + x0
			x2 = pow(x, 2.0)
			y2 = pow(y, 2.0)
			
			i = i + 1
		wend
		
		return i
	End Function
	
	Private Sub Traceroute( s as Integer, x0 as Double, y0 as Double )
		if s >= maxlimit or s <= minlimit then return
	
		dim rescapes, gescapes, bescapes as boolean
		rescapes = rlower < s and s < rlimit
		gescapes = glower < s and s < glimit
		bescapes = blower < s and s < blimit
			
		dim x, y, x2, y2 as double
		x = x0
		y = y0
		x2 = pow(x, 2.0)
		y2 = pow(y, 2.0)
		
		dim i as integer
		while i < maxlimit and (x2 + y2 < 4.0)
			y = 2.0 * x * y + y0
			x = x2 - y2 + x0
			x2 = pow(x, 2.0)
			y2 = pow(y, 2.0)
			
			dim xi, yi as integer
			xi = delerpx(x)
			yi = delerpy(y)
			
			if xi >= 0 and yi >= 0 and xi < width and yi < height then
				if rescapes then racc(xi, yi) = racc(xi, yi) + 1
				if gescapes then gacc(xi, yi) = gacc(xi, yi) + 1
				if bescapes then bacc(xi, yi) = bacc(xi, yi) + 1
			end if
			
			i = i + 1
		wend
	End Sub

	Sub Render(w as integer, h as integer, xc as double, yc as double, scale as double)
		width = h
		height = w
		xcenter = xc // -0.5
		ycenter = yc // 0.0
		rlimit = 0
		glimit = 450
		blimit = 1000
		rlower = 0
		glower = 80
		blower = 100
		rscale = 0
		gscale = 30
		bscale = 30
		
		redim racc(width - 1, height - 1)
		redim gacc(width - 1, height - 1)
		redim bacc(width - 1, height - 1)
		
		truewidth = 3.0 / scale
		trueheight = 2.0 / scale
		leftedge = xcenter - truewidth / 2.0
		topedge = ycenter + trueheight / 2.0
		maxlimit = max(rlimit, max(glimit, blimit))
		minlimit = min(rlower, min(glower, blower))
		
		for x as integer = 0 to width - 1
			for y as integer = 0 to height - 1
				
				dim x0, y0 as double
				x0 = lerpx( x )
				y0 = lerpy( y )
				
				dim escapes as integer
				escapes = escapes(x0, y0)
				
				traceroute escapes, x0, y0
			next
		next
		
		// Convert the accumulators back to colors
		dim pixels(-1, -1) as color
		redim pixels(w - 1, h - 1)
		for x as integer = 0 to w - 1
			for y as integer = 0 to h - 1
				pixels(x, y) = colorize(y, x)
			next
		next
		setpixels(pixels)
	End Sub
End Module

Buddhabrot.Render(384, 512, -0.5, 0.0, 1.0)