00001
00002
00003 #ifndef _ORACLEDISPROVER_TCC
00004 #define _ORACLEDISPROVER_TCC
00005
00006 #include "osl/checkmate/oracleDisprover.h"
00007 #include "osl/checkmate/checkHashTable.h"
00008 #include "osl/checkmate/checkMoveGenerator.h"
00009 #include "osl/checkmate/checkTableUtil.h"
00010 #include "osl/checkmate/checkmateRecorder.h"
00011 #include "osl/checkmate/sameBoardList.h"
00012 #include "osl/checkmate/proofPieces.h"
00013 #include "osl/apply_move/applyMoveWithPath.h"
00014 #include <iostream>
00015
00016
00017 namespace osl
00018 {
00019 namespace checkmate
00020 {
00025 template <Player P, class Disprover>
00026 struct OracleDisproverDefense
00027 {
00028 Disprover *prover;
00029 CheckHashRecord *record;
00030 const DisproofOracleDefense<P>& oracle;
00031 OracleDisproverDefense(Disprover *p, CheckHashRecord *r,
00032 const DisproofOracleDefense<P>& o)
00033 : prover(p), record(r), oracle(o)
00034 {
00035 }
00036 void operator()(Position)
00037 {
00038 assert(! record->isVisited);
00039 (*prover).template defense<P>(record, oracle);
00040 record->isVisited = false;
00041 }
00042 };
00043
00048 template <Player P, class Disprover>
00049 struct OracleDisproverAttack
00050 {
00051 Disprover *prover;
00052 CheckHashRecord *record;
00053 const DisproofOracleAttack<P>& oracle;
00054 OracleDisproverAttack(Disprover *p, CheckHashRecord *r,
00055 const DisproofOracleAttack<P>& o)
00056 : prover(p), record(r), oracle(o)
00057 {
00058 }
00059 void operator()(Position)
00060 {
00061 assert(! record->isVisited);
00062 (*prover).template attack<P>(record, oracle);
00063 record->isVisited = false;
00064 }
00065 };
00066
00067 }
00068 }
00069
00070 template <class Table>
00071 template <osl::Player P>
00072 bool osl::checkmate::OracleDisprover<Table>::
00073 proofNoCheckmate(NumEffectState& state,
00074 const HashKey& key, const PathEncoding& root_path,
00075 const DisproofOracleAttack<P>& oracle)
00076 {
00077 check_assert(oracle.isValid());
00078 check_assert(state.getTurn() == P);
00079 path = root_path;
00080 this->state = &state;
00081 this->key = key;
00082 CheckmateRecorder::setState(&state);
00083 CheckHashRecord *record = table.find(key);
00084 if (! record)
00085 {
00086 const PieceStand white_stand(WHITE, state);
00087 CheckHashRecord *root = table.root();
00088 root->distance = path.getDepth()-1;
00089 CheckTableUtil::allocate(record, table, key, white_stand, path, root);
00090 }
00091
00092 if ((! record->proofDisproof().isFinal())
00093 && (! record->findLoop(path, table.getTwinTable())))
00094 {
00095 const bool visitedBeforeAttack = record->isVisited;
00096 CheckmateRecorder::setNextMove(0);
00097 record->isVisited = false;
00098 attack<P>(record, oracle);
00099 record->isVisited = visitedBeforeAttack;
00100 }
00101 if (record->proofDisproof().isCheckmateFail()
00102 || record->findLoop(path, table.getTwinTable()))
00103 return true;
00104
00105 return false;
00106 }
00107
00108 template <class Table>
00109 template <osl::Player P>
00110 bool osl::checkmate::OracleDisprover<Table>::
00111 proofEscape(NumEffectState& state,
00112 const HashKey& key, const PathEncoding& root_path,
00113 const DisproofOracleDefense<P>& oracle,
00114 Move& best_move, Move last_move)
00115 {
00116 check_assert(oracle.isValid());
00117 check_assert(state.getTurn() == alt(P));
00118 #ifdef CHECKMATE_DEBUG
00119 check_assert(oracle.guide->proofDisproof().isCheckmateFail()
00120 || oracle.guide->findLoop(oracle.path, table.getTwinTable())
00121 || ((! oracle.guide->twins.empty())
00122 && oracle.guide->hasBestMove()
00123 && oracle.guide->getBestMove()->findLoop(oracle.path, table.getTwinTable()))
00124 || oracle.guide->proofDisproof() == ProofDisproof::NoEscape()
00125 || (oracle.guide->dump(), 0));
00126 #endif
00127 path = root_path;
00128 this->state = &state;
00129 this->key = key;
00130 CheckmateRecorder::setState(&state);
00131 CheckHashRecord *record = table.find(key);
00132 if (! record)
00133 {
00134 const PieceStand white_stand(WHITE, state);
00135 CheckHashRecord *root = table.root();
00136 root->distance = path.getDepth()-1;
00137 CheckTableUtil::allocate(record, table, key, white_stand, path, root);
00138 }
00139
00140 if ((! record->proofDisproof().isFinal())
00141 && (! record->findLoop(path, table.getTwinTable())))
00142 {
00143 const bool visitedBeforeDefense = record->isVisited;
00144 CheckmateRecorder::setNextMove(0);
00145 record->isVisited = false;
00146 defense<P>(record, oracle);
00147 record->isVisited = visitedBeforeDefense;
00148 }
00149 if (record->proofDisproof().isCheckmateFail()
00150 || record->findLoop(path, table.getTwinTable()))
00151 {
00152 if (record->hasBestMove())
00153 {
00154 best_move = record->getBestMove()->move;
00155 check_assert(best_move.isValid());
00156 check_assert(best_move.player() == alt(P));
00157 }
00158 else
00159 {
00160 check_assert(record->findLoop(path, table.getTwinTable()));
00161 }
00162 return true;
00163 }
00164 if (record->proofDisproof().isPawnDropFoul(last_move))
00165 return true;
00166 return false;
00167 }
00168
00169 template <class Table>
00170 template <osl::Player P>
00171 void osl::checkmate::OracleDisprover<Table>::
00172 attack(CheckHashRecord *record, const DisproofOracleAttack<P>& oracle)
00173 {
00174 ++node_count;
00175 #ifndef NDEBUG
00176 CheckmateRecorder::Tracer tracer("disproof oracle attack ", record,
00177 key, path, 0, 0);
00178 #endif
00179 check_assert(oracle.isValid());
00180 check_assert(state->getTurn() == P);
00181 check_assert(record);
00182 check_assert(! record->isVisited);
00183 check_assert(! record->findLoop(path, table.getTwinTable()));
00184 record->isVisited = true;
00185 check_assert(! record->proofDisproof().isFinal());
00186
00187 #ifndef NDEBUG
00188 const Position targetKingPosition
00189 =(*state).template getKingPosition<PlayerTraits<P>::opponent>();
00190
00191 check_assert(! state->hasEffectBy(P,targetKingPosition));
00192 #endif
00193
00194 if (record->sameBoards)
00195 {
00196 const CheckHashRecord *loop =
00197 (*record->sameBoards).template
00198 findIneffectiveDropLoop<P>(key.blackStand());
00199 if (loop)
00200 {
00201 record->setLoopDetection(path, loop);
00202 CheckmateRecorder::setLeaveReason("loop confirmation (drop)");
00203 return;
00204 }
00205 }
00206
00207 if (record->needMoveGeneration())
00208 {
00209 CheckMoveGenerator<P>::generateAttack(*state, table.listProvider(),
00210 record->moves);
00211 if (record->moves.empty())
00212 {
00213 record->setDisproofPieces(DisproofPieces::leaf(*state, alt(P),
00214 record->stand(alt(P))));
00215 record->propagateNoCheckmate<P>(ProofDisproof::NoCheckmate());
00216 CheckmateRecorder::setLeaveReason("no attack moves");
00217 return;
00218 }
00219 check_assert(record->moves.size());
00220 record->setProofDisproof(1, record->moves.size());
00221 }
00222 record->filter = MoveFilter();
00223 ProofDisproof bestResultInSolved = record->bestResultInSolved;
00224 examine_moves:
00225 int disproved = 0;
00226 unsigned int sum_disproof = 0;
00227 unsigned int min_proof = ProofDisproof::PROOF_LIMIT;
00228
00229 HashKey new_key;
00230 PathEncoding new_path;
00231
00232 for (CheckMoveList::iterator p=record->moves.begin();
00233 p!=record->moves.end(); ++p)
00234 {
00235 check_assert(p->move.player() == P);
00236 if (! record->filter.isTarget(p->flags))
00237 continue;
00238 new_key = key.newHashWithMove(p->move);
00239 new_path = PathEncoding(path, p->move);
00240 if (! p->record)
00241 {
00242 CheckTableUtil::allocate(p->move, p->record, table,
00243 new_key, new_path, record);
00244 }
00245
00246 if (const TwinEntry *loop
00247 = p->findLoop(path, table.getTwinTable()))
00248 {
00249 #ifdef PAWN_CHECKMATE_SENSITIVE
00250 if ((record->bestResultInSolved != ProofDisproof::PawnCheckmate())
00251 && loop->move.record
00252 && (loop->move.record->bestResultInSolved == ProofDisproof::PawnCheckmate()))
00253 {
00254 record->bestResultInSolved
00255 = record->bestResultInSolved.betterForAttack(ProofDisproof::PawnCheckmate());
00256 }
00257 #endif
00258 bestResultInSolved
00259 = bestResultInSolved.betterForAttack(ProofDisproof::LoopDetection());
00260 continue;
00261 }
00262 if (p->record->isVisited)
00263 {
00264 if (p->record->proofDisproof() == ProofDisproof::PawnCheckmate())
00265 record->bestResultInSolved
00266 = record->bestResultInSolved.betterForAttack(ProofDisproof::PawnCheckmate());
00267 bestResultInSolved
00268 = bestResultInSolved.betterForAttack(ProofDisproof::LoopDetection());
00269 continue;
00270 }
00271 const ProofDisproof& pdp = p->record->proofDisproof();
00272 if (! pdp.isFinal())
00273 {
00274 DisproofOracleDefense<P> new_oracle = oracle.expandOracle(p->move);
00275 if (! new_oracle.isValid())
00276 {
00277 CheckmateRecorder::setLeaveReason("invalid oracle");
00278 #ifdef CHECKMATE_DEBUG
00279 CheckmateRecorder::DepthTracer::stream() << p->move << "\n";
00280 #endif
00281 return;
00282 }
00283 if (! pdp.isFinal())
00284 {
00285 OracleDisproverDefense<P,OracleDisprover>
00286 oracle_disprover(this, p->record, new_oracle);
00287 CheckmateRecorder::setNextMove(&*p);
00288
00289 std::swap(key, new_key);
00290 std::swap(path, new_path);
00291 ApplyMove<P>::doUndoMove(*state, p->move,oracle_disprover);
00292 key = new_key;
00293 path = new_path;
00294 }
00295 }
00296 if (pdp.isCheckmateFail())
00297 {
00298 check_assert(! pdp.isLoopDetection());
00299 record->addToSolvedInAttack(*p, pdp);
00300 ++disproved;
00301 continue;
00302 }
00303 if (pdp.isPawnDropFoul(p->move))
00304 {
00305 record->addToSolvedInAttack(*p, ProofDisproof::PawnCheckmate());
00306 ++disproved;
00307 continue;
00308 }
00309 if (p->findLoop(path, table.getTwinTable()))
00310 {
00311 bestResultInSolved
00312 = bestResultInSolved.betterForAttack(ProofDisproof::LoopDetection());
00313 ++disproved;
00314 continue;
00315 }
00316 assert(! pdp.isCheckmateFail());
00317 record->bestMove = &*p;
00318 if (pdp.isCheckmateSuccess())
00319 {
00320 CheckmateRecorder::setLeaveReason("checkmate move found in attack");
00321 #ifdef CHECKMATE_DEBUG
00322 CheckmateRecorder::DepthTracer::stream() << p->move << "\n";
00323 #endif
00324 if (! record->proofDisproof().isCheckmateSuccess())
00325 {
00326 record->setProofPiecesAttack(P);
00327 record->propagateCheckmate<P>(pdp);
00328 check_assert(record->isConsistent());
00329 }
00330 return;
00331 }
00332 sum_disproof += pdp.disproof();
00333 min_proof = std::min(min_proof, pdp.proof());
00334 }
00335 if (sum_disproof && (disproved == 0))
00336 {
00337 CheckmateRecorder::setLeaveReason("no new nocheckmate found");
00338 assert(min_proof < ProofDisproof::PROOF_LIMIT);
00339 assert(sum_disproof < ProofDisproof::DISPROOF_LIMIT);
00340 check_assert(! record->proofDisproof().isFinal());
00341 record->setProofDisproof(std::max(record->proof(), min_proof),
00342 std::max(record->disproof(), sum_disproof));
00343 return;
00344 }
00345 if (sum_disproof)
00346 goto examine_moves;
00347 #ifdef DELAY_SACRIFICE
00348 if (! record->filter.isTarget(MoveFlags::SacrificeAttack))
00349 {
00350 record->filter.addTarget(MoveFlags::SacrificeAttack);
00351 goto examine_moves;
00352 }
00353 #endif
00354 if ((record->bestResultInSolved == ProofDisproof::PawnCheckmate())
00355 && (! record->filter.isTarget(MoveFlags::NoPromote)))
00356 {
00357 if (! oracle.guide->filter.isTarget(MoveFlags::NoPromote))
00358 {
00359 CheckmateRecorder::setLeaveReason("NoPromote in oracle");
00360 return;
00361 }
00362 record->filter.addTarget(MoveFlags::NoPromote);
00363 goto examine_moves;
00364 }
00365 if (! record->filter.isTarget(MoveFlags::Upward))
00366 {
00367 record->filter.addTarget(MoveFlags::Upward);
00368 record->useMaxInsteadOfSum = true;
00369 goto examine_moves;
00370 }
00371 bestResultInSolved =
00372 bestResultInSolved.betterForAttack(record->bestResultInSolved);
00373 check_assert(bestResultInSolved.isCheckmateFail());
00374 if (bestResultInSolved.isLoopDetection())
00375 {
00376 if (oracle.guide == record)
00377 {
00378
00379 assert(! record->twins.empty());
00380 table.addLoopDetection(path);
00381 }
00382 else
00383 {
00384 record->setLoopDetectionInAttack<P>(path);
00385 }
00386 }
00387 else
00388 {
00389 record->setDisproofPieces(DisproofPieces::attack(record->moves, *state,
00390 record->stand(alt(P))));
00391 record->propagateNoCheckmate<P>(record->bestResultInSolved);
00392 record->twins.clear();
00393 }
00394 return;
00395 }
00396
00397 namespace osl
00398 {
00399 namespace checkmate
00400 {
00401 template <class State, Player Attacker>
00402 struct ConfirmNoEscape
00403 {
00404 State *state;
00405 bool *result;
00406 ConfirmNoEscape(State *s, bool *r) : state(s), result(r)
00407 {
00408 }
00409 void operator()(Position)
00410 {
00411 const Position defense_king_position
00412 = (*state).template getKingPosition<PlayerTraits<Attacker>::opponent>();
00413 *result = state->hasEffectBy(Attacker, defense_king_position);
00414 }
00415 };
00416 }
00417 }
00418
00419 template <class Table>
00420 template <osl::Player P>
00421 void osl::checkmate::OracleDisprover<Table>::
00422 confirmNoEscape(CheckHashRecord *record)
00423 {
00424 if (record->moves.empty())
00425 CheckMoveGenerator<P>::generateEscape(*state, table.listProvider(),
00426 record->moves);
00427 if (record->moves.empty())
00428 {
00429 record->setProofPieces(ProofPieces::leaf(*state, P, record->stand(P)));
00430 record->propagateCheckmate<P>(ProofDisproof::NoEscape());
00431 check_assert(record->isConsistent());
00432 return;
00433 }
00434
00435 }
00436
00437 template <class Table>
00438 template <osl::Player P>
00439 void osl::checkmate::OracleDisprover<Table>::
00440 defense(CheckHashRecord *record, const DisproofOracleDefense<P>& oracle)
00441 {
00442 ++node_count;
00443 #ifndef NDEBUG
00444 CheckmateRecorder::Tracer tracer("disproof oracle defense", record,
00445 key, path, 0, 0);
00446 #endif
00447 check_assert(oracle.isValid());
00448 check_assert(record);
00449 check_assert(! record->isVisited);
00450 record->isVisited = true;
00451 check_assert(! record->proofDisproof().isFinal());
00452 check_assert(! record->findLoop(path, table.getTwinTable()));
00453 #ifdef CHECKMATE_DEBUG
00454 const Position attack_king_position=(*state).template getKingPosition<P>();
00455 const Position defense_king_position=(*state).template getKingPosition<PlayerTraits<P>::opponent>();
00456 check_assert(attack_king_position.isPieceStand()
00457 || ! state->hasEffectBy(alt(P),attack_king_position));
00458 check_assert(state->hasEffectBy(P,defense_king_position));
00459 #endif
00460 if (oracle.guide->proofDisproof() == ProofDisproof::NoEscape())
00461 {
00462 confirmNoEscape<P>(record);
00463 return;
00464 }
00465
00466 if (record->sameBoards)
00467 {
00468 const CheckHashRecord *loop =
00469 (*record->sameBoards).template
00470 findIneffectiveDropLoop<P>(key.blackStand());
00471 if (loop)
00472 {
00473 if (oracle.guide == record)
00474 {
00475
00476 assert(! record->twins.empty());
00477 table.addLoopDetection(path, loop);
00478 }
00479 else
00480 {
00481 record->setLoopDetection(path, loop);
00482 }
00483 CheckmateRecorder::setLeaveReason("loop confirmation (drop)");
00484 return;
00485 }
00486 }
00487
00488 if (oracle.best_move.isInvalid())
00489 {
00490
00491 CheckmateRecorder::setLeaveReason("empty defense oracle");
00492 return;
00493 }
00494 assert(! oracle.best_move.isPass());
00495 Move escape_move = oracle.best_move;
00496 check_assert(escape_move.player() == alt(P));
00497 assert(escape_move.isValid());
00498 if (! escape_move.isDrop())
00499 {
00500 const Ptype existing = state->getPieceOnBoard(escape_move.to()).ptype();
00501 if (existing == KING)
00502 return;
00503 escape_move.setCapturePtype(existing);
00504 }
00505 if (! (*state).template isAlmostValidMove<false>(escape_move))
00506 {
00507 CheckmateRecorder::setLeaveReason("invalid defense oracle");
00508 return;
00509 }
00510
00511 if (record->moves.empty())
00512 CheckMoveGenerator<P>::generateEscape(*state, table.listProvider(),
00513 record->moves);
00514
00515 record->bestMove = 0;
00516 for (CheckMoveList::iterator p=record->moves.begin();
00517 p!=record->moves.end(); ++p)
00518 {
00519 if (p->move == escape_move)
00520 {
00521 if (! p->flags.isSet(MoveFlags::Solved))
00522 record->bestMove = &*p;
00523 break;
00524 }
00525 }
00526 unsigned int best_move_proof = 1;
00527 unsigned int best_move_disproof = 1;
00528 HashKey new_key = key.newHashWithMove(escape_move);
00529 PathEncoding new_path(path, escape_move);
00530
00531 if (! record->hasBestMove())
00532 goto failure_end;
00533 check_assert(record->hasBestMove()
00534 && (record->getBestMove()->move == escape_move));
00535 if (! record->getBestMove()->record)
00536 {
00537 CheckTableUtil::allocate(escape_move, record->getBestMove()->record,
00538 table, new_key, new_path, record);
00539 if (record->proofDisproof().isFinal())
00540 return;
00541 }
00542
00543 if (record->getBestMove()->record->isVisited)
00544 {
00545 if (oracle.guide == record)
00546 {
00547
00548 assert(! record->twins.empty());
00549 table.addLoopDetection(path,
00550 *record->getBestMove(), record->getBestMove()->record);
00551 }
00552 else
00553 {
00554 record->setLoopDetection(path, *record->getBestMove(),
00555 record->getBestMove()->record);
00556 }
00557 CheckmateRecorder::setLeaveReason("loop confirmation (v)");
00558 return;
00559 }
00560 if (const TwinEntry *loop = record->getBestMove()->findLoop(path, table.getTwinTable()))
00561 {
00562 if (oracle.guide == record)
00563 {
00564
00565 assert(! record->twins.empty());
00566 table.addLoopDetection(path, *record->getBestMove(), loop->loopTo);
00567 }
00568 else
00569 {
00570 record->setLoopDetectionTryMerge<P>
00571 (path, *record->getBestMove(), loop->loopTo);
00572 }
00573 CheckmateRecorder::setLeaveReason("loop confirmation (t)");
00574 return;
00575 }
00576
00577 {
00578 const ProofDisproof& pdp = record->getBestMove()->record->proofDisproof();
00579 if (! pdp.isFinal())
00580 {
00581 DisproofOracleAttack<P> new_oracle = oracle.expandOracle();
00582 if (new_oracle.isValid())
00583 {
00584 OracleDisproverAttack<P,OracleDisprover>
00585 oracle_disprover(this, record->getBestMove()->record, new_oracle);
00586 CheckmateRecorder::setNextMove(&*record->getBestMove());
00587
00588 std::swap(key, new_key);
00589 std::swap(path, new_path);
00590
00591 ApplyMove<PlayerTraits<P>::opponent>::doUndoMove
00592 (*state, escape_move,oracle_disprover);
00593
00594 key = new_key;
00595 path = new_path;
00596
00597 if (record->proofDisproof().isFinal())
00598 return;
00599 }
00600 else
00601 {
00602 #ifdef CHECKMATE_DEBUG
00603 CheckmateRecorder::DepthTracer::stream() << "oracle expand fail\n";
00604 if (oracle.guide)
00605 oracle.guide->dump(CheckmateRecorder::DepthTracer::stream(),1);
00606 else
00607 CheckmateRecorder::DepthTracer::stream() << "no guide\n";
00608 if (oracle.next_guide)
00609 oracle.next_guide->dump(CheckmateRecorder::DepthTracer::stream(),1);
00610 else
00611 CheckmateRecorder::DepthTracer::stream() << "no next guide\n";
00612 #endif
00613 }
00614 }
00615 if (pdp.isCheckmateFail())
00616 {
00617 if (! record->proofDisproof().isCheckmateFail())
00618 {
00619 check_assert(! pdp.isLoopDetection());
00620 record->setDisproofPiecesDefense(alt(P));
00621 record->propagateNoCheckmate<P>(pdp);
00622 record->twins.clear();
00623 }
00624 return;
00625 }
00626 if (const TwinEntry *loop
00627 = record->getBestMove()->findLoop(path, table.getTwinTable()))
00628 {
00629 if (oracle.guide == record)
00630 {
00631
00632 assert(! record->twins.empty());
00633 table.addLoopDetection(path, *record->getBestMove(), loop->loopTo);
00634 }
00635 else
00636 {
00637 record->
00638 setLoopDetectionTryMerge<P>(path, *record->getBestMove(), loop->loopTo);
00639 }
00640 CheckmateRecorder::setLeaveReason("loop confirmation after move");
00641 return;
00642 }
00643 if (! pdp.isFinal())
00644 {
00645 best_move_proof = pdp.proof();
00646 best_move_disproof = pdp.disproof();
00647 }
00648 }
00649 record->bestMove = 0;
00650 failure_end:
00651 CheckmateRecorder::setLeaveReason("disproof oracle not found");
00652 #ifdef CHECKMATE_DEBUG
00653 CheckmateRecorder::DepthTracer::stream() << escape_move << " " << path << " " << oracle.path << "\n";
00654 #endif
00655 if (record->proofDisproof().isFinal())
00656 return;
00657 if (record->moves.empty())
00658 {
00659 record->setProofPieces(ProofPieces::leaf(*state, P, record->stand(P)));
00660 record->propagateCheckmate<P>(ProofDisproof::NoEscape());
00661 check_assert(record->isConsistent());
00662 }
00663 else
00664 {
00665 check_assert(best_move_proof < ProofDisproof::PROOF_LIMIT);
00666 check_assert(best_move_disproof < ProofDisproof::DISPROOF_LIMIT);
00667 check_assert(! record->proofDisproof().isFinal());
00668 record->setProofDisproof(std::max((size_t)record->proof(),
00669 best_move_proof + record->moves.size()),
00670 std::max(record->disproof(),
00671 best_move_disproof/4));
00672 }
00673
00674 return;
00675 }
00676
00677 template <class Table>
00678 bool osl::checkmate::OracleDisprover<Table>::
00679 proofNoCheckmate(NumEffectState& state, const PathEncoding& path,
00680 const CheckHashRecord *record, const PathEncoding& opath)
00681 {
00682 const HashKey key = HashKey::calcHash(state);
00683 if (state.getTurn() == BLACK)
00684 {
00685 DisproofOracleAttack<BLACK> oracle(record, opath);
00686 return proofNoCheckmate(state, key, path, oracle);
00687 }
00688 else
00689 {
00690 DisproofOracleAttack<WHITE> oracle(record, opath);
00691 return proofNoCheckmate(state, key, path, oracle);
00692 }
00693 }
00694
00695 template <class Table>
00696 bool osl::checkmate::OracleDisprover<Table>::
00697 proofEscape(NumEffectState& state, const PathEncoding& path,
00698 CheckHashRecord *record, const PathEncoding& opath,
00699 Move& best_move, Move last_move)
00700 {
00701 const HashKey key = HashKey::calcHash(state);
00702 if (state.getTurn() == BLACK)
00703 {
00704 DisproofOracleDefense<WHITE> oracle(record, opath);
00705 return proofEscape(state, key, path, oracle, best_move, last_move);
00706 }
00707 else
00708 {
00709 DisproofOracleDefense<BLACK> oracle(record, opath);
00710 return proofEscape(state, key, path, oracle, best_move, last_move);
00711 }
00712 }
00713
00714 #endif
00715
00716
00717
00718