示例#1
0
    def is_condition_met(self, hand, player_wind, round_wind, *args):
        if len([x for x in hand if is_pon_or_kan(x) and x[0] == player_wind]) == 1 and player_wind == WEST:
            return True

        if len([x for x in hand if is_pon_or_kan(x) and x[0] == round_wind]) == 1 and round_wind == WEST:
            return True

        return False
示例#2
0
    def is_condition_met(self, hand, win_tile, is_tsumo):
        win_tile //= 4
        closed_hand = []
        for item in hand:
            # if we do the ron on syanpon wait our pon will be consider as open
            if is_pon_or_kan(item) and win_tile in item and not is_tsumo:
                continue

            closed_hand.append(item)

        count_of_pon = len([i for i in closed_hand if is_pon_or_kan(i)])
        return count_of_pon == 4
示例#3
0
    def is_condition_met(self, hand, win_tile, melds, is_tsumo):
        """
        Three closed pon sets, the other sets need not to be closed
        :param hand: list of hand's sets
        :param win_tile: 136 tiles format
        :param melds: list Meld objects
        :param is_tsumo:
        :return: true|false
        """
        win_tile //= 4

        open_sets = [x.tiles_34 for x in melds if x.opened]

        chi_sets = [x for x in hand if (is_chi(x) and win_tile in x and x not in open_sets)]
        pon_sets = [x for x in hand if is_pon_or_kan(x)]

        closed_pon_sets = []
        for item in pon_sets:
            if item in open_sets:
                continue

            # if we do the ron on syanpon wait our pon will be consider as open
            # and it is not 789999 set
            if win_tile in item and not is_tsumo and not len(chi_sets):
                continue

            closed_pon_sets.append(item)

        return len(closed_pon_sets) == 3
示例#4
0
    def is_condition_met(self, hand, *args):
        pon_sets = [i for i in hand if is_pon_or_kan(i)]
        if len(pon_sets) < 3:
            return False

        sou_pon = []
        pin_pon = []
        man_pon = []
        for item in pon_sets:
            if is_sou(item[0]):
                sou_pon.append(item)
            elif is_pin(item[0]):
                pin_pon.append(item)
            elif is_man(item[0]):
                man_pon.append(item)

        for sou_item in sou_pon:
            for pin_item in pin_pon:
                for man_item in man_pon:
                    # cast tile indices to 1..9 representation
                    sou_item = set([simplify(x) for x in sou_item])
                    pin_item = set([simplify(x) for x in pin_item])
                    man_item = set([simplify(x) for x in man_item])
                    if sou_item == pin_item == man_item:
                        return True
        return False
示例#5
0
    def is_condition_met(self, hand, *args):
        pon_sets = [x for x in hand if is_pon_or_kan(x)]
        if len(pon_sets) < 3:
            return False

        count_of_wind_sets = 0
        wind_pair = 0
        winds = [EAST, SOUTH, WEST, NORTH]
        for item in hand:
            if is_pon_or_kan(item) and item[0] in winds:
                count_of_wind_sets += 1

            if is_pair(item) and item[0] in winds:
                wind_pair += 1

        return count_of_wind_sets == 3 and wind_pair == 1
示例#6
0
    def is_condition_met(self, hand, *args):
        """
        The hand contains four sets of winds
        :param hand: list of hand's sets
        :return: boolean
        """
        pon_sets = [x for x in hand if is_pon_or_kan(x)]
        if len(pon_sets) != 4:
            return False

        count_wind_sets = 0
        winds = [EAST, SOUTH, WEST, NORTH]
        for item in pon_sets:
            if is_pon_or_kan(item) and item[0] in winds:
                count_wind_sets += 1

        return count_wind_sets == 4
示例#7
0
    def is_condition_met(self, hand, *args):
        dragons = [CHUN, HAKU, HATSU]
        count_of_conditions = 0
        for item in hand:
            # dragon pon or pair
            if (is_pair(item) or is_pon_or_kan(item)) and item[0] in dragons:
                count_of_conditions += 1

        return count_of_conditions == 3
示例#8
0
 def is_condition_met(self, hand, *args):
     return len([x for x in hand
                 if is_pon_or_kan(x) and x[0] == HATSU]) == 1
示例#9
0
    def calculate_fu(
        self,
        hand,
        win_tile,
        win_group,
        config,
        valued_tiles=None,
        melds=None,
    ):
        """
        Calculate hand fu with explanations
        :param hand:
        :param win_tile: 136 tile format
        :param win_group: one set where win tile exists
        :param config: HandConfig object
        :param valued_tiles: dragons, player wind, round wind
        :param melds: opened sets
        :return:
        """

        win_tile_34 = win_tile // 4

        if not valued_tiles:
            valued_tiles = []

        if not melds:
            melds = []

        fu_details = []

        if len(hand) == 7:
            return [{"fu": 25, "reason": FuCalculator.BASE}], 25

        pair = [x for x in hand if is_pair(x)][0]
        pon_sets = [x for x in hand if is_pon_or_kan(x)]

        copied_opened_melds = [x.tiles_34 for x in melds if x.type == Meld.CHI]
        closed_chi_sets = []
        for x in hand:
            if x not in copied_opened_melds:
                closed_chi_sets.append(x)
            else:
                copied_opened_melds.remove(x)

        is_open_hand = any([x.opened for x in melds])

        if win_group in closed_chi_sets:
            tile_index = simplify(win_tile_34)

            # penchan
            if contains_terminals(win_group):
                # 1-2-... wait
                if tile_index == 2 and win_group.index(win_tile_34) == 2:
                    fu_details.append({
                        "fu": 2,
                        "reason": FuCalculator.PENCHAN
                    })
                # 8-9-... wait
                elif tile_index == 6 and win_group.index(win_tile_34) == 0:
                    fu_details.append({
                        "fu": 2,
                        "reason": FuCalculator.PENCHAN
                    })

            # kanchan waiting 5-...-7
            if win_group.index(win_tile_34) == 1:
                fu_details.append({"fu": 2, "reason": FuCalculator.KANCHAN})

        # valued pair
        count_of_valued_pairs = valued_tiles.count(pair[0])
        if count_of_valued_pairs == 1:
            fu_details.append({"fu": 2, "reason": FuCalculator.VALUED_PAIR})

        # east-east pair when you are on east gave double fu
        if count_of_valued_pairs == 2:
            fu_details.append({
                "fu": 4,
                "reason": FuCalculator.DOUBLE_VALUED_PAIR
            })

        # pair wait
        if is_pair(win_group):
            fu_details.append({"fu": 2, "reason": FuCalculator.PAIR_WAIT})

        for set_item in pon_sets:
            open_meld = [x for x in melds if set_item == x.tiles_34]
            open_meld = open_meld and open_meld[0] or None

            set_was_open = open_meld and open_meld.opened or False
            is_kan_set = (open_meld and
                          (open_meld.type == Meld.KAN
                           or open_meld.type == Meld.SHOUMINKAN)) or False
            is_honor = set_item[0] in TERMINAL_INDICES + HONOR_INDICES

            # we win by ron on the third pon tile, our pon will be count as open
            if not config.is_tsumo and set_item == win_group:
                set_was_open = True

            if is_honor:
                if is_kan_set:
                    if set_was_open:
                        fu_details.append({
                            "fu":
                            16,
                            "reason":
                            FuCalculator.OPEN_TERMINAL_KAN
                        })
                    else:
                        fu_details.append({
                            "fu":
                            32,
                            "reason":
                            FuCalculator.CLOSED_TERMINAL_KAN
                        })
                else:
                    if set_was_open:
                        fu_details.append({
                            "fu":
                            4,
                            "reason":
                            FuCalculator.OPEN_TERMINAL_PON
                        })
                    else:
                        fu_details.append({
                            "fu":
                            8,
                            "reason":
                            FuCalculator.CLOSED_TERMINAL_PON
                        })
            else:
                if is_kan_set:
                    if set_was_open:
                        fu_details.append({
                            "fu": 8,
                            "reason": FuCalculator.OPEN_KAN
                        })
                    else:
                        fu_details.append({
                            "fu": 16,
                            "reason": FuCalculator.CLOSED_KAN
                        })
                else:
                    if set_was_open:
                        fu_details.append({
                            "fu": 2,
                            "reason": FuCalculator.OPEN_PON
                        })
                    else:
                        fu_details.append({
                            "fu": 4,
                            "reason": FuCalculator.CLOSED_PON
                        })

        add_tsumo_fu = len(fu_details) > 0 or config.options.fu_for_pinfu_tsumo

        if config.is_tsumo and add_tsumo_fu:
            # 2 additional fu for tsumo (but not for pinfu)
            fu_details.append({"fu": 2, "reason": FuCalculator.TSUMO})

        if is_open_hand and not len(
                fu_details) and config.options.fu_for_open_pinfu:
            # there is no 1-20 hands, so we had to add additional fu
            fu_details.append({
                "fu": 2,
                "reason": FuCalculator.HAND_WITHOUT_FU
            })

        if is_open_hand or config.is_tsumo:
            fu_details.append({"fu": 20, "reason": FuCalculator.BASE})
        else:
            fu_details.append({"fu": 30, "reason": FuCalculator.BASE})

        return fu_details, self.round_fu(fu_details)
示例#10
0
 def is_condition_met(self, hand, *args):
     count_of_dragon_pon_sets = 0
     for item in hand:
         if is_pon_or_kan(item) and item[0] in [CHUN, HAKU, HATSU]:
             count_of_dragon_pon_sets += 1
     return count_of_dragon_pon_sets == 3
示例#11
0
 def is_condition_met(self, hand, *args):
     count_of_pon = len([i for i in hand if is_pon_or_kan(i)])
     return count_of_pon == 4