FA-86261 / Game economy crafting balance / Open access
Daily market rebalance: Price drops round against the seller · case 01
Prices fall one coin more than the floor rule.
ROOT CAUSE
The reduced price is floored, rounding the decrease up.
VERIFIED REPAIR
Restore `new = price - price * pct // 100` at the decrease rounding step.
Unsuccessful approach: Rounding the decrease still over-drops when the fraction is at least one half.
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 > 0:
step = max(step, 1)
new = price + step
elif sold < target:
pct = min(15, (target - sold) * 100 // target)
new = price * (100 - 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 = [[('regression decrease rounding #1', [50, 42, 70, 38, 107], 43),
('regression decrease rounding #2', [99, 39, 40, 15, 1103], 98),
('regression decrease rounding #3', [99, 0, 5, 18, 422], 85),
('regression decrease rounding #4', [50, 4, 5, 36, 1502], 43),
('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)],
[('regression decrease rounding #1', [99, 0, 5, 18, 422], 85),
('regression decrease rounding #2', [50, 4, 5, 36, 1502], 43),
('regression decrease rounding #3', [873, 0, 1, 38, 806], 743),
('regression decrease rounding #4', [99, 39, 40, 28, 329], 98),
('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)],
[('regression decrease rounding #1', [873, 0, 1, 38, 806], 743),
('fault site decrease rounding #1', [50, 50, 51, 3, 1314], 50),
('regression decrease rounding #2', [99, 39, 40, 28, 329], 98),
('regression decrease rounding #3', [99, 0, 1, 41, 274], 85),
('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)],
[('regression decrease rounding #1', [99, 39, 40, 28, 329], 98),
('fault site decrease rounding #1', [675, 0, 41, 20, 744], 574),
('regression decrease rounding #2', [99, 0, 1, 41, 274], 85),
('regression decrease rounding #3', [99, 0, 897, 18, 606], 85),
('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)],
[('regression decrease rounding #1', [99, 0, 1, 41, 274], 85),
('regression decrease rounding #2', [99, 0, 897, 18, 606], 85),
('regression decrease rounding #3', [99, 4, 5, 14, 1130], 85),
('regression decrease rounding #4', [99, 0, 1, 13, 99], 85),
('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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression decrease rounding #1 | 42 | 43 | Failed |
| regression decrease rounding #2 | 97 | 98 | Failed |
| regression decrease rounding #3 | 84 | 85 | Failed |
| regression decrease rounding #4 | 42 | 43 | Failed |
| no target listed #1 | 10 | 10 | Passed |
| cheap item rises one #1 | 4 | 4 | Passed |
| crash capped at 15 #1 | 850 | 850 | Passed |
| control #1 | 118 | 118 | Passed |
SHA-256 / 9b19d2e6b11ed50e07c210db042223a56264f61135adcb9ced1e76f967b28334
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 pct > 0:
step = max(step, 1)
new = price + step
elif sold < target:
pct = min(15, (target - sold) * 100 // target)
new = price - round(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 = [[('regression decrease rounding #1', [50, 42, 70, 38, 107], 43),
('regression decrease rounding #2', [99, 39, 40, 15, 1103], 98),
('regression decrease rounding #3', [99, 0, 5, 18, 422], 85),
('regression decrease rounding #4', [50, 4, 5, 36, 1502], 43),
('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)],
[('regression decrease rounding #1', [99, 0, 5, 18, 422], 85),
('regression decrease rounding #2', [50, 4, 5, 36, 1502], 43),
('regression decrease rounding #3', [873, 0, 1, 38, 806], 743),
('regression decrease rounding #4', [99, 39, 40, 28, 329], 98),
('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)],
[('regression decrease rounding #1', [873, 0, 1, 38, 806], 743),
('fault site decrease rounding #1', [50, 50, 51, 3, 1314], 50),
('regression decrease rounding #2', [99, 39, 40, 28, 329], 98),
('regression decrease rounding #3', [99, 0, 1, 41, 274], 85),
('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)],
[('regression decrease rounding #1', [99, 39, 40, 28, 329], 98),
('fault site decrease rounding #1', [675, 0, 41, 20, 744], 574),
('regression decrease rounding #2', [99, 0, 1, 41, 274], 85),
('regression decrease rounding #3', [99, 0, 897, 18, 606], 85),
('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)],
[('regression decrease rounding #1', [99, 0, 1, 41, 274], 85),
('regression decrease rounding #2', [99, 0, 897, 18, 606], 85),
('regression decrease rounding #3', [99, 4, 5, 14, 1130], 85),
('regression decrease rounding #4', [99, 0, 1, 13, 99], 85),
('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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression decrease rounding #1 | 42 | 43 | Failed |
| regression decrease rounding #2 | 97 | 98 | Failed |
| regression decrease rounding #3 | 84 | 85 | Failed |
| regression decrease rounding #4 | 42 | 43 | Failed |
| no target listed #1 | 10 | 10 | Passed |
| cheap item rises one #1 | 4 | 4 | Passed |
| crash capped at 15 #1 | 850 | 850 | Passed |
| control #1 | 118 | 118 | Passed |
SHA-256 / 5baf08d329cf8e0be263aa3c337e5c5c28f0dadc65d9a7276bb792251224d101
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 = [[('regression decrease rounding #1', [50, 42, 70, 38, 107], 43),
('regression decrease rounding #2', [99, 39, 40, 15, 1103], 98),
('regression decrease rounding #3', [99, 0, 5, 18, 422], 85),
('regression decrease rounding #4', [50, 4, 5, 36, 1502], 43),
('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)],
[('regression decrease rounding #1', [99, 0, 5, 18, 422], 85),
('regression decrease rounding #2', [50, 4, 5, 36, 1502], 43),
('regression decrease rounding #3', [873, 0, 1, 38, 806], 743),
('regression decrease rounding #4', [99, 39, 40, 28, 329], 98),
('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)],
[('regression decrease rounding #1', [873, 0, 1, 38, 806], 743),
('fault site decrease rounding #1', [50, 50, 51, 3, 1314], 50),
('regression decrease rounding #2', [99, 39, 40, 28, 329], 98),
('regression decrease rounding #3', [99, 0, 1, 41, 274], 85),
('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)],
[('regression decrease rounding #1', [99, 39, 40, 28, 329], 98),
('fault site decrease rounding #1', [675, 0, 41, 20, 744], 574),
('regression decrease rounding #2', [99, 0, 1, 41, 274], 85),
('regression decrease rounding #3', [99, 0, 897, 18, 606], 85),
('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)],
[('regression decrease rounding #1', [99, 0, 1, 41, 274], 85),
('regression decrease rounding #2', [99, 0, 897, 18, 606], 85),
('regression decrease rounding #3', [99, 4, 5, 14, 1130], 85),
('regression decrease rounding #4', [99, 0, 1, 13, 99], 85),
('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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression decrease rounding #1 | 43 | 43 | Passed |
| regression decrease rounding #2 | 98 | 98 | Passed |
| regression decrease rounding #3 | 85 | 85 | Passed |
| regression decrease rounding #4 | 43 | 43 | Passed |
| no target listed #1 | 10 | 10 | Passed |
| cheap item rises one #1 | 4 | 4 | Passed |
| crash capped at 15 #1 | 850 | 850 | Passed |
| control #1 | 118 | 118 | Passed |
SHA-256 / 6e04f13c322f9f0f8f387ecd43103d84cddae4d343f527c3d50db83d9c6081dd
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.009978+00:00.
Case digest / fd1a6cad4d1d8025776f1075ddc9b5861c0327bbe791b5f0411683401679702d