board-game-engine 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +33 -0
- package/README.md +2 -2
- package/dist/board-game-engine.cjs +463 -349
- package/dist/board-game-engine.js +463 -349
- package/dist/board-game-engine.min.js +22 -22
- package/dist/board-game-engine.mjs +461 -348
- package/dist/client/client.d.ts +76 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/game-factory/bank/bank-slot.d.ts +30 -0
- package/dist/game-factory/bank/bank-slot.d.ts.map +1 -0
- package/dist/game-factory/bank/bank.d.ts +34 -0
- package/dist/game-factory/bank/bank.d.ts.map +1 -0
- package/dist/game-factory/board.d.ts +4 -0
- package/dist/game-factory/board.d.ts.map +1 -0
- package/dist/game-factory/condition/condition-factory.d.ts +4 -0
- package/dist/game-factory/condition/condition-factory.d.ts.map +1 -0
- package/dist/game-factory/condition/condition.d.ts +13 -0
- package/dist/game-factory/condition/condition.d.ts.map +1 -0
- package/dist/game-factory/condition/contains-condition.d.ts +8 -0
- package/dist/game-factory/condition/contains-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/contains-same-condition.d.ts +7 -0
- package/dist/game-factory/condition/contains-same-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/evaluate-condition.d.ts +8 -0
- package/dist/game-factory/condition/evaluate-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/every-condition.d.ts +12 -0
- package/dist/game-factory/condition/every-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/has-line-condition.d.ts +8 -0
- package/dist/game-factory/condition/has-line-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/in-line-condition.d.ts +8 -0
- package/dist/game-factory/condition/in-line-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/is-condition.d.ts +8 -0
- package/dist/game-factory/condition/is-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/is-full-condition.d.ts +7 -0
- package/dist/game-factory/condition/is-full-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/no-possible-moves-condition.d.ts +7 -0
- package/dist/game-factory/condition/no-possible-moves-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/not-condition.d.ts +7 -0
- package/dist/game-factory/condition/not-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/or-condition.d.ts +7 -0
- package/dist/game-factory/condition/or-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/position-condition.d.ts +7 -0
- package/dist/game-factory/condition/position-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/some-condition.d.ts +8 -0
- package/dist/game-factory/condition/some-condition.d.ts.map +1 -0
- package/dist/game-factory/condition/would-condition.d.ts +8 -0
- package/dist/game-factory/condition/would-condition.d.ts.map +1 -0
- package/dist/game-factory/entity.d.ts +13 -0
- package/dist/game-factory/entity.d.ts.map +1 -0
- package/dist/game-factory/expand-game-rules.d.ts +3 -0
- package/dist/game-factory/expand-game-rules.d.ts.map +1 -0
- package/dist/game-factory/game-factory.d.ts +10 -0
- package/dist/game-factory/game-factory.d.ts.map +1 -0
- package/{src/game-factory/move/end-turn.js → dist/game-factory/move/end-turn.d.ts} +2 -4
- package/dist/game-factory/move/end-turn.d.ts.map +1 -0
- package/dist/game-factory/move/for-each.d.ts +5 -0
- package/dist/game-factory/move/for-each.d.ts.map +1 -0
- package/dist/game-factory/move/index.d.ts +6 -0
- package/dist/game-factory/move/index.d.ts.map +1 -0
- package/dist/game-factory/move/move-entity.d.ts +7 -0
- package/dist/game-factory/move/move-entity.d.ts.map +1 -0
- package/dist/game-factory/move/move-factory.d.ts +18 -0
- package/dist/game-factory/move/move-factory.d.ts.map +1 -0
- package/dist/game-factory/move/move.d.ts +54 -0
- package/dist/game-factory/move/move.d.ts.map +1 -0
- package/dist/game-factory/move/pass-turn.d.ts +5 -0
- package/dist/game-factory/move/pass-turn.d.ts.map +1 -0
- package/{src/game-factory/move/pass.js → dist/game-factory/move/pass.d.ts} +2 -4
- package/dist/game-factory/move/pass.d.ts.map +1 -0
- package/dist/game-factory/move/place-new.d.ts +5 -0
- package/dist/game-factory/move/place-new.d.ts.map +1 -0
- package/dist/game-factory/move/remove-entity.d.ts +5 -0
- package/dist/game-factory/move/remove-entity.d.ts.map +1 -0
- package/dist/game-factory/move/set-active-players.d.ts +5 -0
- package/dist/game-factory/move/set-active-players.d.ts.map +1 -0
- package/dist/game-factory/move/set-state.d.ts +5 -0
- package/dist/game-factory/move/set-state.d.ts.map +1 -0
- package/dist/game-factory/move/shuffle.d.ts +5 -0
- package/dist/game-factory/move/shuffle.d.ts.map +1 -0
- package/dist/game-factory/move/take-from.d.ts +11 -0
- package/dist/game-factory/move/take-from.d.ts.map +1 -0
- package/dist/game-factory/space/space.d.ts +10 -0
- package/dist/game-factory/space/space.d.ts.map +1 -0
- package/dist/game-factory/space-group/grid.d.ts +15 -0
- package/dist/game-factory/space-group/grid.d.ts.map +1 -0
- package/dist/game-factory/space-group/space-group.d.ts +20 -0
- package/dist/game-factory/space-group/space-group.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/registry.d.ts +17 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/types/bagel-types.d.ts +339 -0
- package/dist/types/bagel-types.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/rule-with-conditions.d.ts +9 -0
- package/dist/types/rule-with-conditions.d.ts.map +1 -0
- package/dist/utils/any-valid-moves.d.ts +2 -0
- package/dist/utils/any-valid-moves.d.ts.map +1 -0
- package/dist/utils/bgio-resolve-types.d.ts +25 -0
- package/dist/utils/bgio-resolve-types.d.ts.map +1 -0
- package/dist/utils/check-conditions.d.ts +7 -0
- package/dist/utils/check-conditions.d.ts.map +1 -0
- package/dist/utils/create-payload.d.ts +5 -0
- package/dist/utils/create-payload.d.ts.map +1 -0
- package/dist/utils/deserialize-bgio-arguments.d.ts +3 -0
- package/dist/utils/deserialize-bgio-arguments.d.ts.map +1 -0
- package/dist/utils/do-moves.d.ts +8 -0
- package/dist/utils/do-moves.d.ts.map +1 -0
- package/dist/utils/entity-matches.d.ts +6 -0
- package/dist/utils/entity-matches.d.ts.map +1 -0
- package/dist/utils/find-met-condition.d.ts +6 -0
- package/dist/utils/find-met-condition.d.ts.map +1 -0
- package/dist/utils/get-current-moves.d.ts +24 -0
- package/dist/utils/get-current-moves.d.ts.map +1 -0
- package/dist/utils/get-scenario-results.d.ts +3 -0
- package/dist/utils/get-scenario-results.d.ts.map +1 -0
- package/dist/utils/get-steps.d.ts +13 -0
- package/dist/utils/get-steps.d.ts.map +1 -0
- package/dist/utils/get.d.ts +7 -0
- package/dist/utils/get.d.ts.map +1 -0
- package/dist/utils/grid-contains-sequence.d.ts +27 -0
- package/dist/utils/grid-contains-sequence.d.ts.map +1 -0
- package/dist/utils/json-transformer.d.ts +8 -0
- package/dist/utils/json-transformer.d.ts.map +1 -0
- package/dist/utils/prepare-payload.d.ts +2 -0
- package/dist/utils/prepare-payload.d.ts.map +1 -0
- package/dist/utils/resolve-entity.d.ts +3 -0
- package/dist/utils/resolve-entity.d.ts.map +1 -0
- package/dist/utils/resolve-expression.d.ts +6 -0
- package/dist/utils/resolve-expression.d.ts.map +1 -0
- package/dist/utils/resolve-properties.d.ts +4 -0
- package/dist/utils/resolve-properties.d.ts.map +1 -0
- package/dist/utils/simulate-move.d.ts +16 -0
- package/dist/utils/simulate-move.d.ts.map +1 -0
- package/e2e/fixtures/bge-checkers.html +1 -2
- package/e2e/fixtures/bge-minimal.html +1 -2
- package/e2e/fixtures/bge-ttt.html +1 -2
- package/examples/index.html +1 -1
- package/package.json +9 -3
- package/playwright-report/index.html +1 -1
- package/scripts/build.mjs +2 -2
- package/src/client/client.ts +305 -0
- package/src/game-factory/bank/bank-slot.ts +81 -0
- package/src/game-factory/bank/bank.ts +125 -0
- package/src/game-factory/{board.js → board.ts} +1 -1
- package/src/game-factory/condition/condition-factory.ts +59 -0
- package/src/game-factory/condition/condition.ts +50 -0
- package/src/game-factory/condition/{contains-condition.js → contains-condition.ts} +5 -4
- package/src/game-factory/condition/{contains-same-condition.js → contains-same-condition.ts} +8 -5
- package/src/game-factory/condition/{evaluate-condition.js → evaluate-condition.ts} +4 -3
- package/src/game-factory/condition/every-condition.ts +27 -0
- package/src/game-factory/condition/has-line-condition.ts +15 -0
- package/src/game-factory/condition/in-line-condition.ts +25 -0
- package/src/game-factory/condition/is-condition.ts +24 -0
- package/src/game-factory/condition/is-full-condition.ts +10 -0
- package/src/game-factory/condition/{no-possible-moves-condition.js → no-possible-moves-condition.ts} +3 -2
- package/src/game-factory/condition/{not-condition.js → not-condition.ts} +3 -2
- package/src/game-factory/condition/{or-condition.js → or-condition.ts} +3 -2
- package/src/game-factory/condition/position-condition.ts +13 -0
- package/src/game-factory/condition/{some-condition.js → some-condition.ts} +5 -3
- package/src/game-factory/condition/would-condition.ts +104 -0
- package/src/game-factory/entity.ts +37 -0
- package/src/game-factory/expand-game-rules.ts +263 -0
- package/src/game-factory/game-factory.ts +263 -0
- package/src/game-factory/move/end-turn.ts +7 -0
- package/src/game-factory/move/for-each.ts +20 -0
- package/src/game-factory/move/move-entity.ts +18 -0
- package/src/game-factory/move/move-factory.ts +107 -0
- package/src/game-factory/move/move.ts +147 -0
- package/src/game-factory/move/pass-turn.ts +15 -0
- package/src/game-factory/move/pass.ts +7 -0
- package/src/game-factory/move/place-new.ts +42 -0
- package/src/game-factory/move/remove-entity.ts +11 -0
- package/src/game-factory/move/set-active-players.ts +26 -0
- package/src/game-factory/move/set-state.ts +14 -0
- package/src/game-factory/move/shuffle.ts +9 -0
- package/src/game-factory/move/take-from.ts +12 -0
- package/src/game-factory/space/space.ts +36 -0
- package/src/game-factory/space-group/grid.ts +48 -0
- package/src/game-factory/space-group/space-group.ts +44 -0
- package/src/index.ts +5 -0
- package/src/types/bagel-types.ts +449 -0
- package/src/types/boardgame-io-core.d.ts +7 -0
- package/src/types/index.ts +70 -0
- package/src/types/rule-with-conditions.ts +9 -0
- package/src/utils/{any-valid-moves.js → any-valid-moves.ts} +54 -49
- package/src/utils/bgio-resolve-types.ts +27 -0
- package/src/utils/check-conditions.ts +28 -0
- package/src/utils/create-payload.ts +19 -0
- package/src/utils/deserialize-bgio-arguments.ts +10 -0
- package/src/utils/do-moves.ts +22 -0
- package/src/utils/entity-matches.ts +30 -0
- package/src/utils/expr-eval.d.ts +6 -0
- package/src/utils/find-met-condition.ts +23 -0
- package/src/utils/get-current-moves.ts +39 -0
- package/src/utils/get-scenario-results.ts +30 -0
- package/src/utils/get-steps.ts +38 -0
- package/src/utils/get.ts +28 -0
- package/src/utils/{grid-contains-sequence.js → grid-contains-sequence.ts} +71 -33
- package/src/utils/json-transformer.ts +17 -0
- package/src/utils/prepare-payload.ts +20 -0
- package/src/utils/resolve-entity.ts +15 -0
- package/src/utils/resolve-expression.ts +16 -0
- package/src/utils/resolve-properties.ts +172 -0
- package/src/utils/simulate-move.ts +32 -0
- package/src/wackson.d.ts +4 -0
- package/tsconfig.build.json +14 -0
- package/tsconfig.json +21 -0
- package/src/client/client.js +0 -224
- package/src/game-factory/bank/bank-slot.js +0 -69
- package/src/game-factory/bank/bank.js +0 -114
- package/src/game-factory/condition/condition-factory.js +0 -52
- package/src/game-factory/condition/condition.js +0 -39
- package/src/game-factory/condition/every-condition.js +0 -25
- package/src/game-factory/condition/has-line-condition.js +0 -14
- package/src/game-factory/condition/in-line-condition.js +0 -19
- package/src/game-factory/condition/is-condition.js +0 -23
- package/src/game-factory/condition/is-full-condition.js +0 -9
- package/src/game-factory/condition/position-condition.js +0 -12
- package/src/game-factory/condition/would-condition.js +0 -94
- package/src/game-factory/entity.js +0 -29
- package/src/game-factory/expand-game-rules.js +0 -271
- package/src/game-factory/game-factory.js +0 -239
- package/src/game-factory/move/for-each.js +0 -18
- package/src/game-factory/move/move-entity.js +0 -16
- package/src/game-factory/move/move-factory.js +0 -89
- package/src/game-factory/move/move.js +0 -131
- package/src/game-factory/move/pass-turn.js +0 -10
- package/src/game-factory/move/place-new.js +0 -33
- package/src/game-factory/move/remove-entity.js +0 -7
- package/src/game-factory/move/set-active-players.js +0 -23
- package/src/game-factory/move/set-state.js +0 -11
- package/src/game-factory/move/shuffle.js +0 -7
- package/src/game-factory/move/take-from.js +0 -7
- package/src/game-factory/space/space.js +0 -30
- package/src/game-factory/space-group/grid.js +0 -43
- package/src/game-factory/space-group/space-group.js +0 -29
- package/src/index.js +0 -2
- package/src/utils/check-conditions.js +0 -28
- package/src/utils/create-payload.js +0 -16
- package/src/utils/deserialize-bgio-arguments.js +0 -8
- package/src/utils/do-moves.js +0 -18
- package/src/utils/entity-matches.js +0 -20
- package/src/utils/find-met-condition.js +0 -22
- package/src/utils/get-current-moves.js +0 -12
- package/src/utils/get-scenario-results.js +0 -23
- package/src/utils/get-steps.js +0 -29
- package/src/utils/get.js +0 -25
- package/src/utils/json-transformer.js +0 -12
- package/src/utils/prepare-payload.js +0 -16
- package/src/utils/resolve-entity.js +0 -9
- package/src/utils/resolve-expression.js +0 -10
- package/src/utils/resolve-properties.js +0 -149
- package/src/utils/simulate-move.js +0 -25
- /package/src/game-factory/move/{index.js → index.ts} +0 -0
- /package/src/{registry.js → registry.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-met-condition.d.ts","sourceRoot":"","sources":["../../src/utils/find-met-condition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE1E,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,aAAa,EAAE,OAAO,EACtB,UAAU,EAAE,aAAa,EAAE,YAAK,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;mBAEF,OAAO;cAatC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal shape of the boardgame.io client (or stand-in) used to resolve the active move set.
|
|
3
|
+
*/
|
|
4
|
+
export interface GetCurrentMovesClient {
|
|
5
|
+
game: {
|
|
6
|
+
phases?: Record<string, unknown>;
|
|
7
|
+
moves?: Record<string, unknown>;
|
|
8
|
+
turn?: {
|
|
9
|
+
stages?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
playerID?: string;
|
|
13
|
+
stageName?: string;
|
|
14
|
+
}
|
|
15
|
+
/** `state` shape expected by {@link getCurrentMoves} (boardgame.io match state). */
|
|
16
|
+
export interface GetCurrentMovesState {
|
|
17
|
+
ctx: {
|
|
18
|
+
phase?: string;
|
|
19
|
+
activePlayers?: Record<string, string>;
|
|
20
|
+
currentPlayer?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export default function getCurrentMoves(state: GetCurrentMovesState, client: GetCurrentMovesClient): Record<string, unknown>;
|
|
24
|
+
//# sourceMappingURL=get-current-moves.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-current-moves.d.ts","sourceRoot":"","sources":["../../src/utils/get-current-moves.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE;QACJ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,CAAC;KAC7C,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACvC,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAID,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,qBAAqB,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-scenario-results.d.ts","sourceRoot":"","sources":["../../src/utils/get-scenario-results.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,aAAa,EAAE,gBAAgB,EAC/B,SAAS,EAAE,OAAO,EAAE,WAuBrB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type BgioResolveState } from "./bgio-resolve-types.js";
|
|
2
|
+
export default function getSteps(bgioState: BgioResolveState, moveRule: {
|
|
3
|
+
moveType: string;
|
|
4
|
+
arguments: Record<string, {
|
|
5
|
+
playerChoice?: boolean;
|
|
6
|
+
possibleValues?: unknown[];
|
|
7
|
+
[k: string]: unknown;
|
|
8
|
+
}>;
|
|
9
|
+
}): {
|
|
10
|
+
argName: string;
|
|
11
|
+
getClickable: (context: Record<string, unknown>) => unknown[];
|
|
12
|
+
}[];
|
|
13
|
+
//# sourceMappingURL=get-steps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-steps.d.ts","sourceRoot":"","sources":["../../src/utils/get-steps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAYxE,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC9B,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE;IACR,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;CACzG;;4BAciB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAM1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../src/utils/get.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CAAE,CAAC;AAElF,MAAM,CAAC,OAAO,UAAU,GAAG,CAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAyBzE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Condition } from "../types/bagel-types.js";
|
|
2
|
+
export type SequenceChunk = {
|
|
3
|
+
count?: number;
|
|
4
|
+
minCount?: number;
|
|
5
|
+
maxCount?: number;
|
|
6
|
+
conditions?: Condition[];
|
|
7
|
+
};
|
|
8
|
+
type GridEntity = {
|
|
9
|
+
entities?: unknown[];
|
|
10
|
+
[k: string]: unknown;
|
|
11
|
+
};
|
|
12
|
+
type GridSpace = {
|
|
13
|
+
entities?: GridEntity[];
|
|
14
|
+
[k: string]: unknown;
|
|
15
|
+
};
|
|
16
|
+
export type GridLike = {
|
|
17
|
+
attributes: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
|
21
|
+
entities?: GridSpace[];
|
|
22
|
+
areCoordinatesValid: (c: number[]) => boolean;
|
|
23
|
+
getSpace: (c: number[]) => unknown;
|
|
24
|
+
};
|
|
25
|
+
export default function gridContainsSequence(bgioArguments: unknown, grid: GridLike, sequencePattern: SequenceChunk[], context: Record<string, unknown>): unknown;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=grid-contains-sequence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid-contains-sequence.d.ts","sourceRoot":"","sources":["../../src/utils/grid-contains-sequence.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;CAC1B,CAAC;AAEF,KAAK,UAAU,GAAG;IAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AACjE,KAAK,SAAS,GAAG;IAAE,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AACnE,MAAM,MAAM,QAAQ,GAAG;IACrB,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB,mBAAmB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IAC9C,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;CACpC,CAAC;AAwLF,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAC1C,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE,QAAQ,EACd,eAAe,EAAE,aAAa,EAAE,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WAwDjC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type TransformRule = {
|
|
2
|
+
test: (val: unknown) => boolean;
|
|
3
|
+
replace: (val: unknown) => unknown;
|
|
4
|
+
};
|
|
5
|
+
/** Recurse and replace. Circular references not allowed. */
|
|
6
|
+
export default function transformJSON(data: unknown, rules: TransformRule[]): unknown;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=json-transformer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-transformer.d.ts","sourceRoot":"","sources":["../../src/utils/json-transformer.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAChC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;CACpC,CAAC;AAEF,4DAA4D;AAC5D,MAAM,CAAC,OAAO,UAAU,aAAa,CAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAUrF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-payload.d.ts","sourceRoot":"","sources":["../../src/utils/prepare-payload.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,OAAO,UAAU,cAAc,CAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAgBjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-entity.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-entity.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIxE,MAAM,CAAC,OAAO,UAAU,aAAa,CACnC,aAAa,EAAE,gBAAgB,EAC/B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAIT"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BgioResolveState } from "./bgio-resolve-types.js";
|
|
2
|
+
export default function resolveExpression(bgioArguments: BgioResolveState, rule: {
|
|
3
|
+
expression: string;
|
|
4
|
+
arguments?: unknown;
|
|
5
|
+
}, context: Record<string, unknown>): unknown;
|
|
6
|
+
//# sourceMappingURL=resolve-expression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-expression.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-expression.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACvC,aAAa,EAAE,gBAAgB,EAC/B,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EACjD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAGT"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type BgioResolveState } from "./bgio-resolve-types.js";
|
|
2
|
+
export type { BgioResolveState };
|
|
3
|
+
export default function resolveProperties(bgioArguments: BgioResolveState, obj: unknown, context?: Record<string, unknown>, key?: string): unknown;
|
|
4
|
+
//# sourceMappingURL=resolve-properties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-properties.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-properties.ts"],"names":[],"mappings":"AAKA,OAAO,EAAU,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAExE,YAAY,EAAE,gBAAgB,EAAE,CAAC;AASjC,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACvC,aAAa,EAAE,gBAAgB,EAC/B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CA6BT"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BgioResolveState } from "./bgio-resolve-types.js";
|
|
2
|
+
export default function simulateMove(bgioArguments: BgioResolveState, payload: {
|
|
3
|
+
arguments: Record<string, {
|
|
4
|
+
abstract?: boolean;
|
|
5
|
+
entityId?: unknown;
|
|
6
|
+
} | number>;
|
|
7
|
+
}, context: {
|
|
8
|
+
moveInstance: {
|
|
9
|
+
doMove: (...args: unknown[]) => unknown;
|
|
10
|
+
};
|
|
11
|
+
}): {
|
|
12
|
+
bank: {
|
|
13
|
+
locate: (id: unknown) => unknown;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=simulate-move.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simulate-move.d.ts","sourceRoot":"","sources":["../../src/utils/simulate-move.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,aAAa,EAAE,gBAAgB,EAC/B,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC,CAAA;CAAE,EAC3F,OAAO,EAAE;IAAE,YAAY,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAA;KAAE,CAAA;CAAE;UAG9D;QAAE,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,OAAO,CAAA;KAAE;EAqB7C"}
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
let gameRules;
|
|
19
19
|
try {
|
|
20
20
|
const res = await fetch('/examples/checkers.json');
|
|
21
|
-
|
|
22
|
-
gameRules = JSON.stringify(rules);
|
|
21
|
+
gameRules = await res.json();
|
|
23
22
|
} catch (e) {
|
|
24
23
|
out.textContent = 'Fetch failed: ' + (e && e.message);
|
|
25
24
|
return;
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
let gameRules;
|
|
19
19
|
try {
|
|
20
20
|
const res = await fetch('/e2e/fixtures/minimal-game.json');
|
|
21
|
-
|
|
22
|
-
gameRules = JSON.stringify(rules);
|
|
21
|
+
gameRules = await res.json();
|
|
23
22
|
} catch (e) {
|
|
24
23
|
out.textContent = 'Fetch failed: ' + (e && e.message);
|
|
25
24
|
return;
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
let gameRules;
|
|
19
19
|
try {
|
|
20
20
|
const res = await fetch('/examples/tic-tac-toe.json');
|
|
21
|
-
|
|
22
|
-
gameRules = JSON.stringify(rules);
|
|
21
|
+
gameRules = await res.json();
|
|
23
22
|
} catch (e) {
|
|
24
23
|
out.textContent = 'Fetch failed: ' + (e && e.message);
|
|
25
24
|
return;
|
package/examples/index.html
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "board-game-engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "wip board game engine",
|
|
5
5
|
"main": "dist/board-game-engine.cjs",
|
|
6
6
|
"module": "dist/board-game-engine.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
9
11
|
"import": "./dist/board-game-engine.mjs",
|
|
10
12
|
"require": "./dist/board-game-engine.cjs"
|
|
11
13
|
}
|
|
@@ -19,12 +21,16 @@
|
|
|
19
21
|
"test:e2e:install": "playwright install firefox",
|
|
20
22
|
"serve": "http-server . -p 5174 -c-1",
|
|
21
23
|
"lint": "eslint .",
|
|
22
|
-
"build": "node scripts/build.mjs",
|
|
24
|
+
"build": "node scripts/build.mjs && npm run build:types",
|
|
25
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
23
27
|
"prepublishOnly": "npm run build"
|
|
24
28
|
},
|
|
25
29
|
"author": "Matthew Broatch",
|
|
26
30
|
"license": "ISC",
|
|
27
31
|
"devDependencies": {
|
|
32
|
+
"@playwright/test": "^1.49.0",
|
|
33
|
+
"@types/lodash": "^4.17.24",
|
|
28
34
|
"cross-env": "^7.0.3",
|
|
29
35
|
"esbuild": "^0.24.0",
|
|
30
36
|
"esbuild-plugin-istanbul": "^0.3.0",
|
|
@@ -34,7 +40,7 @@
|
|
|
34
40
|
"http-server": "^14.1.1",
|
|
35
41
|
"nyc": "^15.1.0",
|
|
36
42
|
"standard": "^16.0.4",
|
|
37
|
-
"
|
|
43
|
+
"typescript": "^5.9.3"
|
|
38
44
|
},
|
|
39
45
|
"dependencies": {
|
|
40
46
|
"@mnbroatch/boardgame.io": "0.0.1",
|
|
@@ -82,4 +82,4 @@ Error generating stack: `+a.message+`
|
|
|
82
82
|
<div id='root'></div>
|
|
83
83
|
</body>
|
|
84
84
|
</html>
|
|
85
|
-
<script id="playwrightReportBase64" type="application/zip">data:application/zip;base64,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</script>
|
|
85
|
+
<script id="playwrightReportBase64" type="application/zip">data:application/zip;base64,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</script>
|
package/scripts/build.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as esbuild from 'esbuild'
|
|
2
2
|
import { esbuildPluginIstanbul } from 'esbuild-plugin-istanbul'
|
|
3
3
|
|
|
4
|
-
const entry = 'src/index.
|
|
4
|
+
const entry = 'src/index.ts'
|
|
5
5
|
const outdir = 'dist'
|
|
6
6
|
const globalName = 'BoardGameEngine'
|
|
7
7
|
const coverage = process.env.COVERAGE === '1'
|
|
@@ -24,7 +24,7 @@ if (coverage) {
|
|
|
24
24
|
esbuildPluginIstanbul({
|
|
25
25
|
name: 'istanbul',
|
|
26
26
|
filter: /\.(js|ts)$/,
|
|
27
|
-
include: ['src/**/*.js'],
|
|
27
|
+
include: ['src/**/*.{js,ts}'],
|
|
28
28
|
exclude: ['**/*.spec.js', '**/node_modules/**'],
|
|
29
29
|
}),
|
|
30
30
|
],
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { Client as BoardgameIOClient } from "@mnbroatch/boardgame.io/client";
|
|
2
|
+
import { Debug } from "@mnbroatch/boardgame.io/debug";
|
|
3
|
+
import { SocketIO } from "@mnbroatch/boardgame.io/multiplayer";
|
|
4
|
+
import { serialize, deserialize } from "wackson";
|
|
5
|
+
import gameFactory from "../game-factory/game-factory.js";
|
|
6
|
+
import type { BoardGameEngineGame, BgioArguments } from "../game-factory/game-factory.js";
|
|
7
|
+
import type { Condition, GameFactoryInput } from "../types/bagel-types.js";
|
|
8
|
+
import { registry } from "../registry.js";
|
|
9
|
+
import simulateMove from "../utils/simulate-move.js";
|
|
10
|
+
import getCurrentMoves from "../utils/get-current-moves.js";
|
|
11
|
+
import type { GetCurrentMovesClient, GetCurrentMovesState } from "../utils/get-current-moves.js";
|
|
12
|
+
import resolveProperties from "../utils/resolve-properties.js";
|
|
13
|
+
import type { BgioResolveState } from "../utils/bgio-resolve-types.js";
|
|
14
|
+
import checkConditions from "../utils/check-conditions.js";
|
|
15
|
+
import preparePayload from "../utils/prepare-payload.js";
|
|
16
|
+
import getSteps from "../utils/get-steps.js";
|
|
17
|
+
import createPayload from "../utils/create-payload.js";
|
|
18
|
+
|
|
19
|
+
export interface ClientOptions {
|
|
20
|
+
boardgameIOGame?: BoardGameEngineGame;
|
|
21
|
+
gameRules?: GameFactoryInput;
|
|
22
|
+
gameName?: string;
|
|
23
|
+
server?: string;
|
|
24
|
+
numPlayers?: number;
|
|
25
|
+
debug?: {
|
|
26
|
+
collapseOnLoad?: boolean;
|
|
27
|
+
impl?: typeof Debug;
|
|
28
|
+
};
|
|
29
|
+
matchID?: string;
|
|
30
|
+
playerID?: string | null;
|
|
31
|
+
credentials?: string;
|
|
32
|
+
multiplayer?: ReturnType<typeof SocketIO>;
|
|
33
|
+
onClientUpdate?: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface MoveBuilder {
|
|
37
|
+
targets: unknown[];
|
|
38
|
+
stepIndex: number;
|
|
39
|
+
eliminatedMoves: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class Client {
|
|
43
|
+
options: ClientOptions;
|
|
44
|
+
game: BoardGameEngineGame;
|
|
45
|
+
client?: ReturnType<typeof BoardgameIOClient>;
|
|
46
|
+
moveBuilder?: MoveBuilder;
|
|
47
|
+
optimisticWinner?: unknown | null;
|
|
48
|
+
|
|
49
|
+
constructor (options: ClientOptions) {
|
|
50
|
+
this.options = options;
|
|
51
|
+
this.game = options.boardgameIOGame
|
|
52
|
+
|| gameFactory(options.gameRules!, options.gameName ?? "");
|
|
53
|
+
|
|
54
|
+
if (!options.boardgameIOGame) {
|
|
55
|
+
this.moveBuilder = { targets: [], stepIndex: 0, eliminatedMoves: [] };
|
|
56
|
+
this.optimisticWinner = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
connect () {
|
|
61
|
+
const {
|
|
62
|
+
server,
|
|
63
|
+
numPlayers,
|
|
64
|
+
debug = {
|
|
65
|
+
collapseOnLoad: true,
|
|
66
|
+
impl: Debug,
|
|
67
|
+
},
|
|
68
|
+
matchID,
|
|
69
|
+
playerID,
|
|
70
|
+
credentials,
|
|
71
|
+
multiplayer = SocketIO({ server, socketOpts: { transports: ["websocket", "polling"] } }),
|
|
72
|
+
} = this.options;
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const clientOptions = !credentials
|
|
76
|
+
? { game: this.game, numPlayers, debug }
|
|
77
|
+
: {
|
|
78
|
+
game: this.game,
|
|
79
|
+
multiplayer,
|
|
80
|
+
matchID,
|
|
81
|
+
playerID: playerID ?? undefined,
|
|
82
|
+
credentials,
|
|
83
|
+
numPlayers,
|
|
84
|
+
debug,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
this.client = BoardgameIOClient(clientOptions as Parameters<typeof BoardgameIOClient>[0]);
|
|
88
|
+
this.client.subscribe(() => this.update());
|
|
89
|
+
this.client.start();
|
|
90
|
+
return this;
|
|
91
|
+
} catch (error: unknown) {
|
|
92
|
+
const err = error as { message?: string; stack?: string };
|
|
93
|
+
console.error("Failed to join game:", err?.message ?? error);
|
|
94
|
+
if (err?.stack) console.error(err.stack);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
update () {
|
|
99
|
+
this.options.onClientUpdate?.();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getState () {
|
|
103
|
+
const bgioState = this.client?.getState();
|
|
104
|
+
if (!bgioState) return {};
|
|
105
|
+
|
|
106
|
+
const state = this.options.boardgameIOGame
|
|
107
|
+
? bgioState
|
|
108
|
+
: {
|
|
109
|
+
...bgioState,
|
|
110
|
+
G: deserialize(JSON.stringify(bgioState.G), registry),
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const gameover = this.optimisticWinner ?? state?.ctx?.gameover;
|
|
114
|
+
|
|
115
|
+
const currentMoves = gameover
|
|
116
|
+
? []
|
|
117
|
+
: getCurrentMoves(state as GetCurrentMovesState, this.client as GetCurrentMovesClient);
|
|
118
|
+
|
|
119
|
+
if (this.options.boardgameIOGame) {
|
|
120
|
+
return {
|
|
121
|
+
state,
|
|
122
|
+
gameover,
|
|
123
|
+
moves: this.client!.moves,
|
|
124
|
+
currentMoves,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const _wrappedMoves = Object.entries(currentMoves)
|
|
129
|
+
.reduce<Record<string, unknown>>((acc, [moveName, rawMove]) => {
|
|
130
|
+
const move = (payload: unknown) => {
|
|
131
|
+
this.client!.moves[moveName](preparePayload(payload));
|
|
132
|
+
};
|
|
133
|
+
(move as { moveInstance?: unknown }).moveInstance = (rawMove as { moveInstance: unknown }).moveInstance;
|
|
134
|
+
return { ...acc, [moveName]: move };
|
|
135
|
+
}, {});
|
|
136
|
+
|
|
137
|
+
const { allClickable, _possibleMoveMeta } = getPossibleMoves(state, _wrappedMoves, this.moveBuilder!);
|
|
138
|
+
|
|
139
|
+
return { state, gameover, allClickable, _wrappedMoves, _possibleMoveMeta };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
doStep (_target: unknown) {
|
|
143
|
+
if (this.options.boardgameIOGame) return;
|
|
144
|
+
|
|
145
|
+
const { state, _wrappedMoves, _possibleMoveMeta } = this.getState() as {
|
|
146
|
+
state: { G: { bank: { locate: (id: unknown) => unknown } } };
|
|
147
|
+
_wrappedMoves: Record<string, { (p: unknown): void; moveInstance: unknown }>;
|
|
148
|
+
_possibleMoveMeta: Record<string, { clickableForMove: Set<unknown> }>;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const target = (_target as { abstract?: boolean; entityId?: unknown; value?: unknown }).abstract
|
|
152
|
+
? _target
|
|
153
|
+
: state.G.bank.locate((_target as { entityId: unknown }).entityId);
|
|
154
|
+
|
|
155
|
+
const newEliminated = Object.entries(_possibleMoveMeta)
|
|
156
|
+
.filter(([_, meta]) => !hasTarget(meta.clickableForMove, target))
|
|
157
|
+
.map(([name]) => name)
|
|
158
|
+
.concat(this.moveBuilder!.eliminatedMoves);
|
|
159
|
+
|
|
160
|
+
if (newEliminated.length === Object.keys(_wrappedMoves).length) {
|
|
161
|
+
console.error("invalid move with target:", (target as { rule?: unknown })?.rule);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const remainingMoveEntries = Object.entries(_possibleMoveMeta)
|
|
166
|
+
.filter(([name]) => !newEliminated.includes(name));
|
|
167
|
+
|
|
168
|
+
if (isMoveCompleted(
|
|
169
|
+
state,
|
|
170
|
+
_wrappedMoves as Record<string, { moveInstance: { rule: unknown } }>,
|
|
171
|
+
remainingMoveEntries,
|
|
172
|
+
this.moveBuilder!.stepIndex
|
|
173
|
+
)) {
|
|
174
|
+
const [moveName] = remainingMoveEntries[0];
|
|
175
|
+
const move = _wrappedMoves[moveName];
|
|
176
|
+
const payload = createPayload(
|
|
177
|
+
state as unknown as BgioResolveState,
|
|
178
|
+
(move as { moveInstance: { rule: Parameters<typeof getSteps>[1] } }).moveInstance.rule,
|
|
179
|
+
[...this.moveBuilder!.targets, target],
|
|
180
|
+
{ moveInstance: (move as { moveInstance: unknown }).moveInstance }
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
this.optimisticWinner = getWinnerAfterMove(state, this.game, (move as { moveInstance: unknown }).moveInstance, payload);
|
|
184
|
+
move(payload);
|
|
185
|
+
this.moveBuilder = { targets: [], stepIndex: 0, eliminatedMoves: [] };
|
|
186
|
+
} else {
|
|
187
|
+
this.moveBuilder = {
|
|
188
|
+
eliminatedMoves: newEliminated,
|
|
189
|
+
stepIndex: this.moveBuilder!.stepIndex + 1,
|
|
190
|
+
targets: [...this.moveBuilder!.targets, target],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this.update();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
reset () {
|
|
198
|
+
if (this.options.boardgameIOGame) return;
|
|
199
|
+
this.moveBuilder = { targets: [], stepIndex: 0, eliminatedMoves: [] };
|
|
200
|
+
this.optimisticWinner = null;
|
|
201
|
+
this.update();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
undoStep () {
|
|
205
|
+
if (this.options.boardgameIOGame) return;
|
|
206
|
+
if (this.moveBuilder!.targets.length) {
|
|
207
|
+
this.moveBuilder = {
|
|
208
|
+
targets: this.moveBuilder!.targets.slice(0, -1),
|
|
209
|
+
stepIndex: Math.max(0, this.moveBuilder!.stepIndex - 1),
|
|
210
|
+
eliminatedMoves: [],
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
this.update();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function hasTarget (clickableSet: Set<unknown>, target: unknown) {
|
|
218
|
+
if (!(target as { abstract?: boolean }).abstract) return clickableSet.has(target);
|
|
219
|
+
return [...clickableSet].some((item) => (item as { abstract?: boolean; value?: unknown }).abstract && (item as { value: unknown }).value === (target as { value: unknown }).value);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function getPossibleMoves (
|
|
223
|
+
bgioState: unknown,
|
|
224
|
+
moves: Record<string, unknown>,
|
|
225
|
+
moveBuilder: MoveBuilder
|
|
226
|
+
) {
|
|
227
|
+
const { eliminatedMoves, stepIndex } = moveBuilder;
|
|
228
|
+
const _possibleMoveMeta: Record<string, { clickableForMove: Set<unknown> }> = {};
|
|
229
|
+
const allClickable = new Set<unknown>();
|
|
230
|
+
|
|
231
|
+
Object.entries(moves)
|
|
232
|
+
.filter(([moveName]) => !eliminatedMoves.includes(moveName))
|
|
233
|
+
.forEach(([moveName, move]) => {
|
|
234
|
+
const moveRule = resolveProperties(bgioState as BgioResolveState, {
|
|
235
|
+
...(move as { moveInstance: { rule: Record<string, unknown> } }).moveInstance.rule,
|
|
236
|
+
moveName,
|
|
237
|
+
}) as { arguments?: Record<string, unknown> };
|
|
238
|
+
|
|
239
|
+
const context = {
|
|
240
|
+
moveInstance: (move as { moveInstance: unknown }).moveInstance,
|
|
241
|
+
moveArguments: moveRule.arguments,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const targets = moveBuilder.targets.map((t) =>
|
|
245
|
+
(t as { abstract?: boolean }).abstract ? t : (bgioState as { G: { bank: { locate: (id: unknown) => unknown } } }).G.bank.locate((t as { entityId: unknown }).entityId)
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const payload = createPayload(
|
|
249
|
+
bgioState as BgioResolveState,
|
|
250
|
+
moveRule as Parameters<typeof getSteps>[1],
|
|
251
|
+
targets,
|
|
252
|
+
context
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
context.moveArguments = { ...context.moveArguments, ...payload.arguments };
|
|
256
|
+
|
|
257
|
+
const moveIsAllowed = checkConditions(
|
|
258
|
+
bgioState as BgioResolveState,
|
|
259
|
+
(moveRule as { conditions?: Condition[] }).conditions,
|
|
260
|
+
{},
|
|
261
|
+
context
|
|
262
|
+
).conditionsAreMet;
|
|
263
|
+
const moveSteps = getSteps(
|
|
264
|
+
bgioState as BgioResolveState,
|
|
265
|
+
moveRule as Parameters<typeof getSteps>[1]
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
const clickableForMove = new Set(
|
|
269
|
+
(moveIsAllowed && moveSteps?.[stepIndex]?.getClickable(context)) || []
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
_possibleMoveMeta[moveName] = { clickableForMove };
|
|
273
|
+
clickableForMove.forEach((entity) => allClickable.add(entity));
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
return { _possibleMoveMeta, allClickable };
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function isMoveCompleted (
|
|
280
|
+
state: unknown,
|
|
281
|
+
moves: Record<string, { moveInstance: { rule: unknown } }>,
|
|
282
|
+
remainingMoveEntries: [string, unknown][],
|
|
283
|
+
stepIndex: number
|
|
284
|
+
) {
|
|
285
|
+
return remainingMoveEntries.length === 1 &&
|
|
286
|
+
getSteps(
|
|
287
|
+
state as BgioResolveState,
|
|
288
|
+
moves[remainingMoveEntries[0][0]].moveInstance.rule as Parameters<typeof getSteps>[1]
|
|
289
|
+
).length === stepIndex + 1;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function getWinnerAfterMove (
|
|
293
|
+
state: unknown,
|
|
294
|
+
game: BoardGameEngineGame,
|
|
295
|
+
moveInstance: unknown,
|
|
296
|
+
movePayload: unknown
|
|
297
|
+
) {
|
|
298
|
+
const simulatedG = simulateMove(
|
|
299
|
+
state as unknown as BgioResolveState,
|
|
300
|
+
preparePayload(movePayload) as { arguments: Record<string, number | { abstract?: boolean; entityId?: unknown }> },
|
|
301
|
+
{ moveInstance: moveInstance as { doMove: (...args: unknown[]) => unknown } }
|
|
302
|
+
);
|
|
303
|
+
const endIf = game.endIf as ((ctx: BgioArguments) => unknown) | undefined;
|
|
304
|
+
return endIf?.({ ...state as object, G: JSON.parse(serialize(simulatedG)) } as BgioArguments);
|
|
305
|
+
}
|