mortal3-b40c192-t23032505 β€” Japanese mahjong bot

A Mortal v3 model for four-player Japanese mahjong (riichi), trained on Tenhou Houou (鳳凰卓) game records. It picks a discard or call from the current game state; it is a full playing agent, not a scoring or evaluation model.

Of 6 checkpoints from this training lineage, this one measured strongest in a 5-way head-to-head evaluation β€” see below.

Architecture

Backbone ResNet, 40 blocks Γ— 192 channels, with channel attention
Head dueling DQN (separate value and advantage heads)
Parameters 11,310,592 (10,773,713 backbone + 536,879 head)
Obs version v3 (libriichi feature encoding)
Checkpoint 43.4 MB, fp32

Training

  • Data: 191,132 Tenhou Houou game records in mjai format, one epoch, no augmentation. A superset of that corpus is published as hhim8826/tenhou-houou-mjai.
  • Steps: 107,200 (batch size 2048)
  • Finished: 2023-03-25

Evaluation

Each challenger played one seat against three copies of this model using libriichi's OneVsThree arena under Tenhou hanchan rules (25,000 start, tobi, θ₯Ώε…₯). Every challenger saw the same deal seeds, and each seed was played four times with the challenger in each seat. pt is scored +90/+45/0/-135 by placement. Intervals are 95% CIs clustered by seed.

A challenger equal in strength to this model scores 0 pt by construction, so each interval containing 0 means "not distinguishable from this model".

challenger what it is hanchan avg rank ↓ avg pt ↑ (95% CI) result
mortal_model/best.pth sibling checkpoint, v3, 100k steps 4,000 2.4943 -0.24 (-2.33, +1.86) not separable
mortal-120000.pth sibling checkpoint, v3, 144.8k steps 4,000 2.4992 -0.55 (-2.62, +1.52) not separable
mortal_model/mortal_online.pth online-trained checkpoint, v3, 50.8k steps 4,000 2.5445 -1.67 (-3.93, +0.60) tied on pt, worse on rank
best.pth earlier v4 run, 16k steps 1,000 2.5900 -6.84 (-11.44, -2.24) clearly weaker
mortal_model/mortal4/best.pth earlier v4 run, 2.4k steps 1,000 2.6940 -15.03 (-20.07, -9.99) clearly weaker

No checkpoint beat it. Two are statistically indistinguishable from it, one is worse on placement, and the two early v4 runs are clearly weaker.

Harness control

Running this model against three copies of itself returned avg rank 2.5005 and +0.045 pt over 4,000 hanchan, with placements [999, 997, 1007, 997] β€” the expected exact-symmetry result, which confirms the arena has no seat or scoring bias.

Limitations

  • Relative, not absolute. These numbers compare checkpoints from one training run. The model has not been measured against the official Mortal releases, akochan, or human players, so its absolute strength is unknown.
  • Rule scope. Trained and evaluated on four-player hanchan with red fives. Not evaluated on three-player (sanma) or tonpuusen.
  • The best_perf field recorded inside the original training checkpoint ({'avg_rank': 2.416, 'avg_pt': 6.3}) refers to whatever opponent was current during training and is not comparable to the table above.

Usage

Needs Mortal and its libriichi extension. Point the config at this checkpoint:

import torch
from model import Brain, DQN
from engine import MortalEngine
from libriichi.mjai import Bot

state = torch.load("mortal.pth", map_location="cpu", weights_only=True)
cfg = state["config"]
version = cfg["control"]["version"]

brain = Brain(version=version, **cfg["resnet"]).eval()
dqn = DQN(version=version).eval()
brain.load_state_dict(state["mortal"])
dqn.load_state_dict(state["current_dqn"])

engine = MortalEngine(
    brain, dqn, version=version, is_oracle=False,
    device=torch.device("cpu"), enable_amp=False,
    enable_quick_eval=True, enable_rule_based_agari_guard=True, name="mortal",
)
bot = Bot(engine, player_id=0)  # then feed it mjai events

This checkpoint holds only what inference needs β€” weights plus version and the ResNet shape. Optimizer, scheduler and scaler state were removed, which is why it is 43 MB rather than 142 MB. It cannot be used to resume training.

Files

file what it is
mortal.pth PyTorch weights (43 MB) β€” needs torch plus Mortal's model.py
mortal.onnx The same network exported as one graph, (obs, mask) -> q values, with illegal actions already -inf. Runs on onnxruntime alone, no torch.
grp.onnx The global reward predictor: one feature row per kyoku in, a distribution over the 24 finishing orders out. Used for placement probabilities, not for choosing moves.
model_meta.json Full training hyper-parameters

The ONNX graph was checked against the PyTorch model on real game observations: maximum absolute difference on legal actions is around 1e-5 (float32 rounding), and the chosen action never differs. Serving from ONNX rather than torch cut a demo app's peak memory from 633 MB to 366 MB.

Provenance

Built with Mortal (AGPL-3.0-or-later). Training data came from Tenhou game records; Tenhou publishes terms governing η‰Œθ­œ use on its log listing page. Review those terms for your use case.

SHA-256 of mortal.pth: ec679c428766af25fe2c0520938fffc7047f6c8016e3930f3b6c61fdabe48559

Downloads last month

-

Downloads are not tracked for this model. How to track
Video Preview
loading

Space using hhim8826/mortal3-b40c192 1