Complicating code in C#

Discussion of chess software programming and technical issues.

Moderator: Ras

Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Yes. But I already have eliminated most of them. Only few left.
I have class ChessPosition and a class ChessBoard. I currently store fifty move count in ChessPosition.
So it makes a copy of ChessPosition as well as a copy of ChessBoard when making a move.
That's a bit too much. Also I store GamePhase in ChessPosition. ChessPosition has property ChessBoard.
So maybe I have to eliminate class ChessPosition as well. Put all necessary data in ChessBoard and nothing extra.

But I suspect that Stockfish is doing some clever tricks in check detection/evasion or move generation.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Complicating code in C#

Post by Sven »

It has already been stated a few times: making movegen faster (or check detection, same topic) can't make the search faster by an order of magnitude because the search spends only a small amount of time in movegen, usually between 10% and 30%, so that even making the whole movegen three times as fast as before would only result in a search speedup between 7% and 25%.

Having a position class and a board class sounds ok. Copy&make is not unusual but it can be time consuming if you copy large and/or very complex data. You know that of course ...

If your data structures are not the reason for low speed then it could also be data flow and algorithms.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

I also store moveNumber in ChessPosition. That is last number of the fen.
Don't know where to put it. Maybe in Game.

I only use it to check if position.ConvertToFen() == fen
But if position does not store this moveNumber anymore then that check fails.
So can't do an easy string compare,
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Bit expensive to copy whole array for changing only one bit.
This happens when doing a null move.
It is part of copy move strategy. Instead of do undo.

Code: Select all

  
        public IChessBoard ChangePlayer()
        {
            ulong[] cp = new ulong[NBITBOARDS];
            Pieces.CopyTo(cp, 0);
            cp[OTHER] ^= CUR_PLAYER;
            var result = new ChessBoardBits(cp);
            return result;
        }
 
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Complicating code in C#

Post by Sven »

What is cp[OTHER], what is CUR_PLAYER? Both seem to be bitboards while I would expect something like White or Black ...

Also for copy&make based null move I would expect something like this (I apologize for my C# syntax sloppiness):

Code: Select all

public IChessBoard AfterNullMove()
{
    var result = new ChessBoardBits(Pieces);
    result.Player = Opponent(result.player);
    // and do possible other updates, e.g. reset ep target sqr and 50-moves counter
    return result;
}
which avoids copying the piece bitboards twice.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

New record 53 moves. Previous record 32 moves. But Skipper played Petroff's defence.
[pgn]
[Event "Computer Chess Game"]
[Site "LAPTOP-1FK7MTIP"]
[Date "2021.04.27"]
[Round "-"]
[White "Stockfish 13"]
[Black "Skipper_8_6"]
[Result "1-0"]
[TimeControl "180"]
[Annotator "1. +0.19 1... -0.02"]

1. e4 {+0.19/26} e5 {-0.02/13 4} 2. Nf3 {+0.47/23 0.2} Nf6 {-0.01/13 4} 3.
Nxe5 {+0.47/22 1.8} d6 {-0.02/19 4} 4. Nf3 {+0.47/26 0.1} Nxe4 {-0.05/18 3}
5. d4 {+0.44/25 1.3} Nc6 {+0.00/16 3} 6. Bd3 {+0.62/24 3} d5 {-0.01/9 3} 7.
O-O {+0.58/25 2.1} Nb4 {+0.00/11 3} 8. Re1 {+1.22/23 3} Be7 {-0.13/11 3} 9.
Bxe4 {+1.37/26 0.1} dxe4 {-0.38/11 3} 10. Rxe4 {+1.26/25 0.4} Bf5
{-0.37/9 3} 11. Re2 {+1.42/24 1.2} c5 {-0.34/10 3} 12. Bg5 {+2.17/25 7} f6
{-0.12/13 2.9} 13. Bf4 {+2.21/24 0.1} cxd4 {+0.33/6 2.9} 14. Nxd4
{+2.16/24 2.8} Nc6 {-0.28/9 2.8} 15. Rd2 {+2.07/24 0.2} Nxd4 {-0.29/10 2.8}
16. Rxd4 {+2.12/24 0.2} Qc8 {-0.28/9 2.7} 17. Nc3 {+2.10/23 0.2} O-O
{-0.29/14 2.7} 18. Nd5 {+2.27/23 2.4} Bc5 {-0.08/7 2.6} 19. b4
{+3.33/25 1.8} Bxd4 {+0.09/19 2.6} 20. Ne7+ {+3.94/24 0.4} Kh8
{+0.05/17 2.5} 21. Nxc8 {+3.71/26 0.7} Bxa1 {-0.12/14 2.5} 22. Nd6
{+3.78/25 0.5} Be5 {-0.07/12 2.4} 23. Bxe5 {+3.71/24 1.9} fxe5
{-0.10/10 2.4} 24. Qd5 {+4.13/23 1.5} Bxc2 {+0.40/12 2.3} 25. Nf7+
{+4.77/24 2.7} Rxf7 {+0.00/677 4} 26. Qxf7 {+4.86/26 0.1} Rd8 {+0.00/740 4}
27. h3 {+5.00/27 0.2} Be4 {-0.58/11 2.2} 28. Qe7 {+5.01/27 1.6} Rd1+
{-1.50/20 2.2} 29. Kh2 {+5.00/24 0.5} h6 {-1.85/11 2.1} 30. Qxe5
{+5.02/27 0.9} Bd5 {-2.15/11 2.1} 31. Qb8+ {+5.56/22 2.4} Kh7
{-2.35/11 2.0} 32. Qxa7 {+5.38/24 5} g6 {-2.27/12 2.0} 33. Qc5 {+6.48/22 5}
Rd2 {-2.76/9 1.9} 34. a4 {+6.71/21 1.7} Bf7 {-2.86/11 1.9} 35. Qc7
{+7.78/21 2.8} Rxf2 {-3.27/13 1.9} 36. Qxb7 {+8.78/22 4} Kg8 {-5.28/15 1.9}
37. b5 {+9.01/20 0.4} Rd2 {-5.23/9 1.8} 38. Qc8+ {+9.64/21 2.6} Kh7
{-6.26/40 1.9} 39. Qc7 {+9.71/23 3} Kg8 {-5.86/25 1.8} 40. Qc3
{+10.09/20 0.8} Re2 {-6.25/9 1.7} 41. b6 {+10.99/19 2.9} Bd5 {-7.01/8 1.7}
42. Qc8+ {+19.27/21 2.2} Kg7 {-9.24/12 1.6} 43. Qd7+ {+24.25/23 0.8} Bf7
{-12.15/12 1.6} 44. b7 {+31.90/21 0.8} Re8 {-12.15/10 1.6} 45. a5
{+72.65/24 1.9} g5 {-12.15/8 1.5} 46. a6 {+99.77/25 2.2} g4 {-12.17/6 1.5}
47. Qxg4+ {+99.83/36 0.6} Kh8 {-16.44/7 1.5} 48. a7 {+99.87/59 2.2} Kh7
{-18.27/10 1.5} 49. b8=Q {+99.89/63 2.2} Rxb8 {-22.10/7 1.4} 50. axb8=Q
{+99.93/245 1.4} h5 {-327.60/238 2.0} 51. Qg5 {+99.95/245 0.1} h4
{-327.62/265 2.0} 52. Qf8 {+99.97/245 0.8} Be6 {-327.64/304 2.1} 53. Qgh6#
{+99.99/245 0.8}
{Xboard adjudication: Checkmate} 1-0
[/pgn]
Last edited by Henk on Tue Apr 27, 2021 11:00 pm, edited 2 times in total.
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Sven wrote: Tue Apr 27, 2021 9:43 pm What is cp[OTHER], what is CUR_PLAYER? Both seem to be bitboards while I would expect something like White or Black ...

Also for copy&make based null move I would expect something like this (I apologize for my C# syntax sloppiness):

Code: Select all

public IChessBoard AfterNullMove()
{
    var result = new ChessBoardBits(Pieces);
    result.Player = Opponent(result.player);
    // and do possible other updates, e.g. reset ep target sqr and 50-moves counter
    return result;
}
which avoids copying the piece bitboards twice.
I don't know (yet) if it is copying twice. I thought it would only assign a reference.
But not sure. I can use your code example to see if that would be faster (if it works).
I don't think this.pieces = pieces copies the content of the array.

Code: Select all

        readonly ulong[] pieces;
        private ChessBoardBits(ulong[] pieces)
        {
            this.pieces = pieces;
        }
 
By the way:

Code: Select all

   public const ulong CUR_PLAYER = ((UInt64)1) << 4;
And OTHER points to extra bitboard where sign (of current player = side to move) , en passant, castling rights etc is stored.

Code: Select all

        public const int WHITE_PIECES = (int)King + 1;
        public const int BLACK_PIECES = (int)King + 2;
        public const int OTHER = (int)King + 3;
        const int NBITBOARDS = 9;
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Sven wrote: Tue Apr 27, 2021 9:43 pm What is cp[OTHER], what is CUR_PLAYER? Both seem to be bitboards while I would expect something like White or Black ...

Also for copy&make based null move I would expect something like this (I apologize for my C# syntax sloppiness):

Code: Select all

public IChessBoard AfterNullMove()
{
    var result = new ChessBoardBits(Pieces);
    result.Player = Opponent(result.player);
    // and do possible other updates, e.g. reset ep target sqr and 50-moves counter
    return result;
}
which avoids copying the piece bitboards twice.
No does not work. As expected. Constructor does not make copy of pieces.
this.pieces = pieces; does not copy array.
To make it work I must make copy of pieces explicitly.

Code: Select all

public IChessBoard ChangePlayer()
{
  var cp = new ChessBoardBits(Pieces); // does not work 
   cp.Pieces[OTHER] ^= CUR_PLAYER;
   return cp;
}
This code works. Performance similar.
Better do a CopyTo in constructor.

Code: Select all

public IChessBoard ChangePlayer()
{
            ulong[] cpPieces = new ulong[NBITBOARDS];
            Pieces.CopyTo(cpPieces, 0);
            var cp = new ChessBoardBits(cpPieces);
            cp.Pieces[OTHER] ^= CUR_PLAYER;
            return cp;
 }
 
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Another win against fairy-max. They are still scarce so I post them.
Same story: opponent castling long and a win before end game starts.
Because when in end game Skipper always loses somehow.

[pgn]
[Event "Computer Chess Game"]
[Site "LAPTOP-1FK7MTIP"]
[Date "2021.04.29"]
[Round "-"]
[White "Skipper_8_7"]
[Black "Fairy-Max 4.8V"]
[Result "1-0"]
[TimeControl "180"]
[Annotator "1. +0.37 3... +0.26"]

1. d4 {+0.37/14} d5 2. Nc3 {+0.20/13 4} Nf6 3. Bf4 {+0.21/13 3} c6
{+0.26/7 6} 4. e3 {+0.21/12 3} Be6 {+0.11/7 4} 5. Bd3 {+0.35/12 3} Nbd7
{+0.08/7 3} 6. Nge2 {+0.28/12 3} h6 {+0.04/7 2.3} 7. h4 {+0.31/12 3} Nh5
{+0.01/7 2.7} 8. Bh2 {+0.37/13 3} Qb6 {+0.00/8 6} 9. Rb1 {+0.71/11 3} g5
{+0.04/7 2.7} 10. hxg5 {+0.78/13 3} hxg5 {-0.14/8 2.1} 11. O-O {+0.78/12 3}
O-O-O {+0.18/7 3} 12. b4 {+1.21/11 2.9} Re8 {-0.07/9 4} 13. b5
{+1.01/12 2.9} Qa5 {-0.01/7 3} 14. bxc6 {+0.85/11 2.8} bxc6 {-0.05/8 2.8}
15. e4 {+0.91/10 2.8} Nhf6 {+0.02/8 5} 16. e5 {+0.92/11 2.7} Ng4
{-0.10/9 4} 17. Bg3 {+0.78/12 2.7} f5 {+0.04/8 17} 18. exf6 {+0.65/12 2.6}
Ngxf6 {-0.04/8 3} 19. Re1 {+0.71/10 2.6} Nh5 {+0.04/8 1.8} 20. Bg6
{+0.72/10 2.5} Rd8 {+0.03/9 5} 21. Bh2 {+0.27/11 2.5} Nhf6 {-0.06/8 2.1}
22. Bd3 {+0.53/10 2.4} Bg4 {-0.07/6 1.3} 23. f3 {+0.88/10 2.4} Be6
{-0.66/7 1.9} 24. Qd2 {+0.96/11 2.3} Qa3 {-0.77/6 1.7} 25. Nf4
{+1.67/11 2.3} Bg8 {-1.11/7 1.5} 26. Ne6 {+2.72/12 2.2} Ne4 {-2.05/7 5} 27.
Nxe4 {+4.01/11 2.2} Rxh2 {-3.05/6 3} 28. Qc3 {+6.96/12 2.1} Qa4
{-7.80/8 1.6} 29. Bb5 {+10.16/12 2.1} Qxb5 {-9.77/8 1.8} 30. Rxb5
{+14.51/14 2.1} Ne5 {-11.48/8 1.6} 31. dxe5 {+14.21/13 2.0} Kd7
{-13.76/9 2.4} 32. Nxf8+ {+14.49/12 2.0} Ke8 {-13.30/9 2.0} 33. Qxc6+
{+14.78/12 1.9} Kxf8 {-14.79/10 1.9} 34. Qc7 {+14.96/11 1.9} Re8
{-11.85/9 1.5} 35. Kxh2 {+14.79/12 1.9} dxe4 {-12.23/9 0.9} 36. fxe4
{+15.56/13 1.8} Bxa2 {-12.91/9 1.5} 37. c4 {+17.37/13 1.8} Kg7
{-13.49/8 1.3} 38. Ra1 {+17.50/12 1.8} a6 {-13.94/10 0.9} 39. Rb6
{+18.53/14 1.7} Bxc4 {-14.24/10 2.1} 40. Qxc4 {+18.74/13 1.7} e6
{-19.27/10 1.9} 41. Raxa6 {+19.62/13 1.7} Rh8+ {-79.94/9 0.9} 42. Kg3
{+20.60/14 1.6} Rf8 {-79.96/12 1.0} 43. Rxe6 {+327.59/14 1.6} Rf7
{-79.97/18 0.9} 44. Rg6+ {+327.61/15 1.6} Kh8 {-79.98/28 0.2} 45. Qc8+
{+327.63/16 1.5} Kh7 {-79.99/28 0.2} 46. Qh3# {+327.65/17 1.5}
{Xboard adjudication: Checkmate} 1-0
[/pgn]
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Another win but in the mean time already lost several games.
But looks like wins getting less scarce now.

[pgn]
Event "Computer Chess Game"]
[Site "LAPTOP-1FK7MTIP"]
[Date "2021.04.29"]
[Round "-"]
[White "Skipper_8_7"]
[Black "Fairy-Max 4.8V"]
[Result "1-0"]
[TimeControl "180"]
[Annotator "1. +0.37 2... +0.20"]

1. d4 {+0.37/14} Nf6 2. Nc3 {+0.00/12 4} Nc6 {+0.20/8 4} 3. d5 {+0.57/13 3}
Nb8 {-0.08/8 6} 4. Nf3 {+0.59/12 3} d6 {+0.12/8 7} 5. e4 {+0.80/13 3} c6
{+0.14/7 2.3} 6. Be3 {+0.72/12 3} Nbd7 {+0.14/8 11} 7. Nd4 {+0.55/11 3} Ne5
{+0.05/8 5} 8. h3 {+0.68/11 3} cxd5 {+0.02/8 5} 9. exd5 {+0.84/12 3} Bd7
{-0.06/7 2.3} 10. f4 {+0.81/12 3} Ng6 {-0.21/8 2.6} 11. Bc4 {+0.68/10 3}
Qb6 {+0.10/7 3} 12. Qd3 {+1.14/9 2.9} Qxb2 {+0.02/6 2.0} 13. Rb1
{+1.15/11 2.9} Qa3 {-0.28/8 2.4} 14. Rxb7 {+1.15/9 2.8} a6 {-0.35/7 3} 15.
O-O {+2.01/9 2.8} Bc8 {-0.08/7 5} 16. Rb6 {+2.20/9 2.7} Rg8 {-0.01/6 1.8}
17. Rfb1 {+2.39/8 2.7} Rh8 {-0.23/6 1.6} 18. R1b3 {+3.69/10 2.6} Qc5
{-1.79/9 4} 19. Ne6 {+3.64/11 2.6} Nxf4 {-2.24/8 2.1} 20. Nxf4
{+4.84/11 2.5} Qc7 {-2.40/7 2.1} 21. Bxa6 {+5.00/9 2.5} Bd7 {-2.54/7 1.5}
22. Bb7 {+5.46/10 2.4} Rb8 {-2.63/7 1.8} 23. Bd4 {+4.59/10 2.4} Qd8
{-2.94/7 4} 24. Qe3 {+5.06/10 2.3} Qc7 {-3.06/7 2.6} 25. Nb5 {+5.11/10 2.3}
Qxb6 {-4.59/8 1.5} 26. Bxb6 {+5.59/12 2.2} Bxb5 {-5.46/9 1.7} 27. Bc6+
{+6.92/12 2.2} Bxc6 {-5.01/10 1.7} 28. dxc6 {+6.92/12 2.1} h5 {-5.16/9 4}
29. c7 {+6.37/11 2.1} Rc8 {-5.64/9 1.9} 30. h4 {+6.22/10 2.1} e5
{-5.37/8 1.9} 31. Qe2 {+6.16/10 2.0} g6 {-5.72/8 3} 32. Rd3 {+6.21/8 2.0}
Nd7 {-5.16/9 1.8} 33. Ba5 {+5.85/10 1.9} Be7 {-5.48/8 1.9} 34. Nd5
{+6.42/11 1.9} Nc5 {-5.96/7 1.2} 35. Rh3 {+6.63/10 1.9} f6 {-6.06/8 4} 36.
Rg3 {+7.00/9 1.8} f5 {-6.65/7 1.0} 37. Rxg6 {+7.49/11 1.8} Ra8
{-6.87/7 1.2} 38. Nxe7 {+7.79/8 1.7} Kxe7 {-7.58/9 1.8} 39. Bb4
{+8.71/10 1.7} Kd7 {-7.65/7 1.2} 40. Qd1 {+8.97/10 1.7} Nb7 {-8.44/8 1.2}
41. Bxd6 {+10.09/12 1.7} Rae8 {-9.56/8 2.1} 42. Bxe5+ {+13.23/12 1.6} Kc8
{-17.60/10 1.3} 43. Rg7 {+15.80/11 1.6} Rd8 {-18.49/11 1.1} 44. cxd8=Q+
{+21.22/12 1.6} Rxd8 {-79.96/12 1.0} 45. Qf3 {+24.85/12 1.5} Rd1+
{-79.97/18 0.9} 46. Qxd1 {+25.54/12 1.5} Nc5 {-79.98/28 0.2} 47. Rc7+
{+327.63/12 1.5} Kb8 {-79.99/28 0.2} 48. Qd8# {+327.65/13 1.4}
{Xboard adjudication: Checkmate} 1-0
[/code][/pgn]