mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 08:43:09 +00:00
Assume input FEN string is correct in from_fen()
And also tolerate a 0 value for full move number. Revert BUG_41 patch, now we set initial King file only if a castling is possible, so we don't need the fix anymore in case of correct FEN. No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
9305983018
commit
c9b24c3358
5 changed files with 75 additions and 94 deletions
144
src/position.cpp
144
src/position.cpp
|
@ -48,8 +48,8 @@ Score Position::PieceSquareTable[16][64];
|
||||||
const Value PieceValueMidgame[17] = {
|
const Value PieceValueMidgame[17] = {
|
||||||
VALUE_ZERO,
|
VALUE_ZERO,
|
||||||
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
|
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
|
||||||
RookValueMidgame, QueenValueMidgame, VALUE_ZERO,
|
RookValueMidgame, QueenValueMidgame,
|
||||||
VALUE_ZERO, VALUE_ZERO,
|
VALUE_ZERO, VALUE_ZERO, VALUE_ZERO,
|
||||||
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
|
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
|
||||||
RookValueMidgame, QueenValueMidgame
|
RookValueMidgame, QueenValueMidgame
|
||||||
};
|
};
|
||||||
|
@ -57,8 +57,8 @@ const Value PieceValueMidgame[17] = {
|
||||||
const Value PieceValueEndgame[17] = {
|
const Value PieceValueEndgame[17] = {
|
||||||
VALUE_ZERO,
|
VALUE_ZERO,
|
||||||
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
|
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
|
||||||
RookValueEndgame, QueenValueEndgame, VALUE_ZERO,
|
RookValueEndgame, QueenValueEndgame,
|
||||||
VALUE_ZERO, VALUE_ZERO,
|
VALUE_ZERO, VALUE_ZERO, VALUE_ZERO,
|
||||||
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
|
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
|
||||||
RookValueEndgame, QueenValueEndgame
|
RookValueEndgame, QueenValueEndgame
|
||||||
};
|
};
|
||||||
|
@ -121,7 +121,7 @@ void Position::detach() {
|
||||||
|
|
||||||
startState = *st;
|
startState = *st;
|
||||||
st = &startState;
|
st = &startState;
|
||||||
st->previous = NULL; // as a safe guard
|
st->previous = NULL; // As a safe guard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,64 +159,56 @@ void Position::from_fen(const string& fen, bool isChess960) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char token;
|
char token;
|
||||||
int hmc, fmn;
|
|
||||||
size_t p;
|
size_t p;
|
||||||
|
string ep;
|
||||||
Square sq = SQ_A8;
|
Square sq = SQ_A8;
|
||||||
std::istringstream ss(fen);
|
std::istringstream ss(fen);
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
ss >> std::noskipws;
|
ss >> std::skipws >> token >> std::noskipws;
|
||||||
|
|
||||||
// 1. Piece placement field
|
// 1. Piece placement
|
||||||
while ((ss >> token) && !isspace(token))
|
while (!isspace(token))
|
||||||
{
|
{
|
||||||
if ((p = PieceToChar.find(token)) != string::npos)
|
if (token == '/')
|
||||||
|
sq -= Square(16); // Jump back of 2 rows
|
||||||
|
|
||||||
|
else if (isdigit(token))
|
||||||
|
sq += Square(token - '0'); // Skip the given number of files
|
||||||
|
|
||||||
|
else if ((p = PieceToChar.find(token)) != string::npos)
|
||||||
{
|
{
|
||||||
put_piece(Piece(p), sq);
|
put_piece(Piece(p), sq);
|
||||||
sq++;
|
sq++;
|
||||||
}
|
}
|
||||||
else if (isdigit(token))
|
|
||||||
sq += Square(token - '0'); // Skip the given number of files
|
ss >> token;
|
||||||
else if (token == '/')
|
|
||||||
sq -= SQ_A3; // Jump back of 2 rows
|
|
||||||
else
|
|
||||||
goto incorrect_fen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Active color
|
// 2. Active color
|
||||||
if (!(ss >> token) || (token != 'w' && token != 'b'))
|
ss >> std::skipws >> token;
|
||||||
goto incorrect_fen;
|
|
||||||
|
|
||||||
sideToMove = (token == 'w' ? WHITE : BLACK);
|
sideToMove = (token == 'w' ? WHITE : BLACK);
|
||||||
|
|
||||||
if (!(ss >> token) || !isspace(token))
|
|
||||||
goto incorrect_fen;
|
|
||||||
|
|
||||||
// 3. Castling availability
|
// 3. Castling availability
|
||||||
while ((ss >> token) && !isspace(token))
|
ss >> token >> std::noskipws;
|
||||||
if (!set_castling_rights(token))
|
while (token != '-' && !isspace(token))
|
||||||
goto incorrect_fen;
|
|
||||||
|
|
||||||
// 4. En passant square
|
|
||||||
char col, row;
|
|
||||||
if ( ((ss >> col) && (col >= 'a' && col <= 'h'))
|
|
||||||
&& ((ss >> row) && (row == '3' || row == '6')))
|
|
||||||
{
|
{
|
||||||
st->epSquare = make_square(File(col - 'a') + FILE_A, Rank(row - '1') + RANK_1);
|
set_castling_rights(token);
|
||||||
|
ss >> token;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore if no capture is possible
|
// 4. En passant square. Ignore if no pawn capture is possible
|
||||||
Color them = opposite_color(sideToMove);
|
ss >> std::skipws >> ep;
|
||||||
if (!(attacks_from<PAWN>(st->epSquare, them) & pieces(PAWN, sideToMove)))
|
if (ep.size() == 2)
|
||||||
|
{
|
||||||
|
st->epSquare = make_square(File(ep[0] - 'a'), Rank(ep[1] - '1'));
|
||||||
|
|
||||||
|
if (!(attackers_to(st->epSquare) & pieces(PAWN, sideToMove)))
|
||||||
st->epSquare = SQ_NONE;
|
st->epSquare = SQ_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Halfmove clock
|
// 5-6. Halfmove clock and fullmove number
|
||||||
if (ss >> std::skipws >> hmc)
|
ss >> st->rule50 >> fullMoves;
|
||||||
st->rule50 = hmc;
|
|
||||||
|
|
||||||
// 6. Fullmove number
|
|
||||||
if (ss >> fmn)
|
|
||||||
startPosPlyCounter = (fmn - 1) * 2 + int(sideToMove == BLACK);
|
|
||||||
|
|
||||||
// Various initialisations
|
// Various initialisations
|
||||||
castleRightsMask[make_square(initialKFile, RANK_1)] ^= WHITE_OO | WHITE_OOO;
|
castleRightsMask[make_square(initialKFile, RANK_1)] ^= WHITE_OO | WHITE_OOO;
|
||||||
|
@ -235,10 +227,6 @@ void Position::from_fen(const string& fen, bool isChess960) {
|
||||||
st->value = compute_value();
|
st->value = compute_value();
|
||||||
st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
|
st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
|
||||||
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
|
||||||
return;
|
|
||||||
|
|
||||||
incorrect_fen:
|
|
||||||
cout << "Error in FEN string: " << fen << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -249,39 +237,39 @@ incorrect_fen:
|
||||||
/// associated with the castling right, the traditional castling tag will be replaced
|
/// associated with the castling right, the traditional castling tag will be replaced
|
||||||
/// by the file letter of the involved rook as for the Shredder-FEN.
|
/// by the file letter of the involved rook as for the Shredder-FEN.
|
||||||
|
|
||||||
bool Position::set_castling_rights(char token) {
|
void Position::set_castling_rights(char token) {
|
||||||
|
|
||||||
Color c = token >= 'a' ? BLACK : WHITE;
|
Color c = islower(token) ? BLACK : WHITE;
|
||||||
Square sqA = (c == WHITE ? SQ_A1 : SQ_A8);
|
|
||||||
Square sqH = (c == WHITE ? SQ_H1 : SQ_H8);
|
Square sqA = relative_square(c, SQ_A1);
|
||||||
Piece rook = (c == WHITE ? WR : BR);
|
Square sqH = relative_square(c, SQ_H1);
|
||||||
|
|
||||||
initialKFile = square_file(king_square(c));
|
initialKFile = square_file(king_square(c));
|
||||||
token = char(toupper(token));
|
|
||||||
|
|
||||||
if (token == 'K')
|
if (toupper(token) == 'K')
|
||||||
{
|
{
|
||||||
for (Square sq = sqH; sq >= sqA; sq--)
|
for (Square sq = sqH; sq >= sqA; sq--)
|
||||||
if (piece_on(sq) == rook)
|
if (piece_on(sq) == make_piece(c, ROOK))
|
||||||
{
|
{
|
||||||
set_castle_kingside(c);
|
set_castle_kingside(c);
|
||||||
initialKRFile = square_file(sq);
|
initialKRFile = square_file(sq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (token == 'Q')
|
else if (toupper(token) == 'Q')
|
||||||
{
|
{
|
||||||
for (Square sq = sqA; sq <= sqH; sq++)
|
for (Square sq = sqA; sq <= sqH; sq++)
|
||||||
if (piece_on(sq) == rook)
|
if (piece_on(sq) == make_piece(c, ROOK))
|
||||||
{
|
{
|
||||||
set_castle_queenside(c);
|
set_castle_queenside(c);
|
||||||
initialQRFile = square_file(sq);
|
initialQRFile = square_file(sq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (token >= 'A' && token <= 'H')
|
else if (toupper(token) >= 'A' && toupper(token) <= 'H')
|
||||||
{
|
{
|
||||||
File rookFile = File(token - 'A') + FILE_A;
|
File rookFile = File(toupper(token) - 'A');
|
||||||
|
|
||||||
if (rookFile < initialKFile)
|
if (rookFile < initialKFile)
|
||||||
{
|
{
|
||||||
set_castle_queenside(c);
|
set_castle_queenside(c);
|
||||||
|
@ -293,10 +281,6 @@ bool Position::set_castling_rights(char token) {
|
||||||
initialKRFile = rookFile;
|
initialKRFile = rookFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return token == '-';
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -593,8 +577,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Position::move_is_pl_slow() takes a position and a move and tests whether
|
/// Position::move_is_pl_slow() takes a move and tests whether the move
|
||||||
/// the move is pseudo legal. This version is not very fast and should be used
|
/// is pseudo legal. This version is not very fast and should be used
|
||||||
/// only in non time-critical paths.
|
/// only in non time-critical paths.
|
||||||
|
|
||||||
bool Position::move_is_pl_slow(const Move m) const {
|
bool Position::move_is_pl_slow(const Move m) const {
|
||||||
|
@ -613,8 +597,8 @@ bool Position::move_is_pl_slow(const Move m) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Fast version of Position::move_is_pl() that takes a position a move and a
|
/// Fast version of Position::move_is_pl() that takes a move and a bitboard
|
||||||
/// bitboard of pinned pieces as input, and tests whether the move is pseudo legal.
|
/// of pinned pieces as input, and tests whether the move is pseudo legal.
|
||||||
|
|
||||||
bool Position::move_is_pl(const Move m) const {
|
bool Position::move_is_pl(const Move m) const {
|
||||||
|
|
||||||
|
@ -839,6 +823,10 @@ void Position::do_setup_move(Move m) {
|
||||||
|
|
||||||
StateInfo newSt;
|
StateInfo newSt;
|
||||||
|
|
||||||
|
// Update the number of full moves after black's move
|
||||||
|
if (sideToMove == BLACK)
|
||||||
|
fullMoves++;
|
||||||
|
|
||||||
do_move(m, newSt);
|
do_move(m, newSt);
|
||||||
|
|
||||||
// Reset "game ply" in case we made a non-reversible move.
|
// Reset "game ply" in case we made a non-reversible move.
|
||||||
|
@ -846,9 +834,6 @@ void Position::do_setup_move(Move m) {
|
||||||
if (st->rule50 == 0)
|
if (st->rule50 == 0)
|
||||||
st->gamePly = 0;
|
st->gamePly = 0;
|
||||||
|
|
||||||
// Update the number of plies played from the starting position
|
|
||||||
startPosPlyCounter++;
|
|
||||||
|
|
||||||
// Our StateInfo newSt is about going out of scope so copy
|
// Our StateInfo newSt is about going out of scope so copy
|
||||||
// its content before it disappears.
|
// its content before it disappears.
|
||||||
detach();
|
detach();
|
||||||
|
@ -1591,7 +1576,7 @@ void Position::clear() {
|
||||||
st = &startState;
|
st = &startState;
|
||||||
memset(st, 0, sizeof(StateInfo));
|
memset(st, 0, sizeof(StateInfo));
|
||||||
st->epSquare = SQ_NONE;
|
st->epSquare = SQ_NONE;
|
||||||
startPosPlyCounter = 0;
|
fullMoves = 1;
|
||||||
nodes = 0;
|
nodes = 0;
|
||||||
|
|
||||||
memset(byColorBB, 0, sizeof(Bitboard) * 2);
|
memset(byColorBB, 0, sizeof(Bitboard) * 2);
|
||||||
|
@ -2039,19 +2024,14 @@ bool Position::is_ok(int* failedStep) const {
|
||||||
if (can_castle_queenside(c) && piece_on(initial_qr_square(c)) != make_piece(c, ROOK))
|
if (can_castle_queenside(c) && piece_on(initial_qr_square(c)) != make_piece(c, ROOK))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If we cannot castle castleRightsMask[] could be not valid, for instance when
|
if (castleRightsMask[initial_kr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OO))
|
||||||
// king initial file is FILE_A as queen rook.
|
return false;
|
||||||
if (can_castle(WHITE) || can_castle(BLACK))
|
if (castleRightsMask[initial_qr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OOO))
|
||||||
{
|
return false;
|
||||||
if (castleRightsMask[initial_kr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OO))
|
if (castleRightsMask[initial_kr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OO))
|
||||||
return false;
|
return false;
|
||||||
if (castleRightsMask[initial_qr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OOO))
|
if (castleRightsMask[initial_qr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OOO))
|
||||||
return false;
|
return false;
|
||||||
if (castleRightsMask[initial_kr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OO))
|
|
||||||
return false;
|
|
||||||
if (castleRightsMask[initial_qr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OOO))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failedStep) *failedStep = 0;
|
if (failedStep) *failedStep = 0;
|
||||||
|
|
|
@ -226,7 +226,7 @@ public:
|
||||||
template<bool SkipRepetition> bool is_draw() const;
|
template<bool SkipRepetition> bool is_draw() const;
|
||||||
|
|
||||||
// Number of plies from starting position
|
// Number of plies from starting position
|
||||||
int startpos_ply_counter() const;
|
int full_moves() const;
|
||||||
|
|
||||||
// Other properties of the position
|
// Other properties of the position
|
||||||
bool opposite_colored_bishops() const;
|
bool opposite_colored_bishops() const;
|
||||||
|
@ -253,7 +253,7 @@ private:
|
||||||
void put_piece(Piece p, Square s);
|
void put_piece(Piece p, Square s);
|
||||||
void set_castle_kingside(Color c);
|
void set_castle_kingside(Color c);
|
||||||
void set_castle_queenside(Color c);
|
void set_castle_queenside(Color c);
|
||||||
bool set_castling_rights(char token);
|
void set_castling_rights(char token);
|
||||||
bool move_is_pl_slow(const Move m) const;
|
bool move_is_pl_slow(const Move m) const;
|
||||||
|
|
||||||
// Helper functions for doing and undoing moves
|
// Helper functions for doing and undoing moves
|
||||||
|
@ -295,7 +295,7 @@ private:
|
||||||
StateInfo startState;
|
StateInfo startState;
|
||||||
File initialKFile, initialKRFile, initialQRFile;
|
File initialKFile, initialKRFile, initialQRFile;
|
||||||
bool chess960;
|
bool chess960;
|
||||||
int startPosPlyCounter;
|
int fullMoves;
|
||||||
int threadID;
|
int threadID;
|
||||||
int64_t nodes;
|
int64_t nodes;
|
||||||
StateInfo* st;
|
StateInfo* st;
|
||||||
|
@ -489,8 +489,8 @@ inline bool Position::move_is_passed_pawn_push(Move m) const {
|
||||||
&& pawn_is_passed(c, move_to(m));
|
&& pawn_is_passed(c, move_to(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Position::startpos_ply_counter() const {
|
inline int Position::full_moves() const {
|
||||||
return startPosPlyCounter;
|
return fullMoves;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Position::opposite_colored_bishops() const {
|
inline bool Position::opposite_colored_bishops() const {
|
||||||
|
|
|
@ -403,7 +403,7 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
|
||||||
NodesSincePoll = 0;
|
NodesSincePoll = 0;
|
||||||
current_search_time(get_system_time());
|
current_search_time(get_system_time());
|
||||||
Limits = limits;
|
Limits = limits;
|
||||||
TimeMgr.init(Limits, pos.startpos_ply_counter());
|
TimeMgr.init(Limits, pos.full_moves());
|
||||||
|
|
||||||
// Set output steram in normal or chess960 mode
|
// Set output steram in normal or chess960 mode
|
||||||
cout << set960(pos.is_chess960());
|
cout << set960(pos.is_chess960());
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace {
|
||||||
enum TimeType { OptimumTime, MaxTime };
|
enum TimeType { OptimumTime, MaxTime };
|
||||||
|
|
||||||
template<TimeType>
|
template<TimeType>
|
||||||
int remaining(int myTime, int movesToGo, int currentPly);
|
int remaining(int myTime, int movesToGo, int fullMoveNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ void TimeManager::pv_instability(int curChanges, int prevChanges) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TimeManager::init(const SearchLimits& limits, int currentPly)
|
void TimeManager::init(const SearchLimits& limits, int fullMoveNumber)
|
||||||
{
|
{
|
||||||
/* We support four different kind of time controls:
|
/* We support four different kind of time controls:
|
||||||
|
|
||||||
|
@ -124,8 +124,8 @@ void TimeManager::init(const SearchLimits& limits, int currentPly)
|
||||||
|
|
||||||
hypMyTime = Max(hypMyTime, 0);
|
hypMyTime = Max(hypMyTime, 0);
|
||||||
|
|
||||||
t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, currentPly);
|
t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, fullMoveNumber);
|
||||||
t2 = minThinkingTime + remaining<MaxTime>(hypMyTime, hypMTG, currentPly);
|
t2 = minThinkingTime + remaining<MaxTime>(hypMyTime, hypMTG, fullMoveNumber);
|
||||||
|
|
||||||
optimumSearchTime = Min(optimumSearchTime, t1);
|
optimumSearchTime = Min(optimumSearchTime, t1);
|
||||||
maximumSearchTime = Min(maximumSearchTime, t2);
|
maximumSearchTime = Min(maximumSearchTime, t2);
|
||||||
|
@ -142,11 +142,12 @@ void TimeManager::init(const SearchLimits& limits, int currentPly)
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<TimeType T>
|
template<TimeType T>
|
||||||
int remaining(int myTime, int movesToGo, int currentPly)
|
int remaining(int myTime, int movesToGo, int fullMoveNumber)
|
||||||
{
|
{
|
||||||
const float TMaxRatio = (T == OptimumTime ? 1 : MaxRatio);
|
const float TMaxRatio = (T == OptimumTime ? 1 : MaxRatio);
|
||||||
const float TStealRatio = (T == OptimumTime ? 0 : StealRatio);
|
const float TStealRatio = (T == OptimumTime ? 0 : StealRatio);
|
||||||
|
|
||||||
|
int currentPly = 2 * fullMoveNumber;
|
||||||
int thisMoveImportance = move_importance(currentPly);
|
int thisMoveImportance = move_importance(currentPly);
|
||||||
int otherMovesImportance = 0;
|
int otherMovesImportance = 0;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct SearchLimits;
|
||||||
class TimeManager {
|
class TimeManager {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void init(const SearchLimits& limits, int currentPly);
|
void init(const SearchLimits& limits, int fullMoveNumber);
|
||||||
void pv_instability(int curChanges, int prevChanges);
|
void pv_instability(int curChanges, int prevChanges);
|
||||||
int available_time() const { return optimumSearchTime + unstablePVExtraTime; }
|
int available_time() const { return optimumSearchTime + unstablePVExtraTime; }
|
||||||
int maximum_time() const { return maximumSearchTime; }
|
int maximum_time() const { return maximumSearchTime; }
|
||||||
|
|
Loading…
Add table
Reference in a new issue