Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6c0054b
Rewrite how the board is stored and moves are made
razvanfilea Nov 20, 2019
1c41cd3
Remove 'ToList' MoveGen template arg, make some fixes
razvanfilea Nov 22, 2019
2bfdff3
Fix a critical error with Board::doMove()
razvanfilea Nov 24, 2019
9db8df9
Fix getPhase always returning ENDGAME
razvanfilea Nov 24, 2019
8fd4e8c
Improve the Evaluation function performance
razvanfilea Nov 24, 2019
bee2ee1
Fix Board::hasValidState and update Pawn PSQT
razvanfilea Nov 26, 2019
68d9853
Switch to the previous Multi Threading model
razvanfilea Nov 28, 2019
7154003
Remove KING_DANGER MoveGen
razvanfilea Nov 28, 2019
eb1963c
Add age attribute to the TranspositionTable
razvanfilea Nov 29, 2019
2da9711
Fix crash when generating legal moves
razvanfilea Nov 30, 2019
f922ceb
Rewrite how the UI processes positions
razvanfilea Nov 30, 2019
220b4d7
Rename NegaMax class to Search
razvanfilea Nov 30, 2019
ee721fd
Work on the ThreadPool
razvanfilea Nov 30, 2019
9a9e5ac
Solve a bug with Castling and disable EnPassant for now
razvanfilea Nov 30, 2019
faba2c2
Add Generated Nodes to Stats
razvanfilea Dec 1, 2019
d73bb5c
Remake the Settings Screen
razvanfilea Dec 1, 2019
9b46c3e
Clean ThreadSafeQueue and ThreadPool
razvanfilea Dec 1, 2019
d5d5ae0
Revert to the old Pawn PSQT
razvanfilea Dec 8, 2019
1b60b38
Re-enable EnPassant
razvanfilea Dec 9, 2019
c0be29b
Add Platform Specific Implementations for BSF and BSR
razvanfilea Dec 10, 2019
8a64bbc
Remove StackVector
razvanfilea Dec 10, 2019
7889cfa
Fix compile errors
razvanfilea Dec 10, 2019
e35ab03
Remake the Pawn Evaluation add Connected Bonus
razvanfilea Dec 11, 2019
459400d
Merge Rays.h into Bitboard.h
razvanfilea Dec 11, 2019
9be2e38
Fix Pawn Move Generation from last commit
razvanfilea Dec 12, 2019
9a37891
Remove Light Theme, add Rook on Queen File Evaluation
razvanfilea Dec 15, 2019
b81a38c
Rewrite Piece class to only use 1 byte
razvanfilea Dec 15, 2019
3a122a9
New icon
razvanfilea Dec 15, 2019
99a93b5
Release 1.0
razvanfilea Dec 15, 2019
b8651a6
Fix issues with the Pull Request
razvanfilea Dec 15, 2019
8c8a8d9
Delete MoveOrdering.h
razvanfilea Dec 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix compile errors
  • Loading branch information
razvanfilea committed Dec 10, 2019
commit 7889cfa3d34462658778527d8cf7e16e53e3a4b0
2 changes: 1 addition & 1 deletion ChessAndroid/app/src/main/cpp/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ Java_net_theluckycoder_chess_Native_getPieces(JNIEnv *pEnv, jclass /*type*/)
{
const Pos &pos = it.first;
auto pieceType = static_cast<jbyte>(it.second.type);
if (!it.second.isWhite)
if (it.second.color == BLACK)
pieceType += 6;

jobject obj = pEnv->NewObject(Cache::pieceClass, constructorId, pos.x, pos.y, pieceType);
Expand Down
41 changes: 19 additions & 22 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/Evaluation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ short Evaluation::simpleEvaluation(const Board &board) noexcept
for (byte i = 0; i < 64u; i++)
{
const Piece &piece = board.getPiece(i);
score[piece.isWhite] += Psqt::s_Bonus[piece.type][i];
score[piece.color] += Psqt::s_Bonus[piece.type][i];
}

const Phase phase = board.getPhase();
Expand Down Expand Up @@ -109,11 +109,11 @@ short Evaluation::evaluate(const Board &board) noexcept
{
if (piece.type == PAWN)
{
pawnCount[piece.isWhite]++;
pawnCount[piece.color]++;
continue;
}

const bool isWhite = piece.isWhite;
const bool isWhite = piece.color;
const Pos pos(i);
const auto defendedValue = isWhite ? whiteMoves.map[pos] : blackMoves.map[pos];
const auto attackedValue = isWhite ? blackMoves.map[pos] : whiteMoves.map[pos];
Expand All @@ -135,8 +135,8 @@ short Evaluation::evaluate(const Board &board) noexcept
if (theirAttacks[!isWhite][ROOK] & bb)
points -= ROOK_THREATS[piece.type];

npm[piece.isWhite] += getPieceValue(piece.type);
totalScore[piece.isWhite] += points;
npm[piece.color] += getPieceValue(piece.type);
totalScore[piece.color] += points;
}

// 2 Bishops receive a bonus
Expand All @@ -152,8 +152,8 @@ short Evaluation::evaluate(const Board &board) noexcept
switch (piece.type)
{
case PAWN:
return evaluatePawn(piece, i, board, piece.isWhite ? whiteMoves : blackMoves,
piece.isWhite ? blackMoves : whiteMoves);
return evaluatePawn(piece, i, board, piece.color ? whiteMoves : blackMoves,
piece.color ? blackMoves : whiteMoves);
case KNIGHT:
return evaluateKnight(piece, i, board);
case BISHOP:
Expand All @@ -169,7 +169,7 @@ short Evaluation::evaluate(const Board &board) noexcept
}
}();

totalScore[piece.isWhite] += points;
totalScore[piece.color] += points;
}

if (board.state == State::BLACK_IN_CHECK)
Expand All @@ -190,8 +190,7 @@ Score Evaluation::evaluatePawn(const Piece &piece, const byte square, const Boar
const Pos pos(square);
Score value = Psqt::s_Bonus[PAWN][square];

const Color color = toColor(piece.isWhite);
const byte behind = color ? -1 : 1;
const byte behind = piece.color ? -1 : 1;
const int supported = int(piece == board.at(pos.x - 1u, pos.y + behind))
+ int(piece == board.at(pos.x + 1u, pos.y + behind));

Expand Down Expand Up @@ -224,7 +223,7 @@ Score Evaluation::evaluatePawn(const Piece &piece, const byte square, const Boar

const Piece &other = board[newPos];
const byte type = other.type;
return other.isWhite != piece.isWhite && type > PAWN && type < KING;
return other.color != piece.color && type > PAWN && type < KING;
};

const int i = static_cast<int>(isEnemyPiece(-1, -behind))
Expand All @@ -234,7 +233,7 @@ Score Evaluation::evaluatePawn(const Piece &piece, const byte square, const Boar
}

const auto isPassedPawn = [&] {
const Rays::Dir direction = color ? Rays::NORTH : Rays::SOUTH;
const Rays::Dir direction = piece.color ? Rays::NORTH : Rays::SOUTH;

const Pos posLeft(pos, -1, -behind);
const Pos posRight(pos, 1, -behind);
Expand All @@ -245,12 +244,12 @@ Score Evaluation::evaluatePawn(const Piece &piece, const byte square, const Boar
if (posRight.isValid())
rays |= Rays::getRay(direction, posRight.toSquare());

return static_cast<bool>(rays & board.getType(oppositeColor(color), PAWN));
return static_cast<bool>(rays & board.getType(~piece.color, PAWN));
}();

if (isPassedPawn)
{
const auto rank = (piece.isWhite ? pos.y : 7u - pos.y) - 1u;
const auto rank = (piece.color ? pos.y : 7u - pos.y) - 1u;
value += PASSED_PAWN_RANK[rank];
}

Expand Down Expand Up @@ -301,20 +300,19 @@ Score Evaluation::evaluateBishop(const Piece &piece, const byte square, const Bo
Score Evaluation::evaluateRook(const Piece &piece, const byte square, const Board &board) noexcept
{
const Pos pos(square);
const Color color = toColor(piece.isWhite);
Score value = Psqt::s_Bonus[ROOK][pos.toSquare()];

const int mobility = Bitboard::popCount(MoveGen<ALL>::generateRookMoves(piece, pos.toSquare(), board));
value += ROOK_MOBILITY[mobility];

const int rookOnPawn = [&] {
if ((piece.isWhite && pos.y < 5) || (!piece.isWhite && pos.y > 4)) return 0;
if ((piece.color && pos.y < 5) || (!piece.color && pos.y > 4)) return 0;

const U64 vertical = Rays::getRay(Rays::NORTH, square) | Rays::getRay(Rays::SOUTH, square);
const U64 horizontal = Rays::getRay(Rays::WEST, square) | Rays::getRay(Rays::EAST, square);
const U64 rays = vertical | horizontal;

return Bitboard::popCount(rays & board.getType(oppositeColor(color), PAWN));
return Bitboard::popCount(rays & board.getType(~piece.color, PAWN));
}();
value += ROOK_ON_PAWN * rookOnPawn;

Expand Down Expand Up @@ -347,7 +345,7 @@ Score Evaluation::evaluateQueen(const Piece &piece, const byte square, const Boa
const int mobility = Bitboard::popCount(MoveGen<ALL>::generateQueenMoves(piece, square, board));
value += QUEEN_MOBILITY[mobility];

if (const U64 originalPosition = FILE_D & (piece.isWhite ? RANK_1 : RANK_8);
if (const U64 originalPosition = FILE_D & (piece.color ? RANK_1 : RANK_8);
(originalPosition & Bitboard::shiftedBoards[square]) == 0ull)
value.mg -= 30;

Expand Down Expand Up @@ -380,14 +378,13 @@ Score Evaluation::evaluateQueen(const Piece &piece, const byte square, const Boa
inline Score
Evaluation::evaluateKing(const Piece &piece, const byte square, const Board &board) noexcept
{
const Color color = toColor(piece.isWhite);
Score value = Psqt::s_Bonus[KNIGHT][square];

if (board.isCastled(color))
if (board.isCastled(piece.color))
value.mg += 57;
else {
const int count = static_cast<int>(board.canCastleKs(color))
+ static_cast<int>(board.canCastleQs(color));
const int count = static_cast<int>(board.canCastleKs(piece.color))
+ static_cast<int>(board.canCastleQs(piece.color));
value.mg += count * 23;
}

Expand Down
6 changes: 3 additions & 3 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/Hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void Hash::init()

U64 Hash::movePiece(const byte sq, const Piece &piece)
{
return s_Pieces[sq][piece.isWhite][piece.type];
return s_Pieces[sq][piece.color][piece.type];
}

U64 Hash::compute(const Board &board)
Expand All @@ -40,7 +40,7 @@ U64 Hash::compute(const Board &board)

for (byte i = 0; i < 64; ++i)
if (const Piece &piece = board.getPiece(i); piece)
hash ^= s_Pieces[i][piece.isWhite][piece.type];
hash ^= s_Pieces[i][piece.color][piece.type];

if (board.colorToMove)
hash ^= s_WhiteToMove;
Expand Down Expand Up @@ -73,7 +73,7 @@ void Hash::promotePawn(U64 &key, const byte sq, const Color color, const PieceTy

void Hash::xorPiece(U64 &key, const byte sq, const Piece &piece)
{
key ^= s_Pieces[sq][piece.isWhite][piece.type];
key ^= s_Pieces[sq][piece.color][piece.type];
}

void Hash::flipSide(U64 &key)
Expand Down
45 changes: 22 additions & 23 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/MoveGen.inl
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
template <GenType T>
U64 MoveGen<T>::generatePawnMoves(const Piece &piece, const byte square, const Board &board)
{
U64 attacks = PieceAttacks::getPawnAttacks(piece.isWhite, square);
U64 attacks = PieceAttacks::getPawnAttacks(piece.color, square);

if constexpr (T == ALL || T == CAPTURES)
{
U64 captures = attacks & board.allPieces[!piece.isWhite];
U64 captures = attacks & board.allPieces[~piece.color];

if (board.enPassantSq < 64u)
{
Pos capturedPos(board.enPassantSq);
capturedPos.y += static_cast<byte>(piece.isWhite ? -1 : 1);
capturedPos.y += static_cast<byte>(piece.color ? -1 : 1);
// Keep the en-passant capture if it intersect with one of our potential attacks
captures |= attacks & Bitboard::shiftedBoards[board.enPassantSq];
}
Expand All @@ -32,18 +32,18 @@ U64 MoveGen<T>::generatePawnMoves(const Piece &piece, const byte square, const B
{
const U64 initialBb = Bitboard::shiftedBoards[square];
Pos pos(square);
piece.isWhite ? pos.y++ : pos.y--;
piece.color ? pos.y++ : pos.y--;

if (!board[pos])
{
attacks |= pos.toBitboard();

const U64 initialRank = piece.isWhite ? RANK_2 : RANK_7;
const U64 initialRank = piece.color ? RANK_2 : RANK_7;
if (initialRank & initialBb)
{
byte y = pos.y;

piece.isWhite ? y++ : y--;
piece.color ? y++ : y--;
if (y < 8u && !board.getPiece(pos.x, y))
attacks |= Pos(pos.x, y).toBitboard();
}
Expand All @@ -59,9 +59,9 @@ U64 MoveGen<T>::generateKnightMoves(const Piece &piece, const byte square, const
U64 attacks = PieceAttacks::getKnightAttacks(square);

if constexpr (T == ALL)
attacks &= ~board.allPieces[piece.isWhite]; // Remove our pieces
attacks &= ~board.allPieces[piece.color]; // Remove our pieces
else if (T == CAPTURES)
attacks &= board.allPieces[!piece.isWhite]; // Keep only their pieces
attacks &= board.allPieces[~piece.color]; // Keep only their pieces
else if (T == ATTACKS_DEFENSES)
attacks &= board.occupied; // Keep only the pieces

Expand All @@ -74,9 +74,9 @@ U64 MoveGen<T>::generateBishopMoves(const Piece &piece, const byte square, const
U64 attacks = PieceAttacks::getBishopAttacks(square, board.occupied);

if constexpr (T == ALL)
attacks &= ~board.allPieces[piece.isWhite]; // Remove our pieces
attacks &= ~board.allPieces[piece.color]; // Remove our pieces
else if (T == CAPTURES)
attacks &= board.allPieces[!piece.isWhite]; // Keep only their pieces
attacks &= board.allPieces[~piece.color]; // Keep only their pieces
else if (T == ATTACKS_DEFENSES)
attacks &= board.occupied; // Keep only the pieces

Expand All @@ -89,9 +89,9 @@ U64 MoveGen<T>::generateRookMoves(const Piece &piece, const byte square, const B
U64 attacks = PieceAttacks::getRookAttacks(square, board.occupied);

if constexpr (T == ALL)
attacks &= ~board.allPieces[piece.isWhite]; // Remove our pieces
attacks &= ~board.allPieces[piece.color]; // Remove our pieces
else if (T == CAPTURES)
attacks &= board.allPieces[!piece.isWhite]; // Keep only their pieces
attacks &= board.allPieces[~piece.color]; // Keep only their pieces
else if (T == ATTACKS_DEFENSES)
attacks &= board.occupied; // Keep only the pieces

Expand All @@ -105,9 +105,9 @@ U64 MoveGen<T>::generateQueenMoves(const Piece &piece, const byte square, const
| PieceAttacks::getRookAttacks(square, board.occupied);

if constexpr (T == ALL)
attacks &= ~board.allPieces[piece.isWhite]; // Remove our pieces
attacks &= ~board.allPieces[piece.color]; // Remove our pieces
else if (T == CAPTURES)
attacks &= board.allPieces[!piece.isWhite]; // Keep only their pieces
attacks &= board.allPieces[~piece.color]; // Keep only their pieces
else if (T == ATTACKS_DEFENSES)
attacks &= board.occupied; // Keep only the pieces

Expand All @@ -120,9 +120,9 @@ U64 MoveGen<T>::generateKingMoves(const Piece &piece, const byte square, const B
U64 attacks = PieceAttacks::getKingAttacks(square);

if constexpr (T == ALL)
attacks &= ~board.allPieces[piece.isWhite]; // Remove our pieces
attacks &= ~board.allPieces[piece.color]; // Remove our pieces
else if (T == CAPTURES)
attacks &= board.allPieces[!piece.isWhite]; // Keep only their pieces
attacks &= board.allPieces[~piece.color]; // Keep only their pieces
else if (T == ATTACKS_DEFENSES)
attacks &= board.occupied; // Keep only the pieces

Expand All @@ -131,7 +131,7 @@ U64 MoveGen<T>::generateKingMoves(const Piece &piece, const byte square, const B

U64 opponentsMoves{};
{
const Color opponentColor = oppositeColor(toColor(piece.isWhite));
const Color opponentColor = ~piece.color;
U64 attacksCopy = attacks;

while (attacksCopy)
Expand All @@ -149,10 +149,9 @@ U64 MoveGen<T>::generateKingMoves(const Piece &piece, const byte square, const B

// Castling
const U64 bitboard = Bitboard::shiftedBoards[square];
const Color color = toColor(piece.isWhite);
const State checkState = piece.isWhite ? State::WHITE_IN_CHECK : State::BLACK_IN_CHECK;
const State checkState = piece.color ? State::WHITE_IN_CHECK : State::BLACK_IN_CHECK;

if (board.state == checkState || !board.canCastle(color) || opponentsMoves & bitboard)
if (board.state == checkState || !board.canCastle(piece.color) || opponentsMoves & bitboard)
return attacks;

const byte y = row(square);
Expand All @@ -161,19 +160,19 @@ U64 MoveGen<T>::generateKingMoves(const Piece &piece, const byte square, const B
const U64 bb = Bitboard::shiftedBoards[sq];

return !board.getPiece(x, y) && !(opponentsMoves & bb)
&& !Player::isAttacked(oppositeColor(color), sq, board);
&& !Player::isAttacked(~piece.color, sq, board);
};

// King Side
if (board.canCastleKs(color)
if (board.canCastleKs(piece.color)
&& isEmptyAndCheckFree(5)
&& isEmptyAndCheckFree(6))
{
attacks |= Pos(6, y).toBitboard();
}

// Queen Side
if (board.canCastleQs(color)
if (board.canCastleQs(piece.color)
&& isEmptyAndCheckFree(3)
&& isEmptyAndCheckFree(2)
&& !board.getPiece(1, y))
Expand Down
10 changes: 5 additions & 5 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

bool Player::isAttacked(const Color colorAttacking, const byte targetSquare, const Board &board)
{
if (board.getType(colorAttacking, PAWN) & PieceAttacks::getPawnAttacks(oppositeColor(colorAttacking), targetSquare))
if (board.getType(colorAttacking, PAWN) & PieceAttacks::getPawnAttacks(~colorAttacking, targetSquare))
return true;

if (board.getType(colorAttacking, KNIGHT) & PieceAttacks::getKnightAttacks(targetSquare))
Expand Down Expand Up @@ -42,7 +42,7 @@ bool Player::hasNoValidMoves(const Color color, const Board &board)
for (byte startSq = 0u; startSq < SQUARE_NB; ++startSq)
{
const Piece &attacker = board.getPiece(startSq);
if (attacker.type == NO_PIECE_TYPE || attacker.isWhite != board.colorToMove)
if (attacker.type == NO_PIECE_TYPE || attacker.color != board.colorToMove)
continue;

U64 possibleMoves = attacker.getPossibleMoves(startSq, board);
Expand Down Expand Up @@ -71,7 +71,7 @@ bool Player::isInCheck(const Color color, const Board &board)
const U64 king = board.getType(color, KING);
if (!king) return false;

return isAttacked(oppositeColor(color), Bitboard::bitScanForward(king), board);
return isAttacked(~color, Bitboard::bitScanForward(king), board);
}

AttacksMap Player::getAttacksPerColor(const bool white, const Board &board)
Expand All @@ -81,7 +81,7 @@ AttacksMap Player::getAttacksPerColor(const bool white, const Board &board)
for (byte startSq = 0u; startSq < SQUARE_NB; ++startSq)
{
const Piece &piece = board.getPiece(startSq);
if (piece && piece.isWhite == white)
if (piece && piece.color == white)
{
U64 moves{};
using Generator = MoveGen<ATTACKS_DEFENSES>;
Expand Down Expand Up @@ -114,7 +114,7 @@ AttacksMap Player::getAttacksPerColor(const bool white, const Board &board)
{
const byte destSq = Bitboard::findNextSquare(moves);
attacks.map[destSq]++;
attacks.board[piece.isWhite][piece.type - 1u] |= Bitboard::shiftedBoards[destSq];
attacks.board[piece.color][piece.type - 1u] |= Bitboard::shiftedBoards[destSq];
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion ChessAndroid/app/src/main/cpp/chess/algorithm/Search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ RootMove Search::negaMaxRoot(const std::vector<RootMove> &validMoves, const unsi
for (auto &future : futures)
future.get(); // Wait for the search to finish

s_BestMoveFound = oppositeColor(validMoves.front().board.colorToMove) ? alpha : -alpha;
s_BestMoveFound = validMoves.front().board.colorToMove ? -alpha : alpha;

return bestMove;
}
Expand Down
Loading