# aaaaha0/ai-mahjong-table architecture

> Architecture diagram of the GitHub repository aaaaha0/ai-mahjong-table, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/aaaaha0/ai-mahjong-table
- Repository: https://github.com/aaaaha0/ai-mahjong-table

## Overview

Mahjong Web Table combines a deterministic four-seat rules engine with a browser debug table and configurable human, random, debug, and LLM seats. The primary workflow is to configure a rule, seed, and seats in the browser; create a session; submit actions or ask a controller to choose among legal actions; then inspect snapshots, events, replay, or a FullLog. The graph preserves rule-driven play, tile/wall handling, controller integration, and inspection paths. Some runtime wiring is inferred only from module names and README capabilities because source excerpts are partial.

Main entry points: [`src/mahjong_ai/game/table.py`](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/table.py) (Table Engine), [`src/mahjong_ai/web/session.py`](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/session.py) (Session Manager), [`src/mahjong_ai/web/app.py`](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/app.py) (Web API), [`src/mahjong_ai/game/physical_table.py`](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/physical_table.py) (Physical Operations)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web Table"]
  node_ui["Table UI<br/>[app.js]"]
  node_api["Web API<br/>[app.py]"]
  node_session["Session Manager<br/>[session.py]"]
  node_schemas["API Schemas<br/>[schemas.py]"]
end

subgraph group_engine["Table Engine"]
  node_table["Table Engine<br/>[table.py]"]
  node_physical["Physical Operations<br/>[physical_table.py]"]
  node_state["Table State<br/>[state.py]"]
  node_response["Response Windows<br/>[response_window.py]"]
  node_match["Match Controller<br/>[match.py]"]
end

subgraph group_rules["Rules and Tiles"]
  node_rules_base["Rule Contract<br/>[base.py]"]
  node_rule_loader["Rule Loader<br/>[loader.py]"]
  node_tuidaohe["Tuidaohe Rules<br/>[ruleset.py]"]
  node_wall["Wall Provider<br/>[duplicate.py]"]
  node_tiles["Tile Model<br/>[tile.py]"]
  node_actions["Actions and Scores<br/>[action.py]"]
end

subgraph group_agents["Player Controllers"]
  node_agent_base["Agent Contract<br/>[base.py]"]
  node_executor["Agent Executor<br/>[executor.py]"]
  node_random_agent["Random Agent<br/>[random.py]"]
  node_llm_agent["LLM Adapter<br/>[llm.py]"]
end

subgraph group_inspection["Game Inspection"]
  node_observation["Observation Builder<br/>[builder.py]"]
  node_replay["Replay<br/>[replay.py]"]
  node_snapshot["Snapshot<br/>[snapshot.py]"]
  node_event["Game Events<br/>[event.py]"]
end

node_browser(("Debug Browser"))
node_llm_service(("LLM Endpoint"))

node_browser -->|"uses"| node_ui
node_ui -->|"calls API"| node_api
node_api -->|"validates payloads"| node_schemas
node_api -->|"dispatches requests"| node_session
node_session -->|"loads rules"| node_rule_loader
node_session -->|"creates and drives"| node_table
node_session -->|"requests decisions"| node_llm_agent
node_table -->|"queries rule contract"| node_rules_base
node_table -->|"executes operations"| node_physical
node_table -->|"updates and reads"| node_state
node_table -->|"resolves responses"| node_response
node_rule_loader -->|"loads plugin"| node_tuidaohe
node_tuidaohe -->|"implements"| node_rules_base
node_physical -->|"deals and draws"| node_wall
node_physical -->|"moves tiles"| node_tiles
node_tuidaohe -->|"produces legal actions"| node_actions
node_table -->|"accepts submitted actions"| node_actions
node_match -->|"controls matches"| node_table
node_executor -->|"runs agents"| node_agent_base
node_random_agent -->|"implements"| node_agent_base
node_llm_agent -.->|"requests action choice"| node_llm_service
node_session -->|"builds observations"| node_observation
node_table -->|"provides replay"| node_replay
node_session -->|"serializes replay"| node_replay
node_session -->|"serializes snapshot"| node_snapshot
node_session -->|"serializes events"| node_event
node_table -->|"records events"| node_event

click node_ui "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/static/app.js"
click node_api "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/app.py"
click node_session "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/session.py"
click node_schemas "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/schemas.py"
click node_table "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/table.py"
click node_physical "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/physical_table.py"
click node_state "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/state.py"
click node_response "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/response_window.py"
click node_match "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/match.py"
click node_rules_base "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/rules/base.py"
click node_rule_loader "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/rules/loader.py"
click node_tuidaohe "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/rules/tuidaohe/ruleset.py"
click node_wall "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/walls/duplicate.py"
click node_tiles "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/common/tile.py"
click node_actions "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/common/action.py"
click node_agent_base "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/base.py"
click node_executor "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/executor.py"
click node_random_agent "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/random.py"
click node_llm_agent "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/llm.py"
click node_observation "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/observation/builder.py"
click node_replay "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/replay.py"
click node_snapshot "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/snapshot.py"
click node_event "https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/common/event.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_ui,node_api,node_session,node_schemas,node_browser toneBlue
class node_table,node_physical,node_state,node_response,node_match toneAmber
class node_rules_base,node_rule_loader,node_tuidaohe,node_wall,node_tiles,node_actions toneMint
class node_agent_base,node_executor,node_random_agent,node_llm_agent toneRose
class node_observation,node_replay,node_snapshot,node_event,node_llm_service toneIndigo
```

## Components

### Web Table

- [Table UI](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/static/app.js): `src/mahjong_ai/web/static/app.js`
- [Web API](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/app.py): `src/mahjong_ai/web/app.py`
- [Session Manager](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/session.py): `src/mahjong_ai/web/session.py`
- [API Schemas](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/web/schemas.py): `src/mahjong_ai/web/schemas.py`

### Table Engine

- [Table Engine](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/table.py): `src/mahjong_ai/game/table.py`
- [Physical Operations](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/physical_table.py): `src/mahjong_ai/game/physical_table.py`
- [Table State](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/state.py): `src/mahjong_ai/game/state.py`
- [Response Windows](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/response_window.py): `src/mahjong_ai/game/response_window.py`
- [Match Controller](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/match.py): `src/mahjong_ai/game/match.py`

### Rules and Tiles

- [Rule Contract](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/rules/base.py): `src/mahjong_ai/rules/base.py`
- [Rule Loader](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/rules/loader.py): `src/mahjong_ai/rules/loader.py`
- [Tuidaohe Rules](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/rules/tuidaohe/ruleset.py): `src/mahjong_ai/rules/tuidaohe/ruleset.py`
- [Wall Provider](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/walls/duplicate.py): `src/mahjong_ai/walls/duplicate.py`
- [Tile Model](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/common/tile.py): `src/mahjong_ai/common/tile.py`
- [Actions and Scores](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/common/action.py): `src/mahjong_ai/common/action.py`

### Player Controllers

- [Agent Contract](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/base.py): `src/mahjong_ai/agents/base.py`
- [Agent Executor](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/executor.py): `src/mahjong_ai/agents/executor.py`
- [Random Agent](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/random.py): `src/mahjong_ai/agents/random.py`
- [LLM Adapter](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/agents/llm.py): `src/mahjong_ai/agents/llm.py`

### Game Inspection

- [Observation Builder](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/observation/builder.py): `src/mahjong_ai/observation/builder.py`
- [Replay](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/replay.py): `src/mahjong_ai/game/replay.py`
- [Snapshot](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/game/snapshot.py): `src/mahjong_ai/game/snapshot.py`
- [Game Events](https://github.com/aaaaha0/ai-mahjong-table/blob/main/src/mahjong_ai/common/event.py): `src/mahjong_ai/common/event.py`

### Other components

- **Debug Browser**
- **LLM Endpoint**

## Connections

- Debug Browser → Table UI: uses
- Table UI → Web API: calls API
- Web API → API Schemas: validates payloads
- Web API → Session Manager: dispatches requests
- Session Manager → Rule Loader: loads rules
- Session Manager → Table Engine: creates and drives
- Session Manager → LLM Adapter: requests decisions
- Table Engine → Rule Contract: queries rule contract
- Table Engine → Physical Operations: executes operations
- Table Engine → Table State: updates and reads
- Table Engine → Response Windows: resolves responses
- Rule Loader → Tuidaohe Rules: loads plugin
- Tuidaohe Rules → Rule Contract: implements
- Physical Operations → Wall Provider: deals and draws
- Physical Operations → Tile Model: moves tiles
- Tuidaohe Rules → Actions and Scores: produces legal actions
- Table Engine → Actions and Scores: accepts submitted actions
- Match Controller → Table Engine: controls matches
- Agent Executor → Agent Contract: runs agents
- Random Agent → Agent Contract: implements
- LLM Adapter → LLM Endpoint: requests action choice
- Session Manager → Observation Builder: builds observations
- Table Engine → Replay: provides replay
- Session Manager → Replay: serializes replay
- Session Manager → Snapshot: serializes snapshot
- Session Manager → Game Events: serializes events
- Table Engine → Game Events: records events
