parent
0422768eb0
commit
20c87a3988
@ -0,0 +1,185 @@
|
||||
#include "bitwise_constants.h"
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
|
||||
const std::array<int, 4> ROOK_PIECE_OFFSETS = {-1, -10, 1, 10};
|
||||
const std::array<int, 4> BISHOP_PIECE_OFFSETS = {-11, -9, 9, 11};
|
||||
const std::array<int, 8> KNIGHT_PIECE_OFFSETS = {-12, -21, -19, -8, 8, 12, 19, 21};
|
||||
const std::array<int, 8> KING_PIECE_OFFSETS = {-11, -10, -9, -1, 1, 9, 10, 11};
|
||||
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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 pos, 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;
|
||||
} else {
|
||||
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);
|
||||
*is_not_blocked = false;
|
||||
} else {
|
||||
pns->insert(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 (is_valid_position(pos)){
|
||||
if (_xy_is_color(pos, board, color_of_piece)){
|
||||
return;
|
||||
} else {
|
||||
pns->insert(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){
|
||||
if (is_valid_position(pos) && (_xy_is_color(pos, board, color_of_opposite) ||
|
||||
pos == en_passant)){
|
||||
pns->insert(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){
|
||||
if (*is_not_blocked){
|
||||
if (is_valid_position(pos)){
|
||||
*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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _get_all_moves_rook(int pos, std::unordered_set<int> *pns, std::array<PieceType, 120>* board, Color pc, Color rc){
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 pos, std::unordered_set<int> *pns, std::array<PieceType, 120>* board, Color pc, Color rc){
|
||||
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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
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;
|
||||
_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 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, not_blocked);
|
||||
}
|
||||
/*
|
||||
for (int xo=1;xo<=2;xo++){
|
||||
int yo=(xo==1)?2:1;
|
||||
_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 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, not_blocked);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
_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 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 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);
|
||||
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);
|
||||
}
|
||||
// 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);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#include "bitwise_constants.h"
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
|
||||
int main(){
|
||||
for (int y=0;y<12;y++){
|
||||
for (int x=0;x<10;x++){
|
||||
int cord = (y*10) + x;
|
||||
int val = DEFAULT_BOARD[cord];
|
||||
val==-1?std::cout << '!':std::cout << CHESS_CHARS[val];
|
||||
std::cout << std::hex << y << "," << x << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
#ifndef BITWISE_CONSTANTS_H
|
||||
#define BITWISE_CONSTANTS_H
|
||||
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
|
||||
enum Color {
|
||||
NO_COLOR,
|
||||
WHITE,
|
||||
BLACK
|
||||
};
|
||||
|
||||
enum PieceType {
|
||||
NONE,
|
||||
B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
|
||||
W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING
|
||||
};
|
||||
namespace Pieces{
|
||||
const std::array<PieceType, 6> WHITE = {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING};
|
||||
const std::array<PieceType, 6> BLACK = {B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING};
|
||||
}
|
||||
enum Position {
|
||||
NA=-1,
|
||||
A8=21, B8, C8, D8, E8, F8, G8, H8,
|
||||
A7=31, B7, C7, D7, E7, F7, G7, H7,
|
||||
A6=41, B6, C6, D6, E6, F6, G6, H6,
|
||||
A5=51, B5, C5, D5, E5, F5, G5, H5,
|
||||
A4=61, B4, C4, D4, E4, F4, G4, H4,
|
||||
A3=71, B3, C3, D3, E3, F3, G3, H3,
|
||||
A2=81, B2, C2, D2, E2, F2, G2, H2,
|
||||
A1=91, B1, C1, D1, E1, F1, G1, H1
|
||||
};
|
||||
|
||||
enum Rank{
|
||||
RANK1,
|
||||
RANK2,
|
||||
RANK3,
|
||||
RANK4,
|
||||
RANK5,
|
||||
RANK6,
|
||||
RANK7,
|
||||
RANK8
|
||||
};
|
||||
|
||||
enum File {
|
||||
FILE1,
|
||||
FILE2,
|
||||
FILE3,
|
||||
FILE4,
|
||||
FILE5,
|
||||
FILE6,
|
||||
FILE7,
|
||||
FILE8
|
||||
};
|
||||
|
||||
std::array<int, 120> DEFAULT_BOARD = {
|
||||
NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
|
||||
NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
|
||||
NA, B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK, NA,
|
||||
NA, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, NA,
|
||||
NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA,
|
||||
NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA,
|
||||
NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA,
|
||||
NA, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NA,
|
||||
NA, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, NA,
|
||||
NA, W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK, NA,
|
||||
NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
|
||||
NA,NA,NA,NA,NA,NA,NA,NA,NA,NA
|
||||
};
|
||||
|
||||
char CHESS_CHARS[13] = {
|
||||
' ',
|
||||
'P', 'N', 'B', 'R', 'Q', 'K',
|
||||
'p', 'n', 'b', 'r', 'q', 'k'
|
||||
};
|
||||
#endif
|
@ -0,0 +1,207 @@
|
||||
#include "bitwise.h"
|
||||
#include "bitwise_functions.h"
|
||||
#include "all_moves_bitwise_functions.cpp"
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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, 120> board){
|
||||
return get_color(board[pair_to_pos(x, y)]);
|
||||
}
|
||||
Color get_color(Position pn, std::array<PieceType, 120> 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<int> get_possible_movers(Position pn, std::array<PieceType, 120> board){
|
||||
std::unordered_set<int> pns = {Position::A1};
|
||||
return pns;
|
||||
}
|
||||
|
||||
std::unordered_set<int> get_possible_moves(Position pn, std::array<PieceType, 120> board){
|
||||
std::unordered_set<int> pns = {Position::A1};
|
||||
get_all_moves(pn, &board, &pns);
|
||||
return pns;
|
||||
}
|
||||
|
||||
int get_pos_of(PieceType pt, std::array<PieceType, 120> *board){
|
||||
for (int pn = Position::A8; pn!=Position::H1; pn++){
|
||||
if ((*board)[pn] == pt){
|
||||
return pn;
|
||||
}
|
||||
}
|
||||
return Position::NA;
|
||||
}
|
||||
|
||||
void get_poss_of(PieceType pt, std::array<PieceType, 120>* board, std::vector<Position>* pns){
|
||||
for (int pn = Position::A8; pn!=Position::H1; pn++){
|
||||
if ((*board)[pn] == pt){
|
||||
pns->push_back(static_cast<Position>(pn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team.
|
||||
void filter_checked_moves(Position pn, 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 = pn + (*p_pn >> 6);
|
||||
std::array<PieceType, 120> moved_board = dumb_move(move_int, board);
|
||||
// Get all piecetypes of other team
|
||||
std::array<PieceType, 6> other_team = is_white(pt)?Pieces::BLACK:Pieces::WHITE;
|
||||
bool checks_king = false;
|
||||
// go through each piece of other team
|
||||
for (PieceType other_p : other_team) {
|
||||
checks_king = false;
|
||||
// For every place the piecetype is
|
||||
// NEW CODE
|
||||
// for (Position psn : get_all_moves(my_king_pos, moved_board, false)){
|
||||
//
|
||||
// }
|
||||
// \NEW CODE
|
||||
std::vector<Position> psns;
|
||||
get_poss_of(other_p, &moved_board, &psns);
|
||||
for (auto psn : psns){
|
||||
std::unordered_set<int> other_moves;
|
||||
get_all_moves(psn, &moved_board, &other_moves, false);
|
||||
// for every position the piece can mvoe to
|
||||
for (int cp : other_moves){
|
||||
if (get_to_sq(cp) == my_king_pos){
|
||||
checks_king = true;
|
||||
attackers++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checks_king){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checks_king){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checks_king){
|
||||
p_pn = pns->erase(p_pn);
|
||||
} else {
|
||||
++p_pn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void get_all_moves(Position pn, std::array<PieceType, 120>* board, std::unordered_set<int>* moves, bool recursive, int en_passant){
|
||||
PieceType pt = (*board)[pn];
|
||||
int pos = pn;
|
||||
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(pos, moves, board, color_of_piece, color_of_opponent);
|
||||
_get_all_moves_bishop(pos, moves, board, color_of_piece, color_of_opponent);
|
||||
break;
|
||||
case PieceType::B_ROOK:
|
||||
case PieceType::W_ROOK:
|
||||
_get_all_moves_rook(pos, moves, board, color_of_piece, color_of_opponent);
|
||||
break;
|
||||
case PieceType::B_BISHOP:
|
||||
case PieceType::W_BISHOP:
|
||||
_get_all_moves_bishop(pos, moves, board, color_of_piece, color_of_opponent);
|
||||
break;
|
||||
case PieceType::B_KNIGHT:
|
||||
case PieceType::W_KNIGHT:
|
||||
_get_all_moves_knight(pos, moves, board, color_of_piece, color_of_opponent);
|
||||
break;
|
||||
case PieceType::B_KING:
|
||||
case PieceType::W_KING:
|
||||
_get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent);
|
||||
break;
|
||||
case PieceType::B_PAWN:
|
||||
case PieceType::W_PAWN:
|
||||
_get_all_moves_pawn(pos, moves, board, color_of_piece, color_of_opponent, en_passant);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (recursive){
|
||||
filter_checked_moves(pn, pt, board, moves);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<PieceType, 120> dumb_move(Position from, Position to, std::array<PieceType, 120> board){
|
||||
PieceType piece = board[from];
|
||||
board[to] = piece;
|
||||
board[from] = PieceType::NONE;
|
||||
return board;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
#include "bitwise_constants.h"
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#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
|
||||
std::vector<Position> get_pos_of(PieceType pt, std::array<PieceType, 120>);
|
||||
|
||||
// Convert a Position number into a pair of x y coordiinates
|
||||
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);
|
||||
|
||||
// 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> *board);
|
||||
Color get_color(Position pn, std::array<PieceType, 120> *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.
|
||||
void get_possible_movers(Position pn, std::array<PieceType, 120> *pt,std::unordered_set<int> *moves);
|
||||
|
||||
// Get all possible moved for piece in Position pn.
|
||||
// This may require helper functions for each individual piece.
|
||||
void get_possible_moves(Position pn, std::array<PieceType, 120> *pt,std::unordered_set<int> *moves);
|
||||
|
||||
// Get all moves for piece in Position pn.
|
||||
void get_all_moves(Position pn, std::array<PieceType, 120> *pt,std::unordered_set<int> *moves, bool recursive=true, int en_passant=Position::NA);
|
||||
|
||||
// Dumb function to do board moves.
|
||||
// Does not check if move is valid, just does it.
|
||||
std::array<PieceType, 120> dumb_move(int move, std::array<PieceType, 120> *board);
|
@ -0,0 +1,157 @@
|
||||
#include "catch.hpp"
|
||||
#include "test_boards.h"
|
||||
#include "valid_moves.h"
|
||||
#include "custom_printing.cpp"
|
||||
#include <sstream>
|
||||
#include <bitwise_functions.h>
|
||||
|
||||
|
||||
const std::array<PieceType, 64> TEST_MOVES = {
|
||||
W_QUEEN, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, B_KNIGHT
|
||||
};
|
||||
|
||||
const std::array<PieceType, 64> DUMB_MOVE_1 = {
|
||||
B_ROOK, B_KNIGHT, B_BISHOP, B_QUEEN, B_KING, B_BISHOP, B_KNIGHT, B_ROOK,
|
||||
B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN, B_PAWN,
|
||||
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
|
||||
NONE, W_PAWN, NONE, NONE, NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
|
||||
W_PAWN, NONE, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN, W_PAWN,
|
||||
W_ROOK, W_KNIGHT, W_BISHOP, W_QUEEN, W_KING, W_BISHOP, W_KNIGHT, W_ROOK
|
||||
};
|
||||
|
||||
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_pos_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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
TEST_CASE("Test what pieces may move where functon", "[get_possible_movers]"){
|
||||
std::unordered_set<Position> H1_possible_movers = {Position::H2, Position::G1};
|
||||
CHECK(get_possible_movers(BISHOP_BLOCKED1_KING_POS, BISHOP_BLOCKED1_BOARD) == BISHOP_BLOCKED1_CAN_MOVE_TO_B_KING);
|
||||
CHECK(get_possible_movers(Position::H3, DEFAULT_BOARD) == H1_possible_movers);
|
||||
}
|
||||
|
||||
TEST_CASE("Test where this piece may move to", "[get_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]"){
|
||||
CHECK(get_all_moves(B_KING_POS, B_KING_BOARD) == B_KING_ALL_MOVES);
|
||||
CHECK(get_all_moves(B_QUEEN_POS, B_QUEEN_BOARD) == B_QUEEN_ALL_MOVES);
|
||||
CHECK(get_all_moves(B_ROOK_POS, B_ROOK_BOARD) == B_ROOK_ALL_MOVES);
|
||||
CHECK(get_all_moves(B_BISHOP_POS, B_BISHOP_BOARD) == B_BISHOP_ALL_MOVES);
|
||||
CHECK(get_all_moves(B_KNIGHT_POS, B_KNIGHT_BOARD) == B_KNIGHT_ALL_MOVES);
|
||||
CHECK(get_all_moves(B_PAWN_POS, B_PAWN_BOARD) == B_PAWN_ALL_MOVES);
|
||||
}
|
||||
TEST_CASE("Test all possible and impossible moves for whtie pieces", "[get_all_moves][white]"){
|
||||
CHECK(get_all_moves(W_KING_POS, W_KING_BOARD) == W_KING_ALL_MOVES);
|
||||
CHECK(get_all_moves(W_QUEEN_POS, W_QUEEN_BOARD) == W_QUEEN_ALL_MOVES);
|
||||
CHECK(get_all_moves(W_ROOK_POS, W_ROOK_BOARD) == W_ROOK_ALL_MOVES);
|
||||
CHECK(get_all_moves(W_BISHOP_POS, W_BISHOP_BOARD) == W_BISHOP_ALL_MOVES);
|
||||
CHECK(get_all_moves(W_KNIGHT_POS, W_KNIGHT_BOARD) == W_KNIGHT_ALL_MOVES);
|
||||
CHECK(get_all_moves(W_PAWN_POS, W_PAWN_BOARD) == W_PAWN_ALL_MOVES);
|
||||
}
|
||||
|
||||
TEST_CASE("Test all moves for white in edge cases.", "[get_all_moves][white]"){
|
||||
CHECK(get_all_moves(W_KNIGHT_SIDE1_POS, W_KNIGHT_SIDE1_BOARD) == W_KNIGHT_SIDE1_ALL_MOVES);
|
||||
CHECK(get_all_moves(W_KING_SIDE1_POS, W_KING_SIDE1_BOARD) == W_KING_SIDE1_ALL_MOVES);
|
||||
CHECK(get_all_moves(W_PAWN_SIDE1_POS, W_PAWN_SIDE1_BOARD) == W_PAWN_SIDE1_ALL_MOVES);
|
||||
}
|
||||
TEST_CASE("Test all moves for black in edge cases.", "[get_all_moves][black]"){
|
||||
CHECK(get_all_moves(B_KNIGHT_SIDE1_POS, B_KNIGHT_SIDE1_BOARD) == B_KNIGHT_SIDE1_ALL_MOVES);
|
||||
CHECK(get_all_moves(B_KING_SIDE1_POS, B_KING_SIDE1_BOARD) == B_KING_SIDE1_ALL_MOVES);
|
||||
CHECK(get_all_moves(B_PAWN_SIDE1_POS, B_PAWN_SIDE1_BOARD) == B_PAWN_SIDE1_ALL_MOVES);
|
||||
}
|
||||
|
||||
TEST_CASE("Test that moves that put king in check are not returned", "[get_all_moves]"){
|
||||
CHECK(get_all_moves(ROOK_CHECK_TEST_POS, ROOK_CHECK_TEST_BOARD) == ROOK_CHECK_TEST_MOVES);
|
||||
CHECK(get_all_moves(PAWN_CHECK_TEST_POS, PAWN_CHECK_TEST_BOARD) == PAWN_CHECK_TEST_MOVES);
|
||||
CHECK(get_all_moves(PAWN_DIAG_TEST1_POS, PAWN_DIAG_TEST1_BOARD) == PAWN_DIAG_TEST1_MOVES);
|
||||
}
|
||||
|
||||
TEST_CASE("Tests for en pessant squares.", "[get_all_moves]"){
|
||||
CHECK(get_all_moves(EN_PASSANT_TEST_POS, EN_PASSANT_TEST_BOARD, false, EN_PASSANT_SQUARE) == EN_PASSANT_TEST_MOVES);
|
||||
CHECK(get_all_moves(NO_EN_PASSANT_TEST_POS, NO_EN_PASSANT_TEST_BOARD) == NO_EN_PASSANT_TEST_MOVES);
|
||||
}
|
Loading…
Reference in new issue