emPYre/map.py
2022-10-17 19:17:22 +02:00

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