def send_event_and_close_menu(self, tile_model: TileModel, menu_to_close: Interactable): parking_type = tile_model.space_kind vehicle_type = "AMBULANCE" if parking_type == SpaceKindEnum.AMBULANCE_PARKING else "ENGINE" event = None if self._run_checks_dismount_vehicle(tile_model, vehicle_type): event = DismountVehicleEvent(vehicle_type, player=self._current_player) elif self._run_checks_ride_vehicle(tile_model, vehicle_type): event = RideVehicleEvent(vehicle_type, player=self._current_player) elif self._run_checks_drive_ambulance(tile_model): second_tile = GameStateModel.instance().game_board.get_other_parking_tile(tile_model) event = DriveVehicleEvent("AMBULANCE", (tile_model, second_tile)) elif self._run_checks_drive_engine(tile_model): second_tile = GameStateModel.instance().game_board.get_other_parking_tile(tile_model) event = DriveVehicleEvent("ENGINE", (tile_model, second_tile)) else: menu_to_close.disable() return if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client(event) else: Networking.get_instance().client.send(event) menu_to_close.disable()
def _init_all(self, reuse=False): self._init_background() self._init_ip_addr() self.chat_box = ChatBox(self._current_player) if not reuse: self._init_btn_back(20, 20, "Exit", MEDIA_CONSTS.WOOD, Color.GREEN2) if self._current_player.ip == GameStateModel.instance().host.ip: self._init_start_game_button() else: # Ready button is grey at first self._init_ready(1050, 575, "Not Ready", Color.GREY, Color.BLACK) if not self._game.rules == GameKindEnum.FAMILY: self._init_selec_char(1050, 475, "Select Character", Color.STANDARDBTN, Color.GREEN2) else: if not self._game.rules == GameKindEnum.FAMILY: self.sprite_grp.add(self.buttonSelChar) if self._current_player.ip == GameStateModel.instance().host.ip: self.sprite_grp.add(self.start_button) else: self.sprite_grp.add(self.buttonReady, self.buttonBack) self.sprite_grp.add(self.buttonBack) self._init_sprites()
def _init_sprites(self): text_pos = [(565, 625, 200, 32), (100, 364, 150, 32), (400, 289, 150, 32), (780, 289, 150, 32), (1080, 364, 150, 32)] background_pos = [(565, 375, 200, 250), (100, 164, 150, 200), (400, 89, 150, 200), (780, 89, 150, 200), (1080, 164, 150, 200)] self.player_boxes = [] current_player = [ player for player in GameStateModel.instance().players if player.ip == self._current_player.ip ][0] self.player_boxes.append( PlayerBox(text_pos[0], background_pos[0], self._current_player.nickname, current_player, current_player.color)) players = [ x for x in GameStateModel.instance().players if x.ip != self._current_player.ip ] i = 1 for player in players: self.player_boxes.append( PlayerBox(text_pos[i], background_pos[i], player.nickname, player, player.color)) # self.sprite_grp.add(self._init_text_box(text_pos[i], player.nickname, player.color)) # self.sprite_grp.add(self._init_background_player(background_pos[i])) i += 1
def __init__(self, x: int, y: int, current_damage: int, victims_dead: int, victims_saved: int): super().__init__() GameStateModel.instance().add_observer(self) self.image = pygame.Surface([880, 50]) self.font = pygame.font.SysFont('Agency FB', 35) self.bg = pygame.image.load(WOOD) self.bg = pygame.transform.scale(self.bg, (880, 50)) self.frame = pygame.image.load(FRAME) self.frame = pygame.transform.scale(self.frame, (880, 50)) self.damage_str = f"Damage: {current_damage}/24" self.victims_dead_str = f"Victims Lost: {victims_dead}/4" self.victims_saved_str = f"Victims Saved: {victims_saved}/7" self.damage = self.font.render(self.damage_str, True, Color.GREEN2) self.victims_dead = self.font.render(self.victims_dead_str, True, Color.GREEN2) self.victims_saved = self.font.render(self.victims_saved_str, True, Color.GREEN2) self.rect = self.image.get_rect() self.rect.move_ip(x, y) self.damage_rect = self.damage.get_rect() self.damage_rect.move_ip(55, 5) self.victims_dead_rect = self.victims_dead.get_rect() self.victims_dead_rect.move_ip(630, 5) self.victims_saved_rect = self.victims_saved.get_rect() self.victims_saved_rect.move_ip(330, 5)
def __init__(self, current_player: PlayerModel): super().__init__(current_player) if TileInputController._instance: self._current_player = current_player self.game_board_sprite = GameBoard.instance() ExtinguishController(current_player) MoveController(current_player) ChooseStartingPositionController(current_player) VictimController(current_player) if GameStateModel.instance().rules == GameKindEnum.EXPERIENCED: VehiclePlacementController(current_player) DriveVehiclesController(current_player) IdentifyController(current_player) HazmatController(current_player) CommandPlayerController(current_player) ResuscitateController(current_player) CrewChangeController(current_player) FireDeckGunController(current_player) GameStateModel.instance().add_observer(self) # Force notify observers GameStateModel.instance().state = GameStateModel.instance().state TileInputController._instance = self
def _deserialize_game_state(payload: Dict) -> GameStateModel: """Deserialize a game state""" host: PlayerModel = JSONSerializer.deserialize(payload['_host']) num_players = payload['_max_desired_players'] rules = GameKindEnum(payload['_rules']["value"]) board_type = GameBoardTypeEnum(payload['_board_type']["value"]) difficulty_level = None if rules == GameKindEnum.EXPERIENCED: difficulty_level = DifficultyLevelEnum( payload['_difficulty_level']['value']) if not GameStateModel.instance(): game = GameStateModel(host, num_players, rules, board_type, difficulty_level) else: game = GameStateModel.instance() for player in [x for x in payload['_players'] if x['_ip'] != host.ip]: player_obj: PlayerModel = JSONSerializer.deserialize(player) if player_obj not in game.players: game.add_player(player_obj) JSONSerializer.restore_game_board(game, payload['_game_board']) # game.players_turn = payload['_players_turn_index'] game.damage = payload['_damage'] game.max_damage = payload['_max_damage'] game.victims_lost = payload['_victims_lost'] game.victims_saved = payload['_victims_saved'] return game
def __init__(self, current_player: PlayerModel, current_sprite: pygame.sprite.Sprite, sprite_group: pygame.sprite.Group): super().__init__() self.enabled = False self.running = True self.countdown_thread = None self.image = pygame.Surface([250, 50]) self.font_time = pygame.font.SysFont('Agency FB', 25) bg = pygame.image.load(WOOD) self.bg = pygame.transform.scale(bg, (250, 50)) self.msg = "YOUR TURN" frame = pygame.image.load(FRAME) self.frame = pygame.transform.scale(frame, (250, 50)) self.font_name = pygame.font.SysFont('Agency FB', 30) self.text = self.font_name.render(self.msg, True, Color.GREEN2) self.rect = self.image.get_rect() self.rect.move_ip(880, 600) self.not_your_turn = self.init_not_your_turn() self._current_player = current_player self._current_sprite = current_sprite self._active_sprites = sprite_group self._should_advance_fire = False self.btn = None self.your_turn = None switch.ABORT = False GameStateModel.instance().add_observer(self)
def execute(self): logger.info(f"Player: {self._player.nickname} caused ReadyEvent") if self._ready: GameStateModel.instance().get_player_by_ip( self._player.ip).status = PlayerStatusEnum.READY else: GameStateModel.instance().get_player_by_ip( self._player.ip).status = PlayerStatusEnum.NOT_READY
def check_drop(self, tile: TileModel): game: GameStateModel = GameStateModel.instance() player = game.players_turn if GameStateModel.instance().game_board.get_tile_at(player.row, player.column) == tile \ and isinstance(player.carrying_victim, VictimModel): return True return False
def _update_moveable_tiles(self): GameStateModel.instance().game_board.reset_tiles_visit_count() ap = self.current_player.ap # Rescue specialist's special AP are used for moving if self.current_player.role == PlayerRoleEnum.RESCUE: ap = ap + self.current_player.special_ap self.moveable_tiles = self._determine_reachable_tiles( self.target.row, self.target.column, ap) GameStateModel.instance().game_board.reset_tiles_visit_count()
def _run_checks_ride_vehicle(self, tile_model: TileModel, vehicle_type: str): # Doge cannot ride vehicle if self._current_player.role == PlayerRoleEnum.DOGE: return False ambulance = GameStateModel.instance().game_board.ambulance engine = GameStateModel.instance().game_board.engine player_is_riding = self._current_player in ambulance.passengers or self._current_player in engine.passengers return self._player_is_in_vehicle_space(vehicle_type, tile_model) and not player_is_riding
def clear(): # Reset everything if GameStateModel.instance(): GameStateModel.destroy() if GameBoard.instance(): GameBoard._instance = None # TileInputController.destroy() ChopController._instance = None DoorController._instance = None switch.ABORT = True VeteranController._instance = None
def __init__(self, current_player: PlayerModel): super().__init__(current_player) self.game: GameStateModel = GameStateModel.instance() self.board: GameBoardModel = self.game.game_board if CommandPlayerController._instance: self._current_player = current_player # raise Exception("CommandPlayerController is not a singleton!") if GameStateModel.instance().rules != GameKindEnum.EXPERIENCED: raise Exception("CommandPlayerController should not exist in Family Mode!") CommandPlayerController._instance = self
def execute(self): # Pick random location: roll dice self.game: GameStateModel = GameStateModel.instance() self.board: GameBoardModel = self.game.game_board random.seed(self.seed) logger.info("Executing Fire Placement Event") if self.game.rules == GameKindEnum.FAMILY: self.board.set_fires_family() else: self._set_fires_heroic_veteran_recruit( GameStateModel.instance().difficulty_level)
def callback_client_receive(data): """Handle receiving data from host.""" data: GameStateModel = JSONSerializer.deserialize(data) logger.debug( f"Client received {data.__class__.__name__} object from host.") # print(f"Client received {data.__class__.__name__} object from host.") if isinstance(data, GameStateModel): GameStateModel.set_game(data) return if isinstance(data, TurnEvent) or isinstance(data, ActionEvent): exec_thread = threading.Thread(target=data.execute) exec_thread.start()
def run_checks(self, tile_model: TileModel) -> bool: if GameStateModel.instance().state != GameStateEnum.PLACING_PLAYERS: return False if self.current_player != GameStateModel.instance().players_turn: return False # Check if any Players are in this tile if GameStateModel.instance().get_players_on_tile( tile_model.row, tile_model.column): return False if tile_model.space_kind == SpaceKindEnum.INDOOR: return False return True
def load_game(self, save): """Instantiate a new family game and move to the lobby scene.""" data = save # Restore game metadata game: GameStateModel = JSONSerializer.deserialize(data) game.host = self._current_player game.players = [self._current_player] game._players_turn_index = 0 # Restore GameBoard GameStateModel.set_game(game) game.game_board.is_loaded = True Networking.get_instance().create_host() EventQueue.post(CustomEvent(ChangeSceneEnum.LOBBYSCENE))
def __init__(self, seed: int = 0): super().__init__() game_state: GameStateModel = GameStateModel.instance() if seed == 0: self.seed = random.randint(1, 6969) else: self.seed = seed
def execute(self): logger.info( f"Executing MoveEvent from ({self.fireman.row}, " f"{self.fireman.column}) to ({self.destination.row}, {self.destination.column})" ) self.game: GameStateModel = GameStateModel.instance() # initialize the Dijkstra tiles self._init_dijkstra_tiles(self.destination) # Insert the Dijkstra tiles # into the priority queue pq = PriorityQueue() for d_tile in self.dijkstra_tiles: pq.insert(d_tile) # Get the Dijkstra tile with the least cost. # Go through the list of all the Dijkstra tiles # and if any of those are adjacent to the current # tile, attempt to relax the cost to travel between # those tiles. while not pq.is_empty(): current_d_tile = pq.peek() adjacent_tiles = current_d_tile.tile_model.adjacent_tiles for d_tile in pq.get_tiles(): for direction, tile in adjacent_tiles.items(): if isinstance(tile, NullModel): continue if d_tile.tile_model.row == tile.row and d_tile.tile_model.column == tile.column: self.relax_cost(direction, current_d_tile, d_tile) pq.poll() shortest_path = self.shortest_path() self.traverse_shortest_path(shortest_path)
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 __init__(self, door_model: DoorModel, orientation: str, tile_sprite: TileSprite, tile_model: TileModel, id: Tuple[int, int, str]): super().__init__() self.orientation = orientation self._game: GameStateModel = GameStateModel.instance() self._current_player = self._game.players_turn self._button = None self.tile_model = tile_model self.id = id self.door_model = door_model self.door_model.add_observer(self) self.open = self.door_model.door_status == DoorStatusEnum.OPEN self.closed = self.door_model.door_status == DoorStatusEnum.CLOSED self.destroyed = self.door_model.door_status == DoorStatusEnum.DESTROYED self.marker = None self.tile_sprite = tile_sprite self._prev_x = self.tile_sprite.rect.x self._prev_y = self.tile_sprite.rect.y self.button_input = RectButton( self.tile_sprite.rect.x + 100, self.tile_sprite.rect.y + 100, 100, 25, Color.WOOD, 0, Text(pygame.font.SysFont('Agency FB', 15), "Interact", Color.GREEN2)) pygame.draw.rect(self.button_input.image, Color.YELLOW, [0, 0, 100, 25], 3) self.button_input.disable() self.menu_shown = False
def update(event_queue: EventQueue): MoveController.instance().update(event_queue) ChooseStartingPositionController.instance().update(event_queue) if GameStateModel.instance().rules == GameKindEnum.EXPERIENCED: VehiclePlacementController.instance().update(event_queue)
def process_input(self, tile_sprite: TileSprite): game_state: GameStateModel = GameStateModel.instance() tile_model = game_state.game_board.get_tile_at(tile_sprite.row, tile_sprite.column) parking_type = tile_model.space_kind vehicle_type = "AMBULANCE" if parking_type == SpaceKindEnum.AMBULANCE_PARKING else "ENGINE" button = None if self._run_checks_dismount_vehicle(tile_model, vehicle_type): button = tile_sprite.dismount_vehicle_button tile_sprite.ride_vehicle_button.disable() elif self._run_checks_ride_vehicle(tile_model, vehicle_type): button = tile_sprite.ride_vehicle_button tile_sprite.dismount_vehicle_button.disable() elif self._run_checks_drive_ambulance(tile_model): button = tile_sprite.drive_ambulance_here_button tile_sprite.drive_engine_here_button.disable() elif self._run_checks_drive_engine(tile_model): button = tile_sprite.drive_engine_here_button tile_sprite.drive_ambulance_here_button.disable() if button: button.enable() button.on_click(self.send_event_and_close_menu, tile_model, button) else: tile_sprite.drive_ambulance_here_button.disable() tile_sprite.drive_engine_here_button.disable() tile_sprite.dismount_vehicle_button.disable() tile_sprite.ride_vehicle_button.disable()
def process_input(self, tile_sprite: TileSprite): if not GameStateModel.instance().players_turn.has_pos: tile_model = GameStateModel.instance().game_board.get_tile_at( tile_sprite.row, tile_sprite.column) if not self.run_checks(tile_model): return event = ChooseStartingPositionEvent(tile_model.row, tile_model.column) self.choose_prompt.kill() if Networking.get_instance().is_host: Networking.get_instance().send_to_all_client(event) else: Networking.get_instance().send_to_server(event)
def __init__(self, current_player: PlayerModel): self.current_player = current_player self.game: GameStateModel = GameStateModel.instance() self.board = self.game.game_board ChopController._instance = self self.to_chop: WallSprite = None self.chop_able = False
def execute(self, *args, **kwargs): logger.info("Executing Fire Deck Gun Event") self.game: GameStateModel = GameStateModel.instance() if isinstance(self.target_tile, NullModel): self._set_target_tile() self.target_tile.space_status = SpaceStatusEnum.SAFE FileImporter.play_music(SPLASH_SOUND, 1) tile_sprite = GameBoard.instance().grid.grid[self.target_tile.column][ self.target_tile.row] tile_sprite.fire_deck_gun = True directions = ["North", "East", "West", "South"] for dirn in directions: has_obstacle = self.target_tile.has_obstacle_in_direction(dirn) obstacle = self.target_tile.get_obstacle_in_direction(dirn) # If there is no obstacle in the given direction or there is an # open door, set the status of the space in that direction to Safe. if not has_obstacle or (isinstance(obstacle, DoorModel) and obstacle.door_status == DoorStatusEnum.OPEN)\ or (isinstance(obstacle, WallModel) and obstacle.wall_status == WallStatusEnum.DESTROYED): nb_tile: TileModel = self.target_tile.get_tile_in_direction( dirn) nb_tile.space_status = SpaceStatusEnum.SAFE tile_sprite = GameBoard.instance().grid.grid[nb_tile.column][ nb_tile.row] tile_sprite.fire_deck_gun = True if self.player.role == PlayerRoleEnum.DRIVER: self.player.ap = self.player.ap - 2 else: self.player.ap = self.player.ap - 4
def execute(self, *args, **kwargs): logger.info( f"Executing VehiclePlacedEvent: {self._vehicle_type} placed.") board_model: GameBoardModel = GameStateModel.instance().game_board board_sprite: GameBoard = GameBoard.instance() tile_sprite = board_sprite.grid.grid[self._column][self._row] if self._vehicle_type == "AMBULANCE": # Set ambulance position board_model.ambulance.drive((self._row, self._column)) # Create AmbulanceSprite ambulance_sprite = AmbulanceSprite( board_model.ambulance.orientation, tile_sprite) board_model.ambulance.add_observer(ambulance_sprite) # Add to gameboard sprite group board_sprite.add(ambulance_sprite) else: # Set engine position board_model.engine.drive((self._row, self._column)) # Create EngineSprite engine_sprite = EngineSprite(board_model.engine.orientation, tile_sprite) board_model.engine.add_observer(engine_sprite) # Add to gameboard sprite group board_sprite.add(engine_sprite)
def execute(self, *args, **kwargs): game: GameStateModel = GameStateModel.instance() if self._reply: game.command = (self._source, self._target) commander: PlayerModel = [player for player in game.players if player == self._source][0] commander.special_ap = commander.special_ap - 1 logger.info(f"Player {self._source.nickname} now commands {self._target.nickname}")
def __init__(self, screen, current_player: PlayerModel): super().__init__() self._current_player = current_player self._game = GameStateModel.instance() self.player_boxes = [] if Networking.get_instance().is_host: self._current_player.color = Color.BLUE self._game.host.color = Color.BLUE self._current_player.status = PlayerStatusEnum.READY self._player_count = len(self._game.players) self.isReady = False self.resolution = (1280, 700) self.sprite_grp = pygame.sprite.Group() self.players_not_ready_prompt = None self._init_all() if self._game.rules == GameKindEnum.EXPERIENCED: self.buttonSelChar.on_click( EventQueue.post, CustomEvent(ChangeSceneEnum.CHARACTERSCENE)) if Networking.get_instance().is_host: self._current_player.status = PlayerStatusEnum.READY self.isReady = True self.start_button.on_click(self.start_game) self.start_button.disable() if self._game.rules == GameKindEnum.EXPERIENCED and self._current_player.role == PlayerRoleEnum.FAMILY: self._current_player.status = PlayerStatusEnum.NOT_READY else: self._current_player.status = PlayerStatusEnum.NOT_READY self.buttonReady.on_click(self.set_ready) self.buttonBack.on_click(self.go_back)
def __init__(self, wall_model: WallModel, orientation: str, tile_sprite: TileSprite, tile_model: TileModel, id: Tuple[int, int, str]): super().__init__() self.orientation = orientation self._game: GameStateModel = GameStateModel.instance() self._current_player = self._game.players_turn self._button = None self.tile_model = tile_model self.id = id self.wall_model = wall_model self.wall_model.add_observer(self) self.damaged = self.wall_model.wall_status == WallStatusEnum.DAMAGED self.destroyed = self.wall_model.wall_status == WallStatusEnum.DESTROYED self.tile_sprite = tile_sprite self._prev_x = self.tile_sprite.rect.x self._prev_y = self.tile_sprite.rect.y self.button_input = RectButton( self.tile_sprite.rect.x, self.tile_sprite.rect.y, 100, 25, Color.WOOD, 0, Text(pygame.font.SysFont('Agency FB', 20), "Chop Wall", Color.GREEN2)) pygame.draw.rect(self.button_input.image, Color.YELLOW, [0, 0, 100, 25], 3) self.button_input.disable() self.can_chop = False