Merge pull request #6949 from ornicar/chessground-7.8

update to chessground 7.8 (dests and pieces map)
pull/6962/head
Thibault Duplessis 2020-07-08 20:23:02 +02:00 committed by GitHub
commit 982156dfa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 105 additions and 126 deletions

View File

@ -23,8 +23,8 @@
"ceval": "2.0.0",
"chat": "2.0.0",
"chess": "2.0.0",
"chessground": "^7.7.2",
"chessops": "^0.5.0",
"chessground": "^7.8.0",
"chessops": "^0.6.0",
"common": "2.0.0",
"game": "2.0.0",
"nvui": "2.0.0",

View File

@ -275,12 +275,11 @@ export default class AnalyseCtrl {
makeCgOpts(): ChessgroundConfig {
const node = this.node,
color = this.turnColor(),
emptyDests = {} as cg.Dests,
dests = chessUtil.readDests(this.node.dests),
drops = chessUtil.readDrops(this.node.drops),
movableColor = (this.practice || this.gamebookPlay()) ? this.bottomColor() : (
!this.embed && (
(dests && Object.keys(dests).length > 0) ||
(dests && dests.size > 0) ||
drops === null || drops.length
) ? color : undefined),
config: ChessgroundConfig = {
@ -288,10 +287,10 @@ export default class AnalyseCtrl {
turnColor: color,
movable: this.embed ? {
color: undefined,
dests: emptyDests,
dests: new Map(),
} : {
color: movableColor,
dests: (movableColor === color && dests) || emptyDests,
dests: (movableColor === color && dests) || new Map(),
},
check: !!node.check,
lastMove: this.uciToLastMove(node.uci)
@ -462,7 +461,7 @@ export default class AnalyseCtrl {
userMove = (orig: Key, dest: Key, capture?: JustCaptured): void => {
this.justPlayed = orig;
this.justDropped = undefined;
const piece = this.chessground.state.pieces[dest];
const piece = this.chessground.state.pieces.get(dest);
const isCapture = capture || (piece && piece.role == 'pawn' && orig[0] != dest[0]);
this.sound[isCapture ? 'capture' : 'move']();
if (!promotion.start(this, orig, dest, capture, this.sendMove)) this.sendMove(orig, dest, capture);
@ -759,8 +758,8 @@ export default class AnalyseCtrl {
const move = parseUci(uci)!;
const to = makeSquare(move.to);
if (isNormal(move)) {
const piece = this.chessground.state.pieces[makeSquare(move.from)];
const capture = this.chessground.state.pieces[to];
const piece = this.chessground.state.pieces.get(makeSquare(move.from));
const capture = this.chessground.state.pieces.get(to);
this.sendMove(makeSquare(move.from), to, (capture && piece && capture.color !== piece.color) ? capture : undefined, move.promotion);
} else this.chessground.newPiece({
color: this.chessground.state.movable.color as Color,

View File

@ -24,15 +24,13 @@ export function render(ctrl: AnalyseCtrl): VNode {
}
export function promote(ground: CgApi, key: Key, role: cg.Role) {
const pieces = {};
const piece = ground.state.pieces[key];
const piece = ground.state.pieces.get(key);
if (piece && piece.role == 'pawn') {
pieces[key] = {
ground.setPieces(new Map([[key, {
color: piece.color,
role,
promoted: true
};
ground.setPieces(pieces);
promoted: true,
}]]));
}
}

View File

@ -18,8 +18,8 @@ type Callback = (orig: Key, dest: Key, capture: JustCaptured | undefined, role:
let promoting: Promoting | undefined;
export function start(ctrl: AnalyseCtrl, orig: Key, dest: Key, capture: JustCaptured | undefined, callback: Callback): boolean {
var s = ctrl.chessground.state;
var piece = s.pieces[dest];
const s = ctrl.chessground.state;
const piece = s.pieces.get(dest);
if (piece && piece.role == 'pawn' && (
(dest[1] == '8' && s.turnColor == 'black') ||
(dest[1] == '1' && s.turnColor == 'white'))) {

View File

@ -25,7 +25,7 @@
"typescript": "^3"
},
"dependencies": {
"chessops": "^0.5.0",
"chessops": "^0.6.0",
"common": "2.0.0",
"snabbdom": "^0.7.4"
}

View File

@ -6,22 +6,20 @@ export function fixCrazySan(san: San): San {
return san[0] === 'P' ? san.slice(1) : san;
}
export interface Dests {
[square: string]: Key[];
}
export type Dests = Map<Key, Key[]>;
export function readDests(lines?: string): Dests | null {
if (typeof lines === 'undefined') return null;
const dests: Dests = {};
if (lines) lines.split(' ').forEach(line => {
dests[piotr[line[0]]] = line.slice(1).split('').map(c => piotr[c]);
});
const dests = new Map();
if (lines) for (const line of lines.split(' ')) {
dests.set(piotr[line[0]], line.slice(1).split('').map(c => piotr[c]));
}
return dests;
}
export function readDrops(line?: string | null): string[] | null {
export function readDrops(line?: string | null): Key[] | null {
if (typeof line === 'undefined' || line === null) return null;
return line.match(/.{2}/g) || [];
return line.match(/.{2}/g) as Key[] || [];
}
export const altCastles = {

View File

@ -15,8 +15,8 @@
"@build/rollupProject": "2.0.0"
},
"dependencies": {
"chessground": "^7.7.2",
"chessops": "^0.5.0",
"chessground": "^7.8.0",
"chessops": "^0.6.0",
"snabbdom": "^0.7.4",
"common": "2.0.0"
},

View File

@ -60,7 +60,7 @@ function onMouseEvent(ctrl: EditorCtrl): (e: MouchEvent) => void {
if (e.type === 'mousedown' || e.type === 'touchstart') downKey = key;
if (sel === 'trash') deleteOrHidePiece(ctrl, key, e);
else {
const existingPiece = ctrl.chessground!.state.pieces[key];
const existingPiece = ctrl.chessground!.state.pieces.get(key);
const piece = {
color: sel[0],
role: sel[1]
@ -73,9 +73,7 @@ function onMouseEvent(ctrl: EditorCtrl): (e: MouchEvent) => void {
const endEvents = { mousedown: 'mouseup', touchstart: 'touchend' };
document.addEventListener(endEvents[e.type], () => placeDelete = false, { once: true });
} else if (!placeDelete && (e.type === 'mousedown' || e.type === 'touchstart' || key !== lastKey)) {
ctrl.chessground!.setPieces({
[key]: piece
});
ctrl.chessground!.setPieces(new Map([[key, piece]]));
ctrl.onChange();
ctrl.chessground!.cancelMove();
}
@ -98,7 +96,7 @@ function onMouseEvent(ctrl: EditorCtrl): (e: MouchEvent) => void {
function deleteOrHidePiece(ctrl: EditorCtrl, key: Key, e: Event): void {
if (e.type === 'touchstart') {
if (ctrl.chessground!.state.pieces[key]) {
if (ctrl.chessground!.state.pieces.has(key)) {
(ctrl.chessground!.state.draggable.current!.element as HTMLElement).style.display = 'none';
ctrl.chessground!.cancelMove();
}
@ -109,9 +107,7 @@ function deleteOrHidePiece(ctrl: EditorCtrl, key: Key, e: Event): void {
}
function deletePiece(ctrl: EditorCtrl, key: Key): void {
ctrl.chessground!.setPieces({
[key]: undefined
});
ctrl.chessground!.setPieces(new Map([[key, undefined]]));
ctrl.onChange();
}

View File

@ -18,7 +18,7 @@
"@types/lichess": "2.0.0"
},
"dependencies": {
"chessground": "^7.7.2",
"chessground": "^7.8.0",
"common": "2.0.0",
"snabbdom": "^0.7.4"
},

View File

@ -1,6 +1,6 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { Piece, Pieces } from 'chessground/types';
import { Pieces } from 'chessground/types';
import { invRanks, allKeys } from 'chessground/util';
import { Setting, makeSetting } from './setting';
import { files } from 'chessground/types';
@ -61,8 +61,8 @@ export function renderPieces(pieces: Pieces, style: Style): VNode {
const lists: any = [];
['king', 'queen', 'rook', 'bishop', 'knight', 'pawn'].forEach(role => {
const keys = [];
for (let key in pieces) {
if (pieces[key]!.color === color && pieces[key]!.role === role) keys.push(key);
for (const [key, piece] of pieces) {
if (piece.color === color && piece.role === role) keys.push(key);
}
if (keys.length) lists.push([`${role}${keys.length > 1 ? 's' : ''}`, ...keys]);
});
@ -76,20 +76,19 @@ export function renderPieces(pieces: Pieces, style: Style): VNode {
}
export function renderPieceKeys(pieces: Pieces, p: string, style: Style): string {
let name = `${p === p.toUpperCase() ? 'white' : 'black'} ${roles[p.toUpperCase()]}`;
let res: Key[] = [], piece: Piece | undefined;
for (let k in pieces) {
piece = pieces[k];
const name = `${p === p.toUpperCase() ? 'white' : 'black'} ${roles[p.toUpperCase()]}`;
const res: Key[] = [];
for (const [k, piece] of pieces) {
if (piece && `${piece.color} ${piece.role}` === name) res.push(k as Key);
}
return `${name}: ${res.length ? res.map(k => renderKey(k, style)).join(', ') : 'none'}`;
}
export function renderPiecesOn(pieces: Pieces, rankOrFile: string, style: Style): string {
let res: string[] = [], piece: Piece | undefined;
for (let k of allKeys) {
const res: string[] = [];
for (const k of allKeys) {
if (k.includes(rankOrFile)) {
piece = pieces[k];
const piece = pieces.get(k);
if (piece) res.push(`${renderKey(k, style)} ${piece.color} ${piece.role}`);
}
}
@ -101,8 +100,8 @@ export function renderBoard(pieces: Pieces, pov: Color): string {
for (let rank of invRanks) {
let line = [];
for (let file of files) {
let key = file + rank;
const piece = pieces[key];
let key = file + rank as Key;
const piece = pieces.get(key);
if (piece) {
const letter = letters[piece.role];
line.push(piece.color === 'white' ? letter.toUpperCase() : letter);

View File

@ -19,8 +19,8 @@
},
"dependencies": {
"ceval": "2.0.0",
"chessground": "^7.7.2",
"chessops": "^0.5.0",
"chessground": "^7.8.0",
"chessops": "^0.6.0",
"common": "2.0.0",
"snabbdom": "^0.7.4",
"tree": "2.0.0"

View File

@ -16,7 +16,7 @@ import { parseSquare, parseUci, makeSquare, makeUci } from 'chessops/util';
import { parseFen, makeFen } from 'chessops/fen';
import { makeSanAndPlay } from 'chessops/san';
import { Chess } from 'chessops/chess';
import { chessgroundDests, scalachessId } from 'chessops/compat';
import { chessgroundDests, scalachessCharPair } from 'chessops/compat';
import { Config as CgConfig } from 'chessground/config';
import { Api as CgApi } from 'chessground/api';
import { Redraw, Vm, Controller, PuzzleOpts, PuzzleData, PuzzleRound, PuzzleVote, MoveTest } from './interfaces';
@ -95,11 +95,11 @@ export default function(opts: PuzzleOpts, redraw: Redraw): Controller {
const color: Color = node.ply % 2 === 0 ? 'white' : 'black';
const dests = chessgroundDests(position());
const movable = (vm.mode === 'view' || color === data.puzzle.color) ? {
color: (Object.keys(dests).length > 0) ? color : undefined,
color: dests.size > 0 ? color : undefined,
dests
} : {
color: undefined,
dests: {}
dests: new Map(),
};
const config = {
fen: node.fen,
@ -154,7 +154,7 @@ export default function(opts: PuzzleOpts, redraw: Redraw): Controller {
addNode({
ply: 2 * (pos.fullmoves - 1) + (pos.turn == 'white' ? 0 : 1),
fen: makeFen(pos.toSetup()),
id: scalachessId(move),
id: scalachessCharPair(move),
uci: makeUci(move),
san,
check: defined(check) ? makeSquare(check) : undefined,

View File

@ -12,7 +12,7 @@ export default function(vm: Vm, getGround: Prop<CgApi>, redraw: Redraw): Promoti
function start(orig: Key, dest: Key, callback: (orig: Key, key: Key, prom: Role) => void) {
const g = getGround(),
piece = g.state.pieces[dest];
piece = g.state.pieces.get(dest);
if (piece && piece.role == 'pawn' && (
(dest[1] == '8' && g.state.turnColor == 'black') ||
(dest[1] == '1' && g.state.turnColor == 'white'))) {
@ -28,15 +28,13 @@ export default function(vm: Vm, getGround: Prop<CgApi>, redraw: Redraw): Promoti
}
function promote(g: CgApi, key: Key, role: Role): void {
const piece = g.state.pieces[key];
const piece = g.state.pieces.get(key);
if (piece && piece.role == 'pawn') {
g.setPieces({
[key]: {
color: piece.color,
role,
promoted: true,
}
});
g.setPieces(new Map([[key, {
color: piece.color,
role,
promoted: true,
}]]));
}
}

View File

@ -17,7 +17,7 @@
},
"dependencies": {
"chat": "2.0.0",
"chessground": "^7.7.2",
"chessground": "^7.8.0",
"common": "2.0.0",
"game": "2.0.0",
"nvui": "2.0.0",

View File

@ -4,21 +4,20 @@ import RoundController from './ctrl';
export function capture(ctrl: RoundController, key: cg.Key) {
const exploding: cg.Key[] = [],
diff: cg.PiecesDiff = {},
diff: cg.PiecesDiff = new Map(),
orig = util.key2pos(key),
minX = Math.max(0, orig[0] - 1),
maxX = Math.min(7, orig[0] + 1),
minY = Math.max(0, orig[1] - 1),
maxY = Math.min(7, orig[1] + 1);
const pieces = ctrl.chessground.state.pieces;
for (let x = minX; x <= maxX; x++) {
for (let y = minY; y <= maxY; y++) {
const k = util.pos2key([x, y]);
exploding.push(k);
const explodes = pieces[k] && (
k === key || pieces[k]!.role !== 'pawn')
if (explodes) diff[k] = undefined;
const p = ctrl.chessground.state.pieces.get(k);
const explodes = p && (k === key || p.role !== 'pawn');
if (explodes) diff.set(k, undefined);
}
}
ctrl.chessground.setPieces(diff);

View File

@ -362,14 +362,13 @@ export default class RoundController {
// Chess960.
const keys = util.uci2move(o.uci)!,
pieces = this.chessground.state.pieces;
if (!o.castle || (pieces[o.castle.king[0]]?.role === 'king' && pieces[o.castle.rook[0]]?.role === 'rook')) {
if (!o.castle || (pieces.get(o.castle.king[0])?.role === 'king' && pieces.get(o.castle.rook[0])?.role === 'rook')) {
this.chessground.move(keys[0], keys[1]);
}
}
if (o.enpassant) {
const p = o.enpassant, pieces: cg.PiecesDiff = {};
pieces[p.key] = undefined;
this.chessground.setPieces(pieces);
const p = o.enpassant;
this.chessground.setPieces(new Map([[p.key, undefined]]));
if (d.game.variant.key === 'atomic') {
atomic.enpassant(this, p.key, p.color);
sound.explode();
@ -379,7 +378,7 @@ export default class RoundController {
this.chessground.set({
turnColor: d.game.player,
movable: {
dests: playing ? util.parsePossibleMoves(d.possibleMoves) : {}
dests: playing ? util.parsePossibleMoves(d.possibleMoves) : new Map(),
},
check: !!o.check
});

View File

@ -37,7 +37,7 @@ export function makeConfig(ctrl: RoundController): Config {
movable: {
free: false,
color: playing ? data.player.color : undefined,
dests: playing ? util.parsePossibleMoves(data.possibleMoves) : {},
dests: playing ? util.parsePossibleMoves(data.possibleMoves) : new Map(),
showDests: data.pref.destination,
rookCastle: data.pref.rookCastle,
events: {
@ -84,15 +84,13 @@ export function reload(ctrl: RoundController) {
}
export function promote(ground: CgApi, key: cg.Key, role: cg.Role) {
const piece = ground.state.pieces[key];
const piece = ground.state.pieces.get(key);
if (piece && piece.role === 'pawn') {
const pieces: cg.Pieces = {};
pieces[key] = {
ground.setPieces(new Map([[key, {
color: piece.color,
role,
promoted: true
};
ground.setPieces(pieces);
promoted: true,
}]]));
}
}

View File

@ -38,10 +38,7 @@ export interface SocketDrop {
export type EncodedDests = string | {
[key: string]: string;
}
export interface DecodedDests {
[key: string]: cg.Key[];
}
export type CgDests = cg.Dests;
export type Dests = cg.Dests;
export interface RoundData extends GameData {
clock?: ClockData;

View File

@ -1,5 +1,5 @@
import sanWriter from './sanWriter';
import { CgDests } from '../interfaces';
import { Dests } from '../interfaces';
const keyRegex = /^[a-h][1-8]$/;
const fileRegex = /^[a-h]$/;
@ -66,8 +66,8 @@ window.lichess.keyboardMove = function(opts: any) {
opts.input.classList.remove('wrong');
};
makeBindings(opts, submit, clear);
return function(fen: string, dests: CgDests, yourMove: boolean) {
sans = dests && Object.keys(dests).length ? sanWriter(fen, destsToUcis(dests)) : null;
return function(fen: string, dests: Dests | undefined, yourMove: boolean) {
sans = dests && dests.size > 0 ? sanWriter(fen, destsToUcis(dests)) : null;
submit(opts.input.value, {
server: true,
yourMove: yourMove
@ -128,14 +128,13 @@ function sanCandidates(san: string, sans) {
});
}
function destsToUcis(dests: CgDests) {
function destsToUcis(dests: Dests) {
const ucis: string[] = [];
Object.keys(dests).forEach(function(orig) {
const d = dests[orig];
if (d) d.forEach(function(dest) {
for (const [orig, d] of dests) {
d.forEach(function(dest) {
ucis.push(orig + dest);
});
});
}
return ucis;
}

View File

@ -10,7 +10,7 @@ import renderCorresClock from '../corresClock/corresClockView';
import { renderResult } from '../view/replay';
import { plyStep } from '../round';
import { onInsert } from '../util';
import { Step, CgDests, Position, Redraw } from '../interfaces';
import { Step, Dests, Position, Redraw } from '../interfaces';
import * as game from 'game';
import { renderSan, renderPieces, renderBoard, styleSetting } from 'nvui/chess';
import { renderSetting } from 'nvui/setting';
@ -204,14 +204,13 @@ function anyClock(ctrl: RoundController, position: Position) {
) || undefined;
}
function destsToUcis(dests: CgDests) {
function destsToUcis(dests: Dests) {
const ucis: string[] = [];
Object.keys(dests).forEach(function(orig) {
const d = dests[orig];
for (const [orig, d] of dests) {
if (d) d.forEach(function(dest) {
ucis.push(orig + dest);
});
});
}
return ucis;
}

View File

@ -26,8 +26,8 @@ export function sendPromotion(ctrl: RoundController, orig: cg.Key, dest: cg.Key,
export function start(ctrl: RoundController, orig: cg.Key, dest: cg.Key, meta: cg.MoveMetadata = {} as cg.MoveMetadata): boolean {
const d = ctrl.data,
piece = ctrl.chessground.state.pieces[dest],
premovePiece = ctrl.chessground.state.pieces[orig];
piece = ctrl.chessground.state.pieces.get(dest),
premovePiece = ctrl.chessground.state.pieces.get(orig);
if (((piece && piece.role === 'pawn' && !premovePiece) || (premovePiece && premovePiece.role === 'pawn')) && (
(dest[1] === '8' && d.player.color === 'white') ||
(dest[1] === '1' && d.player.color === 'black'))) {

View File

@ -3,7 +3,7 @@ import { VNodeData } from 'snabbdom/vnode'
import { Hooks } from 'snabbdom/hooks'
import * as cg from 'chessground/types'
import { opposite } from 'chessground/util';
import { Redraw, EncodedDests, DecodedDests, MaterialDiff, Step, CheckCount } from './interfaces';
import { Redraw, EncodedDests, Dests, MaterialDiff, Step, CheckCount } from './interfaces';
const pieceScores = {
pawn: 1,
@ -44,14 +44,14 @@ export function bind(eventName: string, f: (e: Event) => void, redraw?: Redraw,
});
}
export function parsePossibleMoves(dests?: EncodedDests): DecodedDests {
if (!dests) return {};
const dec: DecodedDests = {};
export function parsePossibleMoves(dests?: EncodedDests): Dests {
const dec = new Map();
if (!dests) return dec;
if (typeof dests == 'string')
dests.split(' ').forEach(ds => {
dec[ds.slice(0,2)] = ds.slice(2).match(/.{2}/g) as cg.Key[];
});
else for (let k in dests) dec[k] = dests[k].match(/.{2}/g) as cg.Key[];
for (const ds of dests.split(' ')) {
dec.set(ds.slice(0,2), ds.slice(2).match(/.{2}/g) as cg.Key[]);
}
else for (const k in dests) dec.set(k, dests[k].match(/.{2}/g) as cg.Key[]);
return dec;
}
@ -61,8 +61,8 @@ export function getMaterialDiff(pieces: cg.Pieces): MaterialDiff {
white: { king: 0, queen: 0, rook: 0, bishop: 0, knight: 0, pawn: 0 },
black: { king: 0, queen: 0, rook: 0, bishop: 0, knight: 0, pawn: 0 },
};
for (let k in pieces) {
const p = pieces[k]!, them = diff[opposite(p.color)];
for (const p of pieces.values()) {
const them = diff[opposite(p.color)];
if (them[p.role] > 0) them[p.role]--;
else diff[p.color][p.role]++;
}
@ -70,9 +70,9 @@ export function getMaterialDiff(pieces: cg.Pieces): MaterialDiff {
}
export function getScore(pieces: cg.Pieces): number {
let score = 0, k;
for (k in pieces) {
score += pieceScores[pieces[k]!.role] * (pieces[k]!.color === 'white' ? 1 : -1);
let score = 0;
for (const p of pieces.values()) {
score += pieceScores[p.role] * (p.color === 'white' ? 1 : -1);
}
return score;
}

View File

@ -49,7 +49,7 @@ export function main(ctrl: RoundController): VNode {
bottomColor = d[ctrl.flip ? 'opponent' : 'player'].color;
let material: MaterialDiff, score: number = 0;
if (d.pref.showCaptured) {
let pieces = cgState ? cgState.pieces : fenRead(plyStep(ctrl.data, ctrl.ply).fen);
const pieces = cgState ? cgState.pieces : fenRead(plyStep(ctrl.data, ctrl.ply).fen);
material = util.getMaterialDiff(pieces);
score = util.getScore(pieces) * (bottomColor === 'white' ? 1 : -1);
} else material = emptyMaterialDiff;

View File

@ -18,7 +18,7 @@
},
"dependencies": {
"chat": "2.0.0",
"chessground": "^7.7.2",
"chessground": "^7.8.0",
"common": "2.0.0",
"game": "2.0.0",
"snabbdom": "^0.7.4"

View File

@ -18,7 +18,7 @@
},
"dependencies": {
"chat": "2.0.0",
"chessground": "^7.7.2",
"chessground": "^7.8.0",
"common": "2.0.0",
"game": "2.0.0",
"snabbdom": "^0.7.4"

View File

@ -907,15 +907,15 @@ chessground@^4.4:
merge "1.2.0"
mithril "github:ornicar/mithril.js#v1.0.1"
chessground@^7.7.2:
version "7.7.2"
resolved "https://registry.yarnpkg.com/chessground/-/chessground-7.7.2.tgz#bded8da6fb582ed256e882dde3b09bdcec4709f1"
integrity sha512-vJMu4tHf6vgzeqZNEZPsHUEy8Z6duZUY6A8j84qq7yC7cs+QQKThQoJEIOXu1rtj3AobRoitPNnSelybplmW0g==
chessground@^7.8.0:
version "7.8.0"
resolved "https://registry.yarnpkg.com/chessground/-/chessground-7.8.0.tgz#f04d301e3eb71c2616306fcc03d4d4aaa5294bcb"
integrity sha512-0BD9Li/N1/4jVOrh823cdQCLr4ElRA0pl+8tehyeMzv/tlOhnOB2E/wVMmJOc/3o7/IJFTPVyr/jaOBuHmSLxQ==
chessops@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/chessops/-/chessops-0.5.0.tgz#da7c01e6d9e72ef2342199f8ae13c5c879a6e9ee"
integrity sha512-CFm10wcnD63Ojna6tI1AnXVpQljufsMjvs6cxQ0AgaCAH5V/mwuNGG6Y90EyBRRKmIb3ypxRj7klIyFB07caYA==
chessops@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/chessops/-/chessops-0.6.0.tgz#6c01536bd029c66c588ddce74ccd96da6dc39f4d"
integrity sha512-U3A5X2aUM/siFi/xCDXpR2YoUrLdRXNNgm3Ybjx9cVqVcaCr/mGrF4i7g2UQZXlwHLY7Ljj4eXbDpL7K8Sc9pA==
dependencies:
"@badrap/result" "^0.2.6"