Commit Graph

17 Commits

Author SHA1 Message Date
funman300 43e1ea2bc6 Put the known traps in the catalog, as an open book
A Traps tab joins the synergy catalog: clash duos rendered like the
Combos tab, then the per-joker cautions, one pager spanning both page
kinds. Deliberately no discovery gating and no Progress entry -- the
Combos tab hides pairs to keep the fun of finding them, but a warning
locked behind fielding the bad pair would reward exactly what it warns
against. register_clash now maintains JCA.clash_list alongside the blurb
map so third-party clashes appear on the tab, re-registration updates
without duplicating, and blurbs are read back through clash_blurb at
build time so the newest wording always wins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:18:24 -07:00
funman300 21995589df Answer for shop copiers before the player pays
A purchase always lands in the rightmost slot (buy_from_shop emplaces at
the end, button_callbacks.lua:2279), which the two copiers experience in
opposite ways: a bought Blueprint arrives copying nothing, a bought
Brainstorm copies the leftmost joker immediately. The buy-area tooltip
now says which, by name — JCA.copy_source_if_bought resolves the arrival
target (chaining through a leftmost copier exactly like copy_source),
and Blueprint's line names the joker to slot it against after buying.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:05:02 -07:00
funman300 a2d16ae12f Integrate with the mods actually installed beside us
New integrations.lua, loaded pcall-wrapped at the end of main.lua;
every integration gates on its target's global so a missing mod is
silence. Both targets load before us by priority.

JokerDisplay: each known joker's display definition gains a live
'(2 combos)' counter in JD's own parenthetical reminder style --
the same partner count the hover tooltip names -- by appending a
dynamic element to reminder_text (created when absent) and wrapping
calc_function to fill card.joker_display_values. The wrapper pcalls
the original calc and blanks the text when the new jd_combos config
toggle is off, so it flips mid-run in both directions.

Too Many Jokers: registers the SEARCH_FIELD_FUNCS hook its api.md
documents, indexing every joker under its tag labels on both sides,
so the collection search finds jokers by 'money', 'Hearts',
'held-card retriggers'. Unknown centers stay nil.

The smoke scenario now asserts the JokerDisplay patch against the
real mod: 13/13 in-game.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 14:03:35 -07:00
funman300 2c47449b13 Record the two ways the mod silently vanishes from a boot
The Mods symlink pointed at the repo's pre-rename home and the loader
skipped the mod without a word of complaint - every smoke check failed
with no JCA global before the link was repointed. Document that, the
BMM-disable marker that looks identical (.lovelyignore in the mod
folder), the real Steam library (/mnt/games), and where to re-clone
the smoke harness from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 13:54:07 -07:00
funman300 de67970a15 Stop giving advice the game will not let you follow
Four fixes, all traced to the running source.

* The sell advisor could tell you to sell an ETERNAL joker, which
  Card:can_sell_card refuses outright (card.lua:1993). It now never names
  one, though they still count toward the best score -- they are part of
  the build you are keeping. Advice you cannot take is worse than none.

* Copiers CHAIN. SMODS.blueprint_effect recurses (utils.lua:2269) and
  Blueprint's own blueprint_compat is true, so Blueprint -> Blueprint ->
  Baron really does give two Barons. The tooltip used to answer "Copying
  Blueprint", the one reply that helps nobody; it now walks the chain to
  the joker actually copied and shows the route. Capped at the board size
  like vanilla, and a Blueprint/Brainstorm ring resolves to nothing
  instead of hanging.

* blueprint_compat is tested for TRUTH by vanilla (utils.lua:2254), not
  for `~= false` as I had it. A modded joker that simply omits the flag is
  NOT copyable, and this mod supports other mods' jokers by design, so
  saying otherwise was a lie about someone else's content.

* A debuffed joker copies as nothing (same line), and a debuffed joker
  does nothing at all this blind -- both now say so. Scoring is left
  alone: a debuff is temporary and the advisor advises on the build, so
  hiding a debuffed partner from "Active combos" would misrepresent it.

Also: never call SMODS.is_eternal() from an advisor path. It runs a full
SMODS.calculate_context per call (utils.lua:3079) -- far too heavy for a
hover -- and outside a live run it reported EVERY joker as Eternal, which
silently disabled the sell advisor. The smoke harness caught that; the
stub could not have.

721 pass locally, 12 in-game.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:50:47 -07:00
funman300 96a00d0d0c Add audit.lua: the map that test.lua is not
test.lua is the gate -- it fails on what is broken. This is the map: it
reports what is merely suspicious, and (the actual point) it REMEMBERS.

32 jokers score ~0 against all 150: they give nothing but engine roles
and want nothing, so the advisor has nothing to say about them. For most
that is the correct answer, but I have now worked that question out from
scratch twice, and the reasoning evaporated both times. VERDICTS records
the conclusion for each one, so an audit only surfaces what is new.

It preserves the traps: Steel Joker and Glass Joker look exactly like
Blue Joker and Abstract Joker did, but they want Steel/Glass cards
specifically, and the only enhance_gen givers make Gold and Stone -- so
"fixing" them would invent a synergy that does not exist. That is written
down now instead of being rediscovered.

It also preserves the leads not yet chased (Ceremonial Dagger's
positional destroy, Erosion vs the card-adders, Burglar + Ramen and Green
Joker, Chaos + Flash Card), marked candidate because they are unverified.

A newly-silent joker lands in "never looked at" and fails the audit until
someone decides. AUDIT.md is committed so the map is readable without
running anything.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:28:46 -07:00
funman300 e688de0efb 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>
2026-07-14 12:24:33 -07:00
funman300 bf0672a438 Correct the push-auth note: libsecret, not the tea token
Pushes authenticate through the global libsecret credential helper. The
tea login has auth_method oauth and no token at all, so it cannot create
repos or call the API - it was never what authenticated pushes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:11:49 -07:00
funman300 d31b7502ea Document the in-game smoke harness
The UI hooks are no longer an untested surface: BalatroSmoke boots the
real game and asserts the tooltip, clash, caution, discovery and card
materialize paths against live game state. All 7 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:08:10 -07:00
funman300 47721d1acf Fix a backwards clash, and add 19 verified traps
Every entry here was checked against the running Steamodded source in
Mods/lovely/dump, not from memory.

The headline is a correction: the shipped CLASHES table warned that
Smeared Joker + Flower Pot "cannot make all four" suits. It is backwards.
Flower Pot fills its four suit slots with a greedy if/elseif chain
(card.lua:4256) and SMODS.smeared_check makes Hearts answer for Diamonds
and Spades for Clubs, so the second Heart falls through into the Diamond
slot: any two red + two black cards fill the pot. It is one of the
strongest combos in the game and the mod was steering players away from
it -- while simultaneously scoring the pair +2 via suit_flex, which
should have been the tell. It is now a famous pair.

New clashes (4 -> 22), all traced to the mechanism:
* Burglar zeroes discards_left on blind select (card.lua:2905), which
  switches off every discard-gated joker for the rest of the run: Banner,
  Delayed Gratification, Castle, Yorick, Hit the Road, Burnt, Mail-In
  Rebate, Faceless, Trading Card, and it wipes the discards Drunkard and
  Merry Andy hand you. Delayed Gratification is the cruellest -- "no
  discards used" reads like a synergy, but the code also requires
  discards_left > 0, so it pays exactly $0.
* Vampire strips enhancements in the `before` pass, ahead of the
  per-card `individual` pass where enhancement payoffs are read, so it
  eats what Golden Ticket, Glass, Stone Joker, Marble and Driver's
  License are counting.
* Joker Stencil scales on EMPTY slots, so Riff-Raff and Abstract Joker
  fight it.
* Splash makes every played card score, so a face card that used to be a
  harmless kicker now resets Ride the Bus.

New cautions (3 -> 15): the positional traps (Blueprint dead in the
rightmost slot, Brainstorm in the leftmost), Mime doing nothing without a
held-card payoff, and the decay timers, whose numbers are exact from
game.lua (Ice Cream 100/5 = 20 hands, Popcorn 20/4 = 5 rounds).

Also corrects the stale game path in CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 11:22:35 -07:00
funman300 07cada9e49 Add a test suite, and fix the three dead-data bugs it found
There was no test file -- CLAUDE.md described the harness in prose and
referred to an "orphan-tag check" that did not exist. test.lua now stubs
the game globals and exercises the real engine, database and catalog tab
builders. It found three bugs on its first run:

* four_kind was the only theme in the catalog that could never be
  discovered. Theme discovery needs a giver and a wanter on two DIFFERENT
  fielded jokers, and The Family was its sole member -- so the Hands bar
  and the overall Progress bar could never reach 100%. DNA is the real
  enabler (copying a card is how you stack duplicate ranks, the only
  vanilla route to a reliable Four of a Kind), so it now gives the
  matching-hand tags as a pure enabler.

* hand_level was given by Space Joker and Burnt Joker and wanted by
  nobody, so it could never contribute to a score and its "want" tooltip
  text was unreachable. Nothing in vanilla rewards hand levels; the tag
  is dropped rather than faked.

* Invisible Joker had no tags at all, so it scored 0 against the entire
  game. Selling it duplicates one of your Jokers -- the same "stronger
  target, better payoff" logic Blueprint and Brainstorm already model --
  so it now wants copy_target.

The suite guards both directions of the tag contract (no orphan wants, no
dead gives), theme reachability, blurb widths, the inert-joker list, and
the card materialize fix from the previous commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 11:15:10 -07:00
funman300 38d4f5d1b7 Document the new features in README and CLAUDE.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 14:08:22 -07:00
funman300 4a882e8101 Add anti-synergy warnings: CLASHES pairs and per-joker CAUTIONS
Warning-only data in synergies.lua — never touches the synergy score.
Tooltips gain a red 'Clashes - <owned joker>: <why>' line when a hovered
joker fights one you own (Ride the Bus + Pareidolia, Vampire vs Steel
Joker/Lucky Cat, Smeared vs Flower Pot), and a 'Caution:' line in the
buy area for jokers that harm a board you keep (Ceremonial Dagger,
Madness, Stencil). Learning mode keeps warnings — they teach.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 13:58:10 -07:00
funman300 e37b56471b Cap generic mult/xmult bonus per candidate; opt Stencil out of it
Any xMult joker used to pulse 'recommended' on a board of four unrelated
+Mult/+Chips jokers: the generic engine-complement +1 in JCA.score
accumulated once per owned joker in partners_for, reaching the threshold
of 4 with zero listable partners (pairwise scores never hit 2), so the
card pulsed while its own tooltip said 'No synergy with your jokers.'

- partners_for now counts the generic +1 once per candidate. Tag/pair
  scores are even, so the generic bonus can no longer flip a
  recommendation at all; a pulsing card always has a nameable partner.
- Joker Stencil is the one xMult joker the generic rule actively
  misreads (its multiplier grows with EMPTY slots), so entries support
  {no_generic = true} which suppresses the rule in score() and the
  generic fallback lines in explain(). Stencil also gains copy_target:
  its real famous synergy is being copied by Blueprint/Brainstorm.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 13:51:54 -07:00
funman300 35e54e6976 Add theme-level discovery
A synergy theme counts as explored the first time two different
fielded jokers connect it (one gives the tag, one wants it; cluster
members carry both sides, so any two qualify). Explored themes
persist in config.themes_found, badge their catalog page with
"explored!", and feed a per-tab progress line. One toast per
emplacement, with famous pairs outranking themes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 21:58:47 -07:00
funman300 608e23ed14 Document Gitea remote and push auth in CLAUDE.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 21:54:58 -07:00
funman300 8783785283 Initial release: Joker Combo Advisor v1.0.0
Steamodded mod that teaches Balatro joker synergies: hover tooltips
explain why jokers combo (famous-pair blurbs + tag-based reasons),
combo discovery tracking with catalog grey-out and run recap, an
in-game synergy catalog with real card sprites, learning mode, and
a HUD shortcut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 21:54:04 -07:00