Concepts → Luck and streak protection

Luck pools and streak protection — variance reduction without changing the mean

Hard West has an explicit Luck Bar. XCOM 2 has a hidden streak protection mechanic. Both share the same mathematical structure: cross-attempt state that modulates per-attempt hit chance based on prior outcomes. The user-visible effect: variance shrinks without the mean changing in the limit. The engine models both via a state-carrying Markov walk over the per-attempt distribution.

The core idea: state breaks independence

In the standard probability model, every attack roll is independent. P(hit) is fixed; whether the prior shot hit or missed has no bearing on the current one. Convolution of N independent attempts gives the chain damage distribution.

Streak protection / Luck pools break that. The per-attempt P(hit) depends on cumulative state — typically:

  • Streak protection (XCOM 2-style): consecutive misses boost the next shot's hit chance. Hit resets the streak; another miss advances it.
  • Luck pool (Hard West-style): a pool of "luck" that depletes on hits and refills on misses. Higher pool = bigger boost to the next attempt.

Both produce the same user-visible outcome: misses are anti-correlated with future misses. You can't realistically miss six 70% shots in a row — the engine pushes you back toward your "fair" hit rate.

The math: state-carrying Markov walk

Each attack expression carries a streak rule that defines:

  • An initial state (e.g., "no misses yet" or "full luck pool")
  • A modulate function: (state, base_P_hit) → adjusted_P_hit
  • A transition function: (state, outcome) → next_state

The engine evaluates the chain as a Markov walk over a joint (state, cumulative_damage) distribution. Per strike, branch into hit / crit / miss outcomes weighted by the modulated per-state probabilities; transition state per outcome; aggregate. Marginalize over end-state for the damage PMF.

This is exact (not Monte Carlo) — the Markov chain over a bounded state space (Luck pool 0..=5, miss streak 0..=N) evaluates in closed form for any N strikes.

The user-visible contract: variance reduction

The mean damage stays the same (linearity of expectation; the modulator preserves expected value in equilibrium). What shrinks is variance — specifically the probability of "all misses." For a 5-attempt chain at 50% hit chance:

Chain Mean P(all-miss) Strike URL
Independent (no state) ~25 ~3.1% (0.5⁵) /strike/1d10~hit50attacks5
Streak protection ~27 much lower (state boosts later attempts) /strike/1d10~hit50attacks5streak
Luck pool (starts full) ~35 much lower (first attempt at 75% from full pool) /strike/1d10~hit50attacks5luck

The "luck" version's higher mean isn't the modulator "cheating" — it's that LuckPool starts at full pool (max boost on the first attempt), which biases the chain mean up. Streak protection starts neutral (no boost on first attempt) and only kicks in after misses, so its mean stays close to independent.

The variance reduction is the user-visible feature both modulators provide: the "all-miss" tail of the distribution shrinks substantially in both cases.

Engine grammar

Two postfix keywords on attack chains:

<attack> @ hit P% attacks N streak

Adds XCOM 2-style streak protection — no boost on a fresh streak; +15% per consecutive miss thereafter, ramping linearly through 8 streak states (0, 15, 30, 45, 60, 75, 90, 100%) and clamped at +100. The engine ships the Commander- difficulty rate (+15); Veteran/Rookie use +10 per miss, Legend uses 0 (no protection) per the same INI. Source: community datamining of XComGameCore.ini's MissStreakChanceAdjustment=15 for Commander — Firaxis hasn't officially documented the formula. The "shots ≥ 50% hit chance" gate the real game applies IS modeled (see min_hit_chance_bps: 5000 on the streak preset); shots below 50% roll without the boost.

<attack> @ hit P% attacks N luck

Adds Hard West-style Luck pool — pool of 5 capacity, +5% per pool unit (full pool = +25% boost on next attempt), each hit consumes 1 luck, each miss refunds 1. Approximate Hard West shape; exact game formula isn't officially documented.

Build planning: when does streak protection matter?

The variance reduction matters most when:

  • You need a guaranteed kill window: clearing a turn-critical objective where 1-2 misses cascade into a wipe. Independent chains might whiff; streak protection bounds the worst case.
  • Chain length is moderate (3-7 attacks): too few attempts and state doesn't have time to evolve; too many and the variance reduction relative to the long-run mean becomes a smaller fraction.
  • Base hit chance is in the 30-70% range: below 30% even streak protection can't save you; above 70% the mean is already high and miss streaks are rare anyway.

Streak protection / Luck doesn't change the mean (much). What it changes is the SHAPE of the damage distribution — fewer catastrophic-miss outcomes, slightly more typical-roll outcomes. For tactical games where one bad turn is the difference between winning and losing, that shape matters.

Composition with other engine primitives

The streak/luck modulators compose with two of the engine's multi-attempt primitives. Both compositions use the same joint-state-space Markov walk machinery the standalone chain uses; what changes is which other state axis is in the cross product.

  • Composition with cascade chain: shipped. attacks N luck cascade [HP1, HP2, …] onkill <attack> and the streak variant both work. The cascade state machine (target index, target HP, attack budget, pending bonus, depth cap) joins the modulator state into a single (CascadeState, StreakState) memo key; per-attack hit chance is looked up on the streak axis, and each outcome transitions both axes. Lets you model "what if XCOM had GWM-on-kill" or any kill-cascade with streak protection layered on.
  • Composition with rounds_to_kill: shipped. Multi-round encounters now thread the modulator state across round boundaries. End-of-round-N state distribution becomes the start state for round N+1, instead of resetting to the modulator's initial each round. The marginal-distribution path overstated Hard West luck-pool damage in round 2+ by refilling the pool each round; the joint (state, cum_damage) Markov chain is the honest model.

State persists within an encounter (the multi-round Markov threads streak / pool state across round boundaries) and resets at the encounter boundary — the right model for the vast majority of tactical game encounters, where each combat starts fresh. Per-mission Luck persistence across multiple encounters is a separate layer that wraps the per-encounter output; cross-mission carry composes by chaining encounters together with the end-state distribution as the start state for the next.

About the parameter values

Hard West's exact Luck consumption and refund formulas aren't published in any official source. Community datamining of XCOM 2's ConfigCharacter.ini reveals the streak boost parameters but not the precise activation thresholds. The presets here capture the structural shape of both mechanics — pool depletes / refills, streak boosts after misses — using documented community values.

The math substrate (state-carrying Markov walk) is exact. Per-game preset values can be substituted via the standard modulator parameters when a verified source is available.

Pairs with /games/xcom/ for the XCOM 2 hit / crit / graze / miss outcome model that streak protection layers on top of, and with /games/hard-west/ for the Luck pool's worked examples.