Skip to content

Instantly share code, notes, and snippets.

@pachacamac
Last active December 7, 2015 12:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pachacamac/b058f0bf9ef17105110b to your computer and use it in GitHub Desktop.
Save pachacamac/b058f0bf9ef17105110b to your computer and use it in GitHub Desktop.
quick and dirty procedural island generation
class String
def rgb(r,g,b, bg=false) "\033[#{bg ? 48 : 38};5;#{ 16 + 36 * (r/43) + 6 * (g/43) + (b/43) }m#{self}\033[0;00m" end
end
PALETTE = [0x279faf, 0x3ec2d9, 0x86cfd6, 0xc2dcd1, 0xebd8b8, 0xd9be93, 0xc6a16d, 0xa07644, 0x74a044, 0x2e7f21, 0x440044, 0xff0000].map{|c|
[(c & 0xff0000) >> 16, (c & 0x00ff00) >> 8, c & 0x0000ff]}
def show(m, w=nil, h=nil, pal=PALETTE)
(w0,wn),(h0,hn) = m.keys.minmax_by(&:first).map(&:first), m.keys.minmax_by(&:last).map(&:last)
arr = []
(w0..wn).each do |x|
line = []
(h0..hn).each do |y|
line << (m[[x,y]] == 11 ? 'X' : ' ').rgb(*pal[m[[x,y]]], true)
end
arr << line
end
puts arr.map(&:join).join("\n")
end
def neighbors(m,x,y)
[[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]].map{|dx,dy| [m[[dy+x,dy+x]], [dx+x, dy+y]] }
end
def ncount(m,x,y)
neighbors(m,x,y).count{|e,xy| e > 0}
end
def lake_maker(m, xy, opts={})
opts[:lake_iterations] ||= 3
m[xy] /= 2
neighbors(m,*xy).sample(opts[:lake_neighbor_samples]||3, random: opts[:prng]||Random.new).each do |val, nxy|
m[nxy] /= 2
if opts[:lake_iterations] > 0
o = opts.dup
o[:lake_iterations] -= 1
m = lake_maker(m, nxy, o)
end
end
m
end
def gen(opts={})
w,h = opts[:w] || 64, opts[:h] || 64
r = Random.new(opts[:seed]||rand(99999))
m = Hash.new(0)
(opts[:land_seeds]||4).times{ m[[r.rand(h), r.rand(w)]] = 1 }
(opts[:land_iterations]||20).times do
_m = m.dup
m.keys.each do |x,y|
if ncount(m,x,y) < 3
_m[[x,y]] += 1 if _m[[x,y]] < 10.times.map{|e| 9-(e**2)/10}.sample(random: r)
neighbors(m,x,y).sample(2, random: r).each do |v,xy|
_m[xy] += 1 if _m[xy] < 4
end
end
end
m = _m
end
# generate lakes
(opts[:lake_seeds]||4).times do
begin
xy = m.keys.sample(random: r)
end while m[xy] < 6
m = lake_maker(m, xy, opts.merge(pnrg: r))
end
way_makers = [[[-1,0],[0,-1],[0,1]], [[-1,0],[0,-1],[1,0]], [[1,0],[0,1],[0,-1]], [[1,0],[0,1],[-1,0]]]
# generate rivers
(opts[:river_seeds]||4).times do
xy = m.keys.sample(random: r)
ds = way_makers.sample(random: r)
loop do
d = ds.sample(random: r)
xy = [xy[0]+d[0], xy[1]+d[1]]
break if m[xy] == 0
m[xy] /= 3
end
end
# generate treasure and path
begin
xy = m.keys.sample(random: r)
end while m[xy] < 6
m[xy] = 11
ds = way_makers.sample(random: r)
loop do
d = ds.sample(random: r)
xy = [xy[0]+d[0], xy[1]+d[1]]
break if m[xy] == 0
m[xy] = 10 unless m[xy] == 11
end
m
end
seed = (ARGV[0]||rand(9999)).to_i
show(gen(w:256, h:64, land_seeds:10, lake_neighbor_samples:2, lake_iterations:6, river_seeds:8, land_iterations:25, seed:seed))
puts seed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment