Message Boards Message Boards

Drawing a chess position from FEN (Forsyth–Edwards Notation)

Posted 4 years ago

enter image description here

I'm sure there have been many proposals on how to do this. I gave it a try, and after a few painful attempts I came up with a visually decent result, without too much code (IMHO). Also I really wanted to use unicode symbols, not drawing of pieces found on the web.

TODO:

  • Avoid using a hard-coded font size ;
  • White pieces should not look "transparent" on a dark square.
POSTED BY: Lucien Grondin
10 Replies

I rewrote it using Grid and Item. I think it's arguably more elegant.

I can't quite get the squares to actually be squares, though.

POSTED BY: Lucien Grondin
Posted 4 years ago

Hi Lucien, Take a look at this post by @Shenghui Yang

POSTED BY: Rohit Namjoshi
Posted 4 years ago

"White pieces should not look "transparent" on a dark square."

You can put the solid chessfont with white or dark color first and than the shallow chessfont as a black border around the pieces:

enter image description here

POSTED BY: Oliver Seipel

enter image description here -- you have earned Featured Contributor Badge enter image description here Your exceptional post has been selected for our editorial column Staff Picks http://wolfr.am/StaffPicks and Your Profile is now distinguished by a Featured Contributor Badge and is displayed on the Featured Contributor Board. Thank you!

POSTED BY: EDITORIAL BOARD

@Lucien, this looks nice, thank you for sharing. You might want to consider contributing to The Wolfram Function Repository: https://resources.wolframcloud.com/FunctionRepository

POSTED BY: Vitaliy Kaurov

Thanks, that's quite an honor.

If I manage to make this function work exactly as I'd like to, I'll definitely submit it to the repository.

POSTED BY: Lucien Grondin

How did you do this ? I'm not sure how to specify that kind of font. I'll definitely look it up, though.

PS. Oh wait I see what you mean. I had thought about it. Yes I guess it can be done, though it'll be a bit of a hassle. I still would like to know how you did it. Did you use Overlay ?

POSTED BY: Lucien Grondin

Following the suggestion from @Oliver, I used Overlay to create some kind of a solid white piece.

Also I used ItemSize -> All as a grid option to make sure all squares have the same size.

I'm quite happy with the result.

showChessPosition[
  fen_String : 
   "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
  ] := Grid[
  Partition[Partition[
     Riffle[
      Flatten@Characters[
          StringSplit[StringExtract[fen, 1], "/"]
          ] /. {
         "K" -> \[WhiteKing], "Q" -> \[WhiteQueen], 
         "R" -> \[WhiteRook], "B" -> \[WhiteBishop], 
         "N" -> \[WhiteKnight], "P" -> \[WhitePawn],
         "k" -> \[BlackKing], "q" -> \[BlackQueen], 
         "r" -> \[BlackRook], "b" -> \[BlackBishop], 
         "n" -> \[BlackKnight], "p" -> \[BlackPawn],
         n_String /; DigitQ[n] :> 
          Splice@ConstantArray[" ", ToExpression[n]]
         }
       /. {
        p : \[WhiteKing] | \[WhiteQueen] | \[WhiteBishop] | \
\[WhiteKnight] | \[WhiteRook] | \[WhitePawn] :> Overlay[
          {
           Style[p /. {
              \[WhiteKing] -> \[BlackKing], \[WhiteQueen] -> \
\[BlackQueen], \[WhiteBishop] -> \[BlackBishop], \[WhiteKnight] -> \
\[BlackKnight], \[WhiteRook] -> \[BlackRook], \[WhitePawn] -> \
\[BlackPawn]
              }, White],
           p
           }
          ]
        },
      Flatten@Table[If[EvenQ[i + j], White, LightGray], {i, 8}, {j, 8}]
      ],
     2
     ] /. {p_ , c : White | LightGray} :> Item[p, Background -> c], 8],
  Alignment -> Center,
  Frame -> True,
  ItemSize -> All
  ]

Export[
 "fool's mate.svg", 
 showChessPosition@
  "rnb1kbnr/pppp1ppp/8/4p3/5PPq/8/PPPPP2P/RNBQKBNR w KQkq - 0 1",
  "SVG"
 ]

fool's mate

PS. Here's an other rewrite.

showChessPosition[
  fen_String : 
   "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
  ] := Grid[
  MapThread[
   {piece, color} |-> Item[piece, Background -> color],
   {
    Characters[
       StringReplace[
        StringSplit[StringExtract[fen, 1], "/"],
        MapThread[
         Rule,
         Characters /@ {
           "KQRBNPkqrbnp",

           "\[WhiteKing]\[WhiteQueen]\[WhiteRook]\[WhiteBishop]\
\[WhiteKnight]\[WhitePawn]\[BlackKing]\[BlackQueen]\[BlackRook]\
\[BlackBishop]\[BlackKnight]\[BlackPawn]"
           }
         ]
        ]
       ] /. MapThread[
       {w, b} |-> Rule[w, Overlay[{Style[b, White], w}]],
       Characters /@ {"\[WhiteKing]\[WhiteQueen]\[WhiteRook]\
\[WhiteBishop]\[WhiteKnight]\[WhitePawn]", 
         "\[BlackKing]\[BlackQueen]\[BlackRook]\[BlackBishop]\
\[BlackKnight]\[BlackPawn]"}
       ]
     /. n_String /; DigitQ[n] :> 
      Splice@ConstantArray["", ToExpression[n]],
    Table[If[EvenQ[i + j], LightGray, Gray], {i, 8}, {j, 8}]
    },
   2
   ],
  Frame -> True, ItemSize -> All
  ]
POSTED BY: Lucien Grondin
Posted 4 years ago

I used a Graphics solution with Text (using your first suggestion). I wasn't even aware of Overlay (but now I am:)

fen = "rnb1kbnr/pppp1ppp/8/4p3/5PPq/8/PPPPP2P/RNBQKBNR w KQkq - 0 1";
pieces = Cases[
   Partition[
    Riffle[Flatten[
      ReplaceAll[
       Characters[StringSplit[First[StringSplit[fen]], "/"]], 
       n_String /; DigitQ[n] :> 
        Splice[ConstantArray["\[EmptySet]", ToExpression[n]]]]], 
     Reverse /@ Tuples[{Range[8, 1, -1], Range[8]}]], 
    2], {Except["\[EmptySet]"], __}];
piecesonboard = 
  Graphics[{EdgeForm[Blue], pieces /. {p_String, coord_} :>
      With[{piece = 
         ToLowerCase[p] /. {"k" -> "\[BlackKing]", 
           "q" -> "\[BlackQueen]", "r" -> "\[BlackRook]", 
           "b" -> "\[BlackBishop]", "n" -> "\[BlackKnight]", 
           "p" -> "\[BlackPawn]"}},
       If[
        UpperCaseQ[
         p], {Text[
          Style[piece, FontSize -> 24, LightBlue], {-.5, -.5} + 
           coord], 
         Text[Style[
           p /. {"K" -> "\[WhiteKing]", "Q" -> "\[WhiteQueen]", 
             "R" -> "\[WhiteRook]", "B" -> "\[WhiteBishop]", 
             "N" -> "\[WhiteKnight]", "P" -> "\[WhitePawn]"}, 
           FontSize -> 24, Black], {-.5, -.5} + coord]}, {Text[
          Style[piece, FontSize -> 24, Gray], {-.5, -.5} + coord], 
         Text[Style[
           ToUpperCase[p] /. {"K" -> "\[WhiteKing]", 
             "Q" -> "\[WhiteQueen]", "R" -> "\[WhiteRook]", 
             "B" -> "\[WhiteBishop]", "N" -> "\[WhiteKnight]", 
             "P" -> "\[WhitePawn]"}, FontSize -> 24, 
           Black], {-.5, -.5} + coord]}]]}];
Show[{MatrixPlot[Table[Mod[i + j, 2], {i, 8}, {j, 8}], 
   ColorRules -> {0 -> White, 1 -> LightGray}, 
   FrameTicks -> {{#, #} &@Table[{i, 8 - i + 1, 0}, {i, 8}], {#, #} &@
      Table[{i, FromCharacterCode[ToCharacterCode["a"] + i - 1], 
        0}, {i, 8}]}], piecesonboard}]
POSTED BY: Oliver Seipel
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract