@oathompsonjones/mini-games 1.0.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.
@@ -0,0 +1,124 @@
1
+ import type Board from "./board.js";
2
+ import { EventEmitter } from "eventemitter3";
3
+ import type { Position } from "./board.js";
4
+ export type PlayerType = "easyCPU" | "hardCPU" | "human" | "impossibleCPU" | "mediumCPU";
5
+ export type Algorithm = "alphabeta" | "minimax";
6
+ export interface GameConstructorOptions {
7
+ id?: string;
8
+ onEnd?: (winner: number | null) => Promise<void> | void;
9
+ onInvalidInput?: (position: Position) => Promise<void> | void;
10
+ renderer?: (controller: Controller) => Promise<void> | void;
11
+ }
12
+ export interface GameConstructor {
13
+ new (playerOneType: PlayerType, playerTwoType: PlayerType, options?: GameConstructorOptions): Controller;
14
+ }
15
+ export declare function Game(constructor: GameConstructor): void;
16
+ /**
17
+ * Represents a game controller.
18
+ */
19
+ export default abstract class Controller extends EventEmitter<{
20
+ end: GameConstructorOptions["onEnd"];
21
+ input: GameConstructorOptions["onInvalidInput"];
22
+ invalidInput: GameConstructorOptions["onInvalidInput"];
23
+ }> {
24
+ /**
25
+ * Contains the ID of the game.
26
+ */
27
+ readonly gameID: string;
28
+ /**
29
+ * Contains the board.
30
+ */
31
+ readonly board: Board;
32
+ /**
33
+ * Contains the view object.
34
+ */
35
+ readonly render: Required<GameConstructorOptions>["renderer"];
36
+ /**
37
+ * Contains the player objects.
38
+ */
39
+ protected readonly players: Array<{
40
+ id: number;
41
+ playerType: PlayerType;
42
+ }>;
43
+ /**
44
+ * Contains the ID of the current player.
45
+ */
46
+ private currentPlayerId;
47
+ /**
48
+ * Creates an instance of Controller.
49
+ *
50
+ * @param playerTypes The types of player.
51
+ * @param view The view object.
52
+ * @param gameID The ID of the game.
53
+ * @param board The board.
54
+ */
55
+ protected constructor(playerTypes: PlayerType[], board: Board, render: Controller["render"], gameID: string | undefined, onEnd?: GameConstructorOptions["onEnd"], onInvalidInput?: GameConstructorOptions["onInvalidInput"]);
56
+ /**
57
+ * Gets the current player object.
58
+ */
59
+ get currentPlayer(): {
60
+ id: number;
61
+ playerType: PlayerType;
62
+ };
63
+ /**
64
+ * Controls the main game flow.
65
+ *
66
+ * @returns The winner or null in the event of a tie.
67
+ */
68
+ play(algorithm?: Algorithm): Promise<void>;
69
+ /**
70
+ * The bog standard minimax algorithm. Left in for reference.
71
+ *
72
+ * @link https://en.wikipedia.org/wiki/Minimax
73
+ * @param depth The depth of the algorithm.
74
+ * @param maximisingPlayer Whether or not the current player is the maximising player.
75
+ * @returns The optimal move.
76
+ */
77
+ protected minimax(depth?: number, maximisingPlayer?: boolean): {
78
+ move: Position;
79
+ score: number;
80
+ };
81
+ /**
82
+ * The minimax algorithm with alpha-beta pruning.
83
+ *
84
+ * @link https://en.wikipedia.org/wiki/Minimax
85
+ * @param depth The depth of the algorithm.
86
+ * @param alpha The bounds for the alpha-beta variation of the algorithm.
87
+ * @param beta The bounds for the alpha-beta variation of the algorithm.
88
+ * @param maximisingPlayer Whether or not the current player is the maximising player.
89
+ * @returns The optimal move.
90
+ */
91
+ protected alphabeta(depth?: number, alpha?: number, beta?: number, maximisingPlayer?: boolean): {
92
+ move: Position;
93
+ score: number;
94
+ };
95
+ /**
96
+ * Changes which player's turn it is.
97
+ */
98
+ private nextTurn;
99
+ /**
100
+ * Makes a move.
101
+ *
102
+ * @param input Either the algorithm to use to calculate the move or the move itself.
103
+ */
104
+ private makeMove;
105
+ /**
106
+ * Determines the CPU move.
107
+ *
108
+ * @param difficulty The difficulty of the AI.
109
+ * @param algorithm The algorithm to use.
110
+ * @returns The move.
111
+ */
112
+ abstract determineCPUMove(difficulty: Omit<PlayerType, "human">, algorithm?: Algorithm): Position;
113
+ /**
114
+ * Finds the optimal move.
115
+ *
116
+ * @param options The options.
117
+ * @returns The optimal move.
118
+ */
119
+ abstract findOptimalMove(options?: {
120
+ algorithm?: Algorithm;
121
+ maxDepth?: number;
122
+ randomMove?: Position;
123
+ }): Position;
124
+ }
@@ -0,0 +1,185 @@
1
+ import { EventEmitter } from "eventemitter3";
2
+ export function Game(constructor) {
3
+ void constructor;
4
+ }
5
+ /**
6
+ * Represents a game controller.
7
+ */
8
+ export default class Controller extends EventEmitter {
9
+ /**
10
+ * Contains the ID of the game.
11
+ */
12
+ gameID;
13
+ /**
14
+ * Contains the board.
15
+ */
16
+ board;
17
+ /**
18
+ * Contains the view object.
19
+ */
20
+ render;
21
+ /**
22
+ * Contains the player objects.
23
+ */
24
+ players;
25
+ /**
26
+ * Contains the ID of the current player.
27
+ */
28
+ currentPlayerId = 0;
29
+ /**
30
+ * Creates an instance of Controller.
31
+ *
32
+ * @param playerTypes The types of player.
33
+ * @param view The view object.
34
+ * @param gameID The ID of the game.
35
+ * @param board The board.
36
+ */
37
+ // eslint-disable-next-line @typescript-eslint/max-params
38
+ constructor(playerTypes, board, render, gameID, onEnd, onInvalidInput) {
39
+ super();
40
+ this.gameID = gameID ?? Date.now().toString(16);
41
+ this.board = board;
42
+ this.board.setGameID(this.gameID);
43
+ this.players = playerTypes.map((playerType, id) => ({ id, playerType }));
44
+ this.render = render;
45
+ if (onEnd !== undefined)
46
+ this.on("end", onEnd);
47
+ if (onInvalidInput !== undefined)
48
+ this.on("invalidInput", onInvalidInput);
49
+ }
50
+ /**
51
+ * Gets the current player object.
52
+ */
53
+ get currentPlayer() {
54
+ return this.players[this.currentPlayerId];
55
+ }
56
+ /**
57
+ * Controls the main game flow.
58
+ *
59
+ * @returns The winner or null in the event of a tie.
60
+ */
61
+ async play(algorithm = "alphabeta") {
62
+ await this.render(this);
63
+ this.on("input", async (move) => {
64
+ await this.makeMove(move);
65
+ if (this.currentPlayer.playerType !== "human")
66
+ await this.makeMove(algorithm);
67
+ });
68
+ while (this.currentPlayer.playerType !== "human" && this.board.winner === false)
69
+ // eslint-disable-next-line no-await-in-loop
70
+ await this.makeMove(algorithm);
71
+ }
72
+ /**
73
+ * The bog standard minimax algorithm. Left in for reference.
74
+ *
75
+ * @link https://en.wikipedia.org/wiki/Minimax
76
+ * @param depth The depth of the algorithm.
77
+ * @param maximisingPlayer Whether or not the current player is the maximising player.
78
+ * @returns The optimal move.
79
+ */
80
+ minimax(depth = Infinity, maximisingPlayer = true) {
81
+ const playerIds = [(this.currentPlayerId + 1) % 2, this.currentPlayerId];
82
+ if (depth === 0 || this.board.winner !== false) {
83
+ return {
84
+ move: { x: NaN, y: NaN },
85
+ score: this.board.heuristic * (this.currentPlayerId === 0 ? 1 : -1)
86
+ };
87
+ }
88
+ let bestMove = {
89
+ move: { x: NaN, y: NaN },
90
+ score: maximisingPlayer ? -Infinity : Infinity
91
+ };
92
+ const { emptyCells } = this.board;
93
+ for (const move of emptyCells) {
94
+ this.board.makeMove(move, playerIds[Number(maximisingPlayer)]);
95
+ const score = (9 - emptyCells.length) * this.minimax(depth - 1, !maximisingPlayer).score;
96
+ this.board.undoLastMove();
97
+ if (maximisingPlayer) {
98
+ const bestScore = Math.max(score, bestMove.score);
99
+ if (bestScore !== bestMove.score)
100
+ bestMove = { move, score };
101
+ }
102
+ else {
103
+ const bestScore = Math.min(score, bestMove.score);
104
+ if (bestScore !== bestMove.score)
105
+ bestMove = { move, score };
106
+ }
107
+ }
108
+ return bestMove;
109
+ }
110
+ /**
111
+ * The minimax algorithm with alpha-beta pruning.
112
+ *
113
+ * @link https://en.wikipedia.org/wiki/Minimax
114
+ * @param depth The depth of the algorithm.
115
+ * @param alpha The bounds for the alpha-beta variation of the algorithm.
116
+ * @param beta The bounds for the alpha-beta variation of the algorithm.
117
+ * @param maximisingPlayer Whether or not the current player is the maximising player.
118
+ * @returns The optimal move.
119
+ */
120
+ alphabeta(depth = Infinity, alpha = -Infinity, beta = Infinity, maximisingPlayer = true) {
121
+ const playerIds = [(this.currentPlayerId + 1) % 2, this.currentPlayerId];
122
+ if (depth === 0 || this.board.winner !== false) {
123
+ return {
124
+ move: { x: NaN, y: NaN },
125
+ score: this.board.heuristic * (this.currentPlayerId === 0 ? 1 : -1)
126
+ };
127
+ }
128
+ let bestMove = {
129
+ move: { x: NaN, y: NaN },
130
+ score: maximisingPlayer ? -Infinity : Infinity
131
+ };
132
+ const { emptyCells } = this.board;
133
+ for (const move of emptyCells) {
134
+ this.board.makeMove(move, playerIds[Number(maximisingPlayer)]);
135
+ const score = (9 - emptyCells.length) * this.alphabeta(depth - 1, alpha, beta, !maximisingPlayer).score;
136
+ this.board.undoLastMove();
137
+ if (maximisingPlayer) {
138
+ const bestScore = Math.max(score, bestMove.score);
139
+ if (bestScore !== bestMove.score)
140
+ bestMove = { move, score };
141
+ if (bestMove.score > beta)
142
+ break;
143
+ // eslint-disable-next-line no-param-reassign
144
+ alpha = Math.max(alpha, bestScore);
145
+ }
146
+ else {
147
+ const bestScore = Math.min(score, bestMove.score);
148
+ if (bestScore !== bestMove.score)
149
+ bestMove = { move, score };
150
+ if (bestMove.score < alpha)
151
+ break;
152
+ // eslint-disable-next-line no-param-reassign
153
+ beta = Math.min(beta, bestScore);
154
+ }
155
+ }
156
+ return bestMove;
157
+ }
158
+ /**
159
+ * Changes which player's turn it is.
160
+ */
161
+ nextTurn() {
162
+ this.currentPlayerId = (this.currentPlayerId + 1) % this.players.length;
163
+ }
164
+ /**
165
+ * Makes a move.
166
+ *
167
+ * @param input Either the algorithm to use to calculate the move or the move itself.
168
+ */
169
+ async makeMove(input) {
170
+ if (typeof input === "string") {
171
+ this.board.makeMove(this.determineCPUMove(this.currentPlayer.playerType, input), this.currentPlayer.id);
172
+ }
173
+ else {
174
+ if (this.currentPlayer.playerType !== "human" || !this.board.moveIsValid(input))
175
+ return void this.emit("invalidInput", input);
176
+ this.board.makeMove(input, this.currentPlayer.id);
177
+ }
178
+ await this.render(this);
179
+ const { winner } = this.board;
180
+ if (winner !== false)
181
+ return void this.emit("end", winner);
182
+ this.nextTurn();
183
+ }
184
+ }
185
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iYXNlL2NvbnRyb2xsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQWU3QyxNQUFNLFVBQVUsSUFBSSxDQUFDLFdBQTRCO0lBQzdDLEtBQUssV0FBVyxDQUFDO0FBQ3JCLENBQUM7QUFHRDs7R0FFRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQWdCLFVBQVcsU0FBUSxZQUkvQztJQUNFOztPQUVHO0lBQ2EsTUFBTSxDQUFTO0lBRS9COztPQUVHO0lBQ2EsS0FBSyxDQUFRO0lBRTdCOztPQUVHO0lBQ2EsTUFBTSxDQUErQztJQUVyRTs7T0FFRztJQUNnQixPQUFPLENBQWlEO0lBRTNFOztPQUVHO0lBQ0ssZUFBZSxHQUFXLENBQUMsQ0FBQztJQUVwQzs7Ozs7OztPQU9HO0lBQ0gseURBQXlEO0lBQ3pELFlBQ0ksV0FBeUIsRUFDekIsS0FBWSxFQUNaLE1BQTRCLEVBQzVCLE1BQTBCLEVBQzFCLEtBQXVDLEVBQ3ZDLGNBQXlEO1FBRXpELEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDekUsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFB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TSxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDOUIsSUFBSSxNQUFNLEtBQUssS0FBSztZQUNoQixPQUFPLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3BCLENBQUM7Q0FrQkoiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSBCb2FyZCBmcm9tIFwiLi9ib2FyZC5qc1wiO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSBcImV2ZW50ZW1pdHRlcjNcIjtcbmltcG9ydCB0eXBlIHsgUG9zaXRpb24gfSBmcm9tIFwiLi9ib2FyZC5qc1wiO1xuXG5leHBvcnQgdHlwZSBQbGF5ZXJUeXBlID0gXCJlYXN5Q1BVXCIgfCBcImhhcmRDUFVcIiB8IFwiaHVtYW5cIiB8IFwiaW1wb3NzaWJsZUNQVVwiIHwgXCJtZWRpdW1DUFVcIjtcbmV4cG9ydCB0eXBlIEFsZ29yaXRobSA9IFwiYWxwaGFiZXRhXCIgfCBcIm1pbmltYXhcIjtcbmV4cG9ydCBpbnRlcmZhY2UgR2FtZUNvbnN0cnVjdG9yT3B0aW9ucyB7XG4gICAgaWQ/OiBzdHJpbmc7XG4gICAgb25FbmQ/OiAod2lubmVyOiBudW1iZXIgfCBudWxsKSA9PiBQcm9taXNlPHZvaWQ+IHwgdm9pZDtcbiAgICBvbkludmFsaWRJbnB1dD86IChwb3NpdGlvbjogUG9zaXRpb24pID0+IFByb21pc2U8dm9pZD4gfCB2b2lkO1xuICAgIHJlbmRlcmVyPzogKGNvbnRyb2xsZXI6IENvbnRyb2xsZXIpID0+IFByb21pc2U8dm9pZD4gfCB2b2lkO1xufVxuZXhwb3J0IGludGVyZmFjZSBHYW1lQ29uc3RydWN0b3Ige1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvcHJlZmVyLWZ1bmN0aW9uLXR5cGVcbiAgICBuZXcgKHBsYXllck9uZVR5cGU6IFBsYXllclR5cGUsIHBsYXllclR3b1R5cGU6IFBsYXllclR5cGUsIG9wdGlvbnM/OiBHYW1lQ29uc3RydWN0b3JPcHRpb25zKTogQ29udHJvbGxlcjtcbn1cbmV4cG9ydCBmdW5jdGlvbiBHYW1lKGNvbnN0cnVjdG9yOiBHYW1lQ29uc3RydWN0b3IpOiB2b2lkIHtcbiAgICB2b2lkIGNvbnN0cnVjdG9yO1xufVxuXG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGdhbWUgY29udHJvbGxlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgQ29udHJvbGxlciBleHRlbmRzIEV2ZW50RW1pdHRlcjx7XG4gICAgZW5kOiBHYW1lQ29uc3RydWN0b3JPcHRpb25zW1wib25FbmRcIl07XG4gICAgaW5wdXQ6IEdhbWVDb25zdHJ1Y3Rvck9wdGlvbnNbXCJvbkludmFsaWRJbnB1dFwiXTtcbiAgICBpbnZhbGlkSW5wdXQ6IEdhbWVDb25zdHJ1Y3Rvck9wdGlvbnNbXCJvbkludmFsaWRJbnB1dFwiXTtcbn0+IHtcbiAgICAvKipcbiAgICAgKiBDb250YWlucyB0aGUgSUQgb2YgdGhlIGdhbWUuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGdhbWVJRDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29udGFpbnMgdGhlIGJvYXJkLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBib2FyZDogQm9hcmQ7XG5cbiAgICAvKipcbiAgICAgKiBDb250YWlucyB0aGUgdmlldyBvYmplY3QuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IHJlbmRlcjogUmVxdWlyZWQ8R2FtZUNvbnN0cnVjdG9yT3B0aW9ucz5bXCJyZW5kZXJlclwiXTtcblxuICAgIC8qKlxuICAgICAqIENvbnRhaW5zIHRoZSBwbGF5ZXIgb2JqZWN0cy5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgcGxheWVyczogQXJyYXk8eyBpZDogbnVtYmVyOyBwbGF5ZXJUeXBlOiBQbGF5ZXJUeXBlOyB9PjtcblxuICAgIC8qKlxuICAgICAqIENvbnRhaW5zIHRoZSBJRCBvZiB0aGUgY3VycmVudCBwbGF5ZXIuXG4gICAgICovXG4gICAgcHJpdmF0ZSBjdXJyZW50UGxheWVySWQ6IG51bWJlciA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIENvbnRyb2xsZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGxheWVyVHlwZXMgVGhlIHR5cGVzIG9mIHBsYXllci5cbiAgICAgKiBAcGFyYW0gdmlldyBUaGUgdmlldyBvYmplY3QuXG4gICAgICogQHBhcmFtIGdhbWVJRCBUaGUgSUQgb2YgdGhlIGdhbWUuXG4gICAgICogQHBhcmFtIGJvYXJkIFRoZSBib2FyZC5cbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L21heC1wYXJhbXNcbiAgICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgICAgIHBsYXllclR5cGVzOiBQbGF5ZXJUeXBlW10sXG4gICAgICAgIGJvYXJkOiBCb2FyZCxcbiAgICAgICAgcmVuZGVyOiBDb250cm9sbGVyW1wicmVuZGVyXCJdLFxuICAgICAgICBnYW1lSUQ6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICAgICAgb25FbmQ/OiBHYW1lQ29uc3RydWN0b3JPcHRpb25zW1wib25FbmRcIl0sXG4gICAgICAgIG9uSW52YWxpZElucHV0PzogR2FtZUNvbnN0cnVjdG9yT3B0aW9uc1tcIm9uSW52YWxpZElucHV0XCJdXG4gICAgKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuZ2FtZUlEID0gZ2FtZUlEID8/IERhdGUubm93KCkudG9TdHJpbmcoMTYpO1xuICAgICAgICB0aGlzLmJvYXJkID0gYm9hcmQ7XG4gICAgICAgIHRoaXMuYm9hcmQuc2V0R2FtZUlEKHRoaXMuZ2FtZUlEKTtcbiAgICAgICAgdGhpcy5wbGF5ZXJzID0gcGxheWVyVHlwZXMubWFwKChwbGF5ZXJUeXBlLCBpZCkgPT4gKHsgaWQsIHBsYXllclR5cGUgfSkpO1xuICAgICAgICB0aGlzLnJlbmRlciA9IHJlbmRlcjtcbiAgICAgICAgaWYgKG9uRW5kICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB0aGlzLm9uKFwiZW5kXCIsIG9uRW5kKTtcbiAgICAgICAgaWYgKG9uSW52YWxpZElucHV0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB0aGlzLm9uKFwiaW52YWxpZElucHV0XCIsIG9uSW52YWxpZElucHV0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBjdXJyZW50IHBsYXllciBvYmplY3QuXG4gICAgICovXG4gICAgcHVibGljIGdldCBjdXJyZW50UGxheWVyKCk6IHsgaWQ6IG51bWJlcjsgcGxheWVyVHlwZTogUGxheWVyVHlwZTsgfSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBsYXllcnNbdGhpcy5jdXJyZW50UGxheWVySWRdITtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb250cm9scyB0aGUgbWFpbiBnYW1lIGZsb3cuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgd2lubmVyIG9yIG51bGwgaW4gdGhlIGV2ZW50IG9mIGEgdGllLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBwbGF5KGFsZ29yaXRobTogQWxnb3JpdGhtID0gXCJhbHBoYWJldGFcIik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCB0aGlzLnJlbmRlcih0aGlzKTtcbiAgICAgICAgdGhpcy5vbihcImlucHV0XCIsIGFzeW5jIChtb3ZlOiBQb3NpdGlvbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYWtlTW92ZShtb3ZlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRQbGF5ZXIucGxheWVyVHlwZSAhPT0gXCJodW1hblwiKVxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWFrZU1vdmUoYWxnb3JpdGhtKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHdoaWxlICh0aGlzLmN1cnJlbnRQbGF5ZXIucGxheWVyVHlwZSAhPT0gXCJodW1hblwiICYmIHRoaXMuYm9hcmQud2lubmVyID09PSBmYWxzZSlcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wXG4gICAgICAgICAgICBhd2FpdCB0aGlzLm1ha2VNb3ZlKGFsZ29yaXRobSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJvZyBzdGFuZGFyZCBtaW5pbWF4IGFsZ29yaXRobS4gTGVmdCBpbiBmb3IgcmVmZXJlbmNlLlxuICAgICAqXG4gICAgICogQGxpbmsgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTWluaW1heFxuICAgICAqIEBwYXJhbSBkZXB0aCBUaGUgZGVwdGggb2YgdGhlIGFsZ29yaXRobS5cbiAgICAgKiBAcGFyYW0gbWF4aW1pc2luZ1BsYXllciBXaGV0aGVyIG9yIG5vdCB0aGUgY3VycmVudCBwbGF5ZXIgaXMgdGhlIG1heGltaXNpbmcgcGxheWVyLlxuICAgICAqIEByZXR1cm5zIFRoZSBvcHRpbWFsIG1vdmUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIG1pbmltYXgoZGVwdGg6IG51bWJlciA9IEluZmluaXR5LCBtYXhpbWlzaW5nUGxheWVyOiBib29sZWFuID0gdHJ1ZSk6IHsgbW92ZTogUG9zaXRpb247IHNjb3JlOiBudW1iZXI7IH0ge1xuICAgICAgICBjb25zdCBwbGF5ZXJJZHMgPSBbKHRoaXMuY3VycmVudFBsYXllcklkICsgMSkgJSAyLCB0aGlzLmN1cnJlbnRQbGF5ZXJJZF0gYXMgY29uc3Q7XG4gICAgICAgIGlmIChkZXB0aCA9PT0gMCB8fCB0aGlzLmJvYXJkLndpbm5lciAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbW92ZTogeyB4OiBOYU4sIHk6IE5hTiB9LFxuICAgICAgICAgICAgICAgIHNjb3JlOiB0aGlzLmJvYXJkLmhldXJpc3RpYyAqICh0aGlzLmN1cnJlbnRQbGF5ZXJJZCA9PT0gMCA/IDEgOiAtMSlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGJlc3RNb3ZlOiBSZXR1cm5UeXBlPHR5cGVvZiB0aGlzLm1pbmltYXg+ID0ge1xuICAgICAgICAgICAgbW92ZTogeyB4OiBOYU4sIHk6IE5hTiB9LFxuICAgICAgICAgICAgc2NvcmU6IG1heGltaXNpbmdQbGF5ZXIgPyAtSW5maW5pdHkgOiBJbmZpbml0eVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB7IGVtcHR5Q2VsbHMgfSA9IHRoaXMuYm9hcmQ7XG4gICAgICAgIGZvciAoY29uc3QgbW92ZSBvZiBlbXB0eUNlbGxzKSB7XG4gICAgICAgICAgICB0aGlzLmJvYXJkLm1ha2VNb3ZlKG1vdmUsIHBsYXllcklkc1tOdW1iZXIobWF4aW1pc2luZ1BsYXllcildISk7XG4gICAgICAgICAgICBjb25zdCBzY29yZSA9ICg5IC0gZW1wdHlDZWxscy5sZW5ndGgpICogdGhpcy5taW5pbWF4KGRlcHRoIC0gMSwgIW1heGltaXNpbmdQbGF5ZXIpLnNjb3JlO1xuICAgICAgICAgICAgdGhpcy5ib2FyZC51bmRvTGFzdE1vdmUoKTtcbiAgICAgICAgICAgIGlmIChtYXhpbWlzaW5nUGxheWVyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYmVzdFNjb3JlID0gTWF0aC5tYXgoc2NvcmUsIGJlc3RNb3ZlLnNjb3JlKTtcbiAgICAgICAgICAgICAgICBpZiAoYmVzdFNjb3JlICE9PSBiZXN0TW92ZS5zY29yZSlcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1vdmUgPSB7IG1vdmUsIHNjb3JlIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJlc3RTY29yZSA9IE1hdGgubWluKHNjb3JlLCBiZXN0TW92ZS5zY29yZSk7XG4gICAgICAgICAgICAgICAgaWYgKGJlc3RTY29yZSAhPT0gYmVzdE1vdmUuc2NvcmUpXG4gICAgICAgICAgICAgICAgICAgIGJlc3RNb3ZlID0geyBtb3ZlLCBzY29yZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiZXN0TW92ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWluaW1heCBhbGdvcml0aG0gd2l0aCBhbHBoYS1iZXRhIHBydW5pbmcuXG4gICAgICpcbiAgICAgKiBAbGluayBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NaW5pbWF4XG4gICAgICogQHBhcmFtIGRlcHRoIFRoZSBkZXB0aCBvZiB0aGUgYWxnb3JpdGhtLlxuICAgICAqIEBwYXJhbSBhbHBoYSBUaGUgYm91bmRzIGZvciB0aGUgYWxwaGEtYmV0YSB2YXJpYXRpb24gb2YgdGhlIGFsZ29yaXRobS5cbiAgICAgKiBAcGFyYW0gYmV0YSBUaGUgYm91bmRzIGZvciB0aGUgYWxwaGEtYmV0YSB2YXJpYXRpb24gb2YgdGhlIGFsZ29yaXRobS5cbiAgICAgKiBAcGFyYW0gbWF4aW1pc2luZ1BsYXllciBXaGV0aGVyIG9yIG5vdCB0aGUgY3VycmVudCBwbGF5ZXIgaXMgdGhlIG1heGltaXNpbmcgcGxheWVyLlxuICAgICAqIEByZXR1cm5zIFRoZSBvcHRpbWFsIG1vdmUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFscGhhYmV0YShcbiAgICAgICAgZGVwdGg6IG51bWJlciA9IEluZmluaXR5LFxuICAgICAgICBhbHBoYTogbnVtYmVyID0gLUluZmluaXR5LFxuICAgICAgICBiZXRhOiBudW1iZXIgPSBJbmZpbml0eSxcbiAgICAgICAgbWF4aW1pc2luZ1BsYXllcjogYm9vbGVhbiA9IHRydWVcbiAgICApOiB7IG1vdmU6IFBvc2l0aW9uOyBzY29yZTogbnVtYmVyOyB9IHtcbiAgICAgICAgY29uc3QgcGxheWVySWRzID0gWyh0aGlzLmN1cnJlbnRQbGF5ZXJJZCArIDEpICUgMiwgdGhpcy5jdXJyZW50UGxheWVySWRdIGFzIGNvbnN0O1xuICAgICAgICBpZiAoZGVwdGggPT09IDAgfHwgdGhpcy5ib2FyZC53aW5uZXIgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1vdmU6IHsgeDogTmFOLCB5OiBOYU4gfSxcbiAgICAgICAgICAgICAgICBzY29yZTogdGhpcy5ib2FyZC5oZXVyaXN0aWMgKiAodGhpcy5jdXJyZW50UGxheWVySWQgPT09IDAgPyAxIDogLTEpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGxldCBiZXN0TW92ZTogUmV0dXJuVHlwZTx0eXBlb2YgdGhpcy5hbHBoYWJldGE+ID0ge1xuICAgICAgICAgICAgbW92ZTogeyB4OiBOYU4sIHk6IE5hTiB9LFxuICAgICAgICAgICAgc2NvcmU6IG1heGltaXNpbmdQbGF5ZXIgPyAtSW5maW5pdHkgOiBJbmZpbml0eVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCB7IGVtcHR5Q2VsbHMgfSA9IHRoaXMuYm9hcmQ7XG4gICAgICAgIGZvciAoY29uc3QgbW92ZSBvZiBlbXB0eUNlbGxzKSB7XG4gICAgICAgICAgICB0aGlzLmJvYXJkLm1ha2VNb3ZlKG1vdmUsIHBsYXllcklkc1tOdW1iZXIobWF4aW1pc2luZ1BsYXllcildISk7XG4gICAgICAgICAgICBjb25zdCBzY29yZSA9ICg5IC0gZW1wdHlDZWxscy5sZW5ndGgpICogdGhpcy5hbHBoYWJldGEoZGVwdGggLSAxLCBhbHBoYSwgYmV0YSwgIW1heGltaXNpbmdQbGF5ZXIpLnNjb3JlO1xuICAgICAgICAgICAgdGhpcy5ib2FyZC51bmRvTGFzdE1vdmUoKTtcbiAgICAgICAgICAgIGlmIChtYXhpbWlzaW5nUGxheWVyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYmVzdFNjb3JlID0gTWF0aC5tYXgoc2NvcmUsIGJlc3RNb3ZlLnNjb3JlKTtcbiAgICAgICAgICAgICAgICBpZiAoYmVzdFNjb3JlICE9PSBiZXN0TW92ZS5zY29yZSlcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1vdmUgPSB7IG1vdmUsIHNjb3JlIH07XG4gICAgICAgICAgICAgICAgaWYgKGJlc3RNb3ZlLnNjb3JlID4gYmV0YSlcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgICAgICAgICAgYWxwaGEgPSBNYXRoLm1heChhbHBoYSwgYmVzdFNjb3JlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYmVzdFNjb3JlID0gTWF0aC5taW4oc2NvcmUsIGJlc3RNb3ZlLnNjb3JlKTtcbiAgICAgICAgICAgICAgICBpZiAoYmVzdFNjb3JlICE9PSBiZXN0TW92ZS5zY29yZSlcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1vdmUgPSB7IG1vdmUsIHNjb3JlIH07XG4gICAgICAgICAgICAgICAgaWYgKGJlc3RNb3ZlLnNjb3JlIDwgYWxwaGEpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgICAgICAgICAgIGJldGEgPSBNYXRoLm1pbihiZXRhLCBiZXN0U2NvcmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiZXN0TW92ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2VzIHdoaWNoIHBsYXllcidzIHR1cm4gaXQgaXMuXG4gICAgICovXG4gICAgcHJpdmF0ZSBuZXh0VHVybigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdXJyZW50UGxheWVySWQgPSAodGhpcy5jdXJyZW50UGxheWVySWQgKyAxKSAlIHRoaXMucGxheWVycy5sZW5ndGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYSBtb3ZlLlxuICAgICAqXG4gICAgICogQHBhcmFtIGlucHV0IEVpdGhlciB0aGUgYWxnb3JpdGhtIHRvIHVzZSB0byBjYWxjdWxhdGUgdGhlIG1vdmUgb3IgdGhlIG1vdmUgaXRzZWxmLlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgbWFrZU1vdmUoaW5wdXQ6IEFsZ29yaXRobSB8IFBvc2l0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHRoaXMuYm9hcmQubWFrZU1vdmUodGhpcy5kZXRlcm1pbmVDUFVNb3ZlKHRoaXMuY3VycmVudFBsYXllci5wbGF5ZXJUeXBlLCBpbnB1dCksIHRoaXMuY3VycmVudFBsYXllci5pZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50UGxheWVyLnBsYXllclR5cGUgIT09IFwiaHVtYW5cIiB8fCAhdGhpcy5ib2FyZC5tb3ZlSXNWYWxpZChpbnB1dCkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHZvaWQgdGhpcy5lbWl0KFwiaW52YWxpZElucHV0XCIsIGlucHV0KTtcbiAgICAgICAgICAgIHRoaXMuYm9hcmQubWFrZU1vdmUoaW5wdXQsIHRoaXMuY3VycmVudFBsYXllci5pZCk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5yZW5kZXIodGhpcyk7XG4gICAgICAgIGNvbnN0IHsgd2lubmVyIH0gPSB0aGlzLmJvYXJkO1xuICAgICAgICBpZiAod2lubmVyICE9PSBmYWxzZSlcbiAgICAgICAgICAgIHJldHVybiB2b2lkIHRoaXMuZW1pdChcImVuZFwiLCB3aW5uZXIpO1xuICAgICAgICB0aGlzLm5leHRUdXJuKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyB0aGUgQ1BVIG1vdmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZGlmZmljdWx0eSBUaGUgZGlmZmljdWx0eSBvZiB0aGUgQUkuXG4gICAgICogQHBhcmFtIGFsZ29yaXRobSBUaGUgYWxnb3JpdGhtIHRvIHVzZS5cbiAgICAgKiBAcmV0dXJucyBUaGUgbW92ZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgZGV0ZXJtaW5lQ1BVTW92ZShkaWZmaWN1bHR5OiBPbWl0PFBsYXllclR5cGUsIFwiaHVtYW5cIj4sIGFsZ29yaXRobT86IEFsZ29yaXRobSk6IFBvc2l0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIG9wdGltYWwgbW92ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBvcHRpb25zIFRoZSBvcHRpb25zLlxuICAgICAqIEByZXR1cm5zIFRoZSBvcHRpbWFsIG1vdmUuXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IGZpbmRPcHRpbWFsTW92ZShvcHRpb25zPzogeyBhbGdvcml0aG0/OiBBbGdvcml0aG07IG1heERlcHRoPzogbnVtYmVyOyByYW5kb21Nb3ZlPzogUG9zaXRpb247IH0pOiBQb3NpdGlvbjtcbn1cbiJdfQ==
@@ -0,0 +1,133 @@
1
+ import type LongInt from "./longInt.js";
2
+ import type { StringType } from "./longInt.js";
3
+ /**
4
+ * Represents a BitBoard.
5
+ *
6
+ * @link https://en.wikipedia.org/wiki/Bitboard
7
+ */
8
+ export default abstract class BitBoard<T extends LongInt | number = LongInt | number> {
9
+ /**
10
+ * The numeric data.
11
+ */
12
+ protected _data: T;
13
+ /**
14
+ * Creates an instance of BitBoard.
15
+ *
16
+ * @param data The data to assign to the BitBoard.
17
+ */
18
+ protected constructor(data: T);
19
+ /**
20
+ * Gets the numeric data.
21
+ */
22
+ get data(): T;
23
+ /**
24
+ * Returns a string representation of the BitBoard.
25
+ *
26
+ * @param type The base of the string to print.
27
+ * @returns The string representation.
28
+ */
29
+ toString(type?: StringType): string;
30
+ /**
31
+ * Assigns a given bit a given value.
32
+ *
33
+ * @param bit The x coordinate.
34
+ * @param value The value to assign to the bit.
35
+ */
36
+ assignBit(bit: number, value: 0 | 1): void;
37
+ /**
38
+ * Gets a given bit, based on it's x, y coordinates.
39
+ *
40
+ * @param bit The index of the bit to get, 0 = LSB.
41
+ * @returns The bit.
42
+ */
43
+ abstract getBit(bit: number): 0 | 1;
44
+ /**
45
+ * Sets a given bit (changes the value to 1), based on it's x, y coordinates.
46
+ *
47
+ * @param bit The index of the bit to get, 0 = LSB.
48
+ */
49
+ abstract setBit(bit: number): void;
50
+ /**
51
+ * Clears a given bit (changes the value to 0), based on it's x, y coordinates.
52
+ *
53
+ * @param bit The index of the bit to get, 0 = LSB.
54
+ */
55
+ abstract clearBit(bit: number): void;
56
+ /**
57
+ * Toggles a given bit (changes the value from 0 to 1 or 1 to 0), based on it's x, y coordinates.
58
+ *
59
+ * @param bit The index of the bit to get, 0 = LSB.
60
+ */
61
+ abstract toggleBit(bit: number): void;
62
+ /**
63
+ * Clears the whole BitBoard (sets all values to 0).
64
+ */
65
+ abstract clearAll(): void;
66
+ /**
67
+ * Set the whole BitBoard (sets all values to 1).
68
+ */
69
+ abstract setAll(): void;
70
+ /**
71
+ * Gets a range of bits.
72
+ *
73
+ * @param LSB The least significant bit.
74
+ * @param numberOfBits The number of bits to get.
75
+ * @returns The range of bits.
76
+ */
77
+ abstract getBits(LSB: number, numberOfBits: number): T;
78
+ /**
79
+ * Carries out a bitwise and (&) operation.
80
+ *
81
+ * @param right The right value.
82
+ * @returns The result.
83
+ */
84
+ abstract and(right: BitBoard<T> | T | number): this;
85
+ /**
86
+ * Carries out a bitwise or (|) operation.
87
+ *
88
+ * @param right The right value.
89
+ * @returns The result.
90
+ */
91
+ abstract or(right: BitBoard<T> | T | number): this;
92
+ /**
93
+ * Carries out a bitwise xor (^) operation.
94
+ *
95
+ * @param right The right value.
96
+ * @returns The result.
97
+ */
98
+ abstract xor(right: BitBoard<T> | T | number): this;
99
+ /**
100
+ * Carries out a bitwise not (~) operation.
101
+ *
102
+ * @returns The result.
103
+ */
104
+ abstract not(): this;
105
+ /**
106
+ * Carries out a bitwise left shift (<<) operation.
107
+ *
108
+ * @param shiftAmount How much to shift it by.
109
+ * @returns The result.
110
+ */
111
+ abstract leftShift(shiftAmount: number): this;
112
+ /**
113
+ * Carries out a bitwise logical right shift (>>>) operation.
114
+ *
115
+ * @param shiftAmount How much to shift it by.
116
+ * @returns The result.
117
+ */
118
+ abstract rightShift(shiftAmount: number): this;
119
+ /**
120
+ * Carries out a bitwise arithmetic right shift (>>) operation.
121
+ *
122
+ * @param shiftAmount How much to shift it by.
123
+ * @returns The result.
124
+ */
125
+ abstract arithmeticRightShift(shiftAmount: number): this;
126
+ /**
127
+ * Checks if two BitBoards have equal data values.
128
+ *
129
+ * @param value The value to compare against.
130
+ * @returns Whether or not the two BitBoard have the same data value.
131
+ */
132
+ abstract equals(value: BitBoard<T> | T | number): boolean;
133
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Represents a BitBoard.
3
+ *
4
+ * @link https://en.wikipedia.org/wiki/Bitboard
5
+ */
6
+ export default class BitBoard {
7
+ /**
8
+ * The numeric data.
9
+ */
10
+ _data;
11
+ /**
12
+ * Creates an instance of BitBoard.
13
+ *
14
+ * @param data The data to assign to the BitBoard.
15
+ */
16
+ constructor(data) {
17
+ this._data = data;
18
+ }
19
+ /**
20
+ * Gets the numeric data.
21
+ */
22
+ get data() {
23
+ return this._data;
24
+ }
25
+ /**
26
+ * Returns a string representation of the BitBoard.
27
+ *
28
+ * @param type The base of the string to print.
29
+ * @returns The string representation.
30
+ */
31
+ toString(type = 16) {
32
+ let padLength = 0;
33
+ switch (type) {
34
+ case 2:
35
+ padLength = 32;
36
+ break;
37
+ case 10:
38
+ padLength = 10;
39
+ break;
40
+ case 16:
41
+ padLength = 8;
42
+ break;
43
+ }
44
+ return this._data.toString(type).padStart(padLength, "0");
45
+ }
46
+ /**
47
+ * Assigns a given bit a given value.
48
+ *
49
+ * @param bit The x coordinate.
50
+ * @param value The value to assign to the bit.
51
+ */
52
+ assignBit(bit, value) {
53
+ return value === 0 ? this.clearBit(bit) : this.setBit(bit);
54
+ }
55
+ }
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0Qm9hcmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYml0Qm9hcmQvYml0Qm9hcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0E7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQWdCLFFBQVE7SUFDbEM7O09BRUc7SUFDTyxLQUFLLENBQUk7SUFFbkI7Ozs7T0FJRztJQUNILFlBQXNCLElBQU87UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7SUFDdEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBVyxJQUFJO1FBQ1gsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLFFBQVEsQ0FBQyxPQUFtQixFQUFFO1FBQ2pDLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztRQUNsQixRQUFRLElBQUksRUFBRSxDQUFDO1lBQ1gsS0FBSyxDQUFDO2dCQUNGLFNBQVMsR0FBRyxFQUFFLENBQUM7Z0JBQ2YsTUFBTTtZQUNWLEtBQUssRUFBRTtnQkFDSCxTQUFTLEdBQUcsRUFBRSxDQUFDO2dCQUNmLE1BQU07WUFDVixLQUFLLEVBQUU7Z0JBQ0gsU0FBUyxHQUFHLENBQUMsQ0FBQztnQkFDZCxNQUFNO1FBQ2QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxTQUFTLENBQUMsR0FBVyxFQUFFLEtBQVk7UUFDdEMsT0FBTyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9ELENBQUM7Q0FnSEoiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSBMb25nSW50IGZyb20gXCIuL2xvbmdJbnQuanNcIjtcbmltcG9ydCB0eXBlIHsgU3RyaW5nVHlwZSB9IGZyb20gXCIuL2xvbmdJbnQuanNcIjtcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgQml0Qm9hcmQuXG4gKlxuICogQGxpbmsgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQml0Ym9hcmRcbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgQml0Qm9hcmQ8VCBleHRlbmRzIExvbmdJbnQgfCBudW1iZXIgPSBMb25nSW50IHwgbnVtYmVyPiB7XG4gICAgLyoqXG4gICAgICogVGhlIG51bWVyaWMgZGF0YS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX2RhdGE6IFQ7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEJpdEJvYXJkLlxuICAgICAqXG4gICAgICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gYXNzaWduIHRvIHRoZSBCaXRCb2FyZC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoZGF0YTogVCkge1xuICAgICAgICB0aGlzLl9kYXRhID0gZGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBudW1lcmljIGRhdGEuXG4gICAgICovXG4gICAgcHVibGljIGdldCBkYXRhKCk6IFQge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBCaXRCb2FyZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0eXBlIFRoZSBiYXNlIG9mIHRoZSBzdHJpbmcgdG8gcHJpbnQuXG4gICAgICogQHJldHVybnMgVGhlIHN0cmluZyByZXByZXNlbnRhdGlvbi5cbiAgICAgKi9cbiAgICBwdWJsaWMgdG9TdHJpbmcodHlwZTogU3RyaW5nVHlwZSA9IDE2KTogc3RyaW5nIHtcbiAgICAgICAgbGV0IHBhZExlbmd0aCA9IDA7XG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIHBhZExlbmd0aCA9IDMyO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgICAgICBwYWRMZW5ndGggPSAxMDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgMTY6XG4gICAgICAgICAgICAgICAgcGFkTGVuZ3RoID0gODtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fZGF0YS50b1N0cmluZyh0eXBlKS5wYWRTdGFydChwYWRMZW5ndGgsIFwiMFwiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBc3NpZ25zIGEgZ2l2ZW4gYml0IGEgZ2l2ZW4gdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYml0IFRoZSB4IGNvb3JkaW5hdGUuXG4gICAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZSB0byBhc3NpZ24gdG8gdGhlIGJpdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXNzaWduQml0KGJpdDogbnVtYmVyLCB2YWx1ZTogMCB8IDEpOiB2b2lkIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSAwID8gdGhpcy5jbGVhckJpdChiaXQpIDogdGhpcy5zZXRCaXQoYml0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgZ2l2ZW4gYml0LCBiYXNlZCBvbiBpdCdzIHgsIHkgY29vcmRpbmF0ZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYml0IFRoZSBpbmRleCBvZiB0aGUgYml0IHRvIGdldCwgMCA9IExTQi5cbiAgICAgKiBAcmV0dXJucyBUaGUgYml0LlxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBnZXRCaXQoYml0OiBudW1iZXIpOiAwIHwgMTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBnaXZlbiBiaXQgKGNoYW5nZXMgdGhlIHZhbHVlIHRvIDEpLCBiYXNlZCBvbiBpdCdzIHgsIHkgY29vcmRpbmF0ZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYml0IFRoZSBpbmRleCBvZiB0aGUgYml0IHRvIGdldCwgMCA9IExTQi5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3Qgc2V0Qml0KGJpdDogbnVtYmVyKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIENsZWFycyBhIGdpdmVuIGJpdCAoY2hhbmdlcyB0aGUgdmFsdWUgdG8gMCksIGJhc2VkIG9uIGl0J3MgeCwgeSBjb29yZGluYXRlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBiaXQgVGhlIGluZGV4IG9mIHRoZSBiaXQgdG8gZ2V0LCAwID0gTFNCLlxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBjbGVhckJpdChiaXQ6IG51bWJlcik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIGEgZ2l2ZW4gYml0IChjaGFuZ2VzIHRoZSB2YWx1ZSBmcm9tIDAgdG8gMSBvciAxIHRvIDApLCBiYXNlZCBvbiBpdCdzIHgsIHkgY29vcmRpbmF0ZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYml0IFRoZSBpbmRleCBvZiB0aGUgYml0IHRvIGdldCwgMCA9IExTQi5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgdG9nZ2xlQml0KGJpdDogbnVtYmVyKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIENsZWFycyB0aGUgd2hvbGUgQml0Qm9hcmQgKHNldHMgYWxsIHZhbHVlcyB0byAwKS5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgY2xlYXJBbGwoKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgd2hvbGUgQml0Qm9hcmQgKHNldHMgYWxsIHZhbHVlcyB0byAxKS5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3Qgc2V0QWxsKCk6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgcmFuZ2Ugb2YgYml0cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBMU0IgVGhlIGxlYXN0IHNpZ25pZmljYW50IGJpdC5cbiAgICAgKiBAcGFyYW0gbnVtYmVyT2ZCaXRzIFRoZSBudW1iZXIgb2YgYml0cyB0byBnZXQuXG4gICAgICogQHJldHVybnMgVGhlIHJhbmdlIG9mIGJpdHMuXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IGdldEJpdHMoTFNCOiBudW1iZXIsIG51bWJlck9mQml0czogbnVtYmVyKTogVDtcblxuICAgIC8qKlxuICAgICAqIENhcnJpZXMgb3V0IGEgYml0d2lzZSBhbmQgKCYpIG9wZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByaWdodCBUaGUgcmlnaHQgdmFsdWUuXG4gICAgICogQHJldHVybnMgVGhlIHJlc3VsdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgYW5kKHJpZ2h0OiBCaXRCb2FyZDxUPiB8IFQgfCBudW1iZXIpOiB0aGlzO1xuXG4gICAgLyoqXG4gICAgICogQ2FycmllcyBvdXQgYSBiaXR3aXNlIG9yICh8KSBvcGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmlnaHQgVGhlIHJpZ2h0IHZhbHVlLlxuICAgICAqIEByZXR1cm5zIFRoZSByZXN1bHQuXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IG9yKHJpZ2h0OiBCaXRCb2FyZDxUPiB8IFQgfCBudW1iZXIpOiB0aGlzO1xuXG4gICAgLyoqXG4gICAgICogQ2FycmllcyBvdXQgYSBiaXR3aXNlIHhvciAoXikgb3BlcmF0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHJpZ2h0IFRoZSByaWdodCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyBUaGUgcmVzdWx0LlxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCB4b3IocmlnaHQ6IEJpdEJvYXJkPFQ+IHwgVCB8IG51bWJlcik6IHRoaXM7XG5cbiAgICAvKipcbiAgICAgKiBDYXJyaWVzIG91dCBhIGJpdHdpc2Ugbm90ICh+KSBvcGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgcmVzdWx0LlxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBub3QoKTogdGhpcztcblxuICAgIC8qKlxuICAgICAqIENhcnJpZXMgb3V0IGEgYml0d2lzZSBsZWZ0IHNoaWZ0ICg8PCkgb3BlcmF0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHNoaWZ0QW1vdW50IEhvdyBtdWNoIHRvIHNoaWZ0IGl0IGJ5LlxuICAgICAqIEByZXR1cm5zIFRoZSByZXN1bHQuXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IGxlZnRTaGlmdChzaGlmdEFtb3VudDogbnVtYmVyKTogdGhpcztcblxuICAgIC8qKlxuICAgICAqIENhcnJpZXMgb3V0IGEgYml0d2lzZSBsb2dpY2FsIHJpZ2h0IHNoaWZ0ICg+Pj4pIG9wZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzaGlmdEFtb3VudCBIb3cgbXVjaCB0byBzaGlmdCBpdCBieS5cbiAgICAgKiBAcmV0dXJucyBUaGUgcmVzdWx0LlxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCByaWdodFNoaWZ0KHNoaWZ0QW1vdW50OiBudW1iZXIpOiB0aGlzO1xuXG4gICAgLyoqXG4gICAgICogQ2FycmllcyBvdXQgYSBiaXR3aXNlIGFyaXRobWV0aWMgcmlnaHQgc2hpZnQgKD4+KSBvcGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc2hpZnRBbW91bnQgSG93IG11Y2ggdG8gc2hpZnQgaXQgYnkuXG4gICAgICogQHJldHVybnMgVGhlIHJlc3VsdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgYXJpdGhtZXRpY1JpZ2h0U2hpZnQoc2hpZnRBbW91bnQ6IG51bWJlcik6IHRoaXM7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgdHdvIEJpdEJvYXJkcyBoYXZlIGVxdWFsIGRhdGEgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlIGFnYWluc3QuXG4gICAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgdGhlIHR3byBCaXRCb2FyZCBoYXZlIHRoZSBzYW1lIGRhdGEgdmFsdWUuXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IGVxdWFscyh2YWx1ZTogQml0Qm9hcmQ8VD4gfCBUIHwgbnVtYmVyKTogYm9vbGVhbjtcbn1cbiJdfQ==
@@ -0,0 +1,27 @@
1
+ import BitBoard from "./bitBoard.js";
2
+ /**
3
+ * Represents a BitBoard which uses just one 32-bit number.
4
+ */
5
+ export default class IntBitBoard extends BitBoard<number> {
6
+ /**
7
+ * Creates an instance of NumberBitBoard.
8
+ *
9
+ * @param data The data to fill the BitBoard with.
10
+ */
11
+ constructor(data?: number);
12
+ getBit(bit: number): 0 | 1;
13
+ setBit(bit: number): void;
14
+ clearBit(bit: number): void;
15
+ toggleBit(bit: number): void;
16
+ clearAll(): void;
17
+ setAll(): void;
18
+ getBits(LSB: number, numberOfBits: number): number;
19
+ and(right: IntBitBoard | number): this;
20
+ or(right: IntBitBoard | number): this;
21
+ xor(right: IntBitBoard | number): this;
22
+ not(): this;
23
+ leftShift(shiftAmount: number): this;
24
+ rightShift(shiftAmount: number): this;
25
+ arithmeticRightShift(shiftAmount: number): this;
26
+ equals(value: IntBitBoard | number): boolean;
27
+ }
@@ -0,0 +1,65 @@
1
+ import BitBoard from "./bitBoard.js";
2
+ /**
3
+ * Represents a BitBoard which uses just one 32-bit number.
4
+ */
5
+ export default class IntBitBoard extends BitBoard {
6
+ /**
7
+ * Creates an instance of NumberBitBoard.
8
+ *
9
+ * @param data The data to fill the BitBoard with.
10
+ */
11
+ constructor(data = 0) {
12
+ super(data);
13
+ }
14
+ getBit(bit) {
15
+ return (this._data >>> bit & 1);
16
+ }
17
+ setBit(bit) {
18
+ const mask = 1 << bit;
19
+ this._data |= mask;
20
+ }
21
+ clearBit(bit) {
22
+ const mask = ~(1 << bit);
23
+ this._data &= mask;
24
+ }
25
+ toggleBit(bit) {
26
+ const mask = 1 << bit;
27
+ this._data ^= mask;
28
+ }
29
+ clearAll() {
30
+ this._data = 0;
31
+ }
32
+ setAll() {
33
+ this._data = ~0 >>> 0;
34
+ }
35
+ getBits(LSB, numberOfBits) {
36
+ const mask = 2 ** numberOfBits - 1 << LSB;
37
+ const bits = (this._data & mask) >>> LSB;
38
+ return bits;
39
+ }
40
+ and(right) {
41
+ return new IntBitBoard(this._data & (right instanceof IntBitBoard ? right.data : right));
42
+ }
43
+ or(right) {
44
+ return new IntBitBoard(this._data | (right instanceof IntBitBoard ? right.data : right));
45
+ }
46
+ xor(right) {
47
+ return new IntBitBoard(this._data ^ (right instanceof IntBitBoard ? right.data : right));
48
+ }
49
+ not() {
50
+ return new IntBitBoard(~this._data);
51
+ }
52
+ leftShift(shiftAmount) {
53
+ return new IntBitBoard(this._data << shiftAmount);
54
+ }
55
+ rightShift(shiftAmount) {
56
+ return new IntBitBoard(this._data >>> shiftAmount);
57
+ }
58
+ arithmeticRightShift(shiftAmount) {
59
+ return new IntBitBoard(this._data >> shiftAmount);
60
+ }
61
+ equals(value) {
62
+ return this._data === (value instanceof IntBitBoard ? value._data : value);
63
+ }
64
+ }
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50Qml0Qm9hcmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYml0Qm9hcmQvaW50Qml0Qm9hcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxRQUFRLE1BQU0sZUFBZSxDQUFDO0FBRXJDOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxXQUFZLFNBQVEsUUFBZ0I7SUFDckQ7Ozs7T0FJRztJQUNILFlBQW1CLE9BQWUsQ0FBQztRQUMvQixLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEIsQ0FBQztJQUVNLE1BQU0sQ0FBQyxHQUFXO1FBQ3JCLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQVUsQ0FBQztJQUM3QyxDQUFDO0lBRU0sTUFBTSxDQUFDLEdBQVc7UUFDckIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQztRQUN0QixJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQztJQUN2QixDQUFDO0lBRU0sUUFBUSxDQUFDLEdBQVc7UUFDdkIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQztJQUN2QixDQUFDO0lBRU0sU0FBUyxDQUFDLEdBQVc7UUFDeEIsTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQztRQUN0QixJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQztJQUN2QixDQUFDO0lBRU0sUUFBUTtRQUNYLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLENBQUM7SUFFTSxNQUFNO1FBQ1QsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVNLE9BQU8sQ0FBQyxHQUFXLEVBQUUsWUFBb0I7UUFDNUMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLFlBQVksR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDO1FBQzFDLE1BQU0sSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUM7UUFDekMsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVNLEdBQUcsQ0FBQyxLQUEyQjtRQUNsQyxPQUFPLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxLQUFLLFlBQVksV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBUyxDQUFDO0lBQ3JHLENBQUM7SUFFTSxFQUFFLENBQUMsS0FBMkI7UUFDakMsT0FBTyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsS0FBSyxZQUFZLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQVMsQ0FBQztJQUNyRyxDQUFDO0lBRU0sR0FBRyxDQUFDLEtBQTJCO1FBQ2xDLE9BQU8sSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLEtBQUssWUFBWSxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFTLENBQUM7SUFDckcsQ0FBQztJQUVNLEdBQUc7UUFDTixPQUFPLElBQUksV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBUyxDQUFDO0lBQ2hELENBQUM7SUFFTSxTQUFTLENBQUMsV0FBbUI7UUFDaEMsT0FBTyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLFdBQVcsQ0FBUyxDQUFDO0lBQzlELENBQUM7SUFFTSxVQUFVLENBQUMsV0FBbUI7UUFDakMsT0FBTyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLFdBQVcsQ0FBUyxDQUFDO0lBQy9ELENBQUM7SUFFTSxvQkFBb0IsQ0FBQyxXQUFtQjtRQUMzQyxPQUFPLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksV0FBVyxDQUFTLENBQUM7SUFDOUQsQ0FBQztJQUVNLE1BQU0sQ0FBQyxLQUEyQjtRQUNyQyxPQUFPLElBQUksQ0FBQyxLQUFLLEtBQUssQ0FBQyxLQUFLLFlBQVksV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvRSxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQml0Qm9hcmQgZnJvbSBcIi4vYml0Qm9hcmQuanNcIjtcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgQml0Qm9hcmQgd2hpY2ggdXNlcyBqdXN0IG9uZSAzMi1iaXQgbnVtYmVyLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnRCaXRCb2FyZCBleHRlbmRzIEJpdEJvYXJkPG51bWJlcj4ge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTnVtYmVyQml0Qm9hcmQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBmaWxsIHRoZSBCaXRCb2FyZCB3aXRoLlxuICAgICAqL1xuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihkYXRhOiBudW1iZXIgPSAwKSB7XG4gICAgICAgIHN1cGVyKGRhdGEpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRCaXQoYml0OiBudW1iZXIpOiAwIHwgMSB7XG4gICAgICAgIHJldHVybiAodGhpcy5fZGF0YSA+Pj4gYml0ICYgMSkgYXMgMCB8IDE7XG4gICAgfVxuXG4gICAgcHVibGljIHNldEJpdChiaXQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBtYXNrID0gMSA8PCBiaXQ7XG4gICAgICAgIHRoaXMuX2RhdGEgfD0gbWFzaztcbiAgICB9XG5cbiAgICBwdWJsaWMgY2xlYXJCaXQoYml0OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbWFzayA9IH4oMSA8PCBiaXQpO1xuICAgICAgICB0aGlzLl9kYXRhICY9IG1hc2s7XG4gICAgfVxuXG4gICAgcHVibGljIHRvZ2dsZUJpdChiaXQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBtYXNrID0gMSA8PCBiaXQ7XG4gICAgICAgIHRoaXMuX2RhdGEgXj0gbWFzaztcbiAgICB9XG5cbiAgICBwdWJsaWMgY2xlYXJBbGwoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2RhdGEgPSAwO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRBbGwoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2RhdGEgPSB+MCA+Pj4gMDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0Qml0cyhMU0I6IG51bWJlciwgbnVtYmVyT2ZCaXRzOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBjb25zdCBtYXNrID0gMiAqKiBudW1iZXJPZkJpdHMgLSAxIDw8IExTQjtcbiAgICAgICAgY29uc3QgYml0cyA9ICh0aGlzLl9kYXRhICYgbWFzaykgPj4+IExTQjtcbiAgICAgICAgcmV0dXJuIGJpdHM7XG4gICAgfVxuXG4gICAgcHVibGljIGFuZChyaWdodDogSW50Qml0Qm9hcmQgfCBudW1iZXIpOiB0aGlzIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRCaXRCb2FyZCh0aGlzLl9kYXRhICYgKHJpZ2h0IGluc3RhbmNlb2YgSW50Qml0Qm9hcmQgPyByaWdodC5kYXRhIDogcmlnaHQpKSBhcyB0aGlzO1xuICAgIH1cblxuICAgIHB1YmxpYyBvcihyaWdodDogSW50Qml0Qm9hcmQgfCBudW1iZXIpOiB0aGlzIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRCaXRCb2FyZCh0aGlzLl9kYXRhIHwgKHJpZ2h0IGluc3RhbmNlb2YgSW50Qml0Qm9hcmQgPyByaWdodC5kYXRhIDogcmlnaHQpKSBhcyB0aGlzO1xuICAgIH1cblxuICAgIHB1YmxpYyB4b3IocmlnaHQ6IEludEJpdEJvYXJkIHwgbnVtYmVyKTogdGhpcyB7XG4gICAgICAgIHJldHVybiBuZXcgSW50Qml0Qm9hcmQodGhpcy5fZGF0YSBeIChyaWdodCBpbnN0YW5jZW9mIEludEJpdEJvYXJkID8gcmlnaHQuZGF0YSA6IHJpZ2h0KSkgYXMgdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgbm90KCk6IHRoaXMge1xuICAgICAgICByZXR1cm4gbmV3IEludEJpdEJvYXJkKH50aGlzLl9kYXRhKSBhcyB0aGlzO1xuICAgIH1cblxuICAgIHB1YmxpYyBsZWZ0U2hpZnQoc2hpZnRBbW91bnQ6IG51bWJlcik6IHRoaXMge1xuICAgICAgICByZXR1cm4gbmV3IEludEJpdEJvYXJkKHRoaXMuX2RhdGEgPDwgc2hpZnRBbW91bnQpIGFzIHRoaXM7XG4gICAgfVxuXG4gICAgcHVibGljIHJpZ2h0U2hpZnQoc2hpZnRBbW91bnQ6IG51bWJlcik6IHRoaXMge1xuICAgICAgICByZXR1cm4gbmV3IEludEJpdEJvYXJkKHRoaXMuX2RhdGEgPj4+IHNoaWZ0QW1vdW50KSBhcyB0aGlzO1xuICAgIH1cblxuICAgIHB1YmxpYyBhcml0aG1ldGljUmlnaHRTaGlmdChzaGlmdEFtb3VudDogbnVtYmVyKTogdGhpcyB7XG4gICAgICAgIHJldHVybiBuZXcgSW50Qml0Qm9hcmQodGhpcy5fZGF0YSA+PiBzaGlmdEFtb3VudCkgYXMgdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgZXF1YWxzKHZhbHVlOiBJbnRCaXRCb2FyZCB8IG51bWJlcik6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGF0YSA9PT0gKHZhbHVlIGluc3RhbmNlb2YgSW50Qml0Qm9hcmQgPyB2YWx1ZS5fZGF0YSA6IHZhbHVlKTtcbiAgICB9XG59XG4iXX0=