@mnbroatch/boardgame.io 0.0.1
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/LICENSE +21 -0
- package/README.md +102 -0
- package/ai/package.json +7 -0
- package/client/package.json +7 -0
- package/core/package.json +7 -0
- package/debug/package.json +7 -0
- package/dist/boardgameio.es.js +14238 -0
- package/dist/boardgameio.js +14277 -0
- package/dist/boardgameio.min.js +16 -0
- package/dist/cjs/Debug-9d141c06.js +9586 -0
- package/dist/cjs/ai-e0e8a768.js +377 -0
- package/dist/cjs/ai.js +20 -0
- package/dist/cjs/client-76dec77b.js +258 -0
- package/dist/cjs/client-a22d7500.js +524 -0
- package/dist/cjs/client.js +26 -0
- package/dist/cjs/core.js +52 -0
- package/dist/cjs/debug.js +18 -0
- package/dist/cjs/filter-player-view-bb02e2f6.js +89 -0
- package/dist/cjs/initialize-267fcd69.js +61 -0
- package/dist/cjs/internal.js +25 -0
- package/dist/cjs/master-2904879d.js +320 -0
- package/dist/cjs/master.js +18 -0
- package/dist/cjs/multiplayer.js +23 -0
- package/dist/cjs/plugin-random-7425844d.js +229 -0
- package/dist/cjs/plugins.js +59 -0
- package/dist/cjs/react-native.js +182 -0
- package/dist/cjs/react.js +727 -0
- package/dist/cjs/reducer-16eec232.js +1203 -0
- package/dist/cjs/server.js +4087 -0
- package/dist/cjs/socketio-7a0837eb.js +478 -0
- package/dist/cjs/testing.js +30 -0
- package/dist/cjs/transport-b1874dfa.js +37 -0
- package/dist/cjs/turn-order-b2ff8740.js +1136 -0
- package/dist/cjs/util-fcfd8fb8.js +140 -0
- package/dist/esm/Debug-0141fe2d.js +9577 -0
- package/dist/esm/ai-5c06e761.js +371 -0
- package/dist/esm/ai.js +8 -0
- package/dist/esm/client-2e653027.js +522 -0
- package/dist/esm/client-5f57c3f2.js +255 -0
- package/dist/esm/client.js +16 -0
- package/dist/esm/core.js +40 -0
- package/dist/esm/debug.js +10 -0
- package/dist/esm/filter-player-view-2c6cc96f.js +87 -0
- package/dist/esm/initialize-11d626ca.js +59 -0
- package/dist/esm/internal.js +10 -0
- package/dist/esm/master-fa8f2e43.js +318 -0
- package/dist/esm/master.js +10 -0
- package/dist/esm/multiplayer.js +14 -0
- package/dist/esm/plugin-random-087f861e.js +226 -0
- package/dist/esm/plugins.js +55 -0
- package/dist/esm/react-native.js +173 -0
- package/dist/esm/react.js +716 -0
- package/dist/esm/reducer-c46da7e5.js +1198 -0
- package/dist/esm/socketio-c22ffa65.js +455 -0
- package/dist/esm/testing.js +26 -0
- package/dist/esm/transport-ce07b771.js +35 -0
- package/dist/esm/turn-order-376d315e.js +1091 -0
- package/dist/esm/util-b6147cef.js +135 -0
- package/dist/types/packages/ai.d.ts +5 -0
- package/dist/types/packages/client.d.ts +3 -0
- package/dist/types/packages/core.d.ts +5 -0
- package/dist/types/packages/debug.d.ts +2 -0
- package/dist/types/packages/internal.d.ts +8 -0
- package/dist/types/packages/master.d.ts +2 -0
- package/dist/types/packages/multiplayer.d.ts +3 -0
- package/dist/types/packages/plugins.d.ts +3 -0
- package/dist/types/packages/react-native.d.ts +2 -0
- package/dist/types/packages/react.d.ts +3 -0
- package/dist/types/packages/server.d.ts +6 -0
- package/dist/types/packages/testing.d.ts +1 -0
- package/dist/types/src/ai/ai.d.ts +53 -0
- package/dist/types/src/ai/ai.test.d.ts +1 -0
- package/dist/types/src/ai/bot.d.ts +40 -0
- package/dist/types/src/ai/mcts-bot.d.ts +60 -0
- package/dist/types/src/ai/random-bot.d.ts +27 -0
- package/dist/types/src/client/client.d.ts +104 -0
- package/dist/types/src/client/client.test.d.ts +1 -0
- package/dist/types/src/client/debug/tests/debug.test.d.ts +1 -0
- package/dist/types/src/client/manager.d.ts +61 -0
- package/dist/types/src/client/react.d.ts +75 -0
- package/dist/types/src/client/react.ssr.test.d.ts +4 -0
- package/dist/types/src/client/react.test.d.ts +1 -0
- package/dist/types/src/client/transport/dummy.d.ts +18 -0
- package/dist/types/src/client/transport/local.d.ts +59 -0
- package/dist/types/src/client/transport/local.test.d.ts +1 -0
- package/dist/types/src/client/transport/socketio.d.ts +45 -0
- package/dist/types/src/client/transport/socketio.test.d.ts +1 -0
- package/dist/types/src/client/transport/transport.d.ts +50 -0
- package/dist/types/src/client/transport/transport.test.d.ts +1 -0
- package/dist/types/src/core/action-creators.d.ts +144 -0
- package/dist/types/src/core/action-types.d.ts +10 -0
- package/dist/types/src/core/backwards-compatibility.d.ts +12 -0
- package/dist/types/src/core/constants.d.ts +6 -0
- package/dist/types/src/core/errors.d.ts +15 -0
- package/dist/types/src/core/flow.d.ts +28 -0
- package/dist/types/src/core/flow.test.d.ts +1 -0
- package/dist/types/src/core/game-methods.d.ts +9 -0
- package/dist/types/src/core/game.d.ts +26 -0
- package/dist/types/src/core/game.test.d.ts +1 -0
- package/dist/types/src/core/initialize.d.ts +9 -0
- package/dist/types/src/core/logger.d.ts +2 -0
- package/dist/types/src/core/player-view.d.ts +7 -0
- package/dist/types/src/core/player-view.test.d.ts +1 -0
- package/dist/types/src/core/reducer.d.ts +155 -0
- package/dist/types/src/core/reducer.test.d.ts +1 -0
- package/dist/types/src/core/turn-order.d.ts +179 -0
- package/dist/types/src/core/turn-order.test.d.ts +8 -0
- package/dist/types/src/lobby/client.d.ts +194 -0
- package/dist/types/src/lobby/client.test.d.ts +1 -0
- package/dist/types/src/lobby/connection.d.ts +44 -0
- package/dist/types/src/lobby/connection.test.d.ts +1 -0
- package/dist/types/src/lobby/create-match-form.d.ts +26 -0
- package/dist/types/src/lobby/login-form.d.ts +23 -0
- package/dist/types/src/lobby/match-instance.d.ts +31 -0
- package/dist/types/src/lobby/react.d.ts +113 -0
- package/dist/types/src/lobby/react.ssr.test.d.ts +4 -0
- package/dist/types/src/lobby/react.test.d.ts +1 -0
- package/dist/types/src/master/filter-player-view.d.ts +96 -0
- package/dist/types/src/master/filter-player-view.test.d.ts +1 -0
- package/dist/types/src/master/master.d.ts +94 -0
- package/dist/types/src/master/master.test.d.ts +1 -0
- package/dist/types/src/plugins/events/events.d.ts +54 -0
- package/dist/types/src/plugins/events/events.test.d.ts +1 -0
- package/dist/types/src/plugins/main.d.ts +75 -0
- package/dist/types/src/plugins/main.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-events.d.ts +5 -0
- package/dist/types/src/plugins/plugin-immer.d.ts +7 -0
- package/dist/types/src/plugins/plugin-immer.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-log.d.ts +14 -0
- package/dist/types/src/plugins/plugin-log.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-player.d.ts +29 -0
- package/dist/types/src/plugins/plugin-player.test.d.ts +1 -0
- package/dist/types/src/plugins/plugin-random.d.ts +4 -0
- package/dist/types/src/plugins/plugin-serializable.d.ts +7 -0
- package/dist/types/src/plugins/plugin-serializable.test.d.ts +1 -0
- package/dist/types/src/plugins/random/random.alea.d.ts +19 -0
- package/dist/types/src/plugins/random/random.d.ts +54 -0
- package/dist/types/src/plugins/random/random.test.d.ts +1 -0
- package/dist/types/src/server/api.d.ts +13 -0
- package/dist/types/src/server/api.test.d.ts +1 -0
- package/dist/types/src/server/auth.d.ts +38 -0
- package/dist/types/src/server/auth.test.d.ts +1 -0
- package/dist/types/src/server/cors.d.ts +4 -0
- package/dist/types/src/server/cors.test.d.ts +1 -0
- package/dist/types/src/server/db/base.d.ts +192 -0
- package/dist/types/src/server/db/flatfile.d.ts +44 -0
- package/dist/types/src/server/db/flatfile.test.d.ts +1 -0
- package/dist/types/src/server/db/index.d.ts +4 -0
- package/dist/types/src/server/db/index.test.d.ts +1 -0
- package/dist/types/src/server/db/inmemory.d.ts +43 -0
- package/dist/types/src/server/db/inmemory.test.d.ts +1 -0
- package/dist/types/src/server/db/localstorage.d.ts +7 -0
- package/dist/types/src/server/db/localstorage.test.d.ts +1 -0
- package/dist/types/src/server/index.d.ts +68 -0
- package/dist/types/src/server/index.test.d.ts +1 -0
- package/dist/types/src/server/transport/pubsub/generic-pub-sub.d.ts +6 -0
- package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.d.ts +7 -0
- package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.test.d.ts +1 -0
- package/dist/types/src/server/transport/socketio-simultaneous.test.d.ts +1 -0
- package/dist/types/src/server/transport/socketio.d.ts +65 -0
- package/dist/types/src/server/transport/socketio.test.d.ts +1 -0
- package/dist/types/src/server/util.d.ts +35 -0
- package/dist/types/src/testing/mock-random.d.ts +15 -0
- package/dist/types/src/testing/mock-random.test.d.ts +1 -0
- package/dist/types/src/types.d.ts +387 -0
- package/internal/package.json +7 -0
- package/master/package.json +7 -0
- package/multiplayer/package.json +7 -0
- package/package.json +211 -0
- package/plugins/package.json +7 -0
- package/react/package.json +7 -0
- package/react-native/package.json +7 -0
- package/server/package.json +6 -0
- package/src/ai/ai.test.ts +433 -0
- package/src/ai/ai.ts +84 -0
- package/src/ai/bot.ts +122 -0
- package/src/ai/mcts-bot.ts +331 -0
- package/src/ai/random-bot.ts +20 -0
- package/src/client/client.test.ts +993 -0
- package/src/client/client.ts +588 -0
- package/src/client/debug/Debug.svelte +239 -0
- package/src/client/debug/Menu.svelte +65 -0
- package/src/client/debug/ai/AI.svelte +215 -0
- package/src/client/debug/ai/Options.svelte +48 -0
- package/src/client/debug/info/Info.svelte +22 -0
- package/src/client/debug/info/Item.svelte +24 -0
- package/src/client/debug/log/Log.svelte +157 -0
- package/src/client/debug/log/LogEvent.svelte +149 -0
- package/src/client/debug/log/LogMetadata.svelte +7 -0
- package/src/client/debug/log/PhaseMarker.svelte +27 -0
- package/src/client/debug/log/TurnMarker.svelte +23 -0
- package/src/client/debug/main/ClientSwitcher.svelte +59 -0
- package/src/client/debug/main/Controls.svelte +58 -0
- package/src/client/debug/main/Hotkey.svelte +84 -0
- package/src/client/debug/main/InteractiveFunction.svelte +85 -0
- package/src/client/debug/main/Main.svelte +121 -0
- package/src/client/debug/main/Move.svelte +68 -0
- package/src/client/debug/main/PlayerInfo.svelte +70 -0
- package/src/client/debug/mcts/Action.svelte +22 -0
- package/src/client/debug/mcts/MCTS.svelte +78 -0
- package/src/client/debug/mcts/Table.svelte +98 -0
- package/src/client/debug/tests/JSONTree.mock.svelte +3 -0
- package/src/client/debug/tests/debug.test.ts +183 -0
- package/src/client/debug/utils/shortcuts.js +50 -0
- package/src/client/debug/utils/shortcuts.test.js +49 -0
- package/src/client/manager.ts +177 -0
- package/src/client/react-native.js +136 -0
- package/src/client/react-native.test.js +229 -0
- package/src/client/react.ssr.test.tsx +24 -0
- package/src/client/react.test.tsx +213 -0
- package/src/client/react.tsx +192 -0
- package/src/client/transport/dummy.ts +19 -0
- package/src/client/transport/local.test.ts +353 -0
- package/src/client/transport/local.ts +230 -0
- package/src/client/transport/socketio.test.ts +328 -0
- package/src/client/transport/socketio.ts +210 -0
- package/src/client/transport/transport.test.ts +27 -0
- package/src/client/transport/transport.ts +95 -0
- package/src/core/action-creators.ts +159 -0
- package/src/core/action-types.ts +18 -0
- package/src/core/backwards-compatibility.ts +23 -0
- package/src/core/constants.ts +6 -0
- package/src/core/errors.ts +35 -0
- package/src/core/flow.test.ts +2433 -0
- package/src/core/flow.ts +897 -0
- package/src/core/game-methods.ts +9 -0
- package/src/core/game.test.ts +286 -0
- package/src/core/game.ts +114 -0
- package/src/core/initialize.ts +77 -0
- package/src/core/logger.test.js +90 -0
- package/src/core/logger.ts +18 -0
- package/src/core/player-view.test.ts +50 -0
- package/src/core/player-view.ts +39 -0
- package/src/core/reducer.test.ts +991 -0
- package/src/core/reducer.ts +532 -0
- package/src/core/turn-order.test.ts +1123 -0
- package/src/core/turn-order.ts +473 -0
- package/src/lobby/client.test.ts +385 -0
- package/src/lobby/client.ts +358 -0
- package/src/lobby/connection.test.ts +207 -0
- package/src/lobby/connection.ts +162 -0
- package/src/lobby/create-match-form.tsx +122 -0
- package/src/lobby/login-form.tsx +75 -0
- package/src/lobby/match-instance.tsx +135 -0
- package/src/lobby/react.ssr.test.tsx +22 -0
- package/src/lobby/react.test.tsx +594 -0
- package/src/lobby/react.tsx +402 -0
- package/src/master/filter-player-view.test.ts +381 -0
- package/src/master/filter-player-view.ts +102 -0
- package/src/master/master.test.ts +1068 -0
- package/src/master/master.ts +492 -0
- package/src/plugins/events/events.test.ts +108 -0
- package/src/plugins/events/events.ts +209 -0
- package/src/plugins/main.test.ts +411 -0
- package/src/plugins/main.ts +314 -0
- package/src/plugins/plugin-events.ts +40 -0
- package/src/plugins/plugin-immer.test.ts +86 -0
- package/src/plugins/plugin-immer.ts +37 -0
- package/src/plugins/plugin-log.test.ts +37 -0
- package/src/plugins/plugin-log.ts +40 -0
- package/src/plugins/plugin-player.test.ts +172 -0
- package/src/plugins/plugin-player.ts +100 -0
- package/src/plugins/plugin-random.ts +40 -0
- package/src/plugins/plugin-serializable.test.ts +40 -0
- package/src/plugins/plugin-serializable.ts +55 -0
- package/src/plugins/random/random.alea.ts +109 -0
- package/src/plugins/random/random.test.ts +167 -0
- package/src/plugins/random/random.ts +198 -0
- package/src/server/api.test.ts +1699 -0
- package/src/server/api.ts +527 -0
- package/src/server/auth.test.ts +275 -0
- package/src/server/auth.ts +89 -0
- package/src/server/cors.test.ts +121 -0
- package/src/server/cors.ts +7 -0
- package/src/server/db/base.ts +296 -0
- package/src/server/db/flatfile.test.ts +221 -0
- package/src/server/db/flatfile.ts +228 -0
- package/src/server/db/index.test.ts +8 -0
- package/src/server/db/index.ts +12 -0
- package/src/server/db/inmemory.test.ts +143 -0
- package/src/server/db/inmemory.ts +143 -0
- package/src/server/db/localstorage.test.ts +73 -0
- package/src/server/db/localstorage.ts +44 -0
- package/src/server/index.test.ts +265 -0
- package/src/server/index.ts +175 -0
- package/src/server/transport/pubsub/generic-pub-sub.ts +11 -0
- package/src/server/transport/pubsub/in-memory-pub-sub.test.ts +47 -0
- package/src/server/transport/pubsub/in-memory-pub-sub.ts +28 -0
- package/src/server/transport/socketio-simultaneous.test.ts +603 -0
- package/src/server/transport/socketio.test.ts +303 -0
- package/src/server/transport/socketio.ts +279 -0
- package/src/server/util.ts +85 -0
- package/src/testing/mock-random.test.ts +45 -0
- package/src/testing/mock-random.ts +27 -0
- package/src/types.ts +511 -0
- package/testing/package.json +7 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017 The boardgame.io Authors
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed by a MIT-style
|
|
5
|
+
* license that can be found in the LICENSE file or at
|
|
6
|
+
* https://opensource.org/licenses/MIT.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as logging from './logger';
|
|
10
|
+
import * as plugin from '../plugins/main';
|
|
11
|
+
import type {
|
|
12
|
+
Ctx,
|
|
13
|
+
StageArg,
|
|
14
|
+
ActivePlayersArg,
|
|
15
|
+
PlayerID,
|
|
16
|
+
State,
|
|
17
|
+
TurnConfig,
|
|
18
|
+
FnContext,
|
|
19
|
+
} from '../types';
|
|
20
|
+
import { supportDeprecatedMoveLimit } from './backwards-compatibility';
|
|
21
|
+
|
|
22
|
+
export function SetActivePlayers(ctx: Ctx, arg: ActivePlayersArg): Ctx {
|
|
23
|
+
let activePlayers: typeof ctx.activePlayers = {};
|
|
24
|
+
let _prevActivePlayers: typeof ctx._prevActivePlayers = [];
|
|
25
|
+
let _nextActivePlayers: ActivePlayersArg | null = null;
|
|
26
|
+
let _activePlayersMinMoves = {};
|
|
27
|
+
let _activePlayersMaxMoves = {};
|
|
28
|
+
|
|
29
|
+
if (Array.isArray(arg)) {
|
|
30
|
+
// support a simple array of player IDs as active players
|
|
31
|
+
const value = {};
|
|
32
|
+
arg.forEach((v) => (value[v] = Stage.NULL));
|
|
33
|
+
activePlayers = value;
|
|
34
|
+
} else {
|
|
35
|
+
// process active players argument object
|
|
36
|
+
|
|
37
|
+
// stages previously did not enforce minMoves, this behaviour is kept intentionally
|
|
38
|
+
supportDeprecatedMoveLimit(arg);
|
|
39
|
+
|
|
40
|
+
if (arg.next) {
|
|
41
|
+
_nextActivePlayers = arg.next;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (arg.revert) {
|
|
45
|
+
_prevActivePlayers = [
|
|
46
|
+
...ctx._prevActivePlayers,
|
|
47
|
+
{
|
|
48
|
+
activePlayers: ctx.activePlayers,
|
|
49
|
+
_activePlayersMinMoves: ctx._activePlayersMinMoves,
|
|
50
|
+
_activePlayersMaxMoves: ctx._activePlayersMaxMoves,
|
|
51
|
+
_activePlayersNumMoves: ctx._activePlayersNumMoves,
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (arg.currentPlayer !== undefined) {
|
|
57
|
+
ApplyActivePlayerArgument(
|
|
58
|
+
activePlayers,
|
|
59
|
+
_activePlayersMinMoves,
|
|
60
|
+
_activePlayersMaxMoves,
|
|
61
|
+
ctx.currentPlayer,
|
|
62
|
+
arg.currentPlayer
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (arg.others !== undefined) {
|
|
67
|
+
for (let i = 0; i < ctx.playOrder.length; i++) {
|
|
68
|
+
const id = ctx.playOrder[i];
|
|
69
|
+
if (id !== ctx.currentPlayer) {
|
|
70
|
+
ApplyActivePlayerArgument(
|
|
71
|
+
activePlayers,
|
|
72
|
+
_activePlayersMinMoves,
|
|
73
|
+
_activePlayersMaxMoves,
|
|
74
|
+
id,
|
|
75
|
+
arg.others
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (arg.all !== undefined) {
|
|
82
|
+
for (let i = 0; i < ctx.playOrder.length; i++) {
|
|
83
|
+
const id = ctx.playOrder[i];
|
|
84
|
+
ApplyActivePlayerArgument(
|
|
85
|
+
activePlayers,
|
|
86
|
+
_activePlayersMinMoves,
|
|
87
|
+
_activePlayersMaxMoves,
|
|
88
|
+
id,
|
|
89
|
+
arg.all
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (arg.value) {
|
|
95
|
+
for (const id in arg.value) {
|
|
96
|
+
ApplyActivePlayerArgument(
|
|
97
|
+
activePlayers,
|
|
98
|
+
_activePlayersMinMoves,
|
|
99
|
+
_activePlayersMaxMoves,
|
|
100
|
+
id,
|
|
101
|
+
arg.value[id]
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (arg.minMoves) {
|
|
107
|
+
for (const id in activePlayers) {
|
|
108
|
+
if (_activePlayersMinMoves[id] === undefined) {
|
|
109
|
+
_activePlayersMinMoves[id] = arg.minMoves;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (arg.maxMoves) {
|
|
115
|
+
for (const id in activePlayers) {
|
|
116
|
+
if (_activePlayersMaxMoves[id] === undefined) {
|
|
117
|
+
_activePlayersMaxMoves[id] = arg.maxMoves;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (Object.keys(activePlayers).length === 0) {
|
|
124
|
+
activePlayers = null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (Object.keys(_activePlayersMinMoves).length === 0) {
|
|
128
|
+
_activePlayersMinMoves = null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (Object.keys(_activePlayersMaxMoves).length === 0) {
|
|
132
|
+
_activePlayersMaxMoves = null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const _activePlayersNumMoves = {};
|
|
136
|
+
for (const id in activePlayers) {
|
|
137
|
+
_activePlayersNumMoves[id] = 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
...ctx,
|
|
142
|
+
activePlayers,
|
|
143
|
+
_activePlayersMinMoves,
|
|
144
|
+
_activePlayersMaxMoves,
|
|
145
|
+
_activePlayersNumMoves,
|
|
146
|
+
_prevActivePlayers,
|
|
147
|
+
_nextActivePlayers,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Update activePlayers, setting it to previous, next or null values
|
|
153
|
+
* when it becomes empty.
|
|
154
|
+
* @param ctx
|
|
155
|
+
*/
|
|
156
|
+
export function UpdateActivePlayersOnceEmpty(ctx: Ctx) {
|
|
157
|
+
let {
|
|
158
|
+
activePlayers,
|
|
159
|
+
_activePlayersMinMoves,
|
|
160
|
+
_activePlayersMaxMoves,
|
|
161
|
+
_activePlayersNumMoves,
|
|
162
|
+
_prevActivePlayers,
|
|
163
|
+
_nextActivePlayers,
|
|
164
|
+
} = ctx;
|
|
165
|
+
|
|
166
|
+
if (activePlayers && Object.keys(activePlayers).length === 0) {
|
|
167
|
+
if (_nextActivePlayers) {
|
|
168
|
+
ctx = SetActivePlayers(ctx, _nextActivePlayers);
|
|
169
|
+
({
|
|
170
|
+
activePlayers,
|
|
171
|
+
_activePlayersMinMoves,
|
|
172
|
+
_activePlayersMaxMoves,
|
|
173
|
+
_activePlayersNumMoves,
|
|
174
|
+
_prevActivePlayers,
|
|
175
|
+
} = ctx);
|
|
176
|
+
} else if (_prevActivePlayers.length > 0) {
|
|
177
|
+
const lastIndex = _prevActivePlayers.length - 1;
|
|
178
|
+
({
|
|
179
|
+
activePlayers,
|
|
180
|
+
_activePlayersMinMoves,
|
|
181
|
+
_activePlayersMaxMoves,
|
|
182
|
+
_activePlayersNumMoves,
|
|
183
|
+
} = _prevActivePlayers[lastIndex]);
|
|
184
|
+
_prevActivePlayers = _prevActivePlayers.slice(0, lastIndex);
|
|
185
|
+
} else {
|
|
186
|
+
activePlayers = null;
|
|
187
|
+
_activePlayersMinMoves = null;
|
|
188
|
+
_activePlayersMaxMoves = null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
...ctx,
|
|
194
|
+
activePlayers,
|
|
195
|
+
_activePlayersMinMoves,
|
|
196
|
+
_activePlayersMaxMoves,
|
|
197
|
+
_activePlayersNumMoves,
|
|
198
|
+
_prevActivePlayers,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Apply an active player argument to the given player ID
|
|
204
|
+
* @param {Object} activePlayers
|
|
205
|
+
* @param {Object} _activePlayersMinMoves
|
|
206
|
+
* @param {Object} _activePlayersMaxMoves
|
|
207
|
+
* @param {String} playerID The player to apply the parameter to
|
|
208
|
+
* @param {(String|Object)} arg An active player argument
|
|
209
|
+
*/
|
|
210
|
+
function ApplyActivePlayerArgument(
|
|
211
|
+
activePlayers: Ctx['activePlayers'],
|
|
212
|
+
_activePlayersMinMoves: Ctx['_activePlayersMinMoves'],
|
|
213
|
+
_activePlayersMaxMoves: Ctx['_activePlayersMaxMoves'],
|
|
214
|
+
playerID: PlayerID,
|
|
215
|
+
arg: StageArg
|
|
216
|
+
) {
|
|
217
|
+
if (typeof arg !== 'object' || arg === Stage.NULL) {
|
|
218
|
+
arg = { stage: arg as string | null };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (arg.stage !== undefined) {
|
|
222
|
+
// stages previously did not enforce minMoves, this behaviour is kept intentionally
|
|
223
|
+
supportDeprecatedMoveLimit(arg);
|
|
224
|
+
|
|
225
|
+
activePlayers[playerID] = arg.stage;
|
|
226
|
+
if (arg.minMoves) _activePlayersMinMoves[playerID] = arg.minMoves;
|
|
227
|
+
if (arg.maxMoves) _activePlayersMaxMoves[playerID] = arg.maxMoves;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Converts a playOrderPos index into its value in playOrder.
|
|
233
|
+
* @param {Array} playOrder - An array of player ID's.
|
|
234
|
+
* @param {number} playOrderPos - An index into the above.
|
|
235
|
+
*/
|
|
236
|
+
function getCurrentPlayer(
|
|
237
|
+
playOrder: Ctx['playOrder'],
|
|
238
|
+
playOrderPos: Ctx['playOrderPos']
|
|
239
|
+
) {
|
|
240
|
+
// convert to string in case playOrder is set to number[]
|
|
241
|
+
return playOrder[playOrderPos] + '';
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Called at the start of a turn to initialize turn order state.
|
|
246
|
+
*
|
|
247
|
+
* TODO: This is called inside StartTurn, which is called from
|
|
248
|
+
* both UpdateTurn and StartPhase (so it's called at the beginning
|
|
249
|
+
* of a new phase as well as between turns). We should probably
|
|
250
|
+
* split it into two.
|
|
251
|
+
*/
|
|
252
|
+
export function InitTurnOrderState(state: State, turn: TurnConfig) {
|
|
253
|
+
let { G, ctx } = state;
|
|
254
|
+
const { numPlayers } = ctx;
|
|
255
|
+
const pluginAPIs = plugin.GetAPIs(state);
|
|
256
|
+
const context = { ...pluginAPIs, G, ctx };
|
|
257
|
+
const order = turn.order;
|
|
258
|
+
|
|
259
|
+
let playOrder = [...Array.from({ length: numPlayers })].map((_, i) => i + '');
|
|
260
|
+
if (order.playOrder !== undefined) {
|
|
261
|
+
playOrder = order.playOrder(context);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const playOrderPos = order.first(context);
|
|
265
|
+
const posType = typeof playOrderPos;
|
|
266
|
+
if (posType !== 'number') {
|
|
267
|
+
logging.error(
|
|
268
|
+
`invalid value returned by turn.order.first — expected number got ${posType} “${playOrderPos}”.`
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
const currentPlayer = getCurrentPlayer(playOrder, playOrderPos);
|
|
272
|
+
|
|
273
|
+
ctx = { ...ctx, currentPlayer, playOrderPos, playOrder };
|
|
274
|
+
ctx = SetActivePlayers(ctx, turn.activePlayers || {});
|
|
275
|
+
|
|
276
|
+
return ctx;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Called at the end of each turn to update the turn order state.
|
|
281
|
+
* @param {object} G - The game object G.
|
|
282
|
+
* @param {object} ctx - The game object ctx.
|
|
283
|
+
* @param {object} turn - A turn object for this phase.
|
|
284
|
+
* @param {string} endTurnArg - An optional argument to endTurn that
|
|
285
|
+
may specify the next player.
|
|
286
|
+
*/
|
|
287
|
+
export function UpdateTurnOrderState(
|
|
288
|
+
state: State,
|
|
289
|
+
currentPlayer: PlayerID,
|
|
290
|
+
turn: TurnConfig,
|
|
291
|
+
endTurnArg?: true | { remove?: any; next?: string }
|
|
292
|
+
) {
|
|
293
|
+
const order = turn.order;
|
|
294
|
+
|
|
295
|
+
let { G, ctx } = state;
|
|
296
|
+
let playOrderPos = ctx.playOrderPos;
|
|
297
|
+
let endPhase = false;
|
|
298
|
+
|
|
299
|
+
if (endTurnArg && endTurnArg !== true) {
|
|
300
|
+
if (typeof endTurnArg !== 'object') {
|
|
301
|
+
logging.error(`invalid argument to endTurn: ${endTurnArg}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
Object.keys(endTurnArg).forEach((arg) => {
|
|
305
|
+
switch (arg) {
|
|
306
|
+
case 'remove':
|
|
307
|
+
currentPlayer = getCurrentPlayer(ctx.playOrder, playOrderPos);
|
|
308
|
+
break;
|
|
309
|
+
case 'next':
|
|
310
|
+
playOrderPos = ctx.playOrder.indexOf(endTurnArg.next);
|
|
311
|
+
currentPlayer = endTurnArg.next;
|
|
312
|
+
break;
|
|
313
|
+
default:
|
|
314
|
+
logging.error(`invalid argument to endTurn: ${arg}`);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
} else {
|
|
318
|
+
const pluginAPIs = plugin.GetAPIs(state);
|
|
319
|
+
const context = { ...pluginAPIs, G, ctx };
|
|
320
|
+
const t = order.next(context);
|
|
321
|
+
const type = typeof t;
|
|
322
|
+
if (t !== undefined && type !== 'number') {
|
|
323
|
+
logging.error(
|
|
324
|
+
`invalid value returned by turn.order.next — expected number or undefined got ${type} “${t}”.`
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (t === undefined) {
|
|
329
|
+
endPhase = true;
|
|
330
|
+
} else {
|
|
331
|
+
playOrderPos = t;
|
|
332
|
+
currentPlayer = getCurrentPlayer(ctx.playOrder, playOrderPos);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
ctx = {
|
|
337
|
+
...ctx,
|
|
338
|
+
playOrderPos,
|
|
339
|
+
currentPlayer,
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
return { endPhase, ctx };
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Set of different turn orders possible in a phase.
|
|
347
|
+
* These are meant to be passed to the `turn` setting
|
|
348
|
+
* in the flow objects.
|
|
349
|
+
*
|
|
350
|
+
* Each object defines the first player when the phase / game
|
|
351
|
+
* begins, and also a function `next` to determine who the
|
|
352
|
+
* next player is when the turn ends.
|
|
353
|
+
*
|
|
354
|
+
* The phase ends if next() returns undefined.
|
|
355
|
+
*/
|
|
356
|
+
export const TurnOrder = {
|
|
357
|
+
/**
|
|
358
|
+
* DEFAULT
|
|
359
|
+
*
|
|
360
|
+
* The default round-robin turn order.
|
|
361
|
+
*/
|
|
362
|
+
DEFAULT: {
|
|
363
|
+
first: ({ ctx }: FnContext) =>
|
|
364
|
+
ctx.turn === 0
|
|
365
|
+
? ctx.playOrderPos
|
|
366
|
+
: (ctx.playOrderPos + 1) % ctx.playOrder.length,
|
|
367
|
+
next: ({ ctx }: FnContext) => (ctx.playOrderPos + 1) % ctx.playOrder.length,
|
|
368
|
+
},
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* RESET
|
|
372
|
+
*
|
|
373
|
+
* Similar to DEFAULT, but starts from 0 each time.
|
|
374
|
+
*/
|
|
375
|
+
RESET: {
|
|
376
|
+
first: () => 0,
|
|
377
|
+
next: ({ ctx }: FnContext) => (ctx.playOrderPos + 1) % ctx.playOrder.length,
|
|
378
|
+
},
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* CONTINUE
|
|
382
|
+
*
|
|
383
|
+
* Similar to DEFAULT, but starts with the player who ended the last phase.
|
|
384
|
+
*/
|
|
385
|
+
CONTINUE: {
|
|
386
|
+
first: ({ ctx }: FnContext) => ctx.playOrderPos,
|
|
387
|
+
next: ({ ctx }: FnContext) => (ctx.playOrderPos + 1) % ctx.playOrder.length,
|
|
388
|
+
},
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* ONCE
|
|
392
|
+
*
|
|
393
|
+
* Another round-robin turn order, but goes around just once.
|
|
394
|
+
* The phase ends after all players have played.
|
|
395
|
+
*/
|
|
396
|
+
ONCE: {
|
|
397
|
+
first: () => 0,
|
|
398
|
+
next: ({ ctx }: FnContext) => {
|
|
399
|
+
if (ctx.playOrderPos < ctx.playOrder.length - 1) {
|
|
400
|
+
return ctx.playOrderPos + 1;
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* CUSTOM
|
|
407
|
+
*
|
|
408
|
+
* Identical to DEFAULT, but also sets playOrder at the
|
|
409
|
+
* beginning of the phase.
|
|
410
|
+
*
|
|
411
|
+
* @param {Array} playOrder - The play order.
|
|
412
|
+
*/
|
|
413
|
+
CUSTOM: (playOrder: string[]) => ({
|
|
414
|
+
playOrder: () => playOrder,
|
|
415
|
+
first: () => 0,
|
|
416
|
+
next: ({ ctx }: FnContext) => (ctx.playOrderPos + 1) % ctx.playOrder.length,
|
|
417
|
+
}),
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* CUSTOM_FROM
|
|
421
|
+
*
|
|
422
|
+
* Identical to DEFAULT, but also sets playOrder at the
|
|
423
|
+
* beginning of the phase to a value specified by a field
|
|
424
|
+
* in G.
|
|
425
|
+
*
|
|
426
|
+
* @param {string} playOrderField - Field in G.
|
|
427
|
+
*/
|
|
428
|
+
CUSTOM_FROM: (playOrderField: string) => ({
|
|
429
|
+
playOrder: ({ G }: FnContext) => G[playOrderField],
|
|
430
|
+
first: () => 0,
|
|
431
|
+
next: ({ ctx }: FnContext) => (ctx.playOrderPos + 1) % ctx.playOrder.length,
|
|
432
|
+
}),
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
export const Stage = {
|
|
436
|
+
NULL: null,
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
export const ActivePlayers = {
|
|
440
|
+
/**
|
|
441
|
+
* ALL
|
|
442
|
+
*
|
|
443
|
+
* The turn stays with one player, but any player can play (in any order)
|
|
444
|
+
* until the phase ends.
|
|
445
|
+
*/
|
|
446
|
+
ALL: { all: Stage.NULL },
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* ALL_ONCE
|
|
450
|
+
*
|
|
451
|
+
* The turn stays with one player, but any player can play (once, and in any order).
|
|
452
|
+
* This is typically used in a phase where you want to elicit a response
|
|
453
|
+
* from every player in the game.
|
|
454
|
+
*/
|
|
455
|
+
ALL_ONCE: { all: Stage.NULL, minMoves: 1, maxMoves: 1 },
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* OTHERS
|
|
459
|
+
*
|
|
460
|
+
* The turn stays with one player, and every *other* player can play (in any order)
|
|
461
|
+
* until the phase ends.
|
|
462
|
+
*/
|
|
463
|
+
OTHERS: { others: Stage.NULL },
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* OTHERS_ONCE
|
|
467
|
+
*
|
|
468
|
+
* The turn stays with one player, and every *other* player can play (once, and in any order).
|
|
469
|
+
* This is typically used in a phase where you want to elicit a response
|
|
470
|
+
* from every *other* player in the game.
|
|
471
|
+
*/
|
|
472
|
+
OTHERS_ONCE: { others: Stage.NULL, minMoves: 1, maxMoves: 1 },
|
|
473
|
+
};
|