-
-
Save sehe/8f8881ffa3db7eb5a6c4 to your computer and use it in GitHub Desktop.
matrix chess movement axes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<const mtx_gametype_id_t id> | |
struct gametraits; | |
struct gametraits_base | |
{ | |
enum gamerules | |
{ | |
rule_pawn_doublestep = 1, | |
rule_enpassant_2d = 2 | rule_pawn_doublestep, | |
rule_enpassant_3d = 4 | rule_pawn_doublestep, | |
rule_pawncaptures_2d = 8, | |
rule_pawncaptures_3d = 16, | |
rule_castlekingside = 32, // move definition in gametraits | |
rule_castlequeenside = 64, | |
// | |
rule_castlings = rule_castlekingside | rule_castlequeenside, | |
// | |
pawnrank = 1, // atm this is a given for all gametypes | |
max_castlings = 4, // so externally linked parties can guess the highest number of castlings for any gametype | |
}; | |
const static mtx_move_t no_move; | |
typedef std::pair<mtx_move_t, mtx_move_t> compound_move_t; | |
typedef std::vector<gametraits_base::compound_move_t> compound_moves_t; | |
}; | |
//// skipped specializations | |
template <const mtx_gametype_id_t id> | |
const gametraits_base::compound_moves_t& matrixcore<id>::castlings() | |
{ | |
typedef gametraits_base::compound_moves_t repo; | |
static repo _repo; | |
if (_repo.empty()) | |
{ | |
mtx_board_t* position = create(); | |
setup(position); | |
const bfr wk(find_whiteking(position)); | |
logicErrorAssert(wk.rank()==0); | |
const bfr kings[] = { wk, bfr(wk.board(), wk.file(), dim::num_rank - 1) }; | |
tupleset directions; | |
const bool is3d = num_bord>3; | |
// FIXME TODO detect/allow other axes for truly generic gametypes | |
if(wk.file()>=3) directions.insert(tuple(is3d? -1:0, -1, 0)); | |
if(wk.file()<=num_file-4) directions.insert(tuple(is3d? +1:0, +1, 0)); | |
for (tupleset::const_iterator it=directions.begin(); it!=directions.end(); ++it) | |
{ | |
const int rookdistance = detect_rookdistance(wk, *it); // 3=short (kingside0, 4=long (queenside) | |
// std::cout << "GEN CASTLING: " << rookdistance << " from " << wk << " for " << traits::name() << " with " << *it << std::endl; | |
for (const bfr* kf=kings; kf!=kings+ARRAY_SIZE(kings); kf++) | |
{ | |
const mtx_piece_id_t color = kf->rank()? mtx_black_bit : mtx_NONE; | |
mtx_move_t king_move, rook_move; | |
king_move.actor= (mtx_piece_id_t) (mtx_king | color); | |
rook_move.actor= (mtx_piece_id_t) (mtx_rook | color); | |
logicErrorAssert(kf->valid() && (*kf + *it*rookdistance).valid()); | |
king_move.from = *kf; | |
rook_move.to = *kf + *it; | |
king_move.to = *kf + *it*2; | |
rook_move.from = *kf + *it*rookdistance; | |
// verify that the expected pieces do exist at the expected fields | |
logicErrorAssert(position->array[king_move.from] == (king_move.actor | mtx_unmoved_bit)); | |
logicErrorAssert(position->array[rook_move.from] == (rook_move.actor | mtx_unmoved_bit)); | |
king_move.annex=mtx_regular; // the compositing moves are *not* special (the 'single' move is, however) | |
rook_move.annex=mtx_regular; | |
_repo.push_back(repo::value_type(king_move, rook_move)); | |
} | |
} | |
if (position) | |
mtx_destroy_board(position); | |
logicErrorAssert(_repo.size()<=gametraits_base::max_castlings); | |
} | |
return _repo; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum axismode { jump, ray }; | |
template <const mtx_axes_t axis> | |
struct axistraits | |
{ | |
static const char* const name; | |
static const axismode mode; | |
static const tuple vector; | |
}; | |
template<> const char* const axistraits<mtx_axis_R >::name = "rook"; | |
template<> const char* const axistraits<mtx_axis_B2>::name = "2d bishop"; | |
template<> const char* const axistraits<mtx_axis_B3>::name = "3d bishop"; | |
template<> const char* const axistraits<mtx_axis_N2>::name = "2d knight"; | |
template<> const char* const axistraits<mtx_axis_N3>::name = "3d knight"; | |
template<> const axismode axistraits<mtx_axis_R >::mode = ray; | |
template<> const axismode axistraits<mtx_axis_B2>::mode = ray; | |
template<> const axismode axistraits<mtx_axis_B3>::mode = ray; | |
template<> const axismode axistraits<mtx_axis_N2>::mode = jump; | |
template<> const axismode axistraits<mtx_axis_N3>::mode = jump; | |
template<> const tuple axistraits<mtx_axis_R >::vector(1,0,0); | |
template<> const tuple axistraits<mtx_axis_B2>::vector(0,1,1); | |
template<> const tuple axistraits<mtx_axis_B3>::vector(1,1,1); | |
template<> const tuple axistraits<mtx_axis_N2>::vector(0,1,2); | |
template<> const tuple axistraits<mtx_axis_N3>::vector(1,1,2); | |
template <const mtx_gametype_id_t id> | |
static bool impossible(const tuple& mv) | |
{ | |
typedef typename gametraits<id>::dim dim; | |
return (abs(mv.board()) >= dim::num_bord || | |
abs(mv.file()) >= dim::num_file || | |
abs(mv.rank()) >= dim::num_rank); | |
} | |
/* | |
* again, gen_combinations goes about it in a dumb way. Unique-ness | |
* of generated tuples is simply maintained by storing them in a set, | |
* letting tuple::operator<() do the work | |
*/ | |
tupleset gen_combinations(const tuple& mv, bool both_directions=false) | |
{ | |
tupleset tuples; | |
std::vector<tuple> directions(4, mv); | |
directions[0].board() = - directions[0].board(); // flip z | |
directions[1].file() = - directions[1].file(); // flip x | |
directions[2].rank() = - directions[2].rank(); // flip y | |
for (std::vector<tuple>::iterator it=directions.begin(); it!=directions.end(); ++it) | |
{ | |
tuple& t(*it); | |
if (t<-t) t=-t; // I prefer positive tuples in case of !both_directions; makes it easier to check things | |
std::sort(t.begin(), t.end()); | |
do | |
{ | |
if (both_directions || tuples.end()==tuples.find(-t)) | |
tuples.insert(t); | |
if (both_directions) | |
tuples.insert(-t); | |
} while (std::next_permutation(t.begin(), t.end())); | |
} | |
// std::cout << "Generated " << tuples.size() << " combinations from the tuple " << mv << ": "; | |
// std::copy(tuples.begin(), tuples.end(), std::ostream_iterator<tuple>(std::cout, ", ")); | |
// std::cout << std::endl; | |
return tuples; | |
} | |
template <typename T> | |
T startofray(const T& src, const tuple& step) | |
{ | |
for (T start(src); 1; start-=step) | |
if (!(start-step).valid()) return start; | |
} | |
} | |
template <const mtx_gametype_id_t id> | |
gentable<id>::gentable() | |
{ | |
_axes[mtx_axis_R ].template generate<mtx_axis_R>(); | |
_axes[mtx_axis_B2 ].template generate<mtx_axis_B2>(); | |
_axes[mtx_axis_B3 ].template generate<mtx_axis_B3>(); | |
_axes[mtx_axis_N2 ].template generate<mtx_axis_N2>(); | |
_axes[mtx_axis_N3 ].template generate<mtx_axis_N3>(); | |
_axes[mtx_axis_WpM].template generate_pawnmoves(true); | |
_axes[mtx_axis_BpM].template generate_pawnmoves(false); | |
_axes[mtx_axis_WpC].template generate_pawncaptures(true); | |
_axes[mtx_axis_BpC].template generate_pawncaptures(false); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment