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 a critical error with Board::doMove()
  • Loading branch information
razvanfilea committed Nov 24, 2019
commit 2bfdff3f298845d2516428e5a6432bfb2cc08724
2 changes: 1 addition & 1 deletion ChessAndroid/app/src/main/cpp/chess/BoardManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void BoardManager::movePiece(const byte startSq, const byte destSq, const bool m
assert(startSq < 64 && destSq < 64);

const byte castledBefore = (s_Board.castlingRights & CASTLED_WHITE) | (s_Board.castlingRights & CASTLED_BLACK);
s_Board.doMove(startSq, startSq);
s_Board.doMove(startSq, destSq);
const byte castledAfter = (s_Board.castlingRights & CASTLED_WHITE) | (s_Board.castlingRights & CASTLED_BLACK);

s_Board.score = Evaluation::evaluate(s_Board);
Expand Down
4 changes: 2 additions & 2 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/Evaluation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ short Evaluation::evaluate(const Board &board) noexcept
short whiteNpm = 0;
short blackNpm = 0;

const auto whiteMoves = MoveGen<ATTACKS_DEFENSES>::getAttacksPerColor(true, board);
const auto blackMoves = MoveGen<ATTACKS_DEFENSES>::getAttacksPerColor(false, board);
const AttacksMap whiteMoves = Player::getAttacksPerColor(true, board);
const AttacksMap blackMoves = Player::getAttacksPerColor(false, board);

for (byte i = 0; i < 64u; i++)
if (const auto &piece = board.getPiece(i); piece && piece.type != KING)
Expand Down
5 changes: 0 additions & 5 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/MoveGen.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#pragma once

#include "../containers/Containers.h"

enum GenType : unsigned char
{
ALL,
Expand All @@ -24,9 +22,6 @@ class MoveGen final
static U64 generateRookMoves(const Piece &piece, byte square, const Board &board);
static U64 generateQueenMoves(const Piece &piece, byte square, const Board &board);
static U64 generateKingMoves(const Piece &piece, byte square, const Board &board);

static void forEachAttack(bool white, const Board &board, const std::function<bool(U64 attacks)> &func);
static AttacksMap getAttacksPerColor(bool white, const Board &board);
};

#include "MoveGen.inl"
164 changes: 48 additions & 116 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/MoveGen.inl
Original file line number Diff line number Diff line change
Expand Up @@ -142,137 +142,69 @@ U64 MoveGen<T>::generateKingMoves(const Piece &piece, const byte square, const B
if constexpr (T == CAPTURES || T == ATTACKS_DEFENSES || T == KING_DANGER)
return attacks;

if (attacks == 0ull)
return attacks;

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

while (attacksCopy)
{
const byte currentSquare = Bitboard::findNextSquare(attacksCopy);
if (Player::isAttacked(opponentColor, currentSquare, board))
opponentsMoves |= Bitboard::shiftedBoards[currentSquare];
}

attacks &= ~opponentsMoves;
}

/*U64 opponentsMoves{};
MoveGen<KING_DANGER>::forEachAttack(!piece.isWhite, board, [&] (const U64 enemyAttacks) -> bool {
opponentsMoves |= enemyAttacks;
attacks &= ~enemyAttacks; // Remove Attacked Positions
return static_cast<bool>(attacks);
});
});*/

if (!attacks) return 0ull;
if (!attacks)
return 0ull;

// 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;
if (board.state != checkState
&& board.canCastleAnywhere(color)
&& !(opponentsMoves & Bitboard::shiftedBoards[square]))
{
const byte y = row(square);
const auto isEmptyAndCheckFree = [&, y](const byte x) {
return !board.getPiece(x, y) && !(opponentsMoves & Pos(x, y).toBitboard());
};

if (board.canCastleKs(color)
&& isEmptyAndCheckFree(5)
&& isEmptyAndCheckFree(6))
{
if (const auto &other = board.getPiece(7, y);
other.type == PieceType::ROOK
&& piece.isSameColor(other))
attacks |= Pos(6, y).toBitboard();
}

if (board.canCastleQs(color)
&& isEmptyAndCheckFree(3)
&& isEmptyAndCheckFree(2)
&& !board.getPiece(1, y))
{
if (const auto &other = board.getPiece(0, y);
other.type == PieceType::ROOK
&& piece.isSameColor(other))
attacks |= Pos(2, y).toBitboard();
}
}

return attacks;
}

template <GenType T> // Class Template
void MoveGen<T>::forEachAttack(const bool white, const Board &board, const std::function<bool(U64 attacks)> &func)
{
for (byte i = 0; i < 64u; ++i)
if (board.state == checkState || !board.canCastle(color) || opponentsMoves & bitboard)
return attacks;

const byte y = row(square);
const auto isEmptyAndCheckFree = [&, y](const byte x) {
const byte sq = Pos(x, y).toSquare();
const U64 bb = Bitboard::shiftedBoards[sq];

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

// King Side
if (board.canCastleKs(color)
&& isEmptyAndCheckFree(5)
&& isEmptyAndCheckFree(6))
{
const auto &piece = board.getPiece(i);
if (piece && piece.isWhite == white)
{
U64 moves{};
switch (piece.type)
{
case PieceType::PAWN:
moves = MoveGen<KING_DANGER>::generatePawnMoves(piece, i, board);
break;
case PieceType::KNIGHT:
moves = generateKnightMoves(piece, i, board);
break;
case PieceType::BISHOP:
moves = generateBishopMoves(piece, i, board);
break;
case PieceType::ROOK:
moves = generateRookMoves(piece, i, board);
break;
case PieceType::QUEEN:
moves = generateQueenMoves(piece, i, board);
break;
case PieceType::KING:
moves = MoveGen<KING_DANGER>::generateKingMoves(piece, i, board);
break;
case PieceType::NONE:
break;
}

// The function should return true in order to stop the loop
if (func(moves))
return;
}
// This shouldn't be needed because the Castling rights would not exist
/*if (const auto &other = board.getPiece(7, y);
other.type == PieceType::ROOK
&& piece.isSameColor(other))*/
attacks |= Pos(6, y).toBitboard();
}
}

template<GenType T>
AttacksMap MoveGen<T>::getAttacksPerColor(const bool white, const Board &board)
{
AttacksMap attacks{};

for (byte startSq = 0; startSq < 64u; ++startSq)
// Queen Side
if (board.canCastleQs(color)
&& isEmptyAndCheckFree(3)
&& isEmptyAndCheckFree(2)
&& !board.getPiece(1, y))
{
const Piece &piece = board.getPiece(startSq);
if (piece && piece.isWhite == white)
{
U64 moves{};
switch (piece.type)
{
case PieceType::PAWN:
moves = MoveGen<KING_DANGER>::generatePawnMoves(piece, startSq, board);
break;
case PieceType::KNIGHT:
moves = generateKnightMoves(piece, startSq, board);
break;
case PieceType::BISHOP:
moves = generateBishopMoves(piece, startSq, board);
break;
case PieceType::ROOK:
moves = generateRookMoves(piece, startSq, board);
break;
case PieceType::QUEEN:
moves = generateQueenMoves(piece, startSq, board);
break;
case PieceType::KING:
moves = MoveGen<KING_DANGER>::generateKingMoves(piece, startSq, board);
break;
case PieceType::NONE:
break;
}

while (moves)
{
const byte destSq = Bitboard::findNextSquare(moves);
attacks.map[destSq]++;
attacks.board[piece.isWhite][piece.type - 1u] |= Bitboard::shiftedBoards[destSq];
}
}
/*if (const auto &other = board.getPiece(0, y);
other.type == PieceType::ROOK
&& piece.isSameColor(other))*/
attacks |= Pos(2, y).toBitboard();
}

return attacks;
Expand Down
61 changes: 31 additions & 30 deletions ChessAndroid/app/src/main/cpp/chess/algorithm/PieceAttacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,49 +29,51 @@ constexpr std::array<byte, 64> bishopIndexBits = {
* Rook and bishop magic values for magic table lookups
*/
constexpr std::array<U64, 64> bishopMagics = {
0x89a1121896040240ULL, 0x2004844802002010ULL, 0x2068080051921000ULL, 0x62880a0220200808ULL, 0x4042004000000ULL,
0x100822020200011ULL, 0xc00444222012000aULL, 0x28808801216001ULL, 0x400492088408100ULL, 0x201c401040c0084ULL,
0x840800910a0010ULL, 0x82080240060ULL, 0x2000840504006000ULL, 0x30010c4108405004ULL, 0x1008005410080802ULL,
0x8144042209100900ULL, 0x208081020014400ULL, 0x4800201208ca00ULL, 0xf18140408012008ULL, 0x1004002802102001ULL,
0x841000820080811ULL, 0x40200200a42008ULL, 0x800054042000ULL, 0x88010400410c9000ULL, 0x520040470104290ULL,
0x1004040051500081ULL, 0x2002081833080021ULL, 0x400c00c010142ULL, 0x941408200c002000ULL, 0x658810000806011ULL,
0x188071040440a00ULL, 0x4800404002011c00ULL, 0x104442040404200ULL, 0x511080202091021ULL, 0x4022401120400ULL,
0x80c0040400080120ULL, 0x8040010040820802ULL, 0x480810700020090ULL, 0x102008e00040242ULL, 0x809005202050100ULL,
0x8002024220104080ULL, 0x431008804142000ULL, 0x19001802081400ULL, 0x200014208040080ULL, 0x3308082008200100ULL,
0x41010500040c020ULL, 0x4012020c04210308ULL, 0x208220a202004080ULL, 0x111040120082000ULL, 0x6803040141280a00ULL,
0x2101004202410000ULL, 0x8200000041108022ULL, 0x21082088000ULL, 0x2410204010040ULL, 0x40100400809000ULL,
0x822088220820214ULL, 0x40808090012004ULL, 0x910224040218c9ULL, 0x402814422015008ULL, 0x90014004842410ULL,
0x1000042304105ULL, 0x10008830412a00ULL, 0x2520081090008908ULL, 0x40102000a0a60140ULL,
0x89a1121896040240ull, 0x2004844802002010ull, 0x2068080051921000ull, 0x62880a0220200808ull, 0x4042004000000ull,
0x100822020200011ull, 0xc00444222012000aull, 0x28808801216001ull, 0x400492088408100ull, 0x201c401040c0084ull,
0x840800910a0010ull, 0x82080240060ull, 0x2000840504006000ull, 0x30010c4108405004ull, 0x1008005410080802ull,
0x8144042209100900ull, 0x208081020014400ull, 0x4800201208ca00ull, 0xf18140408012008ull, 0x1004002802102001ull,
0x841000820080811ull, 0x40200200a42008ull, 0x800054042000ull, 0x88010400410c9000ull, 0x520040470104290ull,
0x1004040051500081ull, 0x2002081833080021ull, 0x400c00c010142ull, 0x941408200c002000ull, 0x658810000806011ull,
0x188071040440a00ull, 0x4800404002011c00ull, 0x104442040404200ull, 0x511080202091021ull, 0x4022401120400ull,
0x80c0040400080120ull, 0x8040010040820802ull, 0x480810700020090ull, 0x102008e00040242ull, 0x809005202050100ull,
0x8002024220104080ull, 0x431008804142000ull, 0x19001802081400ull, 0x200014208040080ull, 0x3308082008200100ull,
0x41010500040c020ull, 0x4012020c04210308ull, 0x208220a202004080ull, 0x111040120082000ull, 0x6803040141280a00ull,
0x2101004202410000ull, 0x8200000041108022ull, 0x21082088000ull, 0x2410204010040ull, 0x40100400809000ull,
0x822088220820214ull, 0x40808090012004ull, 0x910224040218c9ull, 0x402814422015008ull, 0x90014004842410ull,
0x1000042304105ull, 0x10008830412a00ull, 0x2520081090008908ull, 0x40102000a0a60140ull,
};

constexpr std::array<U64, 64> rookMagics = {
0xa8002c000108020ULL, 0x6c00049b0002001ULL, 0x100200010090040ULL, 0x2480041000800801ULL, 0x280028004000800ULL,
0x900410008040022ULL, 0x280020001001080ULL, 0x2880002041000080ULL, 0xa000800080400034ULL, 0x4808020004000ULL,
0x2290802004801000ULL, 0x411000d00100020ULL, 0x402800800040080ULL, 0xb000401004208ULL, 0x2409000100040200ULL,
0x1002100004082ULL, 0x22878001e24000ULL, 0x1090810021004010ULL, 0x801030040200012ULL, 0x500808008001000ULL,
0xa08018014000880ULL, 0x8000808004000200ULL, 0x201008080010200ULL, 0x801020000441091ULL, 0x800080204005ULL,
0x1040200040100048ULL, 0x120200402082ULL, 0xd14880480100080ULL, 0x12040280080080ULL, 0x100040080020080ULL,
0x9020010080800200ULL, 0x813241200148449ULL, 0x491604001800080ULL, 0x100401000402001ULL, 0x4820010021001040ULL,
0x400402202000812ULL, 0x209009005000802ULL, 0x810800601800400ULL, 0x4301083214000150ULL, 0x204026458e001401ULL,
0x40204000808000ULL, 0x8001008040010020ULL, 0x8410820820420010ULL, 0x1003001000090020ULL, 0x804040008008080ULL,
0x12000810020004ULL, 0x1000100200040208ULL, 0x430000a044020001ULL, 0x280009023410300ULL, 0xe0100040002240ULL,
0x200100401700ULL, 0x2244100408008080ULL, 0x8000400801980ULL, 0x2000810040200ULL, 0x8010100228810400ULL,
0x2000009044210200ULL, 0x4080008040102101ULL, 0x40002080411d01ULL, 0x2005524060000901ULL, 0x502001008400422ULL,
0x489a000810200402ULL, 0x1004400080a13ULL, 0x4000011008020084ULL, 0x26002114058042ULL
0xa8002c000108020ull, 0x6c00049b0002001ull, 0x100200010090040ull, 0x2480041000800801ull, 0x280028004000800ull,
0x900410008040022ull, 0x280020001001080ull, 0x2880002041000080ull, 0xa000800080400034ull, 0x4808020004000ull,
0x2290802004801000ull, 0x411000d00100020ull, 0x402800800040080ull, 0xb000401004208ull, 0x2409000100040200ull,
0x1002100004082ull, 0x22878001e24000ull, 0x1090810021004010ull, 0x801030040200012ull, 0x500808008001000ull,
0xa08018014000880ull, 0x8000808004000200ull, 0x201008080010200ull, 0x801020000441091ull, 0x800080204005ull,
0x1040200040100048ull, 0x120200402082ull, 0xd14880480100080ull, 0x12040280080080ull, 0x100040080020080ull,
0x9020010080800200ull, 0x813241200148449ull, 0x491604001800080ull, 0x100401000402001ull, 0x4820010021001040ull,
0x400402202000812ull, 0x209009005000802ull, 0x810800601800400ull, 0x4301083214000150ull, 0x204026458e001401ull,
0x40204000808000ull, 0x8001008040010020ull, 0x8410820820420010ull, 0x1003001000090020ull, 0x804040008008080ull,
0x12000810020004ull, 0x1000100200040208ull, 0x430000a044020001ull, 0x280009023410300ull, 0xe0100040002240ull,
0x200100401700ull, 0x2244100408008080ull, 0x8000400801980ull, 0x2000810040200ull, 0x8010100228810400ull,
0x2000009044210200ull, 0x4080008040102101ull, 0x40002080411d01ull, 0x2005524060000901ull, 0x502001008400422ull,
0x489a000810200402ull, 0x1004400080a13ull, 0x4000011008020084ull, 0x26002114058042ull
};

/**
* Rook and bishop sliding attack masks indexed by [square]
* These do not include edge squares
*/
constexpr auto bishopMasks = [] {
const U64 edgeSquares = FILE_A | FILE_H | RANK_1 | RANK_8;
std::array<U64, 64> masks{};

for (byte square = 0u; square < 64u; ++square)
{
masks[square] = Rays::getRay(Rays::NORTH_EAST, square)
masks[square] = (Rays::getRay(Rays::NORTH_EAST, square)
| Rays::getRay(Rays::NORTH_WEST, square)
| Rays::getRay(Rays::SOUTH_EAST, square)
| Rays::getRay(Rays::SOUTH_WEST, square);
| Rays::getRay(Rays::SOUTH_WEST, square)
| Rays::getRay(Rays::SOUTH_EAST, square)) & ~(edgeSquares);
}

return masks;
Expand Down Expand Up @@ -293,7 +295,6 @@ U64 PieceAttacks::getKnightAttacks(const byte square) noexcept

U64 PieceAttacks::getBishopAttacks(const byte square, U64 blockers) noexcept
{
return generateBishopAttacks(square, blockers);
blockers &= bishopMasks[square];
const U64 key = (blockers * bishopMagics[square]) >> (64u - bishopIndexBits[square]);
return s_BishopAttacks[square][key];
Expand Down
4 changes: 1 addition & 3 deletions ChessAndroid/app/src/main/cpp/chess/containers/PosMap.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#pragma once

using byte = unsigned char;

class Pos;
#include "../data/Pos.h"

class PosMap
{
Expand Down
10 changes: 5 additions & 5 deletions ChessAndroid/app/src/main/cpp/chess/data/Board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ void Board::setToFen(const std::string &fen)
parser.parseFen(fen);
}

bool Board::canCastle(const Color color) const noexcept
{
return castlingRights & (color == BLACK ? CASTLE_BLACK : CASTLE_WHITE);
}

bool Board::canCastleKs(const Color color) const noexcept
{
return castlingRights & (color == BLACK ? CASTLE_BLACK_KING : CASTLE_WHITE_KING);
Expand All @@ -24,11 +29,6 @@ bool Board::canCastleQs(const Color color) const noexcept
return castlingRights & (color == BLACK ? CASTLE_BLACK_QUEEN : CASTLE_WHITE_QUEEN);
}

bool Board::canCastleAnywhere(const Color color) const noexcept
{
return castlingRights & (color == BLACK ? CASTLE_BLACK : CASTLE_WHITE);
}

bool Board::isCastled(const Color color) const noexcept
{
return castlingRights & (color == BLACK ? CASTLED_BLACK : CASTLED_WHITE);
Expand Down
2 changes: 1 addition & 1 deletion ChessAndroid/app/src/main/cpp/chess/data/Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ class Board final
void initDefaultBoard() noexcept;
void setToFen(const std::string &fen);

bool canCastle(Color color) const noexcept;
bool canCastleKs(Color color) const noexcept;
bool canCastleQs(Color color) const noexcept;
bool canCastleAnywhere(Color color) const noexcept;
bool isCastled(Color color) const noexcept;

Piece &getPiece(byte squareIndex) noexcept;
Expand Down
Loading