#include <cassert>
#include <cstring>
#include <fstream>
-#include <map>
#include <iostream>
#include <sstream>
// Bonus for having the side to move (modified by Joona Kiiski)
const Score TempoValue = make_score(48, 22);
- struct PieceLetters : public std::map<char, Piece> {
-
- PieceLetters() {
-
- operator[]('K') = WK; operator[]('k') = BK;
- operator[]('Q') = WQ; operator[]('q') = BQ;
- operator[]('R') = WR; operator[]('r') = BR;
- operator[]('B') = WB; operator[]('b') = BB;
- operator[]('N') = WN; operator[]('n') = BN;
- operator[]('P') = WP; operator[]('p') = BP;
- operator[](' ') = PIECE_NONE;
- operator[]('.') = PIECE_NONE_DARK_SQ;
- }
-
- char from_piece(Piece p) const {
-
- std::map<char, Piece>::const_iterator it;
- for (it = begin(); it != end(); ++it)
- if (it->second == p)
- return it->first;
-
- assert(false);
- return 0;
- }
- };
-
- PieceLetters pieceLetters;
+ // To convert a Piece to and from a FEN char
+ const string PieceToChar(".PNBRQK pnbrqk ");
}
char token;
int hmc, fmn;
- std::istringstream ss(fen);
+ size_t p;
Square sq = SQ_A8;
+ std::istringstream ss(fen);
clear();
+ ss >> std::noskipws;
// 1. Piece placement field
- while (ss.get(token) && token != ' ')
+ while ((ss >> token) && !isspace(token))
{
- if (pieceLetters.find(token) != pieceLetters.end())
+ if ((p = PieceToChar.find(token)) != string::npos)
{
- put_piece(pieceLetters[token], sq);
+ put_piece(Piece(p), sq);
sq++;
}
else if (isdigit(token))
}
// 2. Active color
- if (!ss.get(token) || (token != 'w' && token != 'b'))
+ if (!(ss >> token) || (token != 'w' && token != 'b'))
goto incorrect_fen;
sideToMove = (token == 'w' ? WHITE : BLACK);
- if (!ss.get(token) || token != ' ')
+ if (!(ss >> token) || !isspace(token))
goto incorrect_fen;
// 3. Castling availability
- while (ss.get(token) && token != ' ')
+ while ((ss >> token) && !isspace(token))
if (!set_castling_rights(token))
goto incorrect_fen;
// 4. En passant square
char col, row;
- if ( (ss.get(col) && (col >= 'a' && col <= 'h'))
- && (ss.get(row) && (row == '3' || row == '6')))
+ if ( ((ss >> col) && (col >= 'a' && col <= 'h'))
+ && ((ss >> row) && (row == '3' || row == '6')))
{
- st->epSquare = make_square(file_from_char(col), rank_from_char(row));
+ st->epSquare = make_square(File(col - 'a') + FILE_A, Rank(row - '1') + RANK_1);
// Ignore if no capture is possible
Color them = opposite_color(sideToMove);
}
// 5. Halfmove clock
- if (ss >> hmc)
+ if (ss >> std::skipws >> hmc)
st->rule50 = hmc;
// 6. Fullmove number
for (Square sq = sqH; sq >= sqA; sq--)
if (piece_on(sq) == rook)
{
- do_allow_oo(c);
+ set_castle_kingside(c);
initialKRFile = square_file(sq);
break;
}
for (Square sq = sqA; sq <= sqH; sq++)
if (piece_on(sq) == rook)
{
- do_allow_ooo(c);
+ set_castle_queenside(c);
initialQRFile = square_file(sq);
break;
}
File rookFile = File(token - 'A') + FILE_A;
if (rookFile < initialKFile)
{
- do_allow_ooo(c);
+ set_castle_queenside(c);
initialQRFile = rookFile;
}
else
{
- do_allow_oo(c);
+ set_castle_kingside(c);
initialKRFile = rookFile;
}
}
string fen;
Square sq;
- char emptyCnt = '0';
+ char emptyCnt;
for (Rank rank = RANK_8; rank >= RANK_1; rank--, fen += '/')
{
+ emptyCnt = '0';
+
for (File file = FILE_A; file <= FILE_H; file++)
{
sq = make_square(file, rank);
fen += emptyCnt;
emptyCnt = '0';
}
- fen += pieceLetters.from_piece(piece_on(sq));
+ fen += PieceToChar[piece_on(sq)];
} else
emptyCnt++;
}
if (emptyCnt != '0')
- {
fen += emptyCnt;
- emptyCnt = '0';
- }
}
fen += (sideToMove == WHITE ? " w " : " b ");
piece = PIECE_NONE_DARK_SQ;
char c = (color_of_piece_on(sq) == BLACK ? '=' : ' ');
- cout << c << pieceLetters.from_piece(piece) << c << '|';
+ cout << c << PieceToChar[piece] << c << '|';
}
}
cout << dottedLine << "Fen is: " << to_fen() << "\nKey is: " << st->key << endl;
return move_is_pl_slow(m);
// Is not a promotion, so promotion piece must be empty
- if (move_promotion_piece(m) - 2 != PIECE_TYPE_NONE)
+ if (promotion_piece_type(m) - 2 != PIECE_TYPE_NONE)
return false;
// If the from square is not occupied by a piece belonging to the side to
{
clear_bit(&b, from);
- switch (move_promotion_piece(m))
+ switch (promotion_piece_type(m))
{
case KNIGHT:
return bit_is_set(attacks_from<KNIGHT>(to), ci.ksq);
st->epSquare = SQ_NONE;
}
- // Update castle rights, try to shortcut a common case
- int cm = castleRightsMask[from] & castleRightsMask[to];
- if (cm != ALL_CASTLES && ((cm & st->castleRights) != st->castleRights))
+ // Update castle rights if needed
+ if ( st->castleRights != CASTLES_NONE
+ && (castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
{
key ^= zobCastle[st->castleRights];
- st->castleRights &= castleRightsMask[from];
- st->castleRights &= castleRightsMask[to];
+ st->castleRights &= castleRightsMask[from] & castleRightsMask[to];
key ^= zobCastle[st->castleRights];
}
if (pm) // promotion ?
{
- PieceType promotion = move_promotion_piece(m);
+ PieceType promotion = promotion_piece_type(m);
assert(promotion >= KNIGHT && promotion <= QUEEN);
if (pm) // promotion ?
{
- PieceType promotion = move_promotion_piece(m);
+ PieceType promotion = promotion_piece_type(m);
pt = PAWN;
assert(promotion >= KNIGHT && promotion <= QUEEN);
}
-/// Position::init_zobrist() is a static member function which initializes at
-/// startup the various arrays used to compute hash keys.
+/// Position::init() is a static member function which initializes at
+/// startup the various arrays used to compute hash keys and the piece
+/// square tables. The latter is a two-step operation: First, the white
+/// halves of the tables are copied from the MgPST[][] and EgPST[][] arrays.
+/// Second, the black halves of the tables are initialized by mirroring
+/// and changing the sign of the corresponding white scores.
-void Position::init_zobrist() {
+void Position::init() {
- int i,j, k;
RKISS rk;
- for (i = 0; i < 2; i++) for (j = 0; j < 8; j++) for (k = 0; k < 64; k++)
- zobrist[i][j][k] = rk.rand<Key>();
+ for (Color c = WHITE; c <= BLACK; c++)
+ for (PieceType pt = PAWN; pt <= KING; pt++)
+ for (Square s = SQ_A1; s <= SQ_H8; s++)
+ zobrist[c][pt][s] = rk.rand<Key>();
- for (i = 0; i < 64; i++)
- zobEp[i] = rk.rand<Key>();
+ for (Square s = SQ_A1; s <= SQ_H8; s++)
+ zobEp[s] = rk.rand<Key>();
- for (i = 0; i < 16; i++)
+ for (int i = 0; i < 16; i++)
zobCastle[i] = rk.rand<Key>();
zobSideToMove = rk.rand<Key>();
zobExclusion = rk.rand<Key>();
-}
-
-
-/// Position::init_piece_square_tables() initializes the piece square tables.
-/// This is a two-step operation: First, the white halves of the tables are
-/// copied from the MgPST[][] and EgPST[][] arrays. Second, the black halves
-/// of the tables are initialized by mirroring and changing the sign of the
-/// corresponding white scores.
-
-void Position::init_piece_square_tables() {
for (Square s = SQ_A1; s <= SQ_H8; s++)
for (Piece p = WP; p <= WK; p++)
sideToMove = opposite_color(pos.side_to_move());
// Castling rights
- if (pos.can_castle_kingside(WHITE)) do_allow_oo(BLACK);
- if (pos.can_castle_queenside(WHITE)) do_allow_ooo(BLACK);
- if (pos.can_castle_kingside(BLACK)) do_allow_oo(WHITE);
- if (pos.can_castle_queenside(BLACK)) do_allow_ooo(WHITE);
+ if (pos.can_castle_kingside(WHITE)) set_castle_kingside(BLACK);
+ if (pos.can_castle_queenside(WHITE)) set_castle_queenside(BLACK);
+ if (pos.can_castle_kingside(BLACK)) set_castle_kingside(WHITE);
+ if (pos.can_castle_queenside(BLACK)) set_castle_queenside(WHITE);
initialKFile = pos.initialKFile;
initialKRFile = pos.initialKRFile;
if (failedStep) *failedStep = 1;
// Side to move OK?
- if (!color_is_ok(side_to_move()))
+ if (side_to_move() != WHITE && side_to_move() != BLACK)
return false;
// Are the king squares in the position correct?
// Castle files OK?
if (failedStep) (*failedStep)++;
- if (!file_is_ok(initialKRFile))
+ if (!square_is_ok(make_square(initialKRFile, RANK_1)))
return false;
- if (!file_is_ok(initialQRFile))
+ if (!square_is_ok(make_square(initialQRFile, RANK_1)))
return false;
// Do both sides have exactly one king?