Move Content

In our Chess Engine we will need to describe movement as it occurs. This will be useful to keep track move history, the best move at each search level or even the result of our Alpha Beta Search. The Move Content class has 2 major components. The first component describes the moving chess piece(s). The second component describes the chess piece taken or captured during the move. These two components described as 2 structs:

public struct PieceMoving
{
 public byte DstPosition;
 public bool Moved;
 public ChessPieceColor PieceColor;
 public ChessPieceType PieceType;
 public byte SrcPosition;
 public PieceMoving(ChessPieceColor pieceColor, ChessPieceType pieceType, bool moved,
        byte srcPosition, byte dstPosition)
 {
  PieceColor = pieceColor;
  PieceType = pieceType;
  SrcPosition = srcPosition;
  DstPosition = dstPosition;
  Moved = moved;
 }

 public PieceMoving(PieceMoving pieceMoving)
 {
  PieceColor = pieceMoving.PieceColor;
  PieceType = pieceMoving.PieceType;
  SrcPosition = pieceMoving.SrcPosition;
  DstPosition = pieceMoving.DstPosition;
  Moved = pieceMoving.Moved;
 }

 public PieceMoving(ChessPieceType pieceType)
 {
  PieceType = pieceType;
  PieceColor = ChessPieceColor.White;
  SrcPosition = 0;
  DstPosition = 0;
  Moved = false;
 }
}
public struct PieceTaken
{
 public bool Moved;
 public ChessPieceColor PieceColor;
 public ChessPieceType PieceType;
 public byte Position;
 public PieceTaken(ChessPieceColor pieceColor, ChessPieceType pieceType, bool moved,
       byte position)
 {
  PieceColor = pieceColor;
  PieceType = pieceType;
  Position = position;
  Moved = moved;
 }

 public PieceTaken(ChessPieceType pieceType)
 {
  PieceColor = ChessPieceColor.White;
  PieceType = pieceType;
  Position = 0;
  Moved = false;
 }
}

The Move Content class itself makes use of the above 2 structs by declaring them into 3 fields:

  • PieceMoving MovingPiecePrimary – The primary piece that has moved. •
  • PieceMoving MovingPieceSecondary; – The secondary piece that has moved. This is usually null unless a king has castled. In this case the primary Piece would be the king and the secondary piece would be the rook. •
  • PieceTaken TakenPiece – The chess piece that was capture or taken during the move.

The other fields like Score, Pawn Promoted and En Passant Occurred are self explanatory. However the last method ToString requires a bit of an explanation. The Move Content class will be used to generate Portable Game Notation (PGN) string of the game. For this reason I overwrote the ToString() method for the class so that it will return a portion of the PGN string for the move that has occurred.

public new string ToString()
{
    string value = "";
    var srcCol = (byte) (MovingPiecePrimary.SrcPosition%8);
    var srcRow = (byte)(8 - (MovingPiecePrimary.SrcPosition / 8));
    var dstCol = (byte) (MovingPiecePrimary.DstPosition%8);
    var dstRow = (byte) (8 - (MovingPiecePrimary.DstPosition/8));

    if (MovingPieceSecondary.PieceType == ChessPieceType.Rook)
    {
        if (MovingPieceSecondary.PieceColor == ChessPieceColor.Black)
        {
            if (MovingPieceSecondary.SrcPosition == 7)
            {
                value += "O-O";
            }
            else if (MovingPieceSecondary.SrcPosition == 0)
            {
                value += "O-O-O";
            }
        }
        else if (MovingPieceSecondary.PieceColor == ChessPieceColor.White)
        {
            if (MovingPieceSecondary.SrcPosition == 63)
            {
                value += "O-O";
            }
            else if (MovingPieceSecondary.SrcPosition == 56)
            {
                value += "O-O-O";
            }
        }
    }
    else
    {
        value += GetPgnMove(MovingPiecePrimary.PieceType);

        switch (MovingPiecePrimary.PieceType)
        {
            case ChessPieceType.Knight:
                value += GetColumnFromInt(srcCol + 1);
                value += srcRow;
                break;
            case ChessPieceType.Rook:
                value += GetColumnFromInt(srcCol + 1);
                value += srcRow;
                break;
            case ChessPieceType.Pawn:
                if (srcCol != dstCol)
                {
                    value += GetColumnFromInt(srcCol + 1);
                }
                break;
        }

        if (TakenPiece.PieceType != ChessPieceType.None)
        {
            value += "x";
        }

        value += GetColumnFromInt(dstCol + 1);

        value += dstRow;

        if (PawnPromoted)
        {
            value += "=Q";
        }
    }

    return value;
}

Notice: Since the Move Content class and all its components will be used to display information outside of the chess engine like the user interface all the Move Content components and the class itself were declared as public.

The above ToString() method requires a few helper methods that convert objects to strings:

private static string GetColumnFromInt(int column)
{
    switch (column)
    {
        case 1:
            return "a";
        case 2:
            return "b";
        case 3:
            return "c";
        case 4:
            return "d";
        case 5:
            return "e";
        case 6:
            return "f";
        case 7:
            return "g";
        case 8:
            return "h";
        default:
            return "Unknown";
    }
}
private static string GetPgnMove(ChessPieceType pieceType)
{
    switch (pieceType)
    {
        case ChessPieceType.Bishop:
            return "B";

        case ChessPieceType.King:
            return "K";

        case ChessPieceType.Knight:
            return "N";

        case ChessPieceType.Queen:
            return "Q";

        case ChessPieceType.Rook:
            return "R";
        default:
            return "";
    }
}

This concludes the Move Content class.

Want to skip to the end, download the full chess engine source code on GitHub