
Следующийэтот ответ от @StevenB.Segletes, который также является одним из создателей пакетаlistofitems
, теперь я пытаюсь использовать то, что этот пакет смог проанализировать из одной веткиСГФстрока внутри макроса.
Вот чего я хотел бы добиться, но, думаю, у меня возникли проблемы с расширением, потому что я получаю сообщение об Missing \endcsname inserted
ошибке:
\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
}
}
В идеале, если кто-то сможет найти решение этой проблемы, я бы хотел, чтобы оно находило как ходы черных, так и ходы белых ( B
и W
), а также измененные (добавленные) камни ( AB
и AW
), поэтому «если» будут выглядеть следующим образом:
\if\stoneColor { B \OR AB }
...
\if\stoneColor { W \OR AW }
Но, конечно, я могу приберечь это для другого вопроса, если он станет слишком назойливым.
Вот полный пример:
\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}
решение1
Несколько вопросов:
Не используйте
\color
, так как он перезаписывает существующий макрос... Я изменил его на\Color
.Значение
\Color
будетB
илиW
, что не является фактическим цветом. Поэтому я ввожу\newcommand\thecolorofB{black}
и\newcommand\thecolorofW{white}
для преобразования\Color
в фактический цвет.Скобки в определениях SGF также вызывают проблему. Они не анализировались, а интерпретировались как команды SGF (но без связанных
[]
данных). Поэтому я жестко запрограммировал анализ, чтобы переварить их. Этот подход решает непосредственную проблему, но может оказаться неподходящим в зависимости от того, куда вы хотите направить эту проблему в будущем.Значения
\Color
и\sgfCoords
необходимо было расширить, прежде чем передавать их в ваш макрос\drawStoneFromSgfCoords
. Я добился этого, расширив их в\tmp
, а затем расширив\tmp
в вызов макроса.
МВЭ:
\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}