inthearena
A research bridge that drives Magic: The Gathering agents from real MTG Arena game data.
inthearena.mtga parses MTGA's detailed client log (its GRE message stream) into typed (pydantic) game state
and decision points, then lets a decision Policy pick from the legal options the client is already handed.
The first wired policy is AggroPolicy — a relentless develop-and-attack bot — run read-only over your own
game logs ("shadow" mode).
from inthearena.mtga import iter_decisions, AggroPolicy, cards
pol = AggroPolicy()
for d in iter_decisions(): # typed decisions from your local Player.log
print(d.view.phase, d.kind, "->", pol.decide(d))
cards.card_name(79416) # -> 'Arcane Signet' (grpId -> name, from the local card DB)
python -m inthearena.mtga.shadow # replay your games; print what aggro would do at each decision
⚠️ Read this first
This project reads / can automate a live commercial game client. Read DISCLAIMER.md before using it. In short: automating the MTGA client violates its Terms of Service (and can get an account banned), prior art already exists, and this is shared for research — treat it sensitively, and prefer the read-only mode.
What's here
mtga/gre.py— parsePlayer.loginto typed GRE objects; diff-accurate gameplay state; surface decisions.mtga/snapshot.py— the gameplay state as a readable snapshot and asmtg-engine facts.mtga/policy.py—Policyprotocol +AggroPolicy(chooses from MTGA's legal menu; no rules engine needed).mtga/cards.py— resolvegrpId→ English card name from the client's local SQLite card database.mtga/engine.py— position anmtg.Gameat the current board by determinization (visible info fed, hidden zones random-filled); format-aware (Brawl vs Standard → engine variant + commander).mtga/views.py—RecognizedViews(Home, Play menu, Recently played, GamePlay) + where each view's clickable elements sit;navigate.py'sNavigatorwalks Home -> Play menu -> queue all the way into a game.mtga/screen.py— recognize the current view from the latest log scene and/or a pluggable image model.mtga/navigate.py— drive a non-game view INTO a game via a pluggableActuator(no-op by default; the real pyautogui backend is opt-in,pip install inthearena[act], and ToS-relevant — see DISCLAIMER.md). The cursor glides A→B with a wobbled path + jittered speed, lands at a varied spot within the button, and skips the move if it's already there.mtga/vision.py— locate a button on screen with a small local vision model (MoondreamLocator) so click targets come from the live screen, not coordinate estimates (opt-in,pip install inthearena[vision]).mtga/macos.py— find MTGA's window on whichever monitor it's on (find_mtga_window) and capture just that region, so navigation/vision work on a secondary or Retina display, not only the primary one.mtga/live.py— followPlayer.logas it's written (tail -f);LiveStatekeeps board + view current.mtga/shadow.py— run a policy read-only over a log.
Status
Early research. The read + decide half (log → typed state → policy choice, with card names) works today. Driving the live client to actually play is intentionally not included here — that is the ToS-relevant piece (see the disclaimer).
Install (dev)
pip install -e . # needs pydantic>=2
PYTHONPATH=src python3 tests/test_mtga.py
Distributed on PyPI as inthearena (placeholder release; the real API lands in a later version). MIT licensed.
Release files for inthearena 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| inthearena-0.1.0.tar.gz | 144.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| inthearena-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 254.1 kB
Release files / inthearena-0.1.0.tar.gz
| Download URL | inthearena-0.1.0.tar.gz |
|---|---|
| Size | 144.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aee41fae1d1020ece31ff4c04ab3d1c4131ce93dffb4f7c7ff7315695d61a769
|
|
BLAKE2b-256 checksum How to use checksums |
c6fd126c2a82ca377d14a859f4bf8707f60355d2b35830caf762ee802df1ce3b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Release files / inthearena-0.1.0-py3-none-any.whl
| Download URL | inthearena-0.1.0-py3-none-any.whl |
|---|---|
| Size | 110.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f3ec418cb790ae2c423ab65bd8279c69fe1d8120369cdf2f0205701187317f53
|
|
BLAKE2b-256 checksum How to use checksums |
00053b2f5305501a28814e0c1ab6b78db0806a17eccd416ac44d55e744dc4131
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|