00001
00002
00003 #include "osl/annotate/analyzer.h"
00004 #include "osl/checkmate/dualDfpn.h"
00005 #include "osl/checkmate/dfpn.h"
00006 #ifdef OSL_DFPN_SMP
00007 # include "osl/checkmate/dfpnParallel.h"
00008 #endif
00009 #include "osl/move_generator/legalMoves.h"
00010 #include "osl/threatmate/mlPredictor.h"
00011 #include "osl/effect_util/neighboring8Direct.h"
00012 #include "osl/eval/see.h"
00013 #include "osl/eval/ml/openMidEndingEval.h"
00014 #include "osl/game_playing/alphaBetaPlayer.h"
00015 #include "osl/game_playing/gameState.h"
00016 #include <boost/foreach.hpp>
00017
00018 const int checkmate_limit = 1000000/2;
00019
00020 osl::annotate::
00021 Analyzer::~Analyzer()
00022 {
00023 }
00024
00025 osl::annotate::Trivalent osl::annotate::
00026 Analyzer::isCheckmate(NumEffectState& state, Move& best_move, bool attack, size_t *node_count)
00027 {
00028 #ifdef OSL_DFPN_SMP
00029 checkmate::DfpnParallel dfpn;
00030 #else
00031 checkmate::Dfpn dfpn;
00032 #endif
00033 checkmate::DfpnTable table(attack ? state.turn() : alt(state.turn()));
00034 dfpn.setTable(&table);
00035 const PathEncoding path(state.turn());
00036 Move test;
00037 const ProofDisproof pdp
00038 = attack
00039 ? dfpn.hasCheckmateMove(state, HashKey(state), path, checkmate_limit, test)
00040 : dfpn.hasEscapeMove(state, HashKey(state), path, checkmate_limit*2, Move::PASS(alt(state.turn())));
00041 if (node_count)
00042 *node_count = dfpn.nodeCount();
00043 if (pdp.isCheckmateSuccess())
00044 {
00045 best_move = test;
00046 return True;
00047 }
00048 return pdp.isFinal() ? False : Unknown;
00049 }
00050
00051
00052
00053 void osl::annotate::
00054 CheckmateAnalyzer::match(AnalysesResult& shared,
00055 const NumEffectState& src, const vector<Move>& ,
00056 int )
00057 {
00058 if (! src.inCheck())
00059 {
00060 shared.checkmate = False;
00061 return;
00062 }
00063 NumEffectState s(src);
00064 Move dummy;
00065 shared.checkmate = isCheckmate(s, dummy, false);
00066 }
00067
00068 void osl::annotate::
00069 CheckmateWin::match(AnalysesResult& shared,
00070 const NumEffectState& src, const vector<Move>& ,
00071 int )
00072 {
00073 if (src.inCheck())
00074 {
00075 shared.checkmate_win = False;
00076 return;
00077 }
00078 NumEffectState s(src);
00079 shared.checkmate_win = isCheckmate(s, shared.checkmate_move, true);
00080 }
00081
00082 void osl::annotate::
00083 EscapeFromCheck::match(AnalysesResult& shared,
00084 const NumEffectState& src, const vector<Move>& moves,
00085 int last_move)
00086 {
00087 shared.escape_from_check = matchMain(src, moves, last_move) ? True : False;
00088 }
00089
00090 bool osl::annotate::
00091 EscapeFromCheck::matchMain(const NumEffectState& src, const vector<Move>& moves,
00092 int last_move)
00093 {
00094 if (last_move < 0)
00095 return false;
00096 if (moves[last_move].ptype() == KING)
00097 {
00098 if (src.hasEffectAt(src.turn(), moves[last_move].from()))
00099 return true;
00100 if (moves[last_move].capturePtype() != PTYPE_EMPTY)
00101 {
00102 const PtypeO captured = moves[last_move].capturePtypeO();
00103 if (src.hasEffectIf(captured, moves[last_move].to(),
00104 moves[last_move].from()))
00105 return true;
00106 }
00107 return false;
00108 }
00109 const PieceMask pin = src.pin(alt(src.turn()));
00110 if (pin.test(src.pieceAt(moves[last_move].to()).number()))
00111 return true;
00112 if (moves[last_move].capturePtype() != PTYPE_EMPTY)
00113 {
00114 const PtypeO captured = moves[last_move].capturePtypeO();
00115 if (src.hasEffectIf(captured, moves[last_move].to(),
00116 src.kingSquare(alt(src.turn()))))
00117 return true;
00118 }
00119 return false;
00120 }
00121
00122 void osl::annotate::
00123 ThreatmateAnalyzer::match(AnalysesResult& shared,
00124 const NumEffectState& src, const vector<Move>& moves,
00125 int last_move)
00126 {
00127 if (src.inCheck())
00128 {
00129 shared.threatmate = False;
00130 return;
00131 }
00132 NumEffectState s(src);
00133 s.changeTurn();
00134 shared.threatmate = isCheckmate(s, shared.threatmate_move, true, &shared.threatmate_node_count);
00135 threatmate::MlPredictor predictor;
00136 shared.threatmate_probability = (last_move >= 0) ? predictor.probability(src, moves[last_move]) : 0.0;
00137 }
00138
00139
00140 void osl::annotate::
00141 CheckmateForCapture::match(AnalysesResult& shared,
00142 const NumEffectState& src, const vector<Move>& history,
00143 int last_move)
00144 {
00145 if (last_move < 0 || shared.escape_from_check == True)
00146 return;
00147 const Square last_to = history[last_move].to();
00148 if (! src.hasEffectAt(src.turn(), last_to))
00149 return;
00150 MoveVector all, moves;
00151 LegalMoves::generate(src, all);
00152 BOOST_FOREACH(Move m, all)
00153 if (m.to() == last_to)
00154 moves.push_back(m);
00155 if (moves.empty())
00156 return;
00157 BOOST_FOREACH(Move move, moves)
00158 {
00159 DualDfpn dfpn;
00160 NumEffectState s(src);
00161 s.makeMove(move);
00162 Move checkmate_move;
00163 const bool checkmate
00164 #ifdef OSL_DFPN_SMP
00165 = dfpn.isWinningStateParallel(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00166 checkmate_move, move);
00167 #else
00168 = dfpn.isWinningState(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00169 checkmate_move, move);
00170 #endif
00171 if (checkmate)
00172 {
00173 ++shared.checkmate_for_capture.checkmate_count;
00174 if (See::see(src, move) > 0)
00175 ++shared.checkmate_for_capture.see_plus_checkmate_count;
00176 }
00177 else
00178 ++shared.checkmate_for_capture.safe_count;
00179 }
00180 }
00181
00182 void osl::annotate::
00183 CheckmateForEscape::match(AnalysesResult& shared,
00184 const NumEffectState& src, const vector<Move>& history,
00185 int last_move)
00186 {
00187 if (last_move < 0)
00188 return;
00189 const Square last_to = history[last_move].to();
00190 if (! src.inCheck() || src.hasEffectAt(src.turn(), last_to))
00191 return;
00192
00193 MoveVector moves;
00194 LegalMoves::generate(src, moves);
00195 if (moves.empty())
00196 return;
00197 BOOST_FOREACH (Move move, moves)
00198 {
00199
00200 const Square to = move.to();
00201 if (src.hasEffectAt(alt(src.turn()), to)
00202 && (src.countEffect(src.turn(), to)
00203 - (move.isDrop() ? 0 : 1) == 0))
00204 {
00205 ++shared.checkmate_for_escape.safe_count;
00206 continue;
00207 }
00208
00209 DualDfpn dfpn;
00210 NumEffectState s(src);
00211 s.makeMove(move);
00212 Move checkmate_move;
00213 const bool checkmate
00214 #ifdef OSL_DFPN_SMP
00215 = dfpn.isWinningStateParallel(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00216 checkmate_move, move);
00217 #else
00218 = dfpn.isWinningState(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00219 checkmate_move, move);
00220 #endif
00221 if (checkmate)
00222 ++shared.checkmate_for_escape.checkmate_count;
00223 else
00224 ++shared.checkmate_for_escape.safe_count;
00225 }
00226 }
00227
00228 bool osl::annotate::
00229 ThreatmateIfMorePieces::suitable(const NumEffectState& state, Piece p)
00230 {
00231
00232
00233
00234 if (state.hasEffectAt(p.owner(), p.square()))
00235 {
00236 if (state.longEffectAt(p.square(), alt(p.owner())).any())
00237 return false;
00238 if (Neighboring8Direct::hasEffect
00239 (state, p.ptypeO(), p.square(), state.kingSquare(p.owner())))
00240 return false;
00241 }
00242 return true;
00243 }
00244
00245 void osl::annotate::
00246 ThreatmateIfMorePieces::match(AnalysesResult& shared,
00247 const NumEffectState& src, const vector<Move>& ,
00248 int last_move)
00249 {
00250 if (last_move < 0)
00251 return;
00252 if (src.inCheck() || shared.threatmate == True)
00253 return;
00254
00255 const PieceMask effected_pieces = src.effectedMask(alt(src.turn())) & src.piecesOnBoard(src.turn());
00256 BOOST_FOREACH(Ptype ptype, PieceStand::order)
00257 {
00258 DualDfpn dfpn;
00259 if (src.hasPieceOnStand(src.turn(), ptype))
00260 {
00261 NumEffectState s(src.emulateHandPiece(src.turn(), alt(src.turn()), ptype));
00262 s.setTurn(alt(src.turn()));
00263
00264 Move hand_move;
00265 const bool threatmate
00266 #ifdef OSL_DFPN_SMP
00267 = dfpn.isWinningStateParallel(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00268 hand_move, Move::PASS(alt(s.turn())));
00269 #else
00270 = dfpn.isWinningState(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00271 hand_move, Move::PASS(alt(s.turn())));
00272 #endif
00273 if (threatmate)
00274 shared.threatmate_if_more_pieces.hand_ptype.push_back(ptype);
00275 continue;
00276 }
00277 mask_t m = effected_pieces.getMask(Ptype_Table.getIndex(ptype))
00278 & Ptype_Table.getMaskLow(ptype);
00279 if (! m.any())
00280 continue;
00281
00282 Piece p = src.pieceOf(m.takeOneBit());
00283 while (m.any() && !suitable(src, p))
00284 p = src.pieceOf(m.takeOneBit());
00285 if (! suitable(src, p))
00286 continue;
00287 assert(p.isOnBoard());
00288 assert(unpromote(p.ptype()) == ptype);
00289 NumEffectState s(src.emulateCapture(p, alt(src.turn())));
00290 s.setTurn(alt(src.turn()));
00291 if (s.inCheck() || s.inCheck(alt(s.turn())))
00292 continue;
00293
00294 Move board_move;
00295 const bool threatmate
00296 #ifdef OSL_DFPN_SMP
00297 = dfpn.isWinningStateParallel(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00298 board_move, Move::PASS(alt(s.turn())));
00299 #else
00300 = dfpn.isWinningState(checkmate_limit, s, HashKey(s), PathEncoding(s.turn()),
00301 board_move, Move::PASS(alt(s.turn())));
00302 #endif
00303 if (threatmate)
00304 shared.threatmate_if_more_pieces.board_ptype.push_back(p);
00305 }
00306 }
00307
00308 namespace osl
00309 {
00310 namespace
00311 {
00312 MoveWithComment do_search(const NumEffectState& src, int seconds)
00313 {
00314 game_playing::AlphaBeta2OpenMidEndingEvalPlayer player;
00315 player.setNextIterationCoefficient(1.0);
00316 player.setVerbose(0);
00317 player.setTableLimit(100000, 200);
00318
00319 game_playing::GameState state(src);
00320 search::TimeAssigned time(MilliSeconds::Interval(seconds*1000));
00321 return player.searchWithSecondsForThisMove(state, time);
00322 }
00323 }
00324 }
00325
00326
00327 void osl::annotate::
00328 Vision3::match(AnalysesResult& shared,
00329 const NumEffectState& src, const vector<Move>& history,
00330 int last_move)
00331 {
00332 if (last_move < 0)
00333 return;
00334 if (src.inCheck() || shared.threatmate == True
00335 || shared.checkmate == True || shared.checkmate_win == True
00336 || shared.escape_from_check == True)
00337 return;
00338
00339
00340 search::MoveWithComment response = do_search(src, 1);
00341 if (! response.move.isNormal()
00342 || response.move.to() == history[last_move].to())
00343 return;
00344
00345 NumEffectState s = src;
00346 s.changeTurn();
00347
00348
00349 MoveWithComment pv = do_search(s, 2);
00350 if (! pv.move.isNormal())
00351 return;
00352 if (See::see(s, pv.move) > 0) {
00353 if (pv.move.from() == history[last_move].to())
00354 return;
00355 const Piece p = s.pieceAt(pv.move.to());
00356 if (p.isPiece()
00357 && ! s.hasEffectAt(alt(s.turn()), pv.move.to())
00358 && src.effectedChanged(alt(s.turn())).test(p.number()))
00359 return;
00360 }
00361 typedef eval::ml::OpenMidEndingEval eval_t;
00362 shared.vision.cur_eval
00363 = eval_t(s).value() * 200.0/eval_t::captureValue(newPtypeO(WHITE,PAWN));
00364 if (pv.value*eval::delta(s.turn())
00365 < shared.vision.cur_eval*eval::delta(s.turn())+200)
00366 return;
00367 shared.vision.eval = pv.value;
00368 shared.vision.pv.push_back(pv.move);
00369 BOOST_FOREACH(Move m, pv.moves)
00370 shared.vision.pv.push_back(m);
00371 }
00372
00373
00374
00375
00376