def test_open_hand_withou_additional_fu(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(sou='23478', man='234567', pin='22') win_tile = self._string_to_136_tile(sou='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) melds = [self._make_meld(Meld.CHI, sou='234')] config = HandConfig(options=OptionalRules(fu_for_open_pinfu=False)) fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config, melds=melds) self.assertEqual(1, len(fu_details)) self.assertTrue({'fu': 20, 'reason': FuCalculator.BASE} in fu_details) self.assertEqual(fu, 20)
def test_penchan_fu(self): fu_calculator = FuCalculator() config = HandConfig() # 1-2-... wait tiles = self._string_to_136_array(sou='12456', man='123456', pin='55') win_tile = self._string_to_136_tile(sou='3') hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 30, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 2, 'reason': FuCalculator.PENCHAN} in fu_details) self.assertEqual(fu, 40) # ...-8-9 wait tiles = self._string_to_136_array(sou='34589', man='123456', pin='55') win_tile = self._string_to_136_tile(sou='7') hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 30, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 2, 'reason': FuCalculator.PENCHAN} in fu_details) self.assertEqual(fu, 40)
async def read_item(winning_tile: str, man_tile: str = None, pin_tile: str = None, sou_tile: str = None): calculator = HandCalculator() # アガリ形(man=マンズ, pin=ピンズ, sou=ソーズ, honors=字牌) tiles = TilesConverter.string_to_136_array(man=man_tile, pin=pin_tile, sou=sou_tile) # アガリ牌(ソーズの5) win_tile = TilesConverter.string_to_136_array(sou=winning_tile)[0] # 鳴き(チー:CHI, ポン:PON, カン:KAN(True:ミンカン,False:アンカン), カカン:CHANKAN, ヌキドラ:NUKI) melds = None # ドラ(なし) dora_indicators = None # オプション(なし) config = HandConfig(is_tsumo=True) result = calculator.estimate_hand_value(tiles, win_tile, melds, dora_indicators, config) return { "result_main": result.cost['main'], "result_additional": result.cost['additional'], "yaku": result.yaku }
def check_get_point_subfunc(self, now_closehand, new_card, now_openhand, now_open_cnt, now_reach, now_reach_b, now_combo, now_wind, now_selfwind, now_dora): #import mahjong closehand = [i for i in range(136) if now_closehand[i] == 1] melds = get_melds(now_openhand, now_open_cnt) for m in melds: for tile in m.tiles: closehand.append(tile) dora = [i for i in range(136) if now_dora[i][0] == 1] wind = [i for i in range(136) if now_wind[i][0] == 1][0] // 4 selfwind = [i for i in range(136) if now_selfwind[i][0] == 1][0] // 4 calculator = HandCalculator() result = calculator.estimate_hand_value( closehand, new_card, melds, dora, HandConfig(is_tsumo=True, is_riichi=(now_reach == 1), kyoutaku_number=now_reach_b, tsumi_number=now_combo, player_wind=selfwind, round_wind=wind, options=tenhou_option)) if result.cost: return result.cost['total'] else: return 0
def hand_calculator(tiles, win_tile, config=HandConfig()): calculator = HandCalculator() tiles = TilesConverter.one_line_string_to_136_array(str(tiles), has_aka_dora=True) win_tile = TilesConverter.one_line_string_to_136_array( str(win_tile), has_aka_dora=True)[0] return calculator.estimate_hand_value(tiles, win_tile, config=config)
def test_penchan_fu(self): fu_calculator = FuCalculator() config = HandConfig() # 1-2-... wait tiles = self._string_to_136_array(sou="12456", man="123456", pin="55") win_tile = self._string_to_136_tile(sou="3") hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu( hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({"fu": 30, "reason": FuCalculator.BASE} in fu_details) self.assertTrue({ "fu": 2, "reason": FuCalculator.PENCHAN } in fu_details) self.assertEqual(fu, 40) # ...-8-9 wait tiles = self._string_to_136_array(sou="34589", man="123456", pin="55") win_tile = self._string_to_136_tile(sou="7") hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu( hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({"fu": 30, "reason": FuCalculator.BASE} in fu_details) self.assertTrue({ "fu": 2, "reason": FuCalculator.PENCHAN } in fu_details) self.assertEqual(fu, 40)
def _read_config(self): config = configparser.ConfigParser() config.read(self.path_config) handconfig = HandConfig( is_tsumo=eval(config.get(self.section, 'is_tsumo')), is_riichi=eval(config.get(self.section, 'is_riichi')), is_ippatsu=eval(config.get(self.section, 'is_ippatsu')), is_rinshan=eval(config.get(self.section, 'is_rinshan')), is_chankan=eval(config.get(self.section, 'is_chankan')), is_haitei=eval(config.get(self.section, 'is_haitei')), is_houtei=eval(config.get(self.section, 'is_houtei')), is_daburu_riichi=eval(config.get(self.section, 'is_daburu_riichi')), is_nagashi_mangan=eval( config.get(self.section, 'is_nagashi_mangan')), is_tenhou=eval(config.get(self.section, 'is_tenhou')), is_renhou=eval(config.get(self.section, 'is_renhou')), is_chiihou=eval(config.get(self.section, 'is_chiihou')), player_wind=eval(config.get(self.section, 'player_wind')), round_wind=eval(config.get(self.section, 'round_wind')), has_open_tanyao=eval(config.get(self.section, 'has_open_tanyao')), has_aka_dora=eval(config.get(self.section, 'has_aka_dora')), disable_double_yakuman=eval( config.get(self.section, 'disable_double_yakuman')), kazoe=eval(config.get(self.section, 'kazoe')), kiriage=eval(config.get(self.section, 'kiriage')), fu_for_open_pinfu=eval( config.get(self.section, 'fu_for_open_pinfu')), fu_for_pinfu_tsumo=eval( config.get(self.section, 'fu_for_pinfu_tsumo'))) return handconfig
def check_pinfu(man, pin, sou, honors, player_wind, round_wind, win_tile_type, win_tile_value): calculator = HandCalculator() tiles = TilesConverter.string_to_136_array(man=man, pin=pin, sou=sou, honors=honors) print(tiles) win_tile = TilesConverter.string_to_136_array( **{win_tile_type: win_tile_value})[0] config = HandConfig(player_wind=player_wind, round_wind=round_wind) result = calculator.estimate_hand_value(tiles, win_tile, config=config) if result.yaku is not None: for yaku in result.yaku: if yaku.name == "Pinfu": cost = 1500 if config.is_dealer else 1000 return [ json.dumps({ 'isPinfu': True, 'cost': cost }).encode("utf-8") ] return [json.dumps({'isPinfu': False, 'cost': 0}).encode("utf-8")]
def test_closed_pon_fu(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(sou='22278', man='123456', pin='11') win_tile = self._string_to_136_tile(sou='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu( hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 30, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({ 'fu': 4, 'reason': FuCalculator.CLOSED_PON } in fu_details) self.assertEqual(fu, 40) # when we ron on the third pon tile we consider pon as open tiles = self._string_to_136_array(sou='22678', man='123456', pin='11') win_tile = self._string_to_136_tile(sou='2') hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu( hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 30, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({ 'fu': 2, 'reason': FuCalculator.OPEN_PON } in fu_details) self.assertEqual(fu, 40)
def test_closed_terminal_pon_fu(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(sou="11178", man="123456", pin="11") win_tile = self._string_to_136_tile(sou="6") hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu( hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({"fu": 30, "reason": FuCalculator.BASE} in fu_details) self.assertTrue({ "fu": 8, "reason": FuCalculator.CLOSED_TERMINAL_PON } in fu_details) self.assertEqual(fu, 40) # when we ron on the third pon tile we consider pon as open tiles = self._string_to_136_array(sou="11678", man="123456", pin="11") win_tile = self._string_to_136_tile(sou="1") hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu( hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({"fu": 30, "reason": FuCalculator.BASE} in fu_details) self.assertTrue({ "fu": 4, "reason": FuCalculator.OPEN_TERMINAL_PON } in fu_details) self.assertEqual(fu, 40)
def test_valued_pair_fu(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(sou='12378', man='123456', honors='11') win_tile = self._string_to_136_tile(sou='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) valued_tiles = [EAST] fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config, valued_tiles=valued_tiles,) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 30, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 2, 'reason': FuCalculator.VALUED_PAIR} in fu_details) self.assertEqual(fu, 40) # double valued pair valued_tiles = [EAST, EAST] fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config, valued_tiles=valued_tiles) self.assertEqual(3, len(fu_details)) self.assertTrue({'fu': 30, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 2, 'reason': FuCalculator.VALUED_PAIR} in fu_details) self.assertEqual(fu, 40)
def estimate_hand_value(self, win_tile, tiles=None, call_riichi=False): """ :param win_tile: 34 tile format :param tiles: :param call_riichi: :return: """ win_tile *= 4 # we don't need to think, that our waiting is aka dora if win_tile in AKA_DORA_LIST: win_tile += 1 if not tiles: tiles = self.player.tiles tiles += [win_tile] config = HandConfig(is_riichi=call_riichi, player_wind=self.player.player_wind, round_wind=self.player.table.round_wind, has_aka_dora=self.player.table.has_aka_dora, has_open_tanyao=self.player.table.has_open_tanyao) result = self.finished_hand.estimate_hand_value( tiles, win_tile, self.player.melds, self.player.table.dora_indicators, config) return result
def get_score_d(self, player, who_discard): now_closehand = [ 1 if self.closehand[player][0][i][0] == 1 else 0 for i in range(136) ] now_close_cnt = 0 for i in range(136): if now_closehand[i]: now_close_cnt += 1 now_openhand = self.openhand[player] now_open_cnt = self.open_cnt[player] now_reach = 0 for i in range(136): if self.reach[player][0][i][0] == 1: now_reach = 1 now_wind = self.wind[0] now_selfwind = self.selfwind[player][0] now_card = self.last_card if player != who_discard: now_closehand[now_card] = 1 #import mahjong closehand = [i for i in range(136) if now_closehand[i] == 1] melds = get_melds(now_openhand, now_open_cnt) for m in melds: for tile in m.tiles: closehand.append(tile) now_dora = self.dora[0] dora = [i for i in range(136) if now_dora[i][0] == 1] wind = [i for i in range(136) if now_wind[i][0] == 1][0] // 4 selfwind = [i for i in range(136) if now_selfwind[i][0] == 1][0] // 4 calculator = HandCalculator() result = calculator.estimate_hand_value( closehand, now_card, melds, dora, HandConfig(is_tsumo=(player == who_discard), is_riichi=(now_reach == 1), player_wind=selfwind, round_wind=wind, options=tenhou_option)) score_d = [0, 0, 0, 0] if result.cost is None: return score_d else: self.reach_b = 0 wd = wind - 27 - player if wd < 0: wd += 4 if player == who_discard: for i in range(4): if i == player: score_d[i] = result.cost['total'] // 100 else: if (wd + player) % 4 == 0: score_d[i] = -result.cost['main_bonus'] // 100 else: score_d[ i] = -result.cost['additional_bonus'] // 100 else: score_d[player] = result.cost['total'] // 100 score_d[who_discard] = -result.cost['main_bonus'] // 100
def test_calculate_scores_and_tsumo(self): hand = ScoresCalculator() config = HandConfig(is_tsumo=True, options=OptionalRules(kazoe_limit=HandConfig.KAZOE_NO_LIMIT)) result = hand.calculate_scores(han=1, fu=30, config=config) self.assertEqual(result['main'], 500) self.assertEqual(result['additional'], 300) result = hand.calculate_scores(han=3, fu=30, config=config) self.assertEqual(result['main'], 2000) self.assertEqual(result['additional'], 1000) result = hand.calculate_scores(han=3, fu=60, config=config) self.assertEqual(result['main'], 3900) self.assertEqual(result['additional'], 2000) result = hand.calculate_scores(han=4, fu=30, config=config) self.assertEqual(result['main'], 3900) self.assertEqual(result['additional'], 2000) result = hand.calculate_scores(han=5, fu=0, config=config) self.assertEqual(result['main'], 4000) self.assertEqual(result['additional'], 2000) result = hand.calculate_scores(han=6, fu=0, config=config) self.assertEqual(result['main'], 6000) self.assertEqual(result['additional'], 3000) result = hand.calculate_scores(han=8, fu=0, config=config) self.assertEqual(result['main'], 8000) self.assertEqual(result['additional'], 4000) result = hand.calculate_scores(han=11, fu=0, config=config) self.assertEqual(result['main'], 12000) self.assertEqual(result['additional'], 6000) result = hand.calculate_scores(han=13, fu=0, config=config) self.assertEqual(result['main'], 16000) self.assertEqual(result['additional'], 8000) result = hand.calculate_scores(han=26, fu=0, config=config) self.assertEqual(result['main'], 32000) self.assertEqual(result['additional'], 16000) result = hand.calculate_scores(han=39, fu=0, config=config) self.assertEqual(result['main'], 48000) self.assertEqual(result['additional'], 24000) result = hand.calculate_scores(han=52, fu=0, config=config) self.assertEqual(result['main'], 64000) self.assertEqual(result['additional'], 32000) result = hand.calculate_scores(han=65, fu=0, config=config) self.assertEqual(result['main'], 80000) self.assertEqual(result['additional'], 40000) result = hand.calculate_scores(han=78, fu=0, config=config) self.assertEqual(result['main'], 96000) self.assertEqual(result['additional'], 48000)
def test_calculate_scores_and_tsumo_by_dealer(self): hand = ScoresCalculator() config = HandConfig( player_wind=EAST, is_tsumo=True, options=OptionalRules(kazoe_limit=HandConfig.KAZOE_NO_LIMIT)) result = hand.calculate_scores(han=1, fu=30, config=config) self.assertEqual(result["main"], 500) self.assertEqual(result["additional"], 500) result = hand.calculate_scores(han=3, fu=30, config=config) self.assertEqual(result["main"], 2000) self.assertEqual(result["additional"], 2000) result = hand.calculate_scores(han=4, fu=30, config=config) self.assertEqual(result["main"], 3900) self.assertEqual(result["additional"], 3900) result = hand.calculate_scores(han=5, fu=0, config=config) self.assertEqual(result["main"], 4000) self.assertEqual(result["additional"], 4000) result = hand.calculate_scores(han=6, fu=0, config=config) self.assertEqual(result["main"], 6000) self.assertEqual(result["additional"], 6000) result = hand.calculate_scores(han=8, fu=0, config=config) self.assertEqual(result["main"], 8000) self.assertEqual(result["additional"], 8000) result = hand.calculate_scores(han=11, fu=0, config=config) self.assertEqual(result["main"], 12000) self.assertEqual(result["additional"], 12000) result = hand.calculate_scores(han=13, fu=0, config=config) self.assertEqual(result["main"], 16000) self.assertEqual(result["additional"], 16000) result = hand.calculate_scores(han=26, fu=0, config=config) self.assertEqual(result["main"], 32000) self.assertEqual(result["additional"], 32000) result = hand.calculate_scores(han=39, fu=0, config=config) self.assertEqual(result["main"], 48000) self.assertEqual(result["additional"], 48000) result = hand.calculate_scores(han=52, fu=0, config=config) self.assertEqual(result["main"], 64000) self.assertEqual(result["additional"], 64000) result = hand.calculate_scores(han=65, fu=0, config=config) self.assertEqual(result["main"], 80000) self.assertEqual(result["additional"], 80000) result = hand.calculate_scores(han=78, fu=0, config=config) self.assertEqual(result["main"], 96000) self.assertEqual(result["additional"], 96000)
def test_kiriage_mangan(self): hand = ScoresCalculator() config = HandConfig(options=OptionalRules(kiriage=True)) result = hand.calculate_scores(han=4, fu=30, config=config) self.assertEqual(result['main'], 8000) result = hand.calculate_scores(han=3, fu=60, config=config) self.assertEqual(result['main'], 8000) config = HandConfig(player_wind=EAST, options=OptionalRules(kiriage=True)) result = hand.calculate_scores(han=4, fu=30, config=config) self.assertEqual(result['main'], 12000) result = hand.calculate_scores(han=3, fu=60, config=config) self.assertEqual(result['main'], 12000)
def test_calculate_scores_with_bonus(self): hand = ScoresCalculator() config = HandConfig(player_wind=EAST, is_tsumo=True, tsumi_number=2, kyoutaku_number=3) result = hand.calculate_scores(han=3, fu=30, config=config) self.assertEqual(result["main"], 2000) self.assertEqual(result["additional"], 2000) self.assertEqual(result["main_bonus"], 200) self.assertEqual(result["additional_bonus"], 200) self.assertEqual(result["kyoutaku_bonus"], 3000) self.assertEqual(result["total"], 9600) config = HandConfig(player_wind=WEST, is_tsumo=True, tsumi_number=4, kyoutaku_number=1) result = hand.calculate_scores(han=4, fu=30, config=config) self.assertEqual(result["main"], 3900) self.assertEqual(result["additional"], 2000) self.assertEqual(result["main_bonus"], 400) self.assertEqual(result["additional_bonus"], 400) self.assertEqual(result["kyoutaku_bonus"], 1000) self.assertEqual(result["total"], 10100) config = HandConfig(player_wind=WEST, tsumi_number=5) result = hand.calculate_scores(han=6, fu=30, config=config) self.assertEqual(result["main"], 12000) self.assertEqual(result["additional"], 0) self.assertEqual(result["main_bonus"], 1500) self.assertEqual(result["additional_bonus"], 0) self.assertEqual(result["kyoutaku_bonus"], 0) self.assertEqual(result["total"], 13500) config = HandConfig(player_wind=EAST, tsumi_number=5) result = hand.calculate_scores(han=5, fu=30, config=config) self.assertEqual(result["main"], 12000) self.assertEqual(result["additional"], 0) self.assertEqual(result["main_bonus"], 1500) self.assertEqual(result["additional_bonus"], 0) self.assertEqual(result["kyoutaku_bonus"], 0) self.assertEqual(result["total"], 13500)
def test_incorrect_fu_calculation_test_case_2(self): calculator = HandCalculator() tiles = self._string_to_136_array(pin="555", man="11112233444") melds = [self._make_meld(Meld.CHI, man="123")] win_tile = self._string_to_136_tile(man="1") result = calculator.estimate_hand_value( tiles, win_tile, melds=melds, config=HandConfig(is_houtei=True)) self.assertEqual(result.fu, 30)
def __init__(self, tiles, dora_indicators, revealed_tiles): self.tiles = tiles self.Shanten_calculater = Shanten() self.Hand_Calculator = HandCalculator() self.Tiles = TilesConverter() self.shanten = self.Shanten_calculater.calculate_shanten( self.Tiles.to_34_array(self.tiles)) self.Hand_Config = HandConfig(is_riichi=True) self.dora_indicators = dora_indicators self.revealed_tiles = revealed_tiles
def test_tsumo_hand_base(self): fu_calculator = FuCalculator() config = HandConfig(is_tsumo=True) tiles = self._string_to_136_array(sou='22278', man='123456', pin='11') win_tile = self._string_to_136_tile(sou='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, _ = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertTrue({'fu': 20, 'reason': FuCalculator.BASE} in fu_details)
def test_tsumo_hand_base(self): fu_calculator = FuCalculator() config = HandConfig(is_tsumo=True) tiles = self._string_to_136_array(sou="22278", man="123456", pin="11") win_tile = self._string_to_136_tile(sou="6") hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, _ = fu_calculator.calculate_fu( hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertTrue({"fu": 20, "reason": FuCalculator.BASE} in fu_details)
def test_calculate_scores_and_ron(self): hand = ScoresCalculator() config = HandConfig(options=OptionalRules( kazoe_limit=HandConfig.KAZOE_NO_LIMIT)) result = hand.calculate_scores(han=1, fu=30, config=config) self.assertEqual(result['main'], 1000) result = hand.calculate_scores(han=1, fu=110, config=config) self.assertEqual(result['main'], 3600) result = hand.calculate_scores(han=2, fu=30, config=config) self.assertEqual(result['main'], 2000) result = hand.calculate_scores(han=3, fu=30, config=config) self.assertEqual(result['main'], 3900) result = hand.calculate_scores(han=4, fu=30, config=config) self.assertEqual(result['main'], 7700) result = hand.calculate_scores(han=4, fu=40, config=config) self.assertEqual(result['main'], 8000) result = hand.calculate_scores(han=5, fu=0, config=config) self.assertEqual(result['main'], 8000) result = hand.calculate_scores(han=6, fu=0, config=config) self.assertEqual(result['main'], 12000) result = hand.calculate_scores(han=8, fu=0, config=config) self.assertEqual(result['main'], 16000) result = hand.calculate_scores(han=11, fu=0, config=config) self.assertEqual(result['main'], 24000) result = hand.calculate_scores(han=13, fu=0, config=config) self.assertEqual(result['main'], 32000) result = hand.calculate_scores(han=26, fu=0, config=config) self.assertEqual(result['main'], 64000) result = hand.calculate_scores(han=39, fu=0, config=config) self.assertEqual(result['main'], 96000) result = hand.calculate_scores(han=52, fu=0, config=config) self.assertEqual(result['main'], 128000) result = hand.calculate_scores(han=65, fu=0, config=config) self.assertEqual(result['main'], 160000) result = hand.calculate_scores(han=78, fu=0, config=config) self.assertEqual(result['main'], 192000)
def test_pair_wait_fu(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(sou='123678', man='123456', pin='1') win_tile = self._string_to_136_tile(pin='1') hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 30, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 2, 'reason': FuCalculator.PAIR_WAIT} in fu_details) self.assertEqual(fu, 40)
def test_tsumo_hand_and_disabled_pinfu(self): fu_calculator = FuCalculator() config = HandConfig(is_tsumo=True, options=OptionalRules(fu_for_pinfu_tsumo=True)) tiles = self._string_to_136_array(sou='2278', man='123456', pin='123') win_tile = self._string_to_136_tile(sou='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 20, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 2, 'reason': FuCalculator.TSUMO} in fu_details) self.assertEqual(fu, 30)
def score(args): win_tile = to_tiles(args['winTile'])[0] tiles = to_tiles(args['tiles']) melds = [] for i in args['melds']: if i['type'] == 'chi': melds.append(Meld(Meld.CHI, tiles=to_tiles(i), opened=i['opened'])) elif i['type'] == 'pon': melds.append(Meld(Meld.PON, tiles=to_tiles(i), opened=i['opened'])) elif i['type'] == 'kan': melds.append(Meld(Meld.KAN, tiles=to_tiles(i), opened=i['opened'])) elif i['type'] == 'chankan': melds.append( Meld(Meld.CHANKAN, tiles=to_tiles(i), opened=i['opened'])) elif i['type'] == 'nuki': melds.append(Meld(Meld.NUKI, tiles=to_tiles(i), opened=i['opened'])) dora_ind = [] for i in args['doraIndicators']: dora_ind.append(to_tiles(i)[0]) options = args['options'] config = HandConfig(player_wind=options['playerWind'], round_wind=options['roundWind'], is_tsumo=options['isTsumo'], is_riichi=options['isRiichi'], is_daburu_riichi=options['isDoubleRiichi'], is_ippatsu=options['isIppatsu'], is_rinshan=options['isRinshan'], is_chankan=options['isChankan'], is_haitei=options['isHaitei'], is_houtei=options['isHoutei'], is_nagashi_mangan=options['isNagashiMangan'], is_tenhou=options['isTenhou'], is_renhou=options['isRenhou'], is_chiihou=options['isChiihou']) result = calculator.estimate_hand_value(tiles, win_tile, melds=melds, dora_indicators=dora_ind, config=config) opened = False for i in melds: if i.opened: opened = True return result, opened
def main(): hand = random.choice(questions) round_wind, player_wind = get_random_kaze_set() tiles = TilesConverter.string_to_136_array( man=hand.get_man(), pin=hand.get_pin(), sou=hand.get_sou()) win_tile = TilesConverter.string_to_136_array( **hand.get_win_tile())[0] conf = { 'is_tsumo': get_is_or_not(), 'is_riichi': get_is_or_not(), 'player_wind': player_wind, 'round_wind': round_wind } config = HandConfig(**conf) result = calculator.estimate_hand_value(tiles, win_tile, config=config) question_caption = '\n' if config.is_tsumo: question_caption += f"ツモ:{hand.get_win_tile_figure()} " else: question_caption += f"ロン:{hand.get_win_tile_figure()} " if config.is_riichi: question_caption += 'リーチ有 ' else: question_caption += 'リーチ無 ' question_caption += f"場風: {DISPLAY_WINDS_JP[config.round_wind]} 自風: {DISPLAY_WINDS_JP[config.player_wind]}" print(hand.get_figure()) print(question_caption) if config.is_tsumo and config.player_wind == EAST: child_answer = int(input('子の支払う点数: ')) if child_answer == result.cost['main']: print('正解!!') else: print(f"不正解!! 正解は {result.cost['main']} オール") elif config.is_tsumo and config.player_wind != EAST: parent_answer = int(input('親の支払う点数: ')) child_answer = int(input('子の支払う点数: ')) if parent_answer == result.cost['main'] and child_answer == result.cost['additional']: print('正解!!') else: print( f"不正解!! 正解は 親: {result.cost['main']}, 子: {result.cost['additional']}") else: answer = int(input('放銃者の支払う点数: ')) if answer == result.cost['main']: print('正解!!') else: print(f"不正解!! 正解は {result.cost['main']}")
def test_open_terminal_kan_fu(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(sou='2278', man='123456', pin='111') win_tile = self._string_to_136_tile(sou='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) melds = [self._make_meld(Meld.KAN, pin='111', is_open=True)] fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config, melds=melds) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 20, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 16, 'reason': FuCalculator.OPEN_TERMINAL_KAN} in fu_details) self.assertEqual(fu, 40)
def test_open_hand_base(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(sou='22278', man='123456', pin='11') win_tile = self._string_to_136_tile(sou='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) melds = [self._make_meld(Meld.PON, sou='222')] fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, self._get_win_group(hand, win_tile), config, melds=melds) self.assertEqual(2, len(fu_details)) self.assertTrue({'fu': 20, 'reason': FuCalculator.BASE} in fu_details) self.assertTrue({'fu': 2, 'reason': FuCalculator.OPEN_PON} in fu_details) self.assertEqual(fu, 30)
def test_calculate_scores_and_ron_by_dealer(self): hand = ScoresCalculator() config = HandConfig( player_wind=EAST, options=OptionalRules(kazoe_limit=HandConfig.KAZOE_NO_LIMIT)) result = hand.calculate_scores(han=1, fu=30, config=config) self.assertEqual(result['main'], 1500) result = hand.calculate_scores(han=2, fu=30, config=config) self.assertEqual(result['main'], 2900) result = hand.calculate_scores(han=3, fu=30, config=config) self.assertEqual(result['main'], 5800) result = hand.calculate_scores(han=4, fu=30, config=config) self.assertEqual(result['main'], 11600) result = hand.calculate_scores(han=5, fu=0, config=config) self.assertEqual(result['main'], 12000) result = hand.calculate_scores(han=6, fu=0, config=config) self.assertEqual(result['main'], 18000) result = hand.calculate_scores(han=8, fu=0, config=config) self.assertEqual(result['main'], 24000) result = hand.calculate_scores(han=11, fu=0, config=config) self.assertEqual(result['main'], 36000) result = hand.calculate_scores(han=13, fu=0, config=config) self.assertEqual(result['main'], 48000) result = hand.calculate_scores(han=26, fu=0, config=config) self.assertEqual(result['main'], 96000) result = hand.calculate_scores(han=39, fu=0, config=config) self.assertEqual(result['main'], 144000) result = hand.calculate_scores(han=52, fu=0, config=config) self.assertEqual(result['main'], 192000) result = hand.calculate_scores(han=65, fu=0, config=config) self.assertEqual(result['main'], 240000) result = hand.calculate_scores(han=78, fu=0, config=config) self.assertEqual(result['main'], 288000)
def test_fu_based_on_win_group(self): fu_calculator = FuCalculator() config = HandConfig() tiles = self._string_to_136_array(man='234789', pin='1234566') win_tile = self._string_to_136_tile(pin='6') hand = self._hand(self._to_34_array(tiles + [win_tile])) win_groups = [x for x in hand if win_tile // 4 in x] # pinfu wait 4-5-6 fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, win_groups[0], config) self.assertEqual(fu, 30) # pair wait 66 fu_details, fu = fu_calculator.calculate_fu(hand, win_tile, win_groups[1], config) self.assertEqual(fu, 40)