FA-11666 / Game simulation rules / Open access
A full winning board is classified as a draw · case 01
A full winning board is classified as a draw.
ROOT CAUSE
Full-board detection runs before win detection.
VERIFIED REPAIR
Evaluate all eight winning lines before deciding draw.
Unsuccessful approach: Checking only rows misses column and diagonal wins.
Case contract
Return X or O for the sole winner on a 3x3 board of X/O/dot; otherwise draw if full, playing if not. Inputs never have both winners.
Why this case matters
A deterministic game-rule model isolates this rule interaction for regression testing.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(board):
if all('.' not in row for row in board): return 'draw'
lines=list(board)+[''.join(board[r][c] for r in range(3)) for c in range(3)]+[''.join(board[i][i] for i in range(3)),''.join(board[i][2-i] for i in range(3))]
return next((s[0] for s in lines if s in ('XXX','OOO')),'playing')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
p='X' if N%2 else 'O'
check('last square completes row',solve(['XXX','OOX','OXO']),'X')
check('column winner',solve([p+'..',p+'..',p+'..']),p)
check('main diagonal',solve(['X..','.X.','..X']),'X')
check('other diagonal',solve(['..O','.O.','O..']),'O')
check('draw',solve(['XOX','XOO','OXX']),'draw')
check('empty',solve(['...','...','...']),'playing')
check('unfinished',solve(['X..','...','...']),'playing')
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 |
|---|---|---|---|
| last square completes row | draw | X | Failed |
| column winner | X | X | Passed |
| main diagonal | X | X | Passed |
| other diagonal | O | O | Passed |
| draw | draw | draw | Passed |
| empty | playing | playing | Passed |
| unfinished | playing | playing | Passed |
SHA-256 / ac73c701beed8d046c6d5fd14bb1481217f4e923d36310de5b23baf82d0e526a
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(board):
for s in board:
if s in ('XXX','OOO'): return s[0]
return 'draw' if all('.' not in row for row in board) else 'playing'
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
p='X' if N%2 else 'O'
check('last square completes row',solve(['XXX','OOX','OXO']),'X')
check('column winner',solve([p+'..',p+'..',p+'..']),p)
check('main diagonal',solve(['X..','.X.','..X']),'X')
check('other diagonal',solve(['..O','.O.','O..']),'O')
check('draw',solve(['XOX','XOO','OXX']),'draw')
check('empty',solve(['...','...','...']),'playing')
check('unfinished',solve(['X..','...','...']),'playing')
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 |
|---|---|---|---|
| last square completes row | X | X | Passed |
| column winner | playing | X | Failed |
| main diagonal | playing | X | Failed |
| other diagonal | playing | O | Failed |
| draw | draw | draw | Passed |
| empty | playing | playing | Passed |
| unfinished | playing | playing | Passed |
SHA-256 / fefdf13d20b9e882eca9a3bfdabbdf3df7aa2735ad1ddbb359d751efcf3aa95e
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(board):
lines=list(board)+[''.join(board[r][c] for r in range(3)) for c in range(3)]+[''.join(board[i][i] for i in range(3)),''.join(board[i][2-i] for i in range(3))]
for s in lines:
if s in ('XXX','OOO'): return s[0]
return 'draw' if all('.' not in row for row in board) else 'playing'
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
p='X' if N%2 else 'O'
check('last square completes row',solve(['XXX','OOX','OXO']),'X')
check('column winner',solve([p+'..',p+'..',p+'..']),p)
check('main diagonal',solve(['X..','.X.','..X']),'X')
check('other diagonal',solve(['..O','.O.','O..']),'O')
check('draw',solve(['XOX','XOO','OXX']),'draw')
check('empty',solve(['...','...','...']),'playing')
check('unfinished',solve(['X..','...','...']),'playing')
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 |
|---|---|---|---|
| last square completes row | X | X | Passed |
| column winner | X | X | Passed |
| main diagonal | X | X | Passed |
| other diagonal | O | O | Passed |
| draw | draw | draw | Passed |
| empty | playing | playing | Passed |
| unfinished | playing | playing | Passed |
SHA-256 / da43e52cdf90bec89cb24a2b5cf8ccdfbdbbfce69b8a9730dfe1585070447b0b
Verification & scope
Controlled rules-only simulation; not a complete 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:38:49.906202+00:00.
Case digest / 6f26bcdfdc07ff1fbd47a76d11c787d81a03c437947589b444dbdbd6af9507a2