UNPKG

@wxzqs/chess

Version:

公共象棋工具类

945 lines (938 loc) 30 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Chess = {})); })(this, (function (exports) { 'use strict'; function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) { t && (r = t); var n = 0, F = function () {}; return { s: F, n: function () { return n >= r.length ? { done: true } : { done: false, value: r[n++] }; }, e: function (r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = true, u = false; return { s: function () { t = t.call(r); }, n: function () { var r = t.next(); return a = r.done, r; }, e: function (r) { u = true, o = r; }, f: function () { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _toArray(r) { return _arrayWithHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableRest(); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } var PieceKind = { EMPTY: 0, ROOK: "r", KNIGHT: "n", BISHOP: "b", ADVISOR: "a", KING: "k", CANNON: "c", PAWN: "p" }; var PieceType = { // 红方棋子 WP: "P", WC: "C", WR: "R", WN: "N", WB: "B", WA: "A", WK: "K", // 黑方棋子 BP: "p", BC: "c", BR: "r", BN: "n", BB: "b", BA: "a", BK: "k" }; var Color = { WHITE: "w", BLACK: "b" }; var ICCS_REGEXP = /([a-i][0-9])[-]?([a-i][0-9])/i; var EMPTY_BOARD = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; var ChessUtil = { /** * 校验fen是否有效 * <p> * rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1 * </p> * <p>1part 棋盘信息</p> * <p>2part 红/黑 方</p> * <p>3part 忽略</p> * <p>4part 忽略</p> * <p>5part</p> * <p>6part</p> * */ validateFen: function validateFen(fen) { if (!fen) { return { ok: false, error: "Invalid FEN: fen\u4E0D\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32" }; } var tokens = fen.split(/\s+/); if (tokens.length < 2) { return { ok: false, error: "Invalid FEN: \u5FC5\u987B\u5305\u542B\u4E8C\u8981\u7D20\u4FE1\u606F" }; } var moveNumber = parseInt(tokens[5], 10) || 0; if (isNaN(moveNumber) || moveNumber < 0) { return { ok: false, error: "Invalid FEN: \u79FB\u52A8\u6B65\u6570\u5FC5\u987B\u4E3A\u4E00\u4E2A\u6B63\u6574\u6570" }; } var halfMoves = parseInt(tokens[4], 10) || 1; if (isNaN(halfMoves) || halfMoves < 0) { return { ok: false, error: "Invalid FEN: \u534A\u79FB\u52A8\u8BA1\u6570\u6B65\u6570\u5FC5\u987B\u4E3A\u975E\u8D1F\u6570" }; } if (!/^[wb]$/.test(tokens[1])) { return { ok: false, error: "Invalid FEN: \u8F6E\u5230\u8C01\u884C\u52A8\u503C\u65E0\u6548, \u5FC5\u987B\u4E3Aw \u6216 b" }; } var rows = tokens[0].split("/"); if (rows.length !== 10) { return { ok: false, error: "Invalid FEN: \u68CB\u5B50\u6570\u636E\u5206\u5272\u68CB\u5B50\u65E0\u6548 (\u683C\u5B50\u6570\u636E\u672A\u6EE110)" }; } var _iterator = _createForOfIteratorHelper(rows), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var row = _step.value; var sumFields = 0; var previousWasNumber = false; var _iterator2 = _createForOfIteratorHelper(row), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var element = _step2.value; if (this.isDigit(element)) { if (previousWasNumber) { return { ok: false, error: "Invalid FEN: \u68CB\u5B50\u6570\u636E\u65E0\u6548 (\u7A7A\u683C\u6570\u5B57\u65E0\u6548)" }; } sumFields += parseInt(element, 10); previousWasNumber = true; } else { if (!/^[rnbakcpRNBAKCP]$/.test(element)) { return { ok: false, error: "Invalid FEN: \u68CB\u5B50\u6570\u636E\u65E0\u6548 (\u65E0\u6548\u68CB\u5B50".concat(element, ")") }; } sumFields += 1; previousWasNumber = false; } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } if (sumFields < 9) { return { ok: false, error: "Invalid FEN: \u68CB\u5B50\u6570\u636E\u65E0\u6548 (\u683C\u5B50\u6570\u636E\u5C0F\u4E8E9\u5217)" }; } else if (sumFields > 9) { return { ok: false, error: "Invalid FEN: \u68CB\u5B50\u6570\u636E\u65E0\u6548 (\u683C\u5B50\u6570\u636E\u5927\u4E8E9\u5217)" }; } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } var kings = [{ color: "\u7EA2\u65B9", regex: /K/g }, { color: "\u9ED1\u65B9", regex: /k/g }]; for (var _i = 0, _kings = kings; _i < _kings.length; _i++) { var _kings$_i = _kings[_i], color = _kings$_i.color, regex = _kings$_i.regex; if (!regex.test(tokens[0])) { return { ok: false, error: "Invalid FEN: \u672A\u627E\u5230".concat(color, "\u5C06\u519B") }; } if ((tokens[0].match(regex) || []).length > 1) { return { ok: false, error: "Invalid FEN: \u627E\u5230\u591A\u4E2A".concat(color, "\u5C06\u519B") }; } } var pieces = [{ type: "r", max: 2 }, { type: "n", max: 2 }, { type: "b", max: 2 }, { type: "a", max: 2 }, { type: "k", max: 1 }, { type: "c", max: 2 }, { type: "p", max: 5 }]; var boardPart = tokens[0]; var pieceCount = {}; for (var _i2 = 0, _pieces = pieces; _i2 < _pieces.length; _i2++) { var type = _pieces[_i2].type; pieceCount[type] = 0; pieceCount[type.toUpperCase()] = 0; } for (var i = 0; i < boardPart.length; i++) { var _char = boardPart[i]; if (/^[rnbakcpRNBAKCP]$/.test(_char)) { pieceCount[_char]++; } } for (var _i3 = 0, _pieces2 = pieces; _i3 < _pieces2.length; _i3++) { var _pieces2$_i = _pieces2[_i3], _type = _pieces2$_i.type, max = _pieces2$_i.max; var lowerCaseCount = pieceCount[_type]; var upperCaseCount = pieceCount[_type.toUpperCase()]; if (lowerCaseCount > max || upperCaseCount > max) { return { ok: false, error: "\u68CB\u5C40\u65E0\u6548".concat(_type, "\u68CB\u5B50\u8D85\u51FA\u6700\u5927\u4E2A\u6570") }; } } return { ok: true }; }, /** * 是否为数字 * */ isDigit: function isDigit(c) { return "0123456789".indexOf(c) !== -1; }, /** * 去除fen最后两个的配置信息 * */ trimFen: function trimFen(fen) { return fen.split(/\s+/).slice(0, 4).join(" "); }, /** * 交换棋子颜色 * @param {string} color - 当前棋子的颜色 * @returns {string} - 交换后的棋子颜色 */ swapColor: function swapColor(color) { return color === Color.WHITE ? Color.BLACK : Color.WHITE; }, /** * 获取棋子颜色 * */ getColor: function getColor(piece) { return piece < "a" ? Color.WHITE : Color.BLACK; }, /** * 检查棋子位置是否在棋盘内 * @param {number} left - 棋子的左侧坐标 * @param {number} top - 棋子的顶部坐标 * @param {string} checkType - 可选参数,检查的类型,默认为棋盘检查 * @returns {boolean} - 如果棋子位置在棋盘内则返回 true,否则返回 false */ inBoard: function inBoard(left, top) { var checkType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ChessConstants.CHECK_TYPE_BOARD; if (checkType == ChessConstants.CHECK_TYPE_BOARD) { return left >= 0 && left < ChessConstants.MAX_LEFT && top >= 0 && top < ChessConstants.MAX_TOP; } else if (checkType == ChessConstants.CHECK_TYPE_JIU_GONG) { var jiuGong = { left: 3, redBottom: 7, blackBottom: 0, right: 5, redTop: 9, blackTop: 2 }; if (left < jiuGong.left || left > jiuGong.right) { return false; } return top >= jiuGong.blackBottom && top <= jiuGong.blackTop || top >= jiuGong.redBottom && top <= jiuGong.redTop; } }, /** * 翻转方向 * @param directions 方向 * @param revert 是否翻转(Y轴) * @param revertKeys 翻转字段 * */ transformDirections: function transformDirections(directions, revert) { for (var _len = arguments.length, revertKeys = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { revertKeys[_key - 2] = arguments[_key]; } if (!revert) { return directions; } return directions.map(function (v) { Object.keys(v).forEach(function (key) { if (revertKeys.includes(key)) { v[key] = -v[key]; } }); return v; }); }, /** * 是否过河 * */ isCrossRiver: function isCrossRiver(top, color) { return color === Color.BLACK ? top >= 5 : top <= 4; }, isBing: function isBing(type) { return /^[pP]$/.test(type); }, isPao: function isPao(type) { return /^[cC]$/.test(type); }, isChe: function isChe(type) { return /^[rR]$/.test(type); }, isMa: function isMa(type) { return /^[nN]$/.test(type); }, isXiang: function isXiang(type) { return /^[bB]$/.test(type); }, isShi: function isShi(type) { return /^[aA]$/.test(type); }, isJiang: function isJiang(type) { return /^[kK]$/.test(type); }, /** * 对称棋盘 * */ reverseBoard: function reverseBoard(boardMap) { var reversedExpandedBoard = []; if (!boardMap) { return reversedExpandedBoard; } var _iterator3 = _createForOfIteratorHelper(boardMap), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var row = _step3.value; var reversedRow = []; for (var i = row.length - 1; i >= 0; i--) { reversedRow.push(row[i]); } reversedExpandedBoard.push(reversedRow); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } return reversedExpandedBoard; }, /** * 翻转局面代码 * */ reverseFen: function reverseFen(fen) { if (!fen) { return fen; } var _this$validateFen = this.validateFen(fen), ok = _this$validateFen.ok, error = _this$validateFen.error; if (!ok) { throw new Error(error); } var parts = fen.split(/\s+/); var fenCode = parts[0]; var config = parts.slice(1); var expandedBoard = this.toBoard(fenCode); var reversedExpandedBoard = this.reverseBoard(expandedBoard); var reversedFen = this.toFen(reversedExpandedBoard); return [reversedFen].concat(_toConsumableArray(config)).join(" "); }, /** * 标准棋盘 * */ standardBoard: function standardBoard() { var cols = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]; var rows = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; return rows.map(function (row) { return cols.map(function (col) { return "".concat(col).concat(row); }).join("|"); }).reverse().join("\n"); }, /** * 修复局面代码 * */ fixFen: function fixFen(fen) { if (!fen) { throw new Error("\u5C40\u9762\u4EE3\u7801\u4E0D\u80FD\u4E3A\u7A7A"); } var tokens = fen.split(/\s+/); if (tokens.length >= 1 && tokens.length < 6) { var adjustments = [Color.WHITE, "-", "-", "0", "1"]; fen = tokens.concat(adjustments.slice(-(6 - tokens.length))).join(" "); } return fen; }, /** * 将二维数组转换为局面代码 * */ toFen: function toFen(boardMap) { var fenList = []; if (!boardMap) { return fenList; } for (var rowIndex = 0; rowIndex < 10; rowIndex++) { var fenRow = ""; var emptyCount = 0; for (var colIndex = 0; colIndex < 9; colIndex++) { var cell = boardMap[colIndex][9 - rowIndex]; if (cell === PieceKind.EMPTY) { emptyCount++; } else { if (emptyCount > 0) { fenRow += emptyCount; emptyCount = 0; } fenRow += cell; } } if (emptyCount > 0) { fenRow += emptyCount; } fenList.push(fenRow); } return fenList.join("/"); }, /** * 将局面代码转换为二维数组 * */ toBoard: function toBoard(fen) { fen = fen.split(/\s+/)[0]; var boardList = this.emptyBoard(); if (!fen) { return boardList; } var boardLayout = fen.split("/"); boardLayout.forEach(function (rowStr, rowIndex) { var colIndex = 0; var _iterator4 = _createForOfIteratorHelper(rowStr), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var _char2 = _step4.value; if (/\d/.test(_char2)) { colIndex += parseInt(_char2, 10); } else { boardList[colIndex][9 - rowIndex] = _char2; colIndex++; } } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } }); return boardList; }, // 默认局面代码 defaultFen: function defaultFen() { return "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1"; }, // 空局面代码 emptyFen: function emptyFen() { return "9/9/9/9/9/9/9/9/9/9 w - - 0 1"; }, // 默认局面 defaultBoard: function defaultBoard() { return this.toBoard(this.defaultFen()); }, // 空棋盘 emptyBoard: function emptyBoard() { return EMPTY_BOARD.map(function (row) { return _toConsumableArray(row); }); }, /** * 移动 * @param fen 局面代码 * @param tricks 招数列表 */ move: function move(fen) { if (!fen) { throw new Error("\u5C40\u9762\u4EE3\u7801\u4E0D\u80FD\u4E3A\u7A7A"); } for (var _len2 = arguments.length, tricks = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { tricks[_key2 - 1] = arguments[_key2]; } if (!(tricks !== null && tricks !== void 0 && tricks.length)) return fen; var parts = fen.split(/\s+/); var _parts = _toArray(parts), boardPart = _parts[0], currentPlayer = _parts[1], rest = _parts.slice(2); var board = this.toBoard(boardPart); for (var _i4 = 0, _tricks = tricks; _i4 < _tricks.length; _i4++) { var trick = _tricks[_i4]; var _this$toPos = this.toPos(trick), _this$toPos2 = _slicedToArray(_this$toPos, 4), fromLeft = _this$toPos2[0], fromTop = _this$toPos2[1], toLeft = _this$toPos2[2], toTop = _this$toPos2[3]; var piece = board[fromLeft][fromTop]; board[fromLeft][fromTop] = PieceKind.EMPTY; board[toLeft][toTop] = piece; } var newBoard = this.toFen(board); var newPlayer = ChessUtil.swapColor(currentPlayer); return [newBoard, newPlayer].concat(_toConsumableArray(rest)).join(" "); }, /** * 批量翻译着法 * @param fen 局面代码 * @param tricks 着法数组 iccs * @param format 翻译格式 cn:中文纵线格式 wxf:WXF纵线格式 */ translateBatch: function translateBatch(fen, tricks) { var _this = this; var format = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "cn"; return tricks.map(function (trick, index, array) { var newFen = _this.move.apply(_this, [fen].concat(_toConsumableArray(array.slice(0, index)))); return _this.translate(newFen, trick, format); }); }, /** * 翻译着法 * @param fen 局面代码 * @param trick 着法 iccs * @param format 翻译格式 cn:中文纵线格式 wxf:WXF纵线格式 */ translate: function translate(fen, trick) { var format = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "cn"; var pieceMap = { "R": "\u8F66", "N": "\u9A6C", "B": "\u76F8", "A": "\u4ED5", "K": "\u5E05", "C": "\u70AE", "P": "\u5175", "r": "\u8F66", "n": "\u9A6C", "b": "\u8C61", "a": "\u58EB", "k": "\u5C06", "c": "\u70AE", "p": "\u5352" }; var board = this.toBoard(fen); var _this$toPos3 = this.toPos(trick), _this$toPos4 = _slicedToArray(_this$toPos3, 4), fromLeft = _this$toPos4[0], fromTop = _this$toPos4[1], toLeft = _this$toPos4[2], toTop = _this$toPos4[3]; var piece = board[fromLeft][fromTop]; var isRed = piece === piece.toUpperCase(); var startRoad = isRed ? 9 - fromLeft : fromLeft + 1; var endRoad = isRed ? 9 - toLeft : toLeft + 1; var action, value; if (["R", "C", "K", "P"].includes(piece.toUpperCase())) { if (fromLeft !== toLeft) { action = "\u5E73"; value = endRoad; } else { var steps = Math.abs(toTop - fromTop); var direction = isRed && toTop < fromTop || !isRed && toTop > fromTop ? "\u8FDB" : "\u9000"; action = direction; value = steps; } } else { var _direction = isRed && toTop < fromTop || !isRed && toTop > fromTop ? "\u8FDB" : "\u9000"; action = _direction; value = endRoad; } switch (format) { case "cn": { var chineseNumbers = ["", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D", "\u4E03", "\u516B", "\u4E5D"]; var road = isRed ? chineseNumbers[startRoad] : startRoad; value = isRed ? chineseNumbers[value] : value; var type = pieceMap[piece]; return "".concat(type).concat(road).concat(action).concat(value); } case "wxf": { switch (action) { case "\u8FDB": { action = "+"; break; } case "\u9000": { action = "-"; break; } case "\u5E73": { action = "."; break; } } var _chineseNumbers = ["", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; var _road = isRed ? _chineseNumbers[startRoad] : startRoad; var _type2 = piece.toUpperCase(); return "".concat(_type2).concat(_road).concat(action).concat(value); } default: throw new Error("\u672A\u77E5\u7740\u6CD5\u683C\u5F0F"); } }, // ICCS 坐标转棋盘索引 iccsToPos: function iccsToPos(iccs) { var col = iccs[0].toLowerCase().charCodeAt(0) - "a".charCodeAt(0); var row = parseInt(iccs[1]); return { x: col, y: row }; }, /** * 解析棋盘坐标转为iccs坐标 * */ posToIccs: function posToIccs(x, y) { var col = String.fromCharCode("a".charCodeAt(0) + x); return col + y; }, /** * 解析iccs坐标转为棋盘坐标 */ toPos: function toPos(iccs) { if (!ICCS_REGEXP.test(iccs)) { throw new Error("\u975E\u6CD5iccs\u5750\u6807\u683C\u5F0F"); } var _this$iccsToPos = this.iccsToPos(iccs[0] + iccs[1]), startCol = _this$iccsToPos.x, startRow = _this$iccsToPos.y; var _this$iccsToPos2 = this.iccsToPos(iccs[2] + iccs[3]), endCol = _this$iccsToPos2.x, endRow = _this$iccsToPos2.y; return [startCol, startRow, endCol, endRow]; }, // 起始和目标索引转 ICCS 格式坐标 toIccs: function toIccs(x1, y1, x2, y2) { var startIccs = this.posToIccs(x1, y1); var endIccs = this.posToIccs(x2, y2); return startIccs + endIccs; }, // 比较两个fen的差异,只比较两个局面代码 // difference(startFen, toFen) { // if (!startFen || !toFen) { // throw new Error('前后局面代码不能为空') // } // const startBoard = ChessUtil.toBoard(startFen) // const compareBoard = ChessUtil.toBoard(toFen) // // 查找差异位置 // let changed = {} // let count = 0 // for (let left = 0; left < 9; left++) { // for (let top = 0; top < 10; top++) { // const oldPiece = startBoard[left][top] // const newPiece = compareBoard[left][top] // if (oldPiece !== newPiece) { // count++ // switch (newPiece) { // case PieceKind.EMPTY: { // changed.piece = oldPiece // changed.from = oldPiece // changed.color = this.getColor(changed.piece) // break; // } // default: { // changed.to = newPiece // break; // } // } // } // } // } // if (count === 1) { // return [changed, 'one'] // } else if (count === 2) { // if (changed.from === '' || changed.to === '') { // return [changed, 'one'] // } else { // return [changed, 'move'] // } // } else { // return [changed, 'unknown'] // } // }, difference: function difference(fen, lastFen) { var board = ChessUtil.toBoard(fen); var lastBoard = ChessUtil.toBoard(lastFen); var diffs = []; for (var left = 0; left < 9; left++) { for (var top = 0; top < 10; top++) { var piece = board[left][top]; var lastPiece = lastBoard[left][top]; if (piece !== lastPiece) { diffs.push({ piece: piece, lastPiece: lastPiece, left: left, top: top, color: this.getColor(piece || lastPiece) }); } } } return diffs; }, countPiecesDetail: function countPiecesDetail(fen) { var pieceCount = { red: { R: 0, N: 0, B: 0, A: 0, K: 0, C: 0, P: 0 }, black: { r: 0, n: 0, b: 0, a: 0, k: 0, c: 0, p: 0 } }; var board = fen.split(/\s+/)[0].replace(/\//g, "").replace(/\d/g, function (m) { return "-".repeat(parseInt(m)); }); var _iterator5 = _createForOfIteratorHelper(board), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { var _char3 = _step5.value; if (_char3 === "-") continue; if (/[RNBAKCP]/.test(_char3)) { pieceCount.red[_char3] = (pieceCount.red[_char3] || 0) + 1; } else if (/[rnbakcp]/.test(_char3)) { pieceCount.black[_char3.toLowerCase()] = (pieceCount.black[_char3.toLowerCase()] || 0) + 1; } } } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } return { red: { chariot: pieceCount.red.R, horse: pieceCount.red.N, elephant: pieceCount.red.B, advisor: pieceCount.red.A, king: pieceCount.red.K, cannon: pieceCount.red.C, pawn: pieceCount.red.P }, black: { chariot: pieceCount.black.r, horse: pieceCount.black.n, elephant: pieceCount.black.b, advisor: pieceCount.black.a, king: pieceCount.black.k, cannon: pieceCount.black.c, pawn: pieceCount.black.p } }; }, /** * 返回棋子数 * @return 红方棋子数、黑方棋子数、全部棋子数 * */ countPieces: function countPieces(fen) { var result = this.countPiecesDetail(fen); var red = Object.values(result.red).reduce(function (sum, num) { return sum + num; }, 0); var black = Object.values(result.black).reduce(function (sum, num) { return sum + num; }, 0); return { red: red, black: black, all: red + black }; }, /** * 是否为默认局面 * */ isStartPos: function isStartPos(fen) { return this.fixFen(this.defaultFen()) === this.fixFen(fen); }, /** * 判断是否为iccs坐标 s1s2-t1t2 * */ isIccs: function isIccs(iccs) { return iccs.length < 5 && /[a-iA-I][0-9][-.]?[a-iA-I][0-9]/.test(iccs); }, /** * 获取fen的走棋方 * */ getFenColor: function getFenColor(fen) { if (!fen) { throw new Error("\u5C40\u9762\u4EE3\u7801\u4E0D\u80FD\u4E3A\u7A7A"); } var _this$validateFen2 = this.validateFen(fen), ok = _this$validateFen2.ok, error = _this$validateFen2.error; if (!ok) { throw new Error(error); } return fen.includes(Color.WHITE) ? Color.WHITE : Color.BLACK; } }; exports.ChessUtil = ChessUtil; exports.Color = Color; exports.PieceKind = PieceKind; exports.PieceType = PieceType; exports.default = ChessUtil; Object.defineProperty(exports, '__esModule', { value: true }); }));