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