FA-86206 / Game economy crafting balance / Open access
Gem combining cascade: Budget is not reduced by earlier tiers · case 01
A cascade spends more gold than the budget.
ROOT CAUSE
Affordability uses the full budget at every tier.
VERIFIED REPAIR
Restore `(budget - gold) // price` at the remaining budget step.
Unsuccessful approach: Ceiling division lets a partial price buy a combine.
Case contract
gems[t] = count of tier t gems for t = 0..max_tier. Tiers are processed upward: three tier t gems make one tier t+1 gem at a cost of (t+1)*10 gold each, limited by the remaining gold budget; newly made gems can cascade into the next tier. Max-tier gems never combine. Returns [counts, gold_spent].
Why this case matters
Game economies leak or destroy currency when one crafting or pricing rule is off by one boundary, rounding stage or state update; the defect is observable in exact integer outcomes.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(gems, max_tier, budget):
g = list(gems)
gold = 0
for t in range(max_tier):
price = (t + 1) * 10
made = min(g[t] // 3, budget // price)
g[t] -= made * 3
g[t + 1] += made
gold += made * price
return [g, gold]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('regression remaining budget #1', [[4, 4, 3, 3, 9], 4, 29], [[1, 5, 3, 3, 9], 10]),
('fault site remaining budget #1', [[27, 2, 2], 2, 60], [[9, 8, 2], 60]),
('partial repair boundary #1', [[0, 4, 7, 4], 3, 29], [[0, 1, 8, 4], 20]),
('regression remaining budget #2', [[3, 9, 8, 3], 3, 60], [[0, 4, 10, 3], 50]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[27, 2, 2], 2, 60], [[9, 8, 2], 60]),
('regression remaining budget #1', [[3, 9, 8, 3], 3, 60], [[0, 4, 10, 3], 50]),
('regression remaining budget #2', [[4, 4, 0, 9, 8], 4, 60], [[1, 2, 1, 9, 8], 30]),
('regression remaining budget #3', [[8, 8, 4, 0, 0], 4, 30], [[2, 10, 4, 0, 0], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('regression remaining budget #1', [[4, 4, 0, 9, 8], 4, 60], [[1, 2, 1, 9, 8], 30]),
('regression remaining budget #2', [[8, 8, 4, 0, 0], 4, 30], [[2, 10, 4, 0, 0], 20]),
('regression remaining budget #3', [[3, 8, 0], 2, 29], [[0, 9, 0], 10]),
('regression remaining budget #4', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[27, 3, 9], 2, 30], [[18, 6, 9], 30]),
('regression remaining budget #1', [[3, 8, 0], 2, 29], [[0, 9, 0], 10]),
('regression remaining budget #2', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('partial repair boundary #1', [[2, 6, 3, 3, 3], 4, 10], [[2, 6, 3, 3, 3], 0]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 28, 24], 2, 10], [[6, 29, 24], 10])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[8, 9, 9, 3, 4], 4, 60], [[2, 5, 11, 3, 4], 60]),
('regression remaining budget #1', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('partial repair boundary #1', [[9, 9], 1, 29], [[3, 11], 20]),
('regression remaining budget #2', [[8, 10, 3, 8], 3, 29], [[2, 12, 3, 8], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 9, 2], 2, 10], [[6, 10, 2], 10])]]
for label, args, expected in cases[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| budget stops second tier #1 | [[0, 1, 1], 50] | [[0, 4, 0], 30] | Failed |
| regression remaining budget #1 | [[1, 2, 4, 3, 9], 30] | [[1, 5, 3, 3, 9], 10] | Failed |
| fault site remaining budget #1 | [[9, 2, 4], 100] | [[9, 8, 2], 60] | Failed |
| partial repair boundary #1 | [[0, 1, 8, 4], 20] | [[0, 1, 8, 4], 20] | Passed |
| regression remaining budget #2 | [[0, 1, 5, 5], 130] | [[0, 4, 10, 3], 50] | Failed |
| two level cascade #1 | [[0, 0, 1], 50] | [[0, 0, 1], 50] | Passed |
| max tier untouched #1 | [[0, 6], 0] | [[0, 6], 0] | Passed |
| control #1 | [[0, 0, 4], 70] | [[0, 0, 4], 70] | Passed |
SHA-256 / f7f658e622e669f4c4ddbff8313e4d3c58a4bd50c0ef31c11437f0bccff8b5e2
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(gems, max_tier, budget):
g = list(gems)
gold = 0
for t in range(max_tier):
price = (t + 1) * 10
made = min(g[t] // 3, -(-(budget - gold) // price))
g[t] -= made * 3
g[t + 1] += made
gold += made * price
return [g, gold]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('regression remaining budget #1', [[4, 4, 3, 3, 9], 4, 29], [[1, 5, 3, 3, 9], 10]),
('fault site remaining budget #1', [[27, 2, 2], 2, 60], [[9, 8, 2], 60]),
('partial repair boundary #1', [[0, 4, 7, 4], 3, 29], [[0, 1, 8, 4], 20]),
('regression remaining budget #2', [[3, 9, 8, 3], 3, 60], [[0, 4, 10, 3], 50]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[27, 2, 2], 2, 60], [[9, 8, 2], 60]),
('regression remaining budget #1', [[3, 9, 8, 3], 3, 60], [[0, 4, 10, 3], 50]),
('regression remaining budget #2', [[4, 4, 0, 9, 8], 4, 60], [[1, 2, 1, 9, 8], 30]),
('regression remaining budget #3', [[8, 8, 4, 0, 0], 4, 30], [[2, 10, 4, 0, 0], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('regression remaining budget #1', [[4, 4, 0, 9, 8], 4, 60], [[1, 2, 1, 9, 8], 30]),
('regression remaining budget #2', [[8, 8, 4, 0, 0], 4, 30], [[2, 10, 4, 0, 0], 20]),
('regression remaining budget #3', [[3, 8, 0], 2, 29], [[0, 9, 0], 10]),
('regression remaining budget #4', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[27, 3, 9], 2, 30], [[18, 6, 9], 30]),
('regression remaining budget #1', [[3, 8, 0], 2, 29], [[0, 9, 0], 10]),
('regression remaining budget #2', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('partial repair boundary #1', [[2, 6, 3, 3, 3], 4, 10], [[2, 6, 3, 3, 3], 0]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 28, 24], 2, 10], [[6, 29, 24], 10])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[8, 9, 9, 3, 4], 4, 60], [[2, 5, 11, 3, 4], 60]),
('regression remaining budget #1', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('partial repair boundary #1', [[9, 9], 1, 29], [[3, 11], 20]),
('regression remaining budget #2', [[8, 10, 3, 8], 3, 29], [[2, 12, 3, 8], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 9, 2], 2, 10], [[6, 10, 2], 10])]]
for label, args, expected in cases[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| budget stops second tier #1 | [[0, 4, 0], 30] | [[0, 4, 0], 30] | Passed |
| regression remaining budget #1 | [[1, 2, 4, 3, 9], 30] | [[1, 5, 3, 3, 9], 10] | Failed |
| fault site remaining budget #1 | [[9, 8, 2], 60] | [[9, 8, 2], 60] | Passed |
| partial repair boundary #1 | [[0, 1, 5, 5], 50] | [[0, 1, 8, 4], 20] | Failed |
| regression remaining budget #2 | [[0, 1, 11, 3], 70] | [[0, 4, 10, 3], 50] | Failed |
| two level cascade #1 | [[0, 0, 1], 50] | [[0, 0, 1], 50] | Passed |
| max tier untouched #1 | [[0, 6], 0] | [[0, 6], 0] | Passed |
| control #1 | [[0, 0, 4], 70] | [[0, 0, 4], 70] | Passed |
SHA-256 / b9d20dadd3a3cf81db634e031686780153e32e299a2eb56f9482c95926512676
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(gems, max_tier, budget):
g = list(gems)
gold = 0
for t in range(max_tier):
price = (t + 1) * 10
made = min(g[t] // 3, (budget - gold) // price)
g[t] -= made * 3
g[t + 1] += made
gold += made * price
return [g, gold]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('regression remaining budget #1', [[4, 4, 3, 3, 9], 4, 29], [[1, 5, 3, 3, 9], 10]),
('fault site remaining budget #1', [[27, 2, 2], 2, 60], [[9, 8, 2], 60]),
('partial repair boundary #1', [[0, 4, 7, 4], 3, 29], [[0, 1, 8, 4], 20]),
('regression remaining budget #2', [[3, 9, 8, 3], 3, 60], [[0, 4, 10, 3], 50]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[27, 2, 2], 2, 60], [[9, 8, 2], 60]),
('regression remaining budget #1', [[3, 9, 8, 3], 3, 60], [[0, 4, 10, 3], 50]),
('regression remaining budget #2', [[4, 4, 0, 9, 8], 4, 60], [[1, 2, 1, 9, 8], 30]),
('regression remaining budget #3', [[8, 8, 4, 0, 0], 4, 30], [[2, 10, 4, 0, 0], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('regression remaining budget #1', [[4, 4, 0, 9, 8], 4, 60], [[1, 2, 1, 9, 8], 30]),
('regression remaining budget #2', [[8, 8, 4, 0, 0], 4, 30], [[2, 10, 4, 0, 0], 20]),
('regression remaining budget #3', [[3, 8, 0], 2, 29], [[0, 9, 0], 10]),
('regression remaining budget #4', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 3, 2], 2, 1000], [[0, 0, 4], 70])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[27, 3, 9], 2, 30], [[18, 6, 9], 30]),
('regression remaining budget #1', [[3, 8, 0], 2, 29], [[0, 9, 0], 10]),
('regression remaining budget #2', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('partial repair boundary #1', [[2, 6, 3, 3, 3], 4, 10], [[2, 6, 3, 3, 3], 0]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 28, 24], 2, 10], [[6, 29, 24], 10])],
[('budget stops second tier #1', [[9, 1, 0], 2, 30], [[0, 4, 0], 30]),
('fault site remaining budget #1', [[8, 9, 9, 3, 4], 4, 60], [[2, 5, 11, 3, 4], 60]),
('regression remaining budget #1', [[2, 9, 4, 0], 3, 30], [[2, 6, 5, 0], 20]),
('partial repair boundary #1', [[9, 9], 1, 29], [[3, 11], 20]),
('regression remaining budget #2', [[8, 10, 3, 8], 3, 29], [[2, 12, 3, 8], 20]),
('two level cascade #1', [[9, 0, 0], 2, 1000], [[0, 0, 1], 50]),
('max tier untouched #1', [[0, 6], 1, 1000], [[0, 6], 0]),
('control #1', [[9, 9, 2], 2, 10], [[6, 10, 2], 10])]]
for label, args, expected in cases[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| budget stops second tier #1 | [[0, 4, 0], 30] | [[0, 4, 0], 30] | Passed |
| regression remaining budget #1 | [[1, 5, 3, 3, 9], 10] | [[1, 5, 3, 3, 9], 10] | Passed |
| fault site remaining budget #1 | [[9, 8, 2], 60] | [[9, 8, 2], 60] | Passed |
| partial repair boundary #1 | [[0, 1, 8, 4], 20] | [[0, 1, 8, 4], 20] | Passed |
| regression remaining budget #2 | [[0, 4, 10, 3], 50] | [[0, 4, 10, 3], 50] | Passed |
| two level cascade #1 | [[0, 0, 1], 50] | [[0, 0, 1], 50] | Passed |
| max tier untouched #1 | [[0, 6], 0] | [[0, 6], 0] | Passed |
| control #1 | [[0, 0, 4], 70] | [[0, 0, 4], 70] | Passed |
SHA-256 / ae1dac0ec8eaa4be3937cb47b0cdfd5e73ac0b516088b67e614ad42885994d75
Verification & scope
Deterministic toy contract stipulated for this model; integer or exact arithmetic only, not a reproduction of any specific game engine. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:50:47.418526+00:00.
Case digest / 4aa05872df58996d933462774b7dcd90e4f6e0c0fd8be09788c30ae6099e518c