Respect the other two stickers: rentals bleed, perished jokers are dead

JCA.is_rental and JCA.is_perished read ability.rental and
ability.perishable/perish_tally, the same flags vanilla uses
(card.lua:684/676). The sell advisor now docks a rental 2 points (it
drains $3 every round, game.lua:1957) and treats a perished joker --
tally 0, debuffed permanently per card.lua:716 -- as dead weight that
outweighs any synergy score. Tooltips gain the mechanical facts:
countdown on ticking perishables, drain rate on rentals (shop phrasing
notes the $1 price), and 'Perished - it will never work again' instead
of the misleading 'does nothing this blind' on permanently dead cards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-14 13:44:52 -07:00
parent 665bd9b396
commit ea8faac434
2 changed files with 79 additions and 2 deletions
+33
View File
@@ -382,6 +382,39 @@ ok(pick ~= et[1], 'but never an Eternal one, because it cannot be sold',
pick and pick.config.center.key or 'nil')
eq(pick, et[2], 'it falls through to the next sellable candidate instead')
--------------------------------------------------------------------------------
section('Engine: the sell advisor weighs rentals and perished jokers')
--------------------------------------------------------------------------------
-- ability.rental drains $3 a round (card.lua:2646, game.lua:1957); a perishable
-- joker whose tally ran out is debuffed FOREVER (card.lua:716). Both are flags
-- on card.ability, read the same way as eternal.
local plain = field('j_baron', 'j_joker')
eq(JCA.is_rental(plain[1]), false, 'no sticker reads as no rental')
plain[1].ability = {rental = true}
eq(JCA.is_rental(plain[1]), true, 'ability.rental reads as a rental')
plain[2].ability = {perishable = true, perish_tally = 3}
eq(JCA.is_perished(plain[2]), false, 'a ticking perishable has not perished yet')
plain[2].ability.perish_tally = 0
eq(JCA.is_perished(plain[2]), true, 'tally 0 means debuffed for good')
-- Three mutually inert jokers tie at 0, so nothing stands out to cut --
-- until one of them is a rental, which bleeds money every round.
local rent = field('j_joker', 'j_half', 'j_misprint')
G.jokers.config.card_limit = 3
eq(JCA.weakest_link(), nil, 'an all-tied board flags nobody')
rent[2].ability = {rental = true}
eq(JCA.weakest_link(), rent[2], 'the rental loses the tie: it drains $3 a round')
-- A perished joker is dead weight at ANY synergy score: it outweighs even a
-- famous-pair member against the board's zero-scorer.
local per = field('j_baron', 'j_mime', 'j_joker')
G.jokers.config.card_limit = 3
eq(JCA.weakest_link(), per[3], 'normally the zero-scorer is the cut')
per[2].ability = {perishable = true, perish_tally = 0}
eq(JCA.weakest_link(), per[2],
'but a perished joker is the cut at any score - it will never work again')
--------------------------------------------------------------------------------
section('Engine: Ceremonial Dagger names its victim')
--------------------------------------------------------------------------------