Giter VIP home page Giter VIP logo

chess's Introduction

Hey there ๐Ÿ‘‹

My name is Sviatoslav and I am a CS student at UGent, coming from Belgium/Ukraine!

About me

โœจ Improving my programming skills since 2020
๐Ÿ“š Currently learning Typescript
๐Ÿ—ฃ I speak Ukrainian, Dutch and English

I code with:

csharp logo python logo java logo javascript logo dotnetcore logo postgresql logo ssh logo ubuntu logo

stats graph languages graph

chess's People

Contributors

brane-games avatar geras1mleo avatar instantiator avatar rstarkov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

chess's Issues

Cannot load certain En Passant positions from PGN (PGN and demo code included)

Describe the bug
Cannot load certain En Passant positions from PGN

Try to load this PGN (a game from Ding Liren) using ChessBoard.LoadFromPgn:

1.e4 e6 2.d4 d5 3.Nc3 Nf6 4.Bg5 dxe4 5.Nxe4 Be7 6.Bxf6 gxf6 7.Nf3 f5 8.Nc3 a6
9.Qd2 b5 10.O-O-O b4 11.Na4 Bb7 12.Bc4 Bd5 13.Qe2 Nc6 14.Rhe1 Na5 15.Bxd5 Qxd5
16.b3 Nc6 17.c4 bxc3 18.Nxc3 Qa5 19.Qc4 Nb4 20.Kb1 O-O 21.Ne5 Rad8 22.g4 f4
23.Nd3 Nxd3 24.Rxd3 Bf6 25.Red1 Bg7 26.Qc5 Qxc5 27.dxc5 Rxd3 28.Rxd3 f5 29.gxf5 Bxc3
30.Rxc3 Rxf5 31.Kc2 Rg5 32.Kd3 Rg2 33.Ke2 Rxh2 34.Rd3 e5 35.Rd5 e4 36.Rg5+ Kh8
37.Rg4 e3 38.Rxf4 exf2 39.Rf7 c6 40.a4 Kg8 41.Rc7 Rh3 42.Rxc6 Rxb3 43.Rxa6 Rb2+
44.Kf1 Kf7 45.a5 Ke8 46.Ra8+ Kd7 47.a6 Ra2 48.a7 Kc7 1/2-1/2

If fails with "'Given SAN move: Qc4 has been not found with current board positions.'"

This happens because in move 17 when w takes En Passant with bxc3, if you draw the board at that moment, you can see that the board has not had the pawn on c4 removed.

lichess analysis board does handle this PGN correctly.

To Reproduce

var pgn = "1.e4 e6 2.d4 d5 3.Nc3 Nf6 4.Bg5 dxe4 5.Nxe4 Be7 6.Bxf6 gxf6 7.Nf3 f5 8.Nc3 a6\r\n9.Qd2 b5 10.O-O-O b4 11.Na4 Bb7 12.Bc4 Bd5 13.Qe2 Nc6 14.Rhe1 Na5 15.Bxd5 Qxd5\r\n16.b3 Nc6 17.c4 bxc3 18.Nxc3 Qa5 19.Qc4 Nb4 20.Kb1 O-O 21.Ne5 Rad8 22.g4 f4\r\n23.Nd3 Nxd3 24.Rxd3 Bf6 25.Red1 Bg7 26.Qc5 Qxc5 27.dxc5 Rxd3 28.Rxd3 f5 29.gxf5 Bxc3\r\n30.Rxc3 Rxf5 31.Kc2 Rg5 32.Kd3 Rg2 33.Ke2 Rxh2 34.Rd3 e5 35.Rd5 e4 36.Rg5+ Kh8\r\n37.Rg4 e3 38.Rxf4 exf2 39.Rf7 c6 40.a4 Kg8 41.Rc7 Rh3 42.Rxc6 Rxb3 43.Rxa6 Rb2+\r\n44.Kf1 Kf7 45.a5 Ke8 46.Ra8+ Kd7 47.a6 Ra2 48.a7 Kc7  1/2-1/2";
var cb = ChessBoard.LoadFromPgn(pgn);

Expected behaviour
Loading games with En Passant would work.

Screenshots
image

Additional context
I'm working around this by manually reconstructing the board and hacking around this, but not ideal.

Otherwise, I really like the library =)

Here is a demo showing

  1. loading the game up to before the e.p. capture - all good
  2. it DOES the e.p. but does NOT remove the pawn
  3. later on this causes problems.

image

Checkmate not being recognized

Describe the bug
In a position achieved via the given PGN, a checkmate isn't recognized. It recognizes this as just a check

To Reproduce
`// "1. e3 e5 2. d4 e4 3. Nf3 exf3 4. Qxf3 d5 5. Qxf7+ Kxf7 6. e4 Nc6 7. exd5 Qxd5 8. c4 Qe4+ 9. Kd1 Nxd4 10. Bd3 Qxd3+ 11. Ke1 Be7 12. Nc3 Nc2+";

        var listOfMoves = new List<string>() { 
            "e2e3", "e7e5", "d2d4", "e5e4", "g1f3", "exf3", 
            "d1f3", "d7d5", "f3f7", "e8f7", "e3e4", "b8c6", 
            "e4d5", "d8d5", "c2c4", "d5e4", "e1d1", "c6d4",
            "f1d3", "e4d3", "d1e1", "f8e7", "b1c3", "d4c2"};
        var board = ChessBoard.LoadFromFen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
        foreach (var moveInfo in listOfMoves)
        {
            board.Move(moveInfo);
        }
        Assert.True(board.IsEndGame);`

Expected behaviour
board.IsEndGame returns true

Additional context
Working on a game and this is a legitimate position I got while playing against AI. Needless to say the whole game just stopped in this moment as Checkmate wasn't flagged and I couldn't move ๐Ÿ˜€

Suggestion to add Move.IsPromotion and Move.IsEnpassant

I found a way to achieve this
move.Parameter is MovePromotion returns true when the move is a promotion.

And to find out what the promoted piece is, I do

Piece p = new Piece(move.Parameter.ShortStr[1]);
Console.WriteLine(p.Type);

And to check whether a move is EnPassant, I do
move.Parameter is MoveEnPassant

I guess this works since a move can't be both En Passant and promotion at the same time. But it's not very straightforward.

It would be nice if the library supported
Move.Promotion which returns the promoted piece or null when there is no promotion.

Also consider adding Move.IsEnPassant and Move.IsCastling

Anyways, thanks for the amazing library.

ParseToSan and TryParseToSan seem to return null for valid Moves

Describe the bug

I've been having some difficulty with the Chessboard.ParseToSan and .TryParseToSan methods. Despite the Move provided passing ChessBoard.IsValidMove, the .ParseToSan methods return null for the SAN string (.TryParseToSan returns true which leads me to believe the string shouldn't be null).

To Reproduce

I wrote a quick unit test for it (edit: which now also contains the fix I'm proposing because I didn't link to a specific commit)

Expected behaviour

I'm expecting the returned string to contain the SAN equivalent for the move, based on the state of the current board.

Additional context

Hey - hope all's well. I love the library, and I've adopted it for my current project: instantiator/consensus-chess-engine as it's lightweight, and does everything I need (notwithstanding this particular issue). I'd be glad to dig a little deeper and see if I can help figure out what's happening, but I suspect you'd be able to go faster...

ToFen() sometimes doesn't make the proper Fen

Describe the bug
After a LoadFromFen() with at least one particular string, although the resulting .FenBuilder looks correct (and correctly gives the proper FEN when you ask for FenBuilder.ToString()), the .ToFen() method does not properly include the en passant square.

To Reproduce

var board = ChessBoard.LoadFromFen("rnbqkbnr/ppppp1pp/8/8/4P1pP/8/PPPP1P2/RNBQKBNR b KQkq h3 0 4");

At this point if you use the debugger, you will see that board.ToFen() returns "rnbqkbnr/ppppp1pp/8/8/4P1pP/8/PPPP1P2/RNBQKBNR b KQkq - 0 4" but board.FenBuilder.ToString() returns the expected "rnbqkbnr/ppppp1pp/8/8/4P1pP/8/PPPP1P2/RNBQKBNR b KQkq h3 0 4"

Expected behaviour
.ToFen() should reproduce the FEN that .LoadFromFen() used to create the board, including the en passant square.

Screenshots
N/A

Additional context
NOTE: Even with the board being created using .LoadFromFen(), the ChessBoard.Moves() list DOES contain the available en passant capture moves. However, when doing board.Move(oneOfThoseEnPassantMoves) the return value is false and the board is not modified.

Promoting moves from UCI are not accepted

When a match between engines using UCI is played, a promoting move has the format of: h7h8q. This move is not accepted by the library and I believe it should be. Of course it is trivial to convert the h7h8q to h8=Q but I believe this should be supported out of the box.

To Reproduce

var board = ChessBoard.LoadFromFen("8/4R2P/3K4/8/p7/P2b4/1P6/3k4 w - - 3 68");
board.Move("h7h8q");

Expected behaviour
The move is accepted.

I'd be willing to implement this myself if you agree that this is a bug. Thanks a lot for the great library!

False positives on Move.InCheck on promotion moves

Describe the bug
A move that promotes a pawn to a piece that does not deliver check is mistakenly set to IsCheck=true if there are other possible promotions (that is, to other pieces) that WOULD give check.

To Reproduce

var board = ChessBoard.LoadFromFen("k7/7P/8/8/8/8/8/K7 w - - 0 1");
var checks = board.Moves().Where(static move => move.IsCheck).ToList();

You will see that checks.Count is 4, when it should be 2, and that the List includes both h8=N+ and h8=B+ when neither of these promotions actually deliver check.

Expected behaviour
Moves that promote to pieces that do not deliver check should have Move.IsCheck == false. In the example code above, the checks List should contain only two moves: h8=Q+ and h8=R+

Screenshots
N/A

Additional context
N/A

Detecting draws

This library is really cool! I'm making a game around it and I believe it would benefit of having ways to detect if a draw has been reached (three fold repetition or 50 moves rule)

Describe the solution you'd like

  • A method that checks if a draw condition has been reached

Chess bug

Describe the bug
Castling move is not shown properly in ExecutedMoves. It is applicable in both short castling and long castling. Instead of e8g8, it is showing e8h8 for black short castling. Same way instead of White long castling it is showing e1a1 instead of e1c1.
Conversions / Validations / ...

To Reproduce
Steps to reproduce the behaviour or
Eventually a call stack and input data

        string str = "1. e4 c5 2. Nf3 d6 3. Nc3 Nc6 4. Bb5 Nf6 5. d3 a6 6. Bxc6+ bxc6 7. Bg5 g6 8. Qd2 Bg7 9. Bh6 O-O 10. Bxg7 Kxg7 11. O-O-O Rb8 12. Ng5 Qb6 13. Na4 Qb5 14. b3 d5 15. e5 Nd7 16. e6 Nf6 17. exf7 h6 18. Nf3 Be6 19. Ne5 Bxf7 20. Nxf7 Rxf7 21. f3 c4 22. dxc4 dxc4 23. Qc3 cxb3 24. axb3 Qg5+ 25. Kb1 e6 26. Nc5 Kg8 27. g4 Rb5 28. Rd8+ Rf8 29. Rxf8+ Kxf8 30. Nxe6+ Kf7 31. Nxg5+ 1-0";

var board = new ChessBoard();
board = ChessBoard.LoadFromPgn(str);
foreach(var move in board.ExecutedMoves)
{

//Check 9th move of black and 11th move of white. Instead of e8g8, it is showing e8h8 for black short castling. Same way instead of White long castling it is showing e1a1 instead of e1c1. King would not move to extreme corner after castling.

}

Expected behaviour
A clear and concise description of what you expected to happen.

Black short castling = e8g8
White long castle = e1c1

same way,
Black long castling = e8c8
White short castle = e1g1

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Add any other context about the problem here.

Not recognizing InsufficientMaterial EndGame

Describe the bug
A board with insufficient material is not being recognized as such, and its IsEndGame is false, etc.

To Reproduce

var board = ChessBoard.LoadFromFen("2b5/4kB2/8/8/8/8/5K2/8 b - - 0 16");
if (!board.IsIendGame)
    throw new ();

Expected behaviour
Boards such as the one used in the reproduction example should be recognized as having insufficient material to proceed, and the game drawn, with board.EndGame.EndgameType == EndgameType.InsufficientMaterial, and with its board.ToPgn() string being given the ยฝ-ยฝ, etc., etc.

Screenshots
N/A

Additional context
I know that you probably have a much better way to fix this in the library, but in case it is in any way useful, here is the code I added as a workaround in my application:

private static bool IsDrawnForInsufficientMaterial(this ChessBoard board)
{
    //	Insufficient Material isn't properly detected.  Honestly, I checked. Do it ourselves.
    //	If there are any pawns, rooks, or queens on the board, there is sufficient material.
    var fen = board.ToFen().Split()[0];
    if ("PQR".Any(fen.ToUpper().Contains))
	return false;
    // Otherwise, it's just bishops, knights, and kings.  Well, yeah, kings -- ignore them....
    var remainingPieces = new string(fen.Where(static c => c is > '8' and not ('K' or 'k')).ToArray());
    //	Kings only or King against a single bishop or knight is drawn.
    //	Otherwise, except for a bishop apiece, it's sufficient.
    //	In B vs b, it's a draw if both bishops are on light squares or both on dark squares.
    return remainingPieces.Length < 2
        || remainingPieces is "Bb" or "bB"
        && Regex.Replace(fen, "[2468]", string.Empty).Select(static (c, i) => c is 'B' or 'b' ? i : 0).Sum() % 2 is 0;
}

Wrong Fen

Describe the bug
After first move "e2" to "e4" the method "ToFen()" returns wrong value. In this case the En-Passant move is shown, but actually it should not be there since there is no black pawn that could capture. If you import this wrong Fen to Lichess for example, it fails.

To Reproduce
var cb = new ChessBoard();
cb.Move(new Move("e2", "e4");
var fen = cb.ToFen();

Expected behaviour
fen --> rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1

Actual behaviour
fen --> rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1

Chess.ChessBoard Deserialization exception

Describe the bug
When using Newtonsoft.Json to Deserialize a ChessBoard object, I get the following exception:
Newtonsoft.Json.JsonSerializationException: 'Error setting value to 'MoveIndex' on 'Chess.ChessBoard'.
with the Inner Exception being:
IndexOutOfRangeException: Move not found

I get this when executing this line of my code:
JsonConvert.DeserializeObject<T>(value);
where value is an instance of type T : Solver
and Solver is a class that contains this serialized field:

	[JsonProperty]
	private readonly Dictionary<string, MyPosition> _savedPositions = new ();

and MyPosition is a sealed record that contains this serialized field:
public ChessBoard Board { get; set; }

To Reproduce

sealed record MyPosition
{
	public ChessBoard Board { get; set; } = new ();

        // Actually, since the error involves MoveIndex and the Move class, it may be that
        // one or more Moves may need to be made on the Board in order to get it into a
        // state where the Deserialization exception happens??  I do not know, but it is
        // certainly the case that one or more moves were indeed made on the Boards I
        // am trying to Serialize/Deserialize.
}
class Solver
{
	[JsonProperty]
	private readonly Dictionary<string, MyPosition> _savedPositions = new () { ["test"] = new () };
}
...
var serialized = JsonConvert.SerializeObject(new Solver());
var deserialized = JsonConvert.DeserializeObject<Solver>(serialized);

Expected behaviour
The object should deserialize.

Screenshots
N/A

Additional context
N/A

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.