You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
562 lines
19 KiB
562 lines
19 KiB
#include "bitwise.h"
|
|
#include "functions.h"
|
|
#include "all_moves_functions.cpp"
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <cmath>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
/*
|
|
*
|
|
* These functions use an int to pass a lot of information.
|
|
* The notation is like this:
|
|
* 0000 0000 0000 0000 0111 1111 -> position of piece
|
|
* 0000 0000 0000 0111 1000 0000 -> piece type
|
|
* 0000 0000 0111 1000 0000 0000 -> piece of opposite type (eg. opposite of W_KING, is B_KING; B_ROOK, W_ROOK etc...)
|
|
* 0000 0000 1000 0000 0000 0000 -> team of the piece (1=white, 0=black)
|
|
* 0111 1111 0000 0000 0000 0000 -> new position (if applicable)
|
|
*
|
|
**/
|
|
|
|
/*
|
|
* These functions also use an int for king info. This is so:
|
|
* a) I don't have to recompute the info each time I nedd it in a functoin.
|
|
* b) So that I don't have the overhead of a struct. (I know, "micro optimizations are the root of all evil", I can't help myself)
|
|
* The notation is as follows:
|
|
* 0000 0000 0000 0000 0111 1111 -> position of piece
|
|
* 0000 0000 0000 0111 1000 0000 -> piece type
|
|
* 0000 0011 1111 1000 0000 0000 -> opposite piece position
|
|
* 0011 1100 0000 0000 0000 0000 -> piece of opposite type
|
|
* 0100 0000 0000 0000 0000 0000 -> team of the piece (1=white, 0=black)
|
|
*/
|
|
|
|
inline int get_piece_pos(int pieceinfo){
|
|
return (pieceinfo & 0x7f);
|
|
}
|
|
inline int get_piece_type(int pieceinfo){
|
|
return ((pieceinfo << 7) & 0xf);
|
|
}
|
|
inline int get_opposite_piece_type(int pieceinfo){
|
|
return ((pieceinfo << 11) & 0xf);
|
|
}
|
|
// TO find out if white/black use:
|
|
// get_team_of_piece_type == Color::WHITE/BLACK
|
|
inline int get_team_of_piece_type(int pieceinfo){
|
|
return ((pieceinfo << 15) & 0x1);
|
|
}
|
|
inline int get_new_position_of_piece(int pieceinfo){
|
|
return ((pieceinfo << 16) & 0xf);
|
|
}
|
|
|
|
|
|
/* Move ints contain a lot of information as well. However, these are DIFFERENt from the other dense ints. Moves are universalyl passed by reference (&) to a vector of ints, whereas the above is passed only is 1 int by itself.
|
|
* Here is the notation for moves (although it is obscured by the make_move(), get_to/from_sq(), get_captured_pc() etc... functions.
|
|
*
|
|
* From (Position): 7 bits (2^7 == 128) possibilities
|
|
* To (Position): same as above
|
|
* Captured piece, if any: 4 bits (16) possibilities
|
|
* Promoted to, if any: 4 bits (16) possibilities
|
|
* en passant flag: 1 bit
|
|
* pawn starting move flag: 1 bit
|
|
* castle move flag: 1 bit
|
|
*
|
|
* 0000 0000 0000 0000 0000 0111 1111 -> From square position (& 0x7F)
|
|
* 0000 0000 0000 0011 1111 1000 0000 -> To square position (>> 7 & 0x7F)
|
|
* 0000 0000 0011 1100 0000 0000 0000 -> captured piece, if any (>> 14 & 0xF)
|
|
* 0000 0011 1100 0000 0000 0000 0000 -> if prmoted, what to? (>> 18 & 0xF)
|
|
* 0000 0100 0000 0000 0000 0000 0000 -> en passant (>> 22 &0x1)
|
|
* 0000 1000 0000 0000 0000 0000 0000 -> pawn starting move (>> 23 &0x1)
|
|
* 0001 0000 0000 0000 0000 0000 0000 -> castle move (>> 24 0x1)
|
|
* 0010 0000 0000 0000 0000 0000 0000 -> check flag (>> 25 &0x1)
|
|
* */
|
|
|
|
//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::vector<int> QUEEN_PIECE_OFFSETS = {-1, -10, 1, 10, -11, -9, 9, 11};
|
|
|
|
Rank get_rank(int pos){
|
|
int rank = 0;
|
|
while (pos >= 0){
|
|
pos -= 10;
|
|
rank++;
|
|
}
|
|
return static_cast<Rank>(rank - 3);
|
|
}
|
|
|
|
bool is_white(int pt){
|
|
for (auto pn : Pieces::WHITE){
|
|
if (pn == pt) return true;
|
|
}
|
|
return false;
|
|
}
|
|
bool is_black(int 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 pn, const 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;
|
|
}
|
|
PieceType rev_color(PieceType pt){
|
|
//return static_cast<PieceType>((~pt) & 0xf);
|
|
for (long unsigned int i=0; i!=Pieces::WHITE.size(); i++){
|
|
if (pt == Pieces::WHITE[i]){
|
|
return Pieces::BLACK[i];
|
|
}
|
|
}
|
|
for (long unsigned int i=0; i!=Pieces::BLACK.size(); i++){
|
|
if (pt == Pieces::BLACK[i]){
|
|
return Pieces::WHITE[i];
|
|
}
|
|
}
|
|
return PieceType::NONE;
|
|
}
|
|
|
|
std::vector<int> get_possible_movers(Position pn, const std::array<PieceType, 120>& board){
|
|
std::vector<int> pns = {Position::A1};
|
|
return pns;
|
|
}
|
|
|
|
int get_pos_of(PieceType pt, const std::array<PieceType, 120>& board){
|
|
for (int pn = Position::A8; pn!=Position::H1; pn++){
|
|
if (board[pn] == pt){
|
|
return pn;
|
|
}
|
|
}
|
|
return Position::NA;
|
|
}
|
|
|
|
std::vector<int> get_poss_of(PieceType pt, const std::array<PieceType, 120>& board){
|
|
std::vector<int> results;
|
|
for (int pn = Position::A8; pn!=Position::H1; pn++){
|
|
if (board[pn] == pt){
|
|
results.push_back(pn);
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
void get_poss_of(PieceType pt, const 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(pn);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool would_be_attacked(int pos, PieceType piece, const std::array<PieceType, 120>& board){
|
|
Color pc = get_color(piece);
|
|
auto other_pieces = pc==Color::WHITE?Pieces::BLACK:Pieces::WHITE;
|
|
for (PieceType opposite_color_piece : other_pieces){
|
|
PieceType same_color_piece = rev_color(opposite_color_piece);
|
|
std::vector<int> moves;
|
|
get_all_moves_as_if(pos, same_color_piece, board, moves, false);
|
|
for (int reverse_move : moves){
|
|
if (get_captured_pc(reverse_move) == opposite_color_piece){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
bool is_attacked(int pos, const std::array<PieceType, 120>& board){
|
|
return would_be_attacked(pos, board[pos], board);
|
|
}
|
|
|
|
bool king_checked(const std::array<PieceType, 120>& board, Color color_of_king){
|
|
PieceType king = color_of_king==WHITE?W_KING:B_KING;
|
|
int king_pos = get_pos_of(king, board);
|
|
return is_attacked(king_pos, board);
|
|
}
|
|
|
|
void add_checked_flags(PieceType pt, const std::array<PieceType, 120>& board, std::vector<int>& pns){
|
|
PieceType other_king = is_white(pt)?PieceType::B_KING:PieceType::W_KING;
|
|
int other_king_pos = get_pos_of(other_king, board);
|
|
// If the other team doesn't have a king, don't add any checked flags
|
|
if (other_king_pos == Position::NA){
|
|
return;
|
|
}
|
|
for (auto move_pn=pns.begin(); move_pn!=pns.end();){
|
|
std::array<PieceType, 120> moved_board;
|
|
dumb_move(*move_pn, board, moved_board);
|
|
if (is_attacked(other_king_pos, moved_board)){
|
|
*move_pn |= (1 << 25);
|
|
}
|
|
++move_pn;
|
|
}
|
|
}
|
|
|
|
//TODO: Make faster by running from king squar eonly, instead of running on every piece of opposite team.
|
|
void filter_checked_moves(PieceType pt, const std::array<PieceType, 120>& board, std::vector<int>& pns){
|
|
PieceType my_king = is_white(pt)?PieceType::W_KING:PieceType::B_KING;
|
|
int my_king_pos = get_pos_of(my_king, board);
|
|
bool remove_all_castles = false;
|
|
// If this team doesn't have a king, don't do anything, jsut return.
|
|
if (my_king_pos == Position::NA){
|
|
return;
|
|
}
|
|
for (auto p_pn= pns.begin(); p_pn!=pns.end();){
|
|
if (get_castle_flag(*p_pn) == 1){
|
|
// If removing all castle flags is triggered
|
|
// (by being in check)
|
|
// remove all of them.
|
|
if (remove_all_castles){
|
|
p_pn = pns.erase(p_pn);
|
|
++p_pn;
|
|
break;
|
|
}
|
|
// TODO: Make this more effecient.
|
|
// There is no way in hell, this is as complicated as it seems.
|
|
// If moved left
|
|
// Queenside
|
|
if ((get_from_sq(*p_pn) - get_to_sq(*p_pn)) > 0){
|
|
if(would_be_attacked(get_to_sq(*p_pn), my_king, board) ||
|
|
would_be_attacked(get_to_sq(*p_pn)+1, my_king, board)){
|
|
p_pn = pns.erase(p_pn);
|
|
} else {
|
|
++p_pn;
|
|
break;
|
|
}
|
|
// Kingside
|
|
} else {
|
|
if(would_be_attacked(get_to_sq(*p_pn), my_king, board) ||
|
|
would_be_attacked(get_to_sq(*p_pn)-1, my_king, board)){
|
|
p_pn = pns.erase(p_pn);
|
|
} else {
|
|
++p_pn;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
// if it is a king, that is in check
|
|
// remove all castle moves
|
|
if ((pt == PieceType::W_KING ||
|
|
pt == PieceType::B_KING) &&
|
|
is_attacked(get_from_sq(*p_pn), board)){
|
|
remove_all_castles = true;
|
|
}
|
|
// Make move
|
|
std::array<PieceType, 120> moved_board;
|
|
dumb_move(*p_pn, board, moved_board);
|
|
// This is for when the king is the same piece that is moving.
|
|
// If this is the case, reset to king position to the new position given by the get_to_sq() of the move.
|
|
if (pt == my_king){
|
|
my_king_pos = get_to_sq(*p_pn);
|
|
}
|
|
|
|
if (is_attacked(my_king_pos, moved_board)){
|
|
p_pn = pns.erase(p_pn);
|
|
} else {
|
|
++p_pn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void _get_all_moves_as_if_ray_type(int pos, std::vector<int> offsets, std::vector<int>& moves, const std::array<PieceType, 120>& board, Color color_of_piece, Color color_of_opponent){
|
|
for (int offset : offsets){
|
|
for (int times = 1; times < 8; ++times){
|
|
int true_offset = pos+(offset*times);
|
|
if (get_color(board[true_offset]) == color_of_opponent){
|
|
moves.push_back(make_move(pos, true_offset, board[true_offset]));
|
|
break;
|
|
} else if (get_color(board[true_offset]) == color_of_piece ||
|
|
board[true_offset] == PieceType::INV){
|
|
break;
|
|
} else {
|
|
moves.push_back(make_move(pos, true_offset, board[true_offset]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void _get_all_moves_as_if_not_ray(int pos, std::vector<int> offsets, std::vector<int>& moves, const std::array<PieceType, 120>& board, Color color_of_piece, Color color_of_opponent){
|
|
for (int offset : offsets){
|
|
int true_offset = pos+offset;
|
|
if (board[true_offset] == PieceType::NONE ||
|
|
get_color(board[true_offset]) == color_of_opponent){
|
|
moves.push_back(make_move(pos, true_offset, board[true_offset]));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// WARNING: This function depends on the order of the moves being correct.
|
|
// The last two king moves MUST be for the king's position +1, and -1 respectively.
|
|
// TODO finish function
|
|
void _get_all_castle_moves(int pos, int castle_perms, std::vector<int>& moves, const std::array<PieceType, 120>& board, Color color_of_piece, Color color_of_opponent){
|
|
if (color_of_piece == Color::WHITE){
|
|
|
|
} else {
|
|
|
|
}
|
|
}
|
|
|
|
void get_all_moves_as_if(int pos, PieceType pt, const std::array<PieceType, 120>& board, std::vector<int>& moves, bool recursive, int en_passant, int castle_perms){
|
|
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_as_if_ray_type(pos, QUEEN_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent);
|
|
//_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_as_if_ray_type(pos, ROOK_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent);
|
|
//_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_as_if_ray_type(pos, BISHOP_PIECE_OFFSETS, 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_KNIGHT:
|
|
case PieceType::W_KNIGHT:
|
|
_get_all_moves_as_if_not_ray(pos, KNIGHT_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent);
|
|
//_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_as_if_not_ray(pos, KING_PIECE_OFFSETS, moves, board, color_of_piece, color_of_opponent);
|
|
// if (castle_perms != 0){
|
|
// _get_all_castle_moves();
|
|
// }
|
|
_get_all_moves_king(pos, moves, board, color_of_piece, color_of_opponent, castle_perms);
|
|
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(pt, board, moves);
|
|
add_checked_flags(pt, board, moves);
|
|
}
|
|
}
|
|
|
|
void get_all_moves(int pos, const std::array<PieceType, 120>& board, std::vector<int>& moves, bool recursive, int en_passant, int castle_perms){
|
|
get_all_moves_as_if(pos, board[pos], board, moves, recursive, en_passant, castle_perms);
|
|
}
|
|
std::vector<int> get_all_moves(int pos, const std::array<PieceType, 120>& board, bool recursive, int en_passant, int castle_perms){
|
|
std::vector<int> moves = {};
|
|
get_all_moves_as_if(pos, board[pos], board, moves, recursive, en_passant, castle_perms);
|
|
return moves;
|
|
}
|
|
|
|
void dumb_move(int move, const std::array<PieceType, 120>& board, std::array<PieceType, 120>& new_board){
|
|
std::copy(std::begin(board), std::end(board), std::begin(new_board));
|
|
int en_passant_flag = get_en_pass_flag(move);
|
|
int castle_flag = get_castle_flag(move);
|
|
int from = get_from_sq(move);
|
|
int to = get_to_sq(move);
|
|
PieceType piece = new_board[from];
|
|
if (en_passant_flag == 1) {
|
|
int diff = to-from;
|
|
int other_pawn_pos = 0;
|
|
if (diff == -11){
|
|
other_pawn_pos = from-1;
|
|
} else if (diff == -9){
|
|
other_pawn_pos = from+1;
|
|
} else if (diff == 11){
|
|
other_pawn_pos = from+1;
|
|
} else if (diff == 9){
|
|
other_pawn_pos = from-1;
|
|
}
|
|
new_board[other_pawn_pos] = PieceType::NONE;
|
|
new_board[to] = piece;
|
|
new_board[from] = PieceType::NONE;
|
|
} else if(castle_flag == 1){
|
|
int diff = to-from;
|
|
int rook_from_pos = 0;
|
|
int rook_to_pos = 0;
|
|
// If castling queenside
|
|
if (diff == -2){
|
|
rook_from_pos = to-2;
|
|
rook_to_pos = from-1;
|
|
// If caslting kingside
|
|
} else if (diff == 2){
|
|
rook_from_pos = to+1;
|
|
rook_to_pos = from+1;
|
|
}
|
|
PieceType rook_pt = new_board[rook_from_pos];
|
|
new_board[rook_from_pos] = PieceType::NONE;
|
|
new_board[rook_to_pos] = rook_pt;
|
|
new_board[from] = PieceType::NONE;
|
|
new_board[to] = piece;
|
|
} else {
|
|
new_board[to] = piece;
|
|
new_board[from] = PieceType::NONE;
|
|
}
|
|
}
|
|
std::array<PieceType, 120> dumb_move(int pos, const std::array<PieceType, 120>& board){
|
|
std::array<PieceType, 120> new_board = {};
|
|
dumb_move(pos, board, new_board);
|
|
return new_board;
|
|
}
|
|
|
|
void _filter_unneeded_squares(std::vector<int>& moves, int piecetype, int origin){
|
|
for (auto move_pn=moves.begin(); move_pn!=moves.end();){
|
|
if (get_captured_pc(*move_pn) == piecetype &&
|
|
get_to_sq(*move_pn) != origin){
|
|
++move_pn;
|
|
} else {
|
|
move_pn = moves.erase(move_pn);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
void _non_pawn_disambiguate(int from, int to, int piecetype, const std::vector<int>& moves, std::string& disambig){
|
|
if (moves.size() == 1){
|
|
disambig = POSITION_STRING[from][0];
|
|
int other_from = get_to_sq(moves.at(0));
|
|
int min_from = other_from<from?other_from:from;
|
|
int max_from = other_from>from?other_from:from;
|
|
// If the remainder of the difference divided by 10 is 0
|
|
// they are on the same file.
|
|
// Use rank to disambiguate
|
|
if ((max_from-min_from) % 10 == 0){
|
|
disambig = POSITION_STRING[from][1];
|
|
}
|
|
} else if (moves.size() > 1){
|
|
disambig = POSITION_STRING[from];
|
|
}
|
|
}
|
|
|
|
std::string to_notation(int move, const std::array<PieceType, 120>& board){
|
|
int to = get_to_sq(move);
|
|
int from = get_from_sq(move);
|
|
|
|
// This can be ran right away due to the simplicity of the notation.
|
|
if (get_castle_flag(move) == 1){
|
|
return to-from<0 ? "O-O-O" : "O-O";
|
|
}
|
|
|
|
PieceType piecetype = board[from];
|
|
std::string from_string = POSITION_STRING[from];
|
|
int captured_piece = get_captured_pc(move);
|
|
int promoting_to = get_promoted_to_pc(move);
|
|
// Blank if not pawn
|
|
// file if pawn and capture move
|
|
std::string pawn_file = "";
|
|
// Blank if pawn
|
|
// otherwise N/B/R/Q/K corresponding to each piece
|
|
// same for black and white
|
|
std::string piece_character = "";
|
|
// Blank if not a capture
|
|
// x if a capture move
|
|
std::string capture_character = "";
|
|
// Blank if not en passant move
|
|
// otherwise e.p.
|
|
std::string en_passant = "";
|
|
// Black if no check,
|
|
// + if check
|
|
// # if checkmate
|
|
std::string check = "";
|
|
// Blank if only this piece can move to the to square
|
|
// include file (a-h) if another piece can move to the to square
|
|
// includes rank (1-8) if pieces have same file
|
|
// includes both (f)(r) if 2+ identical piece can move to the to square
|
|
std::string disambig = "";
|
|
// Blank if not a pawn promotion move.
|
|
// Otherwise is equal to "=P/N/B/R/Q".
|
|
std::string promotion;
|
|
auto other_pieces = is_white(piecetype)?Pieces::BLACK:Pieces::WHITE;
|
|
|
|
if (captured_piece != PieceType::NONE){
|
|
capture_character = "x";
|
|
// Comment #6
|
|
// if a pawn is capturing, have the disambiguation be the pawn's file
|
|
// stored in a seperate variable because pawn disabiguation by file happens at the start of a notation. For example:
|
|
// exf4 as opposed to Qh1xf4
|
|
if (piecetype == PieceType::W_PAWN ||
|
|
piecetype == PieceType::B_PAWN){
|
|
pawn_file = POSITION_STRING[from][0];
|
|
}
|
|
}
|
|
// Pawns do not require this, as their file is ALWAYS enough to identify them,
|
|
// and the file is always speicified on a pawn capture.
|
|
// (See comment #6)
|
|
if (piecetype != PieceType::W_PAWN &&
|
|
piecetype != PieceType::B_PAWN){
|
|
// Simulated a piece of the same type, and opposite color moving from the to square
|
|
// to check if any other pieces can also move here.
|
|
// Basically it searches to see if there are duplicate pieces which can move to the same spot.
|
|
// and stores any duplicates in the other_moves variable.
|
|
PieceType opposite_piece = rev_color(piecetype);
|
|
std::vector<int> other_moves = {};
|
|
get_all_moves_as_if(to, opposite_piece, board, other_moves, false);
|
|
// This takes out any mention of other squares involing blank pieces, or any peices that do not invole the current one.
|
|
_filter_unneeded_squares(other_moves, piecetype, from);
|
|
piece_character = CHESS_CHARS_INSENSITIVE[piecetype];
|
|
_non_pawn_disambiguate(from, to, piecetype, other_moves, disambig);
|
|
}
|
|
if (get_en_pass_flag(move) == 1){
|
|
en_passant = "e.p.";
|
|
}
|
|
if (get_check_flag(move) == 1){
|
|
check = "+";
|
|
// This checks if the other team has any valid moves.
|
|
// If not, the check sign changes to a hashtag (#).
|
|
std::array<PieceType, 120> moved_board;
|
|
dumb_move(move, board, moved_board);
|
|
|
|
std::vector<int> other_moves = {};
|
|
get_all_moves_for_pieces(other_pieces, moved_board, other_moves);
|
|
if (other_moves.empty()){
|
|
check = "#";
|
|
}
|
|
}
|
|
// If promoting, add an equals sign and the piece promoting to.
|
|
if (promoting_to != PieceType::NONE){
|
|
promotion += "=";
|
|
promotion += CHESS_CHARS_INSENSITIVE[promoting_to];
|
|
}
|
|
// end of checking for multiple pieces
|
|
std::string result = "";
|
|
result += pawn_file + piece_character + disambig + capture_character + POSITION_STRING[to] + en_passant + promotion + check;
|
|
return result;
|
|
}
|
|
|
|
void get_all_moves_for_pieces(std::array<PieceType, 6> pieces, const 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, true, en_passant, castle_perms);
|
|
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() );
|
|
}
|
|
}
|
|
|