Skip to content

Instantly share code, notes, and snippets.

@sehe
Created December 25, 2011 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sehe/8f8881ffa3db7eb5a6c4 to your computer and use it in GitHub Desktop.
Save sehe/8f8881ffa3db7eb5a6c4 to your computer and use it in GitHub Desktop.
matrix chess movement axes
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;
}
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