示例#1
0
    def test_dont_go_for_honitsu_with_ryanmen_in_other_suit(self):
        table = Table()
        player = table.player
        strategy = HonitsuStrategy(BaseStrategy.HONITSU, player)

        tiles = self._string_to_136_array(man='14489',
                                          sou='45',
                                          pin='67',
                                          honors='44456')
        player.init_hand(tiles)

        self.assertEqual(strategy.should_activate_strategy(), False)
示例#2
0
    def determine_strategy(self):
        # for already opened hand we don't need to give up on selected strategy
        if self.player.is_open_hand and self.current_strategy:
            return False

        old_strategy = self.current_strategy
        self.current_strategy = None

        # order is important
        strategies = [
            YakuhaiStrategy(BaseStrategy.YAKUHAI, self.player),
            HonitsuStrategy(BaseStrategy.HONITSU, self.player),
        ]

        if self.player.table.has_open_tanyao:
            strategies.append(TanyaoStrategy(BaseStrategy.TANYAO, self.player))

        for strategy in strategies:
            if strategy.should_activate_strategy():
                self.current_strategy = strategy

        if self.current_strategy:
            if not old_strategy or self.current_strategy.type != old_strategy.type:
                message = '{} switched to {} strategy'.format(self.player.name, self.current_strategy)
                if old_strategy:
                    message += ' from {}'.format(old_strategy)
                logger.info(message)
                logger.info('With such a hand: {}'.format(TilesConverter.to_one_line_string(self.player.tiles)))

        if not self.current_strategy and old_strategy:
            logger.debug('{} gave up on {}'.format(self.player.name, old_strategy))

        return self.current_strategy and True or False
    def test_open_suit_same_shanten(self):
        table = Table()
        player = table.player
        player.scores = 25000
        table.count_of_remaining_tiles = 100

        tiles = self._string_to_136_array(man='1134556', pin='3', sou='78', honors='777')
        player.init_hand(tiles)

        meld = self._make_meld(Meld.CHI, man='345')
        player.add_called_meld(meld)

        strategy = HonitsuStrategy(BaseStrategy.HONITSU, player)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), True)

        tile = self._string_to_136_tile(man='1')
        meld, _ = player.try_to_call_meld(tile, True)
        self.assertNotEqual(meld, None)
        self.assertEqual(self._to_string(meld.tiles), '111m')
示例#4
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)
    def test_suitable_tiles(self):
        table = Table()
        player = table.player
        strategy = HonitsuStrategy(BaseStrategy.HONITSU, player)

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

        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='1')
        self.assertEqual(strategy.is_tile_suitable(tile), True)

        tile = self._string_to_136_tile(honors='1')
        self.assertEqual(strategy.is_tile_suitable(tile), True)
示例#6
0
    def determine_strategy(self, tiles_136):
        # for already opened hand we don't need to give up on selected strategy
        if self.player.is_open_hand and self.current_strategy:
            return False

        old_strategy = self.current_strategy
        self.current_strategy = None

        # order is important, we add strategies with the highest priority first
        strategies = []

        if self.player.table.has_open_tanyao:
            strategies.append(TanyaoStrategy(BaseStrategy.TANYAO, self.player))

        strategies.append(YakuhaiStrategy(BaseStrategy.YAKUHAI, self.player))
        strategies.append(HonitsuStrategy(BaseStrategy.HONITSU, self.player))
        strategies.append(ChinitsuStrategy(BaseStrategy.CHINITSU, self.player))

        strategies.append(ChiitoitsuStrategy(BaseStrategy.CHIITOITSU, self.player))
        strategies.append(FormalTempaiStrategy(BaseStrategy.FORMAL_TEMPAI, self.player))

        for strategy in strategies:
            if strategy.should_activate_strategy(tiles_136):
                self.current_strategy = strategy
                break

        if self.current_strategy:
            if not old_strategy or self.current_strategy.type != old_strategy.type:
                DecisionsLogger.debug(
                    log.STRATEGY_ACTIVATE,
                    context=self.current_strategy,
                )

        if not self.current_strategy and old_strategy:
            DecisionsLogger.debug(log.STRATEGY_DROP, context=old_strategy)

        return self.current_strategy and True or False
示例#7
0
    def should_activate_strategy(self, tiles_136):
        """
        We can go for chinitsu strategy if we have prevalence of one suit
        """

        result = super(ChinitsuStrategy, self).should_activate_strategy(tiles_136)
        if not result:
            return False

        # when making decisions about chinitsu, we should consider
        # the state of our own hand,
        tiles_34 = TilesConverter.to_34_array(self.player.tiles)
        suits = count_tiles_by_suits(tiles_34)

        suits = [x for x in suits if x['name'] != 'honor']
        suits = sorted(suits, key=lambda x: x['count'], reverse=True)
        suit = suits[0]

        count_of_shuntsu_other_suits = 0
        count_of_koutsu_other_suits = 0

        count_of_shuntsu_other_suits += HonitsuStrategy._count_of_shuntsu(tiles_34, suits[1]['function'])
        count_of_shuntsu_other_suits += HonitsuStrategy._count_of_shuntsu(tiles_34, suits[2]['function'])

        count_of_koutsu_other_suits += HonitsuStrategy._count_of_koutsu(tiles_34, suits[1]['function'])
        count_of_koutsu_other_suits += HonitsuStrategy._count_of_koutsu(tiles_34, suits[2]['function'])

        # we need to have at least 9 tiles of one suit to fo for chinitsu
        if suit['count'] < 9:
            return False

        # here we only check doras in different suits, we will deal
        # with honors later
        self._initialize_chinitsu_dora_count(tiles_136, suit)

        # 3 non-isolated doras in other suits is too much
        # to even try
        if self.dora_count_not_suitable >= 3:
            return False

        if self.dora_count_not_suitable == 2:
            # 2 doras in other suits, no doras in our suit
            # let's not consider chinitsu
            if self.dora_count_suitable == 0:
                return False

            # we have 2 doras in other suits and we
            # are 1 shanten, let's not rush chinitsu
            if self.player.ai.shanten == 1:
                return False

            # too late to get rid of doras in other suits
            if self.player.round_step > 8:
                return False

        # we are almost tempai, chinitsu is slower
        if suit['count'] == 9 and self.player.ai.shanten == 1:
            return False

        # only 10 tiles by 8th turn is too slow, considering alternative
        if suit['count'] == 10 and self.player.ai.shanten == 1 and self.player.round_step > 8:
            return False

        # if we have a pon of honors, let's not go for chinitsu
        honor_pons = len([x for x in range(0, 34) if is_honor(x) and tiles_34[x] >= 3])
        if honor_pons >= 1:
            return False

        # if we have a valued pair, let's not go for chinitsu
        valued_pairs = len([x for x in self.player.valued_honors if tiles_34[x] == 2])
        if valued_pairs >= 1:
            return False

        # if we have a pair of honor doras, let's not go for chinitsu
        honor_doras_pairs = len([x for x in range(0, 34) if is_honor(x) and tiles_34[x] == 2
                                 and plus_dora(x * 4, self.player.table.dora_indicators)])
        if honor_doras_pairs >= 1:
            return False

        # if we have a honor pair, we will only throw them away if it's early in the game
        # and if we have lots of tiles in our suit
        honor_pairs = len([x for x in range(0, 34) if is_honor(x) and tiles_34[x] == 2])
        if honor_pairs >= 2:
            return False
        if honor_pairs == 1:
            if suit['count'] < 11:
                return False
            if self.player.round_step > 8:
                return False

        # if we have a complete set in other suits, we can only throw it away if it's early in the game
        if count_of_shuntsu_other_suits + count_of_koutsu_other_suits >= 1:
            # too late to throw away chi after 8 step
            if self.player.round_step > 8:
                return False

            # already 1 shanten, no need to throw away complete set
            if self.player.round_step > 5 and self.player.ai.shanten == 1:
                return False

            # dora is not isolated and we have a complete set, let's not go for chinitsu
            if self.dora_count_not_suitable >= 1:
                return False

        self.chosen_suit = suit['function']

        return True
    def test_should_activate_strategy(self):
        table = Table()
        player = table.player
        strategy = HonitsuStrategy(BaseStrategy.HONITSU, player)

        table.add_dora_indicator(self._string_to_136_tile(pin='1'))
        table.add_dora_indicator(self._string_to_136_tile(honors='5'))

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

        # many tiles in one suit and yakuhai pair, but still many useless winds
        tiles = self._string_to_136_array(sou='12355', man='23', pin='68', honors='2355')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), False)

        # many tiles in one suit and yakuhai pair and another honor pair, so
        # now this is honitsu
        tiles = self._string_to_136_array(sou='12355', man='238', honors='22355')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), True)

        # same conditions, but ready suit with dora in another suit, so no honitsu
        tiles = self._string_to_136_array(sou='12355', pin='234', honors='22355')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), False)

        # same conditions, but we have a pon of yakuhai doras, we shouldn't
        # force honitsu with this hand
        tiles = self._string_to_136_array(sou='12355', pin='238', honors='22666')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), False)

        # if we have a complete set with dora, we shouldn't go for honitsu
        tiles = self._string_to_136_array(sou='11123688', pin='123', honors='55')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), False)

        # even if the set may be interpreted as two forms
        tiles = self._string_to_136_array(sou='1223688', pin='2334', honors='55')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), False)

        # even if the set may be interpreted as two forms v2
        tiles = self._string_to_136_array(sou='1223688', pin='2345', honors='55')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), False)

        # if we have a long form with dora, we shouldn't go for honitsu
        tiles = self._string_to_136_array(sou='1223688', pin='2333', honors='55')
        player.init_hand(tiles)
        self.assertEqual(strategy.should_activate_strategy(player.tiles), False)