Merge branch 'master' into map_generation
# Conflicts: # dungeonbattle/game.py # squirrelbattle/mapgeneration/__init__.py # squirrelbattle/mapgeneration/randomwalk.py
This commit is contained in:
0
squirrelbattle/mapgeneration/__init__.py
Normal file
0
squirrelbattle/mapgeneration/__init__.py
Normal file
98
squirrelbattle/mapgeneration/randomwalk.py
Normal file
98
squirrelbattle/mapgeneration/randomwalk.py
Normal file
@ -0,0 +1,98 @@
|
||||
from enum import auto, Enum
|
||||
from random import choice, random, randint
|
||||
from dungeonbattle.interfaces import Map, Tile
|
||||
|
||||
|
||||
DEFAULT_PARAMS = {"split_chance" : .15,
|
||||
"turn_chance" : .5,
|
||||
"death_chance" : .1,
|
||||
"max_walkers" : 15,
|
||||
"width" : 100,
|
||||
"height" : 100,
|
||||
"fill" : .4}
|
||||
|
||||
|
||||
class Directions(Enum):
|
||||
up = auto()
|
||||
down = auto()
|
||||
left = auto()
|
||||
right = auto()
|
||||
|
||||
|
||||
class Walker:
|
||||
|
||||
def __init__(self, x, y):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.dir = choice(list(Directions))
|
||||
|
||||
def random_turn(self):
|
||||
self.dir = choice(list(Directions))
|
||||
|
||||
def next_pos(self):
|
||||
if self.dir == Directions.up:
|
||||
return self.x, self.y + 1
|
||||
elif self.dir == Directions.down:
|
||||
return self.x, self.y - 1
|
||||
elif self.dir == Directions.right:
|
||||
return self.x + 1, self.y
|
||||
elif self.dir == Directions.left:
|
||||
return self.x - 1, self.y
|
||||
|
||||
def move_in_bounds(self, width, height):
|
||||
nx, ny = self.next_pos()
|
||||
if 0 < nx < width and 0 < ny < height:
|
||||
self.x, self.y = nx, ny
|
||||
|
||||
def split(self):
|
||||
child = Walker(self.x, self.y)
|
||||
child.dir = self.dir
|
||||
return child
|
||||
|
||||
|
||||
class Generator:
|
||||
|
||||
def __init__(self, params = DEFAULT_PARAMS):
|
||||
self.params = params
|
||||
|
||||
def run(self):
|
||||
width, height = self.params["width"], self.params["height"]
|
||||
walkers = [Walker(width//2, height//2)]
|
||||
grid = [[Tile.EMPTY for _ in range(width)] for _ in range(height)]
|
||||
count = 0
|
||||
while count < self.params["fill"] * width*height:
|
||||
# because we can't add or remove walkers while looping over the pop
|
||||
# we need lists to keep track of what will be the walkers for the
|
||||
# next iteration of the main loop
|
||||
next_walker_pop = []
|
||||
|
||||
for walker in walkers:
|
||||
if grid[walker.y][walker.x] == Tile.EMPTY:
|
||||
count += 1
|
||||
grid[walker.y][walker.x] = Tile.FLOOR
|
||||
if random() < self.params["turn_chance"]:
|
||||
walker.random_turn()
|
||||
walker.move_in_bounds(width, height)
|
||||
if random() > self.params["death_chance"]:
|
||||
next_walker_pop.append(walker)
|
||||
|
||||
# we make sure to never kill all walkers
|
||||
if next_walker_pop == []:
|
||||
next_walker_pop.append(choice(walkers))
|
||||
|
||||
# we use a second loop for spliting so we're not bothered by cases
|
||||
# like a walker not spliting because we hit the population cap even
|
||||
# though the next one would have died and freed a place
|
||||
# not a big if it happened though
|
||||
for walker in walkers:
|
||||
if len(next_walker_pop) < self.params["max_walkers"]:
|
||||
if random() < self.params["split_chance"]:
|
||||
next_walker_pop.append(walker.split())
|
||||
walkers = next_walker_pop
|
||||
|
||||
|
||||
start_x, start_y = randint(0, width-1), randint(0, height-1)
|
||||
while grid[start_y][start_x] != Tile.FLOOR:
|
||||
start_x, start_y = randint(0, width-1), randint(0, height-1)
|
||||
|
||||
return Map(width, height, grid, start_x, start_y)
|
Reference in New Issue
Block a user