如何将国际象棋 FEN 变成 PGN?

问题描述 投票:0回答:1

我有一系列 FEN 字符串和 LAN(长代数表示法)中的伴随动作,如下所示。示例数据框粘贴在我的问题末尾。

移动 游戏网址
r3k2r/1b1pbppp/p7/1pp5/3q4/P1NPBp1P/1PP1B1P1/R4Q1K w kq - 0 19 e3d4 f3g2 f1g2 b7g2 h1g2 c5d4 链接
3rr1k1/5ppp/6q1/pp6/1bppPn2/5P2/PPP2QPP/2NRBRK1 w - - 8 25 e1b4 f4h3 g1h1 h3f2 链接
r1bq1rk1/ppp2ppp/2np1b1n/3Q2N1/2B1PP2/4B3/PP2N1PP/R4RK1 b - - 0 13 h6g4 g5f7 f8f7 d5f7 链接

此数据框中的每一行都是一个国际象棋谜题。我想根据初始 FEN 生成拼图的 PGN,然后应用构成拼图的移动序列,当前存储在长代数表示法的

Moves
中。

所以我对上述数据框第一行的理想结果是:

移动 游戏网址 PGN
r3k2r/1b1pbppp/p7/1pp5/3q4/P1NPBp1P/1PP1B1P1/R4Q1K w kq - 0 19 e3d4 f3g2 f1g2 b7g2 h1g2 c5d4 链接 [变体“从位置”][FEN“r3k2r/1b1pbppp/p7/1pp5/3q4/P1NPBp1P/1PP1B1P1/R4Q1K w kq - 0 19”]19。 Bxd4 fxg2+ 20.Qxg2 Bxg2+ 21.Kxg2 cxd4

为了实现这一目标,我们需要将 LAN 移动转换为 SAN(短代数表示法)。

使用 R 的

bigchess
包,我尝试将移动转移到 SAN,如下所示:

library(tidyverse)
library(bigchess)

df2 <- df %>% 
  mutate(Moves_SAN = sapply(Moves, lan2san))

但我认为它读取的

Moves
是从棋盘的起始位置开始的,所以翻译的
Moves_SAN
是不正确的。

有谁知道基于 FEN 并使用 R 中可用包将 LAN 转换为 SAN 的方法吗?

我想象解决方案涉及使用

bigchess
stockfish
chess
加载 FEN,然后应用 LAN 并以某种方式在这种情况下将它们转换为 SAN,但我还无法弄清楚如何实现。

structure(list(FEN = c("r3k2r/1b1pbppp/p7/1pp5/3q4/P1NPBp1P/1PP1B1P1/R4Q1K w kq - 0 19", 
"3rr1k1/5ppp/6q1/pp6/1bppPn2/5P2/PPP2QPP/2NRBRK1 w - - 8 25", 
"r1bq1rk1/ppp2ppp/2np1b1n/3Q2N1/2B1PP2/4B3/PP2N1PP/R4RK1 b - - 0 13"
), Moves = c("e3d4 f3g2 f1g2 b7g2 h1g2 c5d4", "e1b4 f4h3 g1h1 h3f2", 
"h6g4 g5f7 f8f7 d5f7"), GameUrl = c("https://lichess.org/6OEDg4W3#Some(36)", 
"https://lichess.org/W9LaAFV1#Some(48)", "https://lichess.org/BxbS4jtt/black#Some(25)"
)), row.names = c(NA, -3L), class = c("data.table", "data.frame"
), .internal.selfref = <pointer: 0x0000026e39ef2e30>)
r chess
1个回答
0
投票

这是一个起点,有一些 bigchess 的黑客攻击:

> packageVersion("bigchess")
[1] '1.9.1'
> 
> position.fen <- function(fen) {
+     fen <- substr(fen, 1L, regexpr(" ", fen) - 1L)
+     map <- list("P" =  1, "B" =  2, "N" =  3, "R" =  4, "Q" =  5, "K" =  6,
+                 "p" = -1, "b" = -2, "n" = -3, "r" = -4, "q" = -5, "k" = -6)
+     map <- c(map, setNames(lapply(0:8, double), c("/", 1:8)))
+     matrix(unlist(map[strsplit(fen, "")[[1L]]], FALSE, FALSE),
+            nrow = 8L, ncol = 8L, byrow = TRUE,
+            dimnames = list(8:1, letters[1:8]))
+ }
> 
> l2s <- bigchess::lan2san
> formals(l2s) <- alist(movetext.lan =, position = position.start())
> body(l2s)[[4L]] <- NULL
> 
> lan <- "e3d4 f3g2 f1g2 b7g2 h1g2 c5d4"
> fen <- "r3k2r/1b1pbppp/p7/1pp5/3q4/P1NPBp1P/1PP1B1P1/R4Q1K w kq - 0 19"
> l2s(lan, position.fen(fen))
[1] "1. Bxd4 fxg2+ 2. Qxg2 Bxg2+ 3. Kxg2 cxd4"
> 

我明天会再次访问以获取 SAN 中正确的移动编号,此时从 FEN+SAN 到 PGN 的转换应该很简单......

© www.soinside.com 2019 - 2024. All rights reserved.