from dataclasses import dataclass from random import randrange from typing import List import numpy as np import numpy.typing as npt # map config KNIGHTS_PER_TEAM_COUNT = 4 SAND_COUNT = 21 WATER_COUNT = 21 TREE_COUNT = 37 MONSTERS_COUNT = 2 CASTLES_COUNT = 1 ROWS = 19 COLUMNS = 24 KNIGHTS_SPAWN_WIDTH = 4 KNIGHTS_SPAWN_HEIGHT = 7 LEFT_KNIGHTS_SPAWN_FIRST_ROW = 6 LEFT_KNIGHTS_SPAWN_FIRST_COL = 0 RIGHT_KNIGHTS_SPAWN_FIRST_ROW = 6 RIGHT_KNIGHTS_SPAWN_FIRST_COL = 20 # aliases GRASS = 0 SAND = 1 WATER = 2 TREE = 3 MONSTER = 4 CASTLE = 5 KNIGHT_RED = 6 KNIGHT_BLUE = 7 @dataclass class Position: row: int col: int class Genome: grid: npt.NDArray knights_red: List[Position] knights_blue: List[Position] def __init__(self): self.grid = np.zeros((ROWS, COLUMNS), dtype=int) self.knights_red = spawn_objects_in_given_area( grid=self.grid, object_alias=KNIGHT_RED, objects_count=KNIGHTS_PER_TEAM_COUNT, spawn_position_start=Position(row=LEFT_KNIGHTS_SPAWN_FIRST_ROW, col=LEFT_KNIGHTS_SPAWN_FIRST_COL), width=KNIGHTS_SPAWN_WIDTH, height=KNIGHTS_SPAWN_HEIGHT ) self.knights_blue = spawn_objects_in_given_area( grid=self.grid, object_alias=KNIGHT_BLUE, objects_count=KNIGHTS_PER_TEAM_COUNT, spawn_position_start=Position(row=RIGHT_KNIGHTS_SPAWN_FIRST_ROW, col=RIGHT_KNIGHTS_SPAWN_FIRST_COL), width=KNIGHTS_SPAWN_WIDTH, height=KNIGHTS_SPAWN_HEIGHT ) def is_empty(grid: npt.NDArray, position: Position) -> bool: return grid[position.row, position.col] in [GRASS, SAND] def is_invalid_area(spawn_position_start, height, width) -> bool: return spawn_position_start.row + height - 1 < 0 or \ spawn_position_start.row + height - 1 >= ROWS or \ spawn_position_start.col + width - 1 < 0 or \ spawn_position_start.col + width - 1 >= COLUMNS def spawn_objects_in_given_area(grid: npt.NDArray, object_alias: KNIGHT_RED | KNIGHT_BLUE | CASTLE | MONSTER, objects_count: int = 1, spawn_position_start: Position = Position(row=0, col=0), width: int = 1, height: int = 1) -> List[Position]: if is_invalid_area(spawn_position_start, height, width): raise ValueError("Invalid spawn area") objects_remaining = int(objects_count) positions = [] while objects_remaining > 0: row = randrange(spawn_position_start.row, spawn_position_start.row + height) col = randrange(spawn_position_start.col, spawn_position_start.col + width) position = Position(row=row, col=col) if is_empty(grid=grid, position=position): grid[position.row, position.col] = object_alias positions.append(position) objects_remaining -= 1 return positions def main() -> None: example_genome = Genome() print(example_genome.knights_red) print(example_genome.knights_blue) print(example_genome.grid) if __name__ == '__main__': main()