function InitVisibility()
	local Temp1, Temp2, Temp3, Temp4, Temp5, Width, Height = GetMapData( 0, 0 )

	for Y = 0, Height - 1 do
		for X = 0, Width - 1 do
			local Tile, Status, R, G, B = GetMapData( X, Y )

			if Status > 1 then SetMapData( X, Y, 2, 64, 64, 64 ) end
		end
	end
end

function UpdateVisibility( TileX, TileY, Range, ColorR, ColorG, ColorB )
	local Temp1, Temp2, Temp3, Temp4, Temp5, Width, Height, Depth = GetMapData( 0, 0 )

	if Depth < 2 then
		for Y = 0, Height - 1 do
			for X = 0, Width - 1 do
				SetMapData( X, Y, 3, 255, 255, 255 )
			end
		end
	else
		local RangeSq  = Range*Range
		local InvRange = 1.0/RangeSq

		for Y = Max( TileY - math.floor( Range*0.6 ) - 2, 0 ), Min( TileY + math.floor( Range*0.6 ) + 2, Height - 1 ) do
			for X = Max( TileX - Range - 2, 0 ), Min( TileX + Range + 2, Width - 1 ) do
				local Tile, Status, R, G, B = GetMapData( X, Y )

				if not LineMapIntersection( TileX, TileY, X, Y ) then
					local Distance = ( TileX - X )*( TileX - X ) + ( TileY - Y )*( TileY - Y )*2.78

					if Distance <= Range*Range then
						local RatioR = Max( 64 + ColorR - math.floor( Distance*InvRange*ColorR ), 0 )
						local RatioG = Max( 64 + ColorG - math.floor( Distance*InvRange*ColorG ), 0 )
						local RatioB = Max( 64 + ColorB - math.floor( Distance*InvRange*ColorB ), 0 )

						if Status == 3 then
							SetMapData( X, Y, 3, Min( R + RatioR, 255 ), Min( G + RatioG, 255 ), Min( B + RatioB, 255 ) )
						else
							SetMapData( X, Y, 3,          RatioR       ,          RatioG       ,          RatioB        )
						end
					end
				end
			end
		end
	end
end

function LineMapIntersection( X1, Y1, X2, Y2 )
	local WaitForSpace

	local DX = X2 - X1
	local DY = Y2 - Y1

	local ADX = math.abs( DX )
	local ADY = math.abs( DY )

	local SDX = Sgn( DX )
	local SDY = Sgn( DY )

	local PDX, PDY, DDX, DDY, ErrorFast, ErrorSlow

	if ADX > ADY then
		PDX = SDX
		PDY = 0

		DDX = SDX
		DDY = SDY
		ErrorFast = ADY
		ErrorSlow = ADX
	else
		PDX = 0
		PDY = SDY
		DDX = SDX
		DDY = SDY
		ErrorFast = ADX
		ErrorSlow = ADY
	end

	local X = X1
	local Y = Y1

	local Error = math.floor( ErrorSlow/2 )

	for I = 1, ErrorSlow do
		Error = Error - ErrorFast

		if Error < 0 then
			Error = Error + ErrorSlow

			X = X + DDX
			Y = Y + DDY
		else
			X = X + PDX
			Y = Y + PDY
		end

		if X == X2 and Y == Y2 then return false end

		if IsWall( X, Y ) then
			if IsWall( X2, Y2 ) then
				WaitForSpace = true
			else
				return true
			end
		else
			if WaitForSpace then return true end
		end
	end

	return false
end

function IsWall( X, Y )
	return GetMapData( X, Y ) == string.byte( "#" )
end
