Skip to content

Geras1mleo/Chess

Repository files navigation

Gera Chess Library

Develop your chess app with C# lib and ♥ from Geras1mleo

GitHub top language GitHub last commit Nuget

Nuget

Take your chess app to the next level with the Gera Chess Library! This chess logic library is made with C# .NET 6.0/8.0 and is available on NuGet, so you can start using it right away.

The library includes a ChessBoard with a 2-dimensional array of Pieces and the ability to generate, validate, and execute moves with ease. You can also parse Move objects into Standard Algebraic Notation (SAN) and back. Plus, you can load and play a chess game from Forsyth-Edwards Notation (FEN) and Portable Game Notation (PGN) and vice versa.

Get ready for an eventful chess programming experience with the Gera Chess Library. The library has event handlers that are raised for an invalid move that places the king in check, change in king checked status, when a pawn is promoted with ability to specify new promoted piece, and when the end game is declared.

You can also navigate between executed moves, cancel the last executed move, and declare a draw or resign for one of the sides.

Since recent version FIDE and chess.com end game rules such as: InsufficientMaterial, FiftyMoveRule and Repetition are available. These rules are optional and can be specified with AutoEndgameRules property flags.

Usage!

Example simple console chess game:

using Chess;

var board = new ChessBoard();

while (!board.IsEndGame)
{
    Console.WriteLine(board.ToAscii());
    board.Move(Console.ReadLine());
}

Console.WriteLine(board.ToAscii());
Console.WriteLine(board.ToPgn());

// Outcome after last move:
// Qh5
//   ┌────────────────────────┐
// 8 │ r  n  b  q  k  b  n  r │
// 7 │ p  p  p  p  p  .  .  p │
// 6 │ .  .  .  .  .  .  .  . │
// 5 │ .  .  .  .  .  p  p  Q │
// 4 │ .  .  .  .  P  P  .  . │
// 3 │ .  .  .  .  .  .  .  . │
// 2 │ P  P  P  P  .  .  P  P │
// 1 │ R  N  B  .  K  B  N  R │
//   └────────────────────────┘
//     a  b  c  d  e  f  g  h
//
// 1. e4 f5 2. f4 g5 3. Qh5# 1-0

Example random chess game:

using Chess;

var board = new ChessBoard() { AutoEndgameRules = AutoEndgameRules.All };

while (!board.IsEndGame)
{
    var moves = board.Moves();
    board.Move(moves[Random.Shared.Next(moves.Length)]);
}

Console.WriteLine(board.ToAscii());
Console.WriteLine(board.ToPgn());

Track Pieces

Keep track pieces on board using C# indexers:

board["c2"]     // => White Pawn
board['g',8]    // => Black Bishop

// Coordinates counting from 0
board[0, 0]                   // => White Rook
// Custom Position object
board[new Position(4, 7)]     // => Black King

Keep track of all captured pieces:

board.CapturedWhite // => White pieces that has been captured by black player
board.CapturedBlack // => Black pieces that has been captured by white player

Properties above also include captured pieces when board has been loaded from FEN.

Track kings and their state (checked/unchecked):

board.WhiteKing // => White king position on chess board
board.BlackKing // => Black king position on chess board

board.WhiteKingChecked // => State of White king
board.BlackKingChecked // => State of Black king

board.WhiteKing and board.BlackKing are computed properties, the positions are determined at the time of invocation. On the other hand, board.WhiteKingChecked and board.BlackKingChecked are cached properties that are set after each move.

Move Pieces

Move pieces using SAN/LAN:

board.Move("e4");        // => Good
board.Move("N-f6");      // => Good
board.Move("NXf6");      // => Good
board.Move("dxc3 e.p."); // => Good
board.Move("Pe4");       // => Good
board.Move("Pe5xd6");    // => Good
board.Move("O-O-O+");    // => Good

board.Move("ne5");  // => Bad
board.Move("e8=K"); // => Bad
board.Move("0-0");  // => Bad

Move pieces using Move object and corresponding positions:

board.Move(new Move("b1", "c3"));

Ambiguity:

if(ChessBoard.TryLoadFromPgn("1. e4 e5 2. Ne2 f6", out var board))
{
  board.ToAscii();
  //   ┌────────────────────────┐
  // 8 │ r  n  b  q  k  b  n  r │
  // 7 │ p  p  p  p  .  .  p  p │
  // 6 │ .  .  .  .  .  p  .  . │
  // 5 │ .  .  .  .  p  .  .  . │
  // 4 │ .  .  .  .  P  .  .  . │
  // 3 │ .  .  .  .  .  .  .  . │
  // 2 │ P  P  P  P  N  P  P  P │
  // 1 │ R  N  B  Q  K  B  .  R │
  //   └────────────────────────┘
  //     a  b  c  d  e  f  g  h

  board.Move("Nc3"); 	// => Throws exception: ChessSanTooAmbiguousException. Both knights can move to c3
  board.Move("Nc4"); 	// => Throws exception: ChessSanNotFoundException. None of knights can move to c4
}

Load Chess game/board

Load chess board Variant: From Position (using FEN):

board = ChessBoard.LoadFromFen("1nbqkb1r/pppp1ppp/2N5/4p3/3P4/8/PPP1PPPP/RN2KB1R w KQk - 0 1");
board.ToAscii();
//   ┌────────────────────────┐
// 8 │ .  n  b  q  k  b  .  r │
// 7 │ p  p  p  p  .  p  p  p │
// 6 │ .  .  N  .  .  .  .  . │
// 5 │ .  .  .  .  p  .  .  . │
// 4 │ .  .  .  P  .  .  .  . │
// 3 │ .  .  .  .  .  .  .  . │
// 2 │ P  P  P  .  P  P  P  P │
// 1 │ R  N  .  .  K  B  .  R │
//   └────────────────────────┘
//     a  b  c  d  e  f  g  h

board.CapturedWhite // => { White Bishop, White Queen }
board.CapturedBlack // => { Black Rook, Black Knight }

// Stalemate
board.LoadFen("rnb1kbnr/pppppppp/8/8/8/8/5q2/7K w kq - 0 1");
board.EndGame // => { EndgameType = Stalemate, WonSide = null }

Load full chess game from PGN:

board = ChessBoard.LoadFromPgn(
@"[Variant ""From Position""]
[FEN ""rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1""]

1.exd5 e6 2.dxe6 fxe6 3.d4(3.f4 g5 4.fxg5) 3... c5 4.b4");

board.ToAscii();
//   ┌────────────────────────┐
// 8 │ r  n  b  q  k  b  n  r │
// 7 │ p  p  .  .  .  .  p  p │
// 6 │ .  .  .  .  p  .  .  . │
// 5 │ .  .  p  .  .  .  .  . │
// 4 │ .  P  .  P  .  .  .  . │
// 3 │ .  .  .  .  .  .  .  . │
// 2 │ P  .  P  .  .  P  P  P │
// 1 │ R  N  B  Q  K  B  N  R │
//   └────────────────────────┘
//     a  b  c  d  e  f  g  h

Alternative moves and comments are (temporarily) skipped.

In further versions: navigation between alternative branches (variations), also loading those branches from PGN. Also functionality to add comments to each move.

End Game

Declare Draw/Resign:

board.Draw();
board.EndGame // => { EndgameType = DrawDeclared, WonSide = null }

board.Clear(); // Reset board

board.Resign(PieceColor.Black);
board.EndGame // => { EndgameType = Resigned, WonSide = White }

As mentioned before, InsufficientMaterial, FiftyMoveRule and Repetition rules are available.

Here you can see all the tests that have been used to test and improve chess library. Also useful for code examples.

Here you can see the evolution of performance of chess library

Like the project?

Give it a ⭐ Star!

Found a bug?

Drop to Issues

Or: [email protected]

Thanks in advance!