Teach the boss cautions two silencers beyond the card killers
The Water removes every discard at blind start (blind.lua:208, returned only after the fight), idling discard granters and payoffs alike; The Eye blocks a repeated hand type outright (blind.lua:189/577), giving a one-hand build exactly one shot. BOSS_KILLS entries now carry a tag SET and their own factual phrase, since "debuffs X" stopped being the only true sentence. The Arm and The Ox were chased and rejected -- level drain does not touch the planet jokers, and The Ox fires on the player's own hand choice, the same reasoning that rejected the Card Sharp/Obelisk clash -- recorded in the BOSS_KILLS comment so nobody re-adds them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -336,19 +336,42 @@ function JCA.is_perished(card)
|
|||||||
return not not (a and a.perishable and (a.perish_tally or 0) <= 0)
|
return not not (a and a.perishable and (a.perish_tally or 0) <= 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Boss-blind cautions: five bosses debuff a whole class of cards for the
|
-- Boss-blind cautions: bosses that mechanically shut off a class of jokers
|
||||||
-- fight (game.lua P_BLINDS; applied in Blind:debuff_card, blind.lua:708):
|
-- for the fight. Warning-only, like every trap: this never touches a score.
|
||||||
-- The Club/Goad/Head/Window each kill a suit, The Plant kills face cards.
|
-- Each entry maps the boss to the catalog tags it silences and the factual
|
||||||
-- A debuffed card scores nothing and triggers nothing, so a joker that wants
|
-- phrase the tooltip prints ("This ante: <boss> <what>").
|
||||||
-- that class is walking into a dead ante -- and a joker that GIVES it is
|
--
|
||||||
-- worse (Pareidolia under The Plant makes every card a debuffed face).
|
-- Five bosses debuff a whole class of cards (game.lua P_BLINDS; applied in
|
||||||
-- Warning-only, like every trap: this never touches a score.
|
-- Blind:debuff_card, blind.lua:708): The Club/Goad/Head/Window each kill a
|
||||||
|
-- suit, The Plant kills face cards. A debuffed card scores nothing and
|
||||||
|
-- triggers nothing, so a joker that wants that class is walking into a dead
|
||||||
|
-- ante -- and a joker that GIVES it is worse (Pareidolia under The Plant
|
||||||
|
-- makes every card a debuffed face).
|
||||||
|
--
|
||||||
|
-- Two more silence a mechanic rather than a card class:
|
||||||
|
-- The Water removes every discard at blind start (blind.lua:208 eases
|
||||||
|
-- discards_left to 0; given back only after the fight, blind.lua:405), so
|
||||||
|
-- discard granters and discard payoffs both idle.
|
||||||
|
-- The Eye records each played hand type and BLOCKS a repeat outright
|
||||||
|
-- (blind.lua:189 builds the table, debuff_hand rejects at blind.lua:577),
|
||||||
|
-- so a build that spams one hand type gets exactly one shot at it.
|
||||||
|
--
|
||||||
|
-- Chased and REJECTED, so nobody re-adds them: The Arm lowers the played
|
||||||
|
-- hand's LEVEL (blind.lua:584) -- that drains hand-level investment, not the
|
||||||
|
-- planet-economy jokers, so warning them off would be wrong. The Ox fires
|
||||||
|
-- only when the player chooses to play their most played hand -- the same
|
||||||
|
-- "hand choice decides, not the effect" reasoning that rejected the Card
|
||||||
|
-- Sharp/Obelisk clash (see AUDIT.md).
|
||||||
local BOSS_KILLS = {
|
local BOSS_KILLS = {
|
||||||
bl_club = {tag = 'clubs', what = 'Clubs'},
|
bl_club = {tags = {clubs = true}, what = 'debuffs Clubs'},
|
||||||
bl_goad = {tag = 'spades', what = 'Spades'},
|
bl_goad = {tags = {spades = true}, what = 'debuffs Spades'},
|
||||||
bl_head = {tag = 'hearts', what = 'Hearts'},
|
bl_head = {tags = {hearts = true}, what = 'debuffs Hearts'},
|
||||||
bl_window = {tag = 'diamonds', what = 'Diamonds'},
|
bl_window = {tags = {diamonds = true}, what = 'debuffs Diamonds'},
|
||||||
bl_plant = {tag = 'faces', what = 'face cards'},
|
bl_plant = {tags = {faces = true}, what = 'debuffs face cards'},
|
||||||
|
bl_water = {tags = {discards_up = true}, what = 'sets discards to 0'},
|
||||||
|
bl_eye = {tags = {pair = true, two_pair = true, three_kind = true,
|
||||||
|
four_kind = true, straight = true, flush = true},
|
||||||
|
what = 'blocks repeat hand types'},
|
||||||
}
|
}
|
||||||
JCA.boss_kills = BOSS_KILLS
|
JCA.boss_kills = BOSS_KILLS
|
||||||
|
|
||||||
@@ -734,18 +757,24 @@ local function tooltip_rows(card)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Boss caution: buying a joker whose card class the upcoming boss
|
-- Boss caution: buying a joker whose class the upcoming boss silences
|
||||||
-- debuffs is paying for a dead ante. Warnings survive learning mode.
|
-- is paying for a dead ante. Warnings survive learning mode.
|
||||||
if in_buy_area(card) then
|
if in_buy_area(card) then
|
||||||
local boss = JCA.upcoming_boss()
|
local boss = JCA.upcoming_boss()
|
||||||
local kill = boss and BOSS_KILLS[boss]
|
local kill = boss and BOSS_KILLS[boss]
|
||||||
local entry = JCA.db[key]
|
local entry = JCA.db[key]
|
||||||
if kill and entry and (entry.wants[kill.tag] or entry.gives[kill.tag]) then
|
if kill and entry then
|
||||||
|
local hit
|
||||||
|
for t in pairs(kill.tags) do
|
||||||
|
if entry.wants[t] or entry.gives[t] then hit = true break end
|
||||||
|
end
|
||||||
|
if hit then
|
||||||
local bname = G.P_BLINDS and G.P_BLINDS[boss] and G.P_BLINDS[boss].name
|
local bname = G.P_BLINDS and G.P_BLINDS[boss] and G.P_BLINDS[boss].name
|
||||||
text_row(('This ante: %s debuffs %s'):format(bname or 'the boss', kill.what),
|
text_row(('This ante: %s %s'):format(bname or 'the boss', kill.what),
|
||||||
G.C.RED)
|
G.C.RED)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Sticker facts (any area -- higher stakes put stickers on shop jokers
|
-- Sticker facts (any area -- higher stakes put stickers on shop jokers
|
||||||
-- too). Mechanical numbers from the game source, not judgements, so
|
-- too). Mechanical numbers from the game source, not judgements, so
|
||||||
|
|||||||
@@ -504,18 +504,41 @@ eq(deck_total, 0, 'no deck (menus, tests) reads as an empty deck')
|
|||||||
section('Engine: boss-blind cautions know who the boss silences')
|
section('Engine: boss-blind cautions know who the boss silences')
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- The five class-killer bosses, verbatim from game.lua's P_BLINDS debuff
|
-- The class-killer bosses, verbatim from game.lua's P_BLINDS configs and the
|
||||||
-- configs. Every tag they reference must exist in the database, or the
|
-- blind.lua effects. Every tag they reference must exist in the database,
|
||||||
-- caution can never fire.
|
-- or the caution can never fire.
|
||||||
for boss, kill in pairs(JCA.boss_kills) do
|
for boss, kill in pairs(JCA.boss_kills) do
|
||||||
ok(JCA.tag_label[kill.tag], ('boss %s kills a real catalog tag (%s)'):format(boss, kill.tag))
|
local n = 0
|
||||||
|
for tag in pairs(kill.tags) do
|
||||||
|
n = n + 1
|
||||||
|
ok(JCA.tag_label[tag], ('boss %s kills a real catalog tag (%s)'):format(boss, tag))
|
||||||
|
end
|
||||||
|
ok(n > 0, ('boss %s kills at least one tag'):format(boss))
|
||||||
|
ok(type(kill.what) == 'string' and #kill.what > 0,
|
||||||
|
('boss %s carries its tooltip phrase'):format(boss))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The Plant debuffs faces: it must catch both the payoff (Business Card
|
-- The Plant debuffs faces: it must catch both the payoff (Business Card
|
||||||
-- wants faces) and the enabler (Pareidolia turns every card into one).
|
-- wants faces) and the enabler (Pareidolia turns every card into one).
|
||||||
local plant = JCA.boss_kills.bl_plant
|
local plant = JCA.boss_kills.bl_plant
|
||||||
ok(JCA.db.j_business.wants[plant.tag], 'The Plant caution catches face payoffs')
|
ok(JCA.db.j_business.wants.faces and plant.tags.faces,
|
||||||
ok(JCA.db.j_pareidolia.gives[plant.tag], 'and face enablers, whose conversion kills the deck')
|
'The Plant caution catches face payoffs')
|
||||||
|
ok(JCA.db.j_pareidolia.gives.faces, 'and face enablers, whose conversion kills the deck')
|
||||||
|
|
||||||
|
-- The Water removes every discard for the fight (blind.lua:208): both the
|
||||||
|
-- granters (Drunkard) and the payoffs (Hit the Road) must be caught.
|
||||||
|
local water = JCA.boss_kills.bl_water
|
||||||
|
ok(water.tags.discards_up and JCA.db.j_drunkard.gives.discards_up,
|
||||||
|
'The Water caution catches discard granters')
|
||||||
|
ok(JCA.db.j_hit_the_road.wants.discards_up, 'and discard payoffs')
|
||||||
|
|
||||||
|
-- The Eye blocks repeat hand types (blind.lua:577): every hand-type cluster
|
||||||
|
-- tag must be covered, so a one-hand build always hears about it.
|
||||||
|
local eye = JCA.boss_kills.bl_eye
|
||||||
|
for _, t in ipairs({'pair', 'two_pair', 'three_kind', 'four_kind', 'straight', 'flush'}) do
|
||||||
|
ok(eye.tags[t], ('The Eye covers the %s cluster'):format(t))
|
||||||
|
end
|
||||||
|
ok(not eye.tags.hearts, 'but The Eye does not touch suit tags (suits repeat fine)')
|
||||||
|
|
||||||
-- Upcoming-boss reading: warn while the boss is ahead, stay quiet once it
|
-- Upcoming-boss reading: warn while the boss is ahead, stay quiet once it
|
||||||
-- is dealt with.
|
-- is dealt with.
|
||||||
|
|||||||
Reference in New Issue
Block a user