00001
00002
00003 #include "osl/search/moveStackRejections.h"
00004 #include "osl/ptypeTable.h"
00005 #include "osl/boardTable.h"
00006 #include "osl/misc/fixedCapacityVector.h"
00007 #include "osl/misc/carray.h"
00008 #include "osl/misc/lightMutex.h"
00009 #include "osl/eval/evalTraits.h"
00010 #include "osl/oslConfig.h"
00011
00012 #ifdef SHOW_PROBE_COUNTER
00013 #include <iostream>
00014 #endif
00015
00016
00017 std::ostream& osl::search::operator<<(std::ostream& os,osl::search::OnBoardElement const& mp)
00018 {
00019 return os << "[" << mp.pos() << "," << mp.ptypeO() << "]";
00020 }
00021
00022 std::ostream& osl::search::operator<<(std::ostream& os,osl::search::StandElements const& mp)
00023 {
00024 os << "[";
00025 for(int ptypeIndex=8;ptypeIndex<=15;ptypeIndex++)
00026 os << (int)mp.v.c8[ptypeIndex-osl::PTYPE_BASIC_MIN] << ",";
00027 return os << "]";
00028 }
00029 void osl::search::StateElements::
00030 addMyBoard(osl::Position pos,osl::PtypeO ptypeO)
00031 {
00032 short posPtypeO=OnBoardElement::makePosPtypeO(pos,ptypeO);
00033 for(size_t i=0;i<myOnboardMinus.size();++i){
00034 if(myOnboardMinus[i].posPtypeO==posPtypeO){
00035 myOnboardMinus[i]=myOnboardMinus[myOnboardMinus.size()-1];
00036 myOnboardMinus.pop_back();
00037 return;
00038 }
00039 }
00040 myOnboardPlus.push_back(OnBoardElement(pos,ptypeO));
00041 }
00042 void osl::search::StateElements::
00043 subMyBoard(osl::Position pos,osl::PtypeO ptypeO)
00044 {
00045 short posPtypeO=OnBoardElement::makePosPtypeO(pos,ptypeO);
00046 for(size_t i=0;i<myOnboardPlus.size();++i){
00047 if(myOnboardPlus[i].posPtypeO==posPtypeO){
00048 myOnboardPlus[i]=myOnboardPlus[myOnboardPlus.size()-1];
00049 myOnboardPlus.pop_back();
00050 return;
00051 }
00052 }
00053 myOnboardMinus.push_back(OnBoardElement(pos,ptypeO));
00054 }
00055 void osl::search::StateElements::
00056 addOpBoard(osl::Position pos,osl::PtypeO ptypeO)
00057 {
00058 short posPtypeO=OnBoardElement::makePosPtypeO(pos,ptypeO);
00059 for(size_t i=0;i<opOnboardMinus.size();++i){
00060 if(opOnboardMinus[i].posPtypeO==posPtypeO){
00061 opOnboardMinus[i]=opOnboardMinus[opOnboardMinus.size()-1];
00062 opOnboardMinus.pop_back();
00063 return;
00064 }
00065 }
00066 opOnboardPlus.push_back(OnBoardElement(pos,ptypeO));
00067 }
00068 void osl::search::StateElements::
00069 subOpBoard(osl::Position pos,osl::PtypeO ptypeO)
00070 {
00071 short posPtypeO=OnBoardElement::makePosPtypeO(pos,ptypeO);
00072 for(size_t i=0;i<opOnboardPlus.size();++i){
00073 if(opOnboardPlus[i].posPtypeO==posPtypeO){
00074 opOnboardPlus[i]=opOnboardPlus[opOnboardPlus.size()-1];
00075 opOnboardPlus.pop_back();
00076 return;
00077 }
00078 }
00079 opOnboardMinus.push_back(OnBoardElement(pos,ptypeO));
00080 }
00081 void osl::search::StateElements::addStand(osl::Ptype ptype)
00082 {
00083 stand.add(ptype);
00084 }
00085 void osl::search::StateElements::subStand(osl::Ptype ptype)
00086 {
00087 stand.sub(ptype);
00088 }
00089 void osl::search::StateElements::addMyMove(osl::Move move)
00090 {
00091 if(move.isDrop()){
00092 addMyBoard(move.to(),move.ptypeO());
00093 addStand(move.ptype());
00094 }
00095 else{
00096 Ptype capturePtype=move.capturePtype();
00097 if(capturePtype!=PTYPE_EMPTY){
00098 subOpBoard(move.to(),move.capturePtypeO());
00099 subStand(unpromote(getPtype(move.capturePtypeO())));
00100 addMyBoard(move.to(),move.ptypeO());
00101 subMyBoard(move.from(),move.oldPtypeO());
00102 }
00103 else{
00104 addMyBoard(move.to(),move.ptypeO());
00105 subMyBoard(move.from(),move.oldPtypeO());
00106 }
00107 }
00108 }
00109 void osl::search::StateElements::addOpMove(osl::Move move)
00110 {
00111 if(move.isDrop()){
00112 addOpBoard(move.to(),move.ptypeO());
00113 subStand(move.ptype());
00114 }
00115 else{
00116 Ptype capturePtype=move.capturePtype();
00117 if(capturePtype!=PTYPE_EMPTY){
00118 subMyBoard(move.to(),move.capturePtypeO());
00119 addStand(unpromote(getPtype(move.capturePtypeO())));
00120 addOpBoard(move.to(),move.ptypeO());
00121 subOpBoard(move.from(),move.oldPtypeO());
00122 }
00123 else{
00124 addOpBoard(move.to(),move.ptypeO());
00125 subOpBoard(move.from(),move.oldPtypeO());
00126 }
00127 }
00128 }
00129
00130 template<osl::Player P>
00131 bool osl::search::StateElements::
00132 validSimpleMove(osl::state::NumEffectState const& state,
00133 osl::search::OnBoardElement const& fromElement,
00134 osl::search::OnBoardElement const& toElement) const
00135 {
00136 Position from=fromElement.pos(), to=toElement.pos();
00137 PtypeO fromPtypeO=fromElement.ptypeO(), toPtypeO=toElement.ptypeO();
00138
00139 if(fromPtypeO!=toPtypeO &&
00140 (fromPtypeO!=unpromote(toPtypeO) ||
00141 (!from.canPromote<P>() && !to.canPromote<P>())))
00142 return false;
00143 EffectContent effect=Ptype_Table.getEffect(fromPtypeO,from,to);
00144 if(!effect.hasEffect()) return false;
00145 if(effect.hasUnblockableEffect()) return true;
00146 Offset o=effect.offset();
00147 return state.isEmptyBetween(from,to,o,false);
00148 }
00149
00153 template<osl::Player P>
00154 bool osl::search::StateElements::
00155 validSimpleMove(osl::state::NumEffectState const& state,
00156 osl::search::OnBoardElement const& fromElement,
00157 osl::search::OnBoardElement const& toElement,Move lastMove) const
00158 {
00159 Position from=fromElement.pos(), to=toElement.pos();
00160 PtypeO fromPtypeO=fromElement.ptypeO(), toPtypeO=toElement.ptypeO();
00161
00162 if(fromPtypeO!=toPtypeO &&
00163 (fromPtypeO!=unpromote(toPtypeO) ||
00164 (!from.canPromote<P>() && !to.canPromote<P>())))
00165 return false;
00166 EffectContent effect=Ptype_Table.getEffect(fromPtypeO,from,to);
00167 if(!effect.hasEffect()) return false;
00168 if(effect.hasUnblockableEffect()) return true;
00169 Offset o=effect.offset();
00170 Position moveTo=lastMove.to(),moveFrom=lastMove.from();
00171 Position pos=from+o;
00172 for (;; pos+=o) {
00173 if(pos==to) return true;
00174 if(pos==moveTo) return false;
00175 if(!state.getPieceAt(pos).isEmpty()){
00176 if(pos==moveFrom){
00177 for (pos+=o;; pos+=o) {
00178 if(pos==to) return true;
00179 if(pos==moveTo) return false;
00180 if(!state.getPieceAt(pos).isEmpty()){
00181 break;
00182 }
00183 }
00184 }
00185 break;
00186 }
00187 }
00188 return false;
00189 }
00190
00191 template<osl::Player P>
00192 bool osl::search::StateElements::
00193 validCaptureMove(osl::state::NumEffectState const& state,
00194 osl::search::OnBoardElement const& fromElement,
00195 osl::search::OnBoardElement const& toElement,
00196 osl::search::OnBoardElement const& captureElement) const
00197 {
00198 Position to=toElement.pos();
00199 if(to!=captureElement.pos()) return false;
00200 Position from=fromElement.pos();
00201 PtypeO fromPtypeO=fromElement.ptypeO(), toPtypeO=toElement.ptypeO();
00202
00203 if(fromPtypeO!=toPtypeO ||
00204 (fromPtypeO!=unpromote(toPtypeO) &&
00205 !from.canPromote<P>() && !to.canPromote<P>()))
00206 return false;
00207 EffectContent effect=Ptype_Table.getEffect(fromPtypeO,from,to);
00208 if(!effect.hasEffect()) return false;
00209 if(effect.hasUnblockableEffect()) return true;
00210 Offset o=effect.offset();
00211 return state.isEmptyBetween(from,to,o,false);
00212 }
00213 template<osl::Player P>
00214 bool osl::search::StateElements::
00215 validCaptureMove(osl::state::NumEffectState const& state,
00216 osl::search::OnBoardElement const& fromElement,
00217 osl::search::OnBoardElement const& toElement,
00218 osl::search::OnBoardElement const& captureElement,
00219 osl::Move lastMove) const
00220 {
00221 Position to=toElement.pos();
00222 if(to!=captureElement.pos()) return false;
00223 Position from=fromElement.pos();
00224 PtypeO fromPtypeO=fromElement.ptypeO(), toPtypeO=toElement.ptypeO();
00225
00226 if(fromPtypeO!=toPtypeO ||
00227 (fromPtypeO!=unpromote(toPtypeO) &&
00228 !from.canPromote<P>() && !to.canPromote<P>()))
00229 return false;
00230 EffectContent effect=Ptype_Table.getEffect(fromPtypeO,from,to);
00231 if(!effect.hasEffect()) return false;
00232 if(effect.hasUnblockableEffect()) return true;
00233 Offset o=effect.offset();
00234 Position moveTo=lastMove.to(),moveFrom=lastMove.from();
00235 Position pos=from+o;
00236 for (;; pos+=o) {
00237 if(pos==to) return true;
00238 if(pos==moveTo) return false;
00239 if(!state.getPieceAt(pos).isEmpty()){
00240 if(pos==moveFrom){
00241 for (pos+=o;; pos+=o) {
00242 if(pos==to) return true;
00243 if(pos==moveTo) return false;
00244 if(!state.getPieceAt(pos).isEmpty()){
00245 break;
00246 }
00247 }
00248 }
00249 break;
00250 }
00251 }
00252 return false;
00253 }
00264 template<osl::Player P>
00265 bool osl::search::StateElements::canReject(osl::state::NumEffectState const& state,bool notRejectSennichite,bool notRootMove,Move lastMove) const
00266 {
00267 const Player altP=PlayerTraits<P>::opponent;
00268 switch(myOnboardPlus.size()){
00269 case 0:
00270 switch(opOnboardPlus.size()){
00271 case 1:
00272 if(opOnboardMinus.size()==1 && myOnboardMinus.size()==0){
00273
00274 return validSimpleMove<altP>(state,opOnboardPlus[0],opOnboardMinus[0],lastMove)
00275 && stand.gegtZero(notRejectSennichite);
00276 }
00277 return false;
00278 case 0:
00279 if(opOnboardMinus.size()==1){
00280 if(myOnboardMinus.size()==0 && opOnboardMinus.size()==0){
00281 StandElements localStand(stand);
00282
00283 Ptype ptype=getPtype(opOnboardMinus[0].ptypeO());
00284 localStand.sub(ptype);
00285 return localStand.gegtZero(notRejectSennichite);
00286 }
00287 }
00288 else{
00289 if(opOnboardMinus.size()==0 && myOnboardMinus.size()==0){
00290 return stand.gegtZero(notRootMove);
00291 }
00292 }
00293 return false;
00294 default: return false;
00295 }
00296 case 1:
00297 switch(myOnboardMinus.size()){
00298 case 1:
00299 switch(opOnboardMinus.size()){
00300 case 1:
00301 if(opOnboardPlus.size()==0){
00302 if(validCaptureMove<P>(state,myOnboardMinus[0],myOnboardPlus[0],opOnboardMinus[0])){
00303 StandElements localStand(stand);
00304 Ptype capturePtype=unpromote(getPtype(opOnboardMinus[0].ptypeO()));
00305
00306
00307 localStand.add(capturePtype);
00308 return localStand.geZero();
00309 }
00310 }
00311 return false;
00312 case 0:
00313 if(opOnboardPlus.size()==0){
00314 return validSimpleMove<P>(state,myOnboardMinus[0],myOnboardPlus[0]) &&
00315 stand.geZero();
00316 }
00317 return false;
00318 }
00319 case 0:
00320 if(opOnboardPlus.size()==1){
00321 if(opOnboardMinus.size()==1){
00322 if(validCaptureMove<altP>(state,opOnboardPlus[0],opOnboardMinus[0],myOnboardPlus[0])){
00323 StandElements localStand(stand);
00324 Ptype capturePtype=unpromote(getPtype(myOnboardPlus[0].ptypeO()));
00325
00326 localStand.add(capturePtype);
00327 return localStand.gegtZero(notRejectSennichite);
00328 }
00329 }
00330 else return false;
00331 }
00332 else if(opOnboardPlus.size()==0 && opOnboardMinus.size()==0 ){
00333
00334 return stand.geZero();
00335 }
00336 }
00337 default: return false;
00338 }
00339 }
00340
00341 std::ostream& osl::search::operator<<(std::ostream& os,osl::search::StateElements const& mps)
00342 {
00343 {
00344 os << "[ MyOnboardPlus(";
00345 for(size_t i=0;i<mps.myOnboardPlus.size();i++)
00346 os << mps.myOnboardPlus[i] << ",\n";
00347 os << "),";
00348 }
00349 {
00350 os << "[ MyOnboardMinus(";
00351 for(size_t i=0;i<mps.myOnboardMinus.size();i++)
00352 os << mps.myOnboardMinus[i] << ",\n";
00353 os << "),";
00354 }
00355 {
00356 os << "[ OpOnboardPlus(";
00357 for(size_t i=0;i<mps.opOnboardPlus.size();i++)
00358 os << mps.opOnboardPlus[i] << ",\n";
00359 os << "),";
00360 }
00361 {
00362 os << "[ OpOnboardMinus(";
00363 for(size_t i=0;i<mps.opOnboardMinus.size();i++)
00364 os << mps.opOnboardMinus[i] << ",\n";
00365 os << "),";
00366 }
00367 return os << "Stand(" << mps.stand << ") ]\n" << std::endl;
00368 }
00369
00370 #ifdef SHOW_PROBE_COUNTER
00371 struct ProbeCounter{
00372 #ifdef OSL_USE_RACE_DETECTOR
00373 osl::LightMutex mutex;
00374 #endif
00375 osl::misc::CArray<long long int,1024> check,hit;
00376 ProbeCounter(){}
00377 void incCheck(int d){
00378 #ifdef OSL_USE_RACE_DETECTOR
00379 osl::LightMutex::scoped_lock lk(mutex);
00380 #endif
00381 check[d]++;
00382 }
00383 void incHit(int d){
00384 #ifdef OSL_USE_RACE_DETECTOR
00385 osl::LightMutex::scoped_lock lk(mutex);
00386 #endif
00387 hit[d]++;
00388 }
00389 ~ProbeCounter(){
00390 for(int i=0;i<1024;i++){
00391 if(check[i]!=0){
00392 std::cerr << i << " : " << hit[i] << "/" << check[i] << std::endl;
00393 }
00394 }
00395 }
00396 };
00397 ProbeCounter probeCounter;
00398 #endif
00399
00400 template<osl::Player P>
00401 bool osl::search::MoveStackRejections::
00402 probe(osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int curDepth,osl::Move const& m,int alpha,int checkCountOfAltP)
00403 {
00404 StateElements elements;
00405 elements.addMyMove(m);
00406 assert(m.player()==P);
00407 bool existNormal=false;
00408 for(int i=1;i<curDepth;i+=2){
00409 Move m1=history.lastMove(i);
00410 if(m1.isNormal()){
00411 assert(m1.player()==alt(P));
00412 elements.addOpMove(m1);
00413 existNormal=true;
00414 }
00415 if(elements.isLoop()) return false;
00416 Move m2=history.lastMove(i+1);
00417 if(m2.isNormal()){
00418 assert(m2.player()==P);
00419 elements.addMyMove(m2);
00420 existNormal=true;
00421 }
00422 #ifdef SHOW_PROBE_COUNTER
00423 probeCounter.incCheck(i);
00424 #endif
00425
00426
00427 bool notRejectSennichite=osl::eval::betterThan(P,0,alpha) || (i<=checkCountOfAltP*2-1);
00428 bool notRootMove=(i != curDepth-1);
00429 if(
00430 existNormal &&
00431 elements.canReject<P>(state,notRejectSennichite,notRootMove,m)
00432 ){
00433 #ifdef SHOW_PROBE_COUNTER
00434 probeCounter.incHit(i);
00435 #endif
00436 return true;
00437 }
00438 }
00439 return false;
00440 }
00441 namespace osl
00442 {
00443 namespace search
00444 {
00445 template bool MoveStackRejections::probe<BLACK>(
00446 osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int curDepth,osl::Move const& m,int alpha, int checkCountOfAltP);
00447 template bool MoveStackRejections::probe<WHITE>(
00448 osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int curDepth,osl::Move const& m,int alpha,int checkCountOfAltP);
00449 }
00450 }
00451
00452
00453
00454
00455
00456
00457