Created
July 16, 2021 12:56
-
-
Save vgalin/81f4180dca48c701823ce5c808824f47 to your computer and use it in GitHub Desktop.
squarity-cellular-automata-poc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
https://i.imgur.com/I6zEQh5.png | |
-------- | |
{ | |
"game_area": { | |
"nb_tile_width": 32, | |
"nb_tile_height": 32 | |
}, | |
"tile_size": 16, | |
"img_coords": { | |
"b": [0, 0], | |
"g": [16, 0], | |
"^": [32, 0] | |
} | |
} | |
-------- | |
import random | |
# image = https://i.imgur.com/I6zEQh5.png | |
LEVEL = [] | |
AVAILABLE_TILES = 'bg^' | |
CHANCE_TO_START_ALIVE = 0.4 | |
BIRTH_LIMIT = 4 | |
DEATH_LIMIT= 3 | |
NO_OF_STEPS = 2 | |
def count_alive_neighbours(map, x, y, alive): | |
count = 0 | |
width = len(map[0]) | |
height = len(map) | |
i=-1 | |
while i < 2: | |
j=-1 | |
while j < 2: | |
neighbour_x = x + i | |
neighbour_y = y + j | |
if i == 0 and j == 0: | |
pass | |
elif (neighbour_x < 0 or neighbour_y < 0 or | |
neighbour_x >= height or | |
neighbour_y >= width): | |
count += 1 | |
elif (map[neighbour_x][neighbour_y] == alive): | |
count += 1 | |
j += 1 | |
i += 1 | |
return count | |
def count_alive_neighbours_OLD(map, x, y, alive): | |
count = 0 | |
for i in range(x-1, x+2): | |
for j in range(y-1, y+2): | |
if i == x and j == y: | |
continue | |
if i >= 0 and i < len(map) and j >= 0 and j < len(map[0]): | |
if map[i][j] == alive: | |
count += 1 | |
return count | |
def do_simulation_step(old_map, dead, alive): | |
width = len(old_map[0]) | |
height = len(old_map) | |
# init new map with empty cells | |
new_map = [] | |
for _ in range(width): | |
line = [] | |
for _ in range(height): | |
line.append(dead) | |
new_map.append(line) | |
for x in range(height): | |
for y in range(width): | |
nbs = count_alive_neighbours(old_map, x, y, alive) | |
# nbs = count_alive_neighbours_OLD(old_map, x, y, alive) | |
# The new value is based on our simulation rules | |
# First, if a cell is alive but has too few neighbours, kill it. | |
if old_map[x][y] == alive: | |
if nbs < DEATH_LIMIT: | |
new_map[x][y] = dead | |
else: | |
new_map[x][y] = alive | |
# Otherwise, if the cell is dead now, check if it has the right number of neighbours to be 'born' | |
else: | |
if nbs > BIRTH_LIMIT: | |
new_map[x][y] = alive | |
else: | |
new_map[x][y] = dead | |
return new_map | |
def init_with_noise(width, height, dead, alive): | |
map = [] | |
for _ in range(width): | |
line = [] | |
for _ in range(height): | |
if random.random() < CHANCE_TO_START_ALIVE: | |
line.append(alive) | |
else: | |
line.append(dead) | |
map.append(line) | |
return map | |
def generate_with_automata(width, height, dead, alive): # SEED ? | |
map = init_with_noise(width, height, dead, alive) | |
for _ in range(NO_OF_STEPS): | |
map = do_simulation_step(map, dead, alive) | |
return map | |
class GameModel(): | |
def __init__(self): | |
self.w = 32 | |
self.h = 32 | |
self.tiles = [ | |
[ | |
[] for x in range(self.w) | |
] | |
for y in range(self.h) | |
] | |
LEVEL = generate_with_automata(self.w, self.h, dead='g', alive='b') | |
for y in range(self.h): | |
for x in range(self.w): | |
if LEVEL[y][x] != ' ': | |
self.tiles[y][x] = LEVEL[y][x] | |
def export_all_tiles(self): | |
return self.tiles | |
def __str__(self): | |
ret = '' | |
for y in range(self.h): | |
for x in range(self.w): | |
ret += str(self.tiles[y][x]) | |
ret += '\n' | |
return ret | |
if __name__ == '__main__': | |
model = GameModel() | |
print(model) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment