842 lines
28 KiB
C++
842 lines
28 KiB
C++
#ifndef SECONDO_ALGEBRAS_CHESS_POSITIONOPS_HPP
|
|
#define SECONDO_ALGEBRAS_CHESS_POSITIONOPS_HPP
|
|
|
|
#include <map>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <boost/lambda/lambda.hpp>
|
|
#include <boost/lambda/bind.hpp>
|
|
|
|
#include "ternary_function.hpp"
|
|
#include "Position.hpp"
|
|
#include "Material.hpp"
|
|
#include "Piece.hpp"
|
|
#include "MoveOps.hpp"
|
|
|
|
|
|
struct attackcount_op : std::binary_function< Position, Field, int >
|
|
{
|
|
int operator () ( const Position& pos, const Field& f ) const
|
|
{
|
|
int count = 0;
|
|
// Count pawns attacks
|
|
int row = f.row + ( pos.turn() == WHITE ? -1 : 1 );
|
|
if (pos[ Field(f.file - 1, row) ] == Piece(PT_PAWN, pos.turn()).get())
|
|
++count;
|
|
if (pos[ Field(f.file + 1, row) ] == Piece(PT_PAWN, pos.turn()).get())
|
|
++count;
|
|
|
|
// Count pieces attacks
|
|
for( int pt = PT_KNIGHT; pt <= PT_KING; ++pt )
|
|
{
|
|
position_t::board_t::moves_t dirs = pos.moves( PIECE_TYPE(pt) );
|
|
position_t::const_iterator it1 = pos.iter( f );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = it1;
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( *it == NONE )
|
|
continue;
|
|
if ( *it == Piece( PIECE_TYPE(pt), pos.turn() ).get() )
|
|
++count;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
};
|
|
|
|
struct protectcount_op : std::binary_function< Position, Field, int >
|
|
{
|
|
int operator () ( const Position& pos, const Field& f ) const
|
|
{
|
|
int count = 0;
|
|
// Count pawns
|
|
PIECE protecting = Piece( PT_PAWN, !pos.turn() ).get();
|
|
int row = f.row + ( pos.turn() == WHITE ? 1 : -1 );
|
|
if ( pos[ Field(f.file - 1, row) ] == protecting )
|
|
++count;
|
|
if ( pos[ Field(f.file + 1, row) ] == protecting )
|
|
++count;
|
|
|
|
// Count pieces
|
|
for( int pt = PT_KNIGHT; pt <= PT_KING; ++pt )
|
|
{
|
|
position_t::board_t::moves_t dirs = pos.moves( PIECE_TYPE(pt) );
|
|
position_t::const_iterator it1 = pos.iter( f );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = it1;
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( *it == NONE )
|
|
continue;
|
|
if ( *it == Piece( PIECE_TYPE(pt), !pos.turn() ).get() )
|
|
++count;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
};
|
|
|
|
struct move_generator
|
|
{
|
|
typedef std::vector< PlyT > moves_t;
|
|
typedef moves_t::const_iterator iterator;
|
|
|
|
move_generator( const Position& pos ) : pos_(pos)
|
|
{
|
|
generate_castlings( pos_ );
|
|
|
|
//typedef Position::const_iterator pos_iter;
|
|
for( int row = 0; row < 8; ++row )
|
|
{
|
|
for( int file = 0; file < 8; ++file )
|
|
{
|
|
Field from( file, row );
|
|
Piece agent( pos_[from] );
|
|
if ( agent.get() < BLACK_PAWN || agent.get() > WHITE_KING || agent.color() != pos_.turn() )
|
|
continue;
|
|
if ( agent.type() == PT_PAWN )
|
|
generate_pawn_moves( file, row, agent );
|
|
else if ( PT_KNIGHT <= agent.type() && agent.type() <= PT_KING )
|
|
generate_piece_moves( pos_, from, agent );
|
|
}
|
|
}
|
|
}
|
|
|
|
Field find_king( COLOR color ) const
|
|
{
|
|
PIECE king = Piece( PT_KING, color ).get();
|
|
for( int i = 0; i < 64; ++i )
|
|
if ( pos_[ Field(i%8, i/8) ] == king )
|
|
return Field(i%8, i/8);
|
|
throw std::runtime_error( "King not found" );
|
|
}
|
|
|
|
iterator begin() const { return moves_.begin(); }
|
|
iterator end() const { return moves_.begin(); }
|
|
const PlyT& operator[]( int n ) const { return moves_[n]; }
|
|
int size() const { return moves_.size(); }
|
|
|
|
private:
|
|
moves_t moves_;
|
|
Position pos_;
|
|
|
|
|
|
void add_move( const PlyT& p )
|
|
{
|
|
Ply ply(p);
|
|
delete apply_ply_op()( pos_, ply );
|
|
Field king_pos = find_king( !pos_.turn() );
|
|
if ( attackcount_op()( pos_, king_pos ) == 0 )
|
|
moves_.push_back( p );
|
|
delete revert_ply_op()( pos_, ply );
|
|
}
|
|
|
|
void generate_piece_moves( const Position& pos_,
|
|
const Field& from, const Piece& agent )
|
|
{
|
|
position_t::board_t::moves_t dirs = pos_.moves( agent.type() );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = pos_.iter( from );
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( *it == UNDEFINED )
|
|
break;
|
|
if ( *it != NONE && Piece(*it).color() == pos_.turn() )
|
|
break;
|
|
Field to( pos_.field( it ) );
|
|
Piece captured( pos_[to] );
|
|
add_move( PlyT( from, to, agent.get(), pos_.state(), PLY_ORDINARY, captured.type() ) );
|
|
if ( *it != NONE )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void generate_castlings( const Position& pos_ )
|
|
{
|
|
int row = pos_.turn() == WHITE ? 0 : 7;
|
|
if ( pos_.is_castling_possible( true, pos_.turn() ) &&
|
|
pos_[Field(3, row)] == NONE && pos_[Field(2, row)] == NONE &&
|
|
pos_[Field(1, row)] == NONE )
|
|
{
|
|
PIECE agent = pos_[Field(4, row)];
|
|
add_move( PlyT(Field(4, row), Field(2, row), agent, pos_.state(), PLY_CASTLING ) );
|
|
}
|
|
if ( pos_.is_castling_possible( false, pos_.turn() ) &&
|
|
pos_[Field(5, row)] == NONE && pos_[Field(6, row)] == NONE )
|
|
{
|
|
Field from( 4, row );
|
|
Field to( 6, row );
|
|
PIECE agent = pos_[from];
|
|
add_move( PlyT( from, to, agent, pos_.state(), PLY_CASTLING ) );
|
|
}
|
|
}
|
|
|
|
void generate_pawn_moves( int file, int row, const Piece& agent )
|
|
{
|
|
Field from( file, row );
|
|
int dest_row = row + ( pos_.turn() == WHITE ? 1 : -1 );
|
|
Field to( file, dest_row );
|
|
if ( pos_[ to ] == NONE )
|
|
{
|
|
add_move( PlyT( from, to, agent.get(), pos_.state() ) );
|
|
|
|
if ( row == ( pos_.turn() == WHITE ? 1 : 6 ) )
|
|
{
|
|
dest_row += pos_.turn() == WHITE ? 1 : -1;
|
|
to = Field( file, dest_row );
|
|
if ( pos_[ to ] == NONE )
|
|
add_move( PlyT( from, to, agent.get(), pos_.state() ) );
|
|
}
|
|
}
|
|
dest_row = row + ( pos_.turn() == WHITE ? 1 : -1 );
|
|
generate_pawn_capture( from, Field( file - 1, dest_row ), agent );
|
|
generate_pawn_capture( from, Field( file + 1, dest_row ), agent );
|
|
}
|
|
|
|
void generate_pawn_capture( const Field& from, const Field& to, const Piece& agent )
|
|
{
|
|
Piece captured( pos_[to] );
|
|
if ( captured.get() == UNDEFINED )
|
|
return;
|
|
if ( captured.get() == NONE )
|
|
{
|
|
int to_row = pos_.turn() == WHITE ? 5 : 2;
|
|
Field capture_f = Field( to.file, pos_.turn() == WHITE ? 4 : 3 );
|
|
if ( to.row == to_row && pos_.is_enpassant_possible()
|
|
&& Piece( pos_[capture_f] ) == Piece( PT_PAWN, !pos_.turn() )
|
|
&& pos_.enpassant_file() == to.file )
|
|
{
|
|
add_move( PlyT( from, to, agent.get(), pos_.state(), PLY_ENPASSANT, PT_PAWN ) );
|
|
}
|
|
}
|
|
else if ( captured.color() != pos_.turn() )
|
|
add_move( PlyT( from, to, agent.get(), pos_.state(), PLY_ORDINARY, captured.type() ) );
|
|
}
|
|
};
|
|
|
|
struct pieces_op : std::unary_function< Position, Material* >
|
|
{
|
|
Material* operator () ( const Position& pos ) const
|
|
{
|
|
Material* m = new Material( DEFINED );
|
|
for( int i = 0; i < 64; ++i )
|
|
{
|
|
Field field( i % 8, i / 8 );
|
|
PIECE piece = pos[field];
|
|
if ( piece >= BLACK_PAWN && piece <= WHITE_KING )
|
|
++m->pieces[ piece - 2 ];
|
|
}
|
|
return m;
|
|
}
|
|
};
|
|
|
|
struct moveNo_op : std::unary_function< Position, int >
|
|
{
|
|
int operator () ( const Position& p ) const { return p.move_number(); }
|
|
};
|
|
|
|
struct checkmate_op : std::unary_function< Position, bool >
|
|
{
|
|
bool operator () ( const Position& pos ) const
|
|
{
|
|
move_generator gen( pos );
|
|
Field king_pos = gen.find_king( pos.turn() );
|
|
return protectcount_op()( pos, king_pos ) > 0 && gen.size() == 0;
|
|
}
|
|
};
|
|
|
|
struct stalemate_op : std::unary_function< Position, bool >
|
|
{
|
|
bool operator () ( const Position& pos ) const
|
|
{
|
|
move_generator gen( pos );
|
|
Field king_pos = gen.find_king( pos.turn() );
|
|
return protectcount_op()( pos, king_pos ) == 0 && gen.size() == 0;
|
|
}
|
|
};
|
|
|
|
struct includes_op : std::binary_function< Position, Position, bool >
|
|
{
|
|
bool operator () ( const Position& p1, const Position& p2 ) const
|
|
{
|
|
typedef Position::const_iterator Iter;
|
|
for( Iter i1 = p1.begin(), i2 = p2.begin();
|
|
i1 != p1.end() && i2 != p2.end(); ++i1, ++i2 )
|
|
{
|
|
if ( *i1 != *i2 && *i2 != NONE )
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
struct piececount_position_op : std::binary_function< Position, Piece, int >
|
|
{
|
|
int operator() ( const Position& pos, const Piece& piece ) const
|
|
{
|
|
PIECE p = piece.get();
|
|
return std::count_if( pos.begin(), pos.end(), p == boost::lambda::_1 );
|
|
}
|
|
};
|
|
|
|
struct piececount_spos_op : std::binary_function< Position, CcString, int >
|
|
{
|
|
int operator() ( const Position& pos, const CcString& piece ) const
|
|
{
|
|
PIECE_TYPE pt = PT_UNDEFINED;
|
|
try {
|
|
pt = Piece::from_agent_type( piece.GetValue() );
|
|
}
|
|
catch( const std::exception& )
|
|
{
|
|
PIECE p = UNDEFINED;
|
|
try {
|
|
p = Piece::from_agent( piece.GetValue() );
|
|
}
|
|
catch( const std::exception& ){
|
|
throw std::runtime_error( "Unknown Piece 1" );
|
|
}
|
|
if ( p < NONE || p > WHITE_KING )
|
|
throw std::runtime_error( "Unknown Piece 2" );
|
|
return std::count_if( pos.begin(), pos.end(), p == boost::lambda::_1 );
|
|
}
|
|
if ( pt < PT_NONE || pt > PT_KING )
|
|
throw std::runtime_error( "Unknown Piece 3" );
|
|
int sum = 0;
|
|
for( int i = 0; i < 64; ++i )
|
|
if ( Piece( pos[Field(i%8, i/8)] ).type() == pt )
|
|
++sum;
|
|
return sum;
|
|
}
|
|
};
|
|
|
|
struct approx_position_op : std::binary_function< Position, Position, bool >
|
|
{
|
|
bool operator() ( const Position& p1, const Position& p2 ) const
|
|
{
|
|
return abs( p1.value_sum() - p2.value_sum() ) < 0.2;
|
|
}
|
|
};
|
|
|
|
struct posrange_op : ternary_function< Position, Field, Field, Position* >
|
|
{
|
|
Position* operator()( const Position& p, const Field& f1, const Field& f2 )
|
|
{
|
|
Position* pos = new Position( EMPTY_POSITION );
|
|
for( int y = f1.row; y <= f2.row; ++y )
|
|
for( int x = f1.file; x <= f2.file; ++x )
|
|
(*pos)[ Field( x, y ) ] = p[ Field( x, y ) ];
|
|
return pos;
|
|
}
|
|
};
|
|
|
|
struct attacked_by_p_op : ternary_function< Position, Piece, Piece, bool >
|
|
{
|
|
bool operator()( const Position& pos, const Piece& p1, const Piece& p2 )
|
|
{
|
|
Piece attacking = Piece( p2.type(), pos.turn() );
|
|
PIECE attacked = Piece( p1.type(), !pos.turn() ).get();
|
|
|
|
for( int i = 0; i < 64; ++i )
|
|
{
|
|
Field f( i % 8, i / 8 );
|
|
if ( Piece( pos[f] ) == attacking )
|
|
{
|
|
if ( p2.type() == PT_PAWN )
|
|
{
|
|
int row = f.row + ( pos.turn() == WHITE ? 1 : -1 );
|
|
if ( pos[ Field(f.file - 1, row) ] == attacked )
|
|
return true;
|
|
if ( pos[ Field(f.file + 1, row) ] == attacked )
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
|
|
/*
|
|
Warning, sometimes the following code produces a memory
|
|
error, i.e. the it will point after the valid data.
|
|
|
|
*/
|
|
|
|
position_t::board_t::moves_t dirs = pos.moves( p2.type() );
|
|
position_t::const_iterator it1 = pos.iter( f );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = it1;
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( *it == NONE )
|
|
continue;
|
|
if ( *it == attacked )
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
struct attacked_by_f_op : ternary_function< Position, Field, Piece, bool >
|
|
{
|
|
bool operator()( const Position& pos, const Field& f, const Piece& p )
|
|
{
|
|
PIECE attacking = Piece( p.type(), pos.turn() ).get();
|
|
if ( p.type() == PT_PAWN )
|
|
{
|
|
int row = f.row + ( pos.turn() == WHITE ? -1 : 1 );
|
|
if ( pos[ Field(f.file - 1, row) ] == attacking )
|
|
return true;
|
|
if ( pos[ Field(f.file + 1, row) ] == attacking )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
position_t::board_t::moves_t dirs = pos.moves( p.type() );
|
|
position_t::const_iterator it1 = pos.iter( f );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = it1;
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( *it == NONE )
|
|
continue;
|
|
if ( *it == attacking )
|
|
return true;
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
struct attacked_from_p_op : ternary_function< Position, Piece, Field, bool >
|
|
{
|
|
bool operator()( const Position& pos, const Piece& p, const Field& f )
|
|
{
|
|
PIECE_TYPE attacking = Piece( pos[f] ).type();
|
|
if ( attacking < PT_PAWN || attacking > PT_KING )
|
|
return false;
|
|
|
|
PIECE attacked = Piece( p.type(), !pos.turn() ).get();
|
|
// pawns attacks
|
|
if ( attacking == PT_PAWN )
|
|
{
|
|
int row = f.row + ( pos.turn() == WHITE ? -1 : 1 );
|
|
if ( pos[ Field(f.file - 1, row) ] == attacked )
|
|
return true;
|
|
if ( pos[ Field(f.file + 1, row) ] == attacked )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// pieces attacks
|
|
position_t::board_t::moves_t dirs = pos.moves( attacking );
|
|
position_t::const_iterator it1 = pos.iter( f );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = it1;
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( *it == NONE )
|
|
continue;
|
|
if ( *it == attacked )
|
|
return true;
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
struct attacked_from_f_op : ternary_function< Position, Field, Field, bool >
|
|
{
|
|
bool operator()( const Position& pos, const Field& f1, const Field& f2 )
|
|
{
|
|
PIECE_TYPE attacking = Piece( pos[f2] ).type();
|
|
if ( attacking < PT_PAWN || attacking > PT_KING )
|
|
return false;
|
|
|
|
// pawns attacks
|
|
if ( attacking == PT_PAWN )
|
|
{
|
|
int row = f2.row + ( pos.turn() == WHITE ? -1 : 1 );
|
|
if ( Field(f2.file - 1, row) == f1 )
|
|
return true;
|
|
if ( Field(f2.file + 1, row) == f1 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// pieces attacks
|
|
position_t::board_t::moves_t dirs = pos.moves( attacking );
|
|
position_t::const_iterator it1 = pos.iter( f2 );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = it1;
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( pos.field( it ) == f1 )
|
|
return true;
|
|
if ( *it == NONE )
|
|
continue;
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
struct protected_by_p_op : ternary_function< Position, Piece, Piece, bool >
|
|
{
|
|
bool operator()( Position& pos, const Piece& p1, const Piece& p2 )
|
|
{
|
|
pos.increment_turn();
|
|
bool result = attacked_by_p_op()( pos, p1, p2 );
|
|
pos.decrement_turn();
|
|
return result;
|
|
}
|
|
};
|
|
|
|
struct protected_by_f_op : ternary_function< Position, Field, Piece, bool >
|
|
{
|
|
bool operator()( Position& pos, const Field& f, const Piece& p )
|
|
{
|
|
pos.increment_turn();
|
|
bool result = attacked_by_f_op()( pos, f, p );
|
|
pos.decrement_turn();
|
|
return result;
|
|
}
|
|
};
|
|
|
|
struct protected_from_p_op : ternary_function< Position, Piece, Field, bool >
|
|
{
|
|
bool operator()( Position& pos, const Piece& p, const Field& f )
|
|
{
|
|
pos.increment_turn();
|
|
bool result = attacked_from_p_op()( pos, p, f );
|
|
pos.decrement_turn();
|
|
return result;
|
|
}
|
|
};
|
|
|
|
struct protected_from_f_op : ternary_function< Position, Field, Field, bool >
|
|
{
|
|
bool operator()( Position& pos, const Field& f1, const Field& f2 )
|
|
{
|
|
pos.increment_turn();
|
|
bool result = attacked_from_f_op()( pos, f1, f2 );
|
|
pos.decrement_turn();
|
|
return result;
|
|
}
|
|
};
|
|
|
|
struct apply_move_op : ternary_function< Position, Field, Field, Position* >
|
|
{
|
|
Position* operator()( Position& pos, const Field& f1, const Field& f2 )
|
|
{
|
|
// TODO Plausibilitaetspruefung, argument checking
|
|
if ( pos[f1] != NONE )
|
|
{
|
|
pos[f2] = pos[f1];
|
|
pos[f1] = NONE;
|
|
}
|
|
return new Position(pos); // TODO
|
|
}
|
|
};
|
|
|
|
struct pos_fields_op : std::unary_function< Position, std::pair<bool, Tuple*> >
|
|
{
|
|
pos_fields_op( const Position&, ListExpr type ) : index_(-1), type_(type){}
|
|
|
|
std::pair<bool, Tuple*> operator()( const Position& pos )
|
|
{
|
|
TupleType type( type_ );
|
|
if ( ++index_ < 64 )
|
|
{
|
|
Tuple* result = new Tuple( new TupleType(type_) );
|
|
Field* field = new Field( index_ % 8, index_ / 8 );
|
|
result->PutAttribute( 0, field );
|
|
result->PutAttribute( 1, new Piece( pos[*field] ) );
|
|
return std::make_pair( true, result );
|
|
}
|
|
return std::make_pair( false, new Tuple( new TupleType(type_) ) );
|
|
}
|
|
|
|
static list_ostream type( ListExpr )
|
|
{
|
|
return list_ostream()
|
|
<< ( list_ostream() << ChessBSymbol("Field")
|
|
<< ChessBSymbol("field") )
|
|
<< ( list_ostream() << ChessBSymbol("Piece")
|
|
<< ChessBSymbol("piece") );
|
|
}
|
|
private:
|
|
int index_;
|
|
ListExpr type_;
|
|
};
|
|
|
|
struct tuple_t
|
|
{
|
|
tuple_t() : bp(NONE){}
|
|
tuple_t( Piece sp_, Field sf_, Piece bp_, Field bf_, Piece ep_, Field ef_ )
|
|
: sp(sp_), bp(bp_), ep(ep_), sf(sf_), bf(bf_), ef(ef_){}
|
|
Piece sp, bp, ep;
|
|
Field sf, bf, ef;
|
|
};
|
|
|
|
struct pos_moves_op : std::unary_function< Position, std::pair<bool, Tuple*> >
|
|
{
|
|
pos_moves_op( const Position& pos, ListExpr type )
|
|
: type_(type), gen_(pos), current_(-1){}
|
|
|
|
std::pair<bool, Tuple*> operator()( const Position& )
|
|
{
|
|
TupleType type( type_ );
|
|
if ( ++current_ < gen_.size() )
|
|
{
|
|
const PlyT& ply = gen_[current_];
|
|
Tuple* result = new Tuple( new TupleType(type_) );
|
|
result->PutAttribute( 0, new Piece( ply.agent() ) );
|
|
result->PutAttribute( 1, new Field( ply.from() ) );
|
|
result->PutAttribute( 2, new Piece( ply.captured() ) );
|
|
result->PutAttribute( 3, new Field( ply.to() ) );
|
|
return std::make_pair( true, result );
|
|
}
|
|
return std::make_pair( false, new Tuple( new TupleType(type_) ) );
|
|
}
|
|
|
|
static list_ostream type( ListExpr )
|
|
{
|
|
return list_ostream()
|
|
<< ( list_ostream() << ChessBSymbol("SPiece")
|
|
<< ChessBSymbol("piece") )
|
|
<< ( list_ostream() << ChessBSymbol("SField")
|
|
<< ChessBSymbol("field") )
|
|
<< ( list_ostream() << ChessBSymbol("EPiece")
|
|
<< ChessBSymbol("piece") )
|
|
<< ( list_ostream() << ChessBSymbol("EField")
|
|
<< ChessBSymbol("field") );
|
|
}
|
|
private:
|
|
ListExpr type_;
|
|
move_generator gen_;
|
|
int current_;
|
|
};
|
|
|
|
class p_moves_blocked_op;
|
|
|
|
struct pos_moves_blocked_op : std::unary_function< Position, std::pair<bool, Tuple*> >
|
|
{
|
|
pos_moves_blocked_op( const Position& pos, ListExpr t )
|
|
: type_(t), current_(0)
|
|
{
|
|
int srow = pos.turn() == WHITE ? 1 : 6;
|
|
int brow = pos.turn() == WHITE ? 2 : 5;
|
|
int erow = pos.turn() == WHITE ? 3 : 4;
|
|
Piece pawn = Piece( PT_PAWN, pos.turn() );
|
|
for( int file = 0; file < 8; ++file )
|
|
{
|
|
Piece spiece = Piece( pos[ Field( file, srow ) ] );
|
|
Piece bpiece = Piece( pos[ Field( file, brow ) ] );
|
|
Piece epiece = Piece( pos[ Field( file, erow ) ] );
|
|
if ( spiece == pawn && bpiece.get() != NONE
|
|
&& epiece.color() != pos.turn() )
|
|
{
|
|
tuples.push_back( tuple_t( spiece, Field( file, srow ), bpiece,
|
|
Field( file, brow ), epiece, Field( file, erow ) ) );
|
|
}
|
|
}
|
|
|
|
for( int i = 0; i < 64; ++i )
|
|
{
|
|
tuple_t t;
|
|
t.sf = Field( i % 8, i / 8 );
|
|
t.sp = Piece( pos[t.sf] );
|
|
if ( t.sp.type() > PT_KNIGHT && t.sp.type() < PT_KING
|
|
&& t.sp.color() == pos.turn() )
|
|
{
|
|
position_t::board_t::moves_t dirs = pos.moves( t.sp.type() );
|
|
position_t::const_iterator it1 = pos.iter( t.sf );
|
|
for( int d = 0; d < dirs.count; ++d )
|
|
{
|
|
position_t::const_iterator it = it1;
|
|
for( int i = 0; i < dirs.steps; ++i )
|
|
{
|
|
it += dirs.moves[d];
|
|
if ( *it == UNDEFINED )
|
|
break;
|
|
if ( t.bp == Piece( NONE ) )
|
|
{
|
|
if ( *it != NONE )
|
|
{
|
|
t.bp = Piece(*it);
|
|
t.bf = pos.field(it);
|
|
}
|
|
continue;
|
|
}
|
|
if ( *it == NONE )
|
|
{
|
|
t.ep = Piece(*it);
|
|
t.ef = pos.field(it);
|
|
tuples.push_back( t );
|
|
continue;
|
|
}
|
|
else if ( Piece(*it).color() != pos.turn()
|
|
&& Piece(*it).type() != PT_KING )
|
|
{
|
|
t.ep = Piece(*it);
|
|
t.ef = pos.field(it);
|
|
tuples.push_back( t );
|
|
}
|
|
t.bp = Piece(*it);
|
|
t.bf = pos.field(it);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
std::pair<bool, Tuple*> operator()( const Position& )
|
|
{
|
|
TupleType type( type_ );
|
|
if ( current_ < tuples.size() )
|
|
{
|
|
const tuple_t& t = tuples[ current_++ ];
|
|
Tuple* result = new Tuple( new TupleType(type_) );
|
|
result->PutAttribute( 0, new Piece(t.sp) );
|
|
result->PutAttribute( 1, new Field(t.sf) );
|
|
result->PutAttribute( 2, new Piece(t.bp) );
|
|
result->PutAttribute( 3, new Field(t.bf) );
|
|
result->PutAttribute( 4, new Piece(t.ep) );
|
|
result->PutAttribute( 5, new Field(t.ef) );
|
|
return std::make_pair( true, result );
|
|
}
|
|
return std::make_pair( false, new Tuple( new TupleType(type_) ) );
|
|
}
|
|
|
|
static list_ostream type( ListExpr )
|
|
{
|
|
return list_ostream()
|
|
<< ( list_ostream() << ChessBSymbol("SPiece")
|
|
<< ChessBSymbol("piece") )
|
|
<< ( list_ostream() << ChessBSymbol("SField")
|
|
<< ChessBSymbol("field") )
|
|
<< ( list_ostream() << ChessBSymbol("BPiece")
|
|
<< ChessBSymbol("piece") )
|
|
<< ( list_ostream() << ChessBSymbol("BField")
|
|
<< ChessBSymbol("field") )
|
|
<< ( list_ostream() << ChessBSymbol("EPiece")
|
|
<< ChessBSymbol("piece") )
|
|
<< ( list_ostream() << ChessBSymbol("EField")
|
|
<< ChessBSymbol("field") );
|
|
}
|
|
|
|
private:
|
|
ListExpr type_;
|
|
std::vector< tuple_t > tuples;
|
|
std::vector< tuple_t >::size_type current_;
|
|
friend class p_moves_blocked_op;
|
|
};
|
|
|
|
struct piece_moves_op : std::binary_function< Position, Piece, std::pair<bool, Tuple*> >
|
|
{
|
|
piece_moves_op( const Position& pos, const Piece& agent, ListExpr type )
|
|
: type_(type), gen_(pos), current_(-1){}
|
|
|
|
std::pair<bool, Tuple*> operator()( const Position&, const Piece& agent )
|
|
{
|
|
TupleType type( type_ );
|
|
while( ++current_ < gen_.size() )
|
|
{
|
|
const PlyT& ply = gen_[current_];
|
|
if ( ply.agent() != agent )
|
|
continue;
|
|
|
|
Tuple* result = new Tuple( new TupleType(type_) );
|
|
result->PutAttribute( 0, new Piece( ply.agent() ) );
|
|
result->PutAttribute( 1, new Field( ply.from() ) );
|
|
result->PutAttribute( 2, new Piece( ply.captured() ) );
|
|
result->PutAttribute( 3, new Field( ply.to() ) );
|
|
return std::make_pair( true, result );
|
|
}
|
|
return std::make_pair( false, new Tuple( new TupleType(type_) ) );
|
|
}
|
|
|
|
static list_ostream type( ListExpr )
|
|
{
|
|
return list_ostream()
|
|
<< ( list_ostream() << ChessBSymbol("SPiece")
|
|
<< ChessBSymbol("piece") )
|
|
<< ( list_ostream() << ChessBSymbol("SField")
|
|
<< ChessBSymbol("field") )
|
|
<< ( list_ostream() << ChessBSymbol("EPiece")
|
|
<< ChessBSymbol("piece") )
|
|
<< ( list_ostream() << ChessBSymbol("EField")
|
|
<< ChessBSymbol("field") );
|
|
}
|
|
private:
|
|
ListExpr type_;
|
|
move_generator gen_;
|
|
int current_;
|
|
};
|
|
|
|
struct p_moves_blocked_op : std::binary_function< Position, Piece, std::pair<bool, Tuple*> >
|
|
{
|
|
p_moves_blocked_op( const Position& pos, const Piece& p, ListExpr t )
|
|
: type_(t), op_(pos, t){}
|
|
|
|
std::pair<bool, Tuple*> operator()( const Position& pos, const Piece& piece )
|
|
{
|
|
// TODO piece is undefined for some reason in
|
|
// query wjc feed head[1] extract[elem] getposition[0]
|
|
// piece_moves_blocked[Queen] consume;
|
|
|
|
TupleType type( type_ );
|
|
while( op_.current_ < op_.tuples.size() )
|
|
{
|
|
const tuple_t& t = op_.tuples[ op_.current_++ ];
|
|
if ( t.sp != piece )
|
|
continue;
|
|
|
|
Tuple* result = new Tuple( new TupleType(type_) );
|
|
result->PutAttribute( 0, new Piece(t.sp) );
|
|
result->PutAttribute( 1, new Field(t.sf) );
|
|
result->PutAttribute( 2, new Piece(t.bp) );
|
|
result->PutAttribute( 3, new Field(t.bf) );
|
|
result->PutAttribute( 4, new Piece(t.ep) );
|
|
result->PutAttribute( 5, new Field(t.ef) );
|
|
return std::make_pair( true, result );
|
|
}
|
|
return std::make_pair( false, new Tuple( new TupleType(type_) ) );
|
|
}
|
|
|
|
static list_ostream type( ListExpr e )
|
|
{
|
|
return pos_moves_blocked_op::type( e );
|
|
}
|
|
private:
|
|
ListExpr type_;
|
|
pos_moves_blocked_op op_;
|
|
};
|
|
|
|
#endif // SECONDO_ALGEBRAS_CHESS_POSITIONOPS_HPP
|