From d5bc8ddf7285bf2915f2f0003628794dfe36eaa5 Mon Sep 17 00:00:00 2001 From: Apricot-S Date: Wed, 1 Apr 2026 21:56:15 +0900 Subject: [PATCH 1/3] fix: Add a unit test --- tests/tests_shanten.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/tests_shanten.py b/tests/tests_shanten.py index fc50bd6..8bbbe3e 100644 --- a/tests/tests_shanten.py +++ b/tests/tests_shanten.py @@ -187,3 +187,12 @@ def test_calculate_shanten_raises_error_for_3n_tile_count() -> None: tiles = TilesConverter.string_to_34_array(man="123") with pytest.raises(ValueError, match="Invalid tile count"): Shanten.calculate_shanten(tiles) + + +def test_calculate_shanten_kokushi_should_be_ignored_when_melds_exist() -> None: + tiles = TilesConverter.string_to_34_array(sou="19", pin="19", man="19", honors="12345") + shanten_with_kokushi = Shanten.calculate_shanten(tiles, use_kokushi=True) + shanten_without_kokushi = Shanten.calculate_shanten(tiles, use_kokushi=False) + + # Expected: kokushi path must be ignored, so results should match + assert shanten_with_kokushi == shanten_without_kokushi From 65f5da6bc735f7474c61ba11ed617afd1da2ce9c Mon Sep 17 00:00:00 2001 From: Apricot-S Date: Wed, 1 Apr 2026 22:52:03 +0900 Subject: [PATCH 2/3] fix: Ignore chiitoitsu and kokushi when melds exist in shanten calculation --- mahjong/shanten.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/mahjong/shanten.py b/mahjong/shanten.py index 1a1b65a..0d0c596 100644 --- a/mahjong/shanten.py +++ b/mahjong/shanten.py @@ -51,11 +51,14 @@ def calculate_shanten(tiles_34: Sequence[int], use_chiitoitsu: bool = True, use_ :return: minimum shanten number (-1 for agari, 0 for tenpai, positive for tiles needed) :raises ValueError: if tile count exceeds 14 or is divisible by 3 """ - shanten_results = [Shanten.calculate_shanten_for_regular_hand(tiles_34)] - if use_chiitoitsu: - shanten_results.append(Shanten.calculate_shanten_for_chiitoitsu_hand(tiles_34)) - if use_kokushi: - shanten_results.append(Shanten.calculate_shanten_for_kokushi_hand(tiles_34)) + count_of_tiles = sum(tiles_34) + shanten_results = [_RegularShanten(tiles_34).calculate(count_of_tiles)] + + if count_of_tiles >= 13: + if use_chiitoitsu: + shanten_results.append(Shanten.calculate_shanten_for_chiitoitsu_hand(tiles_34)) + if use_kokushi: + shanten_results.append(Shanten.calculate_shanten_for_kokushi_hand(tiles_34)) return min(shanten_results) @@ -150,7 +153,8 @@ def calculate_shanten_for_regular_hand(tiles_34: Sequence[int]) -> int: :return: shanten number for regular hand (-1 for complete, 0+ otherwise) :raises ValueError: if tile count exceeds 14 or is divisible by 3 """ - return _RegularShanten(tiles_34).calculate() + count_of_tiles = sum(tiles_34) + return _RegularShanten(tiles_34).calculate(count_of_tiles) class _RegularShanten: @@ -165,8 +169,7 @@ def __init__(self, tiles_34: Sequence[int]) -> None: self._flag_isolated_tiles = 0 self._min_shanten = 8 - def calculate(self) -> int: - count_of_tiles = sum(self._tiles) + def calculate(self, count_of_tiles: int) -> int: if count_of_tiles > 14: msg = f"Too many tiles = {count_of_tiles}" raise ValueError(msg) From 6ddf6fa17b7295cb77fb6f5b0535534d18d4f5b5 Mon Sep 17 00:00:00 2001 From: Apricot-S Date: Wed, 1 Apr 2026 23:32:00 +0900 Subject: [PATCH 3/3] docs: Add CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40462dc..d0439da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,6 +111,7 @@ The following methods are now available as static methods: - Fixed an issue where `KokushiMusou.is_condition_met()` would return `None` if the condition was not met. It now consistently returns a `bool` value. Remove any `None` checks in the code that relied on the previous behavior. - `Shanten.calculate_shanten()` and `Shanten.calculate_shanten_for_regular_hand()` now raises `ValueError` instead of `assert` when the number of tiles is 15 or more. - `Shanten.calculate_shanten()` and `Shanten.calculate_shanten_for_regular_hand()` now raises `ValueError` for tile counts divisible by 3 (0, 3, 6, 9, 12). These counts never occur in real riichi mahjong gameplay. Valid tile counts are 1, 2, 4, 5, 7, 8, 10, 11, 13, 14. +- `Shanten.calculate_shanten()` now ignores chiitoitsu and kokushi calculations when the hand contains melds (i.e., the number of tiles is less than 13), preventing invalid shanten results from being considered. - `HandDivider.divide_hand()` now determines block type from `Meld.type` instead of inferring it from `Meld.tiles`. Behavior may differ for invalid `Meld.tiles` or inconsistent `Meld.type` and `Meld.tiles` combinations. - Removed `HandCalculator.ERR_HAND_NOT_CORRECT`. Hands that previously returned `ERR_HAND_NOT_CORRECT` now return `ERR_HAND_NOT_WINNING` instead. - `Meld.tiles` is now a `tuple[int, ...]` instead of `list[int]`. Code that mutates `Meld.tiles` in place (e.g., `append()`, `sort()`, item assignment) must be updated.