mahjong.hand_calculating.hand_config

Configuration classes for the hand calculator.

Classes

  • HandConstants - constants for kazoe (counted) yakuman limit modes

  • OptionalRules - 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: object

Constants 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: object

Toggle 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, or HandConstants.KAZOE_NO_LIMIT

  • kiriage (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_suits is True

  • has_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: HandConstants

Configuration for the hand calculator combining win conditions, wind context, and optional rules.

Pass a HandConfig instance to estimate_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_wind is East

  • player_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 OptionalRules with all defaults when None

Return type:

None