将 PGN 转换为 nodejs 中的 FEN 字符串列表(国际象棋符号)
Converting a PGN to a list of FEN strings in nodejs (chess notations)
我正在使用 nodejs 构建一个与国际象棋相关的应用程序。我一直在尝试尽可能多地使用 chess.js
,但我认为我在功能方面遇到了障碍。在扩展该功能之前,我想确保没有其他工具可以满足我的需要。
我正在寻找一种将 PGN 字符串转换为 FEN 动作列表的方法。我希望在 chess.js 中使用 load_pgn()
将移动加载到对象中,然后遍历每个移动并调用 fen()
函数来输出当前的 FEN。但是,chess.js 似乎没有办法完成游戏中的动作。除非我遗漏了什么。
我宁愿不必解析字符串,但如果必须的话,我会的。有什么建议吗?
解法:
另请参阅下面 efirvida 的回答以获得解决方案
像这样的东西(未经测试)似乎有效。该函数接受使用 chess.js
创建的 Chess
对象,该对象已经加载了 PGN。
function getMovesAsFENs(chessObj) {
var moves = chessObj.history();
var newGame = new Chess();
var fens = [];
for (var i = 0; i < moves.length; i++) {
newGame.move(moves[i]);
fens.push(newGame.fen());
}
return fens;
}
查看 github 页面 .load_pgn
link
var chess = new Chess();
pgn = ['[Event "Casual Game"]',
'[Site "Berlin GER"]',
'[Date "1852.??.??"]',
'[EventDate "?"]',
'[Round "?"]',
'[Result "1-0"]',
'[White "Adolf Anderssen"]',
'[Black "Jean Dufresne"]',
'[ECO "C52"]',
'[WhiteElo "?"]',
'[BlackElo "?"]',
'[PlyCount "47"]',
'',
'1.e4 e5 2.Nf3 Nc6 3.Bc4 Bc5 4.b4 Bxb4 5.c3 Ba5 6.d4 exd4 7.O-O',
'd3 8.Qb3 Qf6 9.e5 Qg6 10.Re1 Nge7 11.Ba3 b5 12.Qxb5 Rb8 13.Qa4',
'Bb6 14.Nbd2 Bb7 15.Ne4 Qf5 16.Bxd3 Qh5 17.Nf6+ gxf6 18.exf6',
'Rg8 19.Rad1 Qxf3 20.Rxe7+ Nxe7 21.Qxd7+ Kxd7 22.Bf5+ Ke8',
'23.Bd7+ Kf8 24.Bxe7# 1-0'];
chess.load_pgn(pgn.join('\n'));
// -> true
chess.fen()
// -> 1r3kr1/pbpBBp1p/1b3P2/8/8/2P2q2/P4PPP/3R2K1 b - - 0 24
类似
moves = chess.history();
var chess1 = new Chess();
for (move in moves){
chess1.move(move);
fen = chess1.fen()
}
(不是真正的答案;只是需要额外格式化的评论。)
您的 getMovesAsFENs
函数也可以写成:
function getMovesAsFENs(chessObj) {
return chessObj.history().map(function(move) {
chessObj.move(move);
return chessObj.fen();
});
}
也许你不在乎,但这很符合我的整洁感。
这是添加了一些 ES6 糖的端到端答案:
const Chess = require('chess.js').Chess;
const chess1 = new Chess();
const chess2 = new Chess();
const startPos = chess2.fen();
const pgn = `1.e4 c5 0-1`;
chess1.load_pgn(pgn);
let fens = chess1.history().map(move => {
chess2.move(move);
return chess2.fen();
});
//the above technique will not capture the fen of the starting position. therefore:
fens = [startPos, ...fens];
//double checking everything
fens.forEach(fen => console.log(fen));
"However, chess.js doesn't seem to have a way to walk through the
moves in a game. Unless I'm missing something.".
你是对的(因为我现在已经多次阅读整个图书馆)。所有需要回顾历史的事情基本上都是撤消然后重做动作,没有集成某种真正的导航(以这种方式解决它是一个有趣的选择,它的优点是可以快速完成某些任务,但对于其他看似简单的任务(如您需要的任务)来说,这确实是一种痛苦。
免责声明(我编写了以下工具),我在过去 5 年多的时间里一直在创建一个工具 (isepic-chess.js),类似于 chess.js,我认为它正在慢慢到达那里......库将移动历史存储在一个对象中,其中包含诸如(fen,from_square,to_square,san 等)的信息,并且还有一些类型带有移动索引和一些移动导航助手的“光标”。
因此使用 isepic-chess.js 你可以在解析 PGN 游戏后调用棋盘方法 board.fenHistoryExport()
来获取 FEN 列表:
var example_pgn = `[Event "m1 London"]
[Site "?"]
[Date "1861.07.??"]
[Round "9"]
[White "Kolisch, Ignatz"]
[Black "Anderssen, Adolf"]
[Result "0-1"]
[Annotator "JvR"]
[SetUp "1"]
[FEN "5r1k/pp4pp/3r3q/8/3PpP1P/1P2NbP1/PB1Q3K/R7 b - - 0 30"]
[PlyCount "13"]
[EventDate "1861.??.??"]
30... Rxf4 {Anderssen starts fireworks.} 31. Qe1 (31.gxf4 Qxh4+ 32.Kg1
Rg6+) 31... Rg6 (31...Rxh4+ 32.gxh4 Rg6 ) 32. Bc1 (32.Ng2 ) 32... Rxh4+
33. gxh4 Qf4+ 34. Kh3 Bg2+ 35. Nxg2 Qf3+ 36. Kh2 Qxg2# { Anderssen won
the match by this mate (+4, =2, -3).} 0-1`;
var board = Ic.initBoard({
pgn : example_pgn
});
console.log(board.fenHistoryExport());
在 README.md 中有一个更完整的 node.js example 和 const {Ic} = require("isepic-chess");
导入东西 运行 node.js.
我正在使用 nodejs 构建一个与国际象棋相关的应用程序。我一直在尝试尽可能多地使用 chess.js
,但我认为我在功能方面遇到了障碍。在扩展该功能之前,我想确保没有其他工具可以满足我的需要。
我正在寻找一种将 PGN 字符串转换为 FEN 动作列表的方法。我希望在 chess.js 中使用 load_pgn()
将移动加载到对象中,然后遍历每个移动并调用 fen()
函数来输出当前的 FEN。但是,chess.js 似乎没有办法完成游戏中的动作。除非我遗漏了什么。
我宁愿不必解析字符串,但如果必须的话,我会的。有什么建议吗?
解法:
另请参阅下面 efirvida 的回答以获得解决方案
像这样的东西(未经测试)似乎有效。该函数接受使用 chess.js
创建的 Chess
对象,该对象已经加载了 PGN。
function getMovesAsFENs(chessObj) {
var moves = chessObj.history();
var newGame = new Chess();
var fens = [];
for (var i = 0; i < moves.length; i++) {
newGame.move(moves[i]);
fens.push(newGame.fen());
}
return fens;
}
查看 github 页面 .load_pgn
link
var chess = new Chess();
pgn = ['[Event "Casual Game"]',
'[Site "Berlin GER"]',
'[Date "1852.??.??"]',
'[EventDate "?"]',
'[Round "?"]',
'[Result "1-0"]',
'[White "Adolf Anderssen"]',
'[Black "Jean Dufresne"]',
'[ECO "C52"]',
'[WhiteElo "?"]',
'[BlackElo "?"]',
'[PlyCount "47"]',
'',
'1.e4 e5 2.Nf3 Nc6 3.Bc4 Bc5 4.b4 Bxb4 5.c3 Ba5 6.d4 exd4 7.O-O',
'd3 8.Qb3 Qf6 9.e5 Qg6 10.Re1 Nge7 11.Ba3 b5 12.Qxb5 Rb8 13.Qa4',
'Bb6 14.Nbd2 Bb7 15.Ne4 Qf5 16.Bxd3 Qh5 17.Nf6+ gxf6 18.exf6',
'Rg8 19.Rad1 Qxf3 20.Rxe7+ Nxe7 21.Qxd7+ Kxd7 22.Bf5+ Ke8',
'23.Bd7+ Kf8 24.Bxe7# 1-0'];
chess.load_pgn(pgn.join('\n'));
// -> true
chess.fen()
// -> 1r3kr1/pbpBBp1p/1b3P2/8/8/2P2q2/P4PPP/3R2K1 b - - 0 24
类似
moves = chess.history();
var chess1 = new Chess();
for (move in moves){
chess1.move(move);
fen = chess1.fen()
}
(不是真正的答案;只是需要额外格式化的评论。)
您的 getMovesAsFENs
函数也可以写成:
function getMovesAsFENs(chessObj) {
return chessObj.history().map(function(move) {
chessObj.move(move);
return chessObj.fen();
});
}
也许你不在乎,但这很符合我的整洁感。
这是添加了一些 ES6 糖的端到端答案:
const Chess = require('chess.js').Chess;
const chess1 = new Chess();
const chess2 = new Chess();
const startPos = chess2.fen();
const pgn = `1.e4 c5 0-1`;
chess1.load_pgn(pgn);
let fens = chess1.history().map(move => {
chess2.move(move);
return chess2.fen();
});
//the above technique will not capture the fen of the starting position. therefore:
fens = [startPos, ...fens];
//double checking everything
fens.forEach(fen => console.log(fen));
"However, chess.js doesn't seem to have a way to walk through the moves in a game. Unless I'm missing something.".
你是对的(因为我现在已经多次阅读整个图书馆)。所有需要回顾历史的事情基本上都是撤消然后重做动作,没有集成某种真正的导航(以这种方式解决它是一个有趣的选择,它的优点是可以快速完成某些任务,但对于其他看似简单的任务(如您需要的任务)来说,这确实是一种痛苦。
免责声明(我编写了以下工具),我在过去 5 年多的时间里一直在创建一个工具 (isepic-chess.js),类似于 chess.js,我认为它正在慢慢到达那里......库将移动历史存储在一个对象中,其中包含诸如(fen,from_square,to_square,san 等)的信息,并且还有一些类型带有移动索引和一些移动导航助手的“光标”。
因此使用 isepic-chess.js 你可以在解析 PGN 游戏后调用棋盘方法 board.fenHistoryExport()
来获取 FEN 列表:
var example_pgn = `[Event "m1 London"]
[Site "?"]
[Date "1861.07.??"]
[Round "9"]
[White "Kolisch, Ignatz"]
[Black "Anderssen, Adolf"]
[Result "0-1"]
[Annotator "JvR"]
[SetUp "1"]
[FEN "5r1k/pp4pp/3r3q/8/3PpP1P/1P2NbP1/PB1Q3K/R7 b - - 0 30"]
[PlyCount "13"]
[EventDate "1861.??.??"]
30... Rxf4 {Anderssen starts fireworks.} 31. Qe1 (31.gxf4 Qxh4+ 32.Kg1
Rg6+) 31... Rg6 (31...Rxh4+ 32.gxh4 Rg6 ) 32. Bc1 (32.Ng2 ) 32... Rxh4+
33. gxh4 Qf4+ 34. Kh3 Bg2+ 35. Nxg2 Qf3+ 36. Kh2 Qxg2# { Anderssen won
the match by this mate (+4, =2, -3).} 0-1`;
var board = Ic.initBoard({
pgn : example_pgn
});
console.log(board.fenHistoryExport());
在 README.md 中有一个更完整的 node.js example 和 const {Ic} = require("isepic-chess");
导入东西 运行 node.js.