-
Notifications
You must be signed in to change notification settings - Fork 1
/
wrapper.ts
119 lines (88 loc) · 3.29 KB
/
wrapper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import type {GameState} from "./index";
import { Move } from "./src/move";
import * as engine from "./src/engine";
import { GameEventName } from "./src/log";
import { asserts } from "./src/utils";
import type { LogEvent, LogMove, GameEvents } from './src/log';
import { Player } from "./src/gamestate";
export async function init (nbPlayers: number, expansions: string[], options: {}, seed?: string): Promise<GameState> {
return engine.setup(nbPlayers, options, seed);
}
export function setPlayerMetaData(G: GameState, player: number, metaData: {name: string}) {
G.players[player].name = metaData.name;
return G;
}
export async function move(G: GameState, move: Move, player: number) {
const index = G.log.length;
G = engine.move(G, move, player);
G = automove(G);
for (const roundEvent of G.log.slice(index).filter(item => item.type === "event" && item.event.name === GameEventName.RoundStart)) {
asserts<LogEvent> (roundEvent);
const eventData = roundEvent.event;
asserts<GameEvents.RoundStart> (eventData);
(G as any).messages = [...((G as any).messages || []), `Round ${eventData.round}`];
}
return G;
}
function automove(G: GameState) {
const condition = (pl: Player) => pl.availableMoves && (pl.isAI || pl.availableMoves.placeCard?.length === 1 || pl.availableMoves.chooseCard?.length === 1);
while (G.players.some(condition)) {
G = engine.moveAI(G, G.players.findIndex(condition));
}
return G;
}
export { ended, scores } from './src/engine';
/**
* We give 0 to the last player, 1 to the player before last, ...
* @param G
*/
export function rankings (G: GameState) {
const sortedPoints = G.players.map(pl => pl.points).sort((a, b) => a - b);
return G.players.map(pl => sortedPoints.indexOf(pl.points) + 1);
}
export function replay (G: GameState) {
const oldPlayers = G.players;
const oldG = G;
G = engine.setup(G.players.length, G.options, G.seed);
for (let i = 0; i < oldPlayers.length && i < G.players.length; i++) {
G.players[i].name = oldPlayers[i].name;
G.players[i].isAI = oldPlayers[i].isAI;
}
for (const move of oldG.log.filter(event => event.type === "move")) {
asserts<LogMove>(move);
G = engine.move(G, move.move, move.player);
}
G = automove(G);
return G;
}
export function round (G: GameState) {
return G.round;
}
export async function dropPlayer (G: GameState, player: number) {
G.players[player].isAI = true;
return automove(G);
}
export function currentPlayer (G: GameState) {
return G.players.map((pl, i) => pl.availableMoves ? i : -1).filter(i => i !== -1);
}
export { stripSecret } from './src/engine';
export function messages (G: GameState) {
const messages = (G as any).messages || [];
delete (G as any).messages;
return {
messages,
data: G
};
}
export function logLength (G: GameState, player?: number) {
return G.log.length;
}
export function logSlice (G: GameState, options?: {player?: number; start?: number; end?: number}) {
const stripped = engine.stripSecret(G, options?.player);
return {
log: stripped.log.slice(options?.start, options?.end),
availableMoves: options?.end === undefined ?
stripped.players.map(pl => pl.availableMoves) :
engine.stripSecret(replay({...G, log: G.log.slice(0, options!.end)}), options!.player).players.map(pl => pl.availableMoves)
};
}