MahJax UI Guide
MahJax ships with a FastAPI backend and a static JS frontend, so you can battle the bundled mahjax.no_red_mahjong bots in any browser. This guide shows the basics for running the UI in a release setting.
Quickstart
You need Python 3.10+. Use --reload while developing but turn it off in production.
Core Features
- Instant play – the UI only shows legal actions, so every human move is valid.
- Bilingual board – the backend sends both Japanese and English SVGs, and the toggle swaps between them without extra requests.
- Round insight – modal summaries list winners, yaku, fan/fu, honba, kyotaku, plus a 50-entry action log.
- Observer toggle – hide enemy hands until a non-human Ron/Tsumo or the round end reveals them.
- Pluggable agents – register Python callables with
AgentRegistry(ships withRule-basedandRandom) and they show up right away in/api/agents.
Using the UI
- Header controls: choose the agent, match length (
hanchanorone_round), seat (fixed or random), optional seed, display names, AI delay in ms, and whether to hide opponent hands. The Start and End buttons spawn or delete sessions. - Board & actions: the human seat stays at the bottom. Tile buttons map to discard IDs (
0–33). Extra buttons cover riichi, tsumo, ron, pass, kan, pon, and chi. If only a dummy action remains, an “Advance” button sendsAction.DUMMY. - Scoreboard & log: scores use turn order relative to the human and display current deltas. Logs show discards, calls, and declarations.
- Round summaries: when
_terminated_roundflips on, the server returnsroundSummary, and the UI shows standings plus winner info. Press “Next Round,” or “End Game” ifisGameEndis true.
Extending Agents & UI
- Custom Agents: Register new agents using
AgentRegistry. Your agent must be a callable accepting(state, rng)and returning a valid action ID. - Frontend Customization: Edit
mahjax/ui/static/app.jsandstyles.cssdirectly. No Node.js build step is required.
Adding Custom Agents
To add your own agent to the dropdown menu, create a wrapper script that registers your agent function before starting the app.
- Define your agent: Create a function
(state, rng) -> int. - Register and Run:
# my_ui_app.py
from pathlib import Path
from mahjax.ui.app import create_app
app = create_app()
# Register your agent implementation
app.state.manager.registry.load_callable_from_path(
file_path=Path("path/to/my_agent_impl.py"),
attribute="act", # Function name in your file
description="My Custom Agent"
)
- Run
uvicorn my_ui_app:app --host 0.0.0.0 --port 8000. The agent now appears in/api/agents, so the UI selector lists it right away.
Troubleshooting & Limits
- Blank board? Confirm
mahjax/ui/staticexists and FastAPI mounts it. Check the console for/static404 errors. - Buttons stuck? The game is in
awaiting_aiorround_end. Wait for auto-play or dismiss the summary modal. - AI idle? Check
ai_delay_msand watch/api/game/{id}/autoresponses. - Hidden hands never reveal? Clear the checkbox or note that only non-human wins unhide opponents.
- The current build only supports 4-player Riichi without red dora and runs without auth. Protect it behind a reverse proxy or VPN before exposing it to the internet.