|
|
|
@ -4,113 +4,122 @@ import { FinalOutcome, Player } from "../datatypes/types.ts"; |
|
|
|
|
import { createOpponent } from "../gameplay/opponent.ts"; |
|
|
|
|
import { computeAllSolutions } from "../gameplay/solver.ts"; |
|
|
|
|
import { tictactoeThreeRules } from "../game-variants/tictactoe/tictactoe-three-rules.ts"; |
|
|
|
|
import { checkNextMove, checkSolutionsComplete } from "./test-helpers.ts"; |
|
|
|
|
import { checkNextMove, checkSolutionsComplete, checkSolutionsIncomplete } from "./test-helpers.ts"; |
|
|
|
|
|
|
|
|
|
const rules = tictactoeThreeRules; |
|
|
|
|
|
|
|
|
|
void t.test("computeAllSolutions", async (t) => { |
|
|
|
|
// smallest possible board where X can win
|
|
|
|
|
checkSolutionsComplete(t, rules, 1, 5, { |
|
|
|
|
_____: { finalOutcome: FinalOutcome.Draw, movesLeft: 5 }, |
|
|
|
|
void t.test("1x5, smallest possible board where X can win", async (t) => { |
|
|
|
|
checkSolutionsComplete(t, rules, 1, 5, { |
|
|
|
|
_____: { finalOutcome: FinalOutcome.Draw, movesLeft: 5 }, |
|
|
|
|
|
|
|
|
|
X____: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
XO___: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
X_O__: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
X__O_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
X___O: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_X___: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
OX___: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_XO__: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_X_O_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_X__O: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
__X__: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
O_X__: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
_OX__: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__XO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__X_O: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
___X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
O__X_: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
_O_X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__OX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
___XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
____X: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
O___X: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_O__X: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__O_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
___OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
X____: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
XO___: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
X_O__: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
X__O_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
X___O: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_X___: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
OX___: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_XO__: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_X_O_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_X__O: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
__X__: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
O_X__: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
_OX__: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__XO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__X_O: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
___X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
O__X_: { finalOutcome: FinalOutcome.WinX, movesLeft: 3 }, |
|
|
|
|
_O_X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__OX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
___XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
____X: { finalOutcome: FinalOutcome.Draw, movesLeft: 4 }, |
|
|
|
|
O___X: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
_O__X: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
__O_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
___OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 3 }, |
|
|
|
|
|
|
|
|
|
XOX__: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XO_X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XO__X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XXO__: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_OX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_O_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XX_O_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_XO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X__OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XX__O: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_X_O: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X__XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
OXX__: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
OX_X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
OX__X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XOX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XO_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XXO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_X_OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XX_O: { finalOutcome: FinalOutcome.WinX, movesLeft: 2 }, |
|
|
|
|
_X_XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
O_XX_: { finalOutcome: FinalOutcome.WinX, movesLeft: 2 }, |
|
|
|
|
O_X_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_OXX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_OX_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
__XOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
__XXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
O__XX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_O_XX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
__OXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XOX__: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XO_X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XO__X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XXO__: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_OX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_O_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XX_O_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_XO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X__OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
XX__O: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X_X_O: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
X__XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
OXX__: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
OX_X_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
OX__X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XOX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XO_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XXO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_X_OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_XX_O: { finalOutcome: FinalOutcome.WinX, movesLeft: 2 }, |
|
|
|
|
_X_XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
O_XX_: { finalOutcome: FinalOutcome.WinX, movesLeft: 2 }, |
|
|
|
|
O_X_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_OXX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_OX_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
__XOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
__XXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
O__XX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
_O_XX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
__OXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 2 }, |
|
|
|
|
|
|
|
|
|
XOXO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XOX_O: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XOOX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XO_XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XOO_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XO_OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XXOO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XXO_O: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
X_OXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
X_OOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XX_OO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
X_XOO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OXXO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OXX_O: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OXOX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OX_XO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OXO_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OX_OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_XOXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_XOOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_XXOO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OOXX_: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
O_XXO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OOX_X: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
O_XOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_OXXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_OXOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OO_XX: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
O_OXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_OOXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XOXO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XOX_O: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XOOX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XO_XO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XOO_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XO_OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XXOO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XXO_O: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
X_OXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
X_OOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
XX_OO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
X_XOO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OXXO_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OXX_O: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OXOX_: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OX_XO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OXO_X: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OX_OX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_XOXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_XOOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_XXOO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OOXX_: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
O_XXO: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
OOX_X: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
O_XOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_OXXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_OXOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
OO_XX: { finalOutcome: FinalOutcome.WinX, movesLeft: 1 }, |
|
|
|
|
O_OXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
_OOXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 1 }, |
|
|
|
|
|
|
|
|
|
XOXOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XOXXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XOOXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XXOOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XXOXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XXXOO: { finalOutcome: FinalOutcome.WinX, movesLeft: 0 }, |
|
|
|
|
OXXOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
OXXXO: { finalOutcome: FinalOutcome.WinX, movesLeft: 0 }, |
|
|
|
|
OXOXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
OOXXX: { finalOutcome: FinalOutcome.WinX, movesLeft: 0 }, |
|
|
|
|
XOXOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XOXXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XOOXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XXOOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XXOXO: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
XXXOO: { finalOutcome: FinalOutcome.WinX, movesLeft: 0 }, |
|
|
|
|
OXXOX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
OXXXO: { finalOutcome: FinalOutcome.WinX, movesLeft: 0 }, |
|
|
|
|
OXOXX: { finalOutcome: FinalOutcome.Draw, movesLeft: 0 }, |
|
|
|
|
OOXXX: { finalOutcome: FinalOutcome.WinX, movesLeft: 0 }, |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
void t.test("number of combinations for 3x4 board", async (t) => { |
|
|
|
|
checkSolutionsIncomplete(t, rules, 3, 4, 111973, {}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
void t.test("number of combinations for 4x3 board", async (t) => { |
|
|
|
|
checkSolutionsIncomplete(t, rules, 4, 3, 111973, {}); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|