Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions mahjong/hand_calculating/hand.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ def estimate_hand_value(
config: HandConfig | None = None,
scores_calculator_factory: type[ScoresCalculator] = ScoresCalculator,
ura_dora_indicators: Collection[int] | None = None,
num_nuki_dora: int = 0,
) -> HandResponse:
"""
Estimate the point value of a winning hand.
Expand Down Expand Up @@ -176,7 +175,6 @@ def estimate_hand_value(
:class:`~mahjong.hand_calculating.scores.Aotenjou` for aotenjou (limitless) scoring
:param ura_dora_indicators: ura dora indicator tile indices in 136-format
(counted only when riichi or double riichi is declared)
:param num_nuki_dora: the number of nuki dora (north wind extraction)
:return: :class:`~mahjong.hand_calculating.hand_response.HandResponse` with scoring
details on success, or with :attr:`~mahjong.hand_calculating.hand_response.HandResponse.error`
set on failure
Expand Down Expand Up @@ -281,8 +279,8 @@ def estimate_hand_value(
# precompute dora counts, invariant across all hand decompositions
dora_count_map = build_dora_count_map(dora_indicators)
precomputed_dora = count_dora_for_hand(tiles_34, dora_count_map)
if num_nuki_dora > 0:
precomputed_dora += dora_count_map.get(NORTH, 0) * num_nuki_dora + num_nuki_dora
if config.num_nuki_dora > 0:
precomputed_dora += dora_count_map.get(NORTH, 0) * config.num_nuki_dora + config.num_nuki_dora

precomputed_aka_dora = 0
if config.options.has_aka_dora:
Expand All @@ -292,8 +290,8 @@ def estimate_hand_value(
if config.is_riichi or config.is_daburu_riichi:
ura_count_map = build_dora_count_map(ura_dora_indicators)
precomputed_ura_dora = count_dora_for_hand(tiles_34, ura_count_map)
if num_nuki_dora > 0:
precomputed_ura_dora += ura_count_map.get(NORTH, 0) * num_nuki_dora
if config.num_nuki_dora > 0:
precomputed_ura_dora += ura_count_map.get(NORTH, 0) * config.num_nuki_dora

yakuhai_seat_wind_yaku = (
config.yaku.seat_wind_east,
Expand Down
6 changes: 6 additions & 0 deletions mahjong/hand_calculating/hand_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ class HandConfig(HandConstants):
:vartype kyoutaku_number: int
:ivar tsumi_number: number of honba counters (100 points each per counter)
:vartype tsumi_number: int
:ivar num_nuki_dora: the number of nuki dora (north wind extraction)
:vartype num_nuki_dora: int
"""

yaku: YakuConfig
Expand All @@ -246,6 +248,7 @@ class HandConfig(HandConstants):

kyoutaku_number: int
tsumi_number: int
num_nuki_dora: int

def __init__(
self,
Expand All @@ -268,6 +271,7 @@ def __init__(
tsumi_number: int = 0,
paarenchan: int = 0,
options: OptionalRules | None = None,
num_nuki_dora: int = 0,
) -> None:
"""
Initialize hand configuration.
Expand Down Expand Up @@ -306,6 +310,7 @@ def __init__(
:param paarenchan: consecutive dealer wins count for paarenchan check
:param options: optional rule settings; defaults to :class:`OptionalRules` with
all defaults when None
:param num_nuki_dora: the number of nuki dora (north wind extraction)
"""
self.yaku = YakuConfig()
self.options = options or OptionalRules()
Expand All @@ -331,3 +336,4 @@ def __init__(

self.kyoutaku_number = kyoutaku_number
self.tsumi_number = tsumi_number
self.num_nuki_dora = num_nuki_dora
14 changes: 10 additions & 4 deletions tests/hand_calculating/tests_yaku_calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1398,15 +1398,18 @@ def test_nuki_dora_with_dora_indicators(num_nuki_dora: int, num_dora_indicators:
tiles = TilesConverter.string_to_136_array(sou="345", pin="456", man="12355599", has_aka_dora=True)
win_tile = _string_to_136_tile(man="9")

hand_config = HandConfig(is_tsumo=True, options=OptionalRules(has_aka_dora=True))
hand_config = HandConfig(
is_tsumo=True,
options=OptionalRules(has_aka_dora=True),
num_nuki_dora=num_nuki_dora,
)
dora_indicators = TilesConverter.string_to_136_array(honors="3" * num_dora_indicators)

result = HandCalculator.estimate_hand_value(
tiles,
win_tile,
config=hand_config,
dora_indicators=dora_indicators,
num_nuki_dora=num_nuki_dora,
)
assert result.error is None
assert result.han == han
Expand Down Expand Up @@ -1435,15 +1438,18 @@ def test_nuki_dora_with_ura_dora_indicators(num_nuki_dora: int, num_ura_dora_ind
tiles = TilesConverter.string_to_136_array(sou="345", pin="456", man="12355599", has_aka_dora=True)
win_tile = _string_to_136_tile(man="9")

hand_config = HandConfig(is_riichi=True, options=OptionalRules(has_aka_dora=True))
hand_config = HandConfig(
is_riichi=True,
options=OptionalRules(has_aka_dora=True),
num_nuki_dora=num_nuki_dora,
)
ura_dora_indicators = TilesConverter.string_to_136_array(honors="3" * num_ura_dora_indicators)

result = HandCalculator.estimate_hand_value(
tiles,
win_tile,
config=hand_config,
ura_dora_indicators=ura_dora_indicators,
num_nuki_dora=num_nuki_dora,
)
assert result.error is None
assert result.han == han
Expand Down