From bd160bb42e3e6fddf96b2629abe0ffc8bb11753f Mon Sep 17 00:00:00 2001 From: Timmy Date: Fri, 30 Oct 2026 18:04:19 +0000 Subject: [PATCH] =?UTF-8?q?timmy:=20TM=20formidable-opponent=20build=20?= =?UTF-8?q?=E2=80=94=20table=20directive,=20plans/agendas,=20geometric=20s?= =?UTF-8?q?coring,=20starve-guard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- checkins/2026-10-30-timmy-tm-formidable.md | 99 ++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 checkins/2026-10-30-timmy-tm-formidable.md diff --git a/checkins/2026-10-30-timmy-tm-formidable.md b/checkins/2026-10-30-timmy-tm-formidable.md new file mode 100644 index 0000000..1f3e51c --- /dev/null +++ b/checkins/2026-10-30-timmy-tm-formidable.md @@ -0,0 +1,99 @@ +# Timmy — TM "formidable opponent" build, 2026-10-30 + +*Authored as Timmy (operating partner). Review request for the troupe.* + +## The problem this build answers + +Timmy's Terraforming Mars seat is **0-10** against Alexander, losing by 26–70 points every +game. The last loss (G10: 30 vs 165) exposed the root failure precisely: **TR froze at 17 for +six straight generations** while the seat banked 37 steel + 18 heat + 5 titanium + 4 plants + +25 MC and played 17 cards to Alexander's 77. The deterministic scorer graded every option *in +isolation* — it had no idea it was losing the TR race, what was rotting in the bank, or what +lane it had committed to at the opening. The fixes below wire the *whole table* into the +decision layer, and make the seat decide from a **multi-step agenda** instead of cold-scoring +every turn. + +## What changed (5 items, all in `/root/tm-ai/tm-ai-server/src/tm_llm/`) + +1. **Table directive — the fundamental fix.** `strategy.py:69 _table_directive(state)` reads my + TR vs the opponents' leader, banked resources, and committed strategy. When **behind on TR + (>3 below the leader)**, terraforming cards get `+22`, resource conversion and terraforming + standard projects get `+12`, forcing the TR hunt above normal card play. This is the fix for + "TR froze at 17" — the scorer now *knows* it's losing the clock race and acts on it. + +2. **Plans/agendas, not cold decisions.** `strategy.py:93 derive_plan(state)` returns an ordered + agenda from the committed strategy (space → titanium_production → tag_engine → discounts → + points; ground → plant_production → convert → points; etc.), overridden by phase (late → + points) and table position (behind → terraform/convert). `strategy.py:130 _option_directive` + maps each option to one directive; the **top 2 agenda directives get `+8`** in + `choose_action` (`strategy.py:167`) and `_score` (`strategy.py:238`). Alexander's exact + words, implemented: *"you don't make decisions every single turn — you create paths and + plans … your top 2/3 actions come from your agendas."* + +3. **Geometric/exponential scoring.** `card_ev.py:310 compound` adds a bonus for cards that + COMPOUND — discount, card draw, tag-scaling production, broad production — weighted by timing + (`×1.0` early, `×0.25` late). A discount engine is worth more early because it makes every + future card cheaper. Probe: `Earth Catapult` grades **S 9.5 early → A 6.7 late**. + +4. **Committed strategy reaches the scorer.** `card_ev.py:246 detect_strategy` (from + corporations, stable all game) + `card_ev.py:270 strategy_fit` (weights cards to the + archetype). Under a Saturn Systems start, jovian cards grade S while an off-strategy building + card stays C. The strategy is also printed as `COMMITTED STRATEGY:` in the action prompt + (`prompts.py`). + +5. **Starve-the-generation guard.** `engine.py:29 _LAST_PICK` + `engine.py:32 _waiting_key` + track the last returned deterministic pick; when the TM server rejects it and re-offers the + identical decision, `choose_action` gets it as `blocked_idx` and cycles to the next-best + option instead of looping on the same card (G10 live: "Spin-off Department" re-picked 7×). + Plus an affordability guard on card-play (budget = MC + steel×2 building + titanium×3 space). + +## Verification (run from this host, all green) + +```bash +cd /root/tm-ai/tm-ai-server && .venv/bin/python -c " +import sys; sys.path.insert(0,'src') +from tm_llm import strategy, card_ev, engine +# behind on TR forces a terraforming card +s={'game':{'temperature':2,'oxygen':5,'oceanCount':4,'generation':8}, + 'player':{'terraformRating':17,'megacredits':50,'steel':0,'titanium':0,'plants':0,'heat':0,'corporations':['Helion']}, + 'opponents':[{'name':'Alexander','terraformRating':59}]} +opts=[{'title':'Play project card: Acquired Company','index':0}, + {'title':'Play project card: Deimos Down','index':1}] +assert strategy.choose_action(s,{'type':'or'},opts)[0]==1 # Deimos Down (terraform) forced +# space plan: titanium production on agenda +sp={'game':{'temperature':-10,'oxygen':2,'oceanCount':1,'generation':2}, + 'player':{'terraformRating':20,'megacredits':50,'steel':0,'titanium':0,'plants':0,'heat':0,'corporations':['Phobolog']}, + 'opponents':[{'name':'A','terraformRating':21}]} +o2=[{'title':'Play project card: Titanium Mine','index':0},{'title':'Play project card: Acquired Company','index':1}] +assert strategy.choose_action(sp,{'type':'or'},o2)[0]==0 # on-plan titanium +assert strategy.derive_plan(sp)[0]=='titanium_production' +# geometric: discount engine decays +assert card_ev.card_ev('Earth Catapult',{'game':{'temperature':-30,'oxygen':0,'oceanCount':0,'generation':1},'player':{'corporations':['CrediCor'],'production':{},'tags':{}}})[0] > \ + card_ev.card_ev('Earth Catapult',{'game':{'temperature':6,'oxygen':11,'oceanCount':7,'generation':12},'player':{'corporations':['CrediCor'],'production':{},'tags':{}}})[0] +# starve guard present +assert hasattr(engine,'_waiting_key') and hasattr(engine,'_LAST_PICK') +print('ALL GREEN') +" +``` + +Service restarted and active: `systemctl is-active tm-ai-server` → `active`. + +## Ask (review against these, per wizard) + +- **Argus (evidence law):** each of the 5 items is claimed at a `file:line` above — confirm the + code actually lives there and does what the check-in says, and that the verification command + reproduces `ALL GREEN` from this host. +- **Beam / Merlin (deep reasoning):** hunt for a regression. Specifically: does the `+22`/`+12` + TR-hunt boost, combined with the `+8` plan boost, ever out-score a milestone (70) or an S-tier + engine card in a way that's *wrong*? Is `compound` double-counting `discount_value`/`draw_value` + (both still in the score line)? Does `_option_directive` misclassify any card type? +- **Volt (workhorse):** the residual open bug — the G10 "Spin-off Department" card was affordable + and shape-legal yet never resolved (server-side `getCardCost` may exceed the model's + `calculatedCost` in `checkPaymentAndPlayCard`). Confirm or falsify that hypothesis; the guard + (item 5) now contains the loop but doesn't fix why that card never played. + +## Next + +Playtest against Alexander; if the TR race is no longer lost by 40+ points, the directive/plan +layer is doing its job. Record the next loss as G11 in `strategy-lessons.md` and keep the lesson +loop wired to the scorer.