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 = EffectUtil::isKingInCheck(T, *state);
00151
00152 ntesuki_assert(!EffectUtil::isKingInCheck(O, *state));
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 PieceStand proof_pieces_child = record_child->getPDPieces<P>(pass_left);
00490
00491 proof_pieces = proof_pieces.max(proof_pieces_child);
00492 }
00493
00494
00495 ntesuki_assert(state);
00496
00497 if (! effect_util::UnblockableCheck::isMember(O, *state))
00498 {
00499 for (unsigned int i=0; i<PieceStand::order.size(); ++i)
00500 {
00501 const Ptype ptype = PieceStand::order[i];
00502 if (!state->hasPieceOnStand(O, ptype))
00503 {
00504 const int diff = state->countPiecesOnStand(P, ptype) - proof_pieces.get(ptype);
00505 ntesuki_assert(diff >= 0);
00506 if (diff) proof_pieces.add(ptype, diff);
00507 }
00508 }
00509 }
00510 return proof_pieces;
00511 }
00512
00513 template <osl::Player P>
00514 void
00515 osl::ntesuki::NtesukiRecord::
00516 setProofPieces(int pass_left,
00517 const NtesukiResult& r,
00518 const NtesukiMove& best_move,
00519 const PieceStand* ps)
00520 {
00521 const Player O = PlayerTraits<P>::opponent;
00522 PieceStand proof_pieces;
00523
00524 if (ps)
00525 {
00526
00527
00528 proof_pieces = *ps;
00529 }
00530 else if (best_move.isPass())
00531 {
00532 const NtesukiRecord* record_pass = table->findWithMove(this, best_move);
00533 ntesuki_assert(record_pass);
00534 proof_pieces = record_pass->getPDPieces<P>(pass_left - 1);
00535 }
00536 else if (best_move.isValid())
00537 {
00538 proof_pieces = calcProofPiecesOr<P>(pass_left, best_move);
00539 }
00540 else
00541 {
00542
00543
00544 proof_pieces = calcProofPiecesAnd<P>(pass_left);
00545 }
00546 ntesuki_assert(piece_stand<P>().template hasMoreThan<BLACK>(proof_pieces));
00547
00548 for (unsigned int j = pass_left; j < SIZE; j++)
00549 {
00550 setPDPieces<P>(j, proof_pieces);
00551 setPDPieces<O>(j, proof_pieces);
00552 }
00553 }
00554
00555 template <osl::Player P>
00556 void
00557 osl::ntesuki::NtesukiRecord::
00558 setDisproofPieces(int pass_left,
00559 const NtesukiResult& r,
00560 const NtesukiMove& m,
00561 const PieceStand* ps)
00562 {
00563 const Player O = PlayerTraits<P>::opponent;
00564 PieceStand disproof_pieces;
00565
00566 if (ps)
00567 {
00568
00569
00570 disproof_pieces = *ps;
00571 }
00572 else if (m.isPass())
00573 {
00574 const NtesukiRecord* record_pass = table->findWithMove(this, m);
00575 ntesuki_assert(record_pass);
00576
00577 disproof_pieces = record_pass->getPDPieces<P>(pass_left - 1);
00578 }
00579 else if (m.isValid())
00580 {
00581
00582
00583 ntesuki_assert(turn() != P);
00584
00585 const NtesukiRecord* record_child = table->findWithMove(this, m);
00586 ntesuki_assert(record_child);
00587 disproof_pieces = record_child->getPDPieces<P>(pass_left);
00588
00589 if (m.isDrop())
00590 {
00591 disproof_pieces.add(m.ptype());
00592 }
00593 else if (m.getMove().capturePtype() != PTYPE_EMPTY)
00594 {
00595 disproof_pieces.trySub(unpromote(m.getMove().capturePtype()));
00596 }
00597 }
00598 else
00599 {
00600
00601
00602 ntesuki_assert(turn() == P);
00603
00604 NtesukiMoveList moves;
00605 generateMoves<P>(moves, 0, true);
00606
00607 for (NtesukiMoveList::iterator move_it = moves.begin();
00608 move_it != moves.end(); move_it++)
00609 {
00610 const NtesukiRecord* record_child = table->findWithMove(this, *move_it);
00611 if (!record_child)
00612 {
00613 if (move_it->isPass() ||
00614 (0 == pass_left &&
00615 (!move_it->isCheck() || move_it->isNoPromote())))
00616 {
00617 continue;
00618 }
00619 else
00620 {
00621 setPDPieces<P>(pass_left, piece_stand<O>());
00622 return;
00623 }
00624
00625 }
00626
00627 PieceStand disproof_pieces_child = record_child->getPDPieces<P>(pass_left);
00628
00629 disproof_pieces = disproof_pieces.max(disproof_pieces_child);
00630 }
00631
00632
00633 ntesuki_assert(state);
00634 ntesuki_assert(state->getTurn() == turn());
00635
00636
00637 if (true)
00638 {
00639 for (unsigned int i=0; i<PieceStand::order.size(); ++i)
00640 {
00641 const Ptype ptype = PieceStand::order[i];
00642 if (!state->hasPieceOnStand(P, ptype))
00643 {
00644 const int diff = state->countPiecesOnStand(O, ptype) - disproof_pieces.get(ptype);
00645 ntesuki_assert(diff >= 0);
00646 if (diff) disproof_pieces.add(ptype, diff);
00647 }
00648 }
00649 }
00650 }
00651
00652 #ifndef NDEBUG
00653 ntesuki_assert(piece_stand<O>().isSuperiorOrEqualTo(disproof_pieces))
00654 #endif
00655 setPDPieces<P>(pass_left, disproof_pieces);
00656 }
00657
00658 template <osl::Player P>
00659 void
00660 osl::ntesuki::NtesukiRecord::
00661 setFinal(int pass_left,
00662 const NtesukiResult& r,
00663 const NtesukiMove& m,
00664 const PieceStand* ps)
00665 {
00666 if (r.isCheckmateSuccess() && pass_count)
00667 {
00668 final = true;
00669 }
00670 const Player O = PlayerTraits<P>::opponent;
00671
00672 if (r.isCheckmateSuccess())
00673 {
00674 TRY_DFPN;
00675 setProofPieces<P>(pass_left, r, m, ps);
00676 CATCH_DFPN;
00677
00678 for (unsigned int j = pass_left; j < SIZE; j++)
00679 {
00680 values<P> ()[j] = r;
00681 best_move<P>()[j] = m;
00682
00683 if (!values<O>()[j].isCheckmateFail())
00684 {
00685 ntesuki_assert(!values<O>()[j].isCheckmateSuccess());
00686
00687 values<O> ()[j] = ProofDisproof::AttackBack();
00688 best_move<O>()[j] = m;
00689 }
00690 }
00691
00692 if (use_dominance)
00693 {
00694 propagate_proof<P>(pass_left);
00695 }
00696
00697 #ifdef COLLECT_GARBAGE
00698
00699 if (turn() == P)
00700 {
00701 DifferentMove different_move(best_move<P>()[pass_left]);
00702 moves.remove_if(different_move);
00703 }
00704 #endif
00705 }
00706 else
00707 {
00708 ntesuki_assert(r.isCheckmateFail());
00709 setDisproofPieces<P>(pass_left, r, m, ps);
00710
00711 values<P>()[pass_left] = r;
00712 best_move<P>()[pass_left] = m;
00713
00714 if (pass_left != 0 &&
00715 !values<P>()[pass_left - 1].isCheckmateFail()
00716 )
00717 {
00718 setFinal<P>(pass_left - 1, r, m, ps);
00719 }
00720
00721 if (use_dominance)
00722 {
00723 propagate_disproof<P>(pass_left);
00724 }
00725
00726 #ifdef COLLECT_GARBAGE
00727
00728 if (turn() != P)
00729 {
00730 for (NtesukiMoveList::iterator move_it = moves.begin();
00731 move_it != moves.end(); move_it++)
00732 {
00733 bool not_best_move = true;
00734 for (size_t i = 0; i < SIZE; i++)
00735 {
00736 if (&(*move_it) != best_move<O>()[pass_left]) not_best_move = false;
00737 }
00738
00739 if (not_best_move)
00740 {
00741 move_it->clearRecord();
00742 }
00743 }
00744 }
00745 #endif
00746 }
00747 }
00748
00749
00750
00751
00752
00753 template <osl::Player P>
00754 void
00755 osl::ntesuki::NtesukiRecord::
00756 setResult(int i,
00757 const NtesukiResult& r,
00758 const NtesukiMove& m,
00759 bool bs,
00760 const PieceStand* ps
00761 )
00762 {
00763 ++written_count;
00764
00765
00766
00767 ntesuki_assert(!values<P>()[i].isFinal());
00768 ntesuki_assert(best_move<P>()[i].isInvalid());
00769
00770 by_simulation = bs;
00771
00772 if (r.isFinal())
00773 {
00774 value_before_final = values<P>()[i];
00775 setFinal<P>(i, r, m, ps);
00776 }
00777 else
00778 {
00779 values<P>()[i] = r;
00780
00781 int order = 0;
00782 for (; order < i; order++)
00783 {
00784 if (values<P>()[order].disproof() > r.disproof())
00785 {
00786 values<P>()[order] = ProofDisproof(values<P>()[order].proof(),
00787 r.disproof());
00788 }
00789 }
00790 ++order;
00791 for (; order < (int)SIZE; order++)
00792 {
00793
00794 if (values<P>()[order].isCheckmateFail()) continue;
00795
00796 if (values<P>()[order].disproof() < r.disproof())
00797 {
00798 values<P>()[order] = ProofDisproof(values<P>()[order].proof(),
00799 r.disproof());
00800 }
00801 }
00802 }
00803
00804 #ifndef NDEBUG
00805 if (by_simulation) ntesuki_assert(r.isFinal());
00806
00807 if (m.isValid())
00808 {
00809 ntesuki_assert(r.isFinal());
00810 }
00811
00812 if (key.turn() == P &&
00813 values<P>()[i].isCheckmateSuccess())
00814 {
00815 ntesuki_assert(m.isValid());
00816 }
00817 else if (key.turn() != P &&
00818 values<P>()[i].isCheckmateFail())
00819 {
00820
00821 }
00822 #endif
00823 }
00824
00825
00826
00827 template <osl::Player P>
00828 bool
00829 osl::ntesuki::NtesukiRecord::
00830 isDominatedByProofPieces(const NtesukiRecord* record,
00831 int pass_left) const
00832 {
00833 if (!record->getValue<P>(pass_left).isCheckmateSuccess()) return false;
00834
00835 const PieceStand& my_stand = piece_stand<P>();
00836 const PieceStand& other_pp = record->getPDPieces<P>(pass_left);
00837
00838 return my_stand.isSuperiorOrEqualTo(other_pp);
00839 }
00840
00841
00842
00843 template <osl::Player P>
00844 bool
00845 osl::ntesuki::NtesukiRecord::
00846 isDominatedByDisproofPieces(const NtesukiRecord* record,
00847 int pass_left) const
00848 {
00849 const Player O = PlayerTraits<P>::opponent;
00850 if (!record->getValue<P>(pass_left).isCheckmateFail()) return false;
00851
00852 const PieceStand& my_stand = piece_stand<O>();
00853 const PieceStand& other_dp = record->getPDPieces<P>(pass_left);
00854
00855 return my_stand.isSuperiorOrEqualTo(other_dp);
00856 }
00857
00858
00859
00860 template <osl::Player P>
00861 bool
00862 osl::ntesuki::NtesukiRecord::
00863 isBetterFor(NtesukiRecord* record)
00864 {
00865 const PieceStand& mystand = key.getPieceStand();
00866 const PieceStand& opstand = record->key.getPieceStand();
00867
00868 if (mystand == opstand) return false;
00869 return mystand.hasMoreThan<P>(opstand);
00870 }
00871
00872
00873
00874
00875 template <osl::Player A>
00876 bool osl::ntesuki::NtesukiRecord::
00877 useOld(int pass_left) const
00878 {
00879 return use_old<A>()[pass_left];
00880 }
00881
00882 template <osl::Player A>
00883 void osl::ntesuki::NtesukiRecord::
00884 setUseOld(int pass_left,
00885 bool value)
00886 {
00887 use_old<A>()[pass_left] = value;
00888 }
00889
00890
00891 template <osl::Player P>
00892 bool osl::ntesuki::NtesukiRecord::
00893 isLoopWithPath(int pass_left,
00894 const PathEncoding& path) const
00895 {
00896 typedef osl::ntesuki::PathEncodingList list_t;
00897 const list_t& list = loop_path_list<P>()[pass_left];
00898 for (list_t::const_iterator it = list.begin(); it != list.end(); it++)
00899 {
00900 if (*it == path)
00901 {
00902 return true;
00903 }
00904 }
00905 return false;
00906 }
00907
00908 template <osl::Player P>
00909 void osl::ntesuki::NtesukiRecord::
00910 setLoopWithPath(int pass_left,
00911 const PathEncoding& path)
00912 {
00913 typedef osl::ntesuki::PathEncodingList list_t;
00914 list_t& list = loop_path_list<P>()[pass_left];
00915 list.push_front(path);
00916 }
00917
00918 template <osl::Player P>
00919 const osl::ntesuki::NtesukiResult
00920 osl::ntesuki::NtesukiRecord::
00921 getValue(int i) const
00922 {
00923 ++read_count;
00924 return values<P>()[i];
00925 }
00926
00927 template <osl::Player P>
00928 const osl::ntesuki::NtesukiResult
00929 osl::ntesuki::NtesukiRecord::
00930 getValueWithPath(int i,
00931 const PathEncoding path) const
00932 {
00933 ++read_count;
00934 if (values<P>()[i].isFinal()) return values<P>()[i];
00935 if (isLoopWithPath<P>(i, path))
00936 {
00937 return ProofDisproof::LoopDetection();
00938 }
00939 return values<P>()[i];
00940 }
00941
00942
00943 template <osl::Player P>
00944 const osl::ntesuki::NtesukiResult
00945 osl::ntesuki::NtesukiRecord::
00946 getValueOr(int max_pass_left,
00947 const PathEncoding path,
00948 IWScheme iwscheme) const
00949 {
00950 ++read_count;
00951 if (values<P>()[max_pass_left].isFinal()) return values<P>()[max_pass_left];
00952 if (isLoopWithPath<P>(max_pass_left, path))
00953 {
00954 return ProofDisproof::LoopDetection();
00955 }
00956
00957 NtesukiResult ret = values<P>()[max_pass_left];
00958
00959 if (iwscheme == pn_iw)
00960 {
00961 unsigned int min_proof = ret.proof();
00962 for (int pass_left = 0; pass_left < max_pass_left; ++pass_left)
00963 {
00964 if (isLoopWithPath<P>(pass_left, path)) continue;
00965 const NtesukiResult result = values<P>()[pass_left];
00966 ntesuki_assert(result.disproof() <= ret.disproof());
00967 min_proof = std::min(min_proof, result.proof());
00968 }
00969 ret = NtesukiResult(min_proof, ret.disproof());
00970 }
00971 else if (iwscheme == strict_iw)
00972 {
00973 for (int pass_left = 0; pass_left < max_pass_left; ++pass_left)
00974 {
00975 if (isLoopWithPath<P>(pass_left, path)) continue;
00976 const NtesukiResult result = values<P>()[pass_left];
00977 if (!result.isCheckmateFail())
00978 {
00979 ret = result;
00980 break;
00981 }
00982 }
00983 }
00984 return ret;
00985 }
00986
00987 template <osl::Player P>
00988 const osl::ntesuki::NtesukiResult
00989 osl::ntesuki::NtesukiRecord::
00990 getValueAnd(int max_pass_left,
00991 const PathEncoding path,
00992 IWScheme iwscheme,
00993 PSScheme psscheme) const
00994 {
00995 ++read_count;
00996 if (values<P>()[max_pass_left].isFinal()) return values<P>()[max_pass_left];
00997 if (isLoopWithPath<P>(max_pass_left, path))
00998 {
00999 return ProofDisproof::LoopDetection();
01000 }
01001
01002 NtesukiResult ret = values<P>()[max_pass_left];
01003 if (psscheme && max_pass_left != 0)
01004 {
01005
01006
01007
01008 const Player O = PlayerTraits<P>::opponent;
01009 const NtesukiResult result_opponent = getValueOr<O>(max_pass_left - 1,
01010 path,
01011 iwscheme);
01012 if (!result_opponent.isFinal() &&
01013 result_opponent.proof() + inversion_cost < ret.disproof())
01014 {
01015 ret = ProofDisproof(result_opponent.disproof(),
01016 result_opponent.proof() + inversion_cost);
01017 }
01018 }
01019 return ret;
01020 }
01021
01022 template <osl::Player P>
01023 const osl::ntesuki::NtesukiMove&
01024 osl::ntesuki::NtesukiRecord::
01025 getBestMove(int i) const
01026 {
01027 return best_move<P>()[i];
01028 }
01029
01030 template <osl::Player P>
01031 bool
01032 osl::ntesuki::NtesukiRecord::
01033 isNtesuki(int pass_left) const
01034 {
01035 return is_ntesuki<P>()[pass_left];
01036 }
01037
01038 template <osl::Player P>
01039 void
01040 osl::ntesuki::NtesukiRecord::
01041 setNtesuki(int pass_left)
01042 {
01043
01044 is_ntesuki<P>()[pass_left] = true;
01045 }
01046
01047 template <osl::Player P>
01048 bool
01049 osl::ntesuki::NtesukiRecord::
01050 hasTriedPropagatedOracle(int pass_left) const
01051 {
01052 return propagated_oracle<P>()[pass_left];
01053 }
01054
01055 template <osl::Player P>
01056 void
01057 osl::ntesuki::NtesukiRecord::
01058 triedPropagatedOracle(int pass_left)
01059 {
01060 assert(false == propagated_oracle<P>()[pass_left]);
01061 propagated_oracle<P>()[pass_left] = true;
01062 }
01063
01064 template <osl::Player P>
01065 bool
01066 osl::ntesuki::NtesukiRecord::
01067 isByFixed() const
01068 {
01069 return by_fixed<P>();
01070 }
01071
01072 template <osl::Player P>
01073 osl::PieceStand
01074 osl::ntesuki::NtesukiRecord::
01075 getPDPieces(int pass_left) const
01076 {
01077 return pdpieces<P>()[pass_left];
01078 }
01079
01080 template <osl::Player P>
01081 void
01082 osl::ntesuki::NtesukiRecord::
01083 setPDPieces(int pass_left, const PieceStand p)
01084 {
01085 pdpieces<P>()[pass_left] = p;
01086 }
01087
01088
01089
01090
01091