FAILURE MAP
← Case archive

FA-83521 / Card game rule engines / Open access

Draw cards always hit the clockwise neighbour · case 01

In counter-clockwise play the wrong player draws.

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

ROOT CAUSE

The victim is computed with +1 instead of the direction.

VERIFIED REPAIR

The victim is the next player in the current direction.

Unsuccessful approach: Using two steps picks the player after the victim.

Case contract

Input [players, current, direction(+1/-1), card]. Reverse flips direction (with two players it acts as skip); skip jumps one player; draw2/wild4 make the next player draw 2/4 and lose their turn. Return [next_player, direction, draw_count, victim_or_None].

Why this case matters

Card-game engines, scoring apps and online tables apply this rule automatically on every hand.

1 / The failure

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

N = 1
observations = []
def solve(x):
    n, cur, direction, card = x
    step = 1
    victim = None
    draw = 0
    if card == 'reverse':
        direction = -direction
        if n == 2:
            step = 2
    elif card == 'skip':
        step = 2
    elif card in ('draw2', 'wild4'):
        victim = (cur + 1) % n
        draw = 2 if card == 'draw2' else 4
        step = 2
    nxt = (cur + direction * step) % n
    return [nxt, direction, draw, victim]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[2, 1, 1, 'wild'], [0, 1, 0, None]], [[2, 1, 1, 'wild4'], [1, 1, 4, 0]], [[2, 1, -1, 'skip'], [1, -1, 0, None]], [[2, 1, -1, 'wild'], [0, -1, 0, None]], [[3, 0, 1, 'draw2'], [2, 1, 2, 1]], [[3, 0, 1, 'wild'], [1, 1, 0, None]], [[3, 0, -1, 'wild4'], [1, -1, 4, 2]], [[3, 1, 1, 'wild4'], [0, 1, 4, 2]]], [[[3, 0, -1, 'skip'], [1, -1, 0, None]], [[3, 0, -1, 'reverse'], [1, 1, 0, None]], [[3, 0, -1, 'wild'], [2, -1, 0, None]], [[3, 0, -1, 'wild4'], [1, -1, 4, 2]], [[3, 1, 1, 'num'], [2, 1, 0, None]], [[3, 1, 1, 'skip'], [0, 1, 0, None]], [[4, 0, 1, 'wild4'], [2, 1, 4, 1]], [[4, 0, -1, 'wild4'], [2, -1, 4, 3]]], [[[3, 1, 1, 'wild4'], [0, 1, 4, 2]], [[3, 1, -1, 'num'], [0, -1, 0, None]], [[3, 1, -1, 'skip'], [2, -1, 0, None]], [[3, 1, -1, 'reverse'], [2, 1, 0, None]], [[3, 1, -1, 'wild4'], [2, -1, 4, 0]], [[3, 2, 1, 'skip'], [1, 1, 0, None]], [[4, 2, 1, 'wild4'], [0, 1, 4, 3]], [[4, 2, -1, 'wild4'], [0, -1, 4, 1]]], [[[3, 2, 1, 'wild4'], [1, 1, 4, 0]], [[3, 2, -1, 'skip'], [0, -1, 0, None]], [[3, 2, -1, 'reverse'], [0, 1, 0, None]], [[3, 2, -1, 'wild4'], [0, -1, 4, 1]], [[4, 0, 1, 'num'], [1, 1, 0, None]], [[4, 0, 1, 'skip'], [2, 1, 0, None]], [[4, 3, -1, 'wild4'], [1, -1, 4, 2]], [[5, 0, -1, 'draw2'], [3, -1, 2, 4]]], [[[4, 0, 1, 'wild'], [1, 1, 0, None]], [[4, 0, 1, 'wild4'], [2, 1, 4, 1]], [[4, 0, -1, 'num'], [3, -1, 0, None]], [[4, 0, -1, 'skip'], [2, -1, 0, None]], [[4, 0, -1, 'wild4'], [2, -1, 4, 3]], [[4, 1, 1, 'num'], [2, 1, 0, None]], [[5, 3, 1, 'draw2'], [0, 1, 2, 4]], [[6, 0, -1, 'wild4'], [4, -1, 4, 5]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("turn case %d" % i, 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
turn case 0[0, 1, 0, None][0, 1, 0, None]Passed
turn case 1[1, 1, 4, 0][1, 1, 4, 0]Passed
turn case 2[1, -1, 0, None][1, -1, 0, None]Passed
turn case 3[0, -1, 0, None][0, -1, 0, None]Passed
turn case 4[2, 1, 2, 1][2, 1, 2, 1]Passed
turn case 5[1, 1, 0, None][1, 1, 0, None]Passed
turn case 6[1, -1, 4, 1][1, -1, 4, 2]Failed
turn case 7[0, 1, 4, 2][0, 1, 4, 2]Passed

SHA-256 / b2cf2424b41ea6436110ea92212844a47bb1fa0d32e71e1c6cf16ca127b78c7c

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    n, cur, direction, card = x
    step = 1
    victim = None
    draw = 0
    if card == 'reverse':
        direction = -direction
        if n == 2:
            step = 2
    elif card == 'skip':
        step = 2
    elif card in ('draw2', 'wild4'):
        victim = (cur + direction * 2) % n
        draw = 2 if card == 'draw2' else 4
        step = 2
    nxt = (cur + direction * step) % n
    return [nxt, direction, draw, victim]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[2, 1, 1, 'wild'], [0, 1, 0, None]], [[2, 1, 1, 'wild4'], [1, 1, 4, 0]], [[2, 1, -1, 'skip'], [1, -1, 0, None]], [[2, 1, -1, 'wild'], [0, -1, 0, None]], [[3, 0, 1, 'draw2'], [2, 1, 2, 1]], [[3, 0, 1, 'wild'], [1, 1, 0, None]], [[3, 0, -1, 'wild4'], [1, -1, 4, 2]], [[3, 1, 1, 'wild4'], [0, 1, 4, 2]]], [[[3, 0, -1, 'skip'], [1, -1, 0, None]], [[3, 0, -1, 'reverse'], [1, 1, 0, None]], [[3, 0, -1, 'wild'], [2, -1, 0, None]], [[3, 0, -1, 'wild4'], [1, -1, 4, 2]], [[3, 1, 1, 'num'], [2, 1, 0, None]], [[3, 1, 1, 'skip'], [0, 1, 0, None]], [[4, 0, 1, 'wild4'], [2, 1, 4, 1]], [[4, 0, -1, 'wild4'], [2, -1, 4, 3]]], [[[3, 1, 1, 'wild4'], [0, 1, 4, 2]], [[3, 1, -1, 'num'], [0, -1, 0, None]], [[3, 1, -1, 'skip'], [2, -1, 0, None]], [[3, 1, -1, 'reverse'], [2, 1, 0, None]], [[3, 1, -1, 'wild4'], [2, -1, 4, 0]], [[3, 2, 1, 'skip'], [1, 1, 0, None]], [[4, 2, 1, 'wild4'], [0, 1, 4, 3]], [[4, 2, -1, 'wild4'], [0, -1, 4, 1]]], [[[3, 2, 1, 'wild4'], [1, 1, 4, 0]], [[3, 2, -1, 'skip'], [0, -1, 0, None]], [[3, 2, -1, 'reverse'], [0, 1, 0, None]], [[3, 2, -1, 'wild4'], [0, -1, 4, 1]], [[4, 0, 1, 'num'], [1, 1, 0, None]], [[4, 0, 1, 'skip'], [2, 1, 0, None]], [[4, 3, -1, 'wild4'], [1, -1, 4, 2]], [[5, 0, -1, 'draw2'], [3, -1, 2, 4]]], [[[4, 0, 1, 'wild'], [1, 1, 0, None]], [[4, 0, 1, 'wild4'], [2, 1, 4, 1]], [[4, 0, -1, 'num'], [3, -1, 0, None]], [[4, 0, -1, 'skip'], [2, -1, 0, None]], [[4, 0, -1, 'wild4'], [2, -1, 4, 3]], [[4, 1, 1, 'num'], [2, 1, 0, None]], [[5, 3, 1, 'draw2'], [0, 1, 2, 4]], [[6, 0, -1, 'wild4'], [4, -1, 4, 5]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("turn case %d" % i, 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
turn case 0[0, 1, 0, None][0, 1, 0, None]Passed
turn case 1[1, 1, 4, 1][1, 1, 4, 0]Failed
turn case 2[1, -1, 0, None][1, -1, 0, None]Passed
turn case 3[0, -1, 0, None][0, -1, 0, None]Passed
turn case 4[2, 1, 2, 2][2, 1, 2, 1]Failed
turn case 5[1, 1, 0, None][1, 1, 0, None]Passed
turn case 6[1, -1, 4, 1][1, -1, 4, 2]Failed
turn case 7[0, 1, 4, 0][0, 1, 4, 2]Failed

SHA-256 / 66f08272725cb6517356a1d2ea0a3f740cd05ccdc8cebfb0e9c25e4cd780bbc6

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    n, cur, direction, card = x
    step = 1
    victim = None
    draw = 0
    if card == 'reverse':
        direction = -direction
        if n == 2:
            step = 2
    elif card == 'skip':
        step = 2
    elif card in ('draw2', 'wild4'):
        victim = (cur + direction) % n
        draw = 2 if card == 'draw2' else 4
        step = 2
    nxt = (cur + direction * step) % n
    return [nxt, direction, draw, victim]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[2, 1, 1, 'wild'], [0, 1, 0, None]], [[2, 1, 1, 'wild4'], [1, 1, 4, 0]], [[2, 1, -1, 'skip'], [1, -1, 0, None]], [[2, 1, -1, 'wild'], [0, -1, 0, None]], [[3, 0, 1, 'draw2'], [2, 1, 2, 1]], [[3, 0, 1, 'wild'], [1, 1, 0, None]], [[3, 0, -1, 'wild4'], [1, -1, 4, 2]], [[3, 1, 1, 'wild4'], [0, 1, 4, 2]]], [[[3, 0, -1, 'skip'], [1, -1, 0, None]], [[3, 0, -1, 'reverse'], [1, 1, 0, None]], [[3, 0, -1, 'wild'], [2, -1, 0, None]], [[3, 0, -1, 'wild4'], [1, -1, 4, 2]], [[3, 1, 1, 'num'], [2, 1, 0, None]], [[3, 1, 1, 'skip'], [0, 1, 0, None]], [[4, 0, 1, 'wild4'], [2, 1, 4, 1]], [[4, 0, -1, 'wild4'], [2, -1, 4, 3]]], [[[3, 1, 1, 'wild4'], [0, 1, 4, 2]], [[3, 1, -1, 'num'], [0, -1, 0, None]], [[3, 1, -1, 'skip'], [2, -1, 0, None]], [[3, 1, -1, 'reverse'], [2, 1, 0, None]], [[3, 1, -1, 'wild4'], [2, -1, 4, 0]], [[3, 2, 1, 'skip'], [1, 1, 0, None]], [[4, 2, 1, 'wild4'], [0, 1, 4, 3]], [[4, 2, -1, 'wild4'], [0, -1, 4, 1]]], [[[3, 2, 1, 'wild4'], [1, 1, 4, 0]], [[3, 2, -1, 'skip'], [0, -1, 0, None]], [[3, 2, -1, 'reverse'], [0, 1, 0, None]], [[3, 2, -1, 'wild4'], [0, -1, 4, 1]], [[4, 0, 1, 'num'], [1, 1, 0, None]], [[4, 0, 1, 'skip'], [2, 1, 0, None]], [[4, 3, -1, 'wild4'], [1, -1, 4, 2]], [[5, 0, -1, 'draw2'], [3, -1, 2, 4]]], [[[4, 0, 1, 'wild'], [1, 1, 0, None]], [[4, 0, 1, 'wild4'], [2, 1, 4, 1]], [[4, 0, -1, 'num'], [3, -1, 0, None]], [[4, 0, -1, 'skip'], [2, -1, 0, None]], [[4, 0, -1, 'wild4'], [2, -1, 4, 3]], [[4, 1, 1, 'num'], [2, 1, 0, None]], [[5, 3, 1, 'draw2'], [0, 1, 2, 4]], [[6, 0, -1, 'wild4'], [4, -1, 4, 5]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("turn case %d" % i, 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
turn case 0[0, 1, 0, None][0, 1, 0, None]Passed
turn case 1[1, 1, 4, 0][1, 1, 4, 0]Passed
turn case 2[1, -1, 0, None][1, -1, 0, None]Passed
turn case 3[0, -1, 0, None][0, -1, 0, None]Passed
turn case 4[2, 1, 2, 1][2, 1, 2, 1]Passed
turn case 5[1, 1, 0, None][1, 1, 0, None]Passed
turn case 6[1, -1, 4, 2][1, -1, 4, 2]Passed
turn case 7[0, 1, 4, 2][0, 1, 4, 2]Passed

SHA-256 / f466c6c4991a46fb33d7a6f874808224b0a4906e65cbdaaf127ea920b55e2915

Verification & scope

A bounded toy rule contract stated explicitly in the contract field; cards are two-character codes (rank, suit). Not a complete implementation of any published rulebook or casino table rules. 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:22.426048+00:00.

Case digest / 81f1d1c08090791eec96fbd3afcd6c10abc0f036b9231efa3cb3db28db31c10f