Skip to content

Commit e46d430

Browse files
authored
refactor: move num_nuki_dora to HandConfig (#276)
1 parent 99a81da commit e46d430

3 files changed

Lines changed: 20 additions & 10 deletions

File tree

mahjong/hand_calculating/hand.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ def estimate_hand_value(
9999
config: HandConfig | None = None,
100100
scores_calculator_factory: type[ScoresCalculator] = ScoresCalculator,
101101
ura_dora_indicators: Collection[int] | None = None,
102-
num_nuki_dora: int = 0,
103102
) -> HandResponse:
104103
"""
105104
Estimate the point value of a winning hand.
@@ -176,7 +175,6 @@ def estimate_hand_value(
176175
:class:`~mahjong.hand_calculating.scores.Aotenjou` for aotenjou (limitless) scoring
177176
:param ura_dora_indicators: ura dora indicator tile indices in 136-format
178177
(counted only when riichi or double riichi is declared)
179-
:param num_nuki_dora: the number of nuki dora (north wind extraction)
180178
:return: :class:`~mahjong.hand_calculating.hand_response.HandResponse` with scoring
181179
details on success, or with :attr:`~mahjong.hand_calculating.hand_response.HandResponse.error`
182180
set on failure
@@ -281,8 +279,8 @@ def estimate_hand_value(
281279
# precompute dora counts, invariant across all hand decompositions
282280
dora_count_map = build_dora_count_map(dora_indicators)
283281
precomputed_dora = count_dora_for_hand(tiles_34, dora_count_map)
284-
if num_nuki_dora > 0:
285-
precomputed_dora += dora_count_map.get(NORTH, 0) * num_nuki_dora + num_nuki_dora
282+
if config.num_nuki_dora > 0:
283+
precomputed_dora += dora_count_map.get(NORTH, 0) * config.num_nuki_dora + config.num_nuki_dora
286284

287285
precomputed_aka_dora = 0
288286
if config.options.has_aka_dora:
@@ -292,8 +290,8 @@ def estimate_hand_value(
292290
if config.is_riichi or config.is_daburu_riichi:
293291
ura_count_map = build_dora_count_map(ura_dora_indicators)
294292
precomputed_ura_dora = count_dora_for_hand(tiles_34, ura_count_map)
295-
if num_nuki_dora > 0:
296-
precomputed_ura_dora += ura_count_map.get(NORTH, 0) * num_nuki_dora
293+
if config.num_nuki_dora > 0:
294+
precomputed_ura_dora += ura_count_map.get(NORTH, 0) * config.num_nuki_dora
297295

298296
yakuhai_seat_wind_yaku = (
299297
config.yaku.seat_wind_east,

mahjong/hand_calculating/hand_config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ class HandConfig(HandConstants):
220220
:vartype kyoutaku_number: int
221221
:ivar tsumi_number: number of honba counters (100 points each per counter)
222222
:vartype tsumi_number: int
223+
:ivar num_nuki_dora: the number of nuki dora (north wind extraction)
224+
:vartype num_nuki_dora: int
223225
"""
224226

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

247249
kyoutaku_number: int
248250
tsumi_number: int
251+
num_nuki_dora: int
249252

250253
def __init__(
251254
self,
@@ -268,6 +271,7 @@ def __init__(
268271
tsumi_number: int = 0,
269272
paarenchan: int = 0,
270273
options: OptionalRules | None = None,
274+
num_nuki_dora: int = 0,
271275
) -> None:
272276
"""
273277
Initialize hand configuration.
@@ -306,6 +310,7 @@ def __init__(
306310
:param paarenchan: consecutive dealer wins count for paarenchan check
307311
:param options: optional rule settings; defaults to :class:`OptionalRules` with
308312
all defaults when None
313+
:param num_nuki_dora: the number of nuki dora (north wind extraction)
309314
"""
310315
self.yaku = YakuConfig()
311316
self.options = options or OptionalRules()
@@ -331,3 +336,4 @@ def __init__(
331336

332337
self.kyoutaku_number = kyoutaku_number
333338
self.tsumi_number = tsumi_number
339+
self.num_nuki_dora = num_nuki_dora

tests/hand_calculating/tests_yaku_calculation.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,15 +1398,18 @@ def test_nuki_dora_with_dora_indicators(num_nuki_dora: int, num_dora_indicators:
13981398
tiles = TilesConverter.string_to_136_array(sou="345", pin="456", man="12355599", has_aka_dora=True)
13991399
win_tile = _string_to_136_tile(man="9")
14001400

1401-
hand_config = HandConfig(is_tsumo=True, options=OptionalRules(has_aka_dora=True))
1401+
hand_config = HandConfig(
1402+
is_tsumo=True,
1403+
options=OptionalRules(has_aka_dora=True),
1404+
num_nuki_dora=num_nuki_dora,
1405+
)
14021406
dora_indicators = TilesConverter.string_to_136_array(honors="3" * num_dora_indicators)
14031407

14041408
result = HandCalculator.estimate_hand_value(
14051409
tiles,
14061410
win_tile,
14071411
config=hand_config,
14081412
dora_indicators=dora_indicators,
1409-
num_nuki_dora=num_nuki_dora,
14101413
)
14111414
assert result.error is None
14121415
assert result.han == han
@@ -1435,15 +1438,18 @@ def test_nuki_dora_with_ura_dora_indicators(num_nuki_dora: int, num_ura_dora_ind
14351438
tiles = TilesConverter.string_to_136_array(sou="345", pin="456", man="12355599", has_aka_dora=True)
14361439
win_tile = _string_to_136_tile(man="9")
14371440

1438-
hand_config = HandConfig(is_riichi=True, options=OptionalRules(has_aka_dora=True))
1441+
hand_config = HandConfig(
1442+
is_riichi=True,
1443+
options=OptionalRules(has_aka_dora=True),
1444+
num_nuki_dora=num_nuki_dora,
1445+
)
14391446
ura_dora_indicators = TilesConverter.string_to_136_array(honors="3" * num_ura_dora_indicators)
14401447

14411448
result = HandCalculator.estimate_hand_value(
14421449
tiles,
14431450
win_tile,
14441451
config=hand_config,
14451452
ura_dora_indicators=ura_dora_indicators,
1446-
num_nuki_dora=num_nuki_dora,
14471453
)
14481454
assert result.error is None
14491455
assert result.han == han

0 commit comments

Comments
 (0)