### Install mahjong with pip Source: https://github.com/mahjongrepository/mahjong/blob/master/README.md Install the mahjong library from PyPI. ```bash pip install mahjong ``` -------------------------------- ### Calculate shanten for regular, chiitoitsu, and kokushi hands Source: https://github.com/mahjongrepository/mahjong/wiki/v2-English Uses the mahjong library's Shanten class and TilesConverter to compute shanten for regular hands, tenpai, complete hands, chiitoitsu, and kokushi. The output shows the shanten values for each example. ```python from mahjong.shanten import Shanten from mahjong.tile import TilesConverter # regular hand, 2 shanten tiles = TilesConverter.string_to_34_array(man='13569', pin='123459', sou='443') print("Regular hand shanten:", Shanten.calculate_shanten(tiles)) # tenpai (0 shanten, one tile away from winning) tiles = TilesConverter.string_to_34_array(sou='111345677', pin='11', man='567') print("Tenpai hand:", Shanten.calculate_shanten(tiles)) # complete hand (-1 shanten, already winning) tiles = TilesConverter.string_to_34_array(sou='111234567', pin='11', man='567') print("Complete hand:", Shanten.calculate_shanten(tiles)) # calculate shanten for specific hand forms tiles = TilesConverter.string_to_34_array(sou='114477', pin='114477', man='76') print("Chiitoitsu shanten:", Shanten.calculate_shanten_for_chiitoitsu_hand(tiles)) tiles = TilesConverter.string_to_34_array(sou='129', pin='19', man='19', honors='1234567') print("Kokushi shanten:", Shanten.calculate_shanten_for_kokushi_hand(tiles)) ``` ```output Regular hand shanten: 2 Tenpai hand: 0 Complete hand: -1 Chiitoitsu shanten: 0 Kokushi shanten: 0 ``` -------------------------------- ### Agari.is_agari() usage with various hand types Source: https://github.com/mahjongrepository/mahjong/wiki/v2-English Checks if a hand is complete using Agari.is_agari(). The example tests regular, incomplete, seven pairs, thirteen orphans, and open hand with kan. The output shows True for complete hands and False for incomplete. The open_set parameter is used for open hands with kan melds. ```python from mahjong.agari import Agari from mahjong.tile import TilesConverter # complete hand: 123s 456s 789s 123p 33m tiles = TilesConverter.string_to_34_array(sou='123456789', pin='123', man='33') print("Regular hand:", Agari.is_agari(tiles)) # incomplete hand: 123s 456s 789s 12345p tiles = TilesConverter.string_to_34_array(sou='123456789', pin='12345') print("Incomplete hand:", Agari.is_agari(tiles)) # seven pairs (chiitoitsu): 1133557799s 1199p tiles = TilesConverter.string_to_34_array(sou='1133557799', pin='1199') print("Seven pairs:", Agari.is_agari(tiles)) # thirteen orphans (kokushi): 19s 19p 199m 1234567z tiles = TilesConverter.string_to_34_array(sou='19', pin='19', man='199', honors='1234567') print("Kokushi:", Agari.is_agari(tiles)) # open hand with kan meld: 1111m 123456789p 22s tiles = TilesConverter.string_to_34_array(man='1111', pin='123456789', sou='22') open_set = [0, 0, 0, 0] # kan of 1m (tile index 0 in 34-tile format) print("Open hand with kan:", Agari.is_agari(tiles, [open_set])) ``` ```text Regular hand: True Incomplete hand: False Seven pairs: True Kokushi: True Open hand with kan: True ``` -------------------------------- ### Set up environment with uv sync Source: https://github.com/mahjongrepository/mahjong/blob/master/README.md Set up the local development environment using uv. ```bash uv sync ``` -------------------------------- ### Clone the mahjong repository Source: https://github.com/mahjongrepository/mahjong/blob/master/README.md Clone the repository and navigate into the project directory. ```bash git clone https://github.com/MahjongRepository/mahjong.git cd mahjong ``` -------------------------------- ### Add open set with OptionalRules(has_open_tanyao=True) Source: https://github.com/mahjongrepository/mahjong/wiki/v2-English Adds an open pon of man 444 using Meld and enables open tanyao via OptionalRules(has_open_tanyao=True). Output shows 1 han, 30 fu, cost 1000, yaku [Tanyao], and fu details with open pon. ```python from mahjong.hand_calculating.hand_config import OptionalRules melds = [Meld(meld_type=Meld.PON, tiles=TilesConverter.string_to_136_array(man='444'))] result = HandCalculator.estimate_hand_value(tiles, win_tile, melds=melds, config=HandConfig(options=OptionalRules(has_open_tanyao=True))) print(result.han, result.fu) print(result.cost['main']) print(result.yaku) for fu_item in result.fu_details: print(fu_item) ``` ```text 1 30 1000 [Tanyao] {'fu': 20, 'reason': 'base'} {'fu': 4, 'reason': 'closed_pon'} {'fu': 2, 'reason': 'open_pon'} {'fu': 2, 'reason': 'open_pon'} ``` -------------------------------- ### Run full checks with make check Source: https://github.com/mahjongrepository/mahjong/blob/master/README.md Run full checks (format, lint, and tests) before committing. ```bash make check # Runs format, lint, and tests ``` -------------------------------- ### Run tests with make or uv run pytest Source: https://github.com/mahjongrepository/mahjong/blob/master/README.md Run the test suite either via make or directly with uv run pytest. ```bash make tests # Or directly: uv run pytest ``` -------------------------------- ### Calculate tsumo hand with HandConfig(is_tsumo=True) Source: https://github.com/mahjongrepository/mahjong/wiki/v2-English Calculates the same hand but with tsumo enabled via HandConfig(is_tsumo=True). Output shows 4 han, 40 fu, main cost 4000, additional 2000, yaku [Menzen Tsumo, Tanyao, San Ankou], and fu details including tsumo fu. ```python result = HandCalculator.estimate_hand_value(tiles, win_tile, config=HandConfig(is_tsumo=True)) print(result.han, result.fu) print(result.cost['main'], result.cost['additional']) print(result.yaku) for fu_item in result.fu_details: print(fu_item) ``` ```text 4 40 4000 2000 [Menzen Tsumo, Tanyao, San Ankou] {'fu': 20, 'reason': 'base'} {'fu': 4, 'reason': 'closed_pon'} {'fu': 4, 'reason': 'closed_pon'} {'fu': 4, 'reason': 'closed_pon'} {'fu': 2, 'reason': 'tsumo'} ``` -------------------------------- ### Riichi and Ura dora with dora indicators Source: https://github.com/mahjongrepository/mahjong/wiki/v2-English Calculates hand value with riichi and tsumo enabled, passing dora and ura dora indicators. Output shows 10 han, 40 fu, and yaku list including Ura Dora. ```python tiles = TilesConverter.string_to_136_array(man='22444', pin='333567', sou='444') win_tile = TilesConverter.string_to_136_array(sou='4')[0] dora_indicators = TilesConverter.string_to_136_array(man='1') ura_dora_indicators = TilesConverter.string_to_136_array(pin='2') result = HandCalculator.estimate_hand_value( tiles, win_tile, dora_indicators=dora_indicators, ura_dora_indicators=ura_dora_indicators, config=HandConfig(is_riichi=True, is_tsumo=True), ) print(result.han, result.fu) print(result.yaku) ``` ```text 10 40 [Menzen Tsumo, Riichi, Tanyao, San Ankou, Dora 2, Ura Dora 3] ``` -------------------------------- ### Calculate tanyao hand by ron Source: https://github.com/mahjongrepository/mahjong/wiki/v2-English Calculates the value of a closed tanyao hand won by ron. Uses HandCalculator.estimate_hand_value with default config. Output shows 1 han, 40 fu, cost 1300, yaku [Tanyao], and fu details. ```python from mahjong.hand_calculating.hand import HandCalculator from mahjong.tile import TilesConverter from mahjong.hand_calculating.hand_config import HandConfig from mahjong.meld import Meld # we had to use all 14 tiles in that array tiles = TilesConverter.string_to_136_array(man='22444', pin='333567', sou='444') win_tile = TilesConverter.string_to_136_array(sou='4')[0] result = HandCalculator.estimate_hand_value(tiles, win_tile) print(result.han, result.fu) print(result.cost['main']) print(result.yaku) for fu_item in result.fu_details: print(fu_item) ``` ```text 1 40 1300 [Tanyao] {'fu': 30, 'reason': 'base'} {'fu': 4, 'reason': 'closed_pon'} {'fu': 4, 'reason': 'closed_pon'} {'fu': 2, 'reason': 'open_pon'} ``` -------------------------------- ### Calculate Aotenjou hand value with four kans Source: https://github.com/mahjongrepository/mahjong/wiki/v2-Chinese Calculates the hand value for a four-kan hand using the Aotenjou scoring calculator. The output shows 103 han, 160 fu, and an enormous main cost of 12980742146337069071326240823050300, with the yaku list and fu details printed. ```python from mahjong.hand_calculating.hand import HandCalculator from mahjong.hand_calculating.hand_config import HandConfig from mahjong.hand_calculating.scores import Aotenjou from mahjong.tile import TilesConverter from mahjong.meld import Meld from mahjong.constants import EAST tiles = TilesConverter.string_to_136_array(honors='111133555566667777') win_tile = TilesConverter.string_to_136_array(honors='3')[0] melds = [ Meld(meld_type=Meld.KAN, tiles=TilesConverter.string_to_136_array(honors='1111'), opened=False), Meld(meld_type=Meld.KAN, tiles=TilesConverter.string_to_136_array(honors='5555'), opened=False), Meld(meld_type=Meld.KAN, tiles=TilesConverter.string_to_136_array(honors='6666'), opened=False), Meld(meld_type=Meld.KAN, tiles=TilesConverter.string_to_136_array(honors='7777'), opened=False), ] result = HandCalculator.estimate_hand_value( tiles, win_tile, melds=melds, dora_indicators=TilesConverter.string_to_136_array(honors='4444'), ura_dora_indicators=TilesConverter.string_to_136_array(honors='7777'), scores_calculator_factory=Aotenjou, config=HandConfig( is_riichi=True, is_tsumo=True, is_ippatsu=True, is_haitei=True, player_wind=EAST, round_wind=EAST, ), ) print(result.han, result.fu) print(result.cost['main']) print(result.yaku) for fu_item in result.fu_details: print(fu_item) ``` ```text 103 160 12980742146337069071326240823050300 [Menzen Tsumo, Riichi, Ippatsu, Haitei Raoyue, Yakuhai (seat wind east), Yakuhai (round wind east), Daisangen, Suu Kantsu, Tsuu Iisou, Suu Ankou Tanki, Dora 16, Ura Dora 16] {'fu': 32, 'reason': 'closed_terminal_kan'} {'fu': 32, 'reason': 'closed_terminal_kan'} {'fu': 32, 'reason': 'closed_terminal_kan'} {'fu': 32, 'reason': 'closed_terminal_kan'} {'fu': 20, 'reason': 'base'} {'fu': 2, 'reason': 'pair_wait'} {'fu': 2, 'reason': 'tsumo'} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.