00001
00002
00003 #include "osl/checkmate/oraclePoolLastMove.h"
00004 #include "osl/checkmate/checkHashRecord.h"
00005 #include "osl/state/simpleState.h"
00006 #include "osl/stl/hash_map.h"
00007 #ifdef OSL_SMP
00008 # include "osl/misc/lightMutex.h"
00009 #endif
00010 #include <algorithm>
00011
00012 #if (__GNUC__ >= 4 && __GNUC_MINOR__ >=3)
00013 typedef osl::hash_map<int,const osl::checkmate::CheckHashRecord*,
00014 std::tr1::hash<int> > hash_map_t;
00015 #else
00016 typedef osl::hash_map<int,const osl::checkmate::CheckHashRecord*,
00017 __gnu_cxx::hash<int> > hash_map_t;
00018 #endif
00019
00020 struct osl::checkmate::OraclePoolLastMove::Table
00021 {
00022 #ifdef OSL_SMP
00023 typedef osl::misc::LightMutex Mutex;
00024 mutable Mutex mutex;
00025 #endif
00026
00027 hash_map_t table;
00028 const Player defender;
00029
00030 explicit Table(Player attacker) : defender(alt(attacker))
00031 {
00032 }
00036 int makeKey(Position king_position, Move last_move) const
00037 {
00038 assert(! last_move.isDrop());
00039 assert(last_move.player() == defender);
00040 int result = king_position.index() * Position::indexMax();
00041 result += last_move.to().index();
00042 result *= Position::indexMax();
00043 result += last_move.from().index();
00044 result *= PTYPE_SIZE;
00045 result += last_move.oldPtype();
00046 return result;
00047 }
00048 const CheckHashRecord *& get(Position king_position, Move last_move)
00049 {
00050 const int key = makeKey(king_position, last_move);
00051 #ifdef OSL_SMP
00052 Mutex::scoped_lock lk(mutex);
00053 #endif
00054 return table[key];
00055 }
00056 const CheckHashRecord * find(Position king_position, Move last_move) const
00057 {
00058 const int key = makeKey(king_position, last_move);
00059 #ifdef OSL_SMP
00060 Mutex::scoped_lock lk(mutex);
00061 #endif
00062 hash_map_t::const_iterator pos = table.find(key);
00063 if (pos != table.end())
00064 return pos->second;
00065 return 0;
00066 }
00067 size_t size() const
00068 {
00069 return table.size();
00070 }
00071 };
00072
00073 osl::checkmate::
00074 OraclePoolLastMove::OraclePoolLastMove(Player attacker)
00075 : oracles(new Table(attacker))
00076 {
00077 }
00078
00079 osl::checkmate::
00080 OraclePoolLastMove::~OraclePoolLastMove()
00081 {
00082 }
00083
00084 void osl::checkmate::
00085 OraclePoolLastMove::addOracle(const SimpleState& state, Move last_move,
00086 const CheckHashRecord* oracle)
00087 {
00088 assert(state.getTurn() == alt(oracles->defender));
00089 if (last_move.isPass())
00090 return;
00091 const Position king_position = state.getKingPosition(oracles->defender);
00092 assert(oracle->hasProofPieces());
00093 oracles->get(king_position,last_move) = oracle;
00094 }
00095
00096 const osl::checkmate::CheckHashRecord *osl::checkmate::
00097 OraclePoolLastMove::findOracle(const SimpleState& state,
00098 Move last_move, PieceStand black_stand,
00099 unsigned short& oracle_age) const
00100 {
00101 assert(state.getTurn() == alt(oracles->defender));
00102 if (oracle_age)
00103 return 0;
00104 if (last_move.isPass())
00105 return 0;
00106
00107 const Position king_position = state.getKingPosition(oracles->defender);
00108 const CheckHashRecord *record = oracles->find(king_position, last_move);
00109 if (record)
00110 {
00111 ++oracle_age;
00112 const PieceStand attack_stand
00113 = (oracles->defender != BLACK) ? black_stand : PieceStand(WHITE, state);
00114 if (attack_stand.hasMoreThan<BLACK>(record->proofPieces()))
00115 return record;
00116 }
00117 return 0;
00118 }
00119
00120 size_t osl::checkmate::
00121 OraclePoolLastMove::size() const
00122 {
00123 return oracles->size();
00124 }
00125
00126
00127
00128
00129
00130