Created
August 30, 2014 04:48
-
-
Save BennyHallett/0199fd04ea797b437c15 to your computer and use it in GitHub Desktop.
Unfinished Terrain Generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Terrain do | |
def generate do | |
size = 65 # or 129, 513, 1025 (2^x + 1) | |
initial_state(size) | |
|> diamond { 0, 0 }, { size-1, size-1 } | |
end | |
defp diamond(current, { x1, y1 }, { x2, y2 }) when x2 == x1 + 2 and y2 == y1 + 2 do | |
current | |
|> top( { x1, y1 }, { x2, y2 } ) | |
|> bottom( { x1, y1 }, { x2, y2 } ) | |
|> left( { x1, y1 }, { x2, y2 } ) | |
|> right( { x1, y1 }, { x2, y2 } ) | |
|> center( { x1, y1 }, { x2, y2 } ) | |
end | |
defp diamond(current, { x1, y1 }, { x2, y2 }) do | |
current | |
|> top( { x1, y1 }, { x2, y2 } ) | |
|> bottom( { x1, y1 }, { x2, y2 } ) | |
|> left( { x1, y1 }, { x2, y2 } ) | |
|> right( { x1, y1 }, { x2, y2 } ) | |
|> center( { x1, y1 }, { x2, y2 } ) | |
|> diamond( { x1, y1 }, { div(x1 + x2, 2), div(y1 + y2, 2) } ) | |
|> diamond( { div(x1 + x2, 2), y1 }, { x2, div(y1 + y2, 2) } ) | |
|> diamond( { x1, div(y1 + y2, 2) }, { div(x1 + x2, 2), y2 } ) | |
|> diamond( { div(x1 + x2, 2), div(y1 + y2, 2) }, { x2, y2 } ) | |
end | |
defp top(current, { x1, y1 }, { x2, y2 }) do | |
{ _, v1 } = Enum.find current, fn({ { x1, y1 }, value }) -> 0 end | |
{ _, v2 } = Enum.find current, fn({ { x2, y1 }, value }) -> 0 end | |
IO.puts "#{x1} #{y1} #{x2} #{y2}" | |
[ { { div(x1 + x2, 2), y1 }, (v1 + v2) / 2 } | current ] | |
end | |
defp bottom(current, { x1, y1 }, { x2, y2 }) do | |
{ _, v1 } = Enum.find current, fn({ { x1, y2 }, value }) -> 0 end | |
{ _, v2 } = Enum.find current, fn({ { x2, y2 }, value }) -> 0 end | |
[ { { div(x1 + x2, 2), y2 }, (v1 + v2) / 2 } | current ] | |
end | |
defp left(current, { x1, y1 }, { x2, y2 }) do | |
{ _, v1 } = Enum.find current, fn({ { x1, y1 }, value }) -> 0 end | |
{ _, v2 } = Enum.find current, fn({ { x1, y2 }, value }) -> 0 end | |
[ { { x1, div(y1 + y2, 2) }, (v1 + v2) / 2 } | current ] | |
end | |
defp right(current, { x1, y1 }, { x2, y2 }) do | |
{ _, v1 } = Enum.find current, fn({ { x2, y1 }, value }) -> 0 end | |
{ _, v2 } = Enum.find current, fn({ { x2, y2 }, value }) -> 0 end | |
[ { { x2, div(y1 + y2, 2) }, (v1 + v2) / 2 } | current ] | |
end | |
defp center(current, { x1, y1 }, { x2, y2 }) do | |
{ _, v1 } = Enum.find current, fn({ { x1, y1 }, value }) -> 0 end | |
{ _, v2 } = Enum.find current, fn({ { x2, y1 }, value }) -> 0 end | |
{ _, v3 } = Enum.find current, fn({ { x2, y2 }, value }) -> 0 end | |
{ _, v4 } = Enum.find current, fn({ { x1, y2 }, value }) -> 0 end | |
[ { { div(x1 + x2, 2), div(y1 + y2, 2) }, (v1 + v2 + v3 + v4) / 4 } | current ] | |
end | |
defp initial_state(size) do | |
[ | |
{ {0, 0}, :random.uniform }, | |
{ {0, size-1}, :random.uniform }, | |
{ {size-1, 0}, :random.uniform }, | |
{ {size-1, size-1}, :random.uniform } | |
] | |
end | |
def draw(heightmap) do | |
output = Enum.map(1..65*65, fn _ -> " " end) | |
output = update_output heightmap, output | |
File.open("terrain.txt", [:write], fn f -> | |
output |> draw_line(f) | |
end) | |
end | |
defp update_output([], output) do | |
output | |
end | |
defp update_output([ { {x, y}, value } | t ], output) do | |
IO.puts "Updating #{x},#{y}:#{point_to_pos(x, y)} to be #{point_to_char(value)}" | |
output = List.update_at(output, point_to_pos(x, y), fn _ -> point_to_char(value) end) | |
update_output t, output | |
end | |
defp draw_line([], _) do | |
end | |
defp draw_line(chars, file) do | |
{line, remaining} = Enum.split chars, 65 | |
Enum.each line, &(IO.write file, &1) | |
IO.write file, "\n" | |
draw_line remaining, file | |
end | |
defp point_to_pos(x, y) do (y*57) + x end | |
defp point_to_char(a) when a > 0.6 do "^" end | |
defp point_to_char(a) when a < 0.3 do "~" end | |
defp point_to_char(a) do "." end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment