ntesukiRecord.tcc
Go to the documentation of this file.
00001 #include "ntesukiRecord.h"
00002 #include "osl/ntesuki/ntesukiMoveGenerator.h"
00003 #include "osl/ntesuki/ntesukiTable.h"
00004 #include "osl/checkmate/fixedDepthSearcher.h"
00005 #include "osl/checkmate/fixedDepthSearcher.tcc"
00006 #include "osl/checkmate/libertyEstimator.h"
00007 #include "osl/threatmate/richPredictor.h"
00008 #include "osl/threatmate/kfendPredictor.h"
00009 #include "osl/effect_util/effectUtil.h"
00010 #include "osl/checkmate/pawnCheckmateMoves.h"
00011 #include "osl/effect_util/unblockableCheck.h"
00012 #include "osl/pieceStand.h"
00013 
00014 template <osl::Player P>
00015 void
00016 osl::ntesuki::NtesukiRecord::
00017 propagate_proof(int pass_left)
00018 {
00019   for (RecordList::iterator it = same_board_list->begin();
00020        it != same_board_list->end(); it++)
00021   {
00022     if (&(*it) == this)
00023     {
00024       continue;
00025     }
00026     if (it->isDominatedByProofPieces<P>(this, pass_left))
00027     {
00028       if (!it->getValue<P>(pass_left).isFinal())
00029       {
00030         PieceStand ps = getPDPieces<P>(pass_left);
00031         TRY_DFPN;
00032         it->setResult<P>(pass_left, getValue<P>(pass_left),
00033                          getBestMove<P>(pass_left),
00034                          false, &ps);
00035         CATCH_DFPN;
00036       }
00037       else
00038       {
00039         if (!it->getValue<P>(pass_left).isCheckmateSuccess())
00040         {
00041 #ifdef DEBUG
00042           std::cerr << <"for " < P << "\tat pass_left:" << pass_left << "\tcontradiction occured\n" << *it << *this;
00043           ntesuki_assert(pass_left >0 ||
00044                          it->getValue<P>(pass_left) == ProofDisproof::LoopDetection() ||
00045                          getValue<P>(pass_left) == ProofDisproof::LoopDetection());
00046 #endif
00047         }
00048       }
00049     }
00050   }
00051 }
00052 
00053 template <osl::Player P>
00054 void
00055 osl::ntesuki::NtesukiRecord::
00056 propagate_disproof(int pass_left)
00057 {
00058   for (RecordList::iterator it = same_board_list->begin();
00059        it != same_board_list->end(); it++)
00060   {
00061     if (&(*it) == this)
00062     {
00063       continue;
00064     }
00065     if (it->isDominatedByDisproofPieces<P>(this, pass_left))
00066     {
00067       if (!it->getValue<P>(pass_left).isFinal())
00068       {
00069         PieceStand ps = getPDPieces<P>(pass_left);
00070         TRY_DFPN;
00071         it->setResult<P>(pass_left, getValue<P>(pass_left),
00072                          getBestMove<P>(pass_left),
00073                          false, &ps);
00074         CATCH_DFPN;
00075       }
00076       else
00077       {
00078         if (!it->getValue<P>(pass_left).isCheckmateFail())
00079         {
00080 #ifdef DEBUG
00081           std::cerr << <"for " < P << "\tat pass_left:" << pass_left << "\tcontradiction occured\n" << *it << *this;
00082           ntesuki_assert(it->getValue<P>(pass_left) == ProofDisproof::LoopDetection() ||
00083                          getValue<P>(pass_left) == ProofDisproof::LoopDetection());
00084 #endif
00085         }
00086       }
00087     }
00088   }
00089 }
00090 
00091 namespace osl
00092 {
00093   namespace ntesuki
00094   {
00095     template <class NumEffectState>
00096     Ptype getCheapestDrop(Player turn, const NumEffectState& state)
00097     {
00098       if (state.hasPieceOnStand(turn, PAWN))
00099         return PAWN;
00100       if (state.hasPieceOnStand(turn, LANCE))
00101         return LANCE;
00102       if (state.hasPieceOnStand(turn, KNIGHT))
00103         return KNIGHT;
00104       if (state.hasPieceOnStand(turn, SILVER))
00105         return SILVER;
00106       if (state.hasPieceOnStand(turn, GOLD))
00107         return GOLD;
00108       if (state.hasPieceOnStand(turn, BISHOP))
00109         return BISHOP;
00110       if (state.hasPieceOnStand(turn, ROOK))
00111         return ROOK;
00112       return PTYPE_EMPTY;
00113     }
00114     template <class NumEffectState>
00115     Ptype getSecondCheapestDrop(Player turn, const NumEffectState& state,
00116                                 Ptype cheapest)
00117     {
00118       if (cheapest == PAWN)
00119       {
00120         if (state.hasPieceOnStand(turn, LANCE))
00121           return LANCE;
00122         if (state.hasPieceOnStand(turn, KNIGHT))
00123           return KNIGHT;
00124         if (state.hasPieceOnStand(turn, SILVER))
00125           return SILVER;
00126         if (state.hasPieceOnStand(turn, GOLD))
00127           return GOLD;
00128         if (state.hasPieceOnStand(turn, BISHOP))
00129           return BISHOP;
00130         if (state.hasPieceOnStand(turn, ROOK))
00131           return ROOK;
00132       }
00133       return PTYPE_EMPTY;
00134     }
00135   }
00136 }
00137 
00138 /* ノードの準備
00139  * - 深さ固定 checkmate searcher を呼び出す
00140  */
00141 template <osl::Player T>
00142 bool
00143 osl::ntesuki::NtesukiRecord::
00144 setUpNode()
00145 {
00146   ntesuki_assert(state->turn() == turn());
00147 #ifndef NDEBUG
00148   const Player O = PlayerTraits<T>::opponent;
00149 #endif
00150   const bool under_attack = state->inCheck(T);
00151 
00152   ntesuki_assert(!state->inCheck(O));
00153 
00154   if (already_set_up)
00155   {
00156     return false;
00157   }
00158   already_set_up = true;
00159 
00160   /* 黒が攻めるときの Rzone は白の玉の位置 */
00161   rzone<BLACK>()[0] = Rzone(*state, WHITE);
00162   rzone<BLACK>()[1] = rzone<BLACK>()[0];
00163   /* 白が攻めるときの Rzone は黒の玉の位置 */
00164   rzone<WHITE>()[0] = Rzone(*state, BLACK);
00165   rzone<WHITE>()[1] = rzone<WHITE>()[0];
00166 
00167   if (!under_attack)
00168   {
00169     setUpAttackNode<T>();
00170   }
00171   else
00172   {
00173     setUpDefenseNode<T>();
00174   }
00175   return true;
00176 }
00177 
00178 template <osl::Player T>
00179 void
00180 osl::ntesuki::NtesukiRecord::
00181 setUpAttackNode()
00182 {
00183   const Player O = PlayerTraits<T>::opponent;
00184 
00185   /* 王手がかかっていないときは,相手の手番の即詰は失敗している.
00186    */
00187   NtesukiMove pass(Move::PASS(T));
00188   values<O>()[0] = ProofDisproof::NoCheckmate();
00189   best_move<O>()[0] = pass;
00190 
00191   if (!values<T>()[0].isFinal() &&
00192       state->template kingSquare<O>().isOnBoard())
00193   {
00194     /* 深さ固定 checkmate searcher を呼び出す */
00195     FixedDepthSearcher fixed_searcher(*state);
00196     PieceStand proof_pieces;
00197     Move check_move;
00198       
00199     const NtesukiResult result_fixed =
00200       fixed_searcher.hasCheckmateMove<T>(fixed_search_depth,
00201                                          check_move,
00202                                          proof_pieces);
00203     if (result_fixed.isCheckmateSuccess())
00204     {
00205       NtesukiMove best_move(check_move);
00206       best_move.setCheck();
00207       best_move.setImmediateCheckmate<T>();
00208         
00209       TRY_DFPN;
00210       setResult<T>(0, result_fixed,
00211                    best_move, false, &proof_pieces);
00212       CATCH_DFPN;
00213 
00214     }
00215     else if (result_fixed.isCheckmateFail())
00216     {
00217       PieceStand disproof_pieces = getPieceStand<O>();
00218       TRY_DFPN;
00219       setResult<T>(0, result_fixed,
00220                    NtesukiMove::INVALID(), false, &disproof_pieces);
00221       CATCH_DFPN;
00222     }
00223     else
00224     {
00225       TRY_DFPN;
00226       setResult<T>(0, result_fixed,
00227                    NtesukiMove::INVALID(), false);
00228       if (!values<T>()[1].isFinal())
00229       {
00230         setResult<T>(1, ProofDisproof(1, result_fixed.disproof()),
00231                      NtesukiMove::INVALID(), false);
00232       }
00233       CATCH_DFPN;
00234     }
00235   }
00236 }
00237 
00238 template <osl::Player T>
00239 void
00240 osl::ntesuki::NtesukiRecord::
00241 setUpDefenseNode()
00242 {
00243   const Player O = PlayerTraits<T>::opponent;
00244 
00245   /* 王手がかかっているので自動的に相手からの n 手すきがかかっている.
00246    */
00247   for (size_t i = 0; i < SIZE; ++i)
00248   {
00249     setNtesuki<O>(i);
00250   }
00251 
00252   /* もし自玉が盤面上にあるのなら, fixed depth searcher を呼び出す */
00253   if (!values<O>()[0].isFinal() &&
00254       state->template kingSquare<T>().isOnBoard())
00255   {
00256     /* 深さ固定 checkmate searcher を呼び出す */
00257     FixedDepthSearcher fixed_searcher(*state);
00258     PieceStand proof_pieces;
00259     //when called with Move::INVALID() as last move, PawnDropCheckmate is not checked for
00260     // the last move
00261     const NtesukiResult result_fixed =
00262       fixed_searcher.hasEscapeMove<O>(Move::INVALID(),
00263                                       fixed_search_depth,
00264                                       proof_pieces);
00265     if (result_fixed.isCheckmateSuccess())
00266     {
00267       TRY_DFPN;
00268       setResult<O>(0, result_fixed,
00269                    NtesukiMove::INVALID(), false, &proof_pieces);
00270       CATCH_DFPN;
00271     }
00272     else if (result_fixed.isCheckmateFail())
00273     {
00274       PieceStand disproof_pieces = getPieceStand<T>();
00275       NtesukiMove best_move = NtesukiMove::INVALID();
00276       /* might want to know the true best move, or
00277          mark best move as immediateCheckmate */
00278       TRY_DFPN;
00279       setResult<O>(0, result_fixed,
00280                    best_move, false, &disproof_pieces);
00281       CATCH_DFPN;
00282     }
00283     else
00284     {
00285       TRY_DFPN;
00286       setResult<O>(0, result_fixed,
00287                    NtesukiMove::INVALID(), false);
00288       if (!values<O>()[1].isFinal())
00289       {
00290         setResult<O>(1, ProofDisproof(1, result_fixed.disproof()),
00291                      NtesukiMove::INVALID(), false);
00292       }
00293       CATCH_DFPN;
00294     }
00295   }
00296 }
00297 
00298 /* 手生成を行う
00299  */
00300 template <osl::Player P>
00301 void
00302 osl::ntesuki::NtesukiRecord::
00303 generateMoves(NtesukiMoveList& move_list,
00304               int pass_left,
00305               bool all_moves)
00306 {
00307   const Player O = PlayerTraits<P>::opponent;
00308 
00309   if (all_moves)
00310   {
00311     mg->generateSlow(P, *state, move_list);
00312   }
00313   else
00314   {
00315     mg->generateWithRzoneSlow(P, *state, this, pass_left, move_list);
00316   }
00317   const Ptype cheapest = getCheapestDrop(P, *state);
00318   const Ptype secondCheapest = getSecondCheapestDrop(P, *state, cheapest);
00319 
00320   for (NtesukiMoveList::iterator move_it = move_list.begin();
00321        move_it != move_list.end(); move_it++)
00322   {
00323     const Move move = move_it->getMove();
00324 
00325     if (move_it->isPass())
00326     {
00327       unsigned int p_a = 1, d_a = 1, p_d = 1, d_d = 1;
00328       move_it->setHEstimates(p_a, d_a, p_d, d_d);
00329       continue;
00330     }
00331 
00332     unsigned int p_a = 1, d_a = 1, p_d = 1, d_d = 1;
00333 #if 0
00334     if (state->template kingSquare<O>().isOnBoard())
00335     {
00336       checkmate::LibertyEstimator::attackH(P, *state, move_it->getMove(),
00337                                            p_a, d_a);
00338     }
00339     if (state->template kingSquare<P>().isOnBoard())
00340     {
00341       checkmate::LibertyEstimator::defenseH(P, *state, move_it->getMove(),
00342                                             p_d, d_d);
00343     }
00344 #endif
00345 
00346     move_it->setHEstimates(p_a, d_a, p_d, d_d);
00347 
00348     const Square from = move.from();
00349     const Square to = move.to();
00350     const Ptype ptype = move.ptype();
00351 
00352     /* 駒のただ捨て(無駄合を含む)を記録 */
00353     if (state->hasEffectAt(O, to))
00354     {
00355       if (from.isPieceStand())
00356       {
00357         if ((ptype != cheapest)  && (ptype != secondCheapest))
00358         {
00359           move_it->setInterpose();
00360         }
00361         else if((! state->hasEffectAt(P, to))   // 自分の利きがない
00362                 && (! state->hasMultipleEffectAt(O, to)))// 焦点でもない
00363         {
00364           move_it->setInterpose();
00365         }
00366       }
00367       else if ((ptype != KING) &&
00368                (move.capturePtype() == PTYPE_EMPTY) &&
00369                (! state->hasMultipleEffectAt(P, to)))
00370       {
00371         move_it->setInterpose();
00372       }
00373     }
00374 
00375     /* 無駄な遠い利き */
00376     if (delay_lame_long &&
00377         from.isPieceStand() &&
00378         (isMajor(ptype) || ptype == LANCE) &&
00379         (! state->hasMultipleEffectAt(P, to)))
00380     {
00381       const Square opKingSquare = state->template kingSquare<O>();
00382       const Square myKingSquare = state->template kingSquare<P>();
00383       bool close_to_king = false;
00384       if (opKingSquare.isOnBoard())
00385       {
00386         int distance = (opKingSquare.x() - to.x()) * (opKingSquare.x() - to.x()) +
00387           (opKingSquare.y() - to.y()) * (opKingSquare.y() - to.y());
00388         if (distance < 19)
00389         {
00390           close_to_king = true;
00391         }
00392       }
00393       if (myKingSquare.isOnBoard())
00394       {
00395         int distance = (myKingSquare.x() - to.x()) * (myKingSquare.x() - to.x()) +
00396           (myKingSquare.y() - to.y()) * (myKingSquare.y() - to.y());
00397         if (distance < 19)
00398         {
00399           close_to_king = true;
00400         }
00401       }
00402 
00403       if (!close_to_king)
00404       {
00405         move_it->setLameLong();
00406         ntesuki_assert(move_it->isLameLong());
00407       }
00408     }
00409 
00410     /* 不成を記録 */
00411     if (from.isOnBoard() &&
00412         PawnCheckmateMoves::effectiveOnlyIfPawnCheckmate<P>(ptype, from, to))
00413     {
00414       move_it->setNoPromote();
00415     }
00416   }
00417 }
00418 
00419 struct
00420 DifferentMove
00421 {
00422   const osl::ntesuki::NtesukiMove* move;
00423 
00424   DifferentMove(const osl::ntesuki::NtesukiMove* move)
00425     :move(move) {}
00426 
00427   bool operator()(const osl::ntesuki::NtesukiMove& m)
00428   {
00429     return m.getMove() != move->getMove();
00430   }
00431 };
00432 
00433 template <osl::Player P>
00434 osl::PieceStand
00435 osl::ntesuki::NtesukiRecord::
00436 calcProofPiecesOr(int pass_left,
00437                   const osl::ntesuki::NtesukiMove& move)
00438 {
00439   ntesuki_assert(turn() == P);
00440   PieceStand proof_pieces;
00441 
00442   const NtesukiRecord* record_child = table->findWithMove(this, move);
00443   ntesuki_assert(record_child);
00444   proof_pieces = record_child->getPDPieces<P>(pass_left);
00445 
00446   if (move.isDrop())
00447   {
00448     proof_pieces.add(move.ptype());
00449   }
00450   else if (move.getMove().capturePtype() != PTYPE_EMPTY)
00451   {
00452     proof_pieces.trySub(unpromote(move.getMove().capturePtype()));
00453   }
00454   return proof_pieces;
00455 }
00456 
00457 template <osl::Player P>
00458 osl::PieceStand
00459 osl::ntesuki::NtesukiRecord::
00460 calcProofPiecesAnd(int pass_left)
00461 {
00462   ntesuki_assert(state->turn() == turn());
00463 
00464   const Player O = PlayerTraits<P>::opponent;
00465   ntesuki_assert(turn() != P);
00466   PieceStand proof_pieces;
00467 
00468   NtesukiMoveList moves;
00469   mg->generate<O>(*state, moves);
00470 
00471   for (NtesukiMoveList::iterator move_it = moves.begin();
00472        move_it != moves.end(); move_it++)
00473   {
00474     const NtesukiMove& move = *move_it;
00475     const NtesukiRecord* record_child = table->findWithMove(this, move);
00476     if (!record_child)
00477     {
00478       if (move.isCheck() ||
00479           (0 == pass_left &&
00480            (!move.isCheck() || move.isNoPromote())))
00481       {
00482         continue;
00483       }
00484       else
00485       {
00486         return piece_stand<P>();
00487       }
00488     }
00489     else if (!record_child->getValue<P>(pass_left).isCheckmateSuccess())
00490     {
00491       continue;
00492     }
00493 
00494     PieceStand proof_pieces_child = record_child->getPDPieces<P>(pass_left);
00495     proof_pieces = proof_pieces.max(proof_pieces_child);
00496   }
00497   
00498   /* monopolized pieces */
00499   ntesuki_assert(state);
00500   
00501   if (! effect_util::UnblockableCheck::isMember(O, *state))
00502   {
00503     for (unsigned int i=0; i<PieceStand::order.size(); ++i)
00504     {
00505       const Ptype ptype = PieceStand::order[i];
00506       if (!state->hasPieceOnStand(O, ptype))
00507       {
00508         const int diff = state->countPiecesOnStand(P, ptype) - proof_pieces.get(ptype);
00509         ntesuki_assert(diff >= 0);
00510         if (diff) proof_pieces.add(ptype, diff);
00511       }
00512     }
00513   }
00514   return proof_pieces;
00515 }
00516 
00517 template <osl::Player A>
00518 void
00519 osl::ntesuki::NtesukiRecord::
00520 setProofPieces(int pass_left,
00521                const NtesukiResult& r,
00522                const NtesukiMove& best_move,
00523                const PieceStand* ps)
00524 {
00525   const Player D = PlayerTraits<A>::opponent;
00526   PieceStand proof_pieces;
00527 
00528   if (ps)
00529   {
00530     /* Immediate checkmate or dominance or oracel prover light
00531      */
00532     proof_pieces = *ps;
00533   }
00534   else if (best_move.isPass())
00535   {
00536     const NtesukiRecord* record_pass = table->findWithMove(this, best_move);
00537     ntesuki_assert(record_pass);
00538     proof_pieces = record_pass->getPDPieces<A>(pass_left - 1);
00539   }
00540   else if (best_move.isValid())
00541   {
00542     proof_pieces = calcProofPiecesOr<A>(pass_left, best_move);
00543   }
00544   else
00545   {
00546     /* set_proof_tree_AND
00547      */
00548     proof_pieces = calcProofPiecesAnd<A>(pass_left);
00549   }
00550 
00551   ntesuki_assert(piece_stand<A>().template hasMoreThan<BLACK>(proof_pieces));
00552   for (unsigned int j = pass_left; j < SIZE; j++)
00553   {
00554     setPDPieces<A>(j, proof_pieces);
00555     setPDPieces<D>(j, proof_pieces);//for attack back
00556   }
00557 }
00558 
00559 template <osl::Player P>
00560 void
00561 osl::ntesuki::NtesukiRecord::
00562 setDisproofPieces(int pass_left,
00563                   const NtesukiResult& r,
00564                   const NtesukiMove& m,
00565                   const PieceStand* ps)
00566 {
00567   const Player O = PlayerTraits<P>::opponent;
00568   PieceStand disproof_pieces;
00569 
00570   if (ps)
00571   {
00572     /* Immediate checkmate or dominance
00573      */
00574     disproof_pieces = *ps;
00575   }
00576   else if (m.isPass())
00577   {
00578     const NtesukiRecord* record_pass = table->findWithMove(this, m);
00579     ntesuki_assert(record_pass);
00580     
00581     disproof_pieces = record_pass->getPDPieces<P>(pass_left - 1);
00582   }
00583   else if (m.isValid())
00584   {
00585     /* set_disproof_tree_OR
00586      */
00587     ntesuki_assert(turn() != P);
00588     
00589     const NtesukiRecord* record_child = table->findWithMove(this, m);
00590     ntesuki_assert(record_child);
00591     disproof_pieces = record_child->getPDPieces<P>(pass_left);
00592     
00593     if (m.isDrop())
00594     {
00595       disproof_pieces.add(m.ptype());
00596     }
00597     else if (m.getMove().capturePtype() != PTYPE_EMPTY)
00598     {
00599       disproof_pieces.trySub(unpromote(m.getMove().capturePtype()));
00600     }
00601   }
00602   else
00603   {
00604     /* set_disproof_tree_AND
00605      */
00606     ntesuki_assert(turn() == P);
00607 
00608     NtesukiMoveList moves;
00609     generateMoves<P>(moves, 0, true);
00610 
00611     for (NtesukiMoveList::iterator move_it = moves.begin();
00612          move_it != moves.end(); move_it++)
00613     {
00614       const NtesukiRecord* record_child = table->findWithMove(this, *move_it);
00615       if (!record_child)
00616       {
00617         if (move_it->isPass() ||
00618             (0 == pass_left &&
00619              (!move_it->isCheck() || move_it->isNoPromote())))
00620         {
00621           continue;
00622         }
00623         else
00624         {
00625           setPDPieces<P>(pass_left, piece_stand<O>());
00626           return;
00627         }
00628         
00629       }
00630 
00631       PieceStand disproof_pieces_child = record_child->getPDPieces<P>(pass_left);
00632 
00633       disproof_pieces = disproof_pieces.max(disproof_pieces_child);
00634     }
00635 
00636     /* monopolized pieces */
00637     ntesuki_assert(state);
00638     ntesuki_assert(state->turn() == turn());
00639 
00640     //if (! effect_util::UnblockableCheck::isMember(P, *state))
00641     if (true)
00642     {
00643       for (unsigned int i=0; i<PieceStand::order.size(); ++i)
00644       {
00645         const Ptype ptype = PieceStand::order[i];
00646         if (!state->hasPieceOnStand(P, ptype))
00647         {
00648           const int diff = state->countPiecesOnStand(O, ptype) - disproof_pieces.get(ptype);
00649           ntesuki_assert(diff >= 0);
00650           if (diff) disproof_pieces.add(ptype, diff);
00651         }
00652       }
00653     }
00654   }
00655 
00656 #ifndef NDEBUG
00657   ntesuki_assert(piece_stand<O>().isSuperiorOrEqualTo(disproof_pieces))
00658 #endif
00659   setPDPieces<P>(pass_left, disproof_pieces);
00660 }
00661 
00662 template <osl::Player P>
00663 void
00664 osl::ntesuki::NtesukiRecord::
00665 setFinal(int pass_left,
00666          const NtesukiResult& r,
00667          const NtesukiMove& m,
00668          const PieceStand* ps)
00669 {
00670   if (r.isCheckmateSuccess() && pass_count)
00671   {
00672     final = true;
00673   }
00674   const Player O = PlayerTraits<P>::opponent;
00675 
00676   if (r.isCheckmateSuccess())
00677   {
00678     TRY_DFPN;
00679     setProofPieces<P>(pass_left, r, m, ps);
00680     CATCH_DFPN;
00681 
00682     for (unsigned int j = pass_left; j < SIZE; j++)
00683     {
00684       values<P>   ()[j] = r;
00685       best_move<P>()[j] = m;
00686       
00687       if (!values<O>()[j].isCheckmateFail())
00688       {
00689         ntesuki_assert(!values<O>()[j].isCheckmateSuccess());
00690         
00691         values<O>   ()[j] = ProofDisproof::AttackBack();
00692         best_move<O>()[j] = m;
00693       }
00694     }
00695 
00696     if (use_dominance)
00697     {
00698       propagate_proof<P>(pass_left);
00699     }
00700     
00701 #ifdef COLLECT_GARBAGE
00702     //collect garbage
00703     if (turn() == P)
00704     {
00705       DifferentMove different_move(best_move<P>()[pass_left]);
00706       moves.remove_if(different_move);
00707     }
00708 #endif
00709   }
00710   else //fail
00711   {
00712     ntesuki_assert(r.isCheckmateFail());
00713     setDisproofPieces<P>(pass_left, r, m, ps);
00714 
00715     values<P>()[pass_left] = r;
00716     best_move<P>()[pass_left] = m;
00717 
00718     if (pass_left != 0 &&
00719         !values<P>()[pass_left - 1].isCheckmateFail()
00720         )
00721     {
00722       setFinal<P>(pass_left - 1, r, m, ps);
00723     }
00724 
00725     if (use_dominance)
00726     {
00727       propagate_disproof<P>(pass_left);
00728     }
00729 
00730 #ifdef COLLECT_GARBAGE
00731     //collect garbage
00732     if (turn() != P)
00733     {
00734       for (NtesukiMoveList::iterator move_it = moves.begin();
00735            move_it != moves.end(); move_it++)
00736       {
00737         bool not_best_move = true;
00738         for (size_t i = 0; i < SIZE; i++)
00739         {
00740           if (&(*move_it) != best_move<O>()[pass_left]) not_best_move = false;
00741         }
00742 
00743         if (not_best_move)
00744         {
00745           move_it->clearRecord();
00746         }
00747       }
00748     }
00749 #endif
00750   }
00751 }
00752 
00753 /* set result
00754  *  also propagate values to deeper threats if checkmate success
00755  *  P is the attacker
00756  */
00757 template <osl::Player P>
00758 void
00759 osl::ntesuki::NtesukiRecord::
00760 setResult(int i,                        //i tesuki
00761           const NtesukiResult& r,       //pn/dn of this node at i
00762           const NtesukiMove& m,         //best move
00763           bool bs,                      //by simulation
00764           const PieceStand* ps          //when set by fixed depth searcher
00765           )
00766 {
00767   ++written_count;
00768   /* TODO something that should dissapear,
00769    * as this is a result of a loop gaining/losing pieces
00770    */
00771   ntesuki_assert(!values<P>()[i].isFinal());
00772   ntesuki_assert(best_move<P>()[i].isInvalid());
00773 
00774   by_simulation = bs;
00775 
00776   if (r.isFinal())
00777   {
00778     value_before_final = values<P>()[i];//remember the last pdp for latter use
00779     setFinal<P>(i, r, m, ps);
00780   }
00781   else
00782   {
00783     values<P>()[i] = r;
00784     /* Dominance between lambda order */
00785     int order = 0;
00786     for (; order < i; order++)
00787     {
00788       if (values<P>()[order].disproof() >  r.disproof())
00789       {
00790         values<P>()[order] = ProofDisproof(values<P>()[order].proof(),
00791                                            r.disproof());
00792       }
00793     }
00794     ++order;
00795     for (; order < (int)SIZE; order++)
00796     {
00797       /* L^order が AttackBack等で既に disproof されている場合 */
00798       if (values<P>()[order].isCheckmateFail()) continue;
00799       
00800       if (values<P>()[order].disproof() <  r.disproof())
00801       {
00802         values<P>()[order] = ProofDisproof(values<P>()[order].proof(),
00803                                            r.disproof());
00804       }
00805     }
00806   }
00807   
00808 #ifndef NDEBUG
00809   if (by_simulation) ntesuki_assert(r.isFinal());
00810 
00811   if (m.isValid())
00812   {
00813     ntesuki_assert(r.isFinal());
00814   }
00815 
00816   if (key.turn() == P &&
00817       values<P>()[i].isCheckmateSuccess())
00818   {
00819     ntesuki_assert(m.isValid());
00820   }
00821   else if (key.turn() != P &&
00822            values<P>()[i].isCheckmateFail())
00823   {
00824     /* ntesuki_assert(m); */
00825   }
00826 #endif
00827 }
00828 
00829 /* See if this is dominated by the proof pieces for record
00830  */
00831 template <osl::Player P>
00832 bool
00833 osl::ntesuki::NtesukiRecord::
00834 isDominatedByProofPieces(const NtesukiRecord* record,
00835                          int pass_left) const
00836 {
00837   if (!record->getValue<P>(pass_left).isCheckmateSuccess()) return false;
00838 
00839   const PieceStand& my_stand = piece_stand<P>();
00840   const PieceStand& other_pp = record->getPDPieces<P>(pass_left);
00841 
00842   return my_stand.isSuperiorOrEqualTo(other_pp);
00843 }
00844 
00845 /* See if this is dominated by the disproof pieces for record
00846  */
00847 template <osl::Player P>
00848 bool
00849 osl::ntesuki::NtesukiRecord::
00850 isDominatedByDisproofPieces(const NtesukiRecord* record,
00851                             int pass_left) const
00852 {
00853   const Player O = PlayerTraits<P>::opponent;
00854   if (!record->getValue<P>(pass_left).isCheckmateFail()) return false;
00855   
00856   const PieceStand& my_stand = piece_stand<O>();
00857   const PieceStand& other_dp = record->getPDPieces<P>(pass_left);
00858 
00859   return my_stand.isSuperiorOrEqualTo(other_dp);
00860 }
00861 
00862 /* See if this dominated by record
00863  */
00864 template <osl::Player P>
00865 bool
00866 osl::ntesuki::NtesukiRecord::
00867 isBetterFor(NtesukiRecord* record)
00868 {
00869   const PieceStand& mystand = key.getPieceStand();
00870   const PieceStand& opstand = record->key.getPieceStand();
00871   
00872   if (mystand == opstand) return false;
00873   return mystand.hasMoreThan<P>(opstand);
00874 }
00875 
00876 /* =============================================================================
00877  * accessors
00878  */
00879 template <osl::Player A>
00880 bool osl::ntesuki::NtesukiRecord::
00881 useOld(int pass_left) const
00882 {
00883   return use_old<A>()[pass_left];
00884 }
00885 
00886 template <osl::Player A>
00887 void osl::ntesuki::NtesukiRecord::
00888 setUseOld(int pass_left,
00889            bool value)
00890 {
00891   use_old<A>()[pass_left] = value;
00892 }
00893 
00894 
00895 template <osl::Player P>
00896 bool osl::ntesuki::NtesukiRecord::
00897 isLoopWithPath(int pass_left,
00898                const PathEncoding& path) const
00899 {
00900   typedef osl::ntesuki::PathEncodingList list_t;
00901   const list_t& list = loop_path_list<P>()[pass_left];
00902   for (list_t::const_iterator it = list.begin(); it != list.end(); it++)
00903   {
00904     if (*it == path)
00905     {
00906       return true;
00907     }
00908   }
00909   return false;
00910 }
00911 
00912 template <osl::Player P>
00913 void  osl::ntesuki::NtesukiRecord::
00914 setLoopWithPath(int pass_left,
00915                 const PathEncoding& path)
00916 {
00917   typedef osl::ntesuki::PathEncodingList list_t;
00918   list_t& list = loop_path_list<P>()[pass_left];
00919   list.push_front(path);
00920 }
00921 
00922 template <osl::Player P>
00923 const osl::ntesuki::NtesukiResult
00924 osl::ntesuki::NtesukiRecord::
00925 getValue(int i) const
00926 {
00927   ++read_count;
00928   return  values<P>()[i];
00929 }
00930 
00931 template <osl::Player P>
00932 const osl::ntesuki::NtesukiResult
00933 osl::ntesuki::NtesukiRecord::
00934 getValueWithPath(int i,
00935                  const PathEncoding path) const
00936 {
00937   ++read_count;
00938   if (values<P>()[i].isFinal()) return values<P>()[i];
00939   if (isLoopWithPath<P>(i, path))
00940   {
00941     return ProofDisproof::LoopDetection();
00942   }
00943   return values<P>()[i];
00944 }
00945 
00946 
00947 template <osl::Player P>
00948 const osl::ntesuki::NtesukiResult
00949 osl::ntesuki::NtesukiRecord::
00950 getValueOr(int max_pass_left,
00951            const PathEncoding path,
00952            IWScheme iwscheme) const
00953 {
00954   ++read_count;
00955   if (values<P>()[max_pass_left].isFinal()) return values<P>()[max_pass_left];
00956   if (isLoopWithPath<P>(max_pass_left, path))
00957   {
00958     return ProofDisproof::LoopDetection();
00959   }
00960 
00961   NtesukiResult ret = values<P>()[max_pass_left];
00962 
00963   if (iwscheme == pn_iw)
00964   {
00965     unsigned int min_proof = ret.proof();
00966     for (int pass_left = 0; pass_left < max_pass_left; ++pass_left)
00967     {
00968       if (isLoopWithPath<P>(pass_left, path)) continue;
00969       const NtesukiResult result = values<P>()[pass_left];
00970       ntesuki_assert(result.disproof() <= ret.disproof());
00971       min_proof = std::min(min_proof, result.proof());
00972     }
00973     ret = NtesukiResult(min_proof, ret.disproof());
00974   }
00975   else if (iwscheme == strict_iw)
00976   {
00977     for (int pass_left = 0; pass_left < max_pass_left; ++pass_left)
00978     {
00979       if (isLoopWithPath<P>(pass_left, path)) continue;
00980       const NtesukiResult result = values<P>()[pass_left];
00981       if (!result.isCheckmateFail())
00982       {
00983         ret = result;
00984         break;
00985       }
00986     }
00987   }
00988   return  ret;
00989 }
00990 
00991 template <osl::Player P>
00992 const osl::ntesuki::NtesukiResult
00993 osl::ntesuki::NtesukiRecord::
00994 getValueAnd(int max_pass_left,
00995             const PathEncoding path,
00996             IWScheme iwscheme,
00997             PSScheme psscheme) const
00998 {
00999   ++read_count;
01000   if (values<P>()[max_pass_left].isFinal()) return values<P>()[max_pass_left];
01001   if (isLoopWithPath<P>(max_pass_left, path))
01002   {
01003     return ProofDisproof::LoopDetection();
01004   }
01005 
01006   NtesukiResult ret = values<P>()[max_pass_left];
01007   if (psscheme && max_pass_left != 0)
01008   {
01009     /* max_pass_left - 1 まで敵の PN を見て,
01010      * こちらの DN より小さかったら先に読む.
01011      */
01012     const Player O = PlayerTraits<P>::opponent;
01013     const NtesukiResult result_opponent = getValueOr<O>(max_pass_left - 1,
01014                                                           path,
01015                                                           iwscheme);
01016     if (!result_opponent.isFinal() &&
01017         result_opponent.proof() + inversion_cost < ret.disproof())
01018     {
01019       ret = ProofDisproof(result_opponent.disproof(), //最も単純なモデルでは ret.proof()
01020                           result_opponent.proof() + inversion_cost);
01021     }
01022   }
01023   return  ret;
01024 }
01025 
01026 template <osl::Player P>
01027 const osl::ntesuki::NtesukiMove&
01028 osl::ntesuki::NtesukiRecord::
01029 getBestMove(int i) const
01030 {
01031   return best_move<P>()[i];
01032 }
01033 
01034 template <osl::Player P>
01035 bool
01036 osl::ntesuki::NtesukiRecord::
01037 isNtesuki(int pass_left) const
01038 {
01039   return is_ntesuki<P>()[pass_left];
01040 }
01041 
01042 template <osl::Player P>
01043 void
01044 osl::ntesuki::NtesukiRecord::
01045 setNtesuki(int pass_left)
01046 {
01047   //ntesuki_assert(false == is_ntesuki<P>()[pass_left]);
01048   is_ntesuki<P>()[pass_left] = true;
01049 }
01050 
01051 template <osl::Player P>
01052 bool
01053 osl::ntesuki::NtesukiRecord::
01054 hasTriedPropagatedOracle(int pass_left) const
01055 {
01056   return propagated_oracle<P>()[pass_left];
01057 }
01058 
01059 template <osl::Player P>
01060 void
01061 osl::ntesuki::NtesukiRecord::
01062 triedPropagatedOracle(int pass_left)
01063 {
01064   assert(false == propagated_oracle<P>()[pass_left]);
01065   propagated_oracle<P>()[pass_left] = true;
01066 }
01067 
01068 template <osl::Player P>
01069 bool
01070 osl::ntesuki::NtesukiRecord::
01071 isByFixed() const
01072 {
01073   return by_fixed<P>();
01074 }
01075 
01076 template <osl::Player P>
01077 osl::PieceStand
01078 osl::ntesuki::NtesukiRecord::
01079 getPDPieces(int pass_left) const
01080 {
01081   return pdpieces<P>()[pass_left];
01082 }
01083 
01084 template <osl::Player P>
01085 void
01086 osl::ntesuki::NtesukiRecord::
01087 setPDPieces(int pass_left, const PieceStand p)
01088 {
01089   pdpieces<P>()[pass_left] = p;
01090 }
01091 
01092 // ;;; Local Variables:
01093 // ;;; mode:c++
01094 // ;;; c-basic-offset:2
01095 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines