import json import ctypes # import agent as ag import project_constants as const import tile as tl from mine_models import standard_mine as sm from mine_models import time_mine as tm from mine_models import chained_mine as cm tile_asset_options = { "BLUE": const.ASSET_TILE_BLUE, "GREEN": const.ASSET_TILE_GREEN, "ORANGE": const.ASSET_TILE_ORANGE, "PURPLE": const.ASSET_TILE_PURPLE, "RED": const.ASSET_TILE_RED, "WHITE": const.ASSET_TILE_WHITE, "YELLOW": const.ASSET_TILE_YELLOW } mine_asset_options = { 'A': const.ASSET_MINE_A, 'B': const.ASSET_MINE_B, 'F': const.ASSET_MINE_F, 'K': const.ASSET_MINE_K } def calculate_screen_position(x, y): coords = ( const.V_SCREEN_PADDING + const.V_TILE_SIZE * x, const.V_SCREEN_PADDING + const.V_TILE_SIZE * y, ) return coords class Minefield: def __init__(self, json_path): self.turn = 0 self.agent = ag.Agent(const.MAP_RANDOM_10x10) # open JSON with minefield info with open(json_path) as json_data: data = json.load(json_data) # create matrix of a desired size, fill it with default tile objects self.matrix = [ [ tl.Tile((x, y)) for y in range(const.V_GRID_VER_TILES) ] for x in range(const.V_GRID_HOR_TILES) ] # iterate through tiles, set their colors and add mines for x in range(const.V_GRID_HOR_TILES): for y in range(const.V_GRID_VER_TILES): # load tile's data from json tile_data = data[f"{x},{y}"] # if there is a mine, create & assign new Mine object (type recognition included) if tile_data["mine"] is not None: mine = self._create_mine(tile_data["mine"], x, y) self.matrix[x][y].mine = mine self.matrix[x][y].color = tile_data["color"].upper() def draw(self, window): # iterate through tiles for raw in self.matrix: for tile in raw: # calculate tile position on the screen tile_screen_coords = calculate_screen_position(tile.position[0], tile.position[1]) # draw a tile window.blit(tile_asset_options.get(tile.color), tile_screen_coords) # draw a mine on top if there is one if tile.mine is not None: # TODO: blit appropriate mine type # current icons don't represent actual types, thus every mine has the same icon (temporary solution) window.blit(mine_asset_options['A'], tile_screen_coords) # draw the sapper sapper_screen_coords = calculate_screen_position(self.agent.position[0], self.agent.position[1]) window.blit(const.ASSET_SAPPER, sapper_screen_coords) # ================ # # === MOVEMENT === # # ================ # # check if sapper's destination is accessible if so then change position of the Agent # If Agent comes upon a tile with a mine his starting position shall be reestablished def is_valid_move(self, target_x: int, target_y: int): if 0 <= target_x < const.V_GRID_HOR_TILES and \ 0 <= target_y < const.V_GRID_VER_TILES: if self.matrix[target_x][target_y].mine is None: self.agent.position[0] = target_x self.agent.position[1] = target_y else: self.agent.position[0] = int(self.agent.x) self.agent.position[1] = int(self.agent.y) ctypes.windll.user32.MessageBoxW(0, "Znowu się nie udało", "GAME OVER", 1) # This part of the pop up message is just a temporary solution # distinguishes new mine's type and creates appropriate object def _create_mine(self, mine_data, x, y): mine_type = mine_data["mine_type"] # TIME MINE if mine_type == "time": timer = mine_data["timer"] mine = tm.TimeMine((x, y), int(timer)) # CHAINED MINE elif mine_type == "chained": if mine_data["predecessor"] is not None: # locate predecessor x, y = map(int, mine_data["predecessor"].split(',')) # get predecessor object and assign it to the new mine predecessor = self.matrix[x][y].mine mine = cm.ChainedMine((x, y), predecessor) else: mine = cm.ChainedMine((x, y)) # STANDARD MINE else: mine = sm.StandardMine((x, y)) return mine