- Python 69.5%
- C 18.6%
- HTML 11.4%
- Shell 0.5%
| dev | ||
| docs | ||
| plugins | ||
| reference | ||
| screenshots | ||
| scripts | ||
| site | ||
| test_data | ||
| .gitignore | ||
| monop_bridge.py | ||
| monop_players.py | ||
| README.md | ||
| run_game.py | ||
| screenshot_integration.py | ||
| screenshot_states.py | ||
| test_house_parser.py | ||
| test_integration_bugs.py | ||
| test_midgame_edge_cases.py | ||
| test_midgame_join.py | ||
| test_midgame_resync.py | ||
| test_parser.py | ||
| test_parser_bugs.py | ||
| test_parser_commands.py | ||
| test_parser_resign.py | ||
| test_players.py | ||
| test_plugin_features.py | ||
monop-state
Live Monopoly board viewer for IRC games using monop-irc.
Watches an IRC channel where monop-irc is running, parses the game output in real time, and serves a web board that auto-refreshes every 2 seconds.
Architecture
monop-irc binary
│ (stdout → IRC via bridge)
▼
monop_bridge.py ────────────────────── IRC channel (#monop)
│
Cardinal IRC bot
(monop plugin)
│
┌───────────────┼───────────────┐
│ │ │
game-state.json heartbeat.json api/v1/
│ │ (MiSTy-compatible)
└───────┬───────┘
│
site/index.html
(auto-refreshes @ 2s)
Components:
| Path | Description |
|---|---|
plugins/monop/ |
Cardinal plugin — watches IRC, parses monop output, writes state files |
monop_parser.py |
Core parser — state machine that tracks the full game from IRC log lines |
monop_bridge.py |
Bridge — connects the monop binary's stdin/stdout to an IRC channel |
site/index.html |
Web board viewer — reads game-state.json and renders the board |
scripts/weechat_to_state.py |
CLI tool — parse a WeeChat log file and emit game-state.json |
reference/ |
Source for the monop-irc binary (BSD monop with IRC support) |
dev/ |
Docker Compose dev environment (see below) |
Features
Board viewer:
- Authentic Monopoly board colors with property color bars
- Player tokens with jdenticon avatars and initial badges
- Jail corner with dedicated token placement
- Rent tooltips with gold-highlighted current rent tier
- Houses/hotels rendered inside color bars
- Dice roll flash animation on new rolls
- Monopoly crown (♛) indicator for complete color groups
- Net worth progress bar per player
- GOJF card badges
- Mobile-responsive layout (3→2→1 column breakpoints)
- Debug panel (long-press status dot or Ctrl+Shift+D)
Parser:
- Tracks all game actions: rolls, purchases, auctions, trades, rent, taxes, cards, jail, resign/bankruptcy
- Mid-game join support via
.where,.print, and.holdingsparsing - State restoration on restart — survives Cardinal reconnects without losing ownership
- Heartbeat every 60s (independent of game activity)
- MiSTy-compatible static API file output (
api/v1/board,api/v1/players, etc.)
Parser
monop_parser.py is a pure-Python state machine that processes IRC log lines and reconstructs the full game state: player positions, cash, properties, houses/hotels, mortgages, jail status, GOJF cards, and turn order.
python3 -m pytest -v # 219 tests
Reconnect / Mid-game resync
The parser can bootstrap game state from mid-game by parsing:
.where— player names, numbers, locations, current player.print— full board ownership, mortgages, houses/hotels.holdings/.own— per-player cash, properties, GOJF cards
On Cardinal restart, the plugin restores the parser from the last saved game-state.json so ownership data isn't lost.
WeeChat log replay
Convert a WeeChat #monop log file into a game state:
python3 scripts/weechat_to_state.py path/to/monop.log --out game-state.json --pretty
Plugin Config
In Cardinal's plugin config (e.g. monop-config.json):
{
"channel": "#monop",
"state_file": "site/game-state.json",
"irc_port": 6697,
"irc_ssl": true
}
| Key | Default | Description |
|---|---|---|
channel |
(required) | IRC channel to watch |
bot_nick |
"monop" |
Nick of the monop bot |
state_file |
"game-state.json" |
Path for game state output |
irc_port |
6697 |
IRC port (for display in UI) |
irc_ssl |
true |
Whether TLS is used (for display in UI) |
api_dir |
"api/v1/" |
Directory for MiSTy-compatible API files |
The server hostname is read from cardinal.network automatically.
Dev Environment
Spin up a full local stack with Docker Compose:
docker compose -f dev/docker-compose.yml up --build
This starts:
- Ergo IRCd on
localhost:6667(no auth, no TLS) - monop bridge — starts a game in
#monopwhen the first player joins - Cardinal — observer bot that writes
game-state.json - Web server — board viewer at
http://localhost:8080
Connect any IRC client to localhost:6667, join #monop, and play. The board updates live in the browser.
See dev/README.md for more detail.
Running the site standalone
cd site/
python3 -m http.server 8080
# open http://localhost:8080
The viewer shows a demo board when no game-state.json is present. Use the debug panel (long-press the status dot) to switch between demo states.