8

I have need to typeset some very large Go boards, much larger than normal 19x19 boards, as part of a project I am undertaking in infinite Go, similar to my projects in infinite chess. Can you help me typeset very large Go boards,such as the following comparatively tiny instance:

enter image description here

I am aware of the LaTeX package igo, which seems to produce high-quality Go board images, and while I don't have much experience with it, it does seem to be flexible on board size. I can imagine placing several of these boards next to each other, if need be, in order to make large boards. That is what I had had to do to make my various infinite chess positions, and it worked fine.

I was not actually able to get the igo package working on my (miktek, Windows) system, however, and so I am very sorry that I cannot provide a minimal working example.

Meanwhile, I find the input format used in the igo package to be inconvenient for the typical infinite Go positions, which have many dozens of stones. With the igo format, one evidently types something like

\white{b4,c4,d4,e4,f4,g3,g2,c3}
\black{b3,b2,c2,d3,e3,f3,f2}
\begin{center}
\shortstack{\showgoban\\White to kill}
\end{center}

to get the image:

enter image description here

Thus, one specifies the coordinates of each stone separately.

It would be much more convenient for me, however, to be able to specify the position something like this:

 showgoboard{........\\
             .WWWWW..\\   
             .BWBBBW.\\
             .BB..BW.\\
             ........\\}

or something similar, and also with (much) larger board sizes.

The main point is that with the design of infinite go positions, one is often copying and pasting parts of a position or shifting everything by one unit or two units up or to the right, and so on, and this would be extremely irritating with the coordinate-style igo notation, but it would be easy with my notation. I want a notation system that allows one easily to copy parts of a position as a block into other parts of the board.

Can someone help me out? I would like either a Go board package that can accept something like my notation, or else a translation macro that would convert my notation or something like it into the notation accepted by igo or another Go package.

  • Just some idea: I'd probably use a single TikZ grid instead of several boards placed next to each other. And since my TeX programming skills are pretty non-existent, I'd probably use some scripting language to translate your desired input into the right coordinates. But I am sure someone will have a better clue about this. – Uwe Ziegenhagen May 14 '18 at 3:51
  • 1
    @UweZiegenhagen I'd rather use a Go-specific package, since I will also need to label stones and locations, etc., and I would expect that most of them can do that kind of thing very well. I'd rather not end up writing my own Go package. – JDH May 14 '18 at 3:54
  • If you are going to be copying and pasting positions, I think it would be beneficial to define macros: \whitetokill takes two arguments and typesets your example at that location, \line{b}{5,6}{50,6} typesets the semi-infinite black line in your drawing, etc. But that's all beyond my TeX abilities. – Teepeemm May 15 '18 at 1:12
  • The point is that the positions will be huge, and the design of them will involve dozens of minor adjustments and movings-around of portions. I want to lay them out and work with them in ASCII, where they can be visualized, rather than with an opaque coordinate representation. – JDH May 15 '18 at 1:21
9

First proposition

Here is simple solution via TikZ (note: don't use . as empty intersection).

\documentclass[tikz,margin=2mm]{standalone}
\usepackage{etoolbox}
\usepackage{xparse}
\tikzset{
  @go line/.code args={#1#2#3!}{
    \edef\myrest{#3}
    \edef\myletter{#2}
    \draw (#1,-\mycount) +(0,-.5) -- +(0,.5) +(.5,0) -- +(-.5,0);
    \ifdefstring{\myletter}{W}{
      \path[draw,fill=white] (#1,-\mycount) circle (.4);
    }{
      \ifdefstring{\myletter}{B}{
        \path[draw,fill=black] (#1,-\mycount) circle (.4);
      }{}
    }
    \ifdefstring{\myrest}{}{}{
      \pgfmathsetmacro\mynext{int(#1+1)}
      \pgfkeysalso{@go line={\mynext}#3!}
    }
  },
  go line/.style={@go line={0}#1!},
}
\NewDocumentCommand\showgoboard{m}{
  \begin{tikzpicture}[x=\mygounit,y=\mygounit]
    \edef\myconf{#1}
    \foreach [count=\mycount] \myline in \myconf {
      \tikzset{go line/.expanded=\myline}
    }
  \end{tikzpicture}
}
\def\mygounit{5mm}
\begin{document}
\showgoboard{
  --------,
  -WWWWW--,
  -BWBBBW-,
  -BB--BW-,
  --------
}
\end{document}

enter image description here

Second proposition

Enhanced version with better use of pgfkeys and possible annotations. The (customisable) parser uses the following convention:

  • . (a point) is an error!
  • B as black stone
  • W as white stone
  • - (a minus) as empty point
  • any other symbol as annotation letter
\documentclass[tikz,margin=2mm]{standalone}
\usepackage{lmodern}
\usepackage{etoolbox}
\usepackage{xparse}
\tikzset{
  @go draw intersection/.code 2 args={
    \draw[line width=.5\pgflinewidth] (#1,-#2) +(0,-.5) -- +(0,.5) +(.5,0) -- +(-.5,0);
  },
  @go draw stone/.code n args={3}{
    \path[draw,fill=#3] (#1,-#2) circle (.4);
  },
  @go draw annot/.code n args={3}{
    \pgfmathsetmacro\gofsa{\gounit*.8}
    \pgfmathsetmacro\gofsb{\gofsa*1.2}
    \path (#1,-#2)
    node[fill=white,inner sep=.1em,node font=\fontsize{\gofsa pt}{\gofsb pt}\selectfont,anchor=mid]
    {#3};
  },
  @go draw W/.style 2 args={@go draw stone={#1}{#2}{white}},
  @go draw B/.style 2 args={@go draw stone={#1}{#2}{black}},
  @go draw -/.style 2 args={},
  @go line/.code args={#1#2#3!}{
    \pgfkeysalso{
      @go draw intersection={#1}{\gocount},
      @go draw #2/.try={#1}{\gocount}
    }
    \ifbool{pgfkeyssuccess}{}{\pgfkeysalso{@go draw annot={#1}{\gocount}{#2}}}
    \edef\gorest{#3}
    \ifdefstring{\gorest}{}{}{
      \pgfmathsetmacro\gonext{int(#1+1)}
      \pgfkeysalso{@go line={\gonext}#3!}
    }
  },
  go line/.style={@go line={0}#1!},
}
\NewDocumentCommand\showgoboard{m}{
  \begin{tikzpicture}[x=\gounit,y=\gounit,line width=\gounit*0.03]
    \edef\goconf{#1}
    \foreach [count=\gocount] \goline in \goconf {
      \tikzset{go line/.expanded=\goline}
    }
  \end{tikzpicture}
}
\def\gounit{6mm}
\begin{document}
\showgoboard{
  ---------,
  --BBcd---,
  -WWWWW-e-,
  -BWBBBW--,
  -BB-aBWb-,
  ---------
}
\end{document}

enter image description here

4

If you are willing to use LuaLaTex, converting your notation into the igo notation is reasonably simple:

    \documentclass[10pt,a4paper]{article}
    \usepackage{luacode}

    \newcommand{\white}[1]{WHITE:#1\\}
    \newcommand{\black}[1]{BLACK:#1\\}
    \newbox\tmp
    \newenvironment{go}{
      \setbox\tmp\vbox\bgroup{}
      \directlua{startrecording()}
    }{
      \egroup
      \directlua{stoprecording()}
    }

    \begin{luacode*}
    do
      local board = {}

      function readbuf( buf )
        -- record a part (line) of the go board
        print("Adding to buffer"..buf)
        board = board .. buf .. "\n"
      end

      function startrecording()
        -- start recording the go board; called before the go environment starts
        board = ""
        luatexbase.add_to_callback('process_input_buffer', readbuf, 'readbuf')
      end

      function row_to_char(row)
          -- converts a row number to a character (0=>a, 1=>b, 2=>c, etc)
          return string.char(65+row):lower()
      end

      function stoprecording()
        -- called when the go environment ends
        -- converts the board notation into a string for white & black

        -- removes the callback to stop recording
        luatexbase.remove_from_callback('process_input_buffer', 'readbuf')

        local row = 0               -- current row number
        local col = 0               -- current column 
        local white = ""            -- the string of white positions
        local black = ""            -- the string of black positions
        local c_char = ""           -- helper variable containing the current character

        for pos = 1 , board:len() do  -- iterate over the board string
          c_char = board:sub(pos,pos):lower()
          print("At pos"..row_to_char(row)..col.."("..pos.."), char:"..board:sub(pos,pos))
          if c_char == '.' then 
              col = col + 1
          elseif c_char == 'w' then
              col = col + 1
              white = white..','..row_to_char(row)..col
          elseif c_char == 'b' then
              col = col + 1
              black = black..','..row_to_char(row)..col
          elseif c_char == '\n' then
              col = 0
              row = row + 1
          end
        end

        -- output the commands \white{white position} \black{black position}
        tex.print("\\white{"..white:sub(2).."}\\black{"..black:sub(2).."}")
      end

    end
    \end{luacode*}

    \begin{document}
    \begin{go}
     ..W..W..
     BB.BB..B
     ........
     WWBBWWBB
    \end{go}
    \end{document}
  • Thanks, Jonathan! I'll give this a try and see if it will work for me. It looks very promising. – JDH May 14 '18 at 11:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.