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
00140
00141 template <osl::Player T>
00142 bool
00143 osl::ntesuki::NtesukiRecord::
00144 setUpNode()
00145 {
00146 ntesuki_assert(state->getTurn() == 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
00161 rzone<BLACK>()[0] = Rzone(*state, WHITE);
00162 rzone<BLACK>()[1] = rzone<BLACK>()[0];
00163
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 getKingPosition<O>().isOnBoard())
00193 {
00194
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
00246
00247 for (size_t i = 0; i < SIZE; ++i)
00248 {
00249 setNtesuki<O>(i);
00250 }
00251
00252
00253 if (!values<O>()[0].isFinal() &&
00254 state->template getKingPosition<T>().isOnBoard())
00255 {
00256
00257 FixedDepthSearcher fixed_searcher(*state);
00258 PieceStand proof_pieces;
00259
00260
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
00277
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 getKingPosition<O>().isOnBoard())
00335 {
00336 checkmate::LibertyEstimator::attackH(P, *state, move_it->getMove(),
00337 p_a, d_a);
00338 }
00339 if (state->template getKingPosition<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 Position from = move.from();
00349 const Position to = move.to();
00350 const Ptype ptype = move.ptype();
00351
00352
00353 if (state->hasEffectBy(O, to))
00354 {
00355 if (from.isPieceStand())
00356 {
00357 if ((ptype != cheapest) && (ptype != secondCheapest))
00358 {
00359 move_it->setInterpose();
00360 }
00361 else if((! state->hasEffectBy(P, to))
00362 && (! state->hasMultipleEffectBy(O, to)))
00363 {
00364 move_it->setInterpose();
00365 }
00366 }
00367 else if ((ptype != KING) &&
00368 (move.capturePtype() == PTYPE_EMPTY) &&
00369 (! state->hasMultipleEffectBy(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->hasMultipleEffectBy(P, to)))
00380 {
00381 const Position opKingPosition = state->template getKingPosition<O>();
00382 const Position myKingPosition = state->template getKingPosition<P>();
00383 bool close_to_king = false;
00384 if (opKingPosition.isOnBoard())
00385 {
00386 int distance = (opKingPosition.x() - to.x()) * (opKingPosition.x() - to.x()) +
00387 (opKingPosition.y() - to.y()) * (opKingPosition.y() - to.y());
00388 if (distance < 19)
00389 {
00390 close_to_king = true;
00391 }
00392 }
00393 if (myKingPosition.isOnBoard())
00394 {
00395 int distance = (myKingPosition.x() - to.x()) * (myKingPosition.x() - to.x()) +
00396 (myKingPosition.y() - to.y()) * (myKingPosition.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->getTurn() == 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
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
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
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);
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
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
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
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
00637 ntesuki_assert(state);
00638 ntesuki_assert(state->getTurn() == turn());
00639
00640
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
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
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
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
00754
00755
00756
00757 template <osl::Player P>
00758 void
00759 osl::ntesuki::NtesukiRecord::
00760 setResult(int i,
00761 const NtesukiResult& r,
00762 const NtesukiMove& m,
00763 bool bs,
00764 const PieceStand* ps
00765 )
00766 {
00767 ++written_count;
00768
00769
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];
00779 setFinal<P>(i, r, m, ps);
00780 }
00781 else
00782 {
00783 values<P>()[i] = r;
00784
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
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
00825 }
00826 #endif
00827 }
00828
00829
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
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
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
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
01010
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(),
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
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
01093
01094
01095