00001
00002
00003 #ifndef _SEARCHBASE_H
00004 #define _SEARCHBASE_H
00005
00006 #include "osl/search/searchRecorder.h"
00007 #include "osl/search/searchTable.h"
00008 #include "osl/search/realizationProbability.h"
00009 #include "osl/search/simpleHashRecord.h"
00010 #include "osl/search/searchWindow.h"
00011 #include "osl/search/fixedEval.h"
00012 #include "osl/hash/hashCollision.h"
00013 #include "osl/hash/hashKey.h"
00014 #include "osl/state/numEffectState.h"
00015 #include <cassert>
00016 namespace osl
00017 {
00018 namespace search
00019 {
00020 class SimpleHashTable;
00021
00026 template<typename Eval,
00027 typename Table, typename Recorder, typename Probabilities>
00028 struct SearchBase : protected FixedEval
00029 {
00030
00031 typedef Eval eval_t;
00032
00033 typedef Probabilities Probabilities_t;
00034 protected:
00035 Recorder& recorder;
00036 Table *table;
00037 public:
00038 SearchBase(Recorder& r, Table *t)
00039 : recorder(r), table(t)
00040 {
00041 assert(table);
00042 assert(winThreshold(BLACK) > eval_t::infty());
00043 }
00044 virtual ~SearchBase() {}
00045 virtual bool abort(Move) const { return false; }
00046
00055 bool validTableMove(const NumEffectState& state,
00056 const MoveLogProb& move, int limit) const
00057 {
00058 if ((limit < move.getLogProb()) || (! move.validMove()))
00059 return false;
00060 if (! move.getMove().isNormal())
00061 return false;
00062 const bool valid
00063 = ((move.getMove().player() == state.getTurn())
00064 && state.isAlmostValidMove<false>(move.getMove()));
00065 if (! valid)
00066 {
00067
00068 recorder.recordInvalidMoveInTable(state, move, limit);
00069 throw hash::HashCollision();
00070 }
00071 return valid;
00072 }
00073
00074 void recordLowerBound(Player P,
00075 SimpleHashRecord *record, int limit,
00076 const MoveLogProb& best_move, int val) const
00077 {
00078 assert(limit >= 0);
00079 recorder.tableStoreLowerBound(P, best_move, val, limit);
00080 if (best_move.validMove())
00081 {
00082 MoveLogProb store_move = best_move;
00083 store_move.setLogProbAtLeast(Probabilities::TableMove);
00084 record->setLowerBound(P, limit, store_move, val);
00085 }
00086 else
00087 {
00088 record->setLowerBound(P, limit, best_move, val);
00089 }
00090 }
00091 void recordUpperBound(Player P,
00092 SimpleHashRecord *record, int limit,
00093 const MoveLogProb& best_move, int val) const
00094 {
00095 assert(limit >= 0);
00096 recorder.tableStoreUpperBound(P, best_move, val, limit);
00097
00098 if (best_move.validMove())
00099 {
00100 MoveLogProb store_move = best_move;
00101 store_move.setLogProbAtLeast(Probabilities::TableMove);
00102 record->setUpperBound(P, limit, store_move, val);
00103 }
00104 else
00105 {
00106 record->setUpperBound(P, limit, best_move, val);
00107 }
00108 }
00109 private:
00110 void recordCheckmateResult(Player P, SimpleHashRecord *record,
00111 int val, Move move) const
00112 {
00113 assert(isWinValue(P,val) || isWinValue(alt(P),val));
00114 const int limit = SearchTable::CheckmateSpecialDepth;
00115 const MoveLogProb best_move(move, 101);
00116 recorder.tableStoreLowerBound(P, best_move, val, limit);
00117 recorder.tableStoreUpperBound(P, best_move, val, limit);
00118 record->setAbsoluteValue(best_move.getMove(), val,
00119 SearchTable::CheckmateSpecialDepth);
00120 }
00121 public:
00123 void recordWinByCheckmate(Player P, SimpleHashRecord *record,
00124 Move check_move) const
00125 {
00126 assert(record);
00127 recordCheckmateResult(P, record, winByCheckmate(P), check_move);
00128 }
00130 void recordLoseByCheckmate(Player P, SimpleHashRecord *record) const
00131 {
00132 assert(record);
00133 recordCheckmateResult(P, record, winByCheckmate(alt(P)), Move::INVALID());
00134 }
00135
00136 using FixedEval::isWinValue;
00137 using FixedEval::winByCheckmate;
00138 using FixedEval::winByFoul;
00139 using FixedEval::winByLoop;
00140 using FixedEval::minusInfty;
00141 using FixedEval::drawValue;
00142
00143 };
00144 }
00145 }
00146
00147
00148 #endif
00149
00150
00151
00152