Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
84c3af2bb1 | |||
22acfc5027 | |||
1ff4b6b1f4 | |||
2493892b05 | |||
bdd8011577 | |||
5549c77177 | |||
be016dcbcc | |||
efd7bf6794 | |||
81b24d3082 | |||
497da2de8e | |||
0574a11b32 |
@ -1,6 +1,7 @@
|
|||||||
#include "board.hpp"
|
#include "board.hpp"
|
||||||
|
|
||||||
#include "coords.hpp"
|
#include "coords.hpp"
|
||||||
|
#include "move.hpp"
|
||||||
#include "pieces/piece.hpp"
|
#include "pieces/piece.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -19,6 +20,7 @@ Board Board::setup_fen_position(std::string fen) {
|
|||||||
{'q', Piece::Queen},
|
{'q', Piece::Queen},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -- Pieces
|
||||||
std::string fen_board = fen.substr(0, fen.find(' '));
|
std::string fen_board = fen.substr(0, fen.find(' '));
|
||||||
int rank = 7, file = 0;
|
int rank = 7, file = 0;
|
||||||
for (char symbol : fen_board) {
|
for (char symbol : fen_board) {
|
||||||
@ -39,6 +41,57 @@ Board Board::setup_fen_position(std::string fen) {
|
|||||||
file++;
|
file++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- Active colour
|
||||||
|
int index = fen.find(' ');
|
||||||
|
index++;
|
||||||
|
board.white_to_play = fen[index] == 'w';
|
||||||
|
|
||||||
|
// Castling Rights
|
||||||
|
index += 2;
|
||||||
|
for (char symbol : fen.substr(index, fen.find(' ', index + 1))) {
|
||||||
|
index++;
|
||||||
|
if (symbol == ' ' || symbol == '-') {
|
||||||
|
if (symbol == '-')
|
||||||
|
index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (symbol) {
|
||||||
|
case 'K':
|
||||||
|
board.w_castle_rights |= CastleSide::KingSide;
|
||||||
|
break;
|
||||||
|
case 'Q':
|
||||||
|
board.w_castle_rights |= CastleSide::QueenSide;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
board.b_castle_rights |= CastleSide::KingSide;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
board.b_castle_rights |= CastleSide::QueenSide;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- En passant target
|
||||||
|
if (fen[index] != '-') {
|
||||||
|
Coords c = Coords::from_algebraic(fen.substr(index, 2));
|
||||||
|
index += 2;
|
||||||
|
board.en_passant_target = c.to_index();
|
||||||
|
} else {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Half move clock
|
||||||
|
index = fen.find(' ', index) + 1;
|
||||||
|
board.n_half_moves =
|
||||||
|
std::stoi(fen.substr(index, fen.find(' ', index + 1) - index));
|
||||||
|
|
||||||
|
// -- Full move number
|
||||||
|
index = fen.find(' ', index) + 1;
|
||||||
|
board.n_full_moves = std::stoi(fen.substr(index));
|
||||||
|
|
||||||
|
|
||||||
return board;
|
return board;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,15 +106,16 @@ std::string Board::to_fen() const {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
// -- Pieces
|
||||||
for (int rank = 7; rank >= 0; rank--) {
|
for (int rank = 7; rank >= 0; rank--) {
|
||||||
int empty_cell_counter = 0;
|
int empty_cell_counter = 0;
|
||||||
for (int file = 0; file < 8; file++) {
|
for (int file = 0; file < 8; file++) {
|
||||||
if (this->squares[rank * 8 + file] == Piece::None) {
|
if (squares[rank * 8 + file] == Piece::None) {
|
||||||
empty_cell_counter++;
|
empty_cell_counter++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int full_piece = this->squares[rank * 8 + file];
|
int full_piece = squares[rank * 8 + file];
|
||||||
char piece = p2c[full_piece & 0b111];
|
char piece = p2c[full_piece & 0b111];
|
||||||
int8_t colour = colour_at({file, rank});
|
int8_t colour = colour_at({file, rank});
|
||||||
|
|
||||||
@ -76,6 +130,41 @@ std::string Board::to_fen() const {
|
|||||||
if (rank > 0)
|
if (rank > 0)
|
||||||
ret += "/";
|
ret += "/";
|
||||||
}
|
}
|
||||||
|
ret += " ";
|
||||||
|
|
||||||
|
// -- Active colour
|
||||||
|
ret += white_to_play ? 'w' : 'b';
|
||||||
|
ret += " ";
|
||||||
|
|
||||||
|
// -- Castling Rights
|
||||||
|
if (w_castle_rights == CastleSide::NeitherSide
|
||||||
|
&& b_castle_rights == CastleSide::NeitherSide)
|
||||||
|
ret += '-';
|
||||||
|
else {
|
||||||
|
if (w_castle_rights & CastleSide::KingSide)
|
||||||
|
ret += 'K';
|
||||||
|
if (w_castle_rights & CastleSide::QueenSide)
|
||||||
|
ret += 'Q';
|
||||||
|
if (b_castle_rights & CastleSide::KingSide)
|
||||||
|
ret += 'k';
|
||||||
|
if (b_castle_rights & CastleSide::QueenSide)
|
||||||
|
ret += 'q';
|
||||||
|
}
|
||||||
|
ret += ' ';
|
||||||
|
|
||||||
|
// -- En passant target
|
||||||
|
ret += en_passant_target == -1
|
||||||
|
? "-"
|
||||||
|
: Coords::from_index(en_passant_target).to_algebraic();
|
||||||
|
ret += ' ';
|
||||||
|
|
||||||
|
// -- Half move clock
|
||||||
|
ret += std::to_string(n_half_moves);
|
||||||
|
ret += ' ';
|
||||||
|
|
||||||
|
// -- Full moves number
|
||||||
|
ret += std::to_string(n_full_moves);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,12 @@ struct Board {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
int8_t squares[64] = {Piece::None};
|
int8_t squares[64] = {Piece::None};
|
||||||
bool white_to_play;
|
bool white_to_play = true;
|
||||||
CastleSide w_castle_rights;
|
int8_t w_castle_rights = CastleSide::NeitherSide;
|
||||||
CastleSide b_castle_rights;
|
int8_t b_castle_rights = CastleSide::NeitherSide;
|
||||||
|
int8_t en_passant_target = -1;
|
||||||
|
uint8_t n_half_moves = 0;
|
||||||
|
uint8_t n_full_moves = 0;
|
||||||
|
|
||||||
static Board setup_fen_position(std::string fen);
|
static Board setup_fen_position(std::string fen);
|
||||||
|
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
static std::string _FILES = "abcdefgh";
|
||||||
|
static std::string _RANKS = "12345678";
|
||||||
|
|
||||||
struct Coords {
|
struct Coords {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
|
Coords(int x, int y): x(x), y(y) {}
|
||||||
|
|
||||||
int8_t to_index() const {
|
int8_t to_index() const {
|
||||||
return this->y * 8 + this->x;
|
return this->y * 8 + this->x;
|
||||||
}
|
}
|
||||||
@ -13,7 +21,50 @@ struct Coords {
|
|||||||
return {idx % 8, idx / 8};
|
return {idx % 8, idx / 8};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Coords from_algebraic(std::string pos) {
|
||||||
|
if (pos.size() != 2)
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"An algebraic coordinate should only have two characters"
|
||||||
|
);
|
||||||
|
|
||||||
|
int x = _FILES.find(pos[0]);
|
||||||
|
if (x == std::string::npos)
|
||||||
|
throw std::invalid_argument("The first character of the given "
|
||||||
|
"algebraic coordinate is invalid");
|
||||||
|
|
||||||
|
int y = _RANKS.find(pos[1]);
|
||||||
|
if (y == std::string::npos)
|
||||||
|
throw std::invalid_argument("The second character of the given "
|
||||||
|
"algebraic coordinate is invalid");
|
||||||
|
|
||||||
|
return Coords{x, y};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_algebraic() const {
|
||||||
|
std::string ret;
|
||||||
|
if (x > 7 || y > 7)
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"Can't give the algebraic vesion of an invalid coord"
|
||||||
|
);
|
||||||
|
ret += _FILES[x];
|
||||||
|
ret += _RANKS[y];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_within_bounds() const {
|
bool is_within_bounds() const {
|
||||||
return this->to_index() < 64;
|
return this->to_index() < 64;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const Coords& a, const Coords& b) {
|
||||||
|
return a.x == b.x && a.y == b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const Coords& a, const Coords& b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const Coords& coords) {
|
||||||
|
os << coords.to_algebraic();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
@ -6,5 +6,6 @@ int main(int argc, char* argv[]) {
|
|||||||
std::string pos =
|
std::string pos =
|
||||||
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||||
Board b = Board::setup_fen_position(pos);
|
Board b = Board::setup_fen_position(pos);
|
||||||
|
sizeof(b);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,9 @@ std::vector<Move> king_moves(const Board& b, const Coords xy) {
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// -- Castles
|
// -- Castles
|
||||||
CastleSide castling_rights = b.colour_at(xy) == Colour::White
|
int8_t castling_rights = b.colour_at(xy) == Colour::White
|
||||||
? b.w_castle_rights
|
? b.w_castle_rights
|
||||||
: b.b_castle_rights;
|
: b.b_castle_rights;
|
||||||
|
|
||||||
if (castling_rights == CastleSide::NeitherSide)
|
if (castling_rights == CastleSide::NeitherSide)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
std::vector<Move> rook_moves(const Board& b, const Coords xy) {
|
std::vector<Move> queen_moves(const Board& b, const Coords xy) {
|
||||||
std::vector<Move> ret;
|
std::vector<Move> ret;
|
||||||
auto e = look_direction(b, xy, 1, 0);
|
auto e = look_direction(b, xy, 1, 0);
|
||||||
ret.insert(ret.end(), e.begin(), e.end());
|
ret.insert(ret.end(), e.begin(), e.end());
|
||||||
|
@ -2,21 +2,22 @@
|
|||||||
#include "lib.hpp"
|
#include "lib.hpp"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::string pos = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
|
std::string pos =
|
||||||
ASSERT_EQUALS(pos, Board::setup_fen_position(pos)->to_fen());
|
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||||
|
ASSERT_EQUALS(pos, Board::setup_fen_position(pos).to_fen());
|
||||||
|
|
||||||
pos = "r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1";
|
pos = "r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1 b Qk - 0 1";
|
||||||
ASSERT_EQUALS(pos, Board::setup_fen_position(pos)->to_fen());
|
ASSERT_EQUALS(pos, Board::setup_fen_position(pos).to_fen());
|
||||||
|
|
||||||
pos = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR";
|
pos = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1";
|
||||||
ASSERT_EQUALS(pos, Board::setup_fen_position(pos)->to_fen());
|
ASSERT_EQUALS(pos, Board::setup_fen_position(pos).to_fen());
|
||||||
|
|
||||||
pos = "4k2r/6r1/8/8/8/8/3R4/R3K3";
|
pos = "4k2r/6r1/8/8/8/8/3R4/R3K3 w Qk - 0 1";
|
||||||
ASSERT_EQUALS(pos, Board::setup_fen_position(pos)->to_fen());
|
ASSERT_EQUALS(pos, Board::setup_fen_position(pos).to_fen());
|
||||||
|
|
||||||
pos = "8/8/8/4p1K1/2k1P3/8/8/8";
|
pos = "8/8/8/4p1K1/2k1P3/8/8/8 b - - 0 1";
|
||||||
ASSERT_EQUALS(pos, Board::setup_fen_position(pos)->to_fen());
|
ASSERT_EQUALS(pos, Board::setup_fen_position(pos).to_fen());
|
||||||
|
|
||||||
pos = "8/5k2/3p4/1p1Pp2p/pP2Pp1P/P4P1K/8/8";
|
pos = "8/5k2/3p4/1p1Pp2p/pP2Pp1P/P4P1K/8/8 b - - 99 50";
|
||||||
ASSERT_EQUALS(pos, Board::setup_fen_position(pos)->to_fen());
|
ASSERT_EQUALS(pos, Board::setup_fen_position(pos).to_fen());
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#define ASSERT_EQUALS(expected, actual) \
|
#define ASSERT_EQUALS(x, y) \
|
||||||
{ \
|
{ \
|
||||||
if (expected != actual) \
|
auto expected = x; \
|
||||||
std::cout << "Expected: " << std::endl \
|
auto actual = y; \
|
||||||
|
if (expected != actual) { \
|
||||||
|
std::cerr << "Expected: " << std::endl \
|
||||||
<< '\t' << expected << std::endl \
|
<< '\t' << expected << std::endl \
|
||||||
<< "Got: " << std::endl \
|
<< "Got: " << std::endl \
|
||||||
<< '\t' << actual << std::endl; \
|
<< '\t' << actual << std::endl; \
|
||||||
|
exit(1); \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
20
cpp/tests/positions.cpp
Normal file
20
cpp/tests/positions.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "../src/coords.hpp"
|
||||||
|
#include "lib.hpp"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ASSERT_EQUALS(Coords(0, 0).to_algebraic(), "a1");
|
||||||
|
ASSERT_EQUALS(Coords(1, 0).to_algebraic(), "b1");
|
||||||
|
|
||||||
|
ASSERT_EQUALS(Coords(2, 1).to_algebraic(), "c2");
|
||||||
|
ASSERT_EQUALS(Coords(4, 2).to_algebraic(), "e3");
|
||||||
|
|
||||||
|
ASSERT_EQUALS(Coords(7, 7).to_algebraic(), "h8");
|
||||||
|
|
||||||
|
ASSERT_EQUALS(Coords::from_algebraic("a1"), Coords(0, 0));
|
||||||
|
ASSERT_EQUALS(Coords::from_algebraic("b1"), Coords(1, 0));
|
||||||
|
|
||||||
|
ASSERT_EQUALS(Coords::from_algebraic("c2"), Coords(2, 1));
|
||||||
|
ASSERT_EQUALS(Coords::from_algebraic("e3"), Coords(4, 2));
|
||||||
|
|
||||||
|
ASSERT_EQUALS(Coords::from_algebraic("h8"), Coords(7, 7));
|
||||||
|
}
|
Reference in New Issue
Block a user