Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ jobs:
run: uv run ruff check

- name: Run Formatter
run: uv run ruff format --check
run: uv run ruff format --check

- name: Run Tests
run: uv run pytest
13 changes: 12 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
repos:
# Run lint
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.9.9
hooks:
# Run the linter.
- id: ruff
# Run the formatter.
- id: ruff-format
- id: ruff-format
# Run the tests.
- repo: local
hooks:
- id: pytest
name: pytest
entry: ./.venv/bin/pytest
language: system
types: [python]
pass_filenames: false
always_run: true
Empty file added game/__init__.py
Empty file.
12 changes: 12 additions & 0 deletions game/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import typer

app = typer.Typer()


@app.command()
def main():
print("Hello, World!")


if __name__ == "__main__":
app()
Empty file added game/tests/__init__.py
Empty file.
32 changes: 32 additions & 0 deletions game/tests/map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from game.utils.map import Map


def test_neighbour_count():
excepted_neighbours = 2
game_map = Map()

neighbours = game_map.count_neighbours(1, 1)

assert neighbours == excepted_neighbours


def test_neighbour_count_fail():
excepted_neighbours = 1
game_map = Map()

neighbours = game_map.count_neighbours(1, 1)

assert neighbours != excepted_neighbours


def test_next_generation():
expected_map = [[False, True, True, True, False, False, False, False, False, False] for _ in range(3)] + [
[False for _ in range(10)] for _ in range(7)
]
print(expected_map)
game_map = Map()

game_map.next_generation()
print(game_map.map)

assert game_map.map == expected_map
Empty file added game/utils/__init__.py
Empty file.
100 changes: 100 additions & 0 deletions game/utils/map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
class AbstractMap:
"""
Abstract class for the map.
"""

population = int
generation = int
map = list[list[bool]]

def __init__(self, game_map: list[list[bool]] = None):
if game_map is None:
game_map = [[False for _ in range(10)] for _ in range(10)]
game_map[1][0] = True
game_map[1][1] = True
game_map[1][2] = True
game_map[1][3] = True
game_map[1][4] = True

self.generation = 0
self.map = game_map
self.population = self.count_population()

def __str__(self) -> str:
map_to_str = ""
for row in self.map:
map_to_str += "".join(["#" if cell else "." for cell in row]) + "\n"

return map_to_str

def count_population(self) -> int:
population = 0

for row in self.map:
for cell in row:
if cell:
population += 1
else:
continue

return population

def count_neighbours(self, x, y) -> int:
neighbours = 0

if len(self.map) == 1:
if len(self.map[y]) == 1:
return neighbours

try:
self.map[y][x]
except IndexError:
raise IndexError("Invalid coordinates.") from IndexError

for i in range(y - 1, y + 2):
if 0 <= i < len(self.map):
for j in range(x - 1, x + 2):
if 0 <= j < len(self.map[i]) and (i != y or j != x):
if self.map[i][j]:
neighbours += 1

return neighbours

def next_generation(self):
pass


class Map(AbstractMap):
birth_condition = (list[int],)
survival_condition = (list[int],)

def __init__(self, game_map: list[list[bool]] = None):
super().__init__(game_map)
self.birth_condition = [3]
self.survival_condition = [2, 3]

def __str__(self) -> tuple[str, int, int]:
map_str = super().__str__()

return map_str, self.population, self.generation

def next_generation(self):
new_map = [[False for _ in range(10)] for _ in range(10)]
population = 0

for y, row in enumerate(self.map):
for x, cell in enumerate(row):
neighbours = self.count_neighbours(x, y)

if cell:
if neighbours in self.survival_condition:
population += 1
new_map[y][x] = True
else:
if neighbours in self.birth_condition:
population += 1
new_map[y][x] = True

self.map = new_map
self.generation += 1
self.population = population
20 changes: 19 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
[project]
name = "gameoflifepython"
version = "0.1.0"
description = "Add your description here"
description = "Recreation of Conways Game of Life in python."
requires-python = ">=3.13"
dependencies = [
"pre-commit>=4.1.0",
"pytest>=8.3.5",
"ruff>=0.9.9",
"typer>=0.15.2",
]

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
packages = ["game"]

[project.optional-dependencies]
test = ["pytest"]

[tool.pytest.ini_options]
testpaths = ["game/tests/*"]

[project.scripts]
game = "game.main:app"

[tool.ruff]
line-length = 120
preview = true
Expand Down
Loading