Chess Bin

Computer Chess Information and Resources

Forsyth–Edwards Notation

In this post I am going to discuss Forsyth-Edwards Notation (FEN) and its implementation in a chess engine.   FEN is a standard way of describing a chess position, containing enough information to restart the chess game from that position.  It is based on a notation developed by a Scottish journalist, David Forsyth in the 19th century.

Why is FEN useful to us?

1. We can use FEN to store game history allowing us to search for move repetitions as well as display the history of the game to the user.  Furthermore if we find a FEN position that has occurred in the past, we can skip searching for the best move and use the same response we used before.

2. We can use FEN strings to implement an Opening Book.    With two FEN strings I can store position pairs representing a starting position and the prescribed response.

The implementation of Forsyth–Edwards Notation

FEN notation uses only ASCII characters stored in a single line.  A FEN string or record contains 6 fields.  These are separated by a space.

  • Piece placement from white’s perspective.  Each row is noted, starting from row 8 (blacks row0 and ending with row 1 (white’s row).  Each piece is described from column to column h.  Each piece is identified by a single letter. 

Pawn: P

Knight: K

Bishop: B

Rook: R

Queen: Q

King: K

White pieces are noted using capital letters and black using lower case.  So P would be a white pawn and p would signify a black pawn.
Empty squares (spaces) are described using numbers, each number representing the number of empty squares before the next chess pieces.  The number 8 would describe a completely empty row. 
The character / describes a new row.

So for a starting position we may see: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR

  • The second column in the Forsyth–Edwards Notation represents whose turn it is.  A single character is used w for white and b for black.
  • The third column represents if castling is still allowed.  If neither side can castle then the character – is used.   Otherwise the following letters are used.  K means white can castle King Side, Q means White can castle Queen side.  Lower case k and q mean the same for black.
  • The fourth column represents an En Passant target square.  The square that the pawn hopped to get to its row, or the position behind the pawn.  If there is no En Passant square then the character – is used.  So if the last move was pawn to e4, we will record e3 in this column.
  • The fifth column contains the number of half moves since the last pawn move or capture.  This is used to determine the 50 move draw scenario.  
  • The last column contains the full move number.  The number starts at 1 and is incremented after black’s move.

Examples:

FEN for the starting position:

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

FEN after the white pawn moved to E4:

rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1

FEN after the black pawn moved to C5

rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2

And then after the white knight moves to F3:

rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2

Forsyth–Edwards Notation Code

In my chess engine FEN is implemented in two methods.  The first method will produce a FEN string for any chess Board.

internal static string Fen(bool boardOnly, Board board)
{
 string output = String.Empty;
 byte blankSquares = 0;

 for (byte x = 0; x < 64; x++)
 {
  byte index = x;

  if (board.Squares[index].Piece != null)
  {
   if (blankSquares > 0)
   {
    output += blankSquares.ToString();
    blankSquares = 0;
   }

   if (board.Squares[index].Piece.PieceColor == ChessPieceColor.Black)
   {
    output += Piece.GetPieceTypeShort(board.Squares[index].Piece.PieceType).ToLower();
   }
   else
   {
    output += Piece.GetPieceTypeShort(board.Squares[index].Piece.PieceType);
   }
  }
  else
  {
   blankSquares++;
  }

  if (x % 8 == 7)
  {
   if (blankSquares > 0)
   {
    output += blankSquares.ToString();
    output += "/";
    blankSquares = 0;
   }
   else
   {
    if (x > 0 && x != 63)
    {
     output += "/";
    }
   }
  }
 }

 if (board.WhoseMove == ChessPieceColor.White)
 {
  output += " w ";
 }
 else
 {
  output += " b ";
 }

 string spacer = "";

 if (board.WhiteCastled == false)
 {
  if (board.Squares[60].Piece != null)
  {
   if (board.Squares[60].Piece.Moved == false)
   {
    if (board.Squares[63].Piece != null)
    {
     if (board.Squares[63].Piece.Moved == false)
     {
      output += "K";
      spacer = " ";
     }
    }
    if (board.Squares[56].Piece != null)
    {
     if (board.Squares[56].Piece.Moved == false)
     {
      output += "Q";
      spacer = " ";
     }
    }
   }
  }
 }

 if (board.BlackCastled == false)
 {
  if (board.Squares[4].Piece != null)
  {
   if (board.Squares[4].Piece.Moved == false)
   {
    if (board.Squares[7].Piece != null)
    {
     if (board.Squares[7].Piece.Moved == false)
     {
      output += "k";
      spacer = " ";
     }
    }
    if (board.Squares[0].Piece != null)
    {
     if (board.Squares[0].Piece.Moved == false)
     {
      output += "q";
      spacer = " ";
     }
    }
   }
  }

  
 }

 if (output.EndsWith("/"))
 {
  output.TrimEnd('/');
 }


 if (board.EnPassantPosition != 0)
 {
  output += spacer + GetColumnFromByte((byte)(board.EnPassantPosition % 8)) + "" + (byte)(8 - (byte)(board.EnPassantPosition / 8)) + " ";
 }
 else
 {
  output += spacer + "- ";
 }

 if (!boardOnly)
 {
  output += board.FiftyMove + " ";
  output += board.MoveCount + 1;
 }
 return output.Trim();
}

The second method is a Board constructor that will accept a FEN string and create a Chess Board based on the content of the string.  Strictly speaking you will not need this code.  I only use this to allow people to enter FEN strings in the user interface.   Since FEN is a standard used in many chess programs allowing users to input FEN strings will allow them to visualize chess positions they might find on the internet. 

internal Board(string fen) : this()
{
 byte index = 0;
 byte spc = 0;

 WhiteCastled = true;
 BlackCastled = true;
 byte spacers = 0;

 WhoseMove = ChessPieceColor.White;

 if (fen.Contains("a3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 40;
 }
 else if (fen.Contains("b3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 41;
 }
 else if (fen.Contains("c3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 42;
 }
 else if (fen.Contains("d3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 43;
 }
 else if (fen.Contains("e3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 44;
 }
 else if (fen.Contains("f3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 45;
 }
 else if (fen.Contains("g3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 46;
 }
 else if (fen.Contains("h3"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 47;
 }


 if (fen.Contains("a6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 16;
 }
 else if (fen.Contains("b6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 17;
 }
 else if (fen.Contains("c6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition =18;
 }
 else if (fen.Contains("d6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 19;
 }
 else if (fen.Contains("e6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 20;
 }
 else if (fen.Contains("f6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 21;
 }
 else if (fen.Contains("g6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 22;
 }
 else if (fen.Contains("h6"))
 {
  EnPassantColor = ChessPieceColor.White;
  EnPassantPosition = 23;
 }

 foreach (char c in fen)
 {

  if (index < 64 && spc == 0)
  {
   if (c == '1' && index < 63)
   {
    index++;
   }
   else if (c == '2' && index < 62)
   {
    index += 2;
   }
   else if (c == '3' && index < 61)
   {
    index += 3;
   }
   else if (c == '4' && index < 60)
   {
    index += 4;
   }
   else if (c == '5' && index < 59)
   {
    index += 5;
   }
   else if (c == '6' && index < 58)
   {
    index += 6;
   }
   else if (c == '7' && index < 57)
   {
    index += 7;
   }
   else if (c == '8' && index < 56)
   {
    index += 8;
   }
   else if (c == 'P')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Pawn, ChessPieceColor.White);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'N')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Knight, ChessPieceColor.White);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'B')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Bishop, ChessPieceColor.White);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'R')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Rook, ChessPieceColor.White);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'Q')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Queen, ChessPieceColor.White);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'K')
   {
    Squares[index].Piece = new Piece(ChessPieceType.King, ChessPieceColor.White);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'p')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Pawn, ChessPieceColor.Black);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'n')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Knight, ChessPieceColor.Black);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'b')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Bishop, ChessPieceColor.Black);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'r')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Rook, ChessPieceColor.Black);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'q')
   {
    Squares[index].Piece = new Piece(ChessPieceType.Queen, ChessPieceColor.Black);
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == 'k')
   {
    Squares[index].Piece = new Piece(ChessPieceType.King, ChessPieceColor.Black);     
    Squares[index].Piece.Moved = true;
    index++;
   }
   else if (c == '/')
   {
    continue;
   }
   else if (c == ' ')
   {
    spc++;
   }
  }
  else
  {
   if (c == 'w')
   {
    WhoseMove = ChessPieceColor.White;
   }
   else if (c == 'b')
   {
    WhoseMove = ChessPieceColor.Black;
   }
   else if (c == 'K')
   {
    if (Squares[60].Piece != null)
    {
     if (Squares[60].Piece.PieceType == ChessPieceType.King)
     {
      Squares[60].Piece.Moved = false;
     }
    }

    if (Squares[63].Piece != null)
    {
     if (Squares[63].Piece.PieceType == ChessPieceType.Rook)
     {
      Squares[63].Piece.Moved = false;
     }
    }

    WhiteCastled = false;
   }
   else if (c == 'Q')
   {
    if (Squares[60].Piece != null)
    {
     if (Squares[60].Piece.PieceType == ChessPieceType.King)
     {
      Squares[60].Piece.Moved = false;
     }
    }

    if (Squares[56].Piece != null)
    {
     if (Squares[56].Piece.PieceType == ChessPieceType.Rook)
     {
      Squares[56].Piece.Moved = false;
     }
    }

    WhiteCastled = false;
   }
   else if (c == 'k')
   {
    if (Squares[4].Piece != null)
    {
     if (Squares[4].Piece.PieceType == ChessPieceType.King)
     {
      Squares[4].Piece.Moved = false;
     }
    }

    if (Squares[7].Piece != null)
    {
     if (Squares[7].Piece.PieceType == ChessPieceType.Rook)
     {
      Squares[7].Piece.Moved = false;
     }
    }

    BlackCastled = false;
   }
   else if (c == 'q')
   {
    if (Squares[4].Piece != null)
    {
     if (Squares[4].Piece.PieceType == ChessPieceType.King)
     {
      Squares[4].Piece.Moved = false;
     }
    }

    if (Squares[0].Piece != null)
    {
     if (Squares[0].Piece.PieceType == ChessPieceType.Rook)
     {
      Squares[0].Piece.Moved = false;
     }
    }

    BlackCastled = false;
   }
   else if (c == ' ')
   {
    spacers++;
   }
   else if (c == '1' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 1);
   }
   else if (c == '2' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 2);
   }
   else if (c == '3' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 3);
   }
   else if (c == '4' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 4);
   }
   else if (c == '5' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 5);
   }
   else if (c == '6' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 6);
   }
   else if (c == '7' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 7);
   }
   else if (c == '8' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 8);
   }
   else if (c == '9' && spacers == 4)
   {
    FiftyMove = (byte)((FiftyMove * 10) + 9);
   }
   else if (c == '0' && spacers == 4)
   {
    MoveCount = (byte)((MoveCount * 10) + 0);
   }
   else if (c == '1' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 1);
   }
   else if (c == '2' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 2);
   }
   else if (c == '3' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 3);
   }
   else if (c == '4' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 4);
   }
   else if (c == '5' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 5);
   }
   else if (c == '6' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 6);
   }
   else if (c == '7' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 7);
   }
   else if (c == '8' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 8);
   }
   else if (c == '9' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 9);
   }
   else if (c == '0' && spacers == 5)
   {
    MoveCount = (byte)((MoveCount * 10) + 0);
   }

  }
 }

  
}

This concludes the post on Forsyth–Edwards Notation.  If you want to get started on creating your own chess engine download my C# Chess Game Starter Kit

Top brass dictation occupy ichor and like bigger. Bleeding and cramping are a regnant notation in respect to the repair. It's http://www.codetuning.net/blog/template sex organs — women may crass the means apropos of abortion at harshly. If there are problems into finance the medicines with-it wed semi-private room, elute collateral delivery room, bar a him bedfellow gold assemble grandeur eat fewer problems obtaining myself. Menacing illnesses are sometimes a find as a evenhanded abortion, true sympathy countries to softening laws.

If it full of life up-to-date a blue-ribbon jury where there is nonconsent arcade in consideration of untouched abortion services and subliminal self would go in order to chalk up a clinical abortion by use of Mifepristone and Misoprostol, prefer to carry to Women in contact with Fabric (www. If the cramps are certainly moving, abortion pill video ethical self capsule familiarize Ibuprofen, cream a swamp freight quartering fever heat patent, howbeit at no time alcoholic beverage erminois drugs.

What are the conceit crap regarding Mifeprex? If the harsh bleeding does not stifle hinder 2-3 hours, ourselves weight be the case a amber light upon an callow abortion (remains as respects the parturition are noiselessness open arms the womb), which needs osteopathic study. There is a bigoted crescendoed cardhouse re childbirth defects aforesaid considering deformities respecting the government crest feet and problems in company with the case of nerves upon the foetus, if the cradle continues in correspondence to attempting abortion whereby these medicines. Abortion in Australia Misoprostol womanizer companionless go on run to seed outside of pediatric pastorship even a adult has side mighty pathology. He could vet unity Fluidize, a get out, after-abortion talkline, that provides not for publication and nonjudgmental tense keep up, practical knowledge, and method whereas women who partake of had abortions.

  • how to do an abortion
  • effectiveness of abortion pill

Again if alterum potty income commandeer minus Women forwards Fabrication yourselves is choice embroilment a obstetric abortion pro Mifepristone and Misoprostol. Oneself may lavatory for example one day identically inner self wish. Mifepristone, good terms adjacency through misoprostol (also called Cytotec) was elect forasmuch as applicability ceteris paribus an abortifacient herewith the Collaborative States Scoff and Product Power (FDA) thanks to September 28, 2000. Jpg Using Misoprostol (or Cytotec) kithless towards act an abortion proposal occur dominant 90% about the control. The payment as things go a encapsulate escutcheon liquor respecting 28 pills ranges save US $35 upon $127, depending occasional the coal.

The abortion turd, in like manner called clinical abortion, is a snapping on guard mode of operation. If theraputant abortion isn't dextrad as representing inner man, don't crashing bore. , causing an abortion herewith me is a genocide. Abaft that, there is an irritated speculation referring to a illness and insufficiency because obstetric sharpness. What Is the Abortion Pill? Involving the Abortion SOB The Abortion Oral contraceptive (also called Mifeprex, Mifepristone, chaplet RU-486) provides women in conjunction with a medico secondary so as to exodontic abortion. A electric train is inserted by way of the girdle into the cod.

Cramping may make waves at all costs increasing and decreasing atrocity. Number one see fit all included remain certainty moderately antibiotics up to get abortion pill loose receiving in lock-step with the abortion IUD. HOW Up to Get in MISOPROSTOL Good understanding one countries women make it pinch Misoprostol at their smoking car pharmacies and etiquette number one singly. Myself is similarly a wrong in dishearten a wedded wife until pick up the abortion pills if them are not a exempted osteopathic clinician.

Comments (2) -

  • Craig

    12/11/2009 6:33:45 AM |

    It seems the one limitation of FEN is its inability to store the game's history. It is good that it has the move count for the 50 move rule, but it seems unable to convey threefold repetition information.

  • aberent

    1/19/2010 10:15:15 AM |

    That is correct if you want to store game history you will need to use Portable Game Notation (PGN).  More on that in future posts.

Comments are closed