Return pseudo-valid moves. King check still WIP.

master
Tait Hoyem 5 years ago
parent 832ca16013
commit 805360bb4e

@ -1,64 +1,130 @@
#include "constants.h"
#include <unordered_set>
#include <iostream>
void _push_if_valid_pos(int x, int y, std::unordered_set<Position> *pns){
if (is_valid_position(x, y)){
pns->insert(pair_to_pos(x, y));
}
}
// This function returns true if the color of the piece on tile (x,y) is the Color c
bool _xy_is_color(int x, int y, std::array<PieceType, 64> board, Color c){
return c==Color::WHITE ? is_white(board[pair_to_pos(x, y)]) : is_black(board[pair_to_pos(x, y)]);
}
void _get_all_moves_rook(int x, int y, std::unordered_set<Position> *pns){
for (int offset=1; offset<8; offset++){
_push_if_valid_pos(x+offset, y, pns);
_push_if_valid_pos(x, y+offset, pns);
_push_if_valid_pos(x-offset, y, pns);
_push_if_valid_pos(x, y-offset, pns);
Color _rev_color(Color c){
return c==Color::WHITE ? Color::BLACK : Color::WHITE;
}
// 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 x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){
if (*is_not_blocked && is_valid_position(x, y)){
if (_xy_is_color(x, y, board, color_of_piece)){
*is_not_blocked = false;
} else if (_xy_is_color(x, y, board, color_of_opposite)){
pns->insert(pair_to_pos(x, y));
*is_not_blocked = false;
} else {
pns->insert(pair_to_pos(x, y));
}
}
}
// 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 x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color color_of_piece, Color color_of_opposite){
if (is_valid_position(x, y)){
if (_xy_is_color(x, y, board, color_of_piece)){
return;
} else {
pns->insert(pair_to_pos(x, y));
}
}
}
void _get_all_moves_bishop(int x, int y, std::unordered_set<Position> *pns){
// 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 x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color color_of_piece, Color color_of_opposite){
if (is_valid_position(x, y) && _xy_is_color(x, y, board, color_of_opposite)){
pns->insert(pair_to_pos(x, y));
}
}
// 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 x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked){
if (*is_not_blocked && is_valid_position(x, y)){
if (_xy_is_color(x, y, board, color_of_piece)){
*is_not_blocked = false;
} else if (_xy_is_color(x, y, board, color_of_opposite)){
*is_not_blocked = false;
} else {
pns->insert(pair_to_pos(x, y));
}
}
}
void _get_all_moves_rook(int x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color pc, Color rc){
bool* not_blocked_addx = new bool(true);
bool* not_blocked_minx = new bool(true);
bool* not_blocked_addy = new bool(true);
bool* not_blocked_miny = new bool(true);
for (int offset=1; offset<8; offset++){
_add_if_not_blocked(x+offset, y, pns, board, pc, rc, not_blocked_addx);
_add_if_not_blocked(x, y+offset, pns, board, pc, rc, not_blocked_addy);
_add_if_not_blocked(x-offset, y, pns, board, pc, rc, not_blocked_minx);
_add_if_not_blocked(x, y-offset, pns, board, pc, rc, not_blocked_miny);
}
}
void _get_all_moves_bishop(int x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color pc, Color rc){
bool* not_blocked_addx_addy = new bool(true);
bool* not_blocked_addx_miny = new bool(true);
bool* not_blocked_minx_addy = new bool(true);
bool* not_blocked_minx_miny = new bool(true);
for (int offset=1; offset<8; offset++){
int xpoff = x+offset;
int ypoff = y+offset;
int xnoff = x-offset;
int ynoff = y-offset;
_push_if_valid_pos(xpoff, ypoff, pns);
_push_if_valid_pos(xpoff, ynoff, pns);
_push_if_valid_pos(xnoff, ypoff, pns);
_push_if_valid_pos(xnoff, ynoff, pns);
_add_if_not_blocked(xpoff, ypoff, pns, board, pc, rc, not_blocked_addx_addy);
_add_if_not_blocked(xpoff, ynoff, pns, board, pc, rc, not_blocked_addx_miny);
_add_if_not_blocked(xnoff, ypoff, pns, board, pc, rc, not_blocked_minx_addy);
_add_if_not_blocked(xnoff, ynoff, pns, board, pc, rc, not_blocked_minx_miny);
}
}
void _get_all_moves_knight(int x, int y, std::unordered_set<Position> *pns){
void _get_all_moves_knight(int x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color pc, Color rc){
for (int xo=1;xo<=2;xo++){
int yo=(xo==1)?2:1;
_push_if_valid_pos(x+xo, y+yo, pns);
_push_if_valid_pos(x-xo, y+yo, pns);
_push_if_valid_pos(x+xo, y-yo, pns);
_push_if_valid_pos(x-xo, y-yo, pns);
_add_if_not_blocked(x+xo, y+yo, pns, board, pc, rc);
_add_if_not_blocked(x-xo, y+yo, pns, board, pc, rc);
_add_if_not_blocked(x+xo, y-yo, pns, board, pc, rc);
_add_if_not_blocked(x-xo, y-yo, pns, board, pc, rc);
}
}
void _get_all_moves_king(int x, int y, std::unordered_set<Position> *pns){
_push_if_valid_pos(x+1, y+1, pns);
_push_if_valid_pos(x+1, y-1, pns);
_push_if_valid_pos(x-1, y+1, pns);
_push_if_valid_pos(x-1, y-1, pns);
_push_if_valid_pos(x, y+1, pns);
_push_if_valid_pos(x, y-1, pns);
_push_if_valid_pos(x+1, y, pns);
_push_if_valid_pos(x-1, y, pns);
}
void _get_all_moves_w_pawn(int x, int y, std::unordered_set<Position> *pns){
_push_if_valid_pos(x, y+1, pns);
_push_if_valid_pos(x, y+2, pns);
_push_if_valid_pos(x+1, y+1, pns);
_push_if_valid_pos(x-1, y+1, pns);
}
void _get_all_moves_b_pawn(int x, int y, std::unordered_set<Position> *pns){
_push_if_valid_pos(x, y-1, pns);
_push_if_valid_pos(x, y-2, pns);
_push_if_valid_pos(x-1, y-1, pns);
_push_if_valid_pos(x+1, y-1, pns);
void _get_all_moves_king(int x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color pc, Color rc){
_add_if_not_blocked(x+1, y+1, pns, board, pc, rc);
_add_if_not_blocked(x+1, y-1, pns, board, pc, rc);
_add_if_not_blocked(x-1, y+1, pns, board, pc, rc);
_add_if_not_blocked(x-1, y-1, pns, board, pc, rc);
_add_if_not_blocked(x, y+1, pns, board, pc, rc);
_add_if_not_blocked(x, y-1, pns, board, pc, rc);
_add_if_not_blocked(x+1, y, pns, board, pc, rc);
_add_if_not_blocked(x-1, y, pns, board, pc, rc);
}
void _get_all_moves_pawn(int x, int y, std::unordered_set<Position> *pns, std::array<PieceType, 64> board, Color pc, Color rc){
// if it's white use different offsets, and pawn starting rank
int offset2 = pc==Color::WHITE?2:-2;
int offset1 = pc==Color::WHITE?1:-1;
int pawn_rank = pc==Color::WHITE?1:6;
bool *free_to_double_move = new bool(true);
_pawn_add_if_not_blocked(x, y+offset1, pns, board, pc, rc, free_to_double_move);
if (y == pawn_rank){ // If on second rank
_pawn_add_if_not_blocked(x, y+offset2, pns, board, pc, rc, free_to_double_move);
}
_pawn_diag_add_if_not_blocked(x+1, y+offset1, pns, board, pc, rc);
_pawn_diag_add_if_not_blocked(x-1, y+offset1, pns, board, pc, rc);
}

@ -22,6 +22,15 @@ enum PieceType {
B_KING
};
namespace Pieces {
const std::array<PieceType, 6> BLACK = {B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING};
const std::array<PieceType, 6> WHITE = {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING};
}
enum Color {
NO_COLOR, BLACK, WHITE
};
// Access with CHESS_CHARS[PieceType] to get the character for the piece.
const std::array<char, 13> CHESS_CHARS = {
' ',

@ -49,6 +49,36 @@ bool is_valid_position(int x, int y){
y < 8 && y >= 0);
}
bool is_white(PieceType pt){
for (auto pn : Pieces::WHITE){
if (pn == pt) return true;
}
return false;
}
bool is_black(PieceType pt){
for (auto pn : Pieces::BLACK){
if (pn == pt) return true;
}
return false;
}
Color get_color(PieceType pt){
if (is_white(pt)) return Color::WHITE;
if (is_black(pt)) return Color::BLACK;
return Color::NO_COLOR;
}
Color get_color(int x, int y, std::array<PieceType, 64> board){
return get_color(board[pair_to_pos(x, y)]);
}
Color get_color(Position pn, std::array<PieceType, 64> board){
return get_color(board[pn]);
}
Color rev_color(Color c){
if (c==Color::NO_COLOR) return Color::NO_COLOR;
return c==Color::WHITE?Color::BLACK:Color::WHITE;
}
std::unordered_set<Position> get_possible_movers(Position pn, std::array<PieceType, 64> board){
std::unordered_set<Position> pns = {Position::A1};
return pns;
@ -56,7 +86,8 @@ std::unordered_set<Position> get_possible_movers(Position pn, std::array<PieceTy
std::unordered_set<Position> get_possible_moves(Position pn, std::array<PieceType, 64> board){
std::unordered_set<Position> pns = {Position::A1};
return pns;
return get_all_moves(pn, board);
}
std::unordered_set<Position> get_all_moves(Position pn, std::array<PieceType, 64> board){
@ -64,33 +95,33 @@ std::unordered_set<Position> get_all_moves(Position pn, std::array<PieceType, 64
std::unordered_set<Position> pns;
int x = pos_to_pair(pn).first;
int y = pos_to_pair(pn).second;
Color color_of_piece = get_color(pt);
Color color_of_opponent = rev_color(color_of_piece);
switch(pt){
case PieceType::B_QUEEN:
case PieceType::W_QUEEN:
_get_all_moves_rook(x, y, &pns);
_get_all_moves_bishop(x, y, &pns);
_get_all_moves_rook(x, y, &pns, board, color_of_piece, color_of_opponent);
_get_all_moves_bishop(x, y, &pns, board, color_of_piece, color_of_opponent);
break;
case PieceType::B_ROOK:
case PieceType::W_ROOK:
_get_all_moves_rook(x, y, &pns);
_get_all_moves_rook(x, y, &pns, board, color_of_piece, color_of_opponent);
break;
case PieceType::B_BISHOP:
case PieceType::W_BISHOP:
_get_all_moves_bishop(x, y, &pns);
_get_all_moves_bishop(x, y, &pns, board, color_of_piece, color_of_opponent);
break;
case PieceType::B_KNIGHT:
case PieceType::W_KNIGHT:
_get_all_moves_knight(x, y, &pns);
_get_all_moves_knight(x, y, &pns, board, color_of_piece, color_of_opponent);
break;
case PieceType::B_KING:
case PieceType::W_KING:
_get_all_moves_king(x, y, &pns);
_get_all_moves_king(x, y, &pns, board, color_of_piece, color_of_opponent);
break;
case PieceType::B_PAWN:
_get_all_moves_b_pawn(x, y, &pns);
break;
case PieceType::W_PAWN:
_get_all_moves_w_pawn(x, y, &pns);
_get_all_moves_pawn(x, y, &pns, board, color_of_piece, color_of_opponent);
break;
default:
break;

@ -24,6 +24,18 @@ bool is_valid_position(int pos);
bool is_valid_position(std::pair<int, int> pos);
bool is_valid_position(int x, int y);
// 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, 64> board);
Color get_color(Position pn, std::array<PieceType, 64> board);
Color get_color(PieceType pt);
// NO_COLOR returns NO_COLOR
// WHITE returns BLACK
// BLACK returns WHITE
Color rev_color(Color c);
// Get all positions of pieces which can move to this square
// This may require helper functions for each individual peice.
// TODO rename to something less stupid.

@ -116,8 +116,7 @@ const std::array<PieceType, 64> B_PAWN_BOARD = {
};
const std::unordered_set<Position> B_PAWN_ALL_MOVES = {
E3, F3, G3,
F2
F3
};
const Position B_KNIGHT_SIDE1_POS = B7;
const std::array<PieceType, 64> B_KNIGHT_SIDE1_BOARD = {
@ -151,10 +150,10 @@ const std::unordered_set<Position> B_KING_SIDE1_ALL_MOVES = {
A7,B7
};
const Position B_PAWN_SIDE1_POS = A8;
const Position B_PAWN_SIDE1_POS = A7;
const std::array<PieceType, 64> B_PAWN_SIDE1_BOARD = {
B_PAWN, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
B_PAWN, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
@ -163,6 +162,5 @@ const std::array<PieceType, 64> B_PAWN_SIDE1_BOARD = {
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE
};
const std::unordered_set<Position> B_PAWN_SIDE1_ALL_MOVES = {
A7, B7,
A6
A6, A5
};

@ -160,8 +160,7 @@ const std::array<PieceType, 64> W_PAWN_BOARD = {
};
const std::unordered_set<Position> W_PAWN_ALL_MOVES = {
F6,
E5, F5, G5
F5
};
const Position W_PAWN_SIDE1_POS = A8;

@ -24,6 +24,17 @@ namespace Catch {
return ss.str();
}
};
// This override makes sure that Color enum variables are printed properly
template<>
struct StringMaker<Color> {
static std::string convert(Color const& c){
std::stringstream ss;
if (c==Color::WHITE) ss << "white";
if (c==Color::BLACK) ss << "black";
if (c==Color::NO_COLOR) ss << "N/A";
return ss.str();
}
};
// This prints all board comparisons in a readable fashion. Using the string name of the pieces, and newlines to seperate them.
template<>
struct StringMaker<std::array<PieceType, 64>> {
@ -99,6 +110,37 @@ const std::array<PieceType, 64> DUMB_MOVE_1 = {
W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK
};
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);
}
TEST_CASE("Test that a color can be gotten from a PieceType", "[get_color]"){
CHECK(get_color(PieceType::NONE) == Color::NO_COLOR);
CHECK(get_color(PieceType::W_KING) == Color::WHITE);
CHECK(get_color(PieceType::B_KING) == Color::BLACK);
}
TEST_CASE("Test reversing color", "[rev_color]"){
CHECK(rev_color(Color::NO_COLOR) == Color::NO_COLOR);
CHECK(rev_color(Color::WHITE) == Color::BLACK);
CHECK(rev_color(Color::BLACK) == Color::WHITE);
}
TEST_CASE("Test that is_black, and is_white are working", "[is_black][is_white]"){
CHECK(is_white(DUMB_MOVE_1[Position::A2]));
CHECK(is_black(DUMB_MOVE_1[Position::F7]));
CHECK_FALSE(is_white(DUMB_MOVE_1[Position::B2]));
CHECK_FALSE(is_black(DUMB_MOVE_1[Position::B5]));
// Test that NONE squares return false
CHECK_FALSE(is_white(DUMB_MOVE_1[Position::F4]));
CHECK_FALSE(is_black(DUMB_MOVE_1[Position::F4]));
}
TEST_CASE("Test that dumb moves can be made.", "[dumb_move]"){
CHECK(dumb_move(Position::B2, Position::B5, DEFAULT_BOARD) == DUMB_MOVE_1);
}
@ -151,12 +193,12 @@ TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){
}
TEST_CASE("Test where this piece may move to", "[get_possible_moves]"){
std::unordered_set<Position> white_right_knight_possible_moves = {Position::H3, Position::F3};
std::unordered_set<Position> black_A_pawn_possible_moves = {Position::A6,Position::A5};
CHECK(get_possible_moves(Position::G1, DEFAULT_BOARD) == white_right_knight_possible_moves);
CHECK(get_possible_moves(Position::A7, DEFAULT_BOARD) == black_A_pawn_possible_moves);
CHECK(get_possible_moves(Position::G1, DEFAULT_BOARD) == DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES);
CHECK(get_possible_moves(Position::A7, DEFAULT_BOARD) == DEFAULT_B_A_PAWN_POSSIBLE_MOVES);
CHECK(get_possible_moves(Position::A2, DEFAULT_BOARD) == DEFAULT_W_A_PAWN_POSSIBLE_MOVES);
CHECK(get_possible_moves(KNIGHT_BLOCKED1_POS, KNIGHT_BLOCKED1_BOARD) == KNIGHT_BLOCKED1_MOVES);
CHECK(get_possible_moves(BISHOP_BLOCKED1_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_MOVES);
CHECK(get_possible_moves(ROOK_BLOCKED1_POS, ROOK_BLOCKED1_BOARD) == ROOK_BLOCKED1_MOVES);
}
TEST_CASE("Test all possible and impossible moves for black pieces", "[get_all_moves][black]"){

@ -1,6 +1,21 @@
#include <unordered_set>
#include <constants.h>
/// This is for possible moves on a default board
const std::unordered_set<Position> DEFAULT_B_A_PAWN_POSSIBLE_MOVES = {
A6, A5
};
const std::unordered_set<Position> DEFAULT_W_A_PAWN_POSSIBLE_MOVES = {
A3, A4
};
const std::unordered_set<Position> DEFAULT_W_R_KNIGHT_POSSIBLE_MOVES = {
H3, F3
};
// EMPTY
const std::unordered_set<Position> DEFAULT_W_R_ROOK_POSSIBLE_MOVES = {};
// END of default selections
const Position KNIGHT_BLOCKED1_POS = B8;
const std::array<PieceType, 64> KNIGHT_BLOCKED1_BOARD = {
NONE, B_KNIGHT, NONE, NONE, NONE, NONE, NONE, NONE,
@ -41,3 +56,23 @@ const std::unordered_set<Position> BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING = {
D5
};
const Position BISHOP_BLOCKED1_KING_POS = F3;
const Position ROOK_BLOCKED1_POS = B7;
const std::array<PieceType, 64> ROOK_BLOCKED1_BOARD = {
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
NONE, W_ROOK, NONE , B_PAWN , NONE, B_KING, NONE, NONE,
NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE,
NONE, NONE , B_BISHOP, NONE, NONE, NONE, NONE, NONE,
NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE,
NONE, W_KING , NONE , NONE , NONE, NONE, NONE, NONE,
NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE,
NONE, NONE , NONE , NONE , NONE, NONE, NONE, NONE
};
// Should NOT include E-H2 or B3-1
const std::unordered_set<Position> ROOK_BLOCKED1_MOVES = {
B8,
A7, C7, D7,
B6,B5,B4
};

Loading…
Cancel
Save