yes, i think it should be "if (alpha < examineBoard.Score)".aberent wrote:Did I reverse the operator <>?nevatre wrote:Adam, this doesn't look correct
"if (alpha > examineBoard.Score)
alpha = examineBoard.Score; "
I need help, performance wall!
Moderators: hgm, Rebel, chrisw
-
- Posts: 16
- Joined: Fri Aug 01, 2008 6:09 pm
- Location: UK
Re: I need help, performance wall!
Re: I need help, performance wall!
CRoberson wrote:No, you don't get it fully. There is much more to it than that. But, lets go with what you have figured out. Now, what is the impact ofaberent wrote:Ok so I seperated the Qsearch from regular Alpha Beta. That gave me a small improvement 2%. Better than nothingCRoberson wrote:Most PC's are running chips based on superscalar architectures. Such machines have performance problems with conditional branching (if statements). So, make your quiesce routine a completely different routine. That will get some speed and make your code much easier to debug.
Second, don't generate the next set of moves just before searching the move you just made.
.......
Notice after making a move you then call search (don't gen moves).
In the Qsearch, same concept about move gen.
Now, prove to me you understand that algorithm. How does the stand pat score get returned? Also, explain the efficiency in when I gen moves in the Qsearch vs how you do it. Why is what I typed better?
When you can answer those questions, you have a chance at improving your program.
I think I get it (maybe) you don't call Generate Moves before you enter a deeper depth because you might be at depth 0 in the next move? In that case you just evaluate the position and exit without having to Generate Moves?
not generating moves on the last ply? Think about the branch factor. How many nodes are in the last ply relative to the rest of the tree? Also, how many nodes are in the last ply relative to the previous ply?
Ok so the problem with my code was that I needed to generate valid moves (so I can see what is attacking what) before I evaluated the position. I can see now that this was a huge performance issue.
Once I separated my evaluation from move generation I now have 53% improvement in speed. I can actually play at ply 7 at less than 1 minute per move This is huge for me Thank you so much.
On top of that my chess engine managed to beet chess titans (the chess program that comes with Windows) at level 10 last night for the first time ever. This was always one of my goals that I could not reach by simply searching to ply 5. I am so happy.
Now back to my education
I can see that generating moves just before calling alpha beta, means that I often generated moves just before depth 0, instead of simply returning the score. I also realized that due to the branch factor the unnecessary call at depth 0 is far more damaging to performance than an unnecessary call in an earlier depth.
Please let me know if I got it right.
Thanks allot to everyone that helped
Re: I need help, performance wall!
Here is my fixed code, please feel free to comment:
Code: Select all
private static int SideToMoveScore(int Score, ChessPieceColor color)
{
if (color == ChessPieceColor.White)
return -Score;
return Score;
}
internal static int Quiescence(Board examineBoard, int alpha, int beta, ChessPieceColor movingSide, ref int nodesSearched)
{
nodesSearched++;
//Evaluate Score
Evaluation.EvaluateBoardScore(examineBoard);
//Invert Score to support Negamax
examineBoard.Score = SideToMoveScore(examineBoard.Score, GetOppositeColor(movingSide));
if (examineBoard.Score >= beta)
return beta;
if (alpha < examineBoard.Score)
alpha = examineBoard.Score;
//We Generate Valid Moves for Board
PieceValidMoves.GenerateValidMoves(examineBoard);
List<Position> positions = EvaluateMoves(movingSide, examineBoard, true);
if (positions.Count == 0)
{
return examineBoard.Score;
}
positions.Sort(Sort);
foreach (Position move in positions)
{
//Make a copy
Board board = examineBoard.FastCopy();
//Move Piece
Board.MovePiece(board, move.SrcPosition, move.DstPosition);
int value = -Quiescence(board, -beta, -alpha, GetOppositeColor(movingSide), ref nodesSearched);
if (value >= beta)
{
return beta;
}
if (value > alpha)
alpha = value;
}
return alpha;
}
internal static int AlphaBetaFast(Board examineBoard, byte depth, int alpha, int beta, ChessPieceColor movingSide, ref int nodesSearched)
{
nodesSearched++;
if (depth == 0)
{
//If last move was a capture
if (examineBoard.LastMove.TakenPiece.PieceType != ChessPieceType.None)
{
//Perform a Quiessence Search
return Quiescence(examineBoard, alpha, beta, movingSide, ref nodesSearched);
}
//Evaluate Score
Evaluation.EvaluateBoardScore(examineBoard);
//Invert Score to support Negamax
examineBoard.Score = SideToMoveScore(examineBoard.Score, GetOppositeColor(movingSide));
return examineBoard.Score;
}
//We Generate Valid Moves for Board
PieceValidMoves.GenerateValidMoves(examineBoard);
List<Position> positions = EvaluateMoves(movingSide, examineBoard, false);
if (positions.Count == 0)
{
//Evaluate Score
Evaluation.EvaluateBoardScore(examineBoard);
//Invert Score to support Negamax
examineBoard.Score = SideToMoveScore(examineBoard.Score, GetOppositeColor(movingSide));
return examineBoard.Score;
}
positions.Sort(Sort);
depth--;
foreach (Position move in positions)
{
//Make a copy
Board board = examineBoard.FastCopy();
//Move Piece
Board.MovePiece(board, move.SrcPosition, move.DstPosition);
int value = -AlphaBetaFast(board, depth, -beta, -alpha, GetOppositeColor(movingSide), ref nodesSearched);
if (value >= beta)
{
return beta;
}
if (value > alpha)
alpha = value;
}
return alpha;
}
-
- Posts: 2056
- Joined: Mon Mar 13, 2006 2:31 am
- Location: North Carolina, USA
Re: I need help, performance wall!
Your answer was far more superficial than what I was asking. I'll be more specific. What is the effective branching factor of youraberent wrote:
Ok so the problem with my code was that I needed to generate valid moves (so I can see what is attacking what) before I evaluated the position. I can see now that this was a huge performance issue.
......
Now back to my education
I can see that generating moves just before calling alpha beta, means that I often generated moves just before depth 0, instead of simply returning the score. I also realized that due to the branch factor the unnecessary call at depth 0 is far more damaging to performance than an unnecessary call in an earlier depth.
Please let me know if I got it right.
Thanks allot to everyone that helped
program? Given that, what is the relative size difference between the leaf ply and the ply just before that? Also, what is the size difference
between the leaf ply and the rest of the tree?
-
- Posts: 318
- Joined: Thu Mar 09, 2006 1:07 am
Re: I need help, performance wall!
Please answer my questions to yourself. Not to me.
assuming centipawn score.
You know the meaning of ply and the difference in meaning to depth, do you?
When you enter alphaBeta or quiescence it is a good thing to know
if movingSide is in check. Do that in an extra call at the top of the search functions
or somewhere in or after the makeMove() function.
I don't know your board represenntation, move and vove list structure
or move stack. May be there are some issues or unusual solutions also.
Unusual is not bad. It has the chance to be better. Just be aware of it.
Harald
Good mate values would be -32000 + ply (black wins) or +32000 - ply (white wins)aberent wrote:Here is my fixed code, please feel free to comment:
Code: Select all
private static int SideToMoveScore(int Score, ChessPieceColor color) { if (color == ChessPieceColor.White) return -Score; return Score; } //// You always call this with GetOppositeColor(movingSide). //// Change the .White in the function to .Black and call it always with //// color movingSide. internal static int Quiescence(Board examineBoard, int alpha, int beta, ChessPieceColor movingSide, ref int nodesSearched) { nodesSearched++; //// Is there anything you will do with 50 move draw or repetition? //// Here might be one place to react to that. //Evaluate Score Evaluation.EvaluateBoardScore(examineBoard); //Invert Score to support Negamax examineBoard.Score = SideToMoveScore(examineBoard.Score, GetOppositeColor(movingSide)); //// See above. if (examineBoard.Score >= beta) return beta; if (alpha < examineBoard.Score) alpha = examineBoard.Score; //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(examineBoard); //// In qsearch only generate capture (promotion) moves. //// But generate all moves if movingSide is in check. List<Position> positions = EvaluateMoves(movingSide, examineBoard, true); if (positions.Count == 0) { return examineBoard.Score; } //// Does the Score already include mate or stalemate values? //// If not you might want to do an movingSide_is_in_check investigation //// and return special scores: -mateScore = some extreme number //// and stalemateScore = 0. //// On the other side if you don't generate all moves here but captures only //// than you must assume that those situations don't happen and are //// hidden inside the stand pat logic. positions.Sort(Sort); foreach (Position move in positions) { //Make a copy Board board = examineBoard.FastCopy(); //Move Piece Board.MovePiece(board, move.SrcPosition, move.DstPosition); int value = -Quiescence(board, -beta, -alpha, GetOppositeColor(movingSide), ref nodesSearched); if (value >= beta) { return beta; } if (value > alpha) alpha = value; } return alpha; } internal static int AlphaBetaFast(Board examineBoard, byte depth, int alpha, int beta, ChessPieceColor movingSide, ref int nodesSearched) { nodesSearched++; //// Is there anything you will do with 50 move draw or repetition? //// Here might be one place to react to that. if (depth == 0) { //If last move was a capture //// Don't do this. Read the comment Q below. if (examineBoard.LastMove.TakenPiece.PieceType != ChessPieceType.None) { //Perform a Quiessence Search return Quiescence(examineBoard, alpha, beta, movingSide, ref nodesSearched); } //Evaluate Score //// Don't do this. Read the comment Q below. Evaluation.EvaluateBoardScore(examineBoard); //Invert Score to support Negamax examineBoard.Score = SideToMoveScore(examineBoard.Score, GetOppositeColor(movingSide)); return examineBoard.Score; } //// Q: Just do this: //// if (depth == 0) //// { //// //Perform a Quiessence Search //// return Quiescence(examineBoard, alpha, beta, movingSide, ref nodesSearched); //// } //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(examineBoard); List<Position> positions = EvaluateMoves(movingSide, examineBoard, false); if (positions.Count == 0) { //Evaluate Score Evaluation.EvaluateBoardScore(examineBoard); //Invert Score to support Negamax examineBoard.Score = SideToMoveScore(examineBoard.Score, GetOppositeColor(movingSide)); return examineBoard.Score; } //// Again think about mating and stalemate scores. positions.Sort(Sort); //// That is ok. Another way to do it is: //// Just give a quick and dirty value (MVV/LVA + history or + piece_square_value) //// and pick the next best move from the list in the loop below. //// Mark moves as used. But sort is easier at first and the pick idea is advanced. depth--; //// If you insist. ;-) //// But I would prefer to do that in the call only to have the same depth //// throughout this whole function. Even after the loop. //// The only reason to change it here will come when you implement //// some extensions or reductions later in an advanced engine. foreach (Position move in positions) { //Make a copy Board board = examineBoard.FastCopy(); //Move Piece Board.MovePiece(board, move.SrcPosition, move.DstPosition); int value = -AlphaBetaFast(board, depth, -beta, -alpha, GetOppositeColor(movingSide), ref nodesSearched); //// Here I would use depth-1. if (value >= beta) { return beta; } if (value > alpha) alpha = value; } return alpha; }
assuming centipawn score.
You know the meaning of ply and the difference in meaning to depth, do you?
When you enter alphaBeta or quiescence it is a good thing to know
if movingSide is in check. Do that in an extra call at the top of the search functions
or somewhere in or after the makeMove() function.
I don't know your board represenntation, move and vove list structure
or move stack. May be there are some issues or unusual solutions also.
Unusual is not bad. It has the chance to be better. Just be aware of it.
Harald
Re: I need help, performance wall!
Currently I don't collect data on how many nodes there are in each ply. It will take me a bit of time to set that up.CRoberson wrote:Your answer was far more superficial than what I was asking. I'll be more specific. What is the effective branching factor of youraberent wrote:
Ok so the problem with my code was that I needed to generate valid moves (so I can see what is attacking what) before I evaluated the position. I can see now that this was a huge performance issue.
......
Now back to my education
I can see that generating moves just before calling alpha beta, means that I often generated moves just before depth 0, instead of simply returning the score. I also realized that due to the branch factor the unnecessary call at depth 0 is far more damaging to performance than an unnecessary call in an earlier depth.
Please let me know if I got it right.
Thanks allot to everyone that helped
program? Given that, what is the relative size difference between the leaf ply and the ply just before that? Also, what is the size difference
between the leaf ply and the rest of the tree?
Currently from the starting position to ply 7 my software goes through 2,739,203 nodes (That includes QSearch) Is that high?
-
- Posts: 2056
- Joined: Mon Mar 13, 2006 2:31 am
- Location: North Carolina, USA
Re: I need help, performance wall!
Oh, come on. Forget the code. Do the math.aberent wrote:Currently I don't collect data on how many nodes there are in each ply. It will take me a bit of time to set that up.CRoberson wrote:Your answer was far more superficial than what I was asking. I'll be more specific. What is the effective branching factor of youraberent wrote:
Ok so the problem with my code was that I needed to generate valid moves (so I can see what is attacking what) before I evaluated the position. I can see now that this was a huge performance issue.
......
Now back to my education
I can see that generating moves just before calling alpha beta, means that I often generated moves just before depth 0, instead of simply returning the score. I also realized that due to the branch factor the unnecessary call at depth 0 is far more damaging to performance than an unnecessary call in an earlier depth.
Please let me know if I got it right.
Thanks allot to everyone that helped
program? Given that, what is the relative size difference between the leaf ply and the ply just before that? Also, what is the size difference
between the leaf ply and the rest of the tree?
Currently from the starting position to ply 7 my software goes through 2,739,203 nodes (That includes QSearch) Is that high?
-
- Posts: 201
- Joined: Thu Mar 22, 2007 7:12 pm
- Location: Netherlands
Re: I need help, performance wall!
My program needs about 400,000 nodes with pruning disabled (no hash table / null move / late move reduction cuts)aberent wrote:Currently I don't collect data on how many nodes there are in each ply. It will take me a bit of time to set that up.CRoberson wrote:Your answer was far more superficial than what I was asking. I'll be more specific. What is the effective branching factor of youraberent wrote:
Ok so the problem with my code was that I needed to generate valid moves (so I can see what is attacking what) before I evaluated the position. I can see now that this was a huge performance issue.
......
Now back to my education
I can see that generating moves just before calling alpha beta, means that I often generated moves just before depth 0, instead of simply returning the score. I also realized that due to the branch factor the unnecessary call at depth 0 is far more damaging to performance than an unnecessary call in an earlier depth.
Please let me know if I got it right.
Thanks allot to everyone that helped
program? Given that, what is the relative size difference between the leaf ply and the ply just before that? Also, what is the size difference
between the leaf ply and the rest of the tree?
Currently from the starting position to ply 7 my software goes through 2,739,203 nodes (That includes QSearch) Is that high?
(and 13,425 nodes with all this pruning turned on) so there seems to be room for improvement.
Jan
Re: I need help, performance wall!
What could be causing such a difference in number of searched boards?
-
- Posts: 12550
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: I need help, performance wall!
We don't bother searching as deeply when we toss away a queen for no compensation.aberent wrote:What could be causing such a difference in number of searched boards?
For any given chess position, there are about 2-3 good moves. Why bother scouring the other 35? We don't do it when we are playing OTB.
Null move is a demonstration that a move is so bad it's worse than giving up your turn and letting the other guy go. Seems logical that we don't need to scrub the spots off of that one.
LMR is a demonstration that the last eleven times we looked at this move it stunk like a 3 day old baby diaper. No need to look through that basket to find our lunch.
If we spend most of our time looking at the really good moves and only cursory examination of the moves that look really awful, the tree gets much smaller.
Consider:
[d]r1b2rk1/pp2ppbp/2n3p1/q2pP3/Bn5Q/P1N2N2/1PP2PPP/R1B1K2R b KQ -
Here is the multi-pv search for this position:
Code: Select all
2 00:00 2.920 186.880 -0.96 Nb4a2
2 00:00 2.678 171.392 -0.72 Nb4xc2+
2 00:00 1.798 115.072 -0.36 Nb4a6
2 00:00 3.807 243.648 -0.27 b7b5
2 00:00 2.070 132.480 -0.21 Qa5xa4
---------------------------------------------------------------------------
3 00:00 6.914 150.636 -1.41 Nb4a2
3 00:00 7.261 158.197 -1.38 Nc6xe5
3 00:00 6.500 208.000 -0.79 Nb4xc2+
3 00:00 4.192 134.144 -0.36 Qa5xa4
3 00:00 6.067 194.144 -0.28 Nb4a6
---------------------------------------------------------------------------
4 00:00 10.267 166.879 -1.54 Nb4a2
4 00:00 9.715 157.907 -1.23 Nc6xe5
4 00:00 9.429 153.258 -0.75 Nb4xc2+
4 00:00 8.599 187.348 -0.31 Qa5xa4
4 00:00 8.022 174.777 -0.30 Nb4a6
---------------------------------------------------------------------------
5 00:00 17.557 163.439 -1.61 Nb4a2 Ra1xa2
5 00:00 16.187 150.686 -1.49 Nc6xe5 a3xb4
5 00:00 15.107 164.569 -0.86 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO
5 00:00 13.428 174.054 -0.38 Qa5xa4 Nc3xa4 Nb4xc2+
5 00:00 11.941 154.779 -0.05 Nb4a6 Ba4xc6
---------------------------------------------------------------------------
6 00:00 48.112 165.881 -1.65 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 OO
6 00:00 45.490 165.771 -1.59 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5d8 OO
6 00:00 42.429 173.789 -0.94 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Be5xc3 b2xc3 Qa5xc3 Ra1a2
6 00:00 38.607 168.227 -0.22 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4
6 00:00 26.111 170.303 -0.05 Nb4a6 Ba4xc6 b7xc6 Qh4xe7 d5d4
---------------------------------------------------------------------------
7 00:01 237.032 189.625 -1.58 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5d8 OO Bc8e6 Bc1g5
7 00:01 248.515 189.626 -1.43 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Qa5a6
7 00:01 233.097 191.105 -1.13 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO d5d4 Nc3e4 Qa5c7 Bc2d3 Bc8d7
7 00:01 94.595 177.084 -0.21 Nb4a6 Ba4xc6 b7xc6 OO f7f6 e5xf6 Bg7xf6 Bc1g5
7 00:01 124.884 186.144 -0.15 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1xd5
---------------------------------------------------------------------------
8 00:03 649.388 191.139 -1.75 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5d8 OO Qd8d6 Bc1g5 f7f6
8 00:03 619.870 191.882 -1.56 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Qa5a6 Ba4b3 e7e6 Bc1h6
8 00:03 582.372 192.060 -1.01 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Bc1e3 Ra8c8 Be3d4 Be5xd4 Qh4xd4 Rc8c4
8 00:03 372.897 186.813 -0.16 Nb4a6 Ba4xc6 b7xc6 OO f7f6 e5xf6 Bg7xf6 Bc1g5 Qa5c5 Bg5xf6 e7xf6 Ra1e1
8 00:03 308.440 185.680 -0.15 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1xd5
---------------------------------------------------------------------------
9 00:04 840.599 188.311 -1.75 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5d8 OO Qd8d6 Bc1g5 f7f6 Bg5e3
9 00:04 826.728 187.751 -1.61 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Qa5a6 Ba4b3 e7e6 Bc1h6 Rf8d8 f2f4
9 00:04 790.006 187.869 -1.01 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Bc1e3 Ra8c8 Be3d4 Be5xd4 Qh4xd4 Rc8c4
9 00:04 759.023 188.696 -0.22 Nb4a6 b2b4 Qa5d8 Ba4xc6
9 00:04 699.311 188.893 -0.15 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1xd5
---------------------------------------------------------------------------
10 00:09 1.785.878 189.056 -1.82 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5d8 OO Bc8f5 Bc1g5 f7f6 Bg5e3 a7a6 Ra1d1
10 00:09 1.679.544 189.098 -1.79 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Be5xc3+ b2xc3 Qa5c7 OO a7a5 Qb4b3 Rf8d8 Rf1d1
10 00:09 1.081.453 187.283 -1.03 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Bc1e3 Ra8c8 Be3d4 Be5xd4 Qh4xd4 Rc8c4
10 00:09 998.408 188.316 -0.18 Nb4a6 b2b4 Qa5d8 Ba4xc6 b7xc6 Bc1h6 Na6c7 Bh6xg7 Kg8xg7 OO Nc7e6 Rf1d1
10 00:09 930.360 186.181 -0.15 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1xd5
---------------------------------------------------------------------------
11 00:17 2.567.752 190.011 -1.85 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Be5xc3+ b2xc3 Qa5c7 OO a7a5 Qb4b3 Rf8d8 Rf1d1 Bc8g4
11 00:17 3.273.676 195.340 -1.73 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5a6 Nc3xd5 b7b5 Nd5c7 Qa6c6 Nc7xa8 Qc6xf3 Rh1g1
11 00:17 2.436.592 190.842 -1.12 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Bc1e3 Ra8c8 Be3d4 Be5xd4 Qh4xd4 Rc8c4 Qd4e5 Qa5b6 Bc2d3 f7f6 Qe5e2 Rc4c6 Bd3b5 Rc6c7
11 00:17 2.217.021 191.969 -0.20 Nb4a6 b2b4 Qa5d8 Ba4xc6 b7xc6 Bc1h6 Na6c7 Bh6xg7 Kg8xg7 OO Nc7e6 Rf1d1
11 00:17 2.098.056 189.688 0.00 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1a4 d5d4 Qa4xc6
---------------------------------------------------------------------------
12 00:45 9.266.869 208.386 -1.66 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 d5d4 Ne5c4 Qa5c5 Nc3e4 Qc5xc4 Ba4b3 Qc4c6 OO Bc8f5 Rf1e1 h7h6 f2f3
12 00:45 8.626.288 209.092 -1.60 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5a6 Nc3xd5 b7b5 Nd5c7 Qa6c6 Nc7xb5 Qc6xf3 Rh1g1 Rf8d8 c2c3 Qf3b7 Bc1e3 a7a5 b4xa5 Ra8xa5
12 00:45 5.081.152 197.468 -1.18 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Qh4xe7 Be5xc3 b2xc3 Qa5xc3 Bc1h6 Rf8e8 Qe7h4 Ra8c8 Bc2a4 Rc8c4
12 00:45 4.073.808 197.051 -0.21 Nb4a6 b2b4 Qa5d8 Ba4xc6 b7xc6 Bc1h6 Na6c7 Bh6xg7 Kg8xg7 OO Nc7e6 Rf1d1 h7h6
12 00:45 3.801.115 194.461 0.00 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1a4 d5d4 Qa4xc6
---------------------------------------------------------------------------
13 02:13 27.096.041 207.634 -1.72 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 d5d4 Ne5c4 Qa5c5 OO d4xc3 Bc1e3 Qc5c7 b2b3 Rf8d8 Rf1e1 Bc8f5 Qh4g3 e7e5
13 02:13 25.409.082 207.212 -1.62 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5a6 Nc3xd5 b7b5 Nd5c7 Qa6c6 Nc7xb5 Qc6xf3 Rh1g1 Rf8d8 c2c3 Qf3b7 Bc1e3 a7a5 b4xa5 Ra8xa5 Qh4b4 Ra5a8 Ra1d1 Bc8f5 Rd1xd8+ Ra8xd8 Ba4b3
13 02:13 17.600.097 204.763 -1.26 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Qa5c5 Bc2d3 Bc8d7 Bc1e3 Qc5d6 Ra1e1 f7f6 Nc3d1 Qd6c6
13 02:13 12.633.934 207.375 -0.40 Nb4a6 b2b4 Qa5d8 Bc1f4 Na6c7 OO Bc8f5 Ra1d1 a7a6 g2g4 Bf5c8
13 02:13 10.537.352 208.334 0.00 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5
---------------------------------------------------------------------------
14 03:50 46.032.428 204.451 -1.72 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 d5d4 Ne5c4 Qa5c5 OO d4xc3 Bc1e3 Qc5c7 b2b3 Rf8d8 Rf1e1 Bc8f5 Qh4g3 e7e5
14 03:50 44.675.747 203.875 -1.62 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5a6 Nc3xd5 b7b5 Nd5c7 Qa6c6 Nc7xb5 Qc6xf3 Rh1g1 Rf8d8 c2c3 Qf3b7 Bc1e3 a7a5 b4xa5 Ra8xa5 Qh4b4 Ra5a8 Ra1d1 Bc8f5 Rd1xd8+ Ra8xd8 Ba4b3
14 03:50 43.143.519 203.284 -1.35 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO f7f6 Bc1e3 Be5xc3 b2xc3 Qa5xc3 Ra1c1 Qc3xa3 Be3c5 Qa3b2 Bc5xe7 Rf8f7 Be7c5 Bc8d7 Bc5d4 Qb2b4
14 03:50 38.736.316 206.586 -0.43 Nb4a6 b2b4 Qa5d8 Bc1f4 Na6c7 OO Nc7e6 Rf1d1 Ne6xf4 Qh4xf4 e7e6 Nc3e4 Qd8c7 Ne4f6+ Bg7xf6 Qf4xf6 Bc8d7 Ba4b3 b7b5
14 03:50 29.493.880 208.461 0.00 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5 Qd1a4 Bf5d7 Qa4d1 Bd7f5
---------------------------------------------------------------------------
15 09:19 113.456.587 207.730 -1.77 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Qa5xb4 a3xb4 d5d4 Nc3d5 Bc8e6 Ba4b3 Rf8d8 Ra2a5 Be5d6 Bc1d2 b7b6 Ra5a6 Be6c8 Ra6a1 Bc8b7 f2f3
15 09:19 89.050.737 206.980 -1.59 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5a6 Nc3xd5 b7b5 Nd5c7 Qa6c6 Nc7xb5 Qc6xf3 Rh1g1 Rf8d8 c2c3 a7a6 Nb5d4 Bg7xd4 c3xd4 Bc8e6 Ba4d1 Qf3b7 Bc1d2 Rd8d6 Bd1e2 Ra8c8 Be2d3 Rc8d8
15 09:19 82.973.181 205.920 -1.36 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Qh4xe7 Rf8e8 Qe7b4 Qa5c7 Bc1e3 Be5xh2+ Kg1h1 Bh2e5 Be3d4 a7a5 Bd4xe5 Qc7xe5 Qb4h4 Ra8c8 Rf1e1 Qe5d6
15 09:19 72.607.419 208.430 -0.36 Nb4a6 b2b4 Qa5d8 Bc1f4 Bc8e6 OO Ra8c8 Nc3e2 Na6c7 Ba4xc6 b7xc6 Bf4h6 Qd8d7 Bh6xg7 Kg8xg7 h2h3 Rc8b8 Ra1d1
15 09:19 57.070.820 207.554 0.00 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8
---------------------------------------------------------------------------
16 14:37 178.522.420 208.499 -1.79 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Qa5xb4 a3xb4 d5d4 Nc3e4 Bc8e6 Ra2a3 Be6d5 f2f3 Rf8c8 OO a7a6 Rf1f2 f7f5 Ne4g5 h7h6
16 14:37 160.891.853 209.869 -1.59 Nc6xe5 a3xb4 Ne5xf3+ g2xf3 Qa5a6 Nc3xd5 b7b5 Nd5c7 Qa6c6 Nc7xb5 Qc6xf3 Rh1g1 Rf8d8 c2c3 a7a6 Nb5d4 Bg7xd4 c3xd4 Bc8e6 Ba4d1 Qf3b7 Bc1d2 Rd8d6 Bd1e2 Ra8c8 Be2d3 Rc8d8
16 14:37 151.596.771 209.004 -1.28 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Qh4xe7 Rf8e8 Qe7b4 Qa5c7 Bc1e3 Be5xh2+ Kg1h1 Bh2e5 Be3d4 a7a5 Bd4xe5 Qc7xe5 Qb4h4 Ra8c8 Rf1e1 Qe5d6 Ra1d1 Qd6b6 Bc2a4
16 14:37 135.193.476 210.079 -0.40 Nb4a6 b2b4 Qa5d8 Bc1f4 Bc8e6 OO Ra8c8 Nc3e2 Na6c7 Ba4xc6 b7xc6 Bf4h6 Qd8d7 h2h3 f7f6 Bh6xg7 Kg8xg7 Ne2d4 g6g5 Qh4g3
16 14:37 123.029.134 208.755 0.00 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8
---------------------------------------------------------------------------
17 36:49 455.465.775 216.942 -1.83 Nc6xe5 Qh4xb4 Ne5xf3+ g2xf3 Bg7xc3+ b2xc3 Qa5c7 OO e7e5 Ra1b1 f7f6 Rf1d1 Rf8d8 Bc1h6 a7a5
17 36:49 467.547.514 216.763 -1.75 Nb4a2 Ra1xa2 Nc6xe5 Nf3xe5 Bg7xe5 Qh4b4 Qa5xb4 a3xb4 d5d4 Nc3e4 Bc8e6 Ra2a1 Be6d5 f2f3 Rf8c8 OO a7a6
17 36:49 277.532.774 212.698 -1.28 Nb4xc2+ Ba4xc2 Nc6xe5 Nf3xe5 Bg7xe5 OO Bc8e6 Qh4xe7 Rf8e8 Qe7b4 Qa5c7 Bc1e3 Be5xh2+ Kg1h1 Bh2e5 Be3d4 a7a5 Bd4xe5 Qc7xe5 Qb4h4 Ra8c8 Rf1e1 Qe5d6 Ra1d1 Qd6b6 Bc2a4
17 36:49 256.768.365 214.168 -0.30 Nb4a6 b2b4 Qa5d8 Bc1f4 Na6c7 OO Nc7e6 Bf4g3 Ne6c7 Ra1d1 h7h6 Qh4f4 g6g5 Qf4e3 Bc8g4 Rf1e1 Bg4xf3 Qe3xf3 e7e6
17 36:49 207.680.371 210.429 0.00 Qa5xa4 Nc3xa4 Nb4xc2+ Ke1e2 Nc2xa1 Na4c3 b7b6 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8 Qh4a4 Bc8d7 Qa4h4 Bd7c8