1

I need to write some documentation and need to display a Hnefatafl board. Basically it is an 11x11 board, some of the squares would be highlighted (e.g. cross hatching). The pieces are basically equivalent to black pawn, white pawn, black King - and I could use either circles or even chess board pieces to represent, the board would have chess style rank and file notation (1-11, A-K etc.).

Really looking for some advise, I think I may need to write some (hopefully simple) package, would tikZ be the best place to start or is there a chess package or something else that could enable the above? I'm relatively new to LaTeX, I can do the basics, but need to learn a bit more. I'd appreciate any advise on how to go about this.

Thanks in advance!

6
  • 3
    11x11 boards can be drawn with the chessboard package. Commented Feb 14 at 10:05
  • Thank you, I will take a look, that will save me quite a bit of work.
    – LewisE
    Commented Feb 14 at 10:26
  • 1
    Just to note: There are already several package for typesetting games.
    – cabohah
    Commented Feb 14 at 10:30
  • 3
    Does this answer your question? How to get a 4 by 4 chessboard? Or any other size of board.
    – cabohah
    Commented Feb 14 at 10:31
  • 1
    Thanks for the responses. Basically, I'm looking at the chessboard package now. I need an 11x11 board, if I can tweak the black/white squares to highlight the corners/starting position in Hnefatafl that would be perfect. I can reuse the chess pieces for my documentation, or replace them with go-stones or something like that. I think, at first glance, chessboard seems to be able to do 99% of what I'm after.
    – LewisE
    Commented Feb 14 at 11:38

1 Answer 1

1

You could create your custom commands. Here I used expl syntax to convert some alphanumeric coordinate such as f4 to a node at the relevant coordinate in a TikZ coordinate system. For the actual game board, I made use of a \pic. But of course, there are a lot of other equally valid approaches to this:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\ExplSyntaxOn
\cs_generate_variant:Nn \int_from_alph:n { e }
\NewExpandableDocumentCommand{\HnefataflBoardMakeNode}{ o m }{
    \str_set:Nn \l_tmpa_str { #2 }
    \str_set:Nn \l_tmpb_str { #2 } 
    \regex_replace_all:nnN { \d } { } \l_tmpa_str
    \regex_replace_all:nnN { [a-zA-Z] } { } \l_tmpb_str
    \int_set:Nn \l_tmpa_int { \int_from_alph:e { \l_tmpa_str } }
    \int_set:Nn \l_tmpb_int { \l_tmpb_str } 
    \int_decr:N \l_tmpa_int
    \int_decr:N \l_tmpb_int
    \node[#1] at ( { \int_use:N \l_tmpa_int + 0.5 } , { \int_use:N \l_tmpb_int + 0.5 } ) {};
}
\ExplSyntaxOff

\tikzset{
    pics/hnefatafl board/.style={
        code={
            \tikzset{hnefatafl board/.cd, #1}
            \draw[step=1cm] (0,0) grid 
                (\pgfkeysvalueof{/tikz/hnefatafl board/size},\pgfkeysvalueof{/tikz/hnefatafl board/size});
            \draw[thick] (0,0) rectangle 
                (\pgfkeysvalueof{/tikz/hnefatafl board/size},\pgfkeysvalueof{/tikz/hnefatafl board/size});
            \foreach \cx in {0, {\pgfkeysvalueof{/tikz/hnefatafl board/size}-1}} {
                \foreach \cy in {0, {\pgfkeysvalueof{/tikz/hnefatafl board/size}-1}} {
                    \draw (\cx,\cy) -- +(1,1) +(1,0) -- +(0,1);
                }
            }
        }
    },
    hnefatafl board/size/.initial={11},
    hnefatafl board/king node/.style={
        circle,
        draw,
        minimum size=0.9cm,
        append after command={
            node[circle, draw, minimum size=0.7cm] at (\tikzlastnode.center) {}
        }
    },
    hnefatafl board/defender node/.style={
        circle,
        draw,
        minimum size=0.9cm
    },
    hnefatafl board/aggressor node/.style={
        circle,
        fill,
        minimum size=0.9cm
    },
    hnefatafl board/k/.code={
        \HnefataflBoardMakeNode[hnefatafl board/king node]{#1}
    },
    hnefatafl board/a/.code={
        \HnefataflBoardMakeNode[hnefatafl board/aggressor node]{#1}
    },
    hnefatafl board/d/.code={
        \HnefataflBoardMakeNode[hnefatafl board/defender node]{#1}
    },
    hnefatafl board/king/.code={
        \tikzset{hnefatafl board/k/.list={#1}}
    },
    hnefatafl board/aggressors/.code={
        \tikzset{hnefatafl board/a/.list={#1}}
    },
    hnefatafl board/defenders/.code={
        \tikzset{hnefatafl board/d/.list={#1}}
    }
}

\begin{document}
    \begin{tikzpicture}
        \pic {hnefatafl board={
            king={f6},
            aggressors={a4,a5,a6,a7,a8,b6,k4,k5,k6,k7,k8,j6},
            aggressors={d1,e1,f1,g1,h1,f2,d11,e11,f11,g11,h11,f10},
            defenders={f8,e7,f7,g7,d6,e6,g6,h6,e5,f5,g5,f4},
        }};
    \end{tikzpicture}

    \begin{tikzpicture}
        \pic {hnefatafl board={
            size=7,
            king={d4},
            aggressors={a3,a4,a5,b4,f4,g3,g4,g5},
            aggressors={c1,d1,e1,d2,c7,d7,e7,d6},
            defenders={e3,e4,e5,d3,d5,c3,c4,c5}
        }};
    \end{tikzpicture}
\end{document}

enter image description here


Or maybe an implementation using the l3draw package:

\documentclass[border=10pt]{standalone}
\usepackage{l3draw}

\ExplSyntaxOn

\cs_generate_variant:Nn \int_from_alph:n { e }
\dim_new:N \l_lewise_hnefataflboard_coordx_dim
\dim_new:N \l_lewise_hnefataflboard_coordy_dim
\cs_new:Nn \lewise_hnefataflboard_convert_coordinate:n {
    \str_set:Nn \l_tmpa_str { #1 }
    \str_set:Nn \l_tmpb_str { #1 } 
    \regex_replace_all:nnN { \d } { } \l_tmpa_str
    \regex_replace_all:nnN { [a-zA-Z] } { } \l_tmpb_str
    \int_set:Nn \l_tmpa_int { \int_from_alph:e { \l_tmpa_str } }
    \int_set:Nn \l_tmpb_int { \l_tmpb_str } 
    \int_decr:N \l_tmpa_int
    \int_decr:N \l_tmpb_int
    \dim_set:Nn \l_lewise_hnefataflboard_coordx_dim { \l_tmpa_int cm + 0.5cm }
    \dim_set:Nn \l_lewise_hnefataflboard_coordy_dim { \l_tmpb_int cm + 0.5cm }
}

\int_new:N \l_lewise_hnefataflboard_size_int
\seq_new:N \g_lewise_hnefataflboard_pieces_seq
\keys_define:nn { hnefatafl board } {
    size .int_set:N = \l_lewise_hnefataflboard_size_int ,
    size .initial:n = { 11 } ,
    king .code:n = {
        \clist_set:Nn \l_tmpa_clist { #1 }
        \clist_map_inline:Nn \l_tmpa_clist {
            \seq_gput_right:Nn \g_lewise_hnefataflboard_pieces_seq { 
                \lewise_hnefataflboard_convert_coordinate:n { ##1 } 
                \draw_path_circle:nn 
                    { \l_lewise_hnefataflboard_coordx_dim , 
                      \l_lewise_hnefataflboard_coordy_dim } { 0.45cm }
                \draw_path_circle:nn 
                    { \l_lewise_hnefataflboard_coordx_dim , 
                      \l_lewise_hnefataflboard_coordy_dim } { 0.35cm }
                \draw_path_use_clear:n { stroke }
            }
        }
    },
    defenders .code:n = {
        \clist_set:Nn \l_tmpa_clist { #1 }
        \clist_map_inline:Nn \l_tmpa_clist {
            \seq_gput_right:Nn \g_lewise_hnefataflboard_pieces_seq { 
                \lewise_hnefataflboard_convert_coordinate:n { ##1 } 
                \draw_path_circle:nn 
                    { \l_lewise_hnefataflboard_coordx_dim , 
                      \l_lewise_hnefataflboard_coordy_dim } { 0.45cm }
                \draw_path_use_clear:n { stroke }
            }
        }
    },
    aggressors .code:n = {
        \clist_set:Nn \l_tmpa_clist { #1 }
        \clist_map_inline:Nn \l_tmpa_clist {
            \seq_gput_right:Nn \g_lewise_hnefataflboard_pieces_seq { 
                \lewise_hnefataflboard_convert_coordinate:n { ##1 } 
                \draw_path_circle:nn 
                    { \l_lewise_hnefataflboard_coordx_dim , 
                      \l_lewise_hnefataflboard_coordy_dim } { 0.45cm }
                \draw_path_use_clear:n { fill }
            }
        }
    }
}

\NewDocumentCommand{\HnefataflBoard}{ m }{
    \seq_gclear:N \g_lewise_hnefataflboard_pieces_seq
    \keys_set:nn { hnefatafl board } { #1 } 

    \draw_begin:

    \draw_linewidth:n { 0.2pt }
    \draw_path_grid:nnnn
        { 1cm } { 1cm }
        { 0cm , 0cm }
        { \l_lewise_hnefataflboard_size_int * 1cm , 
            \l_lewise_hnefataflboard_size_int * 1cm }
    \draw_path_use_clear:n { stroke }
    \draw_linewidth:n { 0.4pt }
    \draw_path_rectangle:nn 
        { 0 , 0 } 
        { \l_lewise_hnefataflboard_size_int * 1cm , 
            \l_lewise_hnefataflboard_size_int * 1cm }
    \draw_path_use:n { stroke }

    \draw_path_moveto:n { 0cm , 0cm }
    \draw_path_lineto:n { 1cm , 1cm }
    \draw_path_moveto:n { 1cm , 0cm }
    \draw_path_lineto:n { 0cm , 1cm }
    \draw_path_moveto:n { ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm , 0cm }
    \draw_path_lineto:n { \l_lewise_hnefataflboard_size_int * 1cm , 1cm }
    \draw_path_moveto:n { \l_lewise_hnefataflboard_size_int * 1cm , 0cm }
    \draw_path_lineto:n { ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm , 1cm }
    \draw_path_moveto:n { 0cm , ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm }
    \draw_path_lineto:n { 1cm , \l_lewise_hnefataflboard_size_int * 1cm }
    \draw_path_moveto:n { 0cm , \l_lewise_hnefataflboard_size_int * 1cm }
    \draw_path_lineto:n { 1cm , ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm }
    \draw_path_moveto:n { ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm , 
        ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm }
    \draw_path_lineto:n { \l_lewise_hnefataflboard_size_int * 1cm ,   
        \l_lewise_hnefataflboard_size_int * 1cm }
    \draw_path_moveto:n { ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm , 
        \l_lewise_hnefataflboard_size_int * 1cm }
    \draw_path_lineto:n { \l_lewise_hnefataflboard_size_int * 1cm , 
        ( \l_lewise_hnefataflboard_size_int - 1 ) * 1cm }
    \draw_path_use:n { stroke }

    \seq_map_inline:Nn \g_lewise_hnefataflboard_pieces_seq { ##1 }
    
    \draw_end:
}

\ExplSyntaxOff

\begin{document}
    \HnefataflBoard{ 
        king={f6}, 
        aggressors={a4,a5,a6,a7,a8,b6,k4,k5,k6,k7,k8,j6},
        aggressors={d1,e1,f1,g1,h1,f2,d11,e11,f11,g11,h11,f10},
        defenders={f8,e7,f7,g7,d6,e6,g6,h6,e5,f5,g5,f4}
    }
\end{document}

enter image description here

2
  • That’s fantastic, thank you.
    – LewisE
    Commented Feb 15 at 11:15
  • @LewisE I don't know a lot about this game, but I saw boards of different sizes. So, I thought it might be a good idea to have some option to change the size ... =) Commented Feb 15 at 11:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .