153 lines
4.7 KiB
Python
153 lines
4.7 KiB
Python
import noise
|
|
import random
|
|
from collections import defaultdict
|
|
import math
|
|
|
|
class Map():
|
|
|
|
def __init__( self, width=150, height=50, sealevel=50, scale=32, base=random.randint(1,250), lacunarity=0.5+random.random(), octaves=50, persistence=0.5, xoffset=random.randint(1,10000), yoffset=random.randint(1,10000) ):
|
|
|
|
print("Initializing map")
|
|
|
|
# Dealing with basic params
|
|
self.width = width
|
|
self.height = height
|
|
self.sealevel = -0.37+((0.75/100)*sealevel)
|
|
self.scale = scale
|
|
self.base = base
|
|
self.octaves = octaves
|
|
self.persistence = persistence
|
|
self.lacunarity = lacunarity
|
|
self.xoffset = xoffset
|
|
self.yoffset = yoffset
|
|
|
|
# The master map we are going to need
|
|
self.map = defaultdict(dict)
|
|
self.coast = []
|
|
|
|
# All the required stuff to determine cities
|
|
self.cities = []
|
|
# self.num_cities = 50+(100-int(self.sealevel))
|
|
self.num_cities = 75
|
|
self.coast_percentage = 25
|
|
self.distance = 3
|
|
|
|
|
|
def generateMap(self):
|
|
print("Generating Map")
|
|
# Fill in the blanks with random stuff
|
|
for x in range(1,self.width+1):
|
|
for y in range(1,self.height+1):
|
|
area = noise.pnoise2( self.xoffset+x/self.scale, self.yoffset+y/(self.scale/3), octaves=self.octaves, persistence=self.persistence, lacunarity=self.lacunarity, repeatx=self.height, repeaty=self.width, base=self.base )
|
|
if area > self.sealevel:
|
|
self.map[x][y] = "l"
|
|
else:
|
|
self.map[x][y] = "w"
|
|
|
|
|
|
# Find coastal positions
|
|
def findCoast(self):
|
|
print("Finding coastal tiles")
|
|
# Should replace with a range()-loop
|
|
y = 1
|
|
|
|
while y <= self.height:
|
|
x = 1
|
|
while x <= self.width:
|
|
water = 0
|
|
if x !=1 and x!=self.width and y!=1 and y!=self.height and self.map[x][y]=="l":
|
|
if self.map[x-1][y-1]=="w":
|
|
water += 1
|
|
if self.map[x][y-1]=="w":
|
|
water += 1
|
|
if self.map[x+1][y-1]=="w":
|
|
water += 1
|
|
if self.map[x+1][y]=="w":
|
|
water += 1
|
|
if self.map[x+1][y+1]=="w":
|
|
water += 1
|
|
if self.map[x][y+1]=="w":
|
|
water += 1
|
|
if self.map[x-1][y+1]=="w":
|
|
water += 1
|
|
if self.map[x-1][y]=="w":
|
|
water += 1
|
|
if water >= 1:
|
|
coords = {}
|
|
coords['x'] = x
|
|
coords['y'] = y
|
|
self.coast.append(coords)
|
|
x+=1
|
|
y+=1
|
|
|
|
|
|
def generateCities(self):
|
|
print("Generate cities")
|
|
for round in range(0,self.num_cities):
|
|
if random.randint(1,100) < self.coast_percentage:
|
|
self.cities.append(random.choice(self.coast))
|
|
else:
|
|
found = 0
|
|
while found == 0:
|
|
randX = random.randint(1,self.width)
|
|
randY = random.randint(1,self.height)
|
|
if self.map[randX][randY]=="l" and self.noCityNear(self.distance,randX,randY):
|
|
found = 1
|
|
coords = {}
|
|
coords['x'] = randX
|
|
coords['y'] = randY
|
|
self.cities.append(coords)
|
|
|
|
|
|
def noCityNear(self,distance,x,y):
|
|
noCityNear = True
|
|
counter = 0
|
|
for city in self.cities:
|
|
#Lay-Z D-Bug: print( str(counter) +" x:"+ str( abs(city['x']-x) ) +"; y:"+ str( abs(city['y']-y) ) +";")
|
|
# This should be an OR, but this takes forever! So this is good enough.
|
|
if abs(city['x']-x)<self.distance and abs(city['y']-y)<self.distance:
|
|
noCityNear = False
|
|
counter+=1
|
|
return noCityNear
|
|
|
|
|
|
def calcDistance(self,city,x,y):
|
|
return math.ceil( math.sqrt( ((city['x']-x)**2)+((city['y']-y)**2) ) )
|
|
|
|
|
|
def addCities(self):
|
|
print("Adding cities to map")
|
|
for city in self.cities:
|
|
self.map[city['x']][city['y']] = "c"
|
|
|
|
|
|
# Print the world in its entirety
|
|
# Per column we print the entire row
|
|
def printWorld(self):
|
|
print("Printing map: num_cities:"+str(self.num_cities)+" base:"+str(self.base)+" Offset:"+str(self.xoffset)+"/"+str(self.yoffset))
|
|
for y in range(1,self.height+1):
|
|
for x in range(1,self.width+1):
|
|
if self.map[x][y] == "c":
|
|
print('\x1b[1;37;42m' + '*' + '\x1b[0m', end='')
|
|
elif self.map[x][y] == "l":
|
|
print('\x1b[1;37;42m' + ' ' + '\x1b[0m', end='')
|
|
else:
|
|
print('\x1b[1;37;44m' + ' ' + '\x1b[0m', end='')
|
|
print("")
|
|
|
|
# Dump the map that Python can work with
|
|
def dumpMap(self):
|
|
terrain = self.map
|
|
metadata = {}
|
|
metadata['width'] = self.width
|
|
metadata['height'] = self.height
|
|
metadata['coast_percentage'] = self.coast_percentage
|
|
metadata['scale'] = self.scale
|
|
metadata['base'] = self.base
|
|
metadata['octaves'] = self.octaves
|
|
metadata['persistence'] = self.persistence
|
|
metadata['lacunarity'] = self.lacunarity
|
|
metadata['xoffset'] = self.xoffset
|
|
metadata['yoffset'] = self.yoffset
|
|
return terrain, self.cities, self.coast, metadata
|