FAILURE MAP
← Case archive

FA-86266 / Game economy crafting balance / Open access

Daily market rebalance: Cheap items never rise · case 01

Low-priced items stay flat despite a 1% overshoot.

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

ROOT CAUSE

The one-coin minimum requires more than 1% excess.

VERIFIED REPAIR

Restore `if pct > 0: step = max(step, 1)` at the minimum rise step step.

Unsuccessful approach: Forcing a step whenever it is zero raises the price even at 0%.

Case contract

If target <= 0 the price is only clamped to [floor, ceiling]. If sold > target: pct = min(20, floor((sold-target)*100/target)), step = floor(price*pct/100) but at least 1 when pct > 0, new = price + step. If sold < target: pct = min(15, floor((target-sold)*100/target)), new = price - floor(price*pct/100). Otherwise unchanged. Result clamped to [floor, ceiling].

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(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 1:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site minimum rise step #1', [99, 904, 890, 36, 258], 100),
  ('fault site minimum rise step #2', [50, 76, 75, 35, 345], 51),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('fault site minimum rise step #1', [9, 898, 884, 8, 34], 10),
  ('fault site minimum rise step #2', [99, 806, 793, 1, 532], 100),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [9, 0, 1, 47, 499], 47)],
 [('fault site minimum rise step #1', [50, 830, 817, 5, 563], 51),
  ('fault site minimum rise step #2', [50, 80, 79, 32, 704], 51),
  ('partial repair boundary #1', [50, 734, 732, 21, 710], 50),
  ('partial repair boundary #2', [99, 623, 621, 46, 1542], 99),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site minimum rise step #1', [99, 924, 909, 17, 254], 100),
  ('fault site minimum rise step #2', [99, 904, 890, 36, 258], 100),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [736, 68, 66, 28, 100], 100),
  ('control #2', [3, 75, 76, 12, 1170], 12)],
 [('fault site minimum rise step #1', [50, 76, 75, 35, 345], 51),
  ('fault site minimum rise step #2', [9, 898, 884, 8, 34], 10),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [1000, 5, 5, 37, 1007], 1000),
  ('control #2', [50, 11, 10, 38, 410], 55)]]
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
fault site minimum rise step #199100Failed
fault site minimum rise step #25051Failed
partial repair boundary #15050Passed
partial repair boundary #25050Passed
no target listed #11010Passed
cheap item rises one #144Passed
crash capped at 15 #1850850Passed
control #1118118Passed

SHA-256 / 87ea344137244f4a455c72e6e9ef1d17223cb522994d1e2b0f0f9e00a0977b0e

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if step == 0:
            step = 1
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site minimum rise step #1', [99, 904, 890, 36, 258], 100),
  ('fault site minimum rise step #2', [50, 76, 75, 35, 345], 51),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('fault site minimum rise step #1', [9, 898, 884, 8, 34], 10),
  ('fault site minimum rise step #2', [99, 806, 793, 1, 532], 100),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [9, 0, 1, 47, 499], 47)],
 [('fault site minimum rise step #1', [50, 830, 817, 5, 563], 51),
  ('fault site minimum rise step #2', [50, 80, 79, 32, 704], 51),
  ('partial repair boundary #1', [50, 734, 732, 21, 710], 50),
  ('partial repair boundary #2', [99, 623, 621, 46, 1542], 99),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site minimum rise step #1', [99, 924, 909, 17, 254], 100),
  ('fault site minimum rise step #2', [99, 904, 890, 36, 258], 100),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [736, 68, 66, 28, 100], 100),
  ('control #2', [3, 75, 76, 12, 1170], 12)],
 [('fault site minimum rise step #1', [50, 76, 75, 35, 345], 51),
  ('fault site minimum rise step #2', [9, 898, 884, 8, 34], 10),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [1000, 5, 5, 37, 1007], 1000),
  ('control #2', [50, 11, 10, 38, 410], 55)]]
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
fault site minimum rise step #1100100Passed
fault site minimum rise step #25151Passed
partial repair boundary #15150Failed
partial repair boundary #25150Failed
no target listed #11010Passed
cheap item rises one #144Passed
crash capped at 15 #1850850Passed
control #1118118Passed

SHA-256 / 3f2a1bb2cf099d937420571aebc6dec531aecc534c7d518d1a7e0ab0f8354076

3 / The verified repair

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

N = 1
observations = []
def solve(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site minimum rise step #1', [99, 904, 890, 36, 258], 100),
  ('fault site minimum rise step #2', [50, 76, 75, 35, 345], 51),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('fault site minimum rise step #1', [9, 898, 884, 8, 34], 10),
  ('fault site minimum rise step #2', [99, 806, 793, 1, 532], 100),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [9, 0, 1, 47, 499], 47)],
 [('fault site minimum rise step #1', [50, 830, 817, 5, 563], 51),
  ('fault site minimum rise step #2', [50, 80, 79, 32, 704], 51),
  ('partial repair boundary #1', [50, 734, 732, 21, 710], 50),
  ('partial repair boundary #2', [99, 623, 621, 46, 1542], 99),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site minimum rise step #1', [99, 924, 909, 17, 254], 100),
  ('fault site minimum rise step #2', [99, 904, 890, 36, 258], 100),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [736, 68, 66, 28, 100], 100),
  ('control #2', [3, 75, 76, 12, 1170], 12)],
 [('fault site minimum rise step #1', [50, 76, 75, 35, 345], 51),
  ('fault site minimum rise step #2', [9, 898, 884, 8, 34], 10),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [1000, 5, 5, 37, 1007], 1000),
  ('control #2', [50, 11, 10, 38, 410], 55)]]
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
fault site minimum rise step #1100100Passed
fault site minimum rise step #25151Passed
partial repair boundary #15050Passed
partial repair boundary #25050Passed
no target listed #11010Passed
cheap item rises one #144Passed
crash capped at 15 #1850850Passed
control #1118118Passed

SHA-256 / 7dc83f1ec23fce47be199e3d8778f31c899758503dc408802924c53f9e1cd5be

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

Case digest / e1272bf9b97c778b95c401d49fa8281d9b0d47564904001e66fe12d2625588f5