Last active
July 2, 2020 13:26
-
-
Save hamukichi/58fba8acd3e034ec5ed542802a356846 to your computer and use it in GitHub Desktop.
Python 用ライブラリ mahjong を利用し,与えられた手牌について,和了していれば点数を計算し,さもなければ向聴数を計算する.鳴きには対応させていない(ライブラリ自体には機能が備わっている).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Hamukichi (Nombiri), MIT License | |
from mahjong import agari, constants, shanten, tile | |
from mahjong.hand_calculating import hand, hand_config | |
import fire | |
import copy | |
OPT_RULES = hand_config.OptionalRules(has_open_tanyao=True) | |
WIND_STR2CONST = {"EAST": constants.EAST, | |
"SOUTH": constants.SOUTH, | |
"WEST": constants.WEST, | |
"NORTH": constants.NORTH} | |
WIND_STR2CHARA = {"EAST": "東", | |
"SOUTH": "南", | |
"WEST": "西", | |
"NORTH": "北"} | |
def __analyze(all_tiles, win_tile, player_wind, round_wind, **hand_confs): | |
all_tiles_136 = tile.TilesConverter.one_line_string_to_136_array(all_tiles) | |
all_tiles_34 = tile.TilesConverter.one_line_string_to_34_array(all_tiles) | |
win_tile_136 = tile.TilesConverter.one_line_string_to_136_array(win_tile)[0] | |
player_wind = player_wind.upper() | |
round_wind = round_wind.upper() | |
player_wind_136 = WIND_STR2CONST[player_wind] | |
round_wind_136 = WIND_STR2CONST[round_wind] | |
all_hand_confs = copy.copy(hand_confs) | |
all_hand_confs["player_wind"] = player_wind_136 | |
all_hand_confs["round_wind"] = round_wind_136 | |
config = hand_config.HandConfig(options=OPT_RULES, **all_hand_confs) | |
sh_obj = shanten.Shanten() | |
sh_res = sh_obj.calculate_shanten(all_tiles_34) | |
ag = agari.Agari() | |
if not ag.is_agari(all_tiles_34): | |
return (sh_res, None) | |
else: | |
calc = hand.HandCalculator() | |
hand_res = calc.estimate_hand_value(tiles=all_tiles_136, | |
win_tile=win_tile_136, | |
config=config) | |
wind = "{}場{}".format(WIND_STR2CHARA[round_wind], WIND_STR2CHARA[player_wind]) | |
han_fu = "{} 飜 {} 符".format(hand_res.han, hand_res.fu) | |
if hand_res.han <= 5: | |
basic_score = hand_res.fu * 2 ** (hand_res.han + 2) | |
if basic_score > 2000: | |
gan = "満貫" | |
else: | |
gan = "" | |
elif hand_res.han <= 7: | |
gan = "跳満" | |
elif hand_res.han <= 10: | |
gan = "倍満" | |
elif hand_res.han <= 12: | |
gan = "三倍満" | |
else: | |
n = hand_res.han // 13 | |
if n == 1: | |
gan = "役満" | |
else: | |
gan = "{} 倍役満".format(n) | |
is_tsumo = hand_confs.get("is_tsumo", False) | |
is_dealer = player_wind == "EAST" | |
if hand_res.han < 1: | |
all_cost = "1 飜縛りを満たしていません" | |
elif is_tsumo: | |
if is_dealer: | |
all_cost = "{} 点 オール".format(hand_res.cost["additional"]) | |
else: | |
all_cost = "{} 点 / {} 点".format(hand_res.cost["additional"], | |
hand_res.cost["main"]) | |
else: | |
all_cost = "{} 点".format(hand_res.cost["main"]) | |
hand_report = {"hand_res": hand_res, "wind": wind, | |
"han_fu": han_fu, "gan": gan, "all_cost": all_cost, "yakus": hand_res.yaku} | |
return (sh_res, hand_report) | |
def analyze(all_tiles, win_tile, player_wind="SOUTH", round_wind="EAST", **hand_confs): | |
analyze_res = __analyze(all_tiles, win_tile, player_wind, round_wind, **hand_confs) | |
sh_res, hand_report = analyze_res | |
if hand_report is None: | |
if sh_res != 0: | |
print("{} 向聴".format(sh_res)) | |
else: | |
print("聴牌") | |
else: | |
print(hand_report["wind"]) | |
print(hand_report["han_fu"], end=" ") | |
print(hand_report["gan"]) | |
print(hand_report["all_cost"]) | |
if hand_report["yakus"] is not None: | |
for yaku in hand_report["yakus"]: | |
print(yaku.japanese) | |
def main(): | |
fire.Fire(analyze) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment