
Seguindoesta resposta de @StevenB.Segletes, que também é um dos criadores do pacotelistofitems
, agora estou tentando usar o que esse pacote foi capaz de analisar de uma ramificação únicaSGFstring dentro de uma macro.
Isso é o que eu gostaria de conseguir, mas acho que estou tendo problemas de expansão, porque estou recebendo um Missing \endcsname inserted
erro:
\long\def\Firstof#1#2\endFirstof{#1}
\ignoreemptyitems
\newcommand{\parseSgf}[1]{
\setsepchar{;/[||]}
\readlist*\Z{#1}
% This loop basically splits on `;`, which is a node/move delimiter in SGF
\foreachitem \i \in \Z[]{
\itemtomacro\Z[\icnt, 1]\stoneColor
\itemtomacro\Z[\icnt, 2]\sgfCoords
% These if's test the `key[value]` SGF format for the keys `B` and `W`, which denote Black and White moves, respecitvely
% Other keys typically refer to metadata, or other secondary info.
\if\stoneColor B
\drawStoneFromSgfCoords{black}{\sgfCoords} % if I hardcode the arguments, it works.
% \drawStoneFromSgfCoords{black}{Z[\icnt, 2]} % I've also tried stuff like this directly...
\fi
\if\stoneColor AB
\drawStoneFromSgfCoords{black}{\sgfCoords}
\fi
\if\stoneColor W
\drawStoneFromSgfCoords{white}{\sgfCoords}
\fi
\if\stoneColor AW
\drawStoneFromSgfCoords{white}{\sgfCoords}
\fi
}
}
Idealmente, se alguém conseguir encontrar uma solução para isso, eu gostaria que encontrasse movimentos pretos ou brancos ( B
e W
) e pedras editadas (adicionadas) ( AB
e AW
), para que os ifs ficassem assim:
\if\stoneColor { B \OR AB }
...
\if\stoneColor { W \OR AW }
Mas, claro, posso guardar isso para outra pergunta, se for demais.
Aqui está um exemplo completo:
\documentclass{article}
\usepackage{tikz}
% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708876/64441).
\newcommand\notwhite{black}
\newcommand\notblack{white}
% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708893/64441).
\ExplSyntaxOn
\cs_generate_variant:Nn \int_from_alph:n {e}
\NewExpandableDocumentCommand{\stringToCoordX}{ m }{
\int_from_alph:e { \use_i:nn #1 }
}
\NewExpandableDocumentCommand{\stringToCoordY}{ m }{
\int_from_alph:e { \use_ii:nn #1 }
}
\ExplSyntaxOff
\newcommand{\drawStoneFromSgfCoords}[2]{
\pgfmathsetmacro{\x}{\stringToCoordX{#2} - 1}
\pgfmathsetmacro{\y}{\stringToCoordY{#2} - 1}
\draw[draw = \UseName{not#1}, fill = #1, line width = 0.1mm]
(\x * 10cm / 18, \y * 10cm / 18)
circle [radius = 0.2575cm];
}
\usepackage{listofitems}
% From [this answer by @StevenB.Segletes](https://tex.stackexchange.com/a/709014/64441).
\long\def\Firstof#1#2\endFirstof{#1}
\ignoreemptyitems
\newcommand{\parseSgf}[1]{
\setsepchar{;/[||]}
\readlist*\Z{#1}
\foreachitem \i \in \Z[]{
\itemtomacro\Z[\icnt, 1]\color
\itemtomacro\Z[\icnt, 2]\sgfCoords
\expandafter\if\expandafter\Firstof\stoneColor\endFirstof B
\drawStoneFromSgfCoords{black}{ab}
\else\expandafter\if\expandafter\Firstof\stoneColor\endFirstof W
\drawStoneFromSgfCoords{white}{cd}
\fi\fi
}
}
\def\sgfA{;B[ab];W[cd]} % not truly valid SGF, just one simple example
\def\sgfB{(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2024-02-05];B[as];W[bs];B[cs])}
\def\sgfC{(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2024-02-05];B[as];W[bs];B[cs];PL[W]AB[dq]AW[eq])}
\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\step}{10 / 18}
\draw[step=\step] (0, 0) grid (10, 10);
% \drawStoneFromSgfCoords{black}{ab}
% \drawStoneFromSgfCoords{white}{cd}
\parseSgf{\sgfA}
\end{tikzpicture}
\end{document}
Responder1
Vários problemas:
Não use
\color
, pois ele substitui uma macro existente... eu mudei para\Color
.O valor de
\Color
seráB
ouW
, que não é uma cor real. Portanto, apresento\newcommand\thecolorofB{black}
e\newcommand\thecolorofW{white}
converto\Color
em uma cor real.Os parênteses nas definições do SGF também estão causando um problema. Eles não estavam sendo analisados, mas sim interpretados como comandos SGF (mas faltando o
[]
dado associado). Portanto, conectei a análise para digeri-los. Essa abordagem resolve o problema imediato, mas pode não ser adequada dependendo de onde você deseja resolver o problema no futuro.Os valores de
\Color
e\sgfCoords
precisavam ser expandidos antes de alimentá-los em sua macro\drawStoneFromSgfCoords
. Consegui isso expandindo-os\tmp
e depois expandindo-os\tmp
para a invocação de macro.
O MWE:
\documentclass{article}
\usepackage{tikz}
% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708876/64441).
\newcommand\notwhite{black}
\newcommand\notblack{white}
% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708893/64441).
\ExplSyntaxOn
\cs_generate_variant:Nn \int_from_alph:n {e}
\NewExpandableDocumentCommand{\stringToCoordX}{ m }{
\int_from_alph:e { \use_i:nn #1 }
}
\NewExpandableDocumentCommand{\stringToCoordY}{ m }{
\int_from_alph:e { \use_ii:nn #1 }
}
\ExplSyntaxOff
\newcommand{\drawStoneFromSgfCoords}[2]{%
\pgfmathsetmacro{\x}{\stringToCoordX{#2} - 1}
\pgfmathsetmacro{\y}{\stringToCoordY{#2} - 1}
%
\draw[draw = \UseName{not#1}, fill = #1, line width = 0.1mm]
(\x * 10cm / 18, \y * 10cm / 18)
circle [radius = 0.2575cm];
}
\usepackage{listofitems}
% From [this answer by @StevenB.Segletes](https://tex.stackexchange.com/a/709014/64441).
\long\def\Firstof#1#2\endFirstof{#1}
\newcommand\thecolorofB{black}
\newcommand\thecolorofW{white}
\ignoreemptyitems
\newcommand{\parseSgf}[1]{%
\setsepchar{;||(||)/[||]}%
\readlist*\Z{#1}%
%
\foreachitem \i \in \Z[]{%
\itemtomacro\Z[\icnt, 1]\Color
\itemtomacro\Z[\icnt, 2]\sgfCoords
\edef\tmp{{\csname thecolorof\Color\endcsname}{\sgfCoords}}%
%
\expandafter\if\expandafter\Firstof\Color\endFirstof B
\expandafter\drawStoneFromSgfCoords\tmp
\else\expandafter\if\expandafter\Firstof\Color\endFirstof W
\expandafter\drawStoneFromSgfCoords\tmp
\fi\fi
}%
}
\def\sgfA{;B[ab];W[cd]}
\def\sgfB{(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2024-02-05];B[as];W[bs];B[cs])}
\def\sgfC{(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2024-02-05];B[as];W[bs];B[cs];PL[W]AB[dq]AW[eq])}
\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\step}{10 / 18}
\draw[step=\step] (0, 0) grid (10, 10);
\parseSgf{\sgfC}
\end{tikzpicture}
\end{document}