Skip to content

Kymi808/mahjong-ai

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mahjong AI

Competitive Mahjong AI engine supporting both Japanese Riichi (4-player) and MCR (Chinese Official) rules, with rule-specific strategy profiles designed for high-level play.

Features

Dual Rule Set Support

  • Japanese Riichi Mahjong: Full yaku detection (30+ yaku including all yakuman), han/fu scoring, furiten tracking, riichi declaration
  • MCR (Chinese Official): 81 fan pattern detection with exclusion rules, minimum 8-fan validation

AI Strategy Engine

  • Riichi Strategy (Defensive): Tile efficiency optimization, push/fold EV framework, suji/kabe safety analysis, conservative calling policy, riichi timing
  • MCR Strategy (Aggressive): Fan-targeting hand building, liberal calling policy, fan preservation scoring

Core Engine

  • Shanten Calculator: Recursive suit decomposition with caching for fast tiles-to-tenpai calculation
  • Tile Efficiency (Ukeire): Acceptance width calculation for optimal discard selection
  • Defense Module: Suji inference, kabe (wall) analysis, composite danger evaluation, EV-based push/fold decisions
  • Monte Carlo Simulation: Hidden tile sampling for probability estimation
  • Game Engine: Complete game loop with draw, discard, chi/pon/kan, riichi, tsumo/ron
  • Arena: Agent-vs-agent evaluation framework

Installation

pip install -e ".[dev]"

Quick Start

from mahjong_ai.ai.agent import MahjongAgent
from mahjong_ai.rules.riichi import RiichiRuleSet
from mahjong_ai.training.arena import Arena

# Create 4 AI agents
players = [MahjongAgent.riichi() for _ in range(4)]

# Run a match
arena = Arena(RiichiRuleSet(), players)
stats = arena.run_match(num_rounds=8, num_games=100)
print(stats.summary())

Shanten Calculation

from mahjong_ai.core.tiles import TileSet
from mahjong_ai.shanten import shanten, ukeire

hand = TileSet.from_string("123m456p789s12z")
print(f"Shanten: {shanten(hand)}")

count, accepting = ukeire(hand)
print(f"Acceptance: {count} tiles, kinds: {accepting}")

Hand Scoring

from mahjong_ai.core.hand import Hand, WinContext, WinType
from mahjong_ai.rules.riichi.scoring import calculate_score

hand = Hand.from_string("123m456p789s11177z")
ctx = WinContext(win_tile=33, win_type=WinType.RON, is_riichi=True)
score = calculate_score(hand, ctx)
print(f"{score.han} han / {score.fu} fu = {score.total_points} points")
print(f"Yaku: {score.yaku}")

Architecture

mahjong_ai/
├── core/           # Tile representation (34-array), melds, hands, wall, game state
├── shanten/        # Shanten calculator + tile efficiency (ukeire)
├── rules/
│   ├── riichi/     # Yaku detection, han/fu scoring, furiten tracking
│   └── mcr/        # 81 fan patterns, exclusion rules, MCR scoring
├── engine/         # Game loop, actions, player interface
├── defense/        # Suji, kabe, danger evaluation, push/fold framework
├── ai/             # Strategy agents, hand evaluator, Monte Carlo simulation
└── training/       # Arena for agent evaluation

Tile Notation

Numbered suits: 123m (man/characters), 456p (pin/circles), 789s (sou/bamboo)
Honors (z):     1=East, 2=South, 3=West, 4=North, 5=White, 6=Green, 7=Red

Testing

pytest tests/ -v

Roadmap

  • Cython-accelerated shanten for 100x speedup
  • Neural network policy via self-play reinforcement learning
  • Opponent modeling from discard pattern analysis
  • Tenhou/Majsoul replay import for supervised pre-training
  • MCR knitted pattern support in shanten calculator
  • Web interface for human vs AI play

License

MIT

About

Competitive Mahjong AI for Japanese Riichi and MCR (Chinese Official) rules

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages