I'm new

Code: Select all
#pragma once/*Position.hpp*/
#include"fwd.hpp"
#include"Move.hpp"
namespace Chess{
class Position{/*компактное представление позиции (нет дублирования информации)*/
/*поля доски могут быть пустыми и\или занятыми. маска Exist выделяет занятые
поля. фигуры на занятых полях могут быть активными и\или нет. маска Active
выделяет поля активных фигур среди занятых. поля могут быть заняты пешкой и\или
не пешкой. маска Pawns выделяет поля пешек среди занятых.*/
friend Chess::Search; friend Chess::Node;
using BitBoard = u64;
BitBoard Exist;/*маска занятых полей без учёта королей*/
/*активный и пассивный короли не входят в маски*/
struct __attribute__((packed)) KingInfo{Cell Place:s3*2;u8 HasCastling:2;}Kings[2];
Move::type MoveType;/*тип последнего полу-хода*/
u8 reserved;/*можно использовать как продолжение поля NBRQ*/
/*размеры масок равны количеству установленных в единицу бит в Exist*/
using OccupedFields = u32;/*дополнительные битовые атрибуты занятых полей*/
/*TODO: объединить эти две маскм в одну*/
OccupedFields Active;/*маска активной стороны.*/
OccupedFields Pawns;/*маска пешек независимо от стороны.*/
enum:u8{N,B,R,Q};/*порядок типов фигур*/
static_assert(Queen-Knight==Q-N);enum:u8{nbrq=N|B|R|Q};
/*позиция не рассчитана на 19+ не пешек*/
using NonPawnTag = u32;
NonPawnTag NBRQ;/*маска фигур. каждые 2 бита определяют тип фигуры*/
public:
static Cell constexpr EnPassantCell[1<<(s3+2)]{
/*поля прохода для двойных ходов чёрных пешек и рокировок*/
A6,B6,C6,D6,E6,F6,G6,H6, F8,D8, O64,O64,O64,O64,O64,O64,
/*поля прохода для двойных ходов белых пешек и рокировок*/
A3,B3,C3,D3,E3,F3,G3,H3, F1,D1, O64,O64,O64,O64,O64,O64};
#ifdef INVARIANT
void INVARIANT()const noexcept;
#endif
void swap(Position&)noexcept;/*=default*/
[[nodiscard]]HashKey constexpr hash()const noexcept;/**/
[[nodiscard]]bool constexpr operator==(Position const&)const noexcept;/*=default;*/
[[nodiscard]]bool constexpr operator!=(Position const&)const noexcept;/*=default;*/
constexpr Position()noexcept=default;/*invalid empty position*/
Position(Position const&,Move)noexcept;
void constexpr setStart()noexcept;
void constexpr inspect(auto)const noexcept;/*without kings*/
struct FieldInfo{u8 piece:3;u8 active:1;};
FieldInfo constexpr inspect(Cell)const noexcept;
Piece erase(Cell const)noexcept;
void insert(Cell const,Piece const)noexcept;/*active piece*/
[[nodiscard]] Inline KingInfo aKing(u8 n=0)const noexcept{return Kings[n];}
[[nodiscard]] Inline Move::type aMove()const noexcept{return MoveType;}
u8 make(Move[])const noexcept;/*create moves without considering the check. return "mate" when taking the opponent's king*/
Position& change_side()noexcept;/*apply null-move*/
/*pawn material*/
/*short constexpr pawns_diff()const noexcept{return __builtin_popcount(Pawns&Active)-__builtin_popcount(Pawns&~Active);}*/
void flipV()noexcept;
void flipH()noexcept;
void norm()noexcept;/*приведение с учётом симметрий к виду (активный король справа-внизу)*/
};
[[nodiscard]] Inline bool Position::operator==(Position const&p)const noexcept/*=default;*/
{auto a=&Exist,b=&p.Exist;return*a==*b&&a[1]==b[1]&&a[2]==b[2];}
[[nodiscard]] Inline bool Position::operator!=(Position const&p)const noexcept/*=default;*/
{auto a=&Exist,b=&p.Exist;return*a!=*b||a[1]!=b[1]||a[2]!=b[2];}
/* FNV-1a. Zobrist is not effecive*/
[[nodiscard]] Inline HashKey Position::hash()const noexcept{
u64 const*a=&Exist;/*хеш на основе FNV-1a*/
HashKey key=(14695981039346656037ULL^*a++)*1099511628211ULL;
key^=*a++; return key*1099511628211ULL^*a;
}
Inline void Position::setStart()noexcept{
Exist=0xEFFF00000000FFEFull,
Kings[0]={E1,3}, Kings[1]={E8,3}, MoveType=Irreversible, reserved=0,
Active=0x7FFF, Pawns=0x7FFF80, NBRQ = 0x874A1D2;
}
[[nodiscard]] Inline Position::FieldInfo Position::inspect(Cell fld)const noexcept{
if(1&~Exist>>fld){
if(fld==Kings[0].Place)return{King,1};
if(fld==Kings[1].Place)return{King,0};
return{Empty,0};
}
u8 idx=u8(__builtin_popcountll(Exist&((1ull<<fld)-1)));
bool isActive=1&Active>>idx;
if(1&Pawns>>idx)return{Pawn,isActive};
idx=u8(__builtin_popcount(Pawns&((1u<<idx)-1)));
return{u8(Knight+(NBRQ>>idx*2&0b11)),isActive};
}
Inline void Position::inspect(auto Inspector)const noexcept{
u64 e=Exist; u32 a=Active,p=Pawns,z=NBRQ;
for(;e;p>>=1,a>>=1,e&=e-1){
Piece Pc=Pawn;
if(1&~p)Pc=Piece(Knight+(nbrq&z)),z>>=2;
Inspector(Pc,bool(1&a),Cell(__builtin_ctzll(e)));
}
}
}/*namespace Chess*/