Esempio n. 1
0
 def _init_log_box(self, clr):
     box_size = (self.resolution[0] / 2, self.resolution[1] / 2)
     x_pos = self.resolution[0] / 2 - box_size[0] / 2
     y_pos = self.resolution[1] / 2 - box_size[1] / 2
     log_box = RectLabel(x_pos, y_pos, box_size[0], box_size[1], clr)
     log_box.change_bg_image(WOOD)
     log_box.add_frame(FRAME)
     self.sprite_grp.add(log_box)
Esempio n. 2
0
    def _init_text_box(self, x_pos, y_pos, w, h, text, color, color_text):
        box_size = (w, h)

        user_box = RectLabel(x_pos, y_pos, box_size[0], box_size[1], color, 0,
                             Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
        user_box.change_bg_image(WOOD)
        user_box.add_frame(FRAME)
        self.sprite_grp.add(user_box)
Esempio n. 3
0
 def _init_load_menu(self, x_pos: int, y_pos: int, text: str, color: color,
                     color_text: color):
     user_box = RectLabel(
         x_pos, y_pos, 500, 500, color, 0,
         Text(pygame.font.SysFont('Agency FB', 25), text, color_text))
     user_box.change_bg_image(WOOD)
     user_box.add_frame(FRAME)
     self.sprite_grp.add(user_box)
 def _init_your_turn(self):
     rct = RectLabel(880,
                     600,
                     250,
                     50,
                     background=Color.ORANGE,
                     txt_obj=Text(pygame.font.SysFont('Agency FB', 30),
                                  "YOUR TURN", Color.GREEN2))
     rct.change_bg_image(WOOD)
     rct.add_frame(FRAME)
     return rct
Esempio n. 5
0
    def _init_text_box(self, color: Color):

        box_size = (self.txt_pos[2], self.txt_pos[3])

        user_box = RectLabel(
            self.txt_pos[0], self.txt_pos[1], box_size[0], box_size[1], color,
            0,
            Text(pygame.font.SysFont('Agency FB', 27), self.player_username,
                 color))
        user_box.change_bg_image(MEDIA_CONSTS.WOOD)
        user_box.add_frame(MEDIA_CONSTS.FRAME)
        return user_box
Esempio n. 6
0
 def _init_ip_addr(self):
     if Networking.get_instance().is_host:
         ip_addr = f"Your IP address: {Networking.get_instance().get_ip()}"
         label_width = 400
         label_left = (pygame.display.get_surface().get_size()[0] /
                       2) - (label_width / 2)
         ip_addr_label = RectLabel(label_left,
                                   20,
                                   label_width,
                                   50, (255, 255, 255),
                                   txt_obj=(Text(
                                       pygame.font.SysFont('Agency FB', 26),
                                       ip_addr, Color.GREEN2)))
         ip_addr_label.change_bg_image(MEDIA_CONSTS.WOOD)
         ip_addr_label.add_frame(MEDIA_CONSTS.FRAME)
         #ip_addr_label.set_transparent_background(True)
         self.sprite_grp.add(ip_addr_label)
Esempio n. 7
0
    def create_label(self, x_pos: int, y_pos: int, width: int, height: int, count: int):

        role: PlayerRoleEnum = self.decide_enum(count)

        accept = True

        if any([player.role == role for player in self._game.players]):
            accept = False

        if not accept:
            label =  RectLabel(x_pos - 15, y_pos - 15, width + 30, height + 30, Color.RED)
            label.change_bg_image(MEDIA_CONSTS.WOOD)
            return label
        else:
            label =  RectLabel(x_pos - 15, y_pos - 15, width + 30, height + 30, Color.GREEN)
            label.change_bg_image(MEDIA_CONSTS.WOOD)
            return label
class VehiclePlacementController(Controller):
    """Class for controlling inputs during the placing vehicles phase. Displays prompts."""

    _instance = None

    def __init__(self, current_player: PlayerModel):
        super().__init__(current_player)

        if VehiclePlacementController._instance:
            self._current_player = current_player
            # raise Exception(f"{VehiclePlacementController.__name__} is a singleton!")

        self.choose_engine_prompt = RectLabel(
            500, 30, 350, 75, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 30),
                 "Choose Engine Position", Color.GREEN2))
        self.choose_engine_prompt.change_bg_image(WOOD)
        self.choose_engine_prompt.add_frame(FRAME)
        self.choose_ambulance_prompt = RectLabel(
            500, 30, 350, 75, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 30),
                 "Choose Ambulance Position", Color.GREEN2))
        self.choose_ambulance_prompt.change_bg_image(WOOD)
        self.choose_ambulance_prompt.add_frame(FRAME)
        self.wait_prompt = RectLabel(
            500, 580, 350, 75, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 30),
                 "Host Is Placing Vehicles...", Color.GREEN2))
        self.wait_prompt.change_bg_image(WOOD)
        self.wait_prompt.add_frame(FRAME)
        self.game_board_sprite = GameBoard.instance()
        self.ambulance_placed = False
        self.engine_placed = False

        VehiclePlacementController._instance = self

    @classmethod
    def instance(cls):
        return cls._instance

    def run_checks(self, tile_model: TileModel) -> bool:
        game: GameStateModel = GameStateModel.instance()

        if game.state != GameStateEnum.PLACING_VEHICLES:
            return False

        if not Networking.get_instance().is_host:
            return False

        if tile_model.space_kind == SpaceKindEnum.INDOOR:
            return False

        return True

    def send_event_and_close_menu(self, tile_model: TileModel,
                                  menu_to_close: Interactable):
        game_board: GameBoardModel = GameStateModel.instance().game_board

        spot_list = game_board.engine_spots if self.ambulance_placed else game_board.ambulance_spots
        parking_spot = [spot for spot in spot_list if tile_model in spot]
        if not parking_spot:
            return
        parking_spot = parking_spot[0]
        vehicle = game_board.engine if self.ambulance_placed else game_board.ambulance
        event = VehiclePlacedEvent(vehicle, parking_spot)

        if Networking.get_instance().is_host:
            Networking.get_instance().send_to_all_client(event)
        else:
            Networking.get_instance().client.send(event)

        if not self.ambulance_placed:
            self.ambulance_placed = True

        elif not self.engine_placed:
            self.engine_placed = True

    def _check_highlight(self, tile_model: TileModel, vehicle_type: str):
        if vehicle_type == "AMBULANCE":
            return tile_model.space_kind == SpaceKindEnum.AMBULANCE_PARKING
        elif vehicle_type == "ENGINE":
            return tile_model.space_kind == SpaceKindEnum.ENGINE_PARKING

    def _apply_highlight(self, vehicle_type: str):
        game_state = GameStateModel.instance()

        for i in range(len(self.game_board_sprite.grid.grid)):
            for j in range(len(self.game_board_sprite.grid.grid[i])):
                tile_model = game_state.game_board.get_tile_at(j, i)
                tile_sprite = self.game_board_sprite.grid.grid[i][j]

                success = self._check_highlight(tile_model, vehicle_type)

                if success and not tile_sprite.highlight_color:
                    tile_sprite.highlight_color = Color.GREEN
                elif not success:
                    tile_sprite.highlight_color = None

    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)

        if not self.run_checks(tile_model):
            return

        self.send_event_and_close_menu(tile_model, None)

    def enable_prompts(self):
        if Networking.get_instance().is_host:
            self.game_board_sprite.top_ui.add(self.choose_engine_prompt)
            self.game_board_sprite.top_ui.add(self.choose_ambulance_prompt)
        else:
            self.game_board_sprite.top_ui.add(self.wait_prompt)

    def update(self, event_queue: EventQueue):
        game: GameStateModel = GameStateModel.instance()
        if not game.state == GameStateEnum.PLACING_VEHICLES:
            return

        if self.engine_placed:
            self.choose_engine_prompt.kill()

        if self.ambulance_placed:
            self.choose_ambulance_prompt.kill()

        ambulance: VehicleModel = GameStateModel.instance(
        ).game_board.ambulance
        engine: VehicleModel = GameStateModel.instance().game_board.engine
        if ambulance.orientation != VehicleOrientationEnum.UNSET and engine.orientation != VehicleOrientationEnum.UNSET:
            self.wait_prompt.kill()
            self.choose_ambulance_prompt.kill()
            self.choose_engine_prompt.kill()

        vehicle_type = "ENGINE" if self.ambulance_placed else "AMBULANCE"
        self._apply_highlight(vehicle_type)
class ChooseStartingPositionController(Controller):

    _instance = None

    def __init__(self, current_player: PlayerModel):
        super().__init__(current_player)

        if ChooseStartingPositionController._instance:
            self._current_player = current_player
            # raise Exception("ChooseStartingPositionController is a singleton")
        self.current_player = current_player
        self.game_board_sprite = GameBoard.instance()
        self.choose_prompt = RectLabel(
            500, 30, 350, 75, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 30),
                 "Choose Starting Position", Color.GREEN2))
        self.choose_prompt.change_bg_image(WOOD)
        self.choose_prompt.add_frame(FRAME)
        self.wait_prompt = RectLabel(
            500, 400, 300, 50, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 30), "Wait for your turn!",
                 Color.GREEN2))
        self.wait_prompt.change_bg_image(WOOD)
        self.wait_prompt.add_frame(FRAME)

        self.game_board_sprite.top_ui.add(self.choose_prompt)
        self.game_board_sprite.top_ui.add(self.wait_prompt)
        ChooseStartingPositionController._instance = self

    @classmethod
    def instance(cls):
        return cls._instance

    def _apply_hover(self):
        for i in range(len(self.game_board_sprite.grid.grid)):
            for j in range(len(self.game_board_sprite.grid.grid[i])):
                tile_model = GameStateModel.instance().game_board.get_tile_at(
                    j, i)
                tile_sprite = self.game_board_sprite.grid.grid[i][j]

                success = self.run_checks(tile_model)

                if success and not tile_sprite.highlight_color:
                    tile_sprite.highlight_color = Color.GREEN
                elif not success:
                    tile_sprite.highlight_color = None

    def send_event_and_close_menu(self, tile_model: TileModel,
                                  menu_to_close: Interactable):
        pass

    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 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 update(self, event_queue: EventQueue):
        if self.current_player == GameStateModel.instance().players_turn:
            self.wait_prompt.kill()
        if GameStateModel.instance().state == GameStateEnum.PLACING_PLAYERS:
            self._apply_hover()
Esempio n. 10
0
class PlayerBox(PlayerObserver):
    def __init__(self, text_position, background_position, username: str,
                 player: PlayerModel, color: Color):
        super().__init__()
        self._game: GameStateModel = GameStateModel.instance()
        self._assoc_player = player
        self._assoc_player.add_observer(self)
        self.player_username = username
        self.txt_pos = text_position
        self.background_position = background_position
        self.text_box = self._init_text_box(color)
        self.background = RectLabel(
            self.background_position[0],
            self.background_position[1],
            self.background_position[2],
            self.background_position[3],
        )
        self.background.change_bg_image(MEDIA_CONSTS.WOOD)
        self.background.add_frame(
            self.get_path_from_character_enum(self._assoc_player.role))
        self.background.add_frame(MEDIA_CONSTS.FRAME)

    def delete_class(self):
        self._assoc_player.remove_observer(self)

    def _init_text_box(self, color: Color):

        box_size = (self.txt_pos[2], self.txt_pos[3])

        user_box = RectLabel(
            self.txt_pos[0], self.txt_pos[1], box_size[0], box_size[1], color,
            0,
            Text(pygame.font.SysFont('Agency FB', 27), self.player_username,
                 color))
        user_box.change_bg_image(MEDIA_CONSTS.WOOD)
        user_box.add_frame(MEDIA_CONSTS.FRAME)
        return user_box

    def get_path_from_character_enum(self, enum: PlayerRoleEnum):
        if enum == PlayerRoleEnum.CAFS:
            return MEDIA_CONSTS.CAFS_FIREFIGHTER
        elif enum == PlayerRoleEnum.CAPTAIN:
            return MEDIA_CONSTS.FIRE_CAPTAIN
        elif enum == PlayerRoleEnum.GENERALIST:
            return MEDIA_CONSTS.GENERALIST
        elif enum == PlayerRoleEnum.DRIVER:
            return MEDIA_CONSTS.DRIVER_OPERATOR
        elif enum == PlayerRoleEnum.HAZMAT:
            return MEDIA_CONSTS.HAZMAT_TECHNICIAN
        elif enum == PlayerRoleEnum.IMAGING:
            return MEDIA_CONSTS.IMAGING_TECHNICIAN
        elif enum == PlayerRoleEnum.PARAMEDIC:
            return MEDIA_CONSTS.PARAMEDIC
        elif enum == PlayerRoleEnum.RESCUE:
            return MEDIA_CONSTS.RESCUE_SPECIALIST
        elif enum == PlayerRoleEnum.FAMILY:
            return MEDIA_CONSTS.FAMILY
        elif enum == PlayerRoleEnum.DOGE:
            return MEDIA_CONSTS.DOGE
        elif enum == PlayerRoleEnum.VETERAN:
            return MEDIA_CONSTS.VETERAN

    def draw(self, screen):
        self.text_box.draw(screen)
        if self.background:
            self.background.draw(screen)
            self.background.change_bg_image(MEDIA_CONSTS.WOOD)
            self.background.add_frame(
                self.get_path_from_character_enum(self._assoc_player.role))
            self.background.add_frame(MEDIA_CONSTS.FRAME)

    def player_status_changed(self, status: PlayerStatusEnum):
        pass

    def player_ap_changed(self, updated_ap: int):
        pass

    def player_special_ap_changed(self, updated_ap: int):
        pass

    def player_position_changed(self, row: int, column: int):
        pass

    def player_wins_changed(self, wins: int):
        pass

    def player_losses_changed(self, losses: int):
        pass

    def player_carry_changed(self, carry):
        pass

    def player_leading_victim_changed(self, leading_victim):
        pass

    def player_role_changed(self, role: PlayerRoleEnum):
        if self._game.state == GameStateEnum.READY_TO_JOIN:
            logger.info(f"new role: {role}")
            role_path = self.get_path_from_character_enum(role)
            logger.info(f"Role Path is: {role_path}")
            self.background = (RectLabel(self.background_position[0],
                                         self.background_position[1],
                                         self.background_position[2],
                                         self.background_position[3],
                                         role_path))
Esempio n. 11
0
class DodgePrompt(object):
    """Prompt for the player deciding whether to dodge or not."""
    def __init__(self):

        self.bg = pygame.image.load(WOOD)
        self.frame = pygame.image.load(FRAME)
        self.frame = pygame.transform.scale(self.frame, (400, 100))

        self.accept_button = RectButton(
            550 - 75, 310, 75, 50, Color.ORANGE, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Accept", Color.GREEN2))
        self.accept_button.change_bg_image(WOOD)
        self.accept_button.add_frame(FRAME)

        self.deny_button = RectButton(
            550 + 200, 310, 75, 50, Color.ORANGE, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Deny", Color.GREEN2))
        self.deny_button.change_bg_image(WOOD)
        self.deny_button.add_frame(FRAME)
        self.accept_button.on_click(self._accept_on_click)
        self.deny_button.on_click(self._deny_on_click)

        self.background = RectLabel(
            550, 300, 200, 75, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Dodge?", Color.GREEN2))
        self.background.change_bg_image(WOOD)
        self.background.add_frame(FRAME)
        self.enabled = False
        self.disable()

    def enable(self):
        self.deny_button.enable()
        self.accept_button.enable()
        self.accept_button.on_click(self._accept_on_click)
        self.deny_button.on_click(self._deny_on_click)
        self.enabled = True

    def disable(self):
        self.deny_button.disable()
        self.accept_button.disable()
        self.accept_button.on_click(None)
        self.deny_button.on_click(None)
        self.enabled = False

    def _send_reply_event(self, reply: bool):
        if Networking.get_instance().is_host:
            Networking.get_instance().send_to_all_client(
                DodgeReplyEvent(reply))
        else:
            Networking.get_instance().send_to_server(DodgeReplyEvent(reply))

    def _deny_on_click(self):
        self.disable()
        self._send_reply_event(False)

    def _accept_on_click(self):
        self.disable()
        self._send_reply_event(True)

    def update(self, event_queue: EventQueue):
        self.background.update(event_queue)
        self.accept_button.update(event_queue)
        self.deny_button.update(event_queue)

    def draw(self, screen):
        if self.enabled:
            self.background.draw(screen)
            self.accept_button.draw(screen)
            self.deny_button.draw(screen)
class FireDeckGunController(Controller):
    _instance = None

    def __init__(self, current_player: PlayerModel):
        super().__init__(current_player)

        if FireDeckGunController._instance:
            self._current_player = current_player
            # raise Exception("Victim Controller is a singleton")

        self._game: GameStateModel = GameStateModel.instance()
        self.player = current_player
        self.board: GameBoardModel = self._game.game_board
        self.engine = self.board.engine
        FireDeckGunController._instance = self
        self.label = None
        self.input1 = None
        self.input2 = None
        self.input3 = None
        self.input4 = None
        self.max_input = 0

    @classmethod
    def instance(cls):
        return cls._instance

    def process_input(self, tile_sprite: TileSprite):

        assoc_model = self.board.get_tile_at(tile_sprite.row,
                                             tile_sprite.column)
        button = None
        if self.run_checks(assoc_model):
            button = tile_sprite.fire_deck_gun_button

        if button:
            tile_sprite.fire_deck_gun_button.enable()
            if self._current_player.role == PlayerRoleEnum.DRIVER:
                button.on_click(self.driver_menu_popup, assoc_model)
            else:
                button.on_click(self.send_event_and_close_menu, assoc_model,
                                button)

        else:
            tile_sprite.fire_deck_gun_button.disable()

    def run_checks(self, tile_model: TileModel) -> bool:
        """
                Determines whether or not it is
                possible to perform this event.

                :return: True if it possible to perform
                        this event. False otherwise.
                """

        # Doge cannot fire the deck gun
        if self.player.role == PlayerRoleEnum.DOGE:
            return False

        if not self.player == GameStateModel.instance().players_turn:
            return False

        ap_deduct = 2 if self.player.role == PlayerRoleEnum.DRIVER else 4

        if not TurnEvent.has_required_AP(self.player.ap, ap_deduct):
            return False

        # If the player is not located in the
        # same space as the engine, they cannot
        # fire the deck gun.
        engine_orient = self.engine.orientation
        if engine_orient == VehicleOrientationEnum.HORIZONTAL:
            on_first_spot = self.player.row == self.engine.row and self.player.column == self.engine.column
            on_second_spot = self.player.row == self.engine.row and self.player.column == self.engine.column + 1
            if not on_first_spot and not on_second_spot:
                return False

        elif engine_orient == VehicleOrientationEnum.VERTICAL:
            on_first_spot = self.player.row == self.engine.row and self.player.column == self.engine.column
            on_second_spot = self.player.row == self.engine.row + 1 and self.player.column == self.engine.column
            if not on_first_spot and not on_second_spot:
                return False

        engine_quadrant = self._determine_quadrant(self.engine.row,
                                                   self.engine.column)
        tile_input_quadrant = self._determine_quadrant(tile_model.row,
                                                       tile_model.column)
        # If there are players present in the
        # quadrant, the deck gun cannot be fired.
        # tile input gotta be on quadrant adjacent to engine
        if self._are_players_in_quadrant(
                engine_quadrant) or tile_input_quadrant != engine_quadrant:
            return False

        return True

    @staticmethod
    def _determine_quadrant(row, column) -> QuadrantEnum:
        """
        Determines the quadrant to which
        the row and column belong to.

        :param row:
        :param column:
        :return: Quadrant in which the row and
                column are located.
        """
        if row < 4 and column < 5:
            return QuadrantEnum.TOP_LEFT
        elif row < 4 and column >= 5:
            return QuadrantEnum.TOP_RIGHT
        elif row >= 4 and column < 5:
            return QuadrantEnum.BOTTOM_LEFT
        else:
            return QuadrantEnum.BOTTOM_RIGHT

    @staticmethod
    def _determine_quadrant_player(row, column) -> QuadrantEnum:
        """
        Determines the quadrant to which
        the row and column belong to.

        :param row:
        :param column:
        :return: Quadrant in which the row and
                column are located.
        """
        if 4 > row > 0 and 5 > column > 0:
            return QuadrantEnum.TOP_LEFT
        elif 4 > row > 0 and 5 <= column < 9:
            return QuadrantEnum.TOP_RIGHT
        elif 4 <= row < 7 and 5 > column > 0:
            return QuadrantEnum.BOTTOM_LEFT
        elif 4 <= row < 7 and 5 <= column < 9:
            return QuadrantEnum.BOTTOM_RIGHT

    def _are_players_in_quadrant(self, quadrant: QuadrantEnum) -> bool:
        """
        Determines whether there are any players
        in the given quadrant.

        :param quadrant: Quadrant that we are interested in.
        :return: True if there are players in the quadrant,
                False otherwise.
        """

        for player in self._game.players:
            logger.info(
                f"Player assoc_quadrant: {self._determine_quadrant_player(player.row, player.column)}"
            )
            logger.info(
                f"Player row: {player.row}, Player column: {player.column}")
            logger.info(f"Quadrant to compare: {quadrant}")
            if quadrant == self._determine_quadrant_player(
                    player.row, player.column):
                return True

        return False

    def send_event_and_close_menu(self,
                                  tile_model: TileModel,
                                  menu_to_close: Interactable,
                                  row: int = -1,
                                  column: int = -1):

        event = FireDeckGunEvent(row=row, column=column)

        if not self.run_checks(tile_model):
            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)

        if menu_to_close:
            menu_to_close.disable()

    def _set_target_tile(self, row: int = -1, column: int = -1):
        """
        Set the tile which will be the
        target for the firing of the deck gun.

        :return:
        """
        engine_quadrant = self._determine_quadrant(self.engine.row,
                                                   self.engine.column)
        if row == -1:
            target_row = GameStateModel.instance().roll_red_dice()
        else:
            target_row = row

        if column == -1:
            target_column = GameStateModel.instance().roll_black_dice()
        else:
            target_column = column

        target_quadrant = self._determine_quadrant(target_row, target_column)
        # If the roll gives a tile in the engine's
        # quadrant, that will become the target tile.
        if target_quadrant == engine_quadrant:
            target_tile = GameStateModel.instance().game_board.get_tile_at(
                target_row, target_column)
            return target_tile

        else:
            # Flipping the red dice involves
            # subtracting the roll value from 7.
            flipped_row = 7 - target_row
            # Try out the following combinations
            # and see if any of them are in the
            # engine's quadrant:
            # 1. flipping the row, same column
            # 2. same row, flipping the column
            # 3. flipping the row, flipping the column
            new_target_quadrant = self._determine_quadrant(
                flipped_row, target_column)
            if new_target_quadrant == engine_quadrant:
                target_tile = GameStateModel.instance().game_board.get_tile_at(
                    flipped_row, target_column)
                return target_tile

            flipped_column = GameStateModel.instance(
            ).determine_black_dice_opposite_face(target_column)
            new_target_quadrant = self._determine_quadrant(
                target_row, flipped_column)
            if new_target_quadrant == engine_quadrant:
                target_tile = GameStateModel.instance().game_board.get_tile_at(
                    target_row, flipped_column)
                return target_tile

            new_target_quadrant = self._determine_quadrant(
                flipped_row, flipped_column)

            if new_target_quadrant == engine_quadrant:
                target_tile = GameStateModel.instance().game_board.get_tile_at(
                    flipped_row, flipped_column)
                return target_tile

        # $$$$$$$$$$$$$$$$$
        # Shouldn't be able to reach this point!!
        # One of the cases above should have worked.
        # $$$$$$$$$$$$$$$$$
        logger.error("Possible issue with dice flipping! Stop!!")
        raise FlippingDiceProblemException()

    def driver_menu_popup(self, tile_model: TileModel):
        decision: int = 0
        targetTile: TileModel = self._set_target_tile()
        red_dice = targetTile.row
        black_dice = targetTile.column
        boardSprite: GameBoard = GameBoard.instance().top_ui
        self.label = RectLabel(
            200, 400, 600, 200, Color.BLACK, 0,
            Text(pygame.font.SysFont('Agency FB', 25),
                 f"Roll: {red_dice}, {black_dice}", Color.GREEN2))
        self.label.change_bg_image(WOOD)
        self.label.add_frame(FRAME)

        self.input1 = RectButton(
            200, 350, 150, 50, Color.BLACK, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Accept Roll",
                 Color.GREEN2))
        self.input1.change_bg_image(WOOD)
        self.input1.add_frame(FRAME)
        self.input2 = RectButton(
            350, 350, 150, 50, Color.BLACK, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Black Dice",
                 Color.GREEN2))
        self.input2.change_bg_image(WOOD)
        self.input2.add_frame(FRAME)
        self.input3 = RectButton(
            500, 350, 150, 50, Color.BLACK, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Red Dice",
                 Color.GREEN2))
        self.input3.change_bg_image(WOOD)
        self.input3.add_frame(FRAME)
        self.input4 = RectButton(
            650, 350, 150, 50, Color.BLACK, 0,
            Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Both Die",
                 Color.GREEN2))
        self.input4.change_bg_image(WOOD)
        self.input4.add_frame(FRAME)

        self.input1.on_click(self.input1_process, tile_model, red_dice,
                             black_dice)
        self.input2.on_click(self.input2_process, tile_model, red_dice,
                             black_dice)
        self.input3.on_click(self.input3_process, tile_model, red_dice,
                             black_dice)
        self.input4.on_click(self.input4_process, tile_model, red_dice,
                             black_dice)
        boardSprite.add(self.label)
        boardSprite.add(self.input1)
        boardSprite.add(self.input2)
        boardSprite.add(self.input3)
        boardSprite.add(self.input4)

    def input1_process(self, tile: TileModel, red_dice: int, black_dice: int):
        self.kill_all()
        self.max_input = 0
        self.send_event_and_close_menu(tile, self.input1, red_dice, black_dice)

    def input2_process(self, tile: TileModel, red_dice: int, black_dice: int):
        self.max_input += 1
        board_sprite: GameBoard = GameBoard.instance().top_ui
        self.kill_all()
        new_tile: TileModel = self._set_target_tile(red_dice)
        if self.max_input == 2:
            self.max_input = 0
            self.send_event_and_close_menu(tile, self.input1, new_tile.row,
                                           new_tile.column)
        else:

            black_dice = new_tile.column
            self.label = RectLabel(
                200, 400, 600, 200, Color.BLACK, 0,
                Text(pygame.font.SysFont('Agency FB', 25),
                     f"Roll: {red_dice}, {black_dice}", Color.GREEN2))
            self.label.change_bg_image(WOOD)
            self.label.add_frame(FRAME)
            self.input1 = RectButton(
                200, 350, 150, 50, Color.BLACK, 0,
                Text(pygame.font.SysFont('Agency FB', 25), "Accept Roll",
                     Color.GREEN2))
            self.input1.change_bg_image(WOOD)
            self.input1.add_frame(FRAME)
            self.input3 = RectButton(
                350, 350, 150, 50, Color.BLACK, 0,
                Text(pygame.font.SysFont('Agency FB', 25), "Re-Roll Red Dice",
                     Color.GREEN2))
            self.input3.change_bg_image(WOOD)
            self.input3.add_frame(FRAME)

            self.input1.on_click(self.input1_process, tile, red_dice,
                                 new_tile.column)
            self.input3.on_click(self.input3_process, tile, red_dice,
                                 new_tile.column)
            board_sprite.add(self.label)
            board_sprite.add(self.input1)
            board_sprite.add(self.input3)

    def input3_process(self, tile: TileModel, red_dice: int, black_dice: int):
        self.max_input += 1
        board_sprite: GameBoard = GameBoard.instance().top_ui
        self.kill_all()
        new_tile: TileModel = self._set_target_tile(-1, black_dice)

        if self.max_input == 2:
            self.max_input = 0
            self.send_event_and_close_menu(tile, self.input1, new_tile.row,
                                           new_tile.column)

        else:
            red_dice = new_tile.row
            self.label = RectLabel(
                200, 400, 600, 200, Color.BLACK, 0,
                Text(pygame.font.SysFont('Agency FB', 25),
                     f"Roll: {red_dice}, {black_dice}", Color.GREEN2))
            self.label.change_bg_image(WOOD)
            self.label.add_frame(FRAME)
            self.input1 = RectButton(
                200, 350, 150, 50, Color.BLACK, 0,
                Text(pygame.font.SysFont('Agency FB', 25), "Accept Roll",
                     Color.GREEN2))
            self.input1.change_bg_image(WOOD)
            self.input1.add_frame(FRAME)
            self.input2 = RectButton(
                350, 350, 150, 50, Color.BLACK, 0,
                Text(pygame.font.SysFont('Agency FB', 25),
                     "Re-Roll Black Dice", Color.GREEN2))
            self.input2.change_bg_image(WOOD)
            self.input2.add_frame(FRAME)

            self.input1.on_click(self.input1_process, tile, new_tile.row,
                                 black_dice)
            self.input2.on_click(self.input2_process, tile, new_tile.row,
                                 black_dice)
            board_sprite.add(self.label)
            board_sprite.add(self.input1)
            board_sprite.add(self.input2)

    def input4_process(self, tile: TileModel, red_dice: int, black_dice: int):
        self.kill_all()
        new_tile: TileModel = self._set_target_tile()
        self.send_event_and_close_menu(tile, self.input1, new_tile.row,
                                       new_tile.column)

    def kill_all(self):
        self.input1.kill()
        self.input2.kill()
        self.input3.kill()
        self.input4.kill()
        self.label.kill()
class CommandNotification(object):
    """Displays the command status to the targeted players (source and target)"""
    def __init__(self):
        self._source = None
        self._target = None
        self._notification = RectLabel(
            500, 0, 350, 75, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 30), f"Commanding: None",
                 Color.GREEN2))
        self._notification.change_bg_image(WOOD)
        self._notification.add_frame(FRAME)
        self._wait_command = RectLabel(
            500, 400, 300, 50, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 30), f"Commanded by: None",
                 Color.GREEN2))
        self._wait_command.change_bg_image(WOOD)
        self._wait_command.add_frame(FRAME)
        self._init_end_command_btn()
        self._is_source = False
        self._is_target = False

    def _init_end_command_btn(self):
        # End command button
        self._end_command_btn = RectButton(
            1080,
            450,
            200,
            50,
            background=Color.ORANGE,
            txt_obj=Text(pygame.font.SysFont('Agency FB', 23), "END COMMAND",
                         Color.GREEN2))
        self._end_command_btn.change_bg_image(WOOD)
        self._end_command_btn.add_frame(FRAME)
        self._end_command_btn.on_click(self.end_command)

    def end_command(self):
        event = StopCommandEvent(self._source)

        if Networking.get_instance().is_host:
            Networking.get_instance().send_to_all_client(event)
        else:
            Networking.get_instance().send_to_server(event)

    @property
    def command(self) -> Tuple[PlayerModel, PlayerModel]:
        return self._source, self._target

    @command.setter
    def command(self, command: Tuple[PlayerModel, PlayerModel]):
        (self._source, self._target) = command
        source_msg = "Commanding: None"
        target_msg = "Commanded by: None"
        if self._target:
            source_msg = f"Commanding: {self._target.nickname}"
        if self._source:
            target_msg = f"Commanded by: {self._source.nickname}"

        self._notification.change_text(
            Text(pygame.font.SysFont('Agency FB', 30), source_msg,
                 Color.ORANGE))
        self._notification.change_bg_image(WOOD)
        self._notification.add_frame(FRAME)
        self._wait_command.change_text(
            Text(pygame.font.SysFont('Agency FB', 30), target_msg,
                 Color.ORANGE))
        self._wait_command.change_bg_image(WOOD)
        self._wait_command.add_frame(FRAME)

    @property
    def is_source(self) -> bool:
        return self._is_source

    @is_source.setter
    def is_source(self, source: bool):
        self._is_source = source

    @property
    def is_target(self) -> bool:
        return self._is_target

    @is_target.setter
    def is_target(self, target: bool):
        self._is_target = target

    def update(self, event_queue: EventQueue):
        if self.is_source:
            self._notification.update(event_queue)
            self._end_command_btn.update(event_queue)
        elif self.is_target:
            self._wait_command.update(event_queue)

    def draw(self, screen):
        if self.is_source:
            self._notification.draw(screen)
            self._end_command_btn.draw(screen)
        elif self.is_target:
            self._wait_command.draw(screen)
Esempio n. 14
0
class PermissionPrompt(object):
    """Prompt for the player deciding whether to allow to be commanded or not."""
    def __init__(self):
        self.accept_button = RectButton(
            500 - 75, 310, 75, 50, Color.ORANGE, 0,
            Text(pygame.font.SysFont('Agency FB', 20), "Accept", Color.GREEN2))
        self.accept_button.change_bg_image(WOOD)
        self.accept_button.add_frame(FRAME)
        self.deny_button = RectButton(
            500 + 300, 310, 75, 50, Color.ORANGE, 0,
            Text(pygame.font.SysFont('Agency FB', 20), "Deny", Color.GREEN2))
        self.deny_button.change_bg_image(WOOD)
        self.deny_button.add_frame(FRAME)
        self.accept_button.on_click(self._accept_on_click)
        self.deny_button.on_click(self._deny_on_click)

        self._source = None
        self._target = None
        self.background = RectLabel(
            500, 300, 300, 75, Color.GREY, 0,
            Text(pygame.font.SysFont('Agency FB', 20), "Permission?",
                 Color.GREEN2))
        self.background.change_bg_image(WOOD)
        self.background.add_frame(FRAME)

        self._enabled = False

    def _send_reply_event(self, reply: bool):
        if Networking.get_instance().is_host:
            Networking.get_instance().send_to_all_client(
                PermissionReplyEvent(reply, self._source, self._target))
        else:
            Networking.get_instance().send_to_server(
                PermissionReplyEvent(reply, self._source, self._target))

    def _deny_on_click(self):
        self.enabled = False
        self._send_reply_event(False)

    def _accept_on_click(self):
        self.enabled = False
        self._send_reply_event(True)

    def update(self, event_queue: EventQueue):
        if self._enabled:
            self.background.update(event_queue)
            self.accept_button.update(event_queue)
            self.deny_button.update(event_queue)

    def draw(self, screen):
        if self._enabled:
            self.background.draw(screen)
            self.accept_button.draw(screen)
            self.deny_button.draw(screen)

    @property
    def enabled(self) -> bool:
        return self._enabled

    @enabled.setter
    def enabled(self, enable: bool):
        self._enabled = enable

    @property
    def command(self) -> Tuple[PlayerModel, PlayerModel]:
        return self._source, self._target

    @command.setter
    def command(self, command: Tuple[PlayerModel, PlayerModel]):
        self._source = command[0]
        self._target = command[1]
        self.background.change_text(
            Text(pygame.font.SysFont('Agency FB', 20),
                 f"{self._source.nickname} wants to command you",
                 Color.GREEN2))
        self.background.change_bg_image(WOOD)
        self.background.add_frame(FRAME)