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
Remake the Pawn Evaluation add Connected Bonus
  • Loading branch information
razvanfilea committed Dec 11, 2019
commit e35ab039931a28151b41290a82e2c22a4cf5b771
95 changes: 40 additions & 55 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/Evaluation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define S Score

constexpr short TEMPO_BONUS = 20;
constexpr S CHECK_BONUS{ 30, 42 };
constexpr S CHECK_BONUS(30, 42);

/*
* These values were imported from the Stockfish Chess Engine
Expand All @@ -20,6 +20,10 @@ constexpr S MINOR_THREATS[] =
constexpr S OVERLOAD(12, 6);
constexpr S PAWN_DOUBLED(11, 56);
constexpr S PAWN_ISOLATED(5, 15);
constexpr short PAWN_CONNECTED[] =
{
0, 7, 8, 12, 29, 48, 86
};
constexpr S PASSED_PAWN_RANK[] =
{
S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260)
Expand Down Expand Up @@ -74,7 +78,7 @@ short Evaluation::simpleEvaluation(const Board &board) noexcept
return VALUE_WINNER_BLACK;

Score score[2]{};
for (byte i = 0; i < 64u; i++)
for (byte i = 0; i < SQUARE_NB; i++)
{
const Piece &piece = board.getPiece(i);
score[piece.color] += Psqt::s_Bonus[piece.type][i];
Expand Down Expand Up @@ -104,7 +108,7 @@ short Evaluation::evaluate(const Board &board) noexcept
const AttacksMap whiteMoves = Player::getAttacksPerColor(true, board);
const AttacksMap blackMoves = Player::getAttacksPerColor(false, board);

for (byte i = 0; i < 64u; i++)
for (byte i = 0u; i < SQUARE_NB; i++)
if (const auto &piece = board.getPiece(i); piece && piece.type != KING)
{
if (piece.type == PAWN)
Expand Down Expand Up @@ -145,7 +149,7 @@ short Evaluation::evaluate(const Board &board) noexcept
if (bishopCount[BLACK] >= 2)
totalScore[BLACK] += 10;

for (byte i = 0; i < 64u; i++)
for (byte i = 0u; i < SQUARE_NB; i++)
if (const Piece &piece = board.getPiece(i); piece)
{
const Score points = [&] {
Expand Down Expand Up @@ -187,70 +191,53 @@ short Evaluation::evaluate(const Board &board) noexcept
Score Evaluation::evaluatePawn(const Piece &piece, const byte square, const Board &board,
const AttacksMap &ourAttacks, const AttacksMap &theirAttacks) noexcept
{
const Color oppositeColor = ~piece.color;
const Pos pos(square);
Score value = Psqt::s_Bonus[PAWN][square];

const Rays::Dir forwardDir = piece.color ? Rays::NORTH : Rays::SOUTH;
const byte rank = (piece.color ? pos.y : 7u - pos.y) - 1u;
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));

bool isolated = !static_cast<bool>(supported);

if (piece == board.getPiece(pos.x, pos.y + behind))
value -= PAWN_DOUBLED;
const U64 adjacentFiles = Rays::getAdjacentFiles(square);
const U64 opposed = board.getType(oppositeColor, PAWN) & Rays::getRay(forwardDir, square);
const U64 neighbours = board.getType(piece.color, PAWN) & adjacentFiles;
const U64 connected = neighbours & Rays::getRank(square);
const U64 support = neighbours & Rays::getRank(toSquare(pos.x + behind, pos.y));
const bool isDoubled = board.at(pos.x, pos.y - behind) == piece;

if (isolated)
if (support | connected)
{
for (byte y = 0u ; y < 8u; y++) {
if (piece == board.at(pos.x - 1u, y) ||
piece == board.at(pos.x + 1u, y))
{
isolated = false;
break;
}
}
}
const int connectedScore = PAWN_CONNECTED[rank] * (2 + bool(connected) - bool(opposed))
+ 21 * Bitboard::popCount(support);

if (isolated)
value += Score(connectedScore, connectedScore * (rank - 2) / 4);
} else if (!neighbours)
value -= PAWN_ISOLATED;

if (!support && isDoubled)
value -= PAWN_DOUBLED;

// Threat Safe Pawn
if (ourAttacks.map[square] || theirAttacks.map[square] == 0) // check if the pawn is safe
{
const auto isEnemyPiece = [&] (const byte x, const byte y) {
const Pos newPos(pos, x, y);
if (!newPos.isValid()) return false;
const U64 enemyPieces = MoveGen<CAPTURES>::generatePawnMoves(piece, square, board)
& ~(board.getType(oppositeColor, PAWN) | board.getType(oppositeColor, KING));

const Piece &other = board[newPos];
const byte type = other.type;
return other.color != piece.color && type > PAWN && type < KING;
};
const int count = Bitboard::popCount(enemyPieces);

const int i = static_cast<int>(isEnemyPiece(-1, -behind))
+ static_cast<int>(isEnemyPiece(1u, -behind));

value += THREAT_SAFE_PAWN * i;
value += THREAT_SAFE_PAWN * count;
}

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

const Pos posLeft(pos, -1, -behind);
const Pos posRight(pos, 1, -behind);
{ // Passed Pawn
U64 rays = Rays::getRay(forwardDir, square);
const U64 adjacentRays = Rays::shift<Rays::WEST>(rays) | Rays::shift<Rays::EAST>(rays);
rays |= piece.color ? Rays::shift<Rays::NORTH>(adjacentRays) : Rays::shift<Rays::SOUTH>(adjacentRays);

U64 rays = Rays::getRay(direction, square);
if (posLeft.isValid())
rays |= Rays::getRay(direction, posLeft.toSquare());
if (posRight.isValid())
rays |= Rays::getRay(direction, posRight.toSquare());
const bool isPassedPawn = !static_cast<bool>(rays & board.getType(oppositeColor, PAWN));

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

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

return value;
Expand Down Expand Up @@ -278,7 +265,7 @@ Score Evaluation::evaluateBishop(const Piece &piece, const byte square, const Bo
const auto isLongDiagonalBishop = [&] {
if (pos.y - pos.x == 0 || pos.y - (7 - pos.x) == 0)
{
auto [x, y] = pos;
auto[x, y] = pos;
if (std::min<byte>(x, 7u - x) > 2) return false;
for (byte i = std::min<byte>(x, 7u - x); i < 4; i++)
{
Expand Down Expand Up @@ -375,17 +362,15 @@ Score Evaluation::evaluateQueen(const Piece &piece, const byte square, const Boa
return value;
}

inline Score
Evaluation::evaluateKing(const Piece &piece, const byte square, const Board &board) noexcept
inline Score Evaluation::evaluateKing(const Piece &piece, const byte square, const Board &board) noexcept
{
Score value = Psqt::s_Bonus[KNIGHT][square];

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

return value;
Expand Down
2 changes: 1 addition & 1 deletion ChessAndroid/app/src/main/cpp/chess/algorithm/Hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ U64 Hash::compute(const Board &board)
{
U64 hash{};

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

Expand Down
10 changes: 7 additions & 3 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/Search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ short Search::negaMax(const Board &board, const short ply, short alpha, short be

const auto validMoves = board.listValidMoves<Board>();
short bestScore = VALUE_MIN;
short movesCount = 0;
size_t movesCount{};

Stats::incrementNodesGenerated(validMoves.size());

Expand Down Expand Up @@ -196,7 +196,7 @@ short Search::negaMax(const Board &board, const short ply, short alpha, short be
++movesCount;
}

Stats::incrementNodesSearched(static_cast<size_t>(movesCount));
Stats::incrementNodesSearched(movesCount);

// Store the result in the transposition table
Flag flag = Flag::EXACT;
Expand Down Expand Up @@ -240,8 +240,8 @@ short Search::quiescence(const Board &board, short alpha, const short beta)
}

const auto validMoves = board.listQuiescenceMoves();
size_t movesCount{};

Stats::incrementNodesSearched();
Stats::incrementNodesGenerated(validMoves.size());

for (const Board &move : validMoves)
Expand All @@ -255,8 +255,12 @@ short Search::quiescence(const Board &board, short alpha, const short beta)
return moveScore;
if (moveScore > alpha)
alpha = moveScore;

++movesCount;
}

Stats::incrementNodesSearched(movesCount);

return alpha;
}

Expand Down
4 changes: 2 additions & 2 deletions ChessAndroid/app/src/main/cpp/chess/data/Defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ constexpr U64 FILE_A = 0x101010101010101ull;

constexpr byte SQUARE_NB = 64u;

constexpr byte row(const byte pos) noexcept { return static_cast<byte>(pos / 8u); }
constexpr byte row(const byte pos) noexcept { return static_cast<byte>(pos >> 3u); }

constexpr byte col(const byte pos) noexcept { return static_cast<byte>(pos % 8u); }
constexpr byte col(const byte pos) noexcept { return static_cast<byte>(pos & 7u); }

constexpr byte toSquare(const byte x, const byte y) noexcept
{
Expand Down
54 changes: 51 additions & 3 deletions ChessAndroid/app/src/main/cpp/chess/data/Rays.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ namespace Rays
/**
* Table of precalculated ray bitboards indexed by direction and square
*/
constexpr static std::array<std::array<U64, 64>, 8> rays = [] {
std::array<std::array<U64, 64>, 8> rays{};
constexpr static auto rays = [] {
std::array<std::array<U64, SQUARE_NB>, 8> rays{};

using namespace Bitboard;

for (byte square = 0u; square < 64u; square++)
for (byte square = 0u; square < SQUARE_NB; ++square)
{
rays[NORTH][square] = 0x0101010101010100ULL << square;

Expand All @@ -47,6 +47,39 @@ namespace Rays
return rays;
}();

constexpr static auto ranks = [] {
std::array<U64, 8> ranks{};

for (byte r = 0u; r < 8u; ++r)
ranks[r] = 0b1111'1111ull << (8u * r);

return ranks;
}();

constexpr static auto files = [] {
std::array<U64, 8> files{};

for (byte f = 0u; f < 8u; ++f)
files[f] = 0x101010101010101ull << f;

return files;
}();

template <Dir D>
constexpr U64 shift(const U64 bb) noexcept
{
if constexpr (D == NORTH)
return bb << 8u;
else if (D == SOUTH)
return bb >> 8u;
else if (D == EAST)
return (bb & ~FILE_H) << 1u;
else if (D == WEST)
return (bb & ~FILE_A) >> 1u;

return {};
}

/**
* Returns a bitboard containing the given ray in the given direction.
*
Expand All @@ -57,4 +90,19 @@ namespace Rays
{
return rays[direction][square];
}

constexpr U64 getRank(const byte square) noexcept
{
return ranks[row(square)];
}

constexpr U64 getFile(const byte square) noexcept
{
return files[col(square)];
}

constexpr U64 getAdjacentFiles(const byte square) noexcept
{
return shift<WEST>(getFile(square)) | shift<EAST>(getFile(square));
}
};