0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python麻雀ライブラリ mahjong v2.0.0 の変更点と移行時の注意点

0
Last updated at Posted at 2026-05-13

概要

mahjong は Python 向けの麻雀ライブラリです。

点数計算・シャンテン数計算・牌姿文字列のパースなどを提供します。

v1.2.1 のリリース後、リポジトリはしばらくアーカイブ状態でした。
その後、v1.3.0・v1.4.0 でバグ修正や型アノテーション追加などのメンテナンスが行われ、今回 v2.0.0 がリリースされました。

本記事では、v1.4.0 から v2.0.0 への主な変更点と、移行時に注意すべき破壊的変更を紹介します。

筆者は v1.3.0 以降の開発に参加しており、v2.0.0 からメンテナーを務めています。

PyPI:

GitHub:

v1.4.0 → v2.0.0 変更点ハイライト

点数計算が大幅に高速化

面子分解アルゴリズムや役判定処理の見直しにより、点数計算が高速化されました。

500,000手の点数計算を用いたベンチマークでは、v1.4.0 比で 約6倍 のスループットを記録しています(5回計測した中央値)。

バージョン スループット [hand/s] 1 手あたり平均時間 [ms]
1.4.0 5,925 0.169
2.0.0 35,364 0.028

裏ドラに対応

HandCalculator.estimate_hand_value()ura_dora_indicators (裏ドラ表示牌) 引数が追加され、立直・ダブル立直時の裏ドラ計算に対応しました。

from mahjong.hand_calculating.hand import HandCalculator
from mahjong.hand_calculating.hand_config import HandConfig
from mahjong.tile import TilesConverter

tiles = TilesConverter.one_line_string_to_136_array("123456m33p123456s")
win_tile = TilesConverter.one_line_string_to_136_array("6m")[0]
ura_dora_indicators = TilesConverter.one_line_string_to_136_array("2p")
config = HandConfig(is_riichi=True)

result = HandCalculator.estimate_hand_value(
    tiles,
    win_tile,
    ura_dora_indicators=ura_dora_indicators,
    config=config,
)

print(f"{result.fu}{result.han}")
print(result.yaku)

出力:

30符4飜
[Riichi, Pinfu, Ura Dora 2]

裏ドラは立直・ダブル立直時のみ有効です。

場風牌・自風牌を風牌ごとに分離

v1.4.0 では、点数計算結果に含まれる場風牌・自風牌は、YakuhaiOfPlace / YakuhaiOfRound として表現されていました。

v2.0.0 では、自風・場風それぞれについて東南西北の個別クラスが導入されました。

自風牌は以下のクラスで表現されます。

  • SeatWindEast
  • SeatWindSouth
  • SeatWindWest
  • SeatWindNorth

場風牌は以下のクラスで表現されます。

  • RoundWindEast
  • RoundWindSouth
  • RoundWindWest
  • RoundWindNorth

これにより、「自風 東」「場風 南」などを個別の役として扱えるようになり、天鳳の役表示に近い粒度で扱いやすくなりました。

from mahjong.constants import EAST, SOUTH
from mahjong.hand_calculating.hand import HandCalculator
from mahjong.hand_calculating.hand_config import HandConfig
from mahjong.tile import TilesConverter

tiles = TilesConverter.one_line_string_to_136_array("123456m33p111z222z")
win_tile = TilesConverter.one_line_string_to_136_array("6m")[0]
config = HandConfig(player_wind=EAST, round_wind=SOUTH)

calculator = HandCalculator()
result = calculator.estimate_hand_value(tiles, win_tile, config=config)

print(result.yaku)

v1.4.0 の出力:

[Yakuhai (wind of place), Yakuhai (wind of round)]

v2.0.0 の出力:

[Yakuhai (seat wind east), Yakuhai (round wind south)]

この変更により、風牌役のクラスは v1.x とは互換性がありません。
YakuhaiOfPlaceYakuhaiOfRound などの旧クラスを直接参照しているコードは修正が必要です。

主要APIのstaticmethod化

点数計算やシャンテン数計算などの主要APIが staticmethod 化され、インスタンス生成なしで呼び出せるようになりました。

v1.4.0:

from mahjong.shanten import Shanten
from mahjong.tile import TilesConverter

tiles = TilesConverter.one_line_string_to_34_array('13569m123459p443s')

shanten = Shanten()
print(shanten.calculate_shanten(tiles))

v2.0.0:

from mahjong.shanten import Shanten
from mahjong.tile import TilesConverter

tiles = TilesConverter.one_line_string_to_34_array("13569m123459p443s")

print(Shanten.calculate_shanten(tiles))

主な staticmethod 化対象:

  • HandCalculator.estimate_hand_value()
  • Agari.is_agari()
  • Shanten.calculate_shanten()
  • HandDivider.divide_hand()
  • FuCalculator.calculate_fu()
  • ScoresCalculator.calculate_scores()

TypedDict による戻り値の型情報の詳細化

一部の戻り値の型アノテーションが通常の dict から TypedDict ベースに変更されました。

以下の TypedDict が追加されました。

  • ScoresResult
  • FuDetail
  • SuitCount

HandResponse.costScoresResult | NoneHandResponse.fu_detailslist[FuDetail] | None として型付けされるようになりました。

これにより、型チェッカーやIDE補完で戻り値の扱いが分かりやすくなりました。

シャンテン数計算の入力検証を強化

Shanten.calculate_shanten()Shanten.calculate_shanten_for_regular_hand() の入力検証が強化されました。

v2.0.0 では、15枚以上や0・3・6・9・12枚のような、実戦上発生しない枚数の手牌に対しては ValueError が送出されます。

また、手牌枚数が13枚未満、つまり副露面子が別途ある前提の入力では、七対子・国士無双のシャンテン数計算を無視するようになりました。

たとえば以下の手牌では従来と計算結果が異なります。

from mahjong.shanten import Shanten
from mahjong.tile import TilesConverter

tiles = TilesConverter.one_line_string_to_34_array("19m19p19s12345z")
shanten = Shanten()

print(shanten.calculate_shanten(tiles))

v1.4.0 では 2、v2.0.0 では 6 を返します。

役なしの場合は計算結果を返さない

従来は、役なしの手でも error とあわせて fuhan、ドラ役などの情報が設定されていました。

v2.0.0 では、役なしの場合は error のみが設定され、それ以外のフィールドは None になります。

from mahjong.constants import EAST
from mahjong.hand_calculating.hand import HandCalculator
from mahjong.hand_calculating.hand_config import HandConfig
from mahjong.tile import TilesConverter

tiles = TilesConverter.one_line_string_to_136_array("123456m123456s11z")
win_tile = TilesConverter.one_line_string_to_136_array("6m")[0]
dora_indicators = TilesConverter.one_line_string_to_136_array("4z")
config = HandConfig(player_wind=EAST)

calculator = HandCalculator()
result = calculator.estimate_hand_value(
    tiles,
    win_tile,
    dora_indicators=dora_indicators,
    config=config,
)

print(f"{result.error=}")
print(f"{result.fu}{result.han}")
print(result.yaku)

v1.4.0 の出力:

result.error='no_yaku'
40符2飜
[Dora 2]

v2.0.0 の出力:

result.error='no_yaku'
None符None飜
None

APIドキュメント整備

すべての public API に docstring が追加され、Sphinx ベースの API ドキュメントも公開されました。

APIドキュメント:

移行時の注意点

v2.0.0 はメジャーバージョンアップであり、破壊的変更を含みます。

通常の点数計算用途では影響は限定的ですが、
役クラスや内部寄りAPIを利用している場合は修正が必要になる可能性があります。

Python 3.10以上が必要

v2.0.0 では Python 3.9 のサポートが終了しました。

Python 3.10 以上が必要です。

役クラスの変更

Yaku クラスが再設計されました。

主な変更点は以下です。

  • Yaku が抽象基底クラス (ABC) になりました
  • 各役クラスの yaku_idname などがクラス属性になりました
  • Yaku.english / Yaku.japanese が削除されました
  • 各役クラスの tenhou_id が削除されました
    • 天鳳の役IDが必要な場合は、mahjong.hand_calculating.yaku_configYAKU_ID_TO_TENHOU_ID を使用してください
  • 各役の yaku_id の値が再割り当てされました

役クラスを直接参照しているコードや、yaku_id を保存・比較・シリアライズしているコードでは対応が必要です。

風牌役のクラス変更

風牌役の再設計により、旧クラスは新しいクラスに置き換えられました。

v1.4.0 v2.0.0
YakuhaiOfPlace SeatWindEast / SeatWindSouth / SeatWindWest / SeatWindNorth
YakuhaiOfRound RoundWindEast / RoundWindSouth / RoundWindWest / RoundWindNorth

YakuhaiOfPlace は自風に応じた SeatWind* 系クラスへ、YakuhaiOfRound は場風に応じた RoundWind* 系クラスへ置き換わります。

自風牌と場風牌が東南西北ごとに分離されたため、役一覧を直接処理しているコードでは対応が必要です。

一部定数がlistからfrozensetに変更

以下の定数は、list から frozenset に変更されました。

  • TERMINAL_INDICES
  • WINDS
  • HONOR_INDICES
  • AKA_DORA_LIST

また、AKA_DORA_LISTAKA_DORAS にリネームされています。

x in WINDS のような包含判定はそのまま動作します。

一方で、インデックスアクセスやリスト結合など、list 固有の操作に依存している場合は修正が必要です。

Meld.tiles が tuple に変更

Meld.tileslist[int] から tuple[int, ...] に変更されました。

そのため、以下のようなインプレースな変更はできなくなります。

meld.tiles.append(tile)
meld.tiles.sort()
meld.tiles[0] = tile

Meld.tiles を変更する場合は、新しい tuple を代入する必要があります。

その他の破壊的変更

v2.0.0 では、上記以外にも一部の定数・引数・内部APIが削除または変更されています。

主な変更点は以下です。

  • Meld.CHANKAN は削除されました。加槓には Meld.SHOUMINKAN を使用してください
  • HandCalculator.estimate_hand_value()use_hand_divider_cache 引数は削除されました
  • HandCalculator.ERR_HAND_NOT_CORRECT は削除され、該当するケースでは HandCalculator.ERR_HAND_NOT_WINNING が返るようになりました

これらを利用しているコードでは修正が必要です。

また、HandDivider など内部寄りのクラスにも変更があります。これらを直接利用している場合はCHANGELOGも確認してください。

CHANGELOG: https://github.com/MahjongRepository/mahjong/blob/v2.0.0/CHANGELOG.md

まとめ

v2.0.0 では、点数計算の高速化、裏ドラ対応、風牌役の分離、API整理、型情報改善など、多くの変更が入りました。

一方で、Python 3.9 のサポート終了、役クラスの再設計、定数や Meld.tiles の型変更など、破壊的変更も含まれます。

既存コードを移行する場合は、特に役クラスや内部API利用部分への影響を確認してください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?