306 lines
10 KiB
C++
306 lines
10 KiB
C++
#ifndef INCLUDE_GUARD_MOVE_H
|
|
#define INCLUDE_GUARD_MOVE_H
|
|
|
|
#include <iterator>
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
|
|
#include "utils.h"
|
|
#include "types.h"
|
|
|
|
class Move {
|
|
public:
|
|
using base_type = uint64_t;
|
|
|
|
private:
|
|
base_type _bits;
|
|
|
|
public:
|
|
Move() = default; // required by MoveList
|
|
// Reverse of cast to base_type
|
|
Move(base_type bits) : _bits{bits} { };
|
|
|
|
explicit Move(Index from, Index to)
|
|
: Move(from, to, static_cast<enum piece>(0)) { };
|
|
explicit Move(Index from, Index to, enum piece promotion)
|
|
: Move(static_cast<enum piece>(0), static_cast<enum piece>(0), from, to,
|
|
static_cast<enum piece>(0), promotion) { };
|
|
explicit Move(enum piece color, enum piece piece, Index from, Index to,
|
|
enum piece victim)
|
|
: Move(color, piece, from, to, victim, static_cast<enum piece>(0)) { };
|
|
// General Move constructor
|
|
explicit Move(enum piece color, enum piece piece, Index from, Index to,
|
|
enum piece victim, enum piece promotion)
|
|
: _bits{static_cast<base_type>(
|
|
( color << 21)
|
|
| ( victim << 18)
|
|
| ( piece << 15)
|
|
| (promotion << 12)
|
|
| ( to << 6)
|
|
| from
|
|
)}
|
|
{
|
|
assert(((color == white)
|
|
|| (color == black)));
|
|
assert(((victim == knight)
|
|
|| (victim == bishop)
|
|
|| (victim == rook)
|
|
|| (victim == queen)
|
|
|| (victim == pawn)
|
|
|| !victim));
|
|
assert(((piece == knight)
|
|
|| (piece == bishop)
|
|
|| (piece == rook)
|
|
|| (piece == queen)
|
|
|| (piece == pawn)
|
|
|| (piece == king)
|
|
|| !piece));
|
|
assert(((promotion == knight)
|
|
|| (promotion == bishop)
|
|
|| (promotion == rook)
|
|
|| (promotion == queen)
|
|
|| !promotion));
|
|
assert(( to < 64));
|
|
assert((from < 64));
|
|
};
|
|
|
|
Index from() const { return _bits & 63U; }
|
|
Index to() const { return (_bits >> 6) & 63U; }
|
|
enum piece promote() const {
|
|
return static_cast<enum piece>((_bits >> 12) & 7U);
|
|
}
|
|
enum piece piece() const {
|
|
return static_cast<enum piece>((_bits >> 15) & 7U);
|
|
}
|
|
enum piece victim() const {
|
|
return static_cast<enum piece>((_bits >> 18) & 7U);
|
|
}
|
|
enum piece color() const {
|
|
return static_cast<enum piece>((_bits >> 21) & 7U);
|
|
}
|
|
|
|
uint32_t score() const {
|
|
return static_cast<uint32_t>(_bits >> 32);
|
|
}
|
|
|
|
static constexpr uint32_t killerScore[2] = { 4096U, 4095U };
|
|
void setScore(const uint32_t val) {
|
|
constexpr base_type mask = (1ULL << 22) - 1ULL;
|
|
_bits = (_bits & mask) | (static_cast<base_type>(val) << 32);
|
|
}
|
|
uint32_t calcScore() const {
|
|
const uint32_t mvv_lva = ((victim() << 3) + (7U - piece()));
|
|
const bool winning = victim() > piece();
|
|
// add 128 to ensure the PST values are positive
|
|
const Index t = color() == white ? to() : 63 - to();
|
|
const Index f = color() == white ? from() : 63 - from();
|
|
const uint32_t pst = PSQT[piece()][t] - PSQT[piece()][f] + 128;
|
|
|
|
return ((static_cast<bool>(victim()) * mvv_lva) << (14 + winning * 6)) + pst;
|
|
}
|
|
// Allows to be cast to the base type (as number)
|
|
operator base_type() { return _bits; }
|
|
|
|
bool operator!() const { return this->from() == this->to(); }
|
|
// Comparison of <from><to>[<promotion>] part of the move. Everything else
|
|
// is redundent and allows simple parse move routine (use Board::isLegal
|
|
// for move legality test and augmentation)
|
|
bool operator==(const Move& rhs) const {
|
|
constexpr base_type mask = (1ULL << 22) - 1ULL;
|
|
return (_bits & mask) == (rhs._bits & mask);
|
|
}
|
|
bool operator!=(const Move& rhs) const {
|
|
constexpr base_type mask = (1ULL << 22) - 1ULL;
|
|
return (_bits & mask) != (rhs._bits & mask);
|
|
}
|
|
|
|
// default sort order is decreasing (for scored moves the best move first)
|
|
friend bool operator<(const Move& lhs, const Move& rhs) {
|
|
return lhs._bits > rhs._bits;
|
|
}
|
|
};
|
|
|
|
class MoveList {
|
|
private:
|
|
static constexpr unsigned _max_size = 256;
|
|
unsigned _size;
|
|
Move _moves[_max_size]; // apparently, 218 are the max nr. of moves
|
|
|
|
public:
|
|
MoveList() : _size{0} { };
|
|
|
|
// Copy Constructor
|
|
MoveList(const MoveList& moveList) : _size{moveList._size} {
|
|
assert(_size <= _max_size);
|
|
|
|
std::copy(moveList._moves, moveList._moves + _size, _moves);
|
|
}
|
|
// Copy Assignement Operator
|
|
MoveList& operator=(const MoveList&) = default;
|
|
|
|
unsigned size() const { return _size; };
|
|
bool empty() const { return !static_cast<bool>(_size); };
|
|
static constexpr unsigned max_size() { return _max_size; };
|
|
void clear() { _size = 0; };
|
|
Move* data() { return _moves; };
|
|
const Move* data() const { return _moves; };
|
|
|
|
template <typename... Args>
|
|
void emplace_back(Args&&... args) {
|
|
assert(_size < _max_size);
|
|
|
|
_moves[_size++] = Move(std::forward<Args>(args)...);
|
|
}
|
|
|
|
void push_back(const Move& move) {
|
|
assert(_size < _max_size);
|
|
|
|
_moves[_size++] = move;
|
|
}
|
|
|
|
void append(const MoveList& list) {
|
|
assert((_size + list._size) < _max_size);
|
|
|
|
for (unsigned i = 0; i < list._size; i++) {
|
|
_moves[_size++] = list._moves[i];
|
|
}
|
|
}
|
|
|
|
bool contains(const Move& move) const {
|
|
for (unsigned i = 0; i < _size; i++) {
|
|
if (_moves[i] == move) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Searches for an occurence of `move` in the list and places the `move` as
|
|
* the first element in the list. If the provided `move` is not an element
|
|
* no opperation is performed and `false` will be returned.
|
|
*
|
|
* @param move a move to be searched for and placed as first element.
|
|
* @return `true` if `move` is found and placed as first element,
|
|
* `false` otherwise.
|
|
*/
|
|
bool move_front(const Move& move) {
|
|
for (unsigned i = 0; i < _size; i++) {
|
|
if (_moves[i] == move) {
|
|
std::swap(_moves[0], _moves[i]);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Move& operator[](unsigned i) { return _moves[i]; }
|
|
const Move& operator[](unsigned i) const { return _moves[i]; }
|
|
|
|
struct MoveIter {
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = Move;
|
|
using pointer = value_type*;
|
|
using reference = value_type&;
|
|
|
|
MoveIter(pointer ptr) : _ptr{ptr} { };
|
|
|
|
// Dereference operators
|
|
reference operator*() { return *_ptr; };
|
|
pointer operator->() { return _ptr; };
|
|
|
|
// Arithmetic operators
|
|
MoveIter& operator++() { _ptr++; return *this; };
|
|
MoveIter operator++(int) {
|
|
MoveIter copy = *this; ++(*this); return copy;
|
|
};
|
|
MoveIter& operator--() { _ptr--; return *this; };
|
|
MoveIter operator--(int) {
|
|
MoveIter copy = *this; --(*this); return copy;
|
|
};
|
|
MoveIter& operator+=(int i) {
|
|
_ptr += i; return *this;
|
|
};
|
|
friend MoveIter operator+(MoveIter it, int i) { return (it += i); };
|
|
MoveIter& operator-=(int i) {
|
|
_ptr -= i; return *this;
|
|
};
|
|
friend MoveIter operator-(MoveIter it, int i) { return (it -= i); };
|
|
|
|
friend difference_type operator-(const MoveIter& lhs, const MoveIter& rhs) {
|
|
return lhs._ptr - rhs._ptr;
|
|
};
|
|
|
|
// Comparison operators
|
|
friend bool operator==(const MoveIter& lhs, const MoveIter& rhs) {
|
|
return lhs._ptr == rhs._ptr;
|
|
};
|
|
friend bool operator<=(const MoveIter& lhs, const MoveIter& rhs) {
|
|
return lhs._ptr <= rhs._ptr;
|
|
};
|
|
friend bool operator>=(const MoveIter& lhs, const MoveIter& rhs) {
|
|
return lhs._ptr >= rhs._ptr;
|
|
};
|
|
friend bool operator!=(const MoveIter& lhs, const MoveIter& rhs) {
|
|
return lhs._ptr != rhs._ptr;
|
|
};
|
|
friend bool operator<(const MoveIter& lhs, const MoveIter& rhs) {
|
|
return lhs._ptr < rhs._ptr;
|
|
};
|
|
friend bool operator>(const MoveIter& lhs, const MoveIter& rhs) {
|
|
return lhs._ptr > rhs._ptr;
|
|
};
|
|
|
|
|
|
private:
|
|
pointer _ptr;
|
|
};
|
|
|
|
MoveIter begin() { return MoveIter(_moves); };
|
|
MoveIter end() { return MoveIter(_moves + _size); };
|
|
|
|
struct ConstMoveIter {
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = const Move;
|
|
using pointer = const value_type*;
|
|
using reference = const value_type&;
|
|
|
|
ConstMoveIter(pointer ptr) : _ptr{ptr} { };
|
|
|
|
// Dereference operators
|
|
reference operator*() { return *_ptr; };
|
|
pointer operator->() { return _ptr; };
|
|
|
|
// Arithmetic operators
|
|
ConstMoveIter& operator++() { _ptr++; return *this; };
|
|
ConstMoveIter operator++(int) {
|
|
ConstMoveIter copy = *this; ++(*this); return copy;
|
|
};
|
|
ConstMoveIter& operator--() { _ptr--; return *this; };
|
|
ConstMoveIter operator--(int) {
|
|
ConstMoveIter copy = *this; --(*this); return copy;
|
|
};
|
|
ConstMoveIter& operator+=(int i) {
|
|
_ptr += i; return *this;
|
|
};
|
|
|
|
// Comparison operators
|
|
friend bool operator==(const ConstMoveIter& lhs, const ConstMoveIter& rhs) {
|
|
return lhs._ptr == rhs._ptr;
|
|
};
|
|
friend bool operator!=(const ConstMoveIter& lhs, const ConstMoveIter& rhs) {
|
|
return lhs._ptr != rhs._ptr;
|
|
};
|
|
|
|
private:
|
|
pointer _ptr;
|
|
};
|
|
|
|
ConstMoveIter begin() const { return ConstMoveIter(_moves); };
|
|
ConstMoveIter end() const { return ConstMoveIter(_moves + _size); };
|
|
};
|
|
|
|
#endif /* INCLUDE_GUARD_MOVE_H */
|