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.
Files changed (256) hide show
  1. package/.github/workflows/ci.yml +33 -0
  2. package/README.md +2 -2
  3. package/dist/board-game-engine.cjs +463 -349
  4. package/dist/board-game-engine.js +463 -349
  5. package/dist/board-game-engine.min.js +22 -22
  6. package/dist/board-game-engine.mjs +461 -348
  7. package/dist/client/client.d.ts +76 -0
  8. package/dist/client/client.d.ts.map +1 -0
  9. package/dist/game-factory/bank/bank-slot.d.ts +30 -0
  10. package/dist/game-factory/bank/bank-slot.d.ts.map +1 -0
  11. package/dist/game-factory/bank/bank.d.ts +34 -0
  12. package/dist/game-factory/bank/bank.d.ts.map +1 -0
  13. package/dist/game-factory/board.d.ts +4 -0
  14. package/dist/game-factory/board.d.ts.map +1 -0
  15. package/dist/game-factory/condition/condition-factory.d.ts +4 -0
  16. package/dist/game-factory/condition/condition-factory.d.ts.map +1 -0
  17. package/dist/game-factory/condition/condition.d.ts +13 -0
  18. package/dist/game-factory/condition/condition.d.ts.map +1 -0
  19. package/dist/game-factory/condition/contains-condition.d.ts +8 -0
  20. package/dist/game-factory/condition/contains-condition.d.ts.map +1 -0
  21. package/dist/game-factory/condition/contains-same-condition.d.ts +7 -0
  22. package/dist/game-factory/condition/contains-same-condition.d.ts.map +1 -0
  23. package/dist/game-factory/condition/evaluate-condition.d.ts +8 -0
  24. package/dist/game-factory/condition/evaluate-condition.d.ts.map +1 -0
  25. package/dist/game-factory/condition/every-condition.d.ts +12 -0
  26. package/dist/game-factory/condition/every-condition.d.ts.map +1 -0
  27. package/dist/game-factory/condition/has-line-condition.d.ts +8 -0
  28. package/dist/game-factory/condition/has-line-condition.d.ts.map +1 -0
  29. package/dist/game-factory/condition/in-line-condition.d.ts +8 -0
  30. package/dist/game-factory/condition/in-line-condition.d.ts.map +1 -0
  31. package/dist/game-factory/condition/is-condition.d.ts +8 -0
  32. package/dist/game-factory/condition/is-condition.d.ts.map +1 -0
  33. package/dist/game-factory/condition/is-full-condition.d.ts +7 -0
  34. package/dist/game-factory/condition/is-full-condition.d.ts.map +1 -0
  35. package/dist/game-factory/condition/no-possible-moves-condition.d.ts +7 -0
  36. package/dist/game-factory/condition/no-possible-moves-condition.d.ts.map +1 -0
  37. package/dist/game-factory/condition/not-condition.d.ts +7 -0
  38. package/dist/game-factory/condition/not-condition.d.ts.map +1 -0
  39. package/dist/game-factory/condition/or-condition.d.ts +7 -0
  40. package/dist/game-factory/condition/or-condition.d.ts.map +1 -0
  41. package/dist/game-factory/condition/position-condition.d.ts +7 -0
  42. package/dist/game-factory/condition/position-condition.d.ts.map +1 -0
  43. package/dist/game-factory/condition/some-condition.d.ts +8 -0
  44. package/dist/game-factory/condition/some-condition.d.ts.map +1 -0
  45. package/dist/game-factory/condition/would-condition.d.ts +8 -0
  46. package/dist/game-factory/condition/would-condition.d.ts.map +1 -0
  47. package/dist/game-factory/entity.d.ts +13 -0
  48. package/dist/game-factory/entity.d.ts.map +1 -0
  49. package/dist/game-factory/expand-game-rules.d.ts +3 -0
  50. package/dist/game-factory/expand-game-rules.d.ts.map +1 -0
  51. package/dist/game-factory/game-factory.d.ts +10 -0
  52. package/dist/game-factory/game-factory.d.ts.map +1 -0
  53. package/{src/game-factory/move/end-turn.js → dist/game-factory/move/end-turn.d.ts} +2 -4
  54. package/dist/game-factory/move/end-turn.d.ts.map +1 -0
  55. package/dist/game-factory/move/for-each.d.ts +5 -0
  56. package/dist/game-factory/move/for-each.d.ts.map +1 -0
  57. package/dist/game-factory/move/index.d.ts +6 -0
  58. package/dist/game-factory/move/index.d.ts.map +1 -0
  59. package/dist/game-factory/move/move-entity.d.ts +7 -0
  60. package/dist/game-factory/move/move-entity.d.ts.map +1 -0
  61. package/dist/game-factory/move/move-factory.d.ts +18 -0
  62. package/dist/game-factory/move/move-factory.d.ts.map +1 -0
  63. package/dist/game-factory/move/move.d.ts +54 -0
  64. package/dist/game-factory/move/move.d.ts.map +1 -0
  65. package/dist/game-factory/move/pass-turn.d.ts +5 -0
  66. package/dist/game-factory/move/pass-turn.d.ts.map +1 -0
  67. package/{src/game-factory/move/pass.js → dist/game-factory/move/pass.d.ts} +2 -4
  68. package/dist/game-factory/move/pass.d.ts.map +1 -0
  69. package/dist/game-factory/move/place-new.d.ts +5 -0
  70. package/dist/game-factory/move/place-new.d.ts.map +1 -0
  71. package/dist/game-factory/move/remove-entity.d.ts +5 -0
  72. package/dist/game-factory/move/remove-entity.d.ts.map +1 -0
  73. package/dist/game-factory/move/set-active-players.d.ts +5 -0
  74. package/dist/game-factory/move/set-active-players.d.ts.map +1 -0
  75. package/dist/game-factory/move/set-state.d.ts +5 -0
  76. package/dist/game-factory/move/set-state.d.ts.map +1 -0
  77. package/dist/game-factory/move/shuffle.d.ts +5 -0
  78. package/dist/game-factory/move/shuffle.d.ts.map +1 -0
  79. package/dist/game-factory/move/take-from.d.ts +11 -0
  80. package/dist/game-factory/move/take-from.d.ts.map +1 -0
  81. package/dist/game-factory/space/space.d.ts +10 -0
  82. package/dist/game-factory/space/space.d.ts.map +1 -0
  83. package/dist/game-factory/space-group/grid.d.ts +15 -0
  84. package/dist/game-factory/space-group/grid.d.ts.map +1 -0
  85. package/dist/game-factory/space-group/space-group.d.ts +20 -0
  86. package/dist/game-factory/space-group/space-group.d.ts.map +1 -0
  87. package/dist/index.d.ts +6 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/registry.d.ts +17 -0
  90. package/dist/registry.d.ts.map +1 -0
  91. package/dist/types/bagel-types.d.ts +339 -0
  92. package/dist/types/bagel-types.d.ts.map +1 -0
  93. package/dist/types/index.d.ts +3 -0
  94. package/dist/types/index.d.ts.map +1 -0
  95. package/dist/types/rule-with-conditions.d.ts +9 -0
  96. package/dist/types/rule-with-conditions.d.ts.map +1 -0
  97. package/dist/utils/any-valid-moves.d.ts +2 -0
  98. package/dist/utils/any-valid-moves.d.ts.map +1 -0
  99. package/dist/utils/bgio-resolve-types.d.ts +25 -0
  100. package/dist/utils/bgio-resolve-types.d.ts.map +1 -0
  101. package/dist/utils/check-conditions.d.ts +7 -0
  102. package/dist/utils/check-conditions.d.ts.map +1 -0
  103. package/dist/utils/create-payload.d.ts +5 -0
  104. package/dist/utils/create-payload.d.ts.map +1 -0
  105. package/dist/utils/deserialize-bgio-arguments.d.ts +3 -0
  106. package/dist/utils/deserialize-bgio-arguments.d.ts.map +1 -0
  107. package/dist/utils/do-moves.d.ts +8 -0
  108. package/dist/utils/do-moves.d.ts.map +1 -0
  109. package/dist/utils/entity-matches.d.ts +6 -0
  110. package/dist/utils/entity-matches.d.ts.map +1 -0
  111. package/dist/utils/find-met-condition.d.ts +6 -0
  112. package/dist/utils/find-met-condition.d.ts.map +1 -0
  113. package/dist/utils/get-current-moves.d.ts +24 -0
  114. package/dist/utils/get-current-moves.d.ts.map +1 -0
  115. package/dist/utils/get-scenario-results.d.ts +3 -0
  116. package/dist/utils/get-scenario-results.d.ts.map +1 -0
  117. package/dist/utils/get-steps.d.ts +13 -0
  118. package/dist/utils/get-steps.d.ts.map +1 -0
  119. package/dist/utils/get.d.ts +7 -0
  120. package/dist/utils/get.d.ts.map +1 -0
  121. package/dist/utils/grid-contains-sequence.d.ts +27 -0
  122. package/dist/utils/grid-contains-sequence.d.ts.map +1 -0
  123. package/dist/utils/json-transformer.d.ts +8 -0
  124. package/dist/utils/json-transformer.d.ts.map +1 -0
  125. package/dist/utils/prepare-payload.d.ts +2 -0
  126. package/dist/utils/prepare-payload.d.ts.map +1 -0
  127. package/dist/utils/resolve-entity.d.ts +3 -0
  128. package/dist/utils/resolve-entity.d.ts.map +1 -0
  129. package/dist/utils/resolve-expression.d.ts +6 -0
  130. package/dist/utils/resolve-expression.d.ts.map +1 -0
  131. package/dist/utils/resolve-properties.d.ts +4 -0
  132. package/dist/utils/resolve-properties.d.ts.map +1 -0
  133. package/dist/utils/simulate-move.d.ts +16 -0
  134. package/dist/utils/simulate-move.d.ts.map +1 -0
  135. package/e2e/fixtures/bge-checkers.html +1 -2
  136. package/e2e/fixtures/bge-minimal.html +1 -2
  137. package/e2e/fixtures/bge-ttt.html +1 -2
  138. package/examples/index.html +1 -1
  139. package/package.json +9 -3
  140. package/playwright-report/index.html +1 -1
  141. package/scripts/build.mjs +2 -2
  142. package/src/client/client.ts +305 -0
  143. package/src/game-factory/bank/bank-slot.ts +81 -0
  144. package/src/game-factory/bank/bank.ts +125 -0
  145. package/src/game-factory/{board.js → board.ts} +1 -1
  146. package/src/game-factory/condition/condition-factory.ts +59 -0
  147. package/src/game-factory/condition/condition.ts +50 -0
  148. package/src/game-factory/condition/{contains-condition.js → contains-condition.ts} +5 -4
  149. package/src/game-factory/condition/{contains-same-condition.js → contains-same-condition.ts} +8 -5
  150. package/src/game-factory/condition/{evaluate-condition.js → evaluate-condition.ts} +4 -3
  151. package/src/game-factory/condition/every-condition.ts +27 -0
  152. package/src/game-factory/condition/has-line-condition.ts +15 -0
  153. package/src/game-factory/condition/in-line-condition.ts +25 -0
  154. package/src/game-factory/condition/is-condition.ts +24 -0
  155. package/src/game-factory/condition/is-full-condition.ts +10 -0
  156. package/src/game-factory/condition/{no-possible-moves-condition.js → no-possible-moves-condition.ts} +3 -2
  157. package/src/game-factory/condition/{not-condition.js → not-condition.ts} +3 -2
  158. package/src/game-factory/condition/{or-condition.js → or-condition.ts} +3 -2
  159. package/src/game-factory/condition/position-condition.ts +13 -0
  160. package/src/game-factory/condition/{some-condition.js → some-condition.ts} +5 -3
  161. package/src/game-factory/condition/would-condition.ts +104 -0
  162. package/src/game-factory/entity.ts +37 -0
  163. package/src/game-factory/expand-game-rules.ts +263 -0
  164. package/src/game-factory/game-factory.ts +263 -0
  165. package/src/game-factory/move/end-turn.ts +7 -0
  166. package/src/game-factory/move/for-each.ts +20 -0
  167. package/src/game-factory/move/move-entity.ts +18 -0
  168. package/src/game-factory/move/move-factory.ts +107 -0
  169. package/src/game-factory/move/move.ts +147 -0
  170. package/src/game-factory/move/pass-turn.ts +15 -0
  171. package/src/game-factory/move/pass.ts +7 -0
  172. package/src/game-factory/move/place-new.ts +42 -0
  173. package/src/game-factory/move/remove-entity.ts +11 -0
  174. package/src/game-factory/move/set-active-players.ts +26 -0
  175. package/src/game-factory/move/set-state.ts +14 -0
  176. package/src/game-factory/move/shuffle.ts +9 -0
  177. package/src/game-factory/move/take-from.ts +12 -0
  178. package/src/game-factory/space/space.ts +36 -0
  179. package/src/game-factory/space-group/grid.ts +48 -0
  180. package/src/game-factory/space-group/space-group.ts +44 -0
  181. package/src/index.ts +5 -0
  182. package/src/types/bagel-types.ts +449 -0
  183. package/src/types/boardgame-io-core.d.ts +7 -0
  184. package/src/types/index.ts +70 -0
  185. package/src/types/rule-with-conditions.ts +9 -0
  186. package/src/utils/{any-valid-moves.js → any-valid-moves.ts} +54 -49
  187. package/src/utils/bgio-resolve-types.ts +27 -0
  188. package/src/utils/check-conditions.ts +28 -0
  189. package/src/utils/create-payload.ts +19 -0
  190. package/src/utils/deserialize-bgio-arguments.ts +10 -0
  191. package/src/utils/do-moves.ts +22 -0
  192. package/src/utils/entity-matches.ts +30 -0
  193. package/src/utils/expr-eval.d.ts +6 -0
  194. package/src/utils/find-met-condition.ts +23 -0
  195. package/src/utils/get-current-moves.ts +39 -0
  196. package/src/utils/get-scenario-results.ts +30 -0
  197. package/src/utils/get-steps.ts +38 -0
  198. package/src/utils/get.ts +28 -0
  199. package/src/utils/{grid-contains-sequence.js → grid-contains-sequence.ts} +71 -33
  200. package/src/utils/json-transformer.ts +17 -0
  201. package/src/utils/prepare-payload.ts +20 -0
  202. package/src/utils/resolve-entity.ts +15 -0
  203. package/src/utils/resolve-expression.ts +16 -0
  204. package/src/utils/resolve-properties.ts +172 -0
  205. package/src/utils/simulate-move.ts +32 -0
  206. package/src/wackson.d.ts +4 -0
  207. package/tsconfig.build.json +14 -0
  208. package/tsconfig.json +21 -0
  209. package/src/client/client.js +0 -224
  210. package/src/game-factory/bank/bank-slot.js +0 -69
  211. package/src/game-factory/bank/bank.js +0 -114
  212. package/src/game-factory/condition/condition-factory.js +0 -52
  213. package/src/game-factory/condition/condition.js +0 -39
  214. package/src/game-factory/condition/every-condition.js +0 -25
  215. package/src/game-factory/condition/has-line-condition.js +0 -14
  216. package/src/game-factory/condition/in-line-condition.js +0 -19
  217. package/src/game-factory/condition/is-condition.js +0 -23
  218. package/src/game-factory/condition/is-full-condition.js +0 -9
  219. package/src/game-factory/condition/position-condition.js +0 -12
  220. package/src/game-factory/condition/would-condition.js +0 -94
  221. package/src/game-factory/entity.js +0 -29
  222. package/src/game-factory/expand-game-rules.js +0 -271
  223. package/src/game-factory/game-factory.js +0 -239
  224. package/src/game-factory/move/for-each.js +0 -18
  225. package/src/game-factory/move/move-entity.js +0 -16
  226. package/src/game-factory/move/move-factory.js +0 -89
  227. package/src/game-factory/move/move.js +0 -131
  228. package/src/game-factory/move/pass-turn.js +0 -10
  229. package/src/game-factory/move/place-new.js +0 -33
  230. package/src/game-factory/move/remove-entity.js +0 -7
  231. package/src/game-factory/move/set-active-players.js +0 -23
  232. package/src/game-factory/move/set-state.js +0 -11
  233. package/src/game-factory/move/shuffle.js +0 -7
  234. package/src/game-factory/move/take-from.js +0 -7
  235. package/src/game-factory/space/space.js +0 -30
  236. package/src/game-factory/space-group/grid.js +0 -43
  237. package/src/game-factory/space-group/space-group.js +0 -29
  238. package/src/index.js +0 -2
  239. package/src/utils/check-conditions.js +0 -28
  240. package/src/utils/create-payload.js +0 -16
  241. package/src/utils/deserialize-bgio-arguments.js +0 -8
  242. package/src/utils/do-moves.js +0 -18
  243. package/src/utils/entity-matches.js +0 -20
  244. package/src/utils/find-met-condition.js +0 -22
  245. package/src/utils/get-current-moves.js +0 -12
  246. package/src/utils/get-scenario-results.js +0 -23
  247. package/src/utils/get-steps.js +0 -29
  248. package/src/utils/get.js +0 -25
  249. package/src/utils/json-transformer.js +0 -12
  250. package/src/utils/prepare-payload.js +0 -16
  251. package/src/utils/resolve-entity.js +0 -9
  252. package/src/utils/resolve-expression.js +0 -10
  253. package/src/utils/resolve-properties.js +0 -149
  254. package/src/utils/simulate-move.js +0 -25
  255. /package/src/game-factory/move/{index.js → index.ts} +0 -0
  256. /package/src/{registry.js → registry.ts} +0 -0
@@ -0,0 +1,81 @@
1
+ import resolveProperties from "../../utils/resolve-properties.js";
2
+ import type { BgioResolveState } from "../../utils/bgio-resolve-types.js";
3
+
4
+ class BankSlot {
5
+ bank: { createEntity: (rule: Record<string, unknown>) => unknown };
6
+ rule: Record<string, unknown> & { count?: number | string; name?: string };
7
+ pool: unknown[];
8
+ remaining: number;
9
+
10
+ constructor (rule: Record<string, unknown> & { count?: number | string; name?: string }, bank: BankSlot["bank"]) {
11
+ this.bank = bank;
12
+ this.rule = rule;
13
+ this.pool = [];
14
+ this.remaining = +((rule.count as number | string) || 1);
15
+ }
16
+
17
+ getOne (bgioArguments: BgioResolveState, options: { state?: unknown }, context: Record<string, unknown>) {
18
+ return this.getMultiple(bgioArguments, 1, options, context)[0];
19
+ }
20
+
21
+ getMultiple (
22
+ bgioArguments: BgioResolveState,
23
+ count: number = Infinity,
24
+ options: { state?: unknown } = {},
25
+ context: Record<string, unknown> = {}
26
+ ) {
27
+ const toReturn: unknown[] = [];
28
+
29
+ if (this.remaining === Infinity && count === Infinity) {
30
+ throw new Error(`Cannot get infinite pieces from slot with infinite remaining: ${this.rule.name}`);
31
+ }
32
+
33
+ if (count !== Infinity && count > this.remaining) {
34
+ throw new Error(`Requested ${count} pieces but only ${this.remaining} available in slot: ${this.rule.name}`);
35
+ }
36
+
37
+ const actualCount = count === Infinity ? this.remaining : count;
38
+
39
+ if (this.remaining !== Infinity) {
40
+ this.remaining -= actualCount;
41
+ }
42
+
43
+ const fromPool = Math.min(actualCount, this.pool.length);
44
+ toReturn.push(...this.pool.splice(0, fromPool));
45
+
46
+ const remainder = actualCount - fromPool;
47
+ if (remainder > 0) {
48
+ toReturn.push(
49
+ ...Array.from(new Array(remainder)).map(() =>
50
+ this.bank.createEntity(this.rule)
51
+ )
52
+ );
53
+ }
54
+
55
+ if (options.state) {
56
+ const newState = resolveProperties(bgioArguments, options.state, context);
57
+ toReturn.forEach((entity) => {
58
+ (entity as { state: Record<string, unknown> }).state = {
59
+ ...(entity as { state: Record<string, unknown> }).state,
60
+ ...newState as Record<string, unknown>,
61
+ };
62
+ });
63
+ }
64
+
65
+ return toReturn;
66
+ }
67
+
68
+ returnToBank (entity: { rule: { state?: unknown }; state?: unknown }) {
69
+ if (entity.rule.state) {
70
+ entity.state = entity.rule.state;
71
+ } else {
72
+ delete entity.state;
73
+ }
74
+ if (this.remaining !== undefined) {
75
+ this.remaining += 1;
76
+ }
77
+ this.pool.push(entity);
78
+ }
79
+ }
80
+
81
+ export default BankSlot;
@@ -0,0 +1,125 @@
1
+ import find from "lodash/find.js";
2
+ import filter from "lodash/filter.js";
3
+ import checkConditions from "../../utils/check-conditions.js";
4
+ import type { RuleWithConditions } from "../../types/rule-with-conditions.js";
5
+ import { registry } from "../../registry.js";
6
+ import BankSlot from "./bank-slot.js";
7
+ import type { BgioResolveState } from "../../utils/bgio-resolve-types.js";
8
+
9
+ class Bank {
10
+ currentEntityId: number;
11
+ tracker: Record<number, unknown>;
12
+ slots: InstanceType<typeof BankSlot>[];
13
+
14
+ constructor (entityRules: Record<string, unknown>[]) {
15
+ this.currentEntityId = 0;
16
+ this.tracker = {};
17
+ this.slots = entityRules.map((rule) => new BankSlot(rule, this));
18
+ }
19
+
20
+ createEntity (definition: Record<string, unknown> = {}, options?: Record<string, unknown>) {
21
+ const Ctor = registry[(definition.entityType || "Entity") as keyof typeof registry] as new (
22
+ a: unknown,
23
+ b: Record<string, unknown>,
24
+ c: number
25
+ ) => unknown;
26
+ const entity = new Ctor(
27
+ {
28
+ bank: this,
29
+ fromBank: true,
30
+ ...options,
31
+ },
32
+ definition,
33
+ this.currentEntityId++
34
+ );
35
+ this.track(entity as { entityId: number });
36
+ return entity;
37
+ }
38
+
39
+ track (entity: { entityId: number }) {
40
+ this.tracker[entity.entityId] = entity;
41
+ }
42
+
43
+ locate (entityId: unknown) {
44
+ return this.tracker[entityId as number];
45
+ }
46
+
47
+ findAll (bgioArguments: BgioResolveState, rule: RuleWithConditions, context: Record<string, unknown>) {
48
+ if (!rule.conditions) {
49
+ throw new Error(`Cannot find entity with no conditions. Rule: ${JSON.stringify(rule)}`);
50
+ }
51
+ return filter(
52
+ Object.values(this.tracker),
53
+ (entity) => checkConditions(
54
+ bgioArguments,
55
+ rule.conditions,
56
+ { target: entity },
57
+ context
58
+ ).conditionsAreMet
59
+ );
60
+ }
61
+
62
+ findOne (bgioArguments: BgioResolveState, rule: RuleWithConditions, context: Record<string, unknown>) {
63
+ return this.findAll(bgioArguments, rule, context)[0];
64
+ }
65
+
66
+ find (bgioArguments: BgioResolveState, rule: RuleWithConditions & { matchMultiple?: boolean }, context: Record<string, unknown>) {
67
+ return rule.matchMultiple
68
+ ? this.findAll(bgioArguments, rule, context)
69
+ : this.findOne(bgioArguments, rule, context);
70
+ }
71
+
72
+ findParent (entity: unknown) {
73
+ return find(this.tracker, (ent) =>
74
+ (ent as { entities?: unknown[] }).entities?.includes(entity)
75
+ || (ent as { spaces?: unknown[] }).spaces?.includes(entity)
76
+ );
77
+ }
78
+
79
+ getOne (bgioArguments: BgioResolveState, rule: RuleWithConditions & { state?: unknown }, context: Record<string, unknown>) {
80
+ const slot = this.getSlot(bgioArguments, rule, context);
81
+ if (!slot) {
82
+ console.error(`No matching slot for ${JSON.stringify(rule)}`);
83
+ }
84
+ return slot!.getOne(bgioArguments, { state: rule.state }, context);
85
+ }
86
+
87
+ getMultiple (bgioArguments: BgioResolveState, rule: RuleWithConditions & { state?: unknown }, count: number, context: Record<string, unknown>) {
88
+ const slots = this.getSlots(bgioArguments, rule, context);
89
+ if (!slots.length) {
90
+ console.error(`No matching slots for ${JSON.stringify(rule)}`);
91
+ }
92
+ return slots.reduce<unknown[]>((acc, slot) => [
93
+ ...acc,
94
+ ...slot.getMultiple(bgioArguments, count, { state: rule.state }),
95
+ ], []);
96
+ }
97
+
98
+ getSlot (bgioArguments: BgioResolveState, rule: RuleWithConditions, context: Record<string, unknown>) {
99
+ return this.slots.find((slot) => checkConditions(
100
+ bgioArguments,
101
+ rule.conditions,
102
+ { target: slot },
103
+ context
104
+ ).conditionsAreMet
105
+ );
106
+ }
107
+
108
+ getSlots (bgioArguments: BgioResolveState, rule: RuleWithConditions, context: Record<string, unknown>) {
109
+ return this.slots.filter((slot) => checkConditions(
110
+ bgioArguments,
111
+ rule.conditions,
112
+ { target: slot },
113
+ context
114
+ ).conditionsAreMet
115
+ );
116
+ }
117
+
118
+ returnToBank (bgioArguments: BgioResolveState, entity: { entityId: number; rule: Record<string, unknown> }) {
119
+ (this.findParent(entity) as { remove: (e: unknown) => void }).remove(entity);
120
+ this.getSlot(bgioArguments, entity.rule as RuleWithConditions, {})!.returnToBank(entity);
121
+ delete this.tracker[entity.entityId];
122
+ }
123
+ }
124
+
125
+ export default Bank;
@@ -1,3 +1,3 @@
1
- import Space from './space/space.js'
1
+ import Space from "./space/space.js";
2
2
 
3
3
  export default class Board extends Space {}
@@ -0,0 +1,59 @@
1
+ import type { Condition as ConditionRule } from "../../types/bagel-types.js";
2
+ import type ConditionBase from "./condition.js";
3
+ import Is from "./is-condition.js";
4
+ import Not from "./not-condition.js";
5
+ import Or from "./or-condition.js";
6
+ import Some from "./some-condition.js";
7
+ import Every from "./every-condition.js";
8
+ import ContainsCondition from "./contains-condition.js";
9
+ import ContainsSameCondition from "./contains-same-condition.js";
10
+ import InLine from "./in-line-condition.js";
11
+ import HasLine from "./has-line-condition.js";
12
+ import IsFull from "./is-full-condition.js";
13
+ import Would from "./would-condition.js";
14
+ import NoPossibleMoves from "./no-possible-moves-condition.js";
15
+ import Evaluate from "./evaluate-condition.js";
16
+ import Position from "./position-condition.js";
17
+ // import BingoCondition from "./bingo-condition.js";
18
+ // import RelativeMoveCondition from "./relative-move-condition.js";
19
+
20
+ export default function conditionFactory (rule: ConditionRule): ConditionBase | undefined {
21
+ if (typeof rule !== "object" || rule === null || !("conditionType" in rule)) {
22
+ return undefined;
23
+ }
24
+ const r = rule as { conditionType: string; [k: string]: unknown };
25
+ if (r.conditionType === "Is") {
26
+ return new Is(r);
27
+ } else if (r.conditionType === "Not") {
28
+ return new Not(r);
29
+ } else if (r.conditionType === "Or") {
30
+ return new Or(r);
31
+ } else if (r.conditionType === "Some") {
32
+ return new Some(r);
33
+ } else if (r.conditionType === "Contains") {
34
+ return new ContainsCondition(r);
35
+ } else if (r.conditionType === "ContainsSame") {
36
+ return new ContainsSameCondition(r);
37
+ } else if (r.conditionType === "Every") {
38
+ return new Every(r);
39
+ } else if (r.conditionType === "InLine") {
40
+ return new InLine(r);
41
+ } else if (r.conditionType === "HasLine") {
42
+ return new HasLine(r);
43
+ } else if (r.conditionType === "IsFull") {
44
+ return new IsFull(r);
45
+ } else if (r.conditionType === "Would") {
46
+ return new Would(r);
47
+ } else if (r.conditionType === "NoPossibleMoves") {
48
+ return new NoPossibleMoves(r);
49
+ } else if (r.conditionType === "Evaluate") {
50
+ return new Evaluate(r);
51
+ } else if (r.conditionType === "Position") {
52
+ return new Position(r);
53
+ // } else if (rule.conditionType === "bingo") {
54
+ // return new BingoCondition(rule);
55
+ // } else if (rule.conditionType === "relativeMove") {
56
+ // return new RelativeMoveCondition(rule);
57
+ }
58
+ return undefined;
59
+ }
@@ -0,0 +1,50 @@
1
+ import resolveProperties from "../../utils/resolve-properties.js";
2
+ import type { BgioResolveState } from "../../utils/bgio-resolve-types.js";
3
+
4
+ export default abstract class Condition {
5
+ rule: unknown;
6
+
7
+ constructor (rule: unknown) {
8
+ this.rule = rule;
9
+ }
10
+
11
+ check (bgioArguments: unknown, payload: Record<string, unknown>, context: Record<string, unknown>) {
12
+ const conditionPayload = { ...payload };
13
+ const newContext = { ...context };
14
+
15
+ if (conditionPayload.target) {
16
+ newContext.originalTarget = conditionPayload.target;
17
+ }
18
+
19
+ const rule = resolveProperties(
20
+ bgioArguments as BgioResolveState,
21
+ this.rule,
22
+ newContext
23
+ );
24
+
25
+ if ((rule as { target?: unknown }).target !== undefined) {
26
+ conditionPayload.target = (rule as { target: unknown }).target;
27
+ }
28
+
29
+ if ((this.rule as { target?: unknown }).target !== undefined && !conditionPayload.target) {
30
+ return { conditionIsMet: false };
31
+ }
32
+
33
+ return this.checkCondition(bgioArguments, rule, conditionPayload, newContext);
34
+ }
35
+
36
+ abstract checkCondition (
37
+ bgioArguments: unknown,
38
+ rule: unknown,
39
+ conditionPayload: Record<string, unknown>,
40
+ newContext: Record<string, unknown>
41
+ ): { conditionIsMet: boolean; [k: string]: unknown };
42
+
43
+ isMet (...args: unknown[]) {
44
+ return (this.check as (a: unknown, b: Record<string, unknown>, c: Record<string, unknown>) => { conditionIsMet: boolean })(
45
+ args[0],
46
+ (args[1] as Record<string, unknown>) ?? {},
47
+ (args[2] as Record<string, unknown>) ?? {}
48
+ ).conditionIsMet;
49
+ }
50
+ }
@@ -1,17 +1,18 @@
1
1
  import _matches from "lodash/matches.js";
2
+ import type { Condition as ConditionRule } from "../../types/bagel-types.js";
2
3
  import Condition from "../condition/condition.js";
3
4
  import checkConditions from "../../utils/check-conditions.js";
4
5
 
5
6
  export default class ContainsCondition extends Condition {
6
- checkCondition(bgioArguments, rule, payload, context) {
7
- const { target } = payload
7
+ checkCondition (bgioArguments: unknown, rule: unknown, payload: Record<string, unknown>, context: Record<string, unknown>) {
8
+ const target = payload.target as { entities?: unknown[]; spaces?: unknown[] } | undefined;
8
9
  if (!target) {
9
10
  return { matches: [], conditionIsMet: false }
10
11
  } else {
11
12
  const candidates = target.entities ?? target.spaces
12
- const matches = candidates?.filter(entity => checkConditions(
13
+ const matches = candidates?.filter((entity: unknown) => checkConditions(
13
14
  bgioArguments,
14
- rule,
15
+ (rule as { conditions?: ConditionRule[] }).conditions,
15
16
  { target: entity },
16
17
  context
17
18
  ).conditionsAreMet) ?? []
@@ -3,21 +3,24 @@ import conditionFactory from "./condition-factory.js";
3
3
  import Condition from "./condition.js";
4
4
 
5
5
  export default class ContainsSame extends Condition {
6
- checkCondition (bgioArguments, rule, { targets }) {
6
+ checkCondition (bgioArguments: unknown, rule: unknown, conditionPayload: Record<string, unknown>, _newContext: Record<string, unknown>) {
7
+ const { targets } = conditionPayload as { targets: { entities?: unknown[]; rule?: unknown }[] };
7
8
  if (targets.length === 1 && targets[0].entities?.length) {
8
9
  return { conditionIsMet: true }
9
10
  }
10
11
 
11
12
  const [ first, ...restEntities ] = targets;
12
- const conditionIsMet = first.entities.some(entity => {
13
+ const conditionIsMet = (first.entities ?? []).some((entity: unknown) => {
14
+ const e = entity as { rule?: unknown };
13
15
  const condition = conditionFactory({
14
16
  conditionType: "Contains",
15
17
  conditions: [{
16
18
  conditionType: 'Is',
17
- matcher: pick(entity.rule, rule.properties)
19
+ matcher: pick(e.rule as object, (rule as { properties: unknown }).properties as never)
18
20
  }]
19
- })
20
- return restEntities.every(ent => {
21
+ });
22
+ if (!condition) return false;
23
+ return restEntities.every((ent: unknown) => {
21
24
  return condition.isMet(bgioArguments, { target: ent })
22
25
  })
23
26
  })
@@ -1,16 +1,17 @@
1
1
  import _matches from "lodash/matches.js";
2
2
  import Condition from "../condition/condition.js";
3
3
  import resolveExpression from "../../utils/resolve-expression.js";
4
+ import type { BgioResolveState } from "../../utils/bgio-resolve-types.js";
4
5
 
5
6
  export default class Evaluate extends Condition {
6
- checkCondition(bgioArguments, rule, payload, context) {
7
+ checkCondition (bgioArguments: unknown, rule: unknown, payload: Record<string, unknown>, context: Record<string, unknown>) {
7
8
  const newContext = { ...context }
8
9
  if (payload?.target) {
9
10
  newContext.target = payload.target
10
11
  }
11
12
  const result = resolveExpression(
12
- bgioArguments,
13
- rule,
13
+ bgioArguments as BgioResolveState,
14
+ rule as { expression: string; arguments?: unknown },
14
15
  newContext
15
16
  )
16
17
  return { result, conditionIsMet: !!result }
@@ -0,0 +1,27 @@
1
+ import type { Condition as ConditionRule } from "../../types/bagel-types.js";
2
+ import Condition from "./condition.js";
3
+ import checkConditions from "../../utils/check-conditions.js";
4
+
5
+ export default class EveryCondition extends Condition {
6
+ checkCondition (bgioArguments: unknown, rule: unknown, conditionPayload: Record<string, unknown>, context: Record<string, unknown>) {
7
+ const targets = conditionPayload.target as unknown[];
8
+ const results = targets.map((target: unknown) => {
9
+ const loopContext = {
10
+ ...context,
11
+ loopTarget: target
12
+ }
13
+
14
+ return checkConditions(
15
+ bgioArguments,
16
+ (rule as { conditions?: ConditionRule[] }).conditions,
17
+ undefined,
18
+ loopContext
19
+ )
20
+ })
21
+
22
+ return {
23
+ conditionIsMet: results.every((r: { conditionsAreMet: boolean }) => r.conditionsAreMet),
24
+ results
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,15 @@
1
+ import Condition from "./condition.js";
2
+ import gridContainsSequence from "../../utils/grid-contains-sequence.js";
3
+ import type { GridLike, SequenceChunk } from "../../utils/grid-contains-sequence.js";
4
+
5
+ export default class HasLineCondition extends Condition {
6
+ checkCondition (bgioArguments: unknown, rule: unknown, payload: Record<string, unknown>, context: Record<string, unknown>) {
7
+ const { matches } = gridContainsSequence(
8
+ bgioArguments,
9
+ payload.target as GridLike,
10
+ (rule as { sequence: SequenceChunk[] }).sequence,
11
+ context
12
+ ) as { matches: unknown[] };
13
+ return { matches, conditionIsMet: !!matches.length };
14
+ }
15
+ }
@@ -0,0 +1,25 @@
1
+ import Condition from "./condition.js";
2
+ import gridContainsSequence from "../../utils/grid-contains-sequence.js";
3
+ import type { GridLike, SequenceChunk } from "../../utils/grid-contains-sequence.js";
4
+
5
+
6
+ export default class InLineCondition extends Condition {
7
+ checkCondition (bgioArguments: unknown, rule: unknown, payload: Record<string, unknown>, context: Record<string, unknown>) {
8
+ const { G } = bgioArguments as { G: { bank: { findParent: (t: unknown) => unknown } } };
9
+ const { target } = payload;
10
+ const parent = G.bank.findParent(payload.target);
11
+
12
+ const { matches: allMatches } = gridContainsSequence(
13
+ bgioArguments,
14
+ parent as GridLike,
15
+ (rule as { sequence: SequenceChunk[] }).sequence,
16
+ context
17
+ ) as { matches: unknown[][] };
18
+
19
+ const matches = allMatches.filter((sequence: unknown[]) =>
20
+ sequence.some((space: unknown) => space === target)
21
+ );
22
+
23
+ return { matches, conditionIsMet: !!matches.length };
24
+ }
25
+ }
@@ -0,0 +1,24 @@
1
+ import Condition from "./condition.js";
2
+ import entityMatches from '../../utils/entity-matches.js'
3
+ import type { BgioResolveState } from "../../utils/bgio-resolve-types.js";
4
+
5
+ export default class Is extends Condition {
6
+ checkCondition (bgioArguments: unknown, rule: unknown, { target }: Record<string, unknown>, context: Record<string, unknown>) {
7
+ if ((this.rule as { entity?: unknown }).entity && target !== (rule as { entity?: unknown }).entity) {
8
+ return {
9
+ target,
10
+ conditionIsMet: false,
11
+ }
12
+ }
13
+
14
+ return {
15
+ target,
16
+ conditionIsMet: entityMatches(
17
+ bgioArguments as BgioResolveState,
18
+ (rule as { matcher: Record<string, unknown> }).matcher,
19
+ target as { rule: Record<string, unknown>; state?: Record<string, unknown> },
20
+ context
21
+ )
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,10 @@
1
+ import Condition from "./condition.js";
2
+
3
+ export default class IsFull extends Condition {
4
+ checkCondition (_bgioArguments: unknown, _rule: unknown, payload: Record<string, unknown>, _context: Record<string, unknown>) {
5
+ const t = payload.target as { spaces: { entities?: unknown[] }[] };
6
+ return {
7
+ conditionIsMet: t.spaces.every((space: { entities?: unknown[] }) => space?.entities?.length)
8
+ };
9
+ }
10
+ }
@@ -1,13 +1,14 @@
1
1
  import Condition from "./condition.js";
2
2
  import areThereValidMoves from "../../utils/any-valid-moves.js";
3
3
  import getCurrentMoves from "../../utils/get-current-moves.js";
4
+ import type { GetCurrentMovesClient, GetCurrentMovesState } from "../../utils/get-current-moves.js";
4
5
 
5
6
  export default class NoPossibleMoves extends Condition {
6
- checkCondition(bgioArguments, _, __, context) {
7
+ checkCondition (bgioArguments: unknown, _unused: unknown, _payload: unknown, context: Record<string, unknown>) {
7
8
  return {
8
9
  conditionIsMet: !areThereValidMoves(
9
10
  bgioArguments,
10
- getCurrentMoves(bgioArguments, context),
11
+ getCurrentMoves(bgioArguments as GetCurrentMovesState, context as unknown as GetCurrentMovesClient),
11
12
  )
12
13
  }
13
14
  }
@@ -1,11 +1,12 @@
1
+ import type { Condition as ConditionRule } from "../../types/bagel-types.js";
1
2
  import Condition from "./condition.js";
2
3
  import checkConditions from "../../utils/check-conditions.js";
3
4
 
4
5
  export default class NotCondition extends Condition {
5
- checkCondition(bgioArguments, rule, payload, context) {
6
+ checkCondition (bgioArguments: unknown, rule: unknown, payload: Record<string, unknown>, context: Record<string, unknown>) {
6
7
  const result = checkConditions(
7
8
  bgioArguments,
8
- rule,
9
+ (rule as { conditions?: ConditionRule[] }).conditions,
9
10
  payload,
10
11
  context
11
12
  )
@@ -1,11 +1,12 @@
1
+ import type { Condition as ConditionRule } from "../../types/bagel-types.js";
1
2
  import Condition from "./condition.js";
2
3
  import findMetCondition from "../../utils/find-met-condition.js";
3
4
 
4
5
  export default class Or extends Condition {
5
- checkCondition(bgioArguments, rule, payload, context) {
6
+ checkCondition (bgioArguments: unknown, rule: unknown, payload: Record<string, unknown>, context: Record<string, unknown>) {
6
7
  const result = findMetCondition(
7
8
  bgioArguments,
8
- rule,
9
+ (rule as { conditions?: ConditionRule[] }).conditions,
9
10
  payload,
10
11
  context
11
12
  )
@@ -0,0 +1,13 @@
1
+ import Condition from "./condition.js";
2
+
3
+ export default class Position extends Condition {
4
+ checkCondition (bgioArguments: unknown, rule: unknown, conditionPayload: Record<string, unknown>, _newContext: Record<string, unknown>) {
5
+ const target = conditionPayload.target;
6
+ const parent = (bgioArguments as { G: { bank: { findParent: (t: unknown) => { entities: unknown[] } } } }).G.bank.findParent(target);
7
+ let conditionIsMet = false;
8
+ if ((rule as { position?: string }).position === "First") {
9
+ conditionIsMet = parent.entities.indexOf(target) === 0;
10
+ }
11
+ return { conditionIsMet };
12
+ }
13
+ }
@@ -1,16 +1,18 @@
1
+ import type { Condition as ConditionRule } from "../../types/bagel-types.js";
1
2
  import Condition from "./condition.js";
2
3
  import checkConditions from "../../utils/check-conditions.js";
3
4
 
4
5
  export default class SomeCondition extends Condition {
5
- checkCondition(bgioArguments, rule, { target: targets }, context) {
6
- const result = targets.find((target) => {
6
+ checkCondition (bgioArguments: unknown, rule: unknown, conditionPayload: Record<string, unknown>, context: Record<string, unknown>) {
7
+ const targets = conditionPayload.target as unknown[];
8
+ const result = targets.find((target: unknown) => {
7
9
  const loopContext = {
8
10
  ...context,
9
11
  loopTarget: target
10
12
  }
11
13
  return checkConditions(
12
14
  bgioArguments,
13
- rule,
15
+ (rule as { conditions?: ConditionRule[] }).conditions,
14
16
  undefined,
15
17
  loopContext
16
18
  ).conditionsAreMet