Пример #1
0
def test_skip_cheap_meld_1_shanten_can_move_to_west():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    table.add_dora_indicator(string_to_136_tile(sou="2"))

    tiles = string_to_136_array(man="3488", sou="334678", pin="268")
    table.player.init_hand(tiles)
    table.player.round_step = 12

    player.scores = 18000
    assert table.players[0] == player
    table.players[1].scores = 28000
    table.players[2].scores = 29000
    table.players[3].scores = 31000

    # it's cheap, but with ron from first place we can move game to west round, so let's do it
    tile = string_to_136_tile(sou="2")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None

    # now this is the cost we might win with
    tile = string_to_136_tile(sou="3")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None
Пример #2
0
def test_skip_cheap_meld_2_shanten():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    table.add_dora_indicator(string_to_136_tile(sou="2"))

    tiles = string_to_136_array(man="34889", sou="33468", pin="268")
    table.player.init_hand(tiles)
    table.player.round_step = 12

    player.scores = 18000
    assert table.players[0] == player
    table.players[1].scores = 28000
    table.players[2].scores = 35000
    table.players[3].scores = 40000

    # it's too cheap, let's not open
    tile = string_to_136_tile(sou="2")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is None

    # now this is the cost we might win with
    tile = string_to_136_tile(sou="3")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None
Пример #3
0
def test_must_push_1st_and_4th_place_riichi():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    table.add_dora_indicator(string_to_136_tile(sou="1"))

    # we have 1-shanten with no doras, but we must push because we have 4th place in oorasu
    tiles = string_to_136_array(man="3488", sou="334678", pin="456")
    table.player.init_hand(tiles)
    table.player.round_step = 5

    player.scores = 45000
    assert table.players[0] == player
    table.players[1].scores = 42000
    table.players[2].scores = 5000
    table.players[3].scores = 8000

    enemy_seat = 3
    table.add_called_riichi_step_one(enemy_seat)

    threatening_players = table.player.ai.defence.get_threatening_players()
    assert len(threatening_players) == 1

    assert not player.ai.placement.must_push(threatening_players, 0, 1)
Пример #4
0
    def test_chose_strategy_and_reset_strategy(self):
        table = Table()
        table.has_open_tanyao = True
        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)
Пример #5
0
def test_calculate_our_hand_cost_1_shanten():
    table = Table()
    player = table.player
    enemy_seat = 2

    table.has_open_tanyao = True
    table.has_aka_dora = False

    table.add_called_riichi_step_one(enemy_seat)

    tiles = string_to_136_array(sou="22245677", pin="145", man="67")

    tile = string_to_136_tile(honors="1")
    player.init_hand(tiles)
    player.add_called_meld(make_meld(MeldPrint.PON, sou="222"))
    player.draw_tile(tile)

    discard_option = find_discard_option(player, honors="1")
    cost = discard_option.average_second_level_cost

    assert cost == 1500

    table.add_dora_indicator(string_to_136_tile(sou="6"))
    discard_option = find_discard_option(player, honors="1")
    cost = discard_option.average_second_level_cost

    assert cost == 5850

    table.add_dora_indicator(string_to_136_tile(pin="2"))
    discard_option = find_discard_option(player, honors="1")
    cost = discard_option.average_second_level_cost

    assert cost == 8737
Пример #6
0
def test_skip_ron_in_west_4():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 11
    table.dealer_seat = 1
    player.dealer_seat = 1

    table.add_dora_indicator(string_to_136_tile(sou="1"))

    tiles = string_to_136_array(man="23488", sou="34678", pin="567")
    table.player.init_hand(tiles)
    table.player.add_called_meld(make_meld(MeldPrint.CHI, pin="567"))
    table.player.round_step = 14

    player.scores = 20100
    assert table.players[0] == player
    table.players[1].scores = 22000
    table.players[2].scores = 26000
    table.players[3].scores = 29900

    assert player.should_call_win(string_to_136_tile(sou="5"), False, 1)
    assert not player.should_call_win(string_to_136_tile(sou="5"), False, 2)
    assert not player.should_call_win(string_to_136_tile(sou="5"), False, 3)
Пример #7
0
def test_dont_open_bad_hand_if_there_are_expensive_threat():
    table = Table()
    table.add_dora_indicator(string_to_136_tile(man="4"))
    player = table.player
    player.round_step = 10
    table.has_open_tanyao = True
    table.has_aka_dora = True

    enemy_seat = 1
    table.add_called_riichi_step_one(enemy_seat)
    table.add_discarded_tile(enemy_seat, string_to_136_tile(honors="4"), True)

    tiles = string_to_136_array(sou="226", pin="2469", man="3344",
                                honors="4") + [FIVE_RED_MAN]
    player.init_hand(tiles)

    # cheap enemy tempai, but this meld is garbage, let's not push
    tile = string_to_136_array(man="4444")[2]
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is None

    # cheap enemy tempai, and good chi, let's take this meld
    tile = string_to_136_tile(man="2")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None

    table.add_called_meld(
        enemy_seat, make_meld(MeldPrint.KAN, is_open=False, honors="1111"))
    # enemy hand is more expensive now (12000)
    # in this case let's not open this hand
    tile = string_to_136_tile(man="2")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is None
Пример #8
0
    def test_chose_right_set_to_open_hand(self):
        """
        Different test cases to open hand and chose correct set to open hand.
        Based on real examples of incorrect opened hands
        """
        table = Table()
        table.has_open_tanyao = True
        player = table.player

        tiles = self._string_to_136_array(man='23455',
                                          pin='3445678',
                                          honors='1')
        tile = self._string_to_136_tile(man='5')
        player.init_hand(tiles)

        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(meld.type, Meld.PON)
        self.assertEqual(self._to_string(meld.tiles), '555m')

        table = Table()
        player = table.player
        tiles = self._string_to_136_array(man='335666',
                                          pin='22',
                                          sou='345',
                                          honors='55')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(man='4')
        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(meld.type, Meld.CHI)
        self.assertEqual(self._to_string(meld.tiles), '345m')

        table = Table()
        table.has_open_tanyao = True
        player = table.player
        tiles = self._string_to_136_array(man='23557',
                                          pin='556788',
                                          honors='22')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(pin='5')
        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(meld.type, Meld.PON)
        self.assertEqual(self._to_string(meld.tiles), '555p')
Пример #9
0
def _make_table():
    table = Table()
    table.has_open_tanyao = True

    # add doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(sou="1"))
    table.add_dora_indicator(string_to_136_tile(man="1"))
    table.add_dora_indicator(string_to_136_tile(pin="1"))

    return table
Пример #10
0
    def test_is_dora(self):
        table = Table()
        table.init_round(0, 0, 0, 0, 0, [])

        table.dora_indicators = [self._string_to_136_tile(sou='1')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(sou='2')))

        table.dora_indicators = [self._string_to_136_tile(sou='9')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(sou='1')))

        table.dora_indicators = [self._string_to_136_tile(pin='9')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(pin='1')))

        table.dora_indicators = [self._string_to_136_tile(man='9')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(man='1')))

        table.dora_indicators = [self._string_to_136_tile(man='5')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(man='6')))

        table.dora_indicators = [self._string_to_136_tile(honors='1')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='2')))

        table.dora_indicators = [self._string_to_136_tile(honors='2')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='3')))

        table.dora_indicators = [self._string_to_136_tile(honors='3')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='4')))

        table.dora_indicators = [self._string_to_136_tile(honors='4')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='1')))

        table.dora_indicators = [self._string_to_136_tile(honors='5')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='6')))

        table.dora_indicators = [self._string_to_136_tile(honors='6')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='7')))

        table.dora_indicators = [self._string_to_136_tile(honors='7')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='5')))

        table.dora_indicators = [self._string_to_136_tile(pin='1')]
        self.assertFalse(table.is_dora(self._string_to_136_tile(sou='2')))

        table.has_open_tanyao = True

        # red five man
        self.assertTrue(table.is_dora(FIVE_RED_MAN))

        # red five pin
        self.assertTrue(table.is_dora(FIVE_RED_PIN))

        # red five sou
        self.assertTrue(table.is_dora(FIVE_RED_SOU))
    def test_is_dora(self):
        table = Table()
        table.init_round(0, 0, 0, 0, 0, [])

        table.dora_indicators = [self._string_to_136_tile(sou='1')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(sou='2')))

        table.dora_indicators = [self._string_to_136_tile(sou='9')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(sou='1')))

        table.dora_indicators = [self._string_to_136_tile(pin='9')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(pin='1')))

        table.dora_indicators = [self._string_to_136_tile(man='9')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(man='1')))

        table.dora_indicators = [self._string_to_136_tile(man='5')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(man='6')))

        table.dora_indicators = [self._string_to_136_tile(honors='1')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='2')))

        table.dora_indicators = [self._string_to_136_tile(honors='2')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='3')))

        table.dora_indicators = [self._string_to_136_tile(honors='3')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='4')))

        table.dora_indicators = [self._string_to_136_tile(honors='4')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='1')))

        table.dora_indicators = [self._string_to_136_tile(honors='5')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='6')))

        table.dora_indicators = [self._string_to_136_tile(honors='6')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='7')))

        table.dora_indicators = [self._string_to_136_tile(honors='7')]
        self.assertTrue(table.is_dora(self._string_to_136_tile(honors='5')))

        table.dora_indicators = [self._string_to_136_tile(pin='1')]
        self.assertFalse(table.is_dora(self._string_to_136_tile(sou='2')))

        table.has_open_tanyao = True

        # red five man
        self.assertTrue(table.is_dora(FIVE_RED_MAN))

        # red five pin
        self.assertTrue(table.is_dora(FIVE_RED_PIN))

        # red five sou
        self.assertTrue(table.is_dora(FIVE_RED_SOU))
Пример #12
0
def test_is_dora():
    table = Table()
    table.init_round(0, 0, 0, 0, 0, [])

    table.dora_indicators = [string_to_136_tile(sou="1")]
    assert table.is_dora(string_to_136_tile(sou="2"))

    table.dora_indicators = [string_to_136_tile(sou="9")]
    assert table.is_dora(string_to_136_tile(sou="1"))

    table.dora_indicators = [string_to_136_tile(pin="9")]
    assert table.is_dora(string_to_136_tile(pin="1"))

    table.dora_indicators = [string_to_136_tile(man="9")]
    assert table.is_dora(string_to_136_tile(man="1"))

    table.dora_indicators = [string_to_136_tile(man="5")]
    assert table.is_dora(string_to_136_tile(man="6"))

    table.dora_indicators = [string_to_136_tile(honors="1")]
    assert table.is_dora(string_to_136_tile(honors="2"))

    table.dora_indicators = [string_to_136_tile(honors="2")]
    assert table.is_dora(string_to_136_tile(honors="3"))

    table.dora_indicators = [string_to_136_tile(honors="3")]
    assert table.is_dora(string_to_136_tile(honors="4"))

    table.dora_indicators = [string_to_136_tile(honors="4")]
    assert table.is_dora(string_to_136_tile(honors="1"))

    table.dora_indicators = [string_to_136_tile(honors="5")]
    assert table.is_dora(string_to_136_tile(honors="6"))

    table.dora_indicators = [string_to_136_tile(honors="6")]
    assert table.is_dora(string_to_136_tile(honors="7"))

    table.dora_indicators = [string_to_136_tile(honors="7")]
    assert table.is_dora(string_to_136_tile(honors="5"))

    table.dora_indicators = [string_to_136_tile(pin="1")]
    assert not table.is_dora(string_to_136_tile(sou="2"))

    table.has_open_tanyao = True

    # red five man
    assert table.is_dora(FIVE_RED_MAN)

    # red five pin
    assert table.is_dora(FIVE_RED_PIN)

    # red five sou
    assert table.is_dora(FIVE_RED_SOU)
Пример #13
0
def test_chose_strategy_and_reset_strategy():
    table = Table()
    table.has_open_tanyao = True
    player = table.player

    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="2"))

    # we draw a tile that will set tanyao as our selected strategy
    tiles = string_to_136_array(man="33355788", sou="3479", honors="3")
    player.init_hand(tiles)

    tile = string_to_136_tile(sou="7")
    player.draw_tile(tile)
    assert player.ai.current_strategy is not None
    assert player.ai.current_strategy.type == BaseStrategy.TANYAO

    # we draw a tile that will change our selected strategy
    tiles = string_to_136_array(man="33355788", sou="3479", honors="3")
    player.init_hand(tiles)

    tile = string_to_136_tile(sou="2")
    meld, _ = player.try_to_call_meld(tile, False)
    assert player.ai.current_strategy is not None
    assert player.ai.current_strategy.type == BaseStrategy.TANYAO
    assert meld is None

    tile = string_to_136_tile(sou="8")
    player.draw_tile(tile)
    assert player.ai.current_strategy is None

    # for already opened hand we don't need to give up on selected strategy
    tiles = string_to_136_array(man="33355788", sou="3479", honors="3")
    player.init_hand(tiles)
    player.draw_tile(string_to_136_tile(honors="5"))
    player.discard_tile()

    meld = make_meld(MeldPrint.PON, man="333")
    player.add_called_meld(meld)
    tile = string_to_136_tile(sou="8")
    player.draw_tile(tile)

    assert player.ai.current_strategy is not None
    assert player.ai.current_strategy.type == BaseStrategy.TANYAO
Пример #14
0
def test_calculate_our_hand_cost_1_shanten_karaten():
    table = Table()
    player = table.player
    enemy_seat = 2

    table.has_open_tanyao = True
    table.has_aka_dora = False

    table.add_called_riichi_step_one(enemy_seat)

    tiles = string_to_136_array(sou="22245677", pin="145", man="67")

    tile = string_to_136_tile(honors="1")
    player.init_hand(tiles)
    player.add_called_meld(make_meld(MeldPrint.PON, sou="222"))
    player.draw_tile(tile)

    # average cost should not change because of less waits
    for _ in range(0, 4):
        table.add_discarded_tile(1, string_to_136_tile(pin="3"), False)

    discard_option = find_discard_option(player, honors="1")
    cost = discard_option.average_second_level_cost

    assert cost == 1500

    # average cost should become 0 for karaten, even if just one of the waits is dead
    for _ in range(0, 4):
        table.add_discarded_tile(1, string_to_136_tile(pin="6"), False)

    discard_option = find_discard_option(player, honors="1")
    cost = discard_option.average_second_level_cost

    assert cost == 0

    # nothing should crash in case all waits are dead as well
    for _ in range(0, 4):
        table.add_discarded_tile(1, string_to_136_tile(man="5"), False)
        table.add_discarded_tile(1, string_to_136_tile(man="8"), False)

    discard_option = find_discard_option(player, honors="1")
    cost = discard_option.average_second_level_cost

    assert cost == 0
Пример #15
0
    def test_chose_strategy_and_reset_strategy(self):
        table = Table()
        table.has_open_tanyao = True
        player = table.player

        # add 3 doras so we are sure to go for tanyao
        table.add_dora_indicator(self._string_to_136_tile(man='2'))

        # we draw a tile that will set tanyao as our selected strategy
        tiles = self._string_to_136_array(man='33355788', sou='3479', honors='3')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(sou='7')
        player.draw_tile(tile)
        self.assertNotEqual(player.ai.current_strategy, None)
        self.assertEqual(player.ai.current_strategy.type, BaseStrategy.TANYAO)

        # we draw a tile that will change our selected strategy
        tiles = self._string_to_136_array(man='33355788', sou='3479', honors='3')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(sou='2')
        meld, _ = player.try_to_call_meld(tile, False)
        self.assertNotEqual(player.ai.current_strategy, None)
        self.assertEqual(player.ai.current_strategy.type, BaseStrategy.TANYAO)
        self.assertEqual(meld, None)

        tile = self._string_to_136_tile(sou='8')
        player.draw_tile(tile)
        self.assertEqual(player.ai.current_strategy, None)

        # for already opened hand we don't need to give up on selected strategy
        tiles = self._string_to_136_array(man='33355788', sou='3479', honors='3')
        player.init_hand(tiles)
        player.draw_tile(self._string_to_136_tile(honors='5'))
        player.discard_tile()

        meld = self._make_meld(Meld.PON, man='333')
        player.add_called_meld(meld)
        tile = self._string_to_136_tile(sou='8')
        player.draw_tile(tile)

        self.assertNotEqual(player.ai.current_strategy, None)
        self.assertEqual(player.ai.current_strategy.type, BaseStrategy.TANYAO)
Пример #16
0
def test_take_cheap_meld_tempai():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    table.add_dora_indicator(string_to_136_tile(man="2"))

    tiles = string_to_136_array(man="23789", sou="3789", pin="99", honors="33")
    table.player.init_hand(tiles)
    table.player.round_step = 5

    player.scores = 20000
    assert table.players[0] == player
    table.players[1].scores = 20900
    table.players[2].scores = 35000
    table.players[3].scores = 40000

    # no yaku, skip
    tile = string_to_136_tile(man="4")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is None

    # now this is the cost we might win with
    tile = string_to_136_tile(man="1")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None

    # now this is not enough
    player.scores = 20000
    assert table.players[0] == player
    table.players[1].scores = 30900
    table.players[2].scores = 35000
    table.players[3].scores = 40000

    tile = string_to_136_tile(man="1")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is None
Пример #17
0
def test_skip_ron():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    table.add_dora_indicator(string_to_136_tile(sou="1"))

    # 1900 to 3rd place
    player.scores = 20100
    assert table.players[0] == player
    table.players[1].scores = 22000
    table.players[2].scores = 26000
    table.players[3].scores = 30900

    minimal_cost = player.ai.placement.get_minimal_cost_needed()
    assert minimal_cost == 1900

    tiles = string_to_136_array(man="23488", sou="34678", pin="567")
    table.player.init_hand(tiles)
    table.player.add_called_meld(make_meld(MeldPrint.CHI, pin="567"))
    table.player.round_step = 14

    # we should not call ron 1000 from 2nd place as it leaves us on 4th
    assert not player.should_call_win(string_to_136_tile(sou="5"), False, 2)

    # ron 2000 from 2nd place is ok, it's enough to get to 3rd
    assert player.should_call_win(string_to_136_tile(sou="2"), False, 2)

    # ron 1000 from 3rd place is ok too
    assert player.should_call_win(string_to_136_tile(sou="5"), False, 1)

    # ron 1000 from 1st place is ok too as it moves us to west round
    assert player.should_call_win(string_to_136_tile(sou="5"), False, 3)

    # ron 2000 from 1st place is ok, checking just to be sure
    assert player.should_call_win(string_to_136_tile(sou="2"), False, 3)
Пример #18
0
def test_take_cheap_meld_tempai_tanyao_not_activated():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    # tanyao is not activated due to tanyao rules but we don't care and take this meld
    tiles = string_to_136_array(man="23678", sou="3567", pin="2257")
    table.player.init_hand(tiles)
    table.player.round_step = 5

    player.scores = 20000
    assert table.players[0] == player
    table.players[1].scores = 20900
    table.players[2].scores = 35000
    table.players[3].scores = 40000

    # no yaku, skip
    tile = string_to_136_tile(man="1")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is None

    # now this is the cost we might win with
    tile = string_to_136_tile(man="4")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None

    # now this is not enough
    player.scores = 20000
    assert table.players[0] == player
    table.players[1].scores = 30900
    table.players[2].scores = 35000
    table.players[3].scores = 40000

    tile = string_to_136_tile(man="4")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is None
Пример #19
0
def test_take_cheap_meld_yakuhai_1_shanten():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    tiles = string_to_136_array(man="236778", sou="357", pin="22", honors="55")
    table.player.init_hand(tiles)
    table.player.round_step = 5

    player.scores = 20000
    assert table.players[0] == player
    table.players[1].scores = 20900
    table.players[2].scores = 35000
    table.players[3].scores = 40000

    # bad atodzuke - skip
    tile = string_to_136_tile(pin="2")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is None

    # now this is the cost we might win with
    tile = string_to_136_tile(honors="5")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is not None

    # now this is not enough
    player.scores = 20000
    assert table.players[0] == player
    table.players[1].scores = 30900
    table.players[2].scores = 35000
    table.players[3].scores = 40000

    tile = string_to_136_tile(honors="5")
    meld, _ = table.player.try_to_call_meld(tile, True)
    assert meld is None
Пример #20
0
def test_skip_ron_wind_placement():
    table = Table()
    player = table.player
    table.has_aka_dora = True
    table.has_open_tanyao = True
    # orasu
    table.round_wind_number = 7
    table.dealer_seat = 1
    player.dealer_seat = 1

    table.add_dora_indicator(string_to_136_tile(sou="1"))

    tiles = string_to_136_array(man="23488", sou="34678", pin="567")
    table.player.init_hand(tiles)
    table.player.add_called_meld(make_meld(MeldPrint.CHI, pin="567"))
    table.player.round_step = 14

    player.scores = 21000
    assert table.players[0] == player
    table.players[1].scores = 22000
    table.players[2].scores = 30100
    table.players[3].scores = 31000

    player.first_seat = 0
    table.players[1].first_seat = 1

    assert player.ai.placement.get_minimal_cost_needed() == 1000

    assert player.should_call_win(string_to_136_tile(sou="5"), False, 1)
    assert player.should_call_win(string_to_136_tile(sou="5"), False, 2)
    assert player.should_call_win(string_to_136_tile(sou="5"), False, 3)

    player.first_seat = 1
    table.players[1].first_seat = 0

    assert player.ai.placement.get_minimal_cost_needed() == 1100

    assert player.should_call_win(string_to_136_tile(sou="5"), False, 1)
    assert not player.should_call_win(string_to_136_tile(sou="5"), False, 2)
    assert not player.should_call_win(string_to_136_tile(sou="5"), False, 3)
Пример #21
0
def test_dont_open_bad_hand_if_there_are_multiple_threats():
    table = Table()
    table.add_dora_indicator(string_to_136_tile(man="4"))
    player = table.player
    player.round_step = 10
    table.has_open_tanyao = True
    table.has_aka_dora = True

    table.add_called_riichi_step_one(1)
    table.add_discarded_tile(1, string_to_136_tile(honors="4"), True)

    table.add_called_riichi_step_one(2)
    table.add_discarded_tile(2, string_to_136_tile(honors="4"), True)

    tiles = string_to_136_array(sou="22499", pin="27", man="3344",
                                honors="4") + [FIVE_RED_MAN]
    player.init_hand(tiles)
    tile = string_to_136_tile(man="4")

    # there are multiple threats with (3900+) hands
    # let's not push in that case
    meld, _ = player.try_to_call_meld(tile, False)
    assert meld is None
Пример #22
0
def test_chose_right_set_to_open_hand_dora():
    table = Table()
    table.has_open_tanyao = True
    table.has_aka_dora = False
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="7"))
    table.add_dora_indicator(string_to_136_tile(sou="1"))
    tiles = string_to_136_array(man="3456788", sou="245888")
    player.init_hand(tiles)

    tile = string_to_136_tile(sou="3")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "234s"

    table = Table()
    table.has_open_tanyao = True
    table.has_aka_dora = False
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="7"))
    table.add_dora_indicator(string_to_136_tile(sou="4"))
    tiles = string_to_136_array(man="3456788", sou="245888")
    player.init_hand(tiles)

    tile = string_to_136_tile(sou="3")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "345s"

    table = Table()
    table.has_open_tanyao = True
    table.has_aka_dora = True
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="7"))
    # 5 from string is always aka
    tiles = string_to_136_array(man="3456788", sou="240888")
    player.init_hand(tiles)

    tile = string_to_136_tile(sou="3")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "340s"

    table = Table()
    table.has_open_tanyao = True
    table.has_aka_dora = True
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="7"))
    table.add_dora_indicator(string_to_136_tile(sou="1"))
    table.add_dora_indicator(string_to_136_tile(sou="4"))
    # double dora versus regular dora, we should keep double dora
    tiles = string_to_136_array(man="3456788", sou="245888")
    player.init_hand(tiles)

    tile = string_to_136_tile(sou="3")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "345s"
Пример #23
0
 def _make_table(self):
     table = Table()
     table.has_open_tanyao = True
     return table
Пример #24
0
def test_chose_right_set_to_open_hand():
    """
    Different test cases to open hand and chose correct set to open hand.
    Based on real examples of incorrect opened hands
    """
    table = Table()
    table.has_open_tanyao = True
    player = table.player

    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(pin="2"))
    table.add_dora_indicator(string_to_136_tile(pin="3"))

    tiles = string_to_136_array(man="23455", pin="3445678", honors="1")
    tile = string_to_136_array(man="5555")[2]
    player.init_hand(tiles)

    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.PON
    assert tiles_to_string(meld.tiles) == "555m"

    table = Table()
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="5"))
    tiles = string_to_136_array(man="335666", pin="22", sou="345", honors="55")
    player.init_hand(tiles)

    tile = string_to_136_tile(man="4")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "345m"

    table = Table()
    table.has_open_tanyao = True
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="1"))
    table.add_dora_indicator(string_to_136_tile(man="4"))
    tiles = string_to_136_array(man="23557", pin="556788", honors="22")
    player.init_hand(tiles)

    tile = string_to_136_array(pin="5555")[2]
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.PON
    assert tiles_to_string(meld.tiles) == "555p"

    table = Table()
    table.has_open_tanyao = True
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="4"))
    table.add_dora_indicator(string_to_136_tile(pin="5"))
    tiles = string_to_136_array(man="35568", pin="234668", sou="28")
    player.init_hand(tiles)

    tile = string_to_136_tile(man="4")
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "345m"

    table = Table()
    table.has_open_tanyao = True
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="4"))
    table.add_dora_indicator(string_to_136_tile(pin="5"))
    tiles = string_to_136_array(man="34458", pin="234668", sou="28")
    player.init_hand(tiles)

    tile = string_to_136_array(man="4444")[2]
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "345m"

    table = Table()
    table.has_open_tanyao = True
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="7"))
    tiles = string_to_136_array(man="567888", pin="788", sou="3456")
    player.init_hand(tiles)

    tile = string_to_136_array(sou="4444")[1]
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "456s"

    tile = string_to_136_array(sou="5555")[1]
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "345s"

    table = Table()
    table.has_open_tanyao = True
    player = table.player
    # add 3 doras so we are sure to go for tanyao
    table.add_dora_indicator(string_to_136_tile(man="7"))
    tiles = string_to_136_array(man="567888", pin="788", sou="2345")
    player.init_hand(tiles)

    tile = string_to_136_array(sou="4444")[1]
    meld, _ = player.try_to_call_meld(tile, True)
    assert meld is not None
    assert meld.type == MeldPrint.CHI
    assert tiles_to_string(meld.tiles) == "234s"
Пример #25
0
    def reproduce(self, player, wind, honba, needed_tile, action,
                  tile_number_to_stop):
        player_position = self._find_player_position(player)
        round_content = self._find_needed_round(wind, honba)

        draw_tags = ["T", "U", "V", "W"]
        discard_tags = ["D", "E", "F", "G"]

        player_draw = draw_tags[player_position]

        player_draw_regex = re.compile(r"^<[{}]+\d*".format(
            "".join(player_draw)))
        discard_regex = re.compile(r"^<[{}]+\d*".format("".join(discard_tags)))

        draw_regex = re.compile(r"^<[{}]+\d*".format("".join(draw_tags)))
        last_draws = {0: None, 1: None, 2: None, 3: None}

        table = Table()
        # TODO get this info from log content
        table.has_aka_dora = True
        table.has_open_tanyao = True
        table.player.init_logger(self.logger)

        players = {}
        for round_item in self.rounds:
            for tag in round_item:
                if "<UN" in tag:
                    players_temp = self.decoder.parse_names_and_ranks(tag)
                    if players_temp:
                        for x in players_temp:
                            players[x["seat"]] = x

        draw_tile_seen_number = 0
        enemy_discard_seen_number = 0
        for tag in round_content:
            if player_draw_regex.match(tag) and "UN" not in tag:
                tile = self.decoder.parse_tile(tag)
                table.count_of_remaining_tiles -= 1

                # is it time to stop reproducing?
                found_tile = TilesConverter.to_one_line_string(
                    [tile]) == needed_tile
                if action == "draw" and found_tile:
                    draw_tile_seen_number += 1
                    if draw_tile_seen_number == tile_number_to_stop:
                        self.logger.info("Stop on player draw")

                        discard_result = None
                        with_riichi = False
                        table.player.draw_tile(tile)

                        table.player.should_call_kan(
                            tile,
                            open_kan=False,
                            from_riichi=table.player.in_riichi)

                        if not table.player.in_riichi:
                            discard_result = table.player.discard_tile()
                            with_riichi = table.player.can_call_riichi()

                        return discard_result, with_riichi

                table.player.draw_tile(tile)

            if "INIT" in tag:
                values = self.decoder.parse_initial_values(tag)

                shifted_scores = []
                for x in range(0, 4):
                    shifted_scores.append(
                        values["scores"][self._normalize_position(
                            player_position, x)])

                table.init_round(
                    values["round_wind_number"],
                    values["count_of_honba_sticks"],
                    values["count_of_riichi_sticks"],
                    values["dora_indicator"],
                    self._normalize_position(values["dealer"],
                                             player_position),
                    shifted_scores,
                )

                hands = [
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai0").split(",")
                    ],
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai1").split(",")
                    ],
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai2").split(",")
                    ],
                    [
                        int(x) for x in self.decoder.get_attribute_content(
                            tag, "hai3").split(",")
                    ],
                ]

                table.player.init_hand(hands[player_position])
                table.player.name = players[player_position]["name"]

                self.logger.info("Init round info")
                self.logger.info(table.player.name)
                self.logger.info(f"Scores: {table.player.scores}")
                self.logger.info(
                    f"Wind: {DISPLAY_WINDS[table.player.player_wind]}")

            if "DORA hai" in tag:
                table.add_dora_indicator(
                    int(self._get_attribute_content(tag, "hai")))

            if draw_regex.match(tag) and "UN" not in tag:
                tile = self.decoder.parse_tile(tag)
                player_sign = tag.upper()[1]
                player_seat = self._normalize_position(
                    draw_tags.index(player_sign), player_position)
                last_draws[player_seat] = tile

            if discard_regex.match(tag) and "DORA" not in tag:
                tile = self.decoder.parse_tile(tag)
                player_sign = tag.upper()[1]
                player_seat = self._normalize_position(
                    discard_tags.index(player_sign), player_position)

                if player_seat == 0:
                    table.player.discard_tile(tile, force_tsumogiri=True)
                else:
                    # is it time to stop?
                    found_tile = TilesConverter.to_one_line_string(
                        [tile]) == needed_tile
                    is_kamicha_discard = player_seat == 3

                    if action == "enemy_discard" and found_tile:
                        enemy_discard_seen_number += 1
                        if enemy_discard_seen_number == tile_number_to_stop:
                            self.logger.info("Stop on enemy discard")
                            self._rebuild_bot_shanten_cache(table.player)
                            table.player.should_call_kan(tile,
                                                         open_kan=True,
                                                         from_riichi=False)
                            return table.player.try_to_call_meld(
                                tile, is_kamicha_discard)

                    is_tsumogiri = last_draws[player_seat] == tile
                    table.add_discarded_tile(player_seat,
                                             tile,
                                             is_tsumogiri=is_tsumogiri)

            if "<N who=" in tag:
                meld = self.decoder.parse_meld(tag)
                player_seat = self._normalize_position(meld.who,
                                                       player_position)
                table.add_called_meld(player_seat, meld)

                if player_seat == 0:
                    if meld.type != MeldPrint.KAN and meld.type != MeldPrint.SHOUMINKAN:
                        table.player.draw_tile(meld.called_tile)

            if "<REACH" in tag and 'step="1"' in tag:
                who_called_riichi = self._normalize_position(
                    self.decoder.parse_who_called_riichi(tag), player_position)
                table.add_called_riichi_step_one(who_called_riichi)

            if "<REACH" in tag and 'step="2"' in tag:
                who_called_riichi = self._normalize_position(
                    self.decoder.parse_who_called_riichi(tag), player_position)
                table.add_called_riichi_step_two(who_called_riichi)
Пример #26
0
    def test_chose_right_set_to_open_hand_dora(self):
        table = Table()
        table.has_open_tanyao = True
        table.has_aka_dora = False
        player = table.player
        # add 3 doras so we are sure to go for tanyao
        table.add_dora_indicator(self._string_to_136_tile(man='7'))
        table.add_dora_indicator(self._string_to_136_tile(sou='1'))
        tiles = self._string_to_136_array(man='3456788', sou='245888')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(sou='3')
        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(meld.type, Meld.CHI)
        self.assertEqual(self._to_string(meld.tiles), '234s')

        table = Table()
        table.has_open_tanyao = True
        table.has_aka_dora = False
        player = table.player
        # add 3 doras so we are sure to go for tanyao
        table.add_dora_indicator(self._string_to_136_tile(man='7'))
        table.add_dora_indicator(self._string_to_136_tile(sou='4'))
        tiles = self._string_to_136_array(man='3456788', sou='245888')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(sou='3')
        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(meld.type, Meld.CHI)
        self.assertEqual(self._to_string(meld.tiles), '345s')

        table = Table()
        table.has_open_tanyao = True
        table.has_aka_dora = True
        player = table.player
        # add 3 doras so we are sure to go for tanyao
        table.add_dora_indicator(self._string_to_136_tile(man='7'))
        # 5 from string is always aka
        tiles = self._string_to_136_array(man='3456788', sou='245888')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(sou='3')
        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(meld.type, Meld.CHI)
        self.assertEqual(self._to_string(meld.tiles), '345s')

        table = Table()
        table.has_open_tanyao = True
        table.has_aka_dora = True
        player = table.player
        # add 3 doras so we are sure to go for tanyao
        table.add_dora_indicator(self._string_to_136_tile(man='7'))
        table.add_dora_indicator(self._string_to_136_tile(sou='1'))
        table.add_dora_indicator(self._string_to_136_tile(sou='4'))
        # double dora versus regular dora, we should keep double dora
        tiles = self._string_to_136_array(man='3456788', sou='245888')
        player.init_hand(tiles)

        tile = self._string_to_136_tile(sou='3')
        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(meld.type, Meld.CHI)
        self.assertEqual(self._to_string(meld.tiles), '345s')