diff --git a/main.lua b/main.lua index 8197624..0fd53a9 100644 --- a/main.lua +++ b/main.lua @@ -309,6 +309,32 @@ function JCA.is_perished(card) return not not (a and a.perishable and (a.perish_tally or 0) <= 0) end +-- Boss-blind cautions: five bosses debuff a whole class of cards for the +-- fight (game.lua P_BLINDS; applied in 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). +-- Warning-only, like every trap: this never touches a score. +local BOSS_KILLS = { + bl_club = {tag = 'clubs', what = 'Clubs'}, + bl_goad = {tag = 'spades', what = 'Spades'}, + bl_head = {tag = 'hearts', what = 'Hearts'}, + bl_window = {tag = 'diamonds', what = 'Diamonds'}, + bl_plant = {tag = 'faces', what = 'face cards'}, +} +JCA.boss_kills = BOSS_KILLS + +-- The boss still ahead this ante, or nil once it is dealt with. Both fields +-- live in G.GAME.round_resets (game.lua:2019, misc_functions.lua:398). +function JCA.upcoming_boss() + local rr = G.GAME and G.GAME.round_resets + if not (rr and rr.blind_choices) then return nil end + local state = rr.blind_states and rr.blind_states.Boss + if state == 'Defeated' or state == 'Skipped' then return nil end + return rr.blind_choices.Boss +end + function JCA.weakest_link() if not (G.jokers and G.jokers.cards) then return nil end local cards = G.jokers.cards @@ -592,6 +618,19 @@ local function tooltip_rows(card) local caution = in_buy_area(card) and JCA.cautions[key] if caution then text_row('Caution: ' .. caution, G.C.RED) end + -- Boss caution: buying a joker whose card class the upcoming boss + -- debuffs is paying for a dead ante. Warnings survive learning mode. + if in_buy_area(card) then + local boss = JCA.upcoming_boss() + local kill = boss and BOSS_KILLS[boss] + local entry = JCA.db[key] + if kill and entry and (entry.wants[kill.tag] or entry.gives[kill.tag]) then + 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), + G.C.RED) + end + end + -- Sticker facts (any area -- higher stakes put stickers on shop jokers -- too). Mechanical numbers from the game source, not judgements, so -- learning mode keeps them. diff --git a/test.lua b/test.lua index 067c9e0..68f844f 100644 --- a/test.lua +++ b/test.lua @@ -415,6 +415,35 @@ 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: boss-blind cautions know who the boss silences') +-------------------------------------------------------------------------------- + +-- The five class-killer bosses, verbatim from game.lua's P_BLINDS debuff +-- configs. Every tag they reference must exist in the database, or the +-- caution can never fire. +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)) +end + +-- The Plant debuffs faces: it must catch both the payoff (Business Card +-- wants faces) and the enabler (Pareidolia turns every card into one). +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_pareidolia.gives[plant.tag], 'and face enablers, whose conversion kills the deck') + +-- Upcoming-boss reading: warn while the boss is ahead, stay quiet once it +-- is dealt with. +G.GAME.round_resets = { + blind_choices = {Small = 'bl_small', Big = 'bl_big', Boss = 'bl_plant'}, + blind_states = {Small = 'Defeated', Big = 'Current', Boss = 'Upcoming'}, +} +eq(JCA.upcoming_boss(), 'bl_plant', 'the upcoming boss is read from round_resets') +G.GAME.round_resets.blind_states.Boss = 'Defeated' +eq(JCA.upcoming_boss(), nil, 'a defeated boss warns nobody') +G.GAME.round_resets = nil +eq(JCA.upcoming_boss(), nil, 'no round state (menus, tests) reads as no boss') + -------------------------------------------------------------------------------- section('Engine: Ceremonial Dagger names its victim') --------------------------------------------------------------------------------