All tests running on 10x12 board, and bitwise moves.

master
Tait Hoyem 5 years ago
parent c585c1543e
commit 0b84fcf8e0

@ -13,13 +13,6 @@ inline Position _pair_to_pos_unsafe(int x, int y){
return static_cast<Position>(std::abs(y-7)*8 + x);
}
void _push_if_valid_pos(int pos, std::unordered_set<int> *pns){
if (is_valid_position(pos)){
pns->insert(pos);
}
}
// This function returns true if the color of the piece on tile (x,y) is the Color c
bool _xy_is_color(int pos, std::array<PieceType, 120>* board, Color c){
return c==Color::WHITE ? is_white((*board)[pos]) : is_black((*board)[pos]);
@ -30,7 +23,7 @@ Color _rev_color(Color c){
}
// This function will set the boolean guarding it to false if it is blocked, thus stopping it from running.
void _add_if_not_blocked(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){
void _add_if_not_blocked(int pos, int from, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){
if (*is_not_blocked){
if (!is_valid_position(pos)){
*is_not_blocked = false;
@ -38,45 +31,41 @@ void _add_if_not_blocked(int pos, std::unordered_set<int> *pns, std::array<Piece
if (_xy_is_color(pos, board, color_of_piece)){
*is_not_blocked = false;
} else if (_xy_is_color(pos, board, color_of_opposite)){
pns->insert(pos);
pns->insert(make_move(from, pos));
*is_not_blocked = false;
} else {
pns->insert(pos);
pns->insert(make_move(from, pos));
}
}
}
}
// This function is for non-ray types only, as it ignores the 'ray rules', and just jumps over stuff (e.g. knight), or only moves one space generally (e.g. king)
void _add_if_not_blocked(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite){
if (_xy_is_color(pos, board, color_of_piece)){
void _add_if_not_blocked(int pos, int from, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite){
if (!is_valid_position(pos) ||
_xy_is_color(pos, board, color_of_piece)){
return;
} else {
pns->insert(pos);
pns->insert(make_move(from, pos));
}
}
// This is a specialized function for the pawn's diagonal takes.
// It will only to pns if there is a piece of opposite color on it.
void _pawn_diag_add_if_not_blocked(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, int en_passant){
void _pawn_diag_add_if_not_blocked(int pos, int from, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, int en_passant){
if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) ||
pos == en_passant)){
pns->insert(pos);
pns->insert(make_move(from, pos));
}
}
// This is a specialized functions for the pawn's inability to take going forward.
// Notice the lack of insertion where there usually is when (x,y) is a different color.
void _pawn_add_if_not_blocked(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){
void _pawn_add_if_not_blocked(int pos, int from, std::unordered_set<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){
if (*is_not_blocked){
if (is_valid_position(pos)){
if ((*board)[pos] != PieceType::NONE ||
(*board)[pos] == PieceType::INV){
*is_not_blocked = false;
} else {
if (_xy_is_color(pos, board, color_of_piece)){
*is_not_blocked = false;
} else if (_xy_is_color(pos, board, color_of_opposite)){
*is_not_blocked = false;
} else {
pns->insert(pos);
}
pns->insert(make_move(from, pos));
}
}
}
@ -86,7 +75,7 @@ void _get_all_moves_rook(int pos, std::unordered_set<int> *pns, std::array<Piece
for (int rk_off : ROOK_PIECE_OFFSETS){
bool* not_blocked = new bool(true);
for (int offset=1; offset<8; offset++){
_add_if_not_blocked(pos+(rk_off*offset), pns, board, pc, rc, not_blocked);
_add_if_not_blocked(pos+(rk_off*offset), pos, pns, board, pc, rc, not_blocked);
}
}
@ -108,7 +97,7 @@ void _get_all_moves_bishop(int pos, std::unordered_set<int> *pns, std::array<Pie
for (int bs_off : BISHOP_PIECE_OFFSETS){
bool* not_blocked = new bool(true);
for (int offset=1; offset<8; offset++){
_add_if_not_blocked(pos+(bs_off*offset), pns, board, pc, rc, not_blocked);
_add_if_not_blocked(pos+(bs_off*offset), pos, pns, board, pc, rc, not_blocked);
}
}
/*
@ -132,7 +121,7 @@ void _get_all_moves_bishop(int pos, std::unordered_set<int> *pns, std::array<Pie
void _get_all_moves_knight(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120>* board, Color pc, Color rc){
for (int kn_off : KNIGHT_PIECE_OFFSETS){
bool* not_blocked = new bool(true);
_add_if_not_blocked(pos+kn_off, pns, board, pc, rc);
_add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc);
}
/*
for (int xo=1;xo<=2;xo++){
@ -148,7 +137,7 @@ void _get_all_moves_knight(int pos, std::unordered_set<int> *pns, std::array<Pie
void _get_all_moves_king(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120>* board, Color pc, Color rc){
for (int kn_off : KING_PIECE_OFFSETS){
bool* not_blocked = new bool(true);
_add_if_not_blocked(pos+kn_off, pns, board, pc, rc);
_add_if_not_blocked(pos+kn_off, pos, pns, board, pc, rc);
}
@ -167,17 +156,17 @@ void _get_all_moves_king(int pos, std::unordered_set<int> *pns, std::array<Piece
void _get_all_moves_pawn(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120>* board, Color pc, Color rc, int en_passant){
// if it's white use different offsets, and pawn starting rank
int offset2 = pc==Color::WHITE?20:-20;
int offset1 = pc==Color::WHITE?10:-10;
int offset2 = pc==Color::WHITE?-20:20;
int offset1 = pc==Color::WHITE?-10:10;
int default_pawn_rank = pc==Color::WHITE?Rank::RANK2:Rank::RANK7;
bool *free_to_double_move = new bool(true);
_pawn_add_if_not_blocked(pos+offset1, pns, board, pc, rc, free_to_double_move);
_pawn_add_if_not_blocked(pos+offset1, pos, pns, board, pc, rc, free_to_double_move);
if (get_rank(pos) == default_pawn_rank){ // If on second/seventh rank
_pawn_add_if_not_blocked(pos+offset2, pns, board, pc, rc, free_to_double_move);
_pawn_add_if_not_blocked(pos+offset2, pos, pns, board, pc, rc, free_to_double_move);
}
// pos+offset1 is 1 rank up (or down) depending on color.
// Adding, or removing one will shift it over by one square, hence diagnoals.
_pawn_diag_add_if_not_blocked(pos+offset1+1, pns, board, pc, rc, en_passant);
_pawn_diag_add_if_not_blocked(pos+offset1-1, pns, board, pc, rc, en_passant);
_pawn_diag_add_if_not_blocked(pos+offset1+1, pos, pns, board, pc, rc, en_passant);
_pawn_diag_add_if_not_blocked(pos+offset1-1, pos, pns, board, pc, rc, en_passant);
}

@ -56,17 +56,39 @@ inline int get_pawn_st_flag(int mv){
inline int get_castle_flag(int mv){
return ((mv >> 24) & 0x1);
}
// Just trying to get working for now.
Rank get_rank(int pos){
if (pos >30 && pos < 39){
return Rank::RANK7;
} else if (pos > 80 && pos < 89){
return Rank::RANK2;
}
return Rank::RANK1;
}
inline bool is_valid_position(int position){
return DEFAULT_BOARD[position] != PieceType::INV;
}
inline int set_to_sq(int sq, int base){
return base + (sq << 7);
}
inline int set_to_sq(int sq){
return (sq << 7);
}
inline int make_move(int from){
return from;
}
inline int make_move(int from, int to){
return from + (to << 7);
}
inline int make_move(int from, int to, PieceType captured){
return from + (to << 7) + ((int) captured << 14);
}
inline int make_move(int from, int to, PieceType captured, PieceType promotion){
return from + (to << 7) + ((int) captured << 14) + ((int) promotion << 18);
}
inline int make_move(int from, int to, PieceType captured, PieceType promotion, int en_passant){
return from + (to << 7) + ((int) captured << 14) + ((int) promotion << 18) + (en_passant << 22);
}
inline int make_move(int from, int to, PieceType captured, PieceType promotion, int en_passant, int pawn_start){
return from + (to << 7) + ((int) captured << 14) + ((int) promotion << 18) + (en_passant << 22) + (pawn_start << 23);
}
inline int make_move(int from, int to, PieceType captured, PieceType promotion, int en_passant, int pawn_start, int castle_move){
return from + (to << 7) + ((int) captured << 14) + ((int) promotion << 18) + (en_passant << 22) + (pawn_start << 23) + (castle_move << 24);
}
#endif

@ -52,14 +52,14 @@ const std::array<std::string, 120> POSITION_STRING = {
};
enum Rank{
RANK1,
RANK2,
RANK3,
RANK4,
RANK5,
RANK6,
RANK8,
RANK7,
RANK8
RANK6,
RANK5,
RANK4,
RANK3,
RANK2,
RANK1
};
enum File {

@ -12,41 +12,13 @@
// TODO implement functions.h functions.
// NOTE tests will NOT run unless you implement these functions.
std::pair<int, int> pos_to_pair(Position pn){
int x,y = 0;
for (x = pn; x >= 8; x = x-8){
++y;
}
return std::make_pair(x, std::abs(y-7));
}
// TODO find way to make function arbitary to board size as to allow wide game chess variants. Do much later. Not important now.
Position pair_to_pos(std::pair<int, int> pr){
if (pr.first > 7 || pr.first < 0
|| pr.second > 7 || pr.second < 0) {
throw std::invalid_argument("Cannot use any pairs with values > 7 or < 0.");
}
int int_val = std::abs(pr.second - 7)*8 + pr.first;
if (int_val >= 0 && int_val < 64) {
return static_cast<Position>(int_val);
} else {
std::stringstream ss;
ss << "Something went terribly wrong. x and y < 8 && x and y >= 0 but abs(y-7)*8 + x < 0 or >= 64. It equalled: " << int_val;
throw std::invalid_argument(ss.str());
Rank get_rank(int pos){
int rank = 0;
while (pos >= 0){
pos -= 10;
rank++;
}
}
Position pair_to_pos(int x, int y){
return pair_to_pos(std::make_pair(x, y));
}
bool is_valid_position(std::pair<int, int> pos){
return (pos.first < 8 && pos.second < 8 &&
pos.first >= 0 && pos.second >=0);
}
bool is_valid_position(int x, int y){
return (x < 8 && x >= 0 &&
y < 8 && y >= 0);
return static_cast<Rank>(rank - 3);
}
bool is_white(PieceType pt){
@ -68,9 +40,6 @@ Color get_color(PieceType pt){
return Color::NO_COLOR;
}
Color get_color(int x, int y, std::array<PieceType, 120> const *board){
return get_color((*board)[pair_to_pos(x, y)]);
}
Color get_color(Position pn, std::array<PieceType, 120> const *board){
return get_color((*board)[pn]);
}
@ -110,23 +79,22 @@ std::unordered_set<int> get_poss_of(PieceType pt, std::array<PieceType, 120> con
return results;
}
void get_poss_of(PieceType pt, std::array<PieceType, 120>* board, std::vector<Position>* pns){
void get_poss_of(PieceType pt, std::array<PieceType, 120>* board, std::vector<int>* pns){
for (int pn = Position::A8; pn!=Position::H1; pn++){
if ((*board)[pn] == pt){
pns->push_back(static_cast<Position>(pn));
pns->push_back(pn);
}
}
}
//TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team.
void filter_checked_moves(int pos, PieceType pt, std::array<PieceType, 120> *board, std::unordered_set<int> *pns){
void filter_checked_moves(PieceType pt, std::array<PieceType, 120> *board, std::unordered_set<int> *pns){
PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING;
int my_king_pos = get_pos_of(my_king, board);
int attackers = 0;
for (auto p_pn= pns->begin(); p_pn!=pns->end();){
// Make move
int move_int = pos + (*p_pn >> 7);
std::array<PieceType, 120> moved_board = dumb_move(move_int, *board);
std::array<PieceType, 120> moved_board = dumb_move(*p_pn, *board);
// Get all piecetypes of other team
std::array<PieceType, 6> other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE;
bool checks_king = false;
@ -139,7 +107,7 @@ void filter_checked_moves(int pos, PieceType pt, std::array<PieceType, 120> *boa
//
// }
// \NEW CODE
std::vector<Position> psns;
std::vector<int> psns;
get_poss_of(other_p, &moved_board, &psns);
for (auto psn : psns){
std::unordered_set<int> other_moves;
@ -202,7 +170,7 @@ void get_all_moves(int pos, std::array<PieceType, 120>* board, std::unordered_se
break;
}
if (recursive){
filter_checked_moves(pos, pt, board, moves);
filter_checked_moves(pt, board, moves);
}
}
@ -224,7 +192,6 @@ std::array<PieceType, 120> dumb_move(int move, std::array<PieceType, 120> board)
std::unordered_set<int> get_to_squares(std::unordered_set<int> moves){
std::unordered_set<int> to_squares;
for (int move : moves){
std::cout << "SQ: " << get_to_sq(move) << "\n";
to_squares.insert(get_to_sq(move));
}
return to_squares;

@ -4,11 +4,6 @@
#include <vector>
#include <math.h>
// Convert pair of x y coordinates to Position enum member.
// If pr contains values above 7, or below 0 it will fail with an InvalidArgument exception.
Position pair_to_pos(std::pair<int, int> pr);
Position pair_to_pos(int x, int y);
// Returns a list of positions with PieceType pt
int get_pos_of(PieceType pt, std::array<PieceType, 120> const *board);
std::unordered_set<int> get_poss_of(PieceType pt, std::array<PieceType, 120> const *board);
@ -19,14 +14,14 @@ std::pair<int, int> pos_to_pair(Position pn);
// Check if int is a valid position in enum of Position
// Allow ints, and pairs to be checked.
bool is_valid_position(int pos);
bool is_valid_position(std::pair<int, int> pos);
bool is_valid_position(int x, int y);
// Returns rank enum value for given pos
Rank get_rank(int pos);
// Checks if given piece matches a certain color.
bool is_white(PieceType pt);
bool is_black(PieceType pt);
Color get_color(int x, int y, std::array<PieceType, 120> const *board);
Color get_color(Position pn, std::array<PieceType, 120> const *board);
Color get_color(PieceType pt);
// NO_COLOR returns NO_COLOR

@ -3,18 +3,9 @@
#include <sstream>
#include <unordered_set>
// For some retarted reason, I need to implement the printing of pairs, otherwise in the test outputs they show up as {?}
// Also override default printing for Positions so it prints the value (e.g. 32), then, in parenthasies, the location (e.g. A4).
// override default printing for Positions so it prints the value (e.g. 32), then, in parenthasies, the location (e.g. A4).
// Example: A4(32)
namespace Catch {
template<>
struct StringMaker<std::pair<int, int>> {
static std::string convert(std::pair<int, int> const& p){
std::stringstream ss;
ss << "{ " << p.first << ", " << p.second << " }";
return ss.str();
}
};
template<>
struct StringMaker<Position> {
static std::string convert(Position const& p){
@ -53,20 +44,20 @@ namespace Catch {
};
// This overrides vectors of positions. I want it to print a board with the positions that are selected so we can see a representation of what positions are selected.
template<>
struct StringMaker<std::unordered_set<Position>> {
static std::string convert(std::unordered_set<Position> const& uo_poss){
std::vector<Position> poss(uo_poss.begin(), uo_poss.end());
struct StringMaker<std::unordered_set<int>> {
static std::string convert(std::unordered_set<int> const& uo_poss){
std::vector<int> poss(uo_poss.begin(), uo_poss.end());
std::stringstream ss;
std::string files = " A B C D E F G H";
ss << "{ {" << std::endl;
ss << files << std::endl;
for (int i = 0; i < 8; ++i){
ss << 8-i << "|";
for (int j = 0; j < 8; ++j){
int index = (i*8)+j;
for (int i = 2; i < 10; ++i){
ss << i-1 << "|";
for (int j = 1; j < 9; ++j){
int index = (i*10)+j;
// This part loops through all positions in the list and checks if it contains the current index.
bool part_of_poss = false;
for (Position p : poss){
for (int p : poss){
if (index == p) {
part_of_poss = true;
break;
@ -76,7 +67,7 @@ namespace Catch {
// (if) part_of_poss ?(then) do this :(else) do that.
part_of_poss ? ss << "* " : ss << " ";
}
ss << "|" << 8-i;
ss << "|" << i-1;
ss << std::endl;
}
ss << files << std::endl;

@ -26,14 +26,16 @@ TEST_CASE("Test that the get_to_squares works, this is required!", "[get_to_squa
REQUIRE(get_to_squares(moves) == to_squares);
}
TEST_CASE("Test that get_rank() works)", "[get_rank]"){
CHECK(get_rank(Position::F3) == Rank::RANK3);
CHECK(get_rank(Position::G1) == Rank::RANK1);
}
TEST_CASE("Test that an unordered set of positions are returned when looking for a piece type through a board", "[get_pos_of]"){
CHECK(get_poss_of(PieceType::B_PAWN, &DEFAULT_BOARD) == B_PAWNS_SQUARES);
}
TEST_CASE("Test that a color can be gotten from a given square on the board", "[get_color]"){
CHECK(get_color(2, 7, &DUMB_MOVE_1) == Color::BLACK);
CHECK(get_color(3, 3, &DUMB_MOVE_1) == Color::NO_COLOR);
CHECK(get_color(2, 1, &DUMB_MOVE_1) == Color::WHITE);
CHECK(get_color(Position::C8, &DUMB_MOVE_1) == Color::BLACK);
CHECK(get_color(Position::F4, &DUMB_MOVE_1) == Color::NO_COLOR);
CHECK(get_color(Position::C2, &DUMB_MOVE_1) == Color::WHITE);
@ -66,45 +68,10 @@ TEST_CASE("Test that dumb moves can be made.", "[dumb_move]"){
CHECK(dumb_move(move_int, DEFAULT_BOARD) == DUMB_MOVE_1);
}
TEST_CASE("Test convert method to go from X and Y to board position", "[pair_to_pos]"){
CHECK(pair_to_pos(std::make_pair(2, 3)) == Position::C4);
CHECK(pair_to_pos(std::make_pair(7, 0)) == Position::H1);
CHECK(pair_to_pos(std::make_pair(0, 0)) == Position::A1);
CHECK(pair_to_pos(std::make_pair(7, 7)) == Position::H8);
CHECK_THROWS(pair_to_pos(std::make_pair(8, 2)));
CHECK_THROWS(pair_to_pos(std::make_pair(-1, 1)));
CHECK(pair_to_pos(2, 3) == Position::C4);
CHECK(pair_to_pos(7, 0) == Position::H1);
CHECK(pair_to_pos(0, 0) == Position::A1);
CHECK(pair_to_pos(7, 7) == Position::H8);
CHECK_THROWS(pair_to_pos(8, 2));
CHECK_THROWS(pair_to_pos(-1, 1));
}
TEST_CASE("Test convert method to go from a board position to an x and y", "[pos_to_pair]"){
CHECK(pos_to_pair(Position::A3) == std::make_pair(0, 2));
CHECK(pos_to_pair(Position::A4) == std::make_pair(0, 3));
CHECK(pos_to_pair(Position::B2) == std::make_pair(1, 1));
CHECK(pos_to_pair(Position::H8) == std::make_pair(7, 7));
}
TEST_CASE("Test that invalid position ints return false", "[is_valid_position]"){
CHECK(is_valid_position(0)); // 0=A8
CHECK(is_valid_position(63)); // 63=H1
CHECK_FALSE(is_valid_position(-1)); // -1 is out of bounds
CHECK_FALSE(is_valid_position(64)); // 64 is out of bounds
CHECK(is_valid_position(std::make_pair(0, 0))); // 0-7,0-7 should be valid
CHECK(is_valid_position(std::make_pair(7, 7)));
CHECK_FALSE(is_valid_position(std::make_pair(-1, 5))); // should fail
CHECK_FALSE(is_valid_position(std::make_pair(5, 8))); // should fail
CHECK(is_valid_position(0, 0)); // 0-7,0-7 should be valid
CHECK(is_valid_position(7, 7));
CHECK_FALSE(is_valid_position(-1, 5)); // should fail
CHECK_FALSE(is_valid_position(5, 8)); // should fail
CHECK(is_valid_position(Position::A8));
CHECK(is_valid_position(Position::H1));
CHECK_FALSE(is_valid_position(((int) Position::H1) + 1));
}
TEST_CASE("Test all possible and impossible moves for black pieces", "[get_all_moves][black]"){

Loading…
Cancel
Save