/ChessEngine

Simple, well performed and enough optimized C#/.NET bitboard chess engine.

Primary LanguageC#MIT LicenseMIT

ChessEngine

Chess engine with bitboard representation with no external dependencies. Only C# and .NET 8.

To Do:

  • Basic bitboard and square management operations.
  • Movegen for all moves.
  • Parsing FEN to Position.
  • Simple Perft (no hashtables or parallel calculations).
  • Algebraic notation parsing.
  • PGN (optional).
  • Hashtables for Perft.
  • UCI.
  • Play game functional.

Perft benchmarks

Current perft benchmarks for Initial Position rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 with depth 6.

  • No hashtables.
  • No parralel calculations. Everying is in 1 thread.
  • MakeMove/UndoMove with copy Position (bitboards) approach.
  • Movegen gives pseudolegal moves then check for IsKingChecked() determines if move is legal

See also about Perft: https://www.chessprogramming.org/Perft_Results

Benchmarks collected using BenchmarkDotNet.

Runned on

Intel Core i5-8300H CPU 2.30GHz (Coffee Lake), 1 CPU, 8 logical and 4 physical cores

.NET SDK 8.0.205

Results

Method Mean Error StdDev
StartPos_Depth_6 3.564 s 0.0484 s 0.0429 s

This is average result. Sometimes benchmarks could be a bit faster or a bit slower. (~3.443 s or ~3.613 s)

Example of usage

Create chess game

Create start position board.

ChessGame chessGame = new();

Or

string fen = "";
_ = ChessGame.TryCreateFromFen(fen, out ChessGame chessGame);

Make move

string moveInput = "a2a4";
AlgebraicMove move = AlgebraicMove.Parse(inputMove);
MoveResult moveResult = chessGame.MakeMove(in move);
Console.WriteLine(moveResult);
// >> Move
// There also could be 'Check', 'Capture', 'Checkmate', 'Stalemate'.
// MoveResult is enums with flags.

Get Board

Span<ChessPiece> pieces = stackalloc ChessPiece[64];
chessGame.GetBoardToSpan(pieces);

Console.WriteLine("{0}, {1}", 
	pieces[0].PieceColor, 
	pieces[0].PieceValue);

// >> White, Rook

Empty squares are equal to ChessPiece.Empty. Or just check it with piece.IsEmpty().