Esempio n. 1
0
    def end_game(self) -> None:

        Debug.table(
            f'Table {self.id} hand {self.board.hand}: cards - {self.board}')

        if self.players.count_in_game_players() == 1:

            if self.online:
                self.network.hand_results(self.board, [])
                sleep(Delay.HandResults)

            winner = max(p for p in self.players.in_game_players())
            winner.wins += winner.in_pot

            for player in self.players.all_players():
                if player != winner:
                    if winner.in_pot >= player.in_pot:
                        winner.wins += player.in_pot
                        player.in_pot = 0
                    else:
                        Debug.error('THERE IS SOME ERROR')

            self.give_money(winner)

        else:

            self.collect_pot()

            hand_results = []

            for player in self.players.in_game_players():

                player.hand = HandStrength.max_strength(player.cards.get() +
                                                        self.board.get())

                hand_results += [(player.hand, player, str(player.hand))]

                Debug.table(
                    f'Table {self.id} hand {self.board.hand}: '
                    f'{player.get_cards()}, {player.name} has {player.hand}')

            hand_results.sort(reverse=True, key=lambda x: x[0])

            if self.online:
                self.network.hand_results(self.board, hand_results)
                sleep(Delay.HandResults)

            while self.players.count_in_game_players() > 0:

                wins_hand = max(player.hand
                                for player in self.players.in_game_players())
                players_wins = [
                    p for p in self.players.in_game_players()
                    if p.hand == wins_hand
                ]
                count_winners = len(players_wins)

                Debug.table(
                    f"Table {self.id} hand {self.board.hand}: "
                    f"{', '.join(p.name for p in players_wins)} wins with {wins_hand}"
                )

                all_inners = [p for p in self.players.all_in_players()]
                undivided_money = 0

                if all_inners:
                    all_inners_wins = sorted(
                        [p for p in all_inners if p in players_wins],
                        key=lambda x: x.in_pot)

                    for player in all_inners_wins:

                        side_pot = player.in_pot
                        Debug.table(
                            f'Table {self.id} hand {self.board.hand}: '
                            f'{player.name} opened pot with {player.in_pot}')

                        for opponent in self.players.all_players():
                            if opponent != player:
                                give_away = min(player.in_pot, opponent.in_pot)
                                Debug.table(
                                    f'Table {self.id} hand {self.board.hand}: '
                                    f'{opponent.name} moved to pot {give_away}'
                                )
                                side_pot += give_away
                                opponent.in_pot -= give_away

                        win_for_everyone = side_pot / count_winners
                        if win_for_everyone % 1 != 0:
                            undivided_money = round(
                                (win_for_everyone % 1) * count_winners)

                        win_for_everyone = int(win_for_everyone)

                        if undivided_money > 0:

                            for lucky_man in self.players.sort_by_nearest_to_button(
                                    players_wins):
                                lucky_man.wins += 1
                                undivided_money -= 1

                                if undivided_money == 0:
                                    break

                        for winner in players_wins:
                            winner.wins += win_for_everyone
                            Debug.table(
                                f'Table {self.id} hand {self.board.hand}: '
                                f'{winner.name} took {winner.wins} money from pot'
                            )

                        self.give_money(player)

                        del players_wins[players_wins.index(player)]
                        count_winners -= 1

                if count_winners > 0:

                    main_pot = sum(p.in_pot for p in players_wins)
                    Debug.table(
                        f'Table {self.id} hand {self.board.hand}: '
                        f'{" ".join(p.name for p in players_wins)} opened main pot with '
                        f'{main_pot // len(players_wins)} each and sum {main_pot}'
                    )

                    for player in self.players.all_players():
                        if player not in players_wins:
                            Debug.table(
                                f'Table {self.id} hand {self.board.hand}: '
                                f'{player.name} move {player.in_pot} in main pot'
                            )
                            main_pot += player.in_pot
                            player.in_pot = 0
                            player.in_game = False

                    win_for_everyone = main_pot / count_winners
                    if win_for_everyone % 1 != 0:
                        undivided_money = round(
                            (win_for_everyone % 1) * count_winners)

                    win_for_everyone = int(win_for_everyone)

                    if undivided_money > 0:

                        for lucky_man in self.players.sort_by_nearest_to_button(
                                players_wins):
                            lucky_man.wins += 1
                            undivided_money -= 1

                            if undivided_money == 0:
                                break

                    for winner in players_wins:
                        Debug.table(
                            f'Table {self.id} hand {self.board.hand}: '
                            f'{winner.name} took {win_for_everyone} money from main pot'
                        )
                        winner.wins += win_for_everyone
                        self.give_money(winner)

                for player in self.players.in_game_players():
                    if player.in_pot == 0:
                        player.in_game = False

        self.print_result()

        if self.pot.money != 0:
            Debug.error('ERROR IN POT')
            raise ValueError(f"POT != 0 pot = {self.pot.money}")

        self.players.remove_losers(self.game)
        self.take_cards()

        for player in self.players.all_players():
            if player.in_pot != 0:
                raise ValueError(
                    f"POT != 0 on {player.name} POT = {player.in_pot}")

            if player.in_game:
                raise ValueError(f"{player.name} IN GAME AFTER ALL")

            if player.gived != 0:
                raise ValueError(
                    f"GIVED != 0 on {player.name} gived = {player.gived}")

            if player.wins != 0:
                raise ValueError(
                    f"WINS != 0 on {player.name} wins = {player.wins}")

        self.in_game = False
Esempio n. 2
0
    def start_game(self) -> None:

        if self.wait:
            self.in_game = False
            return

        if self.players.count < 2:
            Debug.table(f'Table {self.id} has {self.players.count} player')
            self.in_game = False
            return

        for player in self.players.controlled:
            self.network.init_hand(player, self, self.game)
            player.network.place(self.game.find_place(player))

        if self.online:
            self.network.init_hand(None, self, self.game)
            sleep(Delay.InitHand)

        if not self.first_hand:
            self.players.move_button()
        else:
            self.first_hand = False

        self.players.lock.acquire()

        ante = self.blinds.ante
        sb = self.blinds.small_blind
        bb = self.blinds.big_blind

        self.collect_ante(ante)

        for step in Step:

            if step == Step.Preflop:

                self.collect_blinds(sb, bb)

                self.give_cards()

                Debug.table(self)

                to_call = bb
                self.raise_counter = 1

            else:
                self.players.to_button()
                to_call = 0
                self.raise_counter = 0

            player = self.players.next_player()
            last_seat = player.id
            min_raise = bb
            can_raise_from = to_call + min_raise

            players_not_decided = self.players.count_in_game_players()

            while True:

                if player.money > 0 and player.in_game and self.players.count_in_game_players(
                ) > 1 and not (self.players.count_in_game_players(
                ) - self.players.count_all_in_players() == 1 and max(
                        p.gived
                        for p in self.players.in_game_not_in_all_in_players())
                               >= max(p.gived
                                      for p in self.players.all_in_players())):

                    if self.online:
                        self.network.switch_decision(player)
                        sleep(Delay.SwitchDecision)

                    result = player.make_decision(
                        online=self.online,
                        step=step,
                        to_call=to_call,
                        min_raise=can_raise_from,
                        board=self.board.get(),
                        pot=self.pot.money +
                        sum(p.gived for p in self.players.all_players()),
                        bb=self.blinds.big_blind,
                    )

                    if result == Result.Raise or result == Result.Allin:
                        players_not_decided = self.players.count_in_game_players(
                        ) - 1  # without raiser
                    else:
                        players_not_decided -= 1

                    self.log(player, result)

                    if self.online:
                        self.network.made_decision(player, result)
                        sleep(Delay.MadeDecision)

                    if result == Result.Raise or result == Result.Allin:

                        raised = player.gived
                        difference = raised - to_call

                        if difference > 0:
                            last_seat = player.id
                            to_call = raised
                        else:
                            Debug.error('ERROR IN DECISIONS')
                            raise ValueError(
                                'Error in decisions: player actually did not raised'
                            )

                        if difference >= min_raise:
                            min_raise = difference

                        self.raise_counter += 1
                        can_raise_from = raised + min_raise

                player = self.players.next_player()

                if last_seat == player.id:
                    break

            if self.online:
                sleep(Delay.EndOfRound)

            if self.players.count_in_game_players() == 1:

                player_max_pot = max(p for p in self.players.in_game_players())
                second_max_pot = max(p.gived
                                     for p in self.players.all_players()
                                     if p != player_max_pot)
                difference = player_max_pot.gived - second_max_pot
                player_max_pot.gived -= difference
                player_max_pot.money += difference

                if self.online:
                    self.network.back_excess_money(player_max_pot, difference)
                    sleep(Delay.ExcessMoney)

                self.log(player_max_pot, Result.ReturnMoney, difference)

                self.collect_pot()

                self.end_game()
                return

            if self.players.count_in_game_players(
            ) - self.players.count_all_in_players() <= 1:

                if self.players.count_in_game_players(
                ) == self.players.count_all_in_players():
                    max_all_in = sorted(
                        p.gived + p.in_pot
                        for p in self.players.all_players())[-2]
                    max_in_pot = max(p.gived + p.in_pot
                                     for p in self.players.in_game_players())

                else:
                    max_all_in = max([
                        p.gived + p.in_pot
                        for p in self.players.all_in_players()
                    ] + [
                        p.gived + p.in_pot
                        for p in self.players.not_in_game_players()
                    ])
                    max_in_pot = max(p.gived + p.in_pot
                                     for p in self.players.in_game_players())

                if max_in_pot > max_all_in:
                    player_max_pot = max(
                        p for p in self.players.in_game_players()
                        if p.gived + p.in_pot == max_in_pot)
                    difference = max_in_pot - max_all_in
                    player_max_pot.gived -= difference
                    player_max_pot.money += difference

                    if self.online:
                        self.network.back_excess_money(player_max_pot,
                                                       difference)
                        sleep(Delay.ExcessMoney)

                    self.log(player, Result.ReturnMoney, difference)

                self.collect_pot()

                if self.online:
                    self.network.open_cards(self)
                    sleep(Delay.OpenCards)

                self.board.open_all_with_network(self)
                self.end_game()
                return

            if step == Step.Preflop:
                Debug.table(
                    f'Table {self.id} hand {self.board.hand}: open flop')
            elif step == Step.Flop:
                Debug.table(
                    f'Table {self.id} hand {self.board.hand}: open turn')
            elif step == Step.Turn:
                Debug.table(
                    f'Table {self.id} hand {self.board.hand}: open river')
            elif step == Step.River:
                Debug.table(
                    f'Table {self.id} hand {self.board.hand}: open cards')

                self.collect_pot()

                if self.online:
                    self.network.open_cards(self)
                    sleep(Delay.OpenCards)

                self.end_game()
                return

            self.collect_pot()

            self.board.open_with_network(self)
            Debug.table(
                f'Table {self.id} hand {self.board.hand}: board {self.board}')