i am working on a chess engine, it is pretty basic so far (alpha beta, mvv-lva, transposition table, iterative deeping, killers) and the next step i want ot take is a SEE function.
I have already a function that works for the three example positions that i threw at it. However, if i use the SEE for moveordering of captures, the nuber of nodes searched increases. I am suspecting a bug in my SEE. Are there any testposition so i can test this function?
The code i have so far looks like this (I know that some cases are not covered, for example when i can win material with first capturing with the queen and then with a rook):
Code: Select all
inline Value see(Position position, const Square attackedSquare, Piece attackedPiece)
{
const Player returnUs = position.us;
const Player returnEnemy = position.enemy;
position.removePiece(position.enemy, attackedPiece, Bitboard::bitAtIndex(attackedSquare));
Player us = position.us;
Value value[2] = {0,0};
Piece attackerStage[2] = {PAWN,PAWN};
while(true)
{
//std::cout << position.getString() << std::endl;
switch(attackerStage[us])
{
case PAWN:
{
U64 attackMask = Bitboard::attackMaskPawnCapture(switchPlayer(us), attackedSquare) & position.players[us] & position.pieces[PAWN];
if(attackMask != 0)
{
position.removePiece(us, PAWN, Bitboard::bitAtIndex(Bitboard::ctz(attackMask)));
value[us] += VALUE[attackedPiece];
attackedPiece = PAWN;
}
else
{
attackerStage[us] += 1;
continue;
}
break;
}
case KNIGHT:
{
U64 attackMask = Bitboard::attackMask<KNIGHT>(attackedSquare, position.occupancy()) & position.players[us] & position.pieces[KNIGHT];
if(attackMask != 0)
{
position.removePiece(us, KNIGHT, Bitboard::bitAtIndex(Bitboard::ctz(attackMask)));
value[us] += VALUE[attackedPiece];
attackedPiece = KNIGHT;
}
else
{
attackerStage[us] += 1;
continue;
}
break;
}
case BISHOP:
{
U64 attackMask = Bitboard::attackMask<BISHOP>(attackedSquare, position.occupancy()) & position.players[us] & position.pieces[BISHOP];
if(attackMask != 0)
{
position.removePiece(us, BISHOP, Bitboard::bitAtIndex(Bitboard::ctz(attackMask)));
value[us] += VALUE[attackedPiece];
attackedPiece = BISHOP;
}
else
{
attackerStage[us] += 1;
continue;
}
break;
}
case ROOK:
{
U64 attackMask = Bitboard::attackMask<ROOK>(attackedSquare, position.occupancy()) & position.players[us] & position.pieces[ROOK];
if(attackMask != 0)
{
position.removePiece(us, ROOK, Bitboard::bitAtIndex(Bitboard::ctz(attackMask)));
value[us] += VALUE[attackedPiece];
attackedPiece = ROOK;
}
else
{
attackerStage[us] += 1;
continue;
}
break;
}
case QUEEN:
{
U64 attackMask = Bitboard::attackMask<ROOK>(attackedSquare, position.occupancy()) & position.players[us] & position.pieces[QUEEN];
if(attackMask != 0)
{
position.removePiece(us, QUEEN, Bitboard::bitAtIndex(Bitboard::ctz(attackMask)));
value[us] += VALUE[attackedPiece];
attackedPiece = QUEEN;
}
else
{
attackerStage[us] += 2; // +2 because we are not interested in capturing with the king
continue;
}
break;
}
case NO_PIECE:
{
return value[returnUs] - value[returnEnemy];
}
}
if(value[us] - VALUE[attackedPiece] - value[switchPlayer(us)] >= 0)
{
return value[returnUs] - value[returnEnemy];
}
us = switchPlayer(us);
}
}