FAILURE MAP
← Case archive

FA-86336 / Game economy crafting balance / Open access

Crafting XP with rested pool: Capped characters burn rested xp · case 01

Rested pool is consumed after the level cap.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The cap test for ignoring gains is strict.

VERIFIED REPAIR

Restore `if level >= 50: break` at the cap gain skip step.

Unsuccessful approach: Only skipping when rested is empty still drains rested at cap.

Case contract

Level L needs 80 + 20*L xp to reach L+1; max level 50. Gains are ignored once level 50 is reached (rested untouched). For each gain g: bonus = min(g, rested) is added on top of g and removed from the rested pool; then as many levels as possible are taken, carrying remaining xp; on reaching level 50 the xp bar is set to 0. Returns [level, xp, rested].

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(level, xp, gains, rested):
    for g in gains:
        if level > 50:
            break
        bonus = min(g, rested)
        rested -= bonus
        xp += g + bonus
        while level < 50 and xp >= 80 + 20 * level:
            xp -= 80 + 20 * level
            level += 1
        if level >= 50:
            xp = 0
    return [level, xp, rested]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [50, 56, [99], 100], [50, 56, 100]),
  ('regression cap gain skip #2', [50, 12, [2000, 50, 300, 50], 30], [50, 12, 30]),
  ('regression cap gain skip #3', [50, 44, [10], 100], [50, 44, 100]),
  ('regression cap gain skip #4', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [50, 12, [2000, 50, 300, 50], 30], [50, 12, 30]),
  ('regression cap gain skip #2', [50, 44, [10], 100], [50, 44, 100]),
  ('regression cap gain skip #3', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('regression cap gain skip #4', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('fault site cap gain skip #1', [50, 110, [50, 10], 0], [50, 110, 0]),
  ('regression cap gain skip #1', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('regression cap gain skip #2', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('regression cap gain skip #3', [50, 124, [100, 300, 2000, 415], 1000], [50, 124, 1000]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('regression cap gain skip #2', [50, 124, [100, 300, 2000, 415], 1000], [50, 124, 1000]),
  ('regression cap gain skip #3', [50, 145, [10], 80], [50, 145, 80]),
  ('regression cap gain skip #4', [50, 65, [2000, 100, 10], 1000], [50, 65, 1000]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [5, 79, [300], 0], [6, 199, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('fault site cap gain skip #1', [50, 85, [10, 207, 99], 0], [50, 85, 0]),
  ('fault site cap gain skip #2', [50, 29, [10, 249, 50, 100], 0], [50, 29, 0]),
  ('regression cap gain skip #1', [50, 65, [2000, 100, 10], 1000], [50, 65, 1000]),
  ('regression cap gain skip #2', [50, 95, [100, 61], 157], [50, 95, 157]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [10, 7, [300, 50, 99, 100], 0], [11, 276, 0])]]
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 fixtureActualExpectedOutcome
gain at cap keeps rested #1[50, 0, 0][50, 0, 40]Failed
regression cap gain skip #1[50, 0, 1][50, 56, 100]Failed
regression cap gain skip #2[50, 0, 0][50, 12, 30]Failed
regression cap gain skip #3[50, 0, 90][50, 44, 100]Failed
regression cap gain skip #4[50, 0, 0][50, 62, 100]Failed
multi-level gain #1[3, 80, 0][3, 80, 0]Passed
exact threshold #1[11, 0, 0][11, 0, 0]Passed
control #1[48, 703, 0][48, 703, 0]Passed

SHA-256 / 524788ca6bc22372a17ec8f98508ed42c69fd84f4d6af06fc6e9a6d8e08c626b

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(level, xp, gains, rested):
    for g in gains:
        if level >= 50 and rested == 0:
            break
        bonus = min(g, rested)
        rested -= bonus
        xp += g + bonus
        while level < 50 and xp >= 80 + 20 * level:
            xp -= 80 + 20 * level
            level += 1
        if level >= 50:
            xp = 0
    return [level, xp, rested]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [50, 56, [99], 100], [50, 56, 100]),
  ('regression cap gain skip #2', [50, 12, [2000, 50, 300, 50], 30], [50, 12, 30]),
  ('regression cap gain skip #3', [50, 44, [10], 100], [50, 44, 100]),
  ('regression cap gain skip #4', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [50, 12, [2000, 50, 300, 50], 30], [50, 12, 30]),
  ('regression cap gain skip #2', [50, 44, [10], 100], [50, 44, 100]),
  ('regression cap gain skip #3', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('regression cap gain skip #4', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('fault site cap gain skip #1', [50, 110, [50, 10], 0], [50, 110, 0]),
  ('regression cap gain skip #1', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('regression cap gain skip #2', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('regression cap gain skip #3', [50, 124, [100, 300, 2000, 415], 1000], [50, 124, 1000]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('regression cap gain skip #2', [50, 124, [100, 300, 2000, 415], 1000], [50, 124, 1000]),
  ('regression cap gain skip #3', [50, 145, [10], 80], [50, 145, 80]),
  ('regression cap gain skip #4', [50, 65, [2000, 100, 10], 1000], [50, 65, 1000]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [5, 79, [300], 0], [6, 199, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('fault site cap gain skip #1', [50, 85, [10, 207, 99], 0], [50, 85, 0]),
  ('fault site cap gain skip #2', [50, 29, [10, 249, 50, 100], 0], [50, 29, 0]),
  ('regression cap gain skip #1', [50, 65, [2000, 100, 10], 1000], [50, 65, 1000]),
  ('regression cap gain skip #2', [50, 95, [100, 61], 157], [50, 95, 157]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [10, 7, [300, 50, 99, 100], 0], [11, 276, 0])]]
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 fixtureActualExpectedOutcome
gain at cap keeps rested #1[50, 0, 0][50, 0, 40]Failed
regression cap gain skip #1[50, 0, 1][50, 56, 100]Failed
regression cap gain skip #2[50, 0, 0][50, 12, 30]Failed
regression cap gain skip #3[50, 0, 90][50, 44, 100]Failed
regression cap gain skip #4[50, 0, 0][50, 62, 100]Failed
multi-level gain #1[3, 80, 0][3, 80, 0]Passed
exact threshold #1[11, 0, 0][11, 0, 0]Passed
control #1[48, 703, 0][48, 703, 0]Passed

SHA-256 / 2e84c3603386a311860c40ed0eb0c86a000c7d2cd8932bbe20100e4924b3c5bf

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(level, xp, gains, rested):
    for g in gains:
        if level >= 50:
            break
        bonus = min(g, rested)
        rested -= bonus
        xp += g + bonus
        while level < 50 and xp >= 80 + 20 * level:
            xp -= 80 + 20 * level
            level += 1
        if level >= 50:
            xp = 0
    return [level, xp, rested]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [50, 56, [99], 100], [50, 56, 100]),
  ('regression cap gain skip #2', [50, 12, [2000, 50, 300, 50], 30], [50, 12, 30]),
  ('regression cap gain skip #3', [50, 44, [10], 100], [50, 44, 100]),
  ('regression cap gain skip #4', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [50, 12, [2000, 50, 300, 50], 30], [50, 12, 30]),
  ('regression cap gain skip #2', [50, 44, [10], 100], [50, 44, 100]),
  ('regression cap gain skip #3', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('regression cap gain skip #4', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('fault site cap gain skip #1', [50, 110, [50, 10], 0], [50, 110, 0]),
  ('regression cap gain skip #1', [50, 62, [300, 2000, 300], 100], [50, 62, 100]),
  ('regression cap gain skip #2', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('regression cap gain skip #3', [50, 124, [100, 300, 2000, 415], 1000], [50, 124, 1000]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [48, 123, [50, 10, 420], 100], [48, 703, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('regression cap gain skip #1', [49, 101, [300, 300, 100, 99, 100], 1000], [50, 0, 400]),
  ('regression cap gain skip #2', [50, 124, [100, 300, 2000, 415], 1000], [50, 124, 1000]),
  ('regression cap gain skip #3', [50, 145, [10], 80], [50, 145, 80]),
  ('regression cap gain skip #4', [50, 65, [2000, 100, 10], 1000], [50, 65, 1000]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [5, 79, [300], 0], [6, 199, 0])],
 [('gain at cap keeps rested #1', [50, 0, [100], 40], [50, 0, 40]),
  ('fault site cap gain skip #1', [50, 85, [10, 207, 99], 0], [50, 85, 0]),
  ('fault site cap gain skip #2', [50, 29, [10, 249, 50, 100], 0], [50, 29, 0]),
  ('regression cap gain skip #1', [50, 65, [2000, 100, 10], 1000], [50, 65, 1000]),
  ('regression cap gain skip #2', [50, 95, [100, 61], 157], [50, 95, 157]),
  ('multi-level gain #1', [1, 0, [300], 0], [3, 80, 0]),
  ('exact threshold #1', [10, 0, [280], 0], [11, 0, 0]),
  ('control #1', [10, 7, [300, 50, 99, 100], 0], [11, 276, 0])]]
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 fixtureActualExpectedOutcome
gain at cap keeps rested #1[50, 0, 40][50, 0, 40]Passed
regression cap gain skip #1[50, 56, 100][50, 56, 100]Passed
regression cap gain skip #2[50, 12, 30][50, 12, 30]Passed
regression cap gain skip #3[50, 44, 100][50, 44, 100]Passed
regression cap gain skip #4[50, 62, 100][50, 62, 100]Passed
multi-level gain #1[3, 80, 0][3, 80, 0]Passed
exact threshold #1[11, 0, 0][11, 0, 0]Passed
control #1[48, 703, 0][48, 703, 0]Passed

SHA-256 / cd6301332677961cc2564daf984a7cce921660726c09529f859c30b4ccf571ed

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:48.645440+00:00.

Case digest / ff8bc35eb28a818791ed4a29f2adc4201f6dcfddde9a841c76e6dd7509315ba0