Fix enabler phrasing, wake two silent jokers, read the board order

* The tooltip mis-taught every pure enabler. JCA.explain used a cluster
  tag's `both` text whenever EITHER side was a full member, so Four
  Fingers next to Runner claimed "both reward Straights" -- Four Fingers
  does not reward Straights, it makes them reachable. `both` now requires
  both sides, and every cluster tag carries give/want phrasings.

* Blue Joker and Abstract Joker scored 0 against all 150 jokers. Blue
  Joker scales on #G.deck.cards, so it wants card_gen (DNA, Marble,
  Certificate); Abstract scales on #G.jokers.cards, so it wants joker_gen
  (Riff-Raff is +6 Mult on its own). Both verified in card.lua. Steel and
  Glass Joker look like the same fix but are NOT: they need Steel/Glass
  specifically, and the only enhance_gen givers make Gold and Stone, so
  tagging them would invent a synergy that does not exist.

* Copy jokers are positional and the board order was there all along.
  JCA.copy_source reports what an owned Blueprint/Brainstorm is actually
  copying, including when the target is one of the 29 centers vanilla
  refuses to copy (blueprint_compat = false), or when it is copying
  nothing at all.

* The sell advisor now counts clashes when ranking what to cut. JCA.score
  stays pure -- a trap must never make a card look like a combo -- but a
  joker eating another one's payoff is exactly the one to sell.

The suite caught a real bug while writing this: `(mode == 'right') and
cards[idx+1] or cards[1]` falls through to the LEFTMOST joker when the
right-hand slot is nil, so a rightmost Blueprint would have named the
wrong card. 673 pass here, 9 in-game via the smoke harness.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-14 12:24:33 -07:00
parent bf0672a438
commit e688de0efb
4 changed files with 226 additions and 19 deletions
+18 -2
View File
@@ -88,9 +88,21 @@ Three-layer split; `JCA` is the single global namespace:
All hook bodies are pcall-wrapped so a scoring bug can never crash a
run — keep it that way.
- Sell advisor: `JCA.weakest_link()` (full board + ≥3 jokers + a strict
minimum required, else nil) flags the lowest-total owned joker with a
minimum required, else nil) flags the lowest-scoring owned joker with a
red verdict row; suppressed by learning mode, toggled by
`config.sell_advisor`.
`config.sell_advisor`. Its ranking subtracts `CLASH_PENALTY` (odd, so it
always breaks a tie) per clash with an owned joker — the joker eating
another one's payoff is the one you want to cut. This is the **only**
place a clash changes a number; `JCA.score` stays pure, because a trap
must never make a card look like a combo.
- Copy advisor: `JCA.copy_source(card)` returns what an owned Blueprint or
Brainstorm is *actually* copying, from the live board order — Blueprint
takes the joker to its right, Brainstorm the leftmost — plus whether
vanilla will copy it at all (29 centers carry `blueprint_compat = false`).
The tooltip names the target, or says it is copying nothing. Do not
rebuild this with the `a and b or c` idiom: for a rightmost Blueprint the
right-hand slot is nil and the idiom falls through to the leftmost joker,
confidently reporting the wrong card.
- Public API for other mods: `JCA.register(key, gives, wants, opts)`,
`JCA.register_pair(a, b, blurb)` (sets `JCA._pairs_dirty` so the
Combos tab re-sorts), `JCA.register_clash(a, b, warning)`. Unknown
@@ -147,6 +159,10 @@ Three-layer split; `JCA` is the single global namespace:
`spectral_gen`): put the same tag in *both* `gives` and `wants` of every member
so members mutually reinforce (2+2 = 4). Pure enablers (e.g. Four Fingers,
Smeared, Pareidolia, DNA) only `give`; pure payoffs only `want`.
A cluster tag needs all three `TAG_TEXT` phrasings, not just `both`: `both` is
only true when *both* jokers sit on both sides of the tag, and `JCA.explain`
requires that before using it. Four Fingers does not "reward Straights" — it
makes them reachable. The suite enforces the three phrasings.
- A tag needs **both sides to exist, on at least two different jokers**: something
must give it, something must want it, or it is dead data that can never change a
score — and if it is also a theme, an achievement nobody can earn. `lua test.lua`