예제 #1
0
    def test_should_go_for_defence_and_good_hand_with_drawn_tile(self):
        """
        When we have 14 tiles in hand and someone declared a riichi
        """
        table = Table()

        tiles = self._string_to_136_array(sou='2223457899', honors='666')
        table.player.init_hand(tiles)
        table.player.draw_tile(self._string_to_136_tile(man='8'))
        table.player.add_called_meld(
            self._make_meld(Meld.PON, self._string_to_136_array(sou='222')))
        table.player.add_called_meld(
            self._make_meld(Meld.PON, self._string_to_136_array(honors='666')))

        self.assertEqual(table.player.ai.defence.should_go_to_defence_mode(),
                         False)

        table.add_called_riichi(3)

        results, shanten = table.player.ai.calculate_outs(
            table.player.tiles, table.player.closed_hand,
            table.player.open_hand_34_tiles)
        selected_tile = table.player.ai.process_discard_options_and_select_tile_to_discard(
            results, shanten)

        self.assertEqual(
            table.player.ai.defence.should_go_to_defence_mode(selected_tile),
            False)
        result = table.player.discard_tile()
        self.assertEqual(self._to_string([result]), '8m')
예제 #2
0
    def test_dont_call_kan_in_defence_mode(self):
        table = Table()

        tiles = self._string_to_136_array(man='12589', sou='111459', pin='12')
        table.player.init_hand(tiles)

        table.add_called_riichi(1)

        tile = self._string_to_136_tile(sou='1')
        self.assertEqual(table.player.can_call_kan(tile, False), None)
예제 #3
0
    def test_init_round(self):
        table = Table()

        round_number = 4
        count_of_honba_sticks = 2
        count_of_riichi_sticks = 3
        dora_indicator = 126
        dealer = 3
        scores = [250, 250, 250, 250]

        table.init_round(round_number, count_of_honba_sticks,
                         count_of_riichi_sticks, dora_indicator, dealer,
                         scores)

        self.assertEqual(table.round_number, round_number)
        self.assertEqual(table.count_of_honba_sticks, count_of_honba_sticks)
        self.assertEqual(table.count_of_riichi_sticks, count_of_riichi_sticks)
        self.assertEqual(table.dora_indicators[0], dora_indicator)
        self.assertEqual(table.get_player(dealer).is_dealer, True)
        self.assertEqual(table.get_player(dealer).scores, 25000)

        dealer = 2
        table.player.in_tempai = True
        table.player.in_riichi = True
        table.init_round(round_number, count_of_honba_sticks,
                         count_of_riichi_sticks, dora_indicator, dealer,
                         scores)

        # test that we reinit round properly
        self.assertEqual(table.get_player(3).is_dealer, False)
        self.assertEqual(table.player.in_tempai, False)
        self.assertEqual(table.player.in_riichi, False)
        self.assertEqual(table.get_player(dealer).is_dealer, True)
예제 #4
0
    def test_prefer_valuable_tiles_with_almost_same_tiles_count(self):
        table = Table()
        player = table.player
        table.add_dora_indicator(self._string_to_136_tile(sou='4'))

        tiles = self._string_to_136_array(sou='1366', pin='123456', man='345')
        player.init_hand(tiles)
        player.draw_tile(self._string_to_136_tile(sou='5'))

        discarded_tile = player.discard_tile()
        self.assertEqual(self._to_string([discarded_tile]), '1s')
예제 #5
0
    def test_not_open_hand_in_defence_mode(self):
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(sou='12368', pin='2358', honors='4455')
        player.init_hand(tiles)

        table.add_called_riichi(1)

        tile = self._string_to_136_tile(honors='5')
        meld, _ = player.try_to_call_meld(tile, False)
        self.assertEqual(meld, None)
예제 #6
0
    def test_calculate_safe_tiles_to_discard(self):
        table = Table()
        table.get_main_player().init_hand([3, 5, 6, 7, 8])
        defence = Defence(table)

        table.players[1].in_riichi = True
        table.players[1].add_discarded_tile(2)

        tile = defence.calculate_safe_tile_against_riichi()

        # 0, 1, 2, 3 - is a same tile
        self.assertEqual(tile, 3)
예제 #7
0
    def test_slide_set_to_keep_dora_in_hand(self):
        table = Table()
        table.dora_indicators = [self._string_to_136_tile(pin='9')]
        player = table.player

        tiles = self._string_to_136_array(sou='123456', pin='23478', man='99')
        tile = self._string_to_136_tile(pin='1')
        player.init_hand(tiles)
        player.draw_tile(tile)

        # 2p is a dora, we had to keep it
        discarded_tile = player.discard_tile()
        self.assertEqual(self._to_string([discarded_tile]), '4p')
예제 #8
0
    def test_call_riichi_and_penchan_wait(self):
        table = Table()
        table.count_of_remaining_tiles = 60
        player = table.player
        player.scores = 25000

        tiles = self._string_to_136_array(sou='11223', pin='234567', man='66')
        tile = self._string_to_136_tile(man='9')
        player.init_hand(tiles)
        player.draw_tile(tile)
        player.discard_tile()

        self.assertEqual(player.can_call_riichi(), True)
예제 #9
0
    def test_keep_aka_dora_in_hand(self):
        table = Table()
        table.dora_indicators = [self._string_to_136_tile(pin='1')]
        player = table.player

        tiles = self._string_to_136_array(sou='12346', pin='34578', man='99')
        # five sou, we can't get it from string (because from string it is always aka dora)
        tiles += [89]
        player.init_hand(tiles)
        player.draw_tile(FIVE_RED_SOU)

        # we had to keep red five and discard just 5s
        discarded_tile = player.discard_tile()
        self.assertNotEqual(discarded_tile, FIVE_RED_SOU)
예제 #10
0
class Client(object):
    statistics = None
    id = ''
    position = 0

    def __init__(self, use_previous_ai_version=False):
        self.table = Table(use_previous_ai_version)
        self.statistics = Statistics()
        self.player = self.table.get_main_player()

        self.id = make_random_letters_and_digit_string()

    def authenticate(self):
        pass

    def start_game(self):
        pass

    def end_game(self):
        pass

    def init_hand(self, tiles):
        self.player.init_hand(tiles)

    def draw_tile(self, tile):
        self.table.count_of_remaining_tiles -= 1
        self.player.draw_tile(tile)

    def discard_tile(self):
        return self.player.discard_tile()

    def call_meld(self, meld):
        # when opponent called meld it is means
        # that he will not get the tile from the wall
        # so, we need to compensate "-" from enemy discard method
        self.table.count_of_remaining_tiles += 1

        return self.table.get_player(meld.who).add_meld(meld)

    def enemy_discard(self, player_seat, tile):
        self.table.get_player(player_seat).add_discarded_tile(tile)
        self.table.count_of_remaining_tiles -= 1

        for player in self.table.players:
            if player.in_riichi:
                player.safe_tiles.append(tile)

    def enemy_riichi(self, player_seat):
        self.table.get_player(player_seat).in_riichi = True
예제 #11
0
    def test_discard_not_effective_tiles_first(self):
        table = Table()
        player = table.player
        player.scores = 25000
        table.count_of_remaining_tiles = 100

        tiles = self._string_to_136_array(man='33',
                                          pin='12788999',
                                          sou='5',
                                          honors='23')
        player.init_hand(tiles)
        player.draw_tile(self._string_to_136_tile(honors='6'))
        tile_to_discard = player.discard_tile()

        self.assertEqual(self._to_string([tile_to_discard]), '5s')
예제 #12
0
    def test_call_riichi_with_bad_wait_against_other_player_riichi(self):
        table = Table()
        table.count_of_remaining_tiles = 60
        table.player.scores = 25000

        tiles = self._string_to_136_array(sou='11223', pin='234678', man='55')
        table.player.init_hand(tiles)
        table.player.draw_tile(self._string_to_136_tile(man='9'))

        table.add_called_riichi(3)

        discard = table.player.discard_tile()
        self.assertEqual(self._to_string([discard]), '9m')
        self.assertEqual(table.player.ai.in_defence, True)
        self.assertEqual(table.player.can_call_riichi(), False)
예제 #13
0
    def test_open_hand_and_discard_tiles_logic(self):
        table = Table()
        player = table.player

        # 2345779m1p256s44z
        tiles = self._string_to_136_array(man='22345',
                                          sou='238',
                                          pin='256',
                                          honors='44')
        player.init_hand(tiles)

        # if we are in tanyao
        # we need to discard terminals and honors
        tile = self._string_to_136_tile(sou='4')
        meld, discard_option = player.try_to_call_meld(tile, True)
        discarded_tile = table.player.discard_tile(discard_option)
        self.assertNotEqual(meld, None)
        self.assertEqual(self._to_string([discarded_tile]), '4z')

        tile = self._string_to_136_tile(pin='5')
        player.draw_tile(tile)
        tile_to_discard = player.discard_tile()

        # we are in tanyao, so we should discard honors and terminals
        self.assertEqual(self._to_string([tile_to_discard]), '4z')
예제 #14
0
    def test_wrong_shanten_improvements_detection(self):
        """
        With hand 2345s1p11z bot wanted to open set on 2s,
        so after opened set we will get 25s1p11z
        it is not correct logic, because we ruined our hand
        :return:
        """
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(sou='2345999', honors='114446')
        player.init_hand(tiles)

        meld = self._make_meld(Meld.PON, self._string_to_136_array(sou='999'))
        player.add_called_meld(meld)
        meld = self._make_meld(Meld.PON,
                               self._string_to_136_array(honors='444'))
        player.add_called_meld(meld)

        # to rebuild all caches
        player.draw_tile(self._string_to_136_tile(pin='2'))
        player.discard_tile()

        tile = self._string_to_136_tile(sou='2')
        meld, _ = table.player.try_to_call_meld(tile, True)
        self.assertEqual(meld, None)
예제 #15
0
    def test_upgrade_opened_pon_to_kan(self):
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(man='34445', sou='123456', pin='89')
        player.init_hand(tiles)
        tile = self._string_to_136_tile(man='4')
        player.draw_tile(tile)

        self.assertEqual(player.can_call_kan(tile, False), None)

        player.add_called_meld(
            self._make_meld(Meld.PON, self._string_to_136_array(man='444')))

        self.assertEqual(len(player.melds), 1)
        self.assertEqual(len(player.tiles), 14)
        self.assertEqual(player.can_call_kan(tile, False), Meld.CHANKAN)

        player.discard_tile()
        player.draw_tile(tile)
        player.add_called_meld(
            self._make_meld(Meld.CHANKAN,
                            self._string_to_136_array(man='4444')))

        self.assertEqual(len(player.melds), 1)
        self.assertEqual(player.melds[0].type, Meld.CHANKAN)
        self.assertEqual(len(player.tiles), 13)
예제 #16
0
    def test_should_activate_strategy(self):
        table = Table()
        player = table.player
        strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)

        tiles = self._string_to_136_array(sou='12355689',
                                          man='89',
                                          honors='123')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='12355689',
                                          man='89',
                                          honors='44')
        player.init_hand(tiles)
        player.dealer_seat = 1
        self.assertEqual(strategy.should_activate_strategy(), True)

        tiles = self._string_to_136_array(sou='12355689',
                                          man='89',
                                          honors='666')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), True)

        # with chitoitsu-like hand we don't need to go for yakuhai
        tiles = self._string_to_136_array(sou='1235566',
                                          man='8899',
                                          honors='66')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)
예제 #17
0
    def test_remaining_tiles_and_dora_indicators(self):
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(man='123456789', sou='167', honors='77')
        player.init_hand(tiles)

        results, shanten = player.ai.calculate_outs(tiles, tiles)
        result = [x for x in results if x.tile_to_discard == self._string_to_34_tile(sou='1')][0]
        self.assertEqual(result.tiles_count, 8)

        table.add_dora_indicator(self._string_to_136_tile(sou='8'))

        results, shanten = player.ai.calculate_outs(tiles, tiles)
        result = [x for x in results if x.tile_to_discard == self._string_to_34_tile(sou='1')][0]
        self.assertEqual(result.tiles_count, 7)
예제 #18
0
    def test_should_activate_strategy(self):
        table = Table()
        player = table.player
        strategy = HonitsuStrategy(BaseStrategy.HONITSU, player)

        tiles = self._string_to_136_array(sou='12355',
                                          man='12389',
                                          honors='123')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='12355',
                                          man='238',
                                          honors='11234')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), True)

        # with hand without pairs we not should go for honitsu,
        # because it is far away from tempai
        tiles = self._string_to_136_array(sou='12358',
                                          man='238',
                                          honors='12345')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        # with chitoitsu-like hand we don't need to go for honitsu
        tiles = self._string_to_136_array(pin='77', man='3355677899', sou='11')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)
예제 #19
0
    def test_should_activate_strategy_and_already_completed_sided_set(self):
        table = Table()
        player = table.player
        strategy = TanyaoStrategy(BaseStrategy.TANYAO, player)

        tiles = self._string_to_136_array(sou='123234', man='3459', pin='234')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='234789', man='3459', pin='234')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='234', man='1233459', pin='234')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='234', man='3457899', pin='234')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='234', man='3459', pin='122334')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='234', man='3459', pin='234789')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)

        tiles = self._string_to_136_array(sou='223344', man='3459', pin='234')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), True)
예제 #20
0
    def test_remaining_tiles_and_opened_meld(self):
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(man='123456789', sou='167', honors='77')
        player.init_hand(tiles)

        results, shanten = player.ai.calculate_outs(tiles, tiles)
        result = [x for x in results if x.tile_to_discard == self._string_to_34_tile(sou='1')][0]
        self.assertEqual(result.tiles_count, 8)

        # was discard and set was opened
        tile = self._string_to_136_tile(sou='8')
        player.table.add_discarded_tile(3, tile, False)
        meld = self._make_meld(Meld.PON, self._string_to_136_array(sou='888'))
        meld.called_tile = tile
        player.table.add_called_meld(3, meld)

        results, shanten = player.ai.calculate_outs(tiles, tiles)
        result = [x for x in results if x.tile_to_discard == self._string_to_34_tile(sou='1')][0]
        self.assertEqual(result.tiles_count, 5)

        # was discard and set was opened
        tile = self._string_to_136_tile(sou='3')
        player.table.add_discarded_tile(2, tile, False)
        meld = self._make_meld(Meld.PON, self._string_to_136_array(sou='345'))
        meld.called_tile = tile
        player.table.add_called_meld(2, meld)

        results, shanten = player.ai.calculate_outs(tiles, tiles)
        result = [x for x in results if x.tile_to_discard == self._string_to_34_tile(sou='1')][0]
        self.assertEqual(result.tiles_count, 4)
예제 #21
0
    def test_set_scores_and_uma(self):
        table = Table()
        table.init_round(0, 0, 0, 0, 0, [])
        scores = [230, 110, 55, 405]
        uma = [-17, 3, 48, -34]

        table.set_players_scores(scores, uma)

        self.assertEqual(table.get_player(0).scores, 23000)
        self.assertEqual(table.get_player(0).uma, -17)
        self.assertEqual(table.get_player(1).scores, 11000)
        self.assertEqual(table.get_player(1).uma, 3)
        self.assertEqual(table.get_player(2).scores, 5500)
        self.assertEqual(table.get_player(2).uma, 48)
        self.assertEqual(table.get_player(3).scores, 40500)
        self.assertEqual(table.get_player(3).uma, -34)
예제 #22
0
    def test_suitable_tiles(self):
        table = Table()
        player = table.player
        strategy = TanyaoStrategy(BaseStrategy.TANYAO, player)

        tile = self._string_to_136_tile(man='1')
        self.assertEqual(strategy.is_tile_suitable(tile), False)

        tile = self._string_to_136_tile(pin='1')
        self.assertEqual(strategy.is_tile_suitable(tile), False)

        tile = self._string_to_136_tile(sou='9')
        self.assertEqual(strategy.is_tile_suitable(tile), False)

        tile = self._string_to_136_tile(honors='1')
        self.assertEqual(strategy.is_tile_suitable(tile), False)

        tile = self._string_to_136_tile(honors='6')
        self.assertEqual(strategy.is_tile_suitable(tile), False)

        tile = self._string_to_136_tile(man='2')
        self.assertEqual(strategy.is_tile_suitable(tile), True)

        tile = self._string_to_136_tile(pin='5')
        self.assertEqual(strategy.is_tile_suitable(tile), True)

        tile = self._string_to_136_tile(sou='8')
        self.assertEqual(strategy.is_tile_suitable(tile), True)
예제 #23
0
    def test_discard_tile(self):
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(sou='11134567', pin='159', man='45')
        tile = self._string_to_136_tile(man='9')
        player.init_hand(tiles)
        player.draw_tile(tile)

        discarded_tile = player.discard_tile()
        self.assertEqual(self._to_string([discarded_tile]), '9m')
        self.assertEqual(player.ai.previous_shanten, 2)

        player.draw_tile(self._string_to_136_tile(pin='4'))
        discarded_tile = player.discard_tile()
        self.assertEqual(self._to_string([discarded_tile]), '1p')
        self.assertEqual(player.ai.previous_shanten, 2)

        player.draw_tile(self._string_to_136_tile(pin='3'))
        discarded_tile = player.discard_tile()
        self.assertEqual(self._to_string([discarded_tile]), '9p')
        self.assertEqual(player.ai.previous_shanten, 1)

        player.draw_tile(self._string_to_136_tile(man='4'))
        discarded_tile = player.discard_tile()
        self.assertEqual(self._to_string([discarded_tile]), '5m')
        self.assertEqual(player.ai.previous_shanten, 0)
예제 #24
0
    def test_open_hand_and_discard_tiles_logic(self):
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(sou='112235589',
                                          man='24',
                                          honors='22')
        player.init_hand(tiles)

        # we don't need to call meld even if it improves our hand,
        # because we are collecting honitsu
        tile = self._string_to_136_tile(man='1')
        meld, _ = player.try_to_call_meld(tile, False)
        self.assertEqual(meld, None)

        # any honor tile is suitable
        tile = self._string_to_136_tile(honors='2')
        meld, _ = player.try_to_call_meld(tile, False)
        self.assertNotEqual(meld, None)

        tile = self._string_to_136_tile(man='1')
        player.draw_tile(tile)
        tile_to_discard = player.discard_tile()

        # we are in honitsu mode, so we should discard man suits
        self.assertEqual(self._to_string([tile_to_discard]), '1m')
예제 #25
0
    def test_chose_strategy_and_reset_strategy(self):
        table = Table()
        player = table.player

        tiles = self._string_to_136_array(man='33355788',
                                          sou='3479',
                                          honors='3')
        player.init_hand(tiles)
        self.assertEqual(player.ai.current_strategy.type, BaseStrategy.TANYAO)

        # we draw a tile that will change our selected strategy
        tile = self._string_to_136_tile(sou='8')
        player.draw_tile(tile)
        self.assertEqual(player.ai.current_strategy, None)

        tiles = self._string_to_136_array(man='33355788',
                                          sou='3479',
                                          honors='3')
        player.init_hand(tiles)
        self.assertEqual(player.ai.current_strategy.type, BaseStrategy.TANYAO)

        # for already opened hand we don't need to give up on selected strategy
        meld = Meld()
        meld.tiles = [1, 2, 3]
        player.add_called_meld(meld)
        tile = self._string_to_136_tile(sou='8')
        player.draw_tile(tile)
        self.assertEqual(player.ai.current_strategy.type, BaseStrategy.TANYAO)
예제 #26
0
    def test_discard_tile(self):
        table = Table()
        player = Player(0, 0, table)

        tiles = self._string_to_136_array(sou='111345677', pin='15', man='56')
        tile = self._string_to_136_array(man='9')[0]
        player.init_hand(tiles)
        player.draw_tile(tile)

        discarded_tile = player.discard_tile()
        self.assertEqual(discarded_tile, 36)

        player.draw_tile(self._string_to_136_array(pin='4')[0])

        discarded_tile = player.discard_tile()
        self.assertEqual(discarded_tile, 92)

        player.draw_tile(self._string_to_136_array(pin='3')[0])

        discarded_tile = player.discard_tile()
        self.assertEqual(discarded_tile, 32)

        player.draw_tile(self._string_to_136_array(man='4')[0])

        discarded_tile = player.discard_tile()
        self.assertEqual(discarded_tile, Shanten.AGARI_STATE)
예제 #27
0
    def test_calculate_suit_tiles_value_and_dora(self):
        table = Table()
        table.dora_indicators = [self._string_to_136_tile(sou='9')]
        player = table.player

        tile = self._string_to_34_tile(sou='1')
        option = DiscardOption(player, tile, 0, [], 0)
        self.assertEqual(option.valuation, 160)

        # double dora
        table.dora_indicators = [
            self._string_to_136_tile(sou='9'),
            self._string_to_136_tile(sou='9')
        ]
        tile = self._string_to_34_tile(sou='1')
        option = DiscardOption(player, tile, 0, [], 0)
        self.assertEqual(option.valuation, 210)
예제 #28
0
    def test_suitable_tiles(self):
        table = Table()
        player = table.player
        strategy = YakuhaiStrategy(BaseStrategy.YAKUHAI, player)

        # for yakuhai we can use any tile
        for tile in range(0, 136):
            self.assertEqual(strategy.is_tile_suitable(tile), True)
예제 #29
0
    def test_should_activate_strategy_and_chitoitsu_like_hand(self):
        table = Table()
        player = table.player
        strategy = TanyaoStrategy(BaseStrategy.TANYAO, player)

        tiles = self._string_to_136_array(sou='223388', man='3344', pin='6687')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(), False)
예제 #30
0
    def test_riichi_and_tiles_from_another_suit_in_the_hand(self):
        table = Table()
        player = table.player
        player.scores = 25000
        table.count_of_remaining_tiles = 100

        tiles = self._string_to_136_array(man='33345678',
                                          pin='22',
                                          honors='155')
        player.init_hand(tiles)

        player.draw_tile(self._string_to_136_tile(man='9'))
        tile_to_discard = player.discard_tile()

        # we don't need to go for honitsu here
        # we already in tempai
        self.assertEqual(self._to_string([tile_to_discard]), '1z')