The API cannot trigger the game's "Reroll Boss Blind" action — the conditional button that appears during blind selection when the player holds the Director's Cut or Retcon voucher. Verified against vendors/balatro/ and confirmed it is the only voucher-gated conditional button in the base game.
Bug
There is no endpoint to reroll the upcoming boss blind. A player holding v_directors_cut (1 reroll per ante, $10) or v_retcon (unlimited rerolls, $10) sees a "Reroll Boss" button at BLIND_SELECT, but the API exposes nothing equivalent.
The button is defined in create_UIBox_blind_select (functions/UI_definitions.lua:1427):
(G.GAME.used_vouchers["v_retcon"] or G.GAME.used_vouchers["v_directors_cut"]) and
UIBox_button({label = {localize('b_reroll_boss'), localize('$')..'10'}, button = "reroll_boss", func = 'reroll_boss_button'}) or nil
It is gated by G.FUNCS.reroll_boss_button (functions/button_callbacks.lua:2784), which requires $10 available and, for Director's Cut only, that the ante's reroll hasn't been used (not G.GAME.round_resets.boss_rerolled). The handler G.FUNCS.reroll_boss (button_callbacks.lua:2800) deducts $10, calls get_new_boss() for a random weighted pick (functions/common_events.lua:2338), and rebuilds the boss blind UI.
set.lua:276 already calls G.FUNCS.reroll_boss() — but as a debug override: it pre-seeds G.GAME.perscribed_bosses[ante] so the result is deterministic, free, and doesn't set boss_rerolled. This is semantically distinct from the player action and not a substitute. The legitimate player reroll (random, costs $10, respects the voucher gate) is entirely unreachable.
Gamestate gap: blinds.boss exposes key/name/score/effect/status but not whether a reroll is available. A client must infer it from used_vouchers + tracking boss_rerolled locally.
Fix
Add a reroll_boss endpoint (no params, mirrors reroll for the shop). Gate on BLIND_SELECT state, require v_directors_cut or v_retcon, verify $10 funds (accounting for bankrupt_at), and for Director's Cut ensure not G.GAME.round_resets.boss_rerolled. Call G.FUNCS.reroll_boss({}) without touching perscribed_bosses, so the result stays random. Optionally surface a boss_reroll_available boolean on blinds.boss in gamestate.lua so clients can detect the action without recomputing the gate.
PoC test
def test_reroll_boss_blind(self, client):
"""Reroll the upcoming boss blind for $10 when holding Director's Cut."""
gamestate = load_fixture(client, "reroll_boss",
"state-BLIND_SELECT--used_vouchers.v_directors_cut-1--money-20")
original_boss = gamestate["blinds"]["boss"]["key"]
response = api(client, "reroll_boss", {})
after = assert_gamestate_response(response)
assert after["blinds"]["boss"]["key"] != original_boss # random new boss
assert after["money"] == 10 # $10 deducted
Sibling of #209.
The API cannot trigger the game's "Reroll Boss Blind" action — the conditional button that appears during blind selection when the player holds the Director's Cut or Retcon voucher. Verified against
vendors/balatro/and confirmed it is the only voucher-gated conditional button in the base game.Bug
There is no endpoint to reroll the upcoming boss blind. A player holding
v_directors_cut(1 reroll per ante, $10) orv_retcon(unlimited rerolls, $10) sees a "Reroll Boss" button atBLIND_SELECT, but the API exposes nothing equivalent.The button is defined in
create_UIBox_blind_select(functions/UI_definitions.lua:1427):It is gated by
G.FUNCS.reroll_boss_button(functions/button_callbacks.lua:2784), which requires$10available and, for Director's Cut only, that the ante's reroll hasn't been used (not G.GAME.round_resets.boss_rerolled). The handlerG.FUNCS.reroll_boss(button_callbacks.lua:2800) deducts $10, callsget_new_boss()for a random weighted pick (functions/common_events.lua:2338), and rebuilds the boss blind UI.set.lua:276already callsG.FUNCS.reroll_boss()— but as a debug override: it pre-seedsG.GAME.perscribed_bosses[ante]so the result is deterministic, free, and doesn't setboss_rerolled. This is semantically distinct from the player action and not a substitute. The legitimate player reroll (random, costs $10, respects the voucher gate) is entirely unreachable.Gamestate gap:
blinds.bossexposeskey/name/score/effect/statusbut not whether a reroll is available. A client must infer it fromused_vouchers+ trackingboss_rerolledlocally.Fix
Add a
reroll_bossendpoint (no params, mirrorsrerollfor the shop). Gate onBLIND_SELECTstate, requirev_directors_cutorv_retcon, verify $10 funds (accounting forbankrupt_at), and for Director's Cut ensurenot G.GAME.round_resets.boss_rerolled. CallG.FUNCS.reroll_boss({})without touchingperscribed_bosses, so the result stays random. Optionally surface aboss_reroll_availableboolean onblinds.bossingamestate.luaso clients can detect the action without recomputing the gate.PoC test
Sibling of #209.