analyzer.cc
Go to the documentation of this file.
00001 /* analyzer.cc
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>& /*moves*/,
00056                          int /*last_move*/)
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>& /*moves*/,
00071                     int /*last_move*/)
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     // treat chuai as safe
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>& /*history*/,
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   // better to takeback?
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   // get pv after pass
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 // ;;; Local Variables:
00374 // ;;; mode:c++
00375 // ;;; c-basic-offset:2
00376 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines