I added killer moves to MadChess 2.0 Beta. Killer moves are quiet moves (not captures or pawn promotions) that cause a beta cutoff. Two killer moves are saved for each ply. They are searched immediately after captures and pawn promotions.
public class KillerMoves | |
{ | |
private readonly Board _board; | |
private readonly KillerMove[][] _killerMoves; | |
public KillerMoves(Board Board, int MaxDepth) | |
{ | |
_board = Board; | |
_killerMoves = new KillerMove[MaxDepth + 1][]; | |
for (int depth = 0; depth <= MaxDepth; depth++) | |
{ | |
_killerMoves[depth] = new KillerMove[2]; | |
_killerMoves[depth][0] = new KillerMove(Piece.None, Square.Illegal); | |
_killerMoves[depth][1] = new KillerMove(Piece.None, Square.Illegal); | |
} | |
} | |
public int GetValue(int Depth, uint Move) | |
{ | |
if (Equals(_killerMoves[Depth][0], Move)) | |
{ | |
return 2; | |
} | |
return Equals(_killerMoves[Depth][1], Move) ? 1 : 0; | |
} | |
public void UpdateValue(int Depth, uint Move) | |
{ | |
if (Equals(_killerMoves[Depth][0], Move)) | |
{ | |
// Move already is the best killer move. | |
return; | |
} | |
// Shift killer moves. | |
_killerMoves[Depth][1] = _killerMoves[Depth][0]; | |
// Update killer move. | |
_killerMoves[Depth][0].Piece = _board.CurrentPosition.Squares[MadChess.Move.From(Move)]; | |
_killerMoves[Depth][0].ToSquare = MadChess.Move.To(Move); | |
} | |
private bool Equals(KillerMove KillerMove, uint Move) | |
{ | |
return (KillerMove.Piece == _board.CurrentPosition.Squares[MadChess.Move.From(Move)]) && | |
(KillerMove.ToSquare == MadChess.Move.To(Move)); | |
} | |
} |
if (score >= Beta) | |
{ | |
// Position is not the result of best play by both players. | |
if (quietMove) | |
{ | |
// Update killer moves. | |
_killerMoves.UpdateValue(Depth, move); | |
} | |
// Update best move cache. | |
UpdateBestMoveCache(Depth, Horizon, move, score, Alpha, Beta); | |
// Beta cutoff | |
return Beta; | |
} | |
public uint GetNextMove(uint[] Moves, int Depth, int CandidateMoveNumber, out int MoveIndex) | |
{ | |
for (int moveIndex = 0; moveIndex < _board.CurrentPosition.MoveIndex; moveIndex++) | |
{ | |
uint move = Moves[moveIndex]; | |
if (move != 0u) | |
{ | |
if (CandidateMoveNumber == 0) | |
{ | |
// Prioritize killer moves. | |
int killer = _killerMoves.GetValue(Depth, move); | |
Move.SetKiller(ref move, killer); | |
} | |
// TODO: Prioritize by move history. | |
} | |
} | |
// Find highest priority unplayed move. | |
uint nextMove = 0u; | |
MoveIndex = 0; | |
for (int moveIndex = 0; moveIndex < _board.CurrentPosition.MoveIndex; moveIndex++) | |
{ | |
uint move = Moves[moveIndex]; | |
if (!Move.Played(move)) | |
{ | |
// Move has not been played. | |
if (move > nextMove) | |
{ | |
nextMove = move; | |
MoveIndex = moveIndex; | |
} | |
} | |
} | |
return nextMove; | |
} |
This added 61 Elo to the playing strength of MadChess 2.0 Beta.
MadChess 2.0 2065 : 800 (+396,=136,-268), 58.0 % vs. : games ( +, =, -), (%) : Diff, SD, CFS (%) BikJump v2.01 : 100 ( 36, 21, 43), 46.5 : -26, 11, 0.8 Matheus-2.3 : 100 ( 40, 20, 40), 50.0 : -7, 11, 27.3 Monarch 1.7 : 100 ( 38, 19, 43), 47.5 : +14, 11, 90.3 BigLion 2.23w : 100 ( 49, 15, 36), 56.5 : +44, 12, 100.0 Sharper 0.17 : 100 ( 61, 5, 34), 63.5 : +60, 11, 100.0 Faile 1.4 : 100 ( 52, 23, 25), 63.5 : +85, 11, 100.0 Jabba13032012 : 100 ( 62, 14, 24), 69.0 : +117, 11, 100.0 Roce 0.0390 : 100 ( 58, 19, 23), 67.5 : +182, 11, 100.0
Feature | Category | Date | Rev1 | WAC2 | Elo Rating3 | Improvement |
---|---|---|---|---|---|---|
Killer Moves | Search | 2015 Jan 03 | 38 | 275 | 2065 | +61 |
Futility Pruning | Search | 2014 Dec 29 | 37 | 256 | 2004 | +54 |
Null Move Quiescence Recaptures |
Search | 2014 Dec 28 | 34 | 242 | 1950 | +46 |
King Safety | Evaluation | 2014 Dec 24 | 32 | 225 | 1904 | +27 |
Piece Mobility | Evaluation | 2014 Dec 16 | 29 | 225 | 1877 | +64 |
Draw By Repetition Bug | Evaluation | 2014 Dec 10 | 27 | 225 | 1813 | +47 |
Passed Pawns | Evaluation | 2014 Dec 09 | 26 | 225 | 1766 | +72 |
Time Management | Search | 2014 Dec 08 | 25 | 231 | 1694 | +24 |
Delay Move Generation Aspiration Window Bug |
Search | 2014 Dec 02 | 23 | 231 | 1670 | +44 |
MVV / LVA Move Order Draw By Insufficient Material Move List Overflow Bug |
Search | 2014 Dec 01 | 22 | 235 | 1626 | +30 |
Tapered Evaluation MG and EG Piece Location |
Evaluation | 2014 Nov 29 | 21 | 234 | 1596 | +107 |
Alpha / Beta Negamax Aspiration Windows Quiescence, Hash Material, Piece Squares |
Baseline | 2014 Nov 25 | 20 | 236 | 1489 | – |
- Subversion source code revision
- Win At Chess position test, 3 seconds per position
- Bullet chess, 2 min / game + 1 sec / move