Exemple #1
0
def test_get_ranking_should_return_turtles_sorted_by_color_when_on_start():
    turtle1 = Turtle('GREEN')
    turtle2 = Turtle('RED')
    board = Board([turtle1, turtle2])

    actual = board.get_ranking()

    assert actual == [turtle2, turtle1]
Exemple #2
0
def test_get_ranking_returns_turtles_sorted_by_position_when_no_stacks():
    turtle1 = Turtle('GREEN')
    turtle2 = Turtle('RED')
    board = Board([turtle1, turtle2])

    board.move(turtle2, 1)
    actual = board.get_ranking()

    assert actual == [turtle2, turtle1]
Exemple #3
0
def test_get_ranking_returns_turtles_sorted_by_pos_when_there_are_stacks():
    turtle1 = Turtle('RED')
    turtle2 = Turtle('GREEN')
    turtle3 = Turtle('YELLOW')
    board = Board([turtle1, turtle2, turtle3])

    board.move(turtle1, 3)
    board.move(turtle2, 2)
    board.move(turtle3, 2)

    actual = board.get_ranking()

    assert actual == [turtle1, turtle3, turtle2]
Exemple #4
0
def test_get_ranking_returns_turtles_sorted_by_position_when_stack_on_start():
    turtles = [Turtle('RED'), Turtle('YELLOW'), Turtle('GREEN'),
               Turtle('PURPLE'), Turtle('BLUE')]

    board = Board(turtles)

    # Turtles 0 and 1 stack on start:
    board.move(turtles[0], 1)
    board.move(turtles[1], 1)
    board.move(turtles[0], -1)

    # Turtles 2 and 3 stack on start:
    board.move(turtles[2], 1)
    board.move(turtles[3], 1)
    board.move(turtles[2], -1)

    board.move(turtles[4], 9)

    actual = board.get_ranking()

    assert actual == [turtles[4], turtles[1], turtles[3], turtles[0],
                      turtles[2]]
Exemple #5
0
class Game(object):
    cards: List[Card]
    stacks: CardStacks
    turtles: List[Turtle]
    board: Board
    players: List[Player]
    active_player: Player

    def __init__(self, people: List[Person], turtles: List[Turtle],
                 cards: List[Card]):
        if len(people) < 2:
            raise ValueError(
                'There are at least 2 players required to start the game')
        if len(cards) < HAND_SIZE * len(people):
            raise ValueError(f'Not enough cards for {len(people)} players')

        self.cards = cards
        self.stacks = CardStacks(cards)
        self.turtles = turtles
        self.board = Board(turtles)
        self.players = self._init_players(people, turtles)
        self.active_player = self.players[0]

        self._ensure_player_can_move(self.active_player)

    def _init_players(self, people: List[Person], turtles: List[Turtle]):
        random.shuffle(turtles)
        return [
            self._init_player(person, turtle)
            for person, turtle in zip(people, turtles)
        ]

    def _init_player(self, person: Person, turtle: Turtle):
        return Player(person, turtle, self.stacks.get_new_cards(HAND_SIZE))

    def _ensure_player_can_move(self, player: Player):
        while not self._can_player_move(player):
            player.cards = self.stacks.get_new_cards(HAND_SIZE)

    def _can_player_move(self, player: Player):
        return any([
            self.board.is_move_with_card_possible(card)
            for card in player.cards
        ])

    def play(self, person: Person, action: Action) -> None:
        player = self._find_player(person)
        if player != self.active_player:
            raise ValueError(f"It is not {person}'s turn yet")
        if not player.has_card(action.card):
            raise ValueError("Player doesn't have given card")

        self._move_turtle(action)
        self._update_player_cards_and_stacks(player, action)

        if self._has_winner():
            return self._get_ranking()

        self._change_active_player()
        self._ensure_player_can_move(self.active_player)

    def _find_player(self, person: Person):
        for player in self.players:
            if player.person == person:
                return player
        raise ValueError(f'Person {person} does not play in this game')

    def _move_turtle(self, action: Action):
        turtle = self._find_turtle(action.get_color())
        if action.does_move_last_turtle() and not self.board.is_last(turtle):
            raise ValueError('Arrow card can move only the last turtle.' +
                             f'Turtle {turtle} is not one of the last turtles')

        self.board.move(turtle, action.get_offset())

    def _find_turtle(self, color: str):
        for turtle in self.turtles:
            if turtle.color == color:
                return turtle
        raise ValueError(f'{color} turtle doesnt exist in this game')

    def get_card(self, id: int):
        for card in self.cards:
            if card.id == id:
                return card
        raise ValueError(f'Card with id {id} does not exist in this game')

    def _update_player_cards_and_stacks(self, player: Player, action: Action):
        self.stacks.put(action.card)
        player.remove_card(action.card)
        new_card = self.stacks.get_new()
        player.add_card(new_card)

    def _has_winner(self):
        return self.board.has_anyone_finished()

    def _get_ranking(self):
        ranking = self.board.get_ranking()
        player_turtles = [player.turtle for player in self.players]
        return [
            self._find_player_by_turtle(turtle).person for turtle in ranking
            if turtle in player_turtles
        ]

    def _find_player_by_turtle(self, turtle: Turtle):
        for player in self.players:
            if player.turtle == turtle:
                return player
        raise ValueError(f'No player with given turtle: {turtle}')

    def _change_active_player(self):
        active_player_idx = self._find_player_idx(self.active_player)
        next_idx = (active_player_idx + 1) % len(self.players)
        self.active_player = self.players[next_idx]

    def _find_player_idx(self, player: Player):
        for idx, current in enumerate(self.players):
            if current == player:
                return idx
        raise ValueError(f'Player {player} does not play in this game')

    def get_person_idx(self, person: Person):
        for idx, player in enumerate(self.players):
            if player.person == person:
                return idx
        raise ValueError(f'Person {person} is not in this game')

    def get_persons_cards(self, person: Person):
        player = self._find_player(person)
        return player.cards

    # TODO: co, jeśli zostanie tylko jeden gracz?
    def remove_player(self, person: Person):
        player = self._find_player(person)
        if self.active_player == player:
            self._change_active_player()
        self.players.remove(player)