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')
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)
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)
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')
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)
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)
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')
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)
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)
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
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')
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)
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')
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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')
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)
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)
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)
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)
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)
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')