Reroll & Banish
Two per-run charge resources the player spends on reward-selection screens (level-up cards, weapon-cache offers, artifact picks, shooting-star choices). They reshape an offer without committing to a pick.
What each does
Reroll — spend 1 charge to discard the entire current offer and roll a fresh set of cards from the same family. The new cards still honor the run’s banish list (banished keys never reappear). If the underlying pool is empty (nothing valid to roll), the charge is not consumed and the call no-ops. Reroll also clears any in-flight banish-targeting state and resets the auto-pick countdown so the player gets fresh thinking time.
Banish — spend 1 charge to permanently remove a single card from the offer and from the run’s entire reward pool. The card vanishes with a smoke animation; banished keys persist for the rest of the run (cleared only when the mission ends and a new one starts). Banishing is two-tap: first tap the BANISH button to enter targeting mode (cards highlight as banish targets), then tap the card to remove. Tapping BANISH again exits targeting without spending a charge.
Charge counts & UI
Both charges live on GameState:
game.rerolls: numbergame.banishes: numbergame.banishedKeys: Set<string>— the keys removed for this rungame.banishTargeting: boolean— true while the player is mid-banish-decision
The HUD draws two buttons below the reward cards showing the icon (🔄 / 🚫) and the remaining charge count. Buttons disable visually when:
- Reroll:
rerolls <= 0, or banish-targeting is active. - Banish:
banishes <= 0, or only one live card remains (banishing the last card would leave nothing to pick).
While in banish-targeting mode the family banner ducks heavily, all cards dim, and the BANISH button pulses red. Tapping a card in this mode routes to banishOption(index) instead of selectReward(index).
Starting charges & replenishment
Every run starts with 3 reroll + 3 banish charges (set in makeInitialGameState). They reset on mission start.
The only source of additional charges mid-run is the shooting-star reward:
grant_rerollcard →+1 rerollgrant_banishcard →+1 banish- (
grant_refuelis the sibling for the refuel resource — same pattern.)
These three grant-cards are special: they are non-banishable (banishing the only path to refill would soft-lock the resource), and they are always eligible in the shooting-star pool regardless of what the ship owns.
There are currently no artifacts or mods that grant reroll/banish charges — shooting stars are the sole replenishment path.
What “banish key” means
Each banishable choice maps to a stable string key via banishKeyForChoice(choice):
weapon|<weaponId>— a NEW weapon offer.weapon_upgrade|<weaponId>— a level-up for a specific owned weapon.weapon_merge|<weaponId>— a legendary merge result.modifier|<modId>— a ship-mod pick (any level).artifact_new|<id>vsartifact_upgrade|<id>— banished separately so removing “NEW artifact X” doesn’t also block “ascend artifact X”.shooting_star|<category>— banishes a shooting-star category (e.g. “ALL WEAPONS”).
banishKeyForChoice returns null for non-banishable cards (the three grant cards). Reroll-pool filters check banishedKeys.has(key) and skip those entries when rolling weapons, modifiers, artifacts, and shooting-star categories.
Persistence scope
banishedKeys is run-scoped only. It is part of GameState (which is rebuilt by makeInitialGameState at mission start) and is never serialized to the metagame profile. Two different missions in the same session do not share banish lists.
Bridge surface
MissionHandle (engine → React bridge) exposes the operations:
rerollRewards()— spend 1 reroll, regenerate the current offer.toggleBanishTargeting()— enter/exit banish targeting mode.banishOption(index: number)— banish the card at index.
There are no getRerollChargeCount / getBanishChargeCount accessors on the bridge. The HUD reads game.rerolls / game.banishes directly while drawing (engine-side), and the React side only needs the toggle/spend verbs.
Key files
src/starship-survivors/engine/bridge.ts—rerollRewards,toggleBanishTargeting,banishOption(~L8223–8285).src/starship-survivors/engine/bridge-types.ts—MissionHandlecontract.src/starship-survivors/engine/world/leveling.ts—banishKeyForChoice(L97), pool filters that respectbanishedKeys(L448, L805, L1149),grant_reroll/grant_banishapply paths (L1063–1066).src/starship-survivors/engine/core/state.ts— starting values (rerolls: 3, banishes: 3, freshbanishedKeysSet) at L220–224.src/starship-survivors/engine/core/types.ts—GameStatefields at L442–449.src/starship-survivors/engine/rendering/hud.ts— reroll/banish buttons, banish-targeting visual takeover (L3615+, L5239+, L5987+).src/starship-survivors/screens/GameScreen.tsx— tap routing: BANISH button at L663, banish-targeting tap →banishOptionat L607, reroll button at L659.