00001
00002
00003 #include "osl/eval/see.h"
00004 #include "osl/eval/ptypeEval.h"
00005 #include "osl/move_generator/effect_action.h"
00006
00007 struct osl::eval::See::FindEffectMore
00008 {
00009 PtypeOSquareVector *direct;
00010 PtypeOSquareVector *more;
00011 Square target;
00012 const NumEffectState *state;
00013
00014 template<Player P,Ptype Type>
00015 void doActionPtype(Piece p) { store(p); }
00016 template<Player P>
00017 void doAction(Piece p, Square) { store(p);}
00018 void store(Piece p);
00019 };
00020
00021 void osl::eval::See::
00022 FindEffectMore::store(Piece p)
00023 {
00024 direct->push_back(std::make_pair(p.ptypeO(), p.square()));
00025 findAdditionalPieces(*state, p.owner(), target, p.square(), *more);
00026 }
00027
00028 template <osl::Player P>
00029 void osl::eval::
00030 See::findEffectPieces(const NumEffectState& state, Square effect_to,
00031 PtypeOSquareVector& my_pieces,
00032 PtypeOSquareVector& op_pieces)
00033 {
00034 typedef effect_action::StorePtypeOSquare store_t;
00035 store_t op_pieces_store(&op_pieces, effect_to);
00036 state.forEachEffect<alt(P),store_t>(effect_to, op_pieces_store);
00037 if (op_pieces.empty())
00038 return;
00039 op_pieces.sort();
00040 if ((int)op_pieces.size() <= state.countEffect(P, effect_to))
00041 {
00042 store_t my_pieces_store(&my_pieces, effect_to);
00043 state.forEachEffect<P,store_t>(effect_to, my_pieces_store);
00044 my_pieces.sort();
00045 return;
00046 }
00047 PtypeOSquareVector my_pieces_more;
00048 FindEffectMore action = { &my_pieces, &my_pieces_more, effect_to, &state };
00049 state.forEachEffect<P,FindEffectMore>(effect_to, action);
00050 my_pieces.sort();
00051
00052 my_pieces.push_back(my_pieces_more.begin(), my_pieces_more.end());
00053
00054 if (op_pieces.size() <= my_pieces.size())
00055 return;
00056 my_pieces_more.clear();
00057
00058 for (size_t i=0; i<op_pieces.size(); ++i) {
00059 findAdditionalPieces(state, P, effect_to, op_pieces[i].second, my_pieces_more);
00060 }
00061 my_pieces.push_back(my_pieces_more.begin(), my_pieces_more.end());
00062 }
00063
00064 template <osl::Player P>
00065 void osl::eval::
00066 See::findEffectPiecesAfterMove(const NumEffectState& state, Move move,
00067 PtypeOSquareVector& my_pieces,
00068 PtypeOSquareVector& op_pieces)
00069 {
00070 const Square from=move.from();
00071 const Square to=move.to();
00072
00073 typedef effect_action::StorePtypeOSquare store_t;
00074 store_t op_pieces_store(&op_pieces, to);
00075 state.forEachEffect<alt(P),store_t>(to, op_pieces_store);
00076 if (op_pieces.empty())
00077 return;
00078 op_pieces.sort();
00079
00080 const Piece moved = state.pieceOnBoard(from);
00081 PieceMask ignore;
00082 ignore.set(moved.number());
00083 if ((int)op_pieces.size() < state.countEffect(P, to))
00084 {
00085 store_t my_pieces_store(&my_pieces, to);
00086 state.forEachEffect<P,store_t>(to, my_pieces_store, ignore);
00087 my_pieces.sort();
00088 return;
00089 }
00090
00091 PtypeOSquareVector my_pieces_more;
00092 findAdditionalPieces(state, move.player(), to, moved.square(), my_pieces_more);
00093
00094 FindEffectMore action = { &my_pieces, &my_pieces_more, to, &state };
00095 state.forEachEffect<P,FindEffectMore>(to, action, ignore);
00096 my_pieces.sort();
00097
00098 my_pieces.push_back(my_pieces_more.begin(), my_pieces_more.end());
00099
00100 if (op_pieces.size() < my_pieces.size())
00101 return;
00102 my_pieces_more.clear();
00103
00104 for (size_t i=0; i<op_pieces.size(); ++i) {
00105 findAdditionalPieces(state, P, to, op_pieces[i].second, my_pieces_more);
00106 }
00107 my_pieces.push_back(my_pieces_more.begin(), my_pieces_more.end());
00108 }
00109
00110 template <osl::Player P>
00111 int osl::eval::
00112 See::computeValue(const NumEffectState& state, Move move,
00113 PtypeOSquareVector& my_pieces,
00114 PtypeOSquareVector& op_pieces,
00115 const PieceMask& my_pin, const PieceMask& op_pin,
00116 const eval::PtypeEvalTable& table)
00117 {
00118 Square target=move.to(), move_from=move.from();
00119 PtypeO ptypeO=move.ptypeO();
00120
00121 int val = 0;
00122 CArray<int,Piece::SIZE> vals;
00123 const Player Opponent = alt(P);
00124 size_t i;
00125 int c=0;
00126 bool op_deleted=false, my_deleted=false;
00127 for (i=0;i<op_pieces.size();i++,c++)
00128 {
00129 if(c>10) break;
00130 {
00131 Square from=op_pieces[i].second;
00132 Piece p=state.pieceAt(from);
00133 int num=p.number();
00134 if(num==KingTraits<Opponent>::index && my_deleted) break;
00135 assert(p.owner()==Opponent);
00136 if(op_pin.test(num) && !state.pinnedCanMoveTo<Opponent>(p,target) &&
00137 ptypeO!=newPtypeO(P,KING)){
00138 Piece attacker=state.pinAttacker<Opponent>(p);
00139 assert(attacker.owner()==P);
00140 Square attacker_sq=attacker.square();
00141 if(attacker_sq != move_from){
00142 size_t j=0;
00143 for(;j<my_pieces.size();j++) if(my_pieces[j].second==attacker_sq) break;
00144 if(i<=j){
00145 if(j==my_pieces.size() || op_pieces.size()<=j+1 ){
00146 for(size_t k=i;k<op_pieces.size()-1;k++)
00147 op_pieces[k]=op_pieces[k+1];
00148 op_pieces.pop_back();
00149 op_deleted=true;
00150 }
00151 else{
00152 std::pair<PtypeO,Square> v=op_pieces[i];
00153 for(size_t k=i;k<=j;k++)
00154 op_pieces[k]=op_pieces[k+1];
00155 op_pieces[j+1]=v;
00156 }
00157 i--;
00158 continue;
00159 }
00160 }
00161
00162 }
00163 }
00164 vals[i*2]=val;
00165
00166 val+=table.captureValue(ptypeO);
00167 {
00168 ptypeO = op_pieces[i].first;
00169 const bool promotable = canPromote(ptypeO)
00170 && (target.canPromote<Opponent>()
00171 || op_pieces[i].second.canPromote<Opponent>());
00172 if (promotable)
00173 {
00174 ptypeO=promote(ptypeO);
00175 val+=table.promoteValue(ptypeO);
00176 }
00177 }
00178 vals[i*2+1]=val;
00179
00180 retry:
00181 if (i>=my_pieces.size()){
00182 break;
00183 }
00184 {
00185 Square from=my_pieces[i].second;
00186 Piece p=state.pieceAt(from);
00187 int num=p.number();
00188 assert(p.owner()==P);
00189 if(num==KingTraits<P>::index && op_deleted) break;
00190 if(my_pin.test(num) && !state.pinnedCanMoveTo<P>(p,target) &&
00191 ptypeO!=newPtypeO(Opponent,KING)){
00192 Piece attacker=state.pinAttacker<P>(p);
00193 assert(attacker.owner()==Opponent);
00194 Square attacker_sq=attacker.square();
00195 size_t j=0;
00196 for(;j<op_pieces.size();j++) if(op_pieces[j].second==attacker_sq) break;
00197 if(i<j){
00198 if(j==op_pieces.size() || my_pieces.size()<=j ){
00199 for(size_t k=i;k<my_pieces.size()-1;k++)
00200 my_pieces[k]=my_pieces[k+1];
00201 my_pieces.pop_back();
00202 my_deleted=true;
00203 }
00204 else{
00205 std::pair<PtypeO,Square> v=my_pieces[i];
00206 for(size_t k=i;k<j;k++)
00207 my_pieces[k]=my_pieces[k+1];
00208 my_pieces[j]=v;
00209 }
00210 goto retry;
00211 }
00212
00213 }
00214 }
00215 val+=table.captureValue(ptypeO);
00216 {
00217 ptypeO=my_pieces[i].first;
00218 const bool promotable = canPromote(ptypeO)
00219 && (target.canPromote<P>()
00220 || my_pieces[i].second.canPromote<P>());
00221 if (promotable)
00222 {
00223 ptypeO=promote(ptypeO);
00224 val+=table.promoteValue(ptypeO);
00225 }
00226 }
00227 }
00228 for (int j=i-1;j>=0;j--)
00229 {
00230 val=EvalTraits<P>::max(val,vals[j*2+1]);
00231 val=EvalTraits<Opponent>::max(val,vals[j*2]);
00232 }
00233 return val;
00234 }
00235
00236 template <osl::Player P>
00237 int osl::eval::See::seeInternal(const NumEffectState& state, Move move,
00238 const PieceMask& my_pin, const PieceMask& op_pin,
00239 const eval::PtypeEvalTable& table)
00240 {
00241 assert(state.isAlmostValidMove(move));
00242
00243 const Square from=move.from();
00244 const Square to=move.to();
00245 PtypeOSquareVector my_pieces, op_pieces;
00246 int val=0;
00247 if (from.isPieceStand())
00248 {
00249 findEffectPieces<P>(state, to, my_pieces, op_pieces);
00250 }
00251 else
00252 {
00253 val = Ptype_Eval_Table.diffWithMove(state,move);
00254 findEffectPiecesAfterMove<P>(state, move, my_pieces, op_pieces);
00255 }
00256 if (op_pieces.empty())
00257 return val;
00258 return val + computeValue<P>(state, move, my_pieces, op_pieces, my_pin, op_pin, table);
00259 }
00260
00261 int osl::eval::See::see(const NumEffectState& state, Move move,
00262 const PieceMask& my_pin, const PieceMask& op_pin,
00263 const eval::PtypeEvalTable *table)
00264 {
00265 if (! table)
00266 table = &Ptype_Eval_Table;
00267 if (move.player() == BLACK)
00268 return seeInternal<BLACK>(state, move, my_pin, op_pin, *table);
00269 else
00270 return -seeInternal<WHITE>(state, move, my_pin, op_pin, *table);
00271 }
00272
00273 void osl::eval::
00274 See::findAdditionalPieces(const NumEffectState& state, Player attack,
00275 Square target,
00276 Square from,
00277 PtypeOSquareVector& out)
00278 {
00279 const Offset32 diff32 = Offset32(from, target);
00280 const Offset step = Board_Table.getShortOffsetNotKnight(diff32);
00281 if (step.zero())
00282 return;
00283
00284 Piece candidate=state.nextPiece(from, step);
00285 if (! candidate.isPiece())
00286 return;
00287 const Offset32 diff_reverse = Offset32(target,candidate.square());
00288 for (; candidate.isPiece();
00289 candidate=state.nextPiece(candidate.square(), step))
00290 {
00291 if (candidate.owner() != attack)
00292 return;
00293 const EffectContent effect
00294 = Ptype_Table.getEffect(candidate.ptypeO(), diff_reverse);
00295 if (! effect.hasEffect())
00296 return;
00297 out.push_back(std::make_pair(candidate.ptypeO(), candidate.square()));
00298 }
00299 }
00300
00301
00302
00303
00304
00305