def _is_path_clear(self, tile_model: TileModel, dirn: str) -> bool: """ Determines if there is an obstacle blocking the way from the tile in the direction 'dirn'. :param tile_model: tile the player is moving from :param dirn: direction from tile in which moving :return: True if the path from the first tile to the second is clear, False otherwise. """ has_obstacle = tile_model.has_obstacle_in_direction(dirn) obstacle = tile_model.get_obstacle_in_direction(dirn) is_open_door = isinstance(obstacle, DoorModel) and obstacle.door_status == DoorStatusEnum.OPEN is_damaged_wall = isinstance(obstacle, WallModel) and obstacle.wall_status == WallStatusEnum.DAMAGED is_carrying_victim = isinstance(self.target.carrying_victim, VictimModel) # there is a destroyed door or a destroyed wall or no obstacle or an open door or a damaged wall if self.current_player.role == PlayerRoleEnum.DOGE: if not has_obstacle or is_open_door or is_damaged_wall: # The Doge is not allowed to carry a # victim through a damaged wall. if is_carrying_victim and is_damaged_wall: return False else: return True # there is a destroyed door or a destroyed wall or no obstacle or an open door else: if not has_obstacle or is_open_door: return True return False
def advance_on_tile(self, target_tile: TileModel) -> bool: """ Advances the fire on the target tile. Determines whether a flare up should occur or not after this instance of Advance Fire is done. :param target_tile: :return: boolean which tells us if a flare up will occur """ flare_up_will_occur = False if target_tile.is_hotspot: flare_up_will_occur = True tile_status = target_tile.space_status # Safe -> Smoke if tile_status == SpaceStatusEnum.SAFE: target_tile.space_status = SpaceStatusEnum.SMOKE # Smoke -> Fire elif tile_status == SpaceStatusEnum.SMOKE: target_tile.space_status = SpaceStatusEnum.FIRE # Fire -> Explosion else: self.explosion(target_tile) return flare_up_will_occur
def _perform_fire_hotspot_explosion( self, tile: TileModel, advance_event: EndTurnAdvanceFireEvent): """ Set the tile on fire, turn hotspot to true and cause an explosion on that tile. :param tile: Target tile :param advance_event: Advance event to access explosion :return: """ tile.space_status = SpaceStatusEnum.FIRE tile.is_hotspot = True advance_event.explosion(tile)
def explosion(self, origin_tile: TileModel): FileImporter.play_music(EXPLOSION_SOUND, 1) logger.info(f"Explosion occurred on {origin_tile}") game_state = GameStateModel.instance() tile_sprite = GameBoard.instance().grid.grid[origin_tile.column][ origin_tile.row] tile_sprite.explosion = True for direction, obstacle in origin_tile.adjacent_edge_objects.items(): # fire does not move to the neighbouring tile # damaging wall present along the tile if isinstance( obstacle, WallModel ) and obstacle.wall_status != WallStatusEnum.DESTROYED: obstacle.inflict_damage() game_state.damage = game_state.damage + 1 # fire does not move to the neighbouring tile # removing door that borders the tile elif isinstance(obstacle, DoorModel): obstacle.destroy_door() # fire can move to the neighbouring tile # if the neighbouring tile is on fire, a shockwave is created # else it is just set on fire. else: nb_tile = origin_tile.get_tile_in_direction(direction) if not isinstance(nb_tile, NullModel): if nb_tile.space_status == SpaceStatusEnum.FIRE: self.shockwave(nb_tile, direction) else: nb_tile.space_status = SpaceStatusEnum.FIRE
def shockwave(self, tile: TileModel, direction: str): """ Send shockwave along a direction. :param tile: the tile where the shockwave starts :param direction: direction in which shockwave continues :return: """ game_state = GameStateModel.instance() should_stop = False while not should_stop: # if there is no obstacle in the given direction - # 1. if neighbouring tile is not on fire, set it to fire # and stop the shockwave. # 2. else set the current tile to the neighbouring tile # and continue the shockwave. if not tile.has_obstacle_in_direction(direction): nb_tile: TileModel = tile.get_tile_in_direction(direction) if nb_tile.space_status != SpaceStatusEnum.FIRE: nb_tile.space_status = SpaceStatusEnum.FIRE should_stop = True else: tile = nb_tile # if there is an obstacle in the given direction else: # 1. if obstacle is a wall, inflict damage on it, increment # game state damage and stop the shockwave. # 2. if obstacle is an open door, continue the shockwave # and destroy the door. # 3. if obstacle is a closed door, stop the shockwave # and destroy the door. obstacle = tile.get_obstacle_in_direction(direction) if isinstance(obstacle, WallModel): obstacle.inflict_damage() game_state.damage = game_state.damage + 1 should_stop = True elif isinstance(obstacle, DoorModel): if obstacle.door_status == DoorStatusEnum.CLOSED: should_stop = True obstacle.destroy_door() else: pass
def _init_all_tiles_board(self, amb_engine_parking_fname: str, outside_doors_fname: str, inside_walls_doors_fname: str) -> List[List[TileModel]]: """ Create all tiles for the board and set their adjacencies. :param amb_engine_parking_fname: Name of file that contains details about the ambulance and engine parking spaces :param outside_doors_fname: Name of file that contains details about the outside doors :param inside_walls_doors_fname: Name of file that contains details about the inside walls/doors :return: A list of list of tile models that will act as the board """ tiles = [] for i in range(self._dimensions[0]): tiles.append([]) for j in range(self._dimensions[1]): tile_kind = self._determine_tile_kind(i, j) tile = TileModel(i, j, tile_kind) tiles[i].append(tile) # setting tile adjacencies self.set_adjacencies(tiles) # setting the top and bottom walls on the outside of the house for top, bottom in [(0, 1), (6, 7)]: for i in range(1, 9): wall = WallModel(top, i, "South") tiles[top][i].set_adjacent_edge_obstacle("South", wall) tiles[bottom][i].set_adjacent_edge_obstacle("North", wall) # setting the left and right walls on the outside of the house for left, right in [(0, 1), (8, 9)]: for i in range(1, 7): wall = WallModel(i, left, "East") tiles[i][left].set_adjacent_edge_obstacle("East", wall) tiles[i][right].set_adjacent_edge_obstacle("West", wall) # setting the ambulance and engine parking spaces self.set_parking_spaces(amb_engine_parking_fname, tiles) # setting the doors present on the outside of the house EXPLICITLY self.set_outside_doors(outside_doors_fname, tiles) # setting the walls and doors present inside the house self.set_inside_walls_doors(inside_walls_doors_fname, tiles) # setting the arrow directions given for the inside tiles self.set_all_tiles_arrows(MEDIA_CONSTS.TILE_ARROW_DIRECTIONS, tiles) return tiles
def run_checks_pickup(self, tile_model: TileModel): # Doge cannot pick up a hazmat if not self._current_player == GameStateModel.instance().players_turn: return False if self._current_player.role == PlayerRoleEnum.DOGE: return False if isinstance(self._current_player.carrying_victim, VictimModel) or isinstance( self._current_player.carrying_hazmat, HazmatModel): return False if self._current_player.column == tile_model.column and self._current_player.row == tile_model.row: if tile_model.has_hazmat(): return True return False
def _determine_movement_direction(self, src_tile: TileModel, dest_tile: TileModel) -> str: """ Determine the direction from the source tile to the destination tile :param src_tile: :param dest_tile: :return: string representation of movement direction """ directions = ["North", "East", "West", "South"] for dirn in directions: nb_src_tile: TileModel = src_tile.get_tile_in_direction(dirn) if isinstance(nb_src_tile, NullModel): continue if nb_src_tile.row == dest_tile.row and nb_src_tile.column == dest_tile.column: return dirn
def set_single_tile_adjacencies(self, tile: TileModel): # set north tile if tile.row == 0: tile.set_adjacent_tile("North", NullModel()) else: tile.set_adjacent_tile("North", self.get_tile_at(tile.row - 1, tile.column)) # set east tile if tile.column == BOARD_DIMENSIONS[1] - 1: tile.set_adjacent_tile("East", NullModel()) else: tile.set_adjacent_tile("East", self.get_tile_at(tile.row, tile.column + 1)) # set west tile if tile.column == 0: tile.set_adjacent_tile("West", NullModel()) else: tile.set_adjacent_tile("West", self.get_tile_at(tile.row, tile.column - 1)) # set south tile if tile.row == BOARD_DIMENSIONS[0] - 1: tile.set_adjacent_tile("South", NullModel()) else: tile.set_adjacent_tile("South", self.get_tile_at(tile.row + 1, tile.column))
def _deserialize_tile(payload: Dict) -> TileModel: tile: TileModel = TileModel(payload['_row'], payload['_column'], payload['_space_kind']) return tile