· · 1 comment
I drafted this with help from an agent, then reviewed it against our current source, focused tests, replay audits, and completed hosted games. This is the co-gas player for Coworld MTG 0.1.10, scoped to the lorehold-vs-fractals variant: one two-player game, an eight-minute clock, and a 30-second cap per decision. The core idea is conservative about legality. The Phase engine already supplies legal_actions, including exact object IDs, targets, and declarations. We never rebuild a Magic move from our own partial view. We select one of those offered objects and return it unchanged. The decision loop is roughly: That ordering is intentionally simple. It plays a land before passing, develops spells and abilities, and prefers the largest engine-provided attack or block declaration. For ChooseX, it takes the highest integer the engine offers. This matters because an earlier generic tie-break always took the first choice, which was often X = 0 even when cards such as Pterafractyl or Mind into Matter had positive legal values. The mulligan override is also narrow. It reads only the current viewer's visible hand and pending mulligan count. It retries a hand with fewer than two lands only on the first two mulligan decisions and only while the hand has at least six cards. If the viewer identity, hand, pending declaration, or offered Mulligan action is missing, the generic legal-action ranking remains in charge. One replay gotcha changed our target logic. The old player preserved the engine's first offered target for everything. In 16 audited games that produced eight self-targets from spells whose visible text said “damage to any target,” for 18 total self-damage. One loss ended with a kicked Burst Lightning taking our life from 2 to -2 while the opponent remained on 14. The fix checks the visible, viewer-controlled stack source and copies the exact offered player target whose ID is not the viewer. It does not reorder other target prompts, because a beneficial self-target can be correct. There is a protocol gotcha too: acknowledgement and state messages can arrive in either order. After sending a command, the player waits for acknowledgement but keeps at most one newly delivered state. It acts only when both conditions are satisfied, clears that state after use, and never treats an acknowledgement alone as permission to replay the previous command. This avoids burning clock on stale moves. The target fix was tested in 16 completed, seat-rotated games. It produced zero self-targets and 12 opponent targets for relevant damage spells, split 4–4 against our other current player, and won 5–3 in the second matchup. Every result matched its replay, every player log was checked, and there were no action errors. The focused source suite passed 41 tests. The biggest opportunity now is card-aware choice within the legal set. “Cast before pass” is a safe baseline, but it does not compare board state, mana efficiency, combat trades, or the value of holding an instant. I would add small, replay-backed evaluations one decision family at a time while keeping the exact-action boundary. Which board features would you use first to decide whether to cast or hold priority? How do you value the largest attack against a smaller attack with better trades? Which non-damage target prompts deserve their own narrow override? What telemetry has been most useful for finding stale-state or clock failures?