Skip to content

Instantly share code, notes, and snippets.

@pbsds
Created May 9, 2013 21:00
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 pbsds/5550589 to your computer and use it in GitHub Desktop.
Save pbsds/5550589 to your computer and use it in GitHub Desktop.
A simple random map generator using seeding and growth to produce it's landmasses.
import Image, random, math
#Made by pbsds/Peder Bergebakken Sundt
#Requires PIL to work
Palette = (0x0045A0,#0 - Dark water
0x0059BC,#1 - Water
0x0078F9,#2 - Shore water
0xFFF65E,#3 - Sand
0x2BE81F,#4 - Grass
0x26B719,#5 - Dark Grass
0xA8712F,#6 - Mountain foot
0x7F3300,#7 - Mountain side
0xA8865C,#8 - Mountain top
0xCEA471,#9 - Mountain peak
0x006B0A,#10- Tree
0xFF0000)#11- City
def Random(i1, i2):
if i1 == i2:
return i1
return int(random.randrange(i1,i2))
def TryInt(i):#tries to convert to int, if possible
try:
return int(i)
except:
return i
def CircleOffsets(Radius):
ret = []
for y in xrange(-Radius-1,Radius+1):
for x in xrange(-Radius-1,Radius+1):
if math.sqrt(x**2 + y**2) <= Radius:
ret.append((x, y))
return ret
def DecAsc(dec,pad = -1):#Converts a decimal into an ascii string with the specified padding(Big Endian)
ret = ""
while dec <> 0:
ret = chr(dec&0xFF) + ret
dec >>= 8
if pad <> -1:
if len(ret) > pad:
ret = ret[:pad]
if len(ret) < pad:
ret = "\0"*(pad-len(ret)) + ret
return ret
def SaveImage(Map, OutputPath = "out.png"):
global Palette
w = len(Map)
h = len(Map[0])
data = []
for y in range(h):
for x in range(w):
data.append(DecAsc(Palette[Map[x][y]],3))
#data[x+y*w] = DecAsc(Map[x][y],3)
data = "".join(data)
img = Image.fromstring("RGB", (w, h), data)
filetype = OutputPath[OutputPath.rfind(".")+1:]
img.save(OutputPath, filetype)
print " - pbsds's map generator -"
print "The values inside the parentheses are my personal preferences during testing."
random.seed(TryInt(raw_input("Insert psuedo-random seed(1337): ")))
Chance = input("Insert land-spread chance percentage(99): ")
Seeds = input("Insert number of inital land-seeds(20-30): ")
Frame = input("Insert border padding size for thhe land-seeds(0): ")
MapWidth = input("Insert output image width(400-500): ")
MapHeight = input("Insert output image height(400-500): ")
print "Generating the land masses..."
Check = []#the pixels to work with
Map = [[None for y in xrange(MapHeight)] for x in xrange(MapWidth)]#None = Unset, or the indexes from Palette
WidthRange = range(MapWidth)
HeightRange = range(MapHeight)
#inital land-roots:
for i in xrange(Seeds):
x = Random(Frame, MapWidth-1-Frame)
y = Random(Frame, MapHeight-1-Frame)
Map[x][y] = 5#dark grass
Check.append((x,y))
#Create the landmasses:
while Check:
x, y = Check.pop(Random(0,len(Check)-1))
for x2, y2 in ((x-1, y-1), (x, y-1), (x+1, y-1), (x+1, y), (x+1, y+1), (x, y+1), (x-1, y+1), (x-1, y)):#For each neightbor:
if not (x2 < 0 or x2 >= MapWidth or y2 < 0 or y2 >= MapHeight):#If within the map:
if Map[x2][y2] == None:#If neighboring pixel isn't set yet:
#if current pixel is water, set neightboring pixel to water.
#if it's land, set the neightboring pixel to either land or water chosen randomly
if Map[x][y] == 0:
Map[x2][y2] = 0#water
else:
if Random(0,100) < Chance:
Map[x2][y2] = 5#grass
else:
Map[x2][y2] = 0#water
Check.append((x2,y2))
print "Removing 1x1 sized lakes..."
for y in HeightRange:
for x in WidthRange:
if Map[x][y] == 0:
Remove = True
for x2, y2 in ((x+1,y), (x-1,y), (x,y+1), (x,y-1)):
if 0 <= x2 < MapWidth and 0 <= y2 < MapHeight:
if Map[x2][y2] == 0:
Remove = False
break
if Remove:
Map[x][y] = 5
#Colour the map:
print "Colouring the map..."
Radius1 = CircleOffsets(4)
Radius2 = CircleOffsets(13)
for i in Radius1:
Radius2.remove(i)
Radius1.remove((0,0))
for y in HeightRange:
for x in WidthRange:
if Map[x][y] in (4, 5):
#Check if by the water:
for x2, y2 in ((x+1,y), (x-1,y), (x,y+1), (x,y-1)):
if 0 <= x2 < MapWidth and 0 <= y2 < MapHeight:
if Map[x2][y2] in (2,1,0):
#Add the sand shore:
Map[x][y] = 3#sand
#Add Bright water along the shore:
for x2, y2 in Radius1:
if not (x+x2 < 0 or x+x2 >= MapWidth or y+y2 < 0 or y+y2 >= MapHeight):
if Map[x+x2][y+y2] in (0,1):
Map[x+x2][y+y2] = 2#Shore water
#add deeper water further out along the shore and lighter grass:
for x2, y2 in Radius2:
if not (x+x2 < 0 or x+x2 >= MapWidth or y+y2 < 0 or y+y2 >= MapHeight):
if Map[x+x2][y+y2] == 0:
Map[x+x2][y+y2] = 1#normal water
elif Map[x+x2][y+y2] == 5:
Map[x+x2][y+y2] = 4#light grass
#Finishing the work:
print "Saving as png...",
SaveImage(Map)
print "Done!"
@pbsds
Copy link
Author

pbsds commented Jun 28, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment