パッケージ `listofitems` とマクロを使用して `\foreachitem` 内の変数を展開する際の問題

パッケージ `listofitems` とマクロを使用して `\foreachitem` 内の変数を展開する際の問題

続く@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 は次のようになります。

\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

いくつかの問題:

  1. \color既存のマクロを上書きするため、を使用しないでください... に変更しました\Color

  2. の値はまたは\Colorとなり、実際の色ではありません。そこで、とを導入して実際の色に変換します。BW\newcommand\thecolorofB{black}\newcommand\thecolorofW{white}\Color

  3. SGF 定義の括弧も問題を引き起こしています。括弧は解析されず、SGF コマンドとして解釈されます (ただし、関連する[]データは欠落しています)。そのため、括弧を消化して取り除くように解析をハードコードしました。このアプローチは当面の問題は解決しますが、将来この問題をどこに持ち込むかによって適さない可能性があります。

  4. \Colorとの値は\sgfCoords、マクロ に渡す前に展開する必要がありました\drawStoneFromSgfCoords。私は、 を に展開して\tmpから、\tmpマクロ呼び出し に展開することでこれを実現しました。

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}

ここに画像の説明を入力してください

関連情報