我有一系列 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>)
这是一个起点,有一些 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 的转换应该很简单......