mirror of
https://github.com/RGBCube/serenity
synced 2025-05-29 11:45:11 +00:00
Everywhere: Colour => Color
The system language is US English. :^)
This commit is contained in:
parent
30ef10a5b9
commit
9d6198b683
7 changed files with 170 additions and 170 deletions
|
@ -59,13 +59,13 @@ void ChessWidget::paint_event(GUI::PaintEvent& event)
|
||||||
|
|
||||||
size_t tile_width = width() / 8;
|
size_t tile_width = width() / 8;
|
||||||
size_t tile_height = height() / 8;
|
size_t tile_height = height() / 8;
|
||||||
unsigned coord_rank_file = (side() == Chess::Colour::White) ? 0 : 7;
|
unsigned coord_rank_file = (side() == Chess::Color::White) ? 0 : 7;
|
||||||
|
|
||||||
Chess::Board& active_board = (m_playback ? board_playback() : board());
|
Chess::Board& active_board = (m_playback ? board_playback() : board());
|
||||||
|
|
||||||
Chess::Square::for_each([&](Chess::Square sq) {
|
Chess::Square::for_each([&](Chess::Square sq) {
|
||||||
Gfx::IntRect tile_rect;
|
Gfx::IntRect tile_rect;
|
||||||
if (side() == Chess::Colour::White) {
|
if (side() == Chess::Color::White) {
|
||||||
tile_rect = { sq.file * tile_width, (7 - sq.rank) * tile_height, tile_width, tile_height };
|
tile_rect = { sq.file * tile_width, (7 - sq.rank) * tile_height, tile_width, tile_height };
|
||||||
} else {
|
} else {
|
||||||
tile_rect = { (7 - sq.file) * tile_width, sq.rank * tile_height, tile_width, tile_height };
|
tile_rect = { (7 - sq.file) * tile_width, sq.rank * tile_height, tile_width, tile_height };
|
||||||
|
@ -141,7 +141,7 @@ void ChessWidget::paint_event(GUI::PaintEvent& event)
|
||||||
Gfx::FloatPoint arrow_start;
|
Gfx::FloatPoint arrow_start;
|
||||||
Gfx::FloatPoint arrow_end;
|
Gfx::FloatPoint arrow_end;
|
||||||
|
|
||||||
if (side() == Chess::Colour::White) {
|
if (side() == Chess::Color::White) {
|
||||||
arrow_start = { m.from.file * tile_width + tile_width / 2.0f, (7 - m.from.rank) * tile_height + tile_height / 2.0f };
|
arrow_start = { m.from.file * tile_width + tile_width / 2.0f, (7 - m.from.rank) * tile_height + tile_height / 2.0f };
|
||||||
arrow_end = { m.to.file * tile_width + tile_width / 2.0f, (7 - m.to.rank) * tile_height + tile_height / 2.0f };
|
arrow_end = { m.to.file * tile_width + tile_width / 2.0f, (7 - m.to.rank) * tile_height + tile_height / 2.0f };
|
||||||
} else {
|
} else {
|
||||||
|
@ -175,7 +175,7 @@ void ChessWidget::mousedown_event(GUI::MouseEvent& event)
|
||||||
|
|
||||||
auto square = mouse_to_square(event);
|
auto square = mouse_to_square(event);
|
||||||
auto piece = board().get_piece(square);
|
auto piece = board().get_piece(square);
|
||||||
if (drag_enabled() && piece.colour == board().turn() && !m_playback) {
|
if (drag_enabled() && piece.color == board().turn() && !m_playback) {
|
||||||
m_dragging_piece = true;
|
m_dragging_piece = true;
|
||||||
m_drag_point = event.position();
|
m_drag_point = event.position();
|
||||||
m_moving_square = square;
|
m_moving_square = square;
|
||||||
|
@ -227,7 +227,7 @@ void ChessWidget::mouseup_event(GUI::MouseEvent& event)
|
||||||
String msg;
|
String msg;
|
||||||
switch (board().game_result()) {
|
switch (board().game_result()) {
|
||||||
case Chess::Board::Result::CheckMate:
|
case Chess::Board::Result::CheckMate:
|
||||||
if (board().turn() == Chess::Colour::White) {
|
if (board().turn() == Chess::Color::White) {
|
||||||
msg = "Black wins by Checkmate.";
|
msg = "Black wins by Checkmate.";
|
||||||
} else {
|
} else {
|
||||||
msg = "White wins by Checkmate.";
|
msg = "White wins by Checkmate.";
|
||||||
|
@ -333,18 +333,18 @@ static RefPtr<Gfx::Bitmap> get_piece(const StringView& set, const StringView& im
|
||||||
void ChessWidget::set_piece_set(const StringView& set)
|
void ChessWidget::set_piece_set(const StringView& set)
|
||||||
{
|
{
|
||||||
m_piece_set = set;
|
m_piece_set = set;
|
||||||
m_pieces.set({ Chess::Colour::White, Chess::Type::Pawn }, get_piece(set, "white-pawn.png"));
|
m_pieces.set({ Chess::Color::White, Chess::Type::Pawn }, get_piece(set, "white-pawn.png"));
|
||||||
m_pieces.set({ Chess::Colour::Black, Chess::Type::Pawn }, get_piece(set, "black-pawn.png"));
|
m_pieces.set({ Chess::Color::Black, Chess::Type::Pawn }, get_piece(set, "black-pawn.png"));
|
||||||
m_pieces.set({ Chess::Colour::White, Chess::Type::Knight }, get_piece(set, "white-knight.png"));
|
m_pieces.set({ Chess::Color::White, Chess::Type::Knight }, get_piece(set, "white-knight.png"));
|
||||||
m_pieces.set({ Chess::Colour::Black, Chess::Type::Knight }, get_piece(set, "black-knight.png"));
|
m_pieces.set({ Chess::Color::Black, Chess::Type::Knight }, get_piece(set, "black-knight.png"));
|
||||||
m_pieces.set({ Chess::Colour::White, Chess::Type::Bishop }, get_piece(set, "white-bishop.png"));
|
m_pieces.set({ Chess::Color::White, Chess::Type::Bishop }, get_piece(set, "white-bishop.png"));
|
||||||
m_pieces.set({ Chess::Colour::Black, Chess::Type::Bishop }, get_piece(set, "black-bishop.png"));
|
m_pieces.set({ Chess::Color::Black, Chess::Type::Bishop }, get_piece(set, "black-bishop.png"));
|
||||||
m_pieces.set({ Chess::Colour::White, Chess::Type::Rook }, get_piece(set, "white-rook.png"));
|
m_pieces.set({ Chess::Color::White, Chess::Type::Rook }, get_piece(set, "white-rook.png"));
|
||||||
m_pieces.set({ Chess::Colour::Black, Chess::Type::Rook }, get_piece(set, "black-rook.png"));
|
m_pieces.set({ Chess::Color::Black, Chess::Type::Rook }, get_piece(set, "black-rook.png"));
|
||||||
m_pieces.set({ Chess::Colour::White, Chess::Type::Queen }, get_piece(set, "white-queen.png"));
|
m_pieces.set({ Chess::Color::White, Chess::Type::Queen }, get_piece(set, "white-queen.png"));
|
||||||
m_pieces.set({ Chess::Colour::Black, Chess::Type::Queen }, get_piece(set, "black-queen.png"));
|
m_pieces.set({ Chess::Color::Black, Chess::Type::Queen }, get_piece(set, "black-queen.png"));
|
||||||
m_pieces.set({ Chess::Colour::White, Chess::Type::King }, get_piece(set, "white-king.png"));
|
m_pieces.set({ Chess::Color::White, Chess::Type::King }, get_piece(set, "white-king.png"));
|
||||||
m_pieces.set({ Chess::Colour::Black, Chess::Type::King }, get_piece(set, "black-king.png"));
|
m_pieces.set({ Chess::Color::Black, Chess::Type::King }, get_piece(set, "black-king.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Chess::Square ChessWidget::mouse_to_square(GUI::MouseEvent& event) const
|
Chess::Square ChessWidget::mouse_to_square(GUI::MouseEvent& event) const
|
||||||
|
@ -352,7 +352,7 @@ Chess::Square ChessWidget::mouse_to_square(GUI::MouseEvent& event) const
|
||||||
size_t tile_width = width() / 8;
|
size_t tile_width = width() / 8;
|
||||||
size_t tile_height = height() / 8;
|
size_t tile_height = height() / 8;
|
||||||
|
|
||||||
if (side() == Chess::Colour::White) {
|
if (side() == Chess::Color::White) {
|
||||||
return { 7 - (event.y() / tile_height), event.x() / tile_width };
|
return { 7 - (event.y() / tile_height), event.x() / tile_width };
|
||||||
} else {
|
} else {
|
||||||
return { event.y() / tile_height, 7 - (event.x() / tile_width) };
|
return { event.y() / tile_height, 7 - (event.x() / tile_width) };
|
||||||
|
@ -371,7 +371,7 @@ void ChessWidget::reset()
|
||||||
m_playback_move_number = 0;
|
m_playback_move_number = 0;
|
||||||
m_board_playback = Chess::Board();
|
m_board_playback = Chess::Board();
|
||||||
m_board = Chess::Board();
|
m_board = Chess::Board();
|
||||||
m_side = (arc4random() % 2) ? Chess::Colour::White : Chess::Colour::Black;
|
m_side = (arc4random() % 2) ? Chess::Color::White : Chess::Color::Black;
|
||||||
m_drag_enabled = true;
|
m_drag_enabled = true;
|
||||||
input_engine_move();
|
input_engine_move();
|
||||||
update();
|
update();
|
||||||
|
@ -380,7 +380,7 @@ void ChessWidget::reset()
|
||||||
void ChessWidget::set_board_theme(const StringView& name)
|
void ChessWidget::set_board_theme(const StringView& name)
|
||||||
{
|
{
|
||||||
// FIXME: Add some kind of themes.json
|
// FIXME: Add some kind of themes.json
|
||||||
// The following Colours have been taken from lichess.org, but i'm pretty sure they took them from chess.com.
|
// The following Colors have been taken from lichess.org, but i'm pretty sure they took them from chess.com.
|
||||||
if (name == "Beige") {
|
if (name == "Beige") {
|
||||||
m_board_theme = { "Beige", Color::from_rgb(0xb58863), Color::from_rgb(0xf0d9b5) };
|
m_board_theme = { "Beige", Color::from_rgb(0xb58863), Color::from_rgb(0xf0d9b5) };
|
||||||
} else if (name == "Green") {
|
} else if (name == "Green") {
|
||||||
|
@ -497,7 +497,7 @@ bool ChessWidget::import_pgn(const StringView& import_path)
|
||||||
bool skip = false;
|
bool skip = false;
|
||||||
bool recursive_annotation = false;
|
bool recursive_annotation = false;
|
||||||
bool future_expansion = false;
|
bool future_expansion = false;
|
||||||
Chess::Colour turn = Chess::Colour::White;
|
Chess::Color turn = Chess::Color::White;
|
||||||
String movetext;
|
String movetext;
|
||||||
|
|
||||||
for (size_t j = i; j < lines.size(); j++)
|
for (size_t j = i; j < lines.size(); j++)
|
||||||
|
@ -549,11 +549,11 @@ bool ChessWidget::import_pgn(const StringView& import_path)
|
||||||
break;
|
break;
|
||||||
// FIXME: When we become able to set more of the game state, fix these end results
|
// FIXME: When we become able to set more of the game state, fix these end results
|
||||||
if (token.contains("1-0")) {
|
if (token.contains("1-0")) {
|
||||||
m_board.set_resigned(Chess::Colour::Black);
|
m_board.set_resigned(Chess::Color::Black);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (token.contains("0-1")) {
|
if (token.contains("0-1")) {
|
||||||
m_board.set_resigned(Chess::Colour::White);
|
m_board.set_resigned(Chess::Color::White);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (token.contains("1/2-1/2")) {
|
if (token.contains("1/2-1/2")) {
|
||||||
|
@ -561,7 +561,7 @@ bool ChessWidget::import_pgn(const StringView& import_path)
|
||||||
}
|
}
|
||||||
if (!token.ends_with(".")) {
|
if (!token.ends_with(".")) {
|
||||||
m_board.apply_move(Chess::Move::from_algebraic(token, turn, m_board));
|
m_board.apply_move(Chess::Move::from_algebraic(token, turn, m_board));
|
||||||
turn = Chess::opposing_colour(turn);
|
turn = Chess::opposing_color(turn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,8 +593,8 @@ bool ChessWidget::export_pgn(const StringView& export_path) const
|
||||||
String username(getlogin());
|
String username(getlogin());
|
||||||
const String player1 = (!username.is_empty() ? username : "?");
|
const String player1 = (!username.is_empty() ? username : "?");
|
||||||
const String player2 = (!m_engine.is_null() ? "SerenityOS ChessEngine" : "?");
|
const String player2 = (!m_engine.is_null() ? "SerenityOS ChessEngine" : "?");
|
||||||
file.write(String::formatted("[White \"{}\"]\n", m_side == Chess::Colour::White ? player1 : player2));
|
file.write(String::formatted("[White \"{}\"]\n", m_side == Chess::Color::White ? player1 : player2));
|
||||||
file.write(String::formatted("[Black \"{}\"]\n", m_side == Chess::Colour::Black ? player1 : player2));
|
file.write(String::formatted("[Black \"{}\"]\n", m_side == Chess::Color::Black ? player1 : player2));
|
||||||
|
|
||||||
file.write(String::formatted("[Result \"{}\"]\n", Chess::Board::result_to_points(m_board.game_result(), m_board.turn())));
|
file.write(String::formatted("[Result \"{}\"]\n", Chess::Board::result_to_points(m_board.game_result(), m_board.turn())));
|
||||||
file.write("[WhiteElo \"?\"]\n");
|
file.write("[WhiteElo \"?\"]\n");
|
||||||
|
@ -632,7 +632,7 @@ void ChessWidget::flip_board()
|
||||||
GUI::MessageBox::show(window(), "You can only flip the board on your turn.", "Flip Board", GUI::MessageBox::Type::Information);
|
GUI::MessageBox::show(window(), "You can only flip the board on your turn.", "Flip Board", GUI::MessageBox::Type::Information);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_side = Chess::opposing_colour(m_side);
|
m_side = Chess::opposing_color(m_side);
|
||||||
input_engine_move();
|
input_engine_move();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,8 @@ public:
|
||||||
Chess::Board& board_playback() { return m_board_playback; };
|
Chess::Board& board_playback() { return m_board_playback; };
|
||||||
const Chess::Board& board_playback() const { return m_board_playback; };
|
const Chess::Board& board_playback() const { return m_board_playback; };
|
||||||
|
|
||||||
Chess::Colour side() const { return m_side; };
|
Chess::Color side() const { return m_side; };
|
||||||
void set_side(Chess::Colour side) { m_side = side; };
|
void set_side(Chess::Color side) { m_side = side; };
|
||||||
|
|
||||||
void set_piece_set(const StringView& set);
|
void set_piece_set(const StringView& set);
|
||||||
const String& piece_set() const { return m_piece_set; };
|
const String& piece_set() const { return m_piece_set; };
|
||||||
|
@ -135,7 +135,7 @@ private:
|
||||||
Color m_marking_primary_color { Color::from_rgba(0x66ff0000) };
|
Color m_marking_primary_color { Color::from_rgba(0x66ff0000) };
|
||||||
Color m_marking_alternate_color { Color::from_rgba(0x66ffaa00) };
|
Color m_marking_alternate_color { Color::from_rgba(0x66ffaa00) };
|
||||||
Color m_marking_secondary_color { Color::from_rgba(0x6655dd55) };
|
Color m_marking_secondary_color { Color::from_rgba(0x6655dd55) };
|
||||||
Chess::Colour m_side { Chess::Colour::White };
|
Chess::Color m_side { Chess::Color::White };
|
||||||
HashMap<Chess::Piece, RefPtr<Gfx::Bitmap>> m_pieces;
|
HashMap<Chess::Piece, RefPtr<Gfx::Bitmap>> m_pieces;
|
||||||
String m_piece_set;
|
String m_piece_set;
|
||||||
Chess::Square m_moving_square { 50, 50 };
|
Chess::Square m_moving_square { 50, 50 };
|
||||||
|
|
|
@ -72,9 +72,9 @@ Chess::Type piece_for_char_promotion(const StringView& str)
|
||||||
return Type::None;
|
return Type::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Colour opposing_colour(Colour colour)
|
Color opposing_color(Color color)
|
||||||
{
|
{
|
||||||
return (colour == Colour::White) ? Colour::Black : Colour::White;
|
return (color == Color::White) ? Color::Black : Color::White;
|
||||||
}
|
}
|
||||||
|
|
||||||
Square::Square(const StringView& name)
|
Square::Square(const StringView& name)
|
||||||
|
@ -122,14 +122,14 @@ String Move::to_long_algebraic() const
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Move Move::from_algebraic(const StringView& algebraic, const Colour turn, const Board& board)
|
Move Move::from_algebraic(const StringView& algebraic, const Color turn, const Board& board)
|
||||||
{
|
{
|
||||||
String move_string = algebraic;
|
String move_string = algebraic;
|
||||||
Move move({ 50, 50 }, { 50, 50 });
|
Move move({ 50, 50 }, { 50, 50 });
|
||||||
|
|
||||||
if (move_string.contains("-")) {
|
if (move_string.contains("-")) {
|
||||||
move.from = Square(turn == Colour::White ? 0 : 7, 4);
|
move.from = Square(turn == Color::White ? 0 : 7, 4);
|
||||||
move.to = Square(turn == Colour::White ? 0 : 7, move_string == "O-O" ? 6 : 2);
|
move.to = Square(turn == Color::White ? 0 : 7, move_string == "O-O" ? 6 : 2);
|
||||||
move.promote_to = Type::None;
|
move.promote_to = Type::None;
|
||||||
move.piece = { turn, Type::King };
|
move.piece = { turn, Type::King };
|
||||||
|
|
||||||
|
@ -251,33 +251,33 @@ Board::Board()
|
||||||
|
|
||||||
// Fill white pawns.
|
// Fill white pawns.
|
||||||
for (unsigned file = 0; file < 8; ++file) {
|
for (unsigned file = 0; file < 8; ++file) {
|
||||||
set_piece({ 1, file }, { Colour::White, Type::Pawn });
|
set_piece({ 1, file }, { Color::White, Type::Pawn });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill black pawns.
|
// Fill black pawns.
|
||||||
for (unsigned file = 0; file < 8; ++file) {
|
for (unsigned file = 0; file < 8; ++file) {
|
||||||
set_piece({ 6, file }, { Colour::Black, Type::Pawn });
|
set_piece({ 6, file }, { Color::Black, Type::Pawn });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill while pieces.
|
// Fill while pieces.
|
||||||
set_piece(Square("a1"), { Colour::White, Type::Rook });
|
set_piece(Square("a1"), { Color::White, Type::Rook });
|
||||||
set_piece(Square("b1"), { Colour::White, Type::Knight });
|
set_piece(Square("b1"), { Color::White, Type::Knight });
|
||||||
set_piece(Square("c1"), { Colour::White, Type::Bishop });
|
set_piece(Square("c1"), { Color::White, Type::Bishop });
|
||||||
set_piece(Square("d1"), { Colour::White, Type::Queen });
|
set_piece(Square("d1"), { Color::White, Type::Queen });
|
||||||
set_piece(Square("e1"), { Colour::White, Type::King });
|
set_piece(Square("e1"), { Color::White, Type::King });
|
||||||
set_piece(Square("f1"), { Colour::White, Type::Bishop });
|
set_piece(Square("f1"), { Color::White, Type::Bishop });
|
||||||
set_piece(Square("g1"), { Colour::White, Type::Knight });
|
set_piece(Square("g1"), { Color::White, Type::Knight });
|
||||||
set_piece(Square("h1"), { Colour::White, Type::Rook });
|
set_piece(Square("h1"), { Color::White, Type::Rook });
|
||||||
|
|
||||||
// Fill black pieces.
|
// Fill black pieces.
|
||||||
set_piece(Square("a8"), { Colour::Black, Type::Rook });
|
set_piece(Square("a8"), { Color::Black, Type::Rook });
|
||||||
set_piece(Square("b8"), { Colour::Black, Type::Knight });
|
set_piece(Square("b8"), { Color::Black, Type::Knight });
|
||||||
set_piece(Square("c8"), { Colour::Black, Type::Bishop });
|
set_piece(Square("c8"), { Color::Black, Type::Bishop });
|
||||||
set_piece(Square("d8"), { Colour::Black, Type::Queen });
|
set_piece(Square("d8"), { Color::Black, Type::Queen });
|
||||||
set_piece(Square("e8"), { Colour::Black, Type::King });
|
set_piece(Square("e8"), { Color::Black, Type::King });
|
||||||
set_piece(Square("f8"), { Colour::Black, Type::Bishop });
|
set_piece(Square("f8"), { Color::Black, Type::Bishop });
|
||||||
set_piece(Square("g8"), { Colour::Black, Type::Knight });
|
set_piece(Square("g8"), { Color::Black, Type::Knight });
|
||||||
set_piece(Square("h8"), { Colour::Black, Type::Rook });
|
set_piece(Square("h8"), { Color::Black, Type::Rook });
|
||||||
}
|
}
|
||||||
|
|
||||||
String Board::to_fen() const
|
String Board::to_fen() const
|
||||||
|
@ -301,7 +301,7 @@ String Board::to_fen() const
|
||||||
if (piece == "")
|
if (piece == "")
|
||||||
piece = "P";
|
piece = "P";
|
||||||
|
|
||||||
builder.append(p.colour == Colour::Black ? piece.to_lowercase() : piece);
|
builder.append(p.color == Color::Black ? piece.to_lowercase() : piece);
|
||||||
}
|
}
|
||||||
if (empty > 0) {
|
if (empty > 0) {
|
||||||
builder.append(String::number(empty));
|
builder.append(String::number(empty));
|
||||||
|
@ -312,8 +312,8 @@ String Board::to_fen() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Active color
|
// 2. Active color
|
||||||
ASSERT(m_turn != Colour::None);
|
ASSERT(m_turn != Color::None);
|
||||||
builder.append(m_turn == Colour::White ? " w " : " b ");
|
builder.append(m_turn == Color::White ? " w " : " b ");
|
||||||
|
|
||||||
// 3. Castling availability
|
// 3. Castling availability
|
||||||
builder.append(m_white_can_castle_kingside ? "K" : "");
|
builder.append(m_white_can_castle_kingside ? "K" : "");
|
||||||
|
@ -361,7 +361,7 @@ Piece Board::set_piece(const Square& square, const Piece& piece)
|
||||||
return m_board[square.rank][square.file] = piece;
|
return m_board[square.rank][square.file] = piece;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_legal_promotion(const Move& move, Colour colour) const
|
bool Board::is_legal_promotion(const Move& move, Color color) const
|
||||||
{
|
{
|
||||||
auto piece = get_piece(move.from);
|
auto piece = get_piece(move.from);
|
||||||
|
|
||||||
|
@ -375,7 +375,7 @@ bool Board::is_legal_promotion(const Move& move, Colour colour) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned promotion_rank = (colour == Colour::White) ? 7 : 0;
|
unsigned promotion_rank = (color == Color::White) ? 7 : 0;
|
||||||
|
|
||||||
if (move.to.rank != promotion_rank && move.promote_to != Type::None) {
|
if (move.to.rank != promotion_rank && move.promote_to != Type::None) {
|
||||||
// attempted promotion from invalid rank
|
// attempted promotion from invalid rank
|
||||||
|
@ -390,31 +390,31 @@ bool Board::is_legal_promotion(const Move& move, Colour colour) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_legal(const Move& move, Colour colour) const
|
bool Board::is_legal(const Move& move, Color color) const
|
||||||
{
|
{
|
||||||
if (colour == Colour::None)
|
if (color == Color::None)
|
||||||
colour = turn();
|
color = turn();
|
||||||
|
|
||||||
if (!is_legal_no_check(move, colour))
|
if (!is_legal_no_check(move, color))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!is_legal_promotion(move, colour))
|
if (!is_legal_promotion(move, color))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Board clone = *this;
|
Board clone = *this;
|
||||||
clone.apply_illegal_move(move, colour);
|
clone.apply_illegal_move(move, color);
|
||||||
if (clone.in_check(colour))
|
if (clone.in_check(color))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Don't allow castling through check or out of check.
|
// Don't allow castling through check or out of check.
|
||||||
Vector<Square> check_squares;
|
Vector<Square> check_squares;
|
||||||
if (colour == Colour::White && move.from == Square("e1") && get_piece(Square("e1")) == Piece(Colour::White, Type::King)) {
|
if (color == Color::White && move.from == Square("e1") && get_piece(Square("e1")) == Piece(Color::White, Type::King)) {
|
||||||
if (move.to == Square("a1") || move.to == Square("c1")) {
|
if (move.to == Square("a1") || move.to == Square("c1")) {
|
||||||
check_squares = { Square("e1"), Square("d1"), Square("c1") };
|
check_squares = { Square("e1"), Square("d1"), Square("c1") };
|
||||||
} else if (move.to == Square("h1") || move.to == Square("g1")) {
|
} else if (move.to == Square("h1") || move.to == Square("g1")) {
|
||||||
check_squares = { Square("e1"), Square("f1"), Square("g1") };
|
check_squares = { Square("e1"), Square("f1"), Square("g1") };
|
||||||
}
|
}
|
||||||
} else if (colour == Colour::Black && move.from == Square("e8") && get_piece(Square("e8")) == Piece(Colour::Black, Type::King)) {
|
} else if (color == Color::Black && move.from == Square("e8") && get_piece(Square("e8")) == Piece(Color::Black, Type::King)) {
|
||||||
if (move.to == Square("a8") || move.to == Square("c8")) {
|
if (move.to == Square("a8") || move.to == Square("c8")) {
|
||||||
check_squares = { Square("e8"), Square("d8"), Square("c8") };
|
check_squares = { Square("e8"), Square("d8"), Square("c8") };
|
||||||
} else if (move.to == Square("h8") || move.to == Square("g8")) {
|
} else if (move.to == Square("h8") || move.to == Square("g8")) {
|
||||||
|
@ -424,19 +424,19 @@ bool Board::is_legal(const Move& move, Colour colour) const
|
||||||
for (auto& square : check_squares) {
|
for (auto& square : check_squares) {
|
||||||
Board clone = *this;
|
Board clone = *this;
|
||||||
clone.set_piece(move.from, EmptyPiece);
|
clone.set_piece(move.from, EmptyPiece);
|
||||||
clone.set_piece(square, { colour, Type::King });
|
clone.set_piece(square, { color, Type::King });
|
||||||
if (clone.in_check(colour))
|
if (clone.in_check(color))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
bool Board::is_legal_no_check(const Move& move, Color color) const
|
||||||
{
|
{
|
||||||
auto piece = get_piece(move.from);
|
auto piece = get_piece(move.from);
|
||||||
|
|
||||||
if (piece.colour != colour)
|
if (piece.color != color)
|
||||||
// attempted move of opponent's piece
|
// attempted move of opponent's piece
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -445,8 +445,8 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (piece.type == Type::Pawn) {
|
if (piece.type == Type::Pawn) {
|
||||||
int dir = (colour == Colour::White) ? +1 : -1;
|
int dir = (color == Color::White) ? +1 : -1;
|
||||||
unsigned start_rank = (colour == Colour::White) ? 1 : 6;
|
unsigned start_rank = (color == Color::White) ? 1 : 6;
|
||||||
|
|
||||||
if (move.from.rank == start_rank && move.to.rank == move.from.rank + (2 * dir) && move.to.file == move.from.file
|
if (move.from.rank == start_rank && move.to.rank == move.from.rank + (2 * dir) && move.to.file == move.from.file
|
||||||
&& get_piece(move.to).type == Type::None && get_piece({ move.from.rank + dir, move.from.file }).type == Type::None) {
|
&& get_piece(move.to).type == Type::None && get_piece({ move.from.rank + dir, move.from.file }).type == Type::None) {
|
||||||
|
@ -464,15 +464,15 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (move.to.file == move.from.file + 1 || move.to.file == move.from.file - 1) {
|
if (move.to.file == move.from.file + 1 || move.to.file == move.from.file - 1) {
|
||||||
unsigned other_start_rank = (colour == Colour::White) ? 6 : 1;
|
unsigned other_start_rank = (color == Color::White) ? 6 : 1;
|
||||||
unsigned en_passant_rank = (colour == Colour::White) ? 4 : 3;
|
unsigned en_passant_rank = (color == Color::White) ? 4 : 3;
|
||||||
Move en_passant_last_move = { { other_start_rank, move.to.file }, { en_passant_rank, move.to.file } };
|
Move en_passant_last_move = { { other_start_rank, move.to.file }, { en_passant_rank, move.to.file } };
|
||||||
if (get_piece(move.to).colour == opposing_colour(colour)) {
|
if (get_piece(move.to).color == opposing_color(color)) {
|
||||||
// Pawn capture.
|
// Pawn capture.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (m_last_move.has_value() && move.from.rank == en_passant_rank && m_last_move.value() == en_passant_last_move
|
if (m_last_move.has_value() && move.from.rank == en_passant_rank && m_last_move.value() == en_passant_last_move
|
||||||
&& get_piece(en_passant_last_move.to) == Piece(opposing_colour(colour), Type::Pawn)) {
|
&& get_piece(en_passant_last_move.to) == Piece(opposing_color(color), Type::Pawn)) {
|
||||||
// En passant.
|
// En passant.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +482,7 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
} else if (piece.type == Type::Knight) {
|
} else if (piece.type == Type::Knight) {
|
||||||
int rank_delta = abs(move.to.rank - move.from.rank);
|
int rank_delta = abs(move.to.rank - move.from.rank);
|
||||||
int file_delta = abs(move.to.file - move.from.file);
|
int file_delta = abs(move.to.file - move.from.file);
|
||||||
if (get_piece(move.to).colour != colour && max(rank_delta, file_delta) == 2 && min(rank_delta, file_delta) == 1) {
|
if (get_piece(move.to).color != color && max(rank_delta, file_delta) == 2 && min(rank_delta, file_delta) == 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (piece.type == Type::Bishop) {
|
} else if (piece.type == Type::Bishop) {
|
||||||
|
@ -497,7 +497,7 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_piece(move.to).colour != colour) {
|
if (get_piece(move.to).color != color) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,7 +513,7 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_piece(move.to).colour != colour) {
|
if (get_piece(move.to).color != color) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -529,7 +529,7 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_piece(move.to).colour != colour) {
|
if (get_piece(move.to).color != color) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,12 +537,12 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
int rank_delta = move.to.rank - move.from.rank;
|
int rank_delta = move.to.rank - move.from.rank;
|
||||||
int file_delta = move.to.file - move.from.file;
|
int file_delta = move.to.file - move.from.file;
|
||||||
if (abs(rank_delta) <= 1 && abs(file_delta) <= 1) {
|
if (abs(rank_delta) <= 1 && abs(file_delta) <= 1) {
|
||||||
if (get_piece(move.to).colour != colour) {
|
if (get_piece(move.to).color != color) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colour == Colour::White) {
|
if (color == Color::White) {
|
||||||
if ((move.to == Square("a1") || move.to == Square("c1")) && m_white_can_castle_queenside && get_piece(Square("b1")).type == Type::None && get_piece(Square("c1")).type == Type::None && get_piece(Square("d1")).type == Type::None) {
|
if ((move.to == Square("a1") || move.to == Square("c1")) && m_white_can_castle_queenside && get_piece(Square("b1")).type == Type::None && get_piece(Square("c1")).type == Type::None && get_piece(Square("d1")).type == Type::None) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -564,11 +564,11 @@ bool Board::is_legal_no_check(const Move& move, Colour colour) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::in_check(Colour colour) const
|
bool Board::in_check(Color color) const
|
||||||
{
|
{
|
||||||
Square king_square = { 50, 50 };
|
Square king_square = { 50, 50 };
|
||||||
Square::for_each([&](const Square& square) {
|
Square::for_each([&](const Square& square) {
|
||||||
if (get_piece(square) == Piece(colour, Type::King)) {
|
if (get_piece(square) == Piece(color, Type::King)) {
|
||||||
king_square = square;
|
king_square = square;
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
}
|
}
|
||||||
|
@ -577,7 +577,7 @@ bool Board::in_check(Colour colour) const
|
||||||
|
|
||||||
bool check = false;
|
bool check = false;
|
||||||
Square::for_each([&](const Square& square) {
|
Square::for_each([&](const Square& square) {
|
||||||
if (is_legal_no_check({ square, king_square }, opposing_colour(colour))) {
|
if (is_legal_no_check({ square, king_square }, opposing_color(color))) {
|
||||||
check = true;
|
check = true;
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
}
|
}
|
||||||
|
@ -587,20 +587,20 @@ bool Board::in_check(Colour colour) const
|
||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::apply_move(const Move& move, Colour colour)
|
bool Board::apply_move(const Move& move, Color color)
|
||||||
{
|
{
|
||||||
if (colour == Colour::None)
|
if (color == Color::None)
|
||||||
colour = turn();
|
color = turn();
|
||||||
|
|
||||||
if (!is_legal(move, colour))
|
if (!is_legal(move, color))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const_cast<Move&>(move).piece = get_piece(move.from);
|
const_cast<Move&>(move).piece = get_piece(move.from);
|
||||||
|
|
||||||
return apply_illegal_move(move, colour);
|
return apply_illegal_move(move, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::apply_illegal_move(const Move& move, Colour colour)
|
bool Board::apply_illegal_move(const Move& move, Color color)
|
||||||
{
|
{
|
||||||
Board clone = *this;
|
Board clone = *this;
|
||||||
clone.m_previous_states = {};
|
clone.m_previous_states = {};
|
||||||
|
@ -612,7 +612,7 @@ bool Board::apply_illegal_move(const Move& move, Colour colour)
|
||||||
m_previous_states.set(clone, state_count + 1);
|
m_previous_states.set(clone, state_count + 1);
|
||||||
m_moves.append(move);
|
m_moves.append(move);
|
||||||
|
|
||||||
m_turn = opposing_colour(colour);
|
m_turn = opposing_color(color);
|
||||||
|
|
||||||
m_last_move = move;
|
m_last_move = move;
|
||||||
m_moves_since_capture++;
|
m_moves_since_capture++;
|
||||||
|
@ -627,32 +627,32 @@ bool Board::apply_illegal_move(const Move& move, Colour colour)
|
||||||
if (move.from == Square("h8") || move.to == Square("h8") || move.from == Square("e8"))
|
if (move.from == Square("h8") || move.to == Square("h8") || move.from == Square("e8"))
|
||||||
m_black_can_castle_kingside = false;
|
m_black_can_castle_kingside = false;
|
||||||
|
|
||||||
if (colour == Colour::White && move.from == Square("e1") && get_piece(Square("e1")) == Piece(Colour::White, Type::King)) {
|
if (color == Color::White && move.from == Square("e1") && get_piece(Square("e1")) == Piece(Color::White, Type::King)) {
|
||||||
if (move.to == Square("a1") || move.to == Square("c1")) {
|
if (move.to == Square("a1") || move.to == Square("c1")) {
|
||||||
set_piece(Square("e1"), EmptyPiece);
|
set_piece(Square("e1"), EmptyPiece);
|
||||||
set_piece(Square("a1"), EmptyPiece);
|
set_piece(Square("a1"), EmptyPiece);
|
||||||
set_piece(Square("c1"), { Colour::White, Type::King });
|
set_piece(Square("c1"), { Color::White, Type::King });
|
||||||
set_piece(Square("d1"), { Colour::White, Type::Rook });
|
set_piece(Square("d1"), { Color::White, Type::Rook });
|
||||||
return true;
|
return true;
|
||||||
} else if (move.to == Square("h1") || move.to == Square("g1")) {
|
} else if (move.to == Square("h1") || move.to == Square("g1")) {
|
||||||
set_piece(Square("e1"), EmptyPiece);
|
set_piece(Square("e1"), EmptyPiece);
|
||||||
set_piece(Square("h1"), EmptyPiece);
|
set_piece(Square("h1"), EmptyPiece);
|
||||||
set_piece(Square("g1"), { Colour::White, Type::King });
|
set_piece(Square("g1"), { Color::White, Type::King });
|
||||||
set_piece(Square("f1"), { Colour::White, Type::Rook });
|
set_piece(Square("f1"), { Color::White, Type::Rook });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (colour == Colour::Black && move.from == Square("e8") && get_piece(Square("e8")) == Piece(Colour::Black, Type::King)) {
|
} else if (color == Color::Black && move.from == Square("e8") && get_piece(Square("e8")) == Piece(Color::Black, Type::King)) {
|
||||||
if (move.to == Square("a8") || move.to == Square("c8")) {
|
if (move.to == Square("a8") || move.to == Square("c8")) {
|
||||||
set_piece(Square("e8"), EmptyPiece);
|
set_piece(Square("e8"), EmptyPiece);
|
||||||
set_piece(Square("a8"), EmptyPiece);
|
set_piece(Square("a8"), EmptyPiece);
|
||||||
set_piece(Square("c8"), { Colour::Black, Type::King });
|
set_piece(Square("c8"), { Color::Black, Type::King });
|
||||||
set_piece(Square("d8"), { Colour::Black, Type::Rook });
|
set_piece(Square("d8"), { Color::Black, Type::Rook });
|
||||||
return true;
|
return true;
|
||||||
} else if (move.to == Square("h8") || move.to == Square("g8")) {
|
} else if (move.to == Square("h8") || move.to == Square("g8")) {
|
||||||
set_piece(Square("e8"), EmptyPiece);
|
set_piece(Square("e8"), EmptyPiece);
|
||||||
set_piece(Square("h8"), EmptyPiece);
|
set_piece(Square("h8"), EmptyPiece);
|
||||||
set_piece(Square("g8"), { Colour::Black, Type::King });
|
set_piece(Square("g8"), { Color::Black, Type::King });
|
||||||
set_piece(Square("f8"), { Colour::Black, Type::Rook });
|
set_piece(Square("f8"), { Color::Black, Type::Rook });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,14 +660,14 @@ bool Board::apply_illegal_move(const Move& move, Colour colour)
|
||||||
if (move.piece.type == Type::Pawn)
|
if (move.piece.type == Type::Pawn)
|
||||||
m_moves_since_pawn_advance = 0;
|
m_moves_since_pawn_advance = 0;
|
||||||
|
|
||||||
if (get_piece(move.to).colour != Colour::None) {
|
if (get_piece(move.to).color != Color::None) {
|
||||||
const_cast<Move&>(move).is_capture = true;
|
const_cast<Move&>(move).is_capture = true;
|
||||||
m_moves_since_capture = 0;
|
m_moves_since_capture = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_piece(move.from).type == Type::Pawn && ((colour == Colour::Black && move.to.rank == 0) || (colour == Colour::White && move.to.rank == 7))) {
|
if (get_piece(move.from).type == Type::Pawn && ((color == Color::Black && move.to.rank == 0) || (color == Color::White && move.to.rank == 7))) {
|
||||||
// Pawn Promotion
|
// Pawn Promotion
|
||||||
set_piece(move.to, { colour, move.promote_to });
|
set_piece(move.to, { color, move.promote_to });
|
||||||
set_piece(move.from, EmptyPiece);
|
set_piece(move.from, EmptyPiece);
|
||||||
|
|
||||||
if (in_check(m_turn))
|
if (in_check(m_turn))
|
||||||
|
@ -678,7 +678,7 @@ bool Board::apply_illegal_move(const Move& move, Colour colour)
|
||||||
|
|
||||||
if (get_piece(move.from).type == Type::Pawn && move.from.file != move.to.file && get_piece(move.to).type == Type::None) {
|
if (get_piece(move.from).type == Type::Pawn && move.from.file != move.to.file && get_piece(move.to).type == Type::None) {
|
||||||
// En passant.
|
// En passant.
|
||||||
if (colour == Colour::White) {
|
if (color == Color::White) {
|
||||||
set_piece({ move.to.rank - 1, move.to.file }, EmptyPiece);
|
set_piece({ move.to.rank - 1, move.to.file }, EmptyPiece);
|
||||||
} else {
|
} else {
|
||||||
set_piece({ move.to.rank + 1, move.to.file }, EmptyPiece);
|
set_piece({ move.to.rank + 1, move.to.file }, EmptyPiece);
|
||||||
|
@ -689,8 +689,8 @@ bool Board::apply_illegal_move(const Move& move, Colour colour)
|
||||||
|
|
||||||
Square::for_each([&](Square sq) {
|
Square::for_each([&](Square sq) {
|
||||||
// Ambiguous Move
|
// Ambiguous Move
|
||||||
if (sq != move.from && get_piece(sq).type == move.piece.type && get_piece(sq).colour == move.piece.colour) {
|
if (sq != move.from && get_piece(sq).type == move.piece.type && get_piece(sq).color == move.piece.color) {
|
||||||
if (is_legal(Move(sq, move.to), get_piece(sq).colour)) {
|
if (is_legal(Move(sq, move.to), get_piece(sq).color)) {
|
||||||
m_moves.last().is_ambiguous = true;
|
m_moves.last().is_ambiguous = true;
|
||||||
m_moves.last().ambiguous = sq;
|
m_moves.last().ambiguous = sq;
|
||||||
|
|
||||||
|
@ -709,10 +709,10 @@ bool Board::apply_illegal_move(const Move& move, Colour colour)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Move Board::random_move(Colour colour) const
|
Move Board::random_move(Color color) const
|
||||||
{
|
{
|
||||||
if (colour == Colour::None)
|
if (color == Color::None)
|
||||||
colour = turn();
|
color = turn();
|
||||||
|
|
||||||
Move move = { { 50, 50 }, { 50, 50 } };
|
Move move = { { 50, 50 }, { 50, 50 } };
|
||||||
int probability = 1;
|
int probability = 1;
|
||||||
|
@ -728,8 +728,8 @@ Move Board::random_move(Colour colour) const
|
||||||
|
|
||||||
Board::Result Board::game_result() const
|
Board::Result Board::game_result() const
|
||||||
{
|
{
|
||||||
if (m_resigned != Colour::None)
|
if (m_resigned != Color::None)
|
||||||
return (m_resigned == Colour::White) ? Result::WhiteResign : Result::BlackResign;
|
return (m_resigned == Color::White) ? Result::WhiteResign : Result::BlackResign;
|
||||||
|
|
||||||
bool sufficient_material = false;
|
bool sufficient_material = false;
|
||||||
bool no_more_pieces_allowed = false;
|
bool no_more_pieces_allowed = false;
|
||||||
|
@ -750,7 +750,7 @@ Board::Result Board::game_result() const
|
||||||
|
|
||||||
if (get_piece(sq).type == Type::Bishop) {
|
if (get_piece(sq).type == Type::Bishop) {
|
||||||
if (bishop.has_value()) {
|
if (bishop.has_value()) {
|
||||||
if (get_piece(sq).colour == get_piece(bishop.value()).colour) {
|
if (get_piece(sq).color == get_piece(bishop.value()).color) {
|
||||||
sufficient_material = true;
|
sufficient_material = true;
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
} else if (sq.is_light() != bishop.value().is_light()) {
|
} else if (sq.is_light() != bishop.value().is_light()) {
|
||||||
|
@ -800,22 +800,22 @@ Board::Result Board::game_result() const
|
||||||
return Result::StaleMate;
|
return Result::StaleMate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Colour Board::game_winner() const
|
Color Board::game_winner() const
|
||||||
{
|
{
|
||||||
if (game_result() == Result::CheckMate)
|
if (game_result() == Result::CheckMate)
|
||||||
return opposing_colour(turn());
|
return opposing_color(turn());
|
||||||
|
|
||||||
return Colour::None;
|
return Color::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Board::game_score() const
|
int Board::game_score() const
|
||||||
{
|
{
|
||||||
switch (game_winner()) {
|
switch (game_winner()) {
|
||||||
case Colour::White:
|
case Color::White:
|
||||||
return +1;
|
return +1;
|
||||||
case Colour::Black:
|
case Color::Black:
|
||||||
return -1;
|
return -1;
|
||||||
case Colour::None:
|
case Color::None:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -849,7 +849,7 @@ int Board::material_imbalance() const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_piece(square).colour == Colour::White) {
|
if (get_piece(square).color == Color::White) {
|
||||||
imbalance += value;
|
imbalance += value;
|
||||||
} else {
|
} else {
|
||||||
imbalance -= value;
|
imbalance -= value;
|
||||||
|
@ -859,12 +859,12 @@ int Board::material_imbalance() const
|
||||||
return imbalance;
|
return imbalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::is_promotion_move(const Move& move, Colour colour) const
|
bool Board::is_promotion_move(const Move& move, Color color) const
|
||||||
{
|
{
|
||||||
if (colour == Colour::None)
|
if (color == Color::None)
|
||||||
colour = turn();
|
color = turn();
|
||||||
|
|
||||||
unsigned promotion_rank = (colour == Colour::White) ? 7 : 0;
|
unsigned promotion_rank = (color == Color::White) ? 7 : 0;
|
||||||
if (move.to.rank != promotion_rank)
|
if (move.to.rank != promotion_rank)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -873,7 +873,7 @@ bool Board::is_promotion_move(const Move& move, Colour colour) const
|
||||||
|
|
||||||
Move queen_move = move;
|
Move queen_move = move;
|
||||||
queen_move.promote_to = Type::Queen;
|
queen_move.promote_to = Type::Queen;
|
||||||
if (!is_legal(queen_move, colour))
|
if (!is_legal(queen_move, color))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -904,17 +904,17 @@ bool Board::operator==(const Board& other) const
|
||||||
return turn() == other.turn();
|
return turn() == other.turn();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::set_resigned(Chess::Colour c)
|
void Board::set_resigned(Chess::Color c)
|
||||||
{
|
{
|
||||||
m_resigned = c;
|
m_resigned = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Board::result_to_string(Result result, Colour turn)
|
String Board::result_to_string(Result result, Color turn)
|
||||||
{
|
{
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case Result::CheckMate:
|
case Result::CheckMate:
|
||||||
ASSERT(turn != Chess::Colour::None);
|
ASSERT(turn != Chess::Color::None);
|
||||||
return turn == Chess::Colour::White ? "Black wins by Checkmate" : "White wins by Checkmate";
|
return turn == Chess::Color::White ? "Black wins by Checkmate" : "White wins by Checkmate";
|
||||||
case Result::WhiteResign:
|
case Result::WhiteResign:
|
||||||
return "Black wins by Resignation";
|
return "Black wins by Resignation";
|
||||||
case Result::BlackResign:
|
case Result::BlackResign:
|
||||||
|
@ -938,12 +938,12 @@ String Board::result_to_string(Result result, Colour turn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String Board::result_to_points(Result result, Colour turn)
|
String Board::result_to_points(Result result, Color turn)
|
||||||
{
|
{
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case Result::CheckMate:
|
case Result::CheckMate:
|
||||||
ASSERT(turn != Chess::Colour::None);
|
ASSERT(turn != Chess::Color::None);
|
||||||
return turn == Chess::Colour::White ? "0-1" : "1-0";
|
return turn == Chess::Color::White ? "0-1" : "1-0";
|
||||||
case Result::WhiteResign:
|
case Result::WhiteResign:
|
||||||
return "0-1";
|
return "0-1";
|
||||||
case Result::BlackResign:
|
case Result::BlackResign:
|
||||||
|
|
|
@ -48,31 +48,31 @@ enum class Type {
|
||||||
String char_for_piece(Type type);
|
String char_for_piece(Type type);
|
||||||
Chess::Type piece_for_char_promotion(const StringView& str);
|
Chess::Type piece_for_char_promotion(const StringView& str);
|
||||||
|
|
||||||
enum class Colour {
|
enum class Color {
|
||||||
White,
|
White,
|
||||||
Black,
|
Black,
|
||||||
None,
|
None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Colour opposing_colour(Colour colour);
|
Color opposing_color(Color color);
|
||||||
|
|
||||||
struct Piece {
|
struct Piece {
|
||||||
constexpr Piece()
|
constexpr Piece()
|
||||||
: colour(Colour::None)
|
: color(Color::None)
|
||||||
, type(Type::None)
|
, type(Type::None)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
constexpr Piece(Colour c, Type t)
|
constexpr Piece(Color c, Type t)
|
||||||
: colour(c)
|
: color(c)
|
||||||
, type(t)
|
, type(t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Colour colour : 4;
|
Color color : 4;
|
||||||
Type type : 4;
|
Type type : 4;
|
||||||
bool operator==(const Piece& other) const { return colour == other.colour && type == other.type; }
|
bool operator==(const Piece& other) const { return color == other.color && type == other.type; }
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Piece EmptyPiece = { Colour::None, Type::None };
|
constexpr Piece EmptyPiece = { Color::None, Type::None };
|
||||||
|
|
||||||
struct Square {
|
struct Square {
|
||||||
unsigned rank; // zero indexed;
|
unsigned rank; // zero indexed;
|
||||||
|
@ -122,7 +122,7 @@ struct Move {
|
||||||
}
|
}
|
||||||
bool operator==(const Move& other) const { return from == other.from && to == other.to && promote_to == other.promote_to; }
|
bool operator==(const Move& other) const { return from == other.from && to == other.to && promote_to == other.promote_to; }
|
||||||
|
|
||||||
static Move from_algebraic(const StringView& algebraic, const Colour turn, const Board& board);
|
static Move from_algebraic(const StringView& algebraic, const Color turn, const Board& board);
|
||||||
String to_long_algebraic() const;
|
String to_long_algebraic() const;
|
||||||
String to_algebraic() const;
|
String to_algebraic() const;
|
||||||
};
|
};
|
||||||
|
@ -134,12 +134,12 @@ public:
|
||||||
Piece get_piece(const Square&) const;
|
Piece get_piece(const Square&) const;
|
||||||
Piece set_piece(const Square&, const Piece&);
|
Piece set_piece(const Square&, const Piece&);
|
||||||
|
|
||||||
bool is_legal(const Move&, Colour colour = Colour::None) const;
|
bool is_legal(const Move&, Color color = Color::None) const;
|
||||||
bool in_check(Colour colour) const;
|
bool in_check(Color color) const;
|
||||||
|
|
||||||
bool is_promotion_move(const Move&, Colour colour = Colour::None) const;
|
bool is_promotion_move(const Move&, Color color = Color::None) const;
|
||||||
|
|
||||||
bool apply_move(const Move&, Colour colour = Colour::None);
|
bool apply_move(const Move&, Color color = Color::None);
|
||||||
const Optional<Move>& last_move() const { return m_last_move; }
|
const Optional<Move>& last_move() const { return m_last_move; }
|
||||||
|
|
||||||
String to_fen() const;
|
String to_fen() const;
|
||||||
|
@ -157,32 +157,32 @@ public:
|
||||||
NotFinished,
|
NotFinished,
|
||||||
};
|
};
|
||||||
|
|
||||||
static String result_to_string(Result, Colour turn);
|
static String result_to_string(Result, Color turn);
|
||||||
static String result_to_points(Result, Colour turn);
|
static String result_to_points(Result, Color turn);
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void generate_moves(Callback callback, Colour colour = Colour::None) const;
|
void generate_moves(Callback callback, Color color = Color::None) const;
|
||||||
Move random_move(Colour colour = Colour::None) const;
|
Move random_move(Color color = Color::None) const;
|
||||||
Result game_result() const;
|
Result game_result() const;
|
||||||
Colour game_winner() const;
|
Color game_winner() const;
|
||||||
int game_score() const;
|
int game_score() const;
|
||||||
bool game_finished() const;
|
bool game_finished() const;
|
||||||
void set_resigned(Colour);
|
void set_resigned(Color);
|
||||||
int material_imbalance() const;
|
int material_imbalance() const;
|
||||||
|
|
||||||
Colour turn() const { return m_turn; }
|
Color turn() const { return m_turn; }
|
||||||
const Vector<Move>& moves() const { return m_moves; }
|
const Vector<Move>& moves() const { return m_moves; }
|
||||||
|
|
||||||
bool operator==(const Board& other) const;
|
bool operator==(const Board& other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_legal_no_check(const Move&, Colour colour) const;
|
bool is_legal_no_check(const Move&, Color color) const;
|
||||||
bool is_legal_promotion(const Move&, Colour colour) const;
|
bool is_legal_promotion(const Move&, Color color) const;
|
||||||
bool apply_illegal_move(const Move&, Colour colour);
|
bool apply_illegal_move(const Move&, Color color);
|
||||||
|
|
||||||
Piece m_board[8][8];
|
Piece m_board[8][8];
|
||||||
Colour m_turn { Colour::White };
|
Color m_turn { Color::White };
|
||||||
Colour m_resigned { Colour::None };
|
Color m_resigned { Color::None };
|
||||||
Optional<Move> m_last_move;
|
Optional<Move> m_last_move;
|
||||||
int m_moves_since_capture { 0 };
|
int m_moves_since_capture { 0 };
|
||||||
int m_moves_since_pawn_advance { 0 };
|
int m_moves_since_pawn_advance { 0 };
|
||||||
|
@ -198,13 +198,13 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void Board::generate_moves(Callback callback, Colour colour) const
|
void Board::generate_moves(Callback callback, Color color) const
|
||||||
{
|
{
|
||||||
if (colour == Colour::None)
|
if (color == Color::None)
|
||||||
colour = turn();
|
color = turn();
|
||||||
|
|
||||||
auto try_move = [&](Move m) {
|
auto try_move = [&](Move m) {
|
||||||
if (is_legal(m, colour)) {
|
if (is_legal(m, color)) {
|
||||||
if (callback(m) == IterationDecision::Break)
|
if (callback(m) == IterationDecision::Break)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ void Board::generate_moves(Callback callback, Colour colour) const
|
||||||
|
|
||||||
Square::for_each([&](Square sq) {
|
Square::for_each([&](Square sq) {
|
||||||
auto piece = get_piece(sq);
|
auto piece = get_piece(sq);
|
||||||
if (piece.colour != colour)
|
if (piece.color != color)
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
bool keep_going = true;
|
bool keep_going = true;
|
||||||
|
@ -298,7 +298,7 @@ template<>
|
||||||
struct AK::Traits<Chess::Piece> : public GenericTraits<Chess::Piece> {
|
struct AK::Traits<Chess::Piece> : public GenericTraits<Chess::Piece> {
|
||||||
static unsigned hash(Chess::Piece piece)
|
static unsigned hash(Chess::Piece piece)
|
||||||
{
|
{
|
||||||
return pair_int_hash(static_cast<u32>(piece.colour), static_cast<u32>(piece.type));
|
return pair_int_hash(static_cast<u32>(piece.color), static_cast<u32>(piece.type));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ void XtermSuggestionDisplay::display(const SuggestionManager& manager)
|
||||||
if (lines_used + m_prompt_lines_at_suggestion_initiation >= m_num_lines)
|
if (lines_used + m_prompt_lines_at_suggestion_initiation >= m_num_lines)
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
|
||||||
// Only apply colour to the selection if something is *actually* added to the buffer.
|
// Only apply color to the selection if something is *actually* added to the buffer.
|
||||||
if (manager.is_current_suggestion_complete() && index == manager.next_index()) {
|
if (manager.is_current_suggestion_complete() && index == manager.next_index()) {
|
||||||
VT::apply_style({ Style::Foreground(Style::XtermColor::Blue) });
|
VT::apply_style({ Style::Foreground(Style::XtermColor::Blue) });
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
|
@ -131,7 +131,7 @@ void MCTSTree::do_round()
|
||||||
|
|
||||||
Chess::Move MCTSTree::best_move() const
|
Chess::Move MCTSTree::best_move() const
|
||||||
{
|
{
|
||||||
int score_multiplier = (m_board.turn() == Chess::Colour::White) ? 1 : -1;
|
int score_multiplier = (m_board.turn() == Chess::Color::White) ? 1 : -1;
|
||||||
|
|
||||||
Chess::Move best_move = { { 0, 0 }, { 0, 0 } };
|
Chess::Move best_move = { { 0, 0 }, { 0, 0 } };
|
||||||
double best_score = -double(INFINITY);
|
double best_score = -double(INFINITY);
|
||||||
|
@ -156,13 +156,13 @@ double MCTSTree::expected_value() const
|
||||||
return double(m_white_points) / m_simulations;
|
return double(m_white_points) / m_simulations;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MCTSTree::uct(Chess::Colour colour) const
|
double MCTSTree::uct(Chess::Color color) const
|
||||||
{
|
{
|
||||||
// UCT: Upper Confidence Bound Applied to Trees.
|
// UCT: Upper Confidence Bound Applied to Trees.
|
||||||
// Kocsis, Levente; Szepesvári, Csaba (2006). "Bandit based Monte-Carlo Planning"
|
// Kocsis, Levente; Szepesvári, Csaba (2006). "Bandit based Monte-Carlo Planning"
|
||||||
|
|
||||||
// Fun fact: Szepesvári was my data structures professor.
|
// Fun fact: Szepesvári was my data structures professor.
|
||||||
double expected = expected_value() * ((colour == Chess::Colour::White) ? 1 : -1);
|
double expected = expected_value() * ((color == Chess::Color::White) ? 1 : -1);
|
||||||
return expected + m_exploration_parameter * sqrt(log(m_parent->m_simulations) / m_simulations);
|
return expected + m_exploration_parameter * sqrt(log(m_parent->m_simulations) / m_simulations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
|
|
||||||
Chess::Move best_move() const;
|
Chess::Move best_move() const;
|
||||||
double expected_value() const;
|
double expected_value() const;
|
||||||
double uct(Chess::Colour colour) const;
|
double uct(Chess::Color color) const;
|
||||||
bool expanded() const;
|
bool expanded() const;
|
||||||
|
|
||||||
EvalMethod eval_method() const { return m_eval_method; }
|
EvalMethod eval_method() const { return m_eval_method; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue