mahjong.hand_calculating.hand_config
Configuration classes for the hand calculator.
Classes
HandConstants- constants for kazoe (counted) yakuman limit modesOptionalRules- toggle optional rule variants (open tanyao, aka dora, etc.)HandConfig- full hand configuration combining win conditions, wind context, bonuses, and optional rules
- class mahjong.hand_calculating.hand_config.HandConstants[source]
Bases:
objectConstants for kazoe (counted) yakuman limit modes.
- KAZOE_LIMITED = 0
Kazoe hands (13+ han) are capped at single yakuman.
- KAZOE_SANBAIMAN = 1
Kazoe hands (13+ han) are capped at sanbaiman.
- KAZOE_NO_LIMIT = 2
No cap on kazoe hands; 13+ han as yakuman, 26+ as double yakuman, and so on.
- class mahjong.hand_calculating.hand_config.OptionalRules(has_open_tanyao=False, has_aka_dora=False, has_double_yakuman=True, kazoe_limit=0, kiriage=False, fu_for_open_pinfu=True, fu_for_pinfu_tsumo=False, renhou_as_yakuman=False, has_daisharin=False, has_daisharin_other_suits=False, has_sashikomi_yakuman=False, limit_to_sextuple_yakuman=True, paarenchan_needs_yaku=True, has_daichisei=False)[source]
Bases:
objectToggle optional rule variants for hand evaluation.
Japanese mahjong has many rule variations across different parlors and online platforms. This class controls which optional rules are active during hand calculation.
- Variables:
has_open_tanyao (bool) – allow tanyao on open hands (kuitan)
has_aka_dora (bool) – enable red five tiles as bonus dora
has_double_yakuman (bool) – allow double yakuman scoring for applicable hands
kazoe_limit (int) – kazoe yakuman limit mode; one of
HandConstants.KAZOE_LIMITED,HandConstants.KAZOE_SANBAIMAN, orHandConstants.KAZOE_NO_LIMITkiriage (bool) – round up to mangan when han/fu are at the boundary (4 han 30 fu or 3 han 60 fu)
fu_for_open_pinfu (bool) – add 2 fu for open pinfu-form ron (totaling 30 fu); when False, 1 han 20 fu hands become possible
fu_for_pinfu_tsumo (bool) – award 2 fu for tsumo on pinfu hands (disabling the 0-fu tsumo pinfu exception)
renhou_as_yakuman (bool) – treat renhou as yakuman instead of mangan
has_daisharin (bool) – enable daisharin 22334455667788p as yakuman; automatically set to True when
has_daisharin_other_suitsis Truehas_daisharin_other_suits (bool) – allow daisharin in man and sou suits (not only pin)
has_daichisei (bool) – enable daichisei (tsuuiisou / all honors as seven pairs) as yakuman
has_sashikomi_yakuman (bool) – enable sashikomi (intentional deal-in for open riichi) as yakuman
limit_to_sextuple_yakuman (bool) – cap yakuman multiplier at 6x
paarenchan_needs_yaku (bool) – require at least one yaku for paarenchan to count
- Parameters:
has_open_tanyao (bool)
has_aka_dora (bool)
has_double_yakuman (bool)
kazoe_limit (int)
kiriage (bool)
fu_for_open_pinfu (bool)
fu_for_pinfu_tsumo (bool)
renhou_as_yakuman (bool)
has_daisharin (bool)
has_daisharin_other_suits (bool)
has_sashikomi_yakuman (bool)
limit_to_sextuple_yakuman (bool)
paarenchan_needs_yaku (bool)
has_daichisei (bool)
- __init__(has_open_tanyao=False, has_aka_dora=False, has_double_yakuman=True, kazoe_limit=0, kiriage=False, fu_for_open_pinfu=True, fu_for_pinfu_tsumo=False, renhou_as_yakuman=False, has_daisharin=False, has_daisharin_other_suits=False, has_sashikomi_yakuman=False, limit_to_sextuple_yakuman=True, paarenchan_needs_yaku=True, has_daichisei=False)[source]
Initialize optional rules.
>>> from mahjong.hand_calculating.hand_config import OptionalRules >>> options = OptionalRules(has_open_tanyao=True, kiriage=True) >>> options.has_open_tanyao True >>> options.kiriage True
- Parameters:
has_open_tanyao (bool) – allow tanyao on open hands (kuitan)
has_aka_dora (bool) – enable red five tiles as bonus dora
has_double_yakuman (bool) – allow double yakuman scoring
kazoe_limit (int) – kazoe yakuman limit mode
kiriage (bool) – round up to mangan at boundary han/fu combinations
fu_for_open_pinfu (bool) – award 2 fu for open hands with no other fu sources
fu_for_pinfu_tsumo (bool) – award tsumo fu even for pinfu hands
renhou_as_yakuman (bool) – treat renhou as yakuman
has_daisharin (bool) – enable daisharin yakuman
has_daisharin_other_suits (bool) – allow daisharin in all suits
has_sashikomi_yakuman (bool) – enable sashikomi yakuman
limit_to_sextuple_yakuman (bool) – cap yakuman multiplier at 6x
paarenchan_needs_yaku (bool) – require yaku for paarenchan
has_daichisei (bool) – enable daichisei yakuman
- Return type:
None
- class mahjong.hand_calculating.hand_config.HandConfig(is_tsumo=False, is_riichi=False, is_ippatsu=False, is_rinshan=False, is_chankan=False, is_haitei=False, is_houtei=False, is_daburu_riichi=False, is_nagashi_mangan=False, is_tenhou=False, is_renhou=False, is_chiihou=False, is_open_riichi=False, player_wind=None, round_wind=None, kyoutaku_number=0, tsumi_number=0, paarenchan=0, options=None)[source]
Bases:
HandConstantsConfiguration for the hand calculator combining win conditions, wind context, and optional rules.
Pass a
HandConfiginstance toestimate_hand_value()to describe how the hand was won and which rules apply.A default config represents a closed ron with no special conditions:
>>> from mahjong.hand_calculating.hand_config import HandConfig >>> config = HandConfig() >>> config.is_tsumo False >>> config.is_dealer False
Configure a dealer tsumo win with riichi and ippatsu:
>>> from mahjong.constants import EAST >>> config = HandConfig(is_tsumo=True, is_riichi=True, is_ippatsu=True, player_wind=EAST) >>> config.is_tsumo True >>> config.is_dealer True
Include score bonuses and optional rules:
>>> from mahjong.hand_calculating.hand_config import OptionalRules >>> options = OptionalRules(has_open_tanyao=True, has_aka_dora=True) >>> config = HandConfig(tsumi_number=2, kyoutaku_number=3, options=options) >>> config.tsumi_number 2 >>> config.options.has_open_tanyao True
- Variables:
yaku (YakuConfig) – yaku definition objects used during hand evaluation
options (OptionalRules) – optional rule settings
is_tsumo (bool) – hand won by self-draw
is_riichi (bool) – player declared riichi
is_ippatsu (bool) – win within one turn of declaring riichi
is_rinshan (bool) – win on a replacement tile after calling kan
is_chankan (bool) – win by robbing another player’s kan declaration
is_haitei (bool) – win on the last drawable tile (tsumo) of the round
is_houtei (bool) – win on the discard following the last drawable tile (ron)
is_daburu_riichi (bool) – player declared double riichi (riichi on first turn)
is_nagashi_mangan (bool) – all discards are terminals and honors with no calls against them
is_tenhou (bool) – dealer wins on the initial draw
is_renhou (bool) – non-dealer wins on the first go-around before any calls
is_chiihou (bool) – non-dealer wins on the initial draw
is_open_riichi (bool) – player declared open riichi (revealed hand)
is_dealer (bool) – True when
player_windis Eastplayer_wind (int | None) – tile index in 34-format of the player’s seat wind, or None
round_wind (int | None) – tile index in 34-format of the round wind, or None
paarenchan (int) – consecutive dealer wins count; above 0 enables paarenchan yakuman check
kyoutaku_number (int) – number of riichi deposits on the table (1000 points each)
tsumi_number (int) – number of honba counters (100 points each per counter)
- Parameters:
is_tsumo (bool)
is_riichi (bool)
is_ippatsu (bool)
is_rinshan (bool)
is_chankan (bool)
is_haitei (bool)
is_houtei (bool)
is_daburu_riichi (bool)
is_nagashi_mangan (bool)
is_tenhou (bool)
is_renhou (bool)
is_chiihou (bool)
is_open_riichi (bool)
player_wind (int | None)
round_wind (int | None)
kyoutaku_number (int)
tsumi_number (int)
paarenchan (int)
options (OptionalRules)
- __init__(is_tsumo=False, is_riichi=False, is_ippatsu=False, is_rinshan=False, is_chankan=False, is_haitei=False, is_houtei=False, is_daburu_riichi=False, is_nagashi_mangan=False, is_tenhou=False, is_renhou=False, is_chiihou=False, is_open_riichi=False, player_wind=None, round_wind=None, kyoutaku_number=0, tsumi_number=0, paarenchan=0, options=None)[source]
Initialize hand configuration.
>>> from mahjong.hand_calculating.hand_config import HandConfig, OptionalRules >>> from mahjong.constants import EAST, SOUTH >>> config = HandConfig( ... is_tsumo=True, ... is_riichi=True, ... player_wind=EAST, ... round_wind=SOUTH, ... options=OptionalRules(has_open_tanyao=True), ... ) >>> config.is_dealer True >>> config.round_wind == SOUTH True
- Parameters:
is_tsumo (bool) – hand won by self-draw
is_riichi (bool) – player declared riichi
is_ippatsu (bool) – win within one turn of declaring riichi
is_rinshan (bool) – win on a replacement tile after calling kan
is_chankan (bool) – win by robbing another player’s kan
is_haitei (bool) – win on the last drawable tile
is_houtei (bool) – win on the discard following the last drawable tile
is_daburu_riichi (bool) – player declared double riichi
is_nagashi_mangan (bool) – all discards are terminals and honors
is_tenhou (bool) – dealer wins on the initial draw
is_renhou (bool) – non-dealer wins on the first go-around
is_chiihou (bool) – non-dealer wins on the initial draw
is_open_riichi (bool) – player declared open riichi
player_wind (int | None) – tile index in 34-format of the player’s seat wind
round_wind (int | None) – tile index in 34-format of the round wind
kyoutaku_number (int) – riichi deposits on the table (1000 points each)
tsumi_number (int) – honba counters (100 points each per counter)
paarenchan (int) – consecutive dealer wins count for paarenchan check
options (OptionalRules | None) – optional rule settings; defaults to
OptionalRuleswith all defaults when None
- Return type:
None