Almost done. Check checks not working properly.

master
Tait Hoyem 5 years ago
parent 0270636ee2
commit e8c884f5a8

@ -69,23 +69,29 @@ void _add_if_not_blocked(int pos, int from, std::vector<int> *pns, std::array<Pi
}
}
void _add_pawn_promotions(int from, int to, PieceType capture, Color color_of_piece, std::vector<int> *pns){
if (color_of_piece == Color::WHITE){
pns->push_back(make_move(from, to, capture, PieceType::W_KNIGHT));
pns->push_back(make_move(from, to, capture, PieceType::W_BISHOP));
pns->push_back(make_move(from, to, capture, PieceType::W_ROOK));
pns->push_back(make_move(from, to, capture, PieceType::W_QUEEN));
} else {
pns->push_back(make_move(from, to, capture, PieceType::B_KNIGHT));
pns->push_back(make_move(from, to, capture, PieceType::B_BISHOP));
pns->push_back(make_move(from, to, capture, PieceType::B_ROOK));
pns->push_back(make_move(from, to, capture, PieceType::B_QUEEN));
}
}
// 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, int from, std::vector<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, int en_passant, int promoting){
if (is_valid_position(pos)){
// Theoretically this is not run with en_passant because those flags should NEVER overlap, but if it does, my tests will alert me.
if (_xy_is_color(pos, board, color_of_opposite)){
if (promoting){
if (color_of_piece == Color::WHITE){
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_KNIGHT));
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_BISHOP));
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_ROOK));
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::W_QUEEN));
} else {
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_KNIGHT));
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_BISHOP));
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_ROOK));
pns->push_back(make_move(from, pos, (*board)[pos], PieceType::B_QUEEN));
}
_add_pawn_promotions(from, pos, (*board)[pos], color_of_piece, pns);
} else {
pns->push_back(make_move(from, pos, (*board)[pos]));
}
@ -94,19 +100,23 @@ void _pawn_diag_add_if_not_blocked(int pos, int from, std::vector<int> *pns, std
// ...otherwise get to the right (-1)
int captured_pos = from-pos>0?from+1:from-1;
pns->push_back(make_move(from, pos, (*board)[captured_pos], PieceType::NONE, 1));
}
}
}
}
// This is a specialized functions for the pawn's inability to take going forward.
// Notice the lack of push_backion where there usually is when (x,y) is a different color.
void _pawn_add_if_not_blocked(int pos, int from, std::vector<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, bool double_move){
void _pawn_add_if_not_blocked(int pos, int from, std::vector<int> *pns, std::array<PieceType, 120> *board, Color color_of_piece, Color color_of_opposite, bool *is_not_blocked, bool double_move, bool promoted){
if (*is_not_blocked){
if ((*board)[pos] != PieceType::NONE ||
(*board)[pos] == PieceType::INV){
*is_not_blocked = false;
} else if (double_move){
pns->push_back(make_move(from, pos, PieceType::NONE, PieceType::NONE, 0, 1));
} else if (promoted){
_add_pawn_promotions(from, pos, PieceType::NONE, color_of_piece, pns);
} else {
double_move?pns->push_back(make_move(from, pos, (*board)[pos], PieceType::NONE, 0, 1)):pns->push_back(make_move(from, pos, (*board)[pos]));
pns->push_back(make_move(from, pos, (*board)[pos]));
}
}
}
@ -222,9 +232,9 @@ void _get_all_moves_pawn(int pos, std::vector<int> *pns, std::array<PieceType, 1
int is_promoting_if_forward = get_rank(pos) == promotion_rank?1:0;
bool *free_to_double_move = new bool(true);
_pawn_add_if_not_blocked(pos+offset1, pos, pns, board, pc, rc, free_to_double_move, false);
_pawn_add_if_not_blocked(pos+offset1, pos, pns, board, pc, rc, free_to_double_move, false, is_promoting_if_forward);
if (get_rank(pos) == default_pawn_rank){ // If on second/seventh rank
_pawn_add_if_not_blocked(pos+offset2, pos, pns, board, pc, rc, free_to_double_move, true);
_pawn_add_if_not_blocked(pos+offset2, pos, pns, board, pc, rc, free_to_double_move, true, is_promoting_if_forward);
}
// pos+offset1 is 1 rank up (or down) depending on color.
// Adding, or removing one will shift it over by one square, hence diagnoals.

@ -1,6 +1,7 @@
#include <iostream>
#include <stdio.h>
#include <string>
#include "bitwise.h"
#include "constants.h"
#include "functions.h"
#include "color.hpp"
@ -37,26 +38,21 @@ int main(){
vector<int> all_moves = {};
vector<string> all_moves_notation = {};
int en_passant_square = 0;
int castle_perms = 0xF;
bool reset_en_passant = false;
while (true){
all_moves = {};
all_moves_notation = {};
array<PieceType, 6> my_pieces = whos_turn==Color::WHITE?Pieces::WHITE:Pieces::BLACK;
// Gets all moves for color who's turn it is.
if (whos_turn == Color::WHITE){
get_all_white_moves(&my_board, &all_moves);
} else {
get_all_black_moves(&my_board, &all_moves);
}
get_all_moves_for_pieces(my_pieces, &my_board, &all_moves, en_passant_square, castle_perms);
print_board(my_board);
// Gets a string from cin called input
string input;
getline(cin, input);
// Quits
if (input == "q"){
break;
}
// Gets all moves and stores them in a notation list
// TODO make into own function
bool move_exec = false;
@ -70,15 +66,65 @@ int main(){
break;
}
}
// Quits
if (input == "q"){
break;
} else if (input == "l"){
cout << "Listing moves: \n";
for (string notation : all_moves_notation){
cout << notation << " ";
}
cout << endl;
continue;
}
// If the input did not match any legal move.
if (!move_exec){
cout << "Invalid move!" << std::endl;
cout << "These are the only valid moves: ";
for (string notation : all_moves_notation){
cout << notation << " ";
}
cout << endl;
continue;
// If the input did match a legal move.
} else {
int moving_from_pos = get_from_sq(move_to_exec);
int moving_piece = my_board[moving_from_pos];
// Depending on move, change castle perms, or en_passant square
if (get_pawn_st_flag(move_to_exec) == 1){
int en_pass_offset = whos_turn==Color::WHITE?10:-10;
en_passant_square = get_to_sq(move_to_exec)+en_pass_offset;
reset_en_passant = false;
}
if (moving_piece == W_ROOK){
if (moving_from_pos == Position::A1 &&
(castle_perms & CastlePerms::WQS == 1)){
castle_perms - CastlePerms::WQS;
} else if (moving_from_pos == Position::H1 &&
(castle_perms & CastlePerms::WKS == 1)){
castle_perms - CastlePerms::WKS;
}
} else if (moving_piece == B_ROOK){
if (moving_from_pos == Position::H8 &&
(castle_perms & CastlePerms::BKS == 1)){
castle_perms - CastlePerms::BKS;
} else if (moving_from_pos == Position::A8 &&
(castle_perms & CastlePerms::BQS == 1)){
castle_perms - CastlePerms::BQS;
}
}
// This will keep the en passant sqaure for one whole turn.
if (reset_en_passant){
en_passant_square = 0;
reset_en_passant = false;
}
if (en_passant_square != 0){
cout << "En passant move at: " << POSITION_STRING[en_passant_square] << endl;
reset_en_passant = true;
}
// This reverses the whos_turn variable.
// and runs the move on the my_board variable.
my_board = dumb_move(move_to_exec, my_board);
whos_turn = rev_color(whos_turn);
}

@ -1,6 +1,8 @@
#include "bitwise.h"
#include "functions.h"
#include "all_moves_functions.cpp"
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <stdexcept>
@ -376,21 +378,18 @@ std::string to_notation(int move, std::array<PieceType, 120> *board){
return ss.str();
}
void get_all_white_moves(std::array<PieceType, 120> *board, std::vector<int> *moves){
for (PieceType pt : Pieces::WHITE){
void get_all_moves_for_pieces(std::array<PieceType, 6> pieces, std::array<PieceType, 120> *board, std::vector<int> *moves, int en_passant, int castle_perms){
for (PieceType pt : pieces){
for (int pos_of : get_poss_of(pt, board)){
std::vector<int> local_moves = {};
get_all_moves_as_if(pos_of, pt, board, &local_moves);
get_all_moves_as_if(pos_of, pt, board, &local_moves, true, en_passant, castle_perms);
moves->insert(moves->end(), local_moves.begin(), local_moves.end());
}
}
}
void get_all_black_moves(std::array<PieceType, 120> *board, std::vector<int> *moves){
for (PieceType pt : Pieces::BLACK){
for (int pos_of : get_poss_of(pt, board)){
std::vector<int> local_moves = {};
get_all_moves_as_if(pos_of, pt, board, &local_moves);
moves->insert(moves->end(), local_moves.begin(), local_moves.end());
}
}
// From StackOverflow (https://stackoverflow.com/questions/5891610/how-to-remove-certain-characters-from-a-string-in-c#5891643)
void remove_chars_from_string(std::string &str, std::string charsToRemove ) {
for ( unsigned int i = 0; i < charsToRemove.length(); ++i ) {
str.erase( remove(str.begin(), str.end(), charsToRemove.at(i)), str.end() );
}
}

@ -64,5 +64,5 @@ bool is_checked(int pos, std::array<PieceType, 120> board);
std::string to_notation(int move, std::array<PieceType, 120> *board);
// These functions are just for printing (for now) so they are not included in the tests.
void get_all_white_moves(std::array<PieceType, 120> *board, std::vector<int> *moves);
void get_all_black_moves(std::array<PieceType, 120> *board, std::vector<int> *moves);
void get_all_moves_for_pieces(std::array<PieceType, 6> pieces, std::array<PieceType, 120> *board, std::vector<int> *moves, int en_passant, int castle_perms);
void remove_chars_from_string(std::string &std, std::string to_remove);

@ -269,5 +269,14 @@ TEST_CASE("Do extra (random board tests) on notation and move generation", "[to_
CHECK(get_notations(knight_moves, EXTRA1_BOARD) == KNIGHT_EXTRA1_NOTATION);
CHECK(get_notations(knight_moves2, EXTRA2_BOARD) == KNIGHT_EXTRA2_NOTATION);
CHECK(get_to_squares(knight_moves2) == KNIGHT_EXTRA2_MOVES);
}
TEST_CASE("Test for promotions on empty squares", "[get_all_moves]"){
auto pawn_prom = get_all_moves(PAWN_PROM_BLANK_POS, PAWN_PROM_BLANK_BOARD);
CHECK(get_notations(pawn_prom, PAWN_PROM_BLANK_BOARD) == PAWN_PROM_BLANK_NOTATION);
}
TEST_CASE("Tests for check on square of queenside capture", "[get_all_moves]"){
auto cannot_queenside = get_all_moves(CASTLE_CHECK1_POS, CASTLE_CHECK1_BOARD);
CHECK(get_notations(cannot_queenside, CASTLE_CHECK1_BOARD) == CASTLE_CHECK1_NOTATION);
}

@ -735,7 +735,7 @@ const std::array<PieceType, 120> EXTRA1_BOARD = {
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV
};
const std::vector<std::string> KNIGHT_EXTRA1_NOTATION = {
"Nh3", "Nf3", "Ne4", "Ne6", "Nf7", "Nxh7"
"Ne6", "Nf7", "Nxh7", "Ne4", "Nf3", "Nh3"
};
const int KNIGHT_EXTRA2_POS = D4;
@ -754,10 +754,10 @@ const std::array<PieceType, 120> EXTRA2_BOARD = {
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV
};
const std::vector<int> KNIGHT_EXTRA2_MOVES = {
B3, F3, F5, E6, C6, B5
B5, C6, E6, F5, B3, F3
};
const std::vector<std::string> KNIGHT_EXTRA2_NOTATION = {
"Nb5", "Nc6", "Nxe6", "Nf5", "Nb3", "Ndf3"
};
const std::array<PieceType, 120> EXTRA3_BOARD = {
@ -775,3 +775,47 @@ const std::array<PieceType, 120> EXTRA3_BOARD = {
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV
};
// Tests that a pawn has promotion moves, even if there are only blank sqaures to move to.
const int PAWN_PROM_BLANK_POS = D7;
const std::array<PieceType, 120> PAWN_PROM_BLANK_BOARD = {
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV,
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, W_PAWN, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, B_ROOK, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, NONE, INV,
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV,
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV
};
const std::vector<std::string> PAWN_PROM_BLANK_NOTATION = {
"d8=N", "d8=B", "d8=R", "d8=Q"
};
// This is another test for castling.
// As of the writing of this, the castling works even if the king is in check
// in the square it moves to... WTF?
const int CASTLE_CHECK1_POS = E8;
const std::array<PieceType, 120> CASTLE_CHECK1_BOARD = {
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV,
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV,
INV, B_ROOK, NONE, NONE, NONE, B_KING, B_PAWN, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, B_PAWN, B_PAWN, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, W_BISHOP, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, INV,
INV, NONE, NONE, NONE, NONE, NONE, NONE, W_KING, NONE, INV,
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV,
INV, INV, INV, INV, INV, INV, INV, INV, INV, INV
};
const std::vector<std::string> CASTLE_CHECK1_NOTATION = {
"Kd8"
};

Loading…
Cancel
Save