moveStackRejections.cc
Go to the documentation of this file.
00001 /* moveStackRejections.cc
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::Square 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::Square 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::Square 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::Square 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     if(move.isCapture()){
00097       subOpBoard(move.to(),move.capturePtypeO());
00098       subStand(unpromote(getPtype(move.capturePtypeO()))); // 相手にとって
00099       addMyBoard(move.to(),move.ptypeO());
00100       subMyBoard(move.from(),move.oldPtypeO());
00101     }
00102     else{
00103       addMyBoard(move.to(),move.ptypeO());
00104       subMyBoard(move.from(),move.oldPtypeO());
00105     }
00106   }
00107 }
00108 void osl::search::StateElements::addOpMove(osl::Move move)
00109 {
00110   if(move.isDrop()){
00111     addOpBoard(move.to(),move.ptypeO());
00112     subStand(move.ptype());
00113   }
00114   else{
00115     if(move.isCapture()){
00116       subMyBoard(move.to(),move.capturePtypeO());
00117       addStand(unpromote(getPtype(move.capturePtypeO()))); // 相手にとって
00118       addOpBoard(move.to(),move.ptypeO());
00119       subOpBoard(move.from(),move.oldPtypeO());
00120     }
00121     else{
00122       addOpBoard(move.to(),move.ptypeO());
00123       subOpBoard(move.from(),move.oldPtypeO());
00124     }
00125   }
00126 }
00127 
00131 template<osl::Player P>
00132 bool osl::search::StateElements::
00133 validSimpleMove(osl::state::NumEffectState const& state,
00134                 osl::search::OnBoardElement const& fromElement,
00135                 osl::search::OnBoardElement const& toElement,Move lastMove) const
00136 {
00137   Square from=fromElement.pos(), to=toElement.pos();
00138   PtypeO fromPtypeO=fromElement.ptypeO(), toPtypeO=toElement.ptypeO();
00139 
00140   if(fromPtypeO!=toPtypeO &&
00141      (fromPtypeO!=unpromote(toPtypeO) ||
00142       (!from.canPromote<P>() && !to.canPromote<P>())))
00143     return false;
00144   EffectContent effect=Ptype_Table.getEffect(fromPtypeO,from,to);
00145   if(!effect.hasEffect()) return false;
00146   if(effect.hasUnblockableEffect()) return true;
00147   Offset o=effect.offset();
00148   Square moveTo=lastMove.to(),moveFrom=lastMove.from();
00149   Square pos=from+o;
00150   for (;; pos+=o) {
00151     if(pos==to) return true;
00152     if(pos==moveTo) return false;
00153     if(!state.pieceAt(pos).isEmpty()){
00154       if(pos==moveFrom){
00155         for (pos+=o;; pos+=o) {
00156           if(pos==to) return true;
00157           if(pos==moveTo) return false;
00158           if(!state.pieceAt(pos).isEmpty()){
00159             break;
00160           }
00161         }
00162       }
00163       break;
00164     }
00165   }
00166   return false;
00167 }
00168 
00169 template<osl::Player P>
00170 bool osl::search::StateElements::
00171 validCaptureMove(osl::state::NumEffectState const& state,
00172                  osl::search::OnBoardElement const& fromElement,
00173                  osl::search::OnBoardElement const& toElement,
00174                  osl::search::OnBoardElement const& captureElement,
00175                  osl::Move lastMove) const
00176 {
00177   Square to=toElement.pos();
00178   if(to!=captureElement.pos()) return false;
00179   Square from=fromElement.pos();
00180   PtypeO fromPtypeO=fromElement.ptypeO(), toPtypeO=toElement.ptypeO();
00181 
00182   if(fromPtypeO!=toPtypeO &&
00183      (fromPtypeO!=unpromote(toPtypeO) ||
00184       (!from.canPromote<P>() && !to.canPromote<P>())))
00185     return false;
00186   EffectContent effect=Ptype_Table.getEffect(fromPtypeO,from,to);
00187   if(!effect.hasEffect()) return false;
00188   if(effect.hasUnblockableEffect()) return true;
00189   Offset o=effect.offset();
00190   Square moveTo=lastMove.to(),moveFrom=lastMove.from();
00191   Square pos=from+o;
00192   for (;; pos+=o) {
00193     if(pos==to) return true;
00194     if(pos==moveTo) return false;
00195     if(!state.pieceAt(pos).isEmpty()){
00196       if(pos==moveFrom){
00197         for (pos+=o;; pos+=o) {
00198           if(pos==to) return true;
00199           if(pos==moveTo) return false;
00200           if(!state.pieceAt(pos).isEmpty()){
00201             break;
00202           }
00203         }
00204       }
00205       break;
00206     }
00207   }
00208   return false;
00209 }
00220 template<osl::Player P>
00221 bool osl::search::StateElements::canReject(osl::state::NumEffectState const& state,bool notRejectSennichite,bool notRootMove,Move lastMove,Move actualMove) const
00222 {
00223   const Player altP=PlayerTraits<P>::opponent;
00224   switch(myOnboardPlus.size()){
00225   case 0:
00226     switch(opOnboardPlus.size()){
00227     case 1: // myPlus=0, opPlus=1
00228       if(opOnboardMinus.size()==1 && myOnboardMinus.size()==0){
00229         // op simple move
00230         if(validSimpleMove<altP>(state,opOnboardPlus[0],opOnboardMinus[0],lastMove)){
00231           if(notRejectSennichite && stand.isZero()){
00232             return false;
00233           }
00234           return stand.geZero();
00235         }
00236       }
00237       return false;
00238     case 0:  // myPlus=0, opPlus=0
00239       if(opOnboardMinus.size()==1){
00240         if(myOnboardMinus.size()==0){
00241           StandElements localStand(stand);
00242         // op drop move
00243           Ptype ptype=getPtype(opOnboardMinus[0].ptypeO());
00244           if(!isPromoted(ptype)){
00245             localStand.sub(ptype);
00246             if(notRejectSennichite && localStand.isZero()){
00247               return false;
00248             }
00249             return localStand.geZero();
00250           }
00251         }
00252       }
00253       else{ // pass moves (including piece loosing cases)
00254         if(opOnboardMinus.size()==0 && myOnboardMinus.size()==0){
00255           return stand.gegtZero(!notRootMove);
00256         }
00257       }
00258       return false;
00259     default: return false;
00260     }
00261   case 1:  // myPlus=1
00262     switch(myOnboardMinus.size()){
00263     case 1:  // myPlus=1, myMinus=1
00264       switch(opOnboardMinus.size()){
00265       case 1:   // myPlus=1, myMinus=1, opMinus=1
00266         if(opOnboardPlus.size()==0){ // my capture move
00267           if(validCaptureMove<P>(state,myOnboardMinus[0],myOnboardPlus[0],opOnboardMinus[0],lastMove))
00268             {
00269             StandElements localStand(stand);
00270             Ptype capturePtype=unpromote(getPtype(opOnboardMinus[0].ptypeO()));
00271             // altPに関して減りすぎた分を増やす?
00272             // 相手に取って減っているはずなので,それをキャンセルする
00273             localStand.add(capturePtype);
00274             if(localStand.isZero()){
00275               assert(actualMove.player()==P);
00276               if(notRejectSennichite &&
00277                  actualMove.ptypeO()==myOnboardPlus[0].ptypeO() &&
00278                  actualMove.from()==myOnboardMinus[0].pos() &&
00279                  actualMove.to()==myOnboardPlus[0].pos()) return false;
00280               return true;
00281             }
00282             return localStand.geZero();
00283           }
00284         }
00285         return false;
00286       case 0:   // myPlus=1, myMinus=1, opMinus=0
00287         if(opOnboardPlus.size()==0){ // my simple move
00288           if(validSimpleMove<P>(state,myOnboardMinus[0],myOnboardPlus[0],lastMove)){
00289             if(stand.isZero()){
00290               assert(actualMove.player()==P);
00291               if(notRejectSennichite &&
00292                  actualMove.ptypeO()==myOnboardPlus[0].ptypeO() &&
00293                  actualMove.from()==myOnboardMinus[0].pos() &&
00294                  actualMove.to()==myOnboardPlus[0].pos()) return false;
00295               return true;
00296             }
00297             return stand.geZero();
00298           }
00299         }
00300         return false;
00301       }
00302     case 0:    // myPlus=1, myMinus=0
00303       if(opOnboardPlus.size()==1){
00304         if(opOnboardMinus.size()==1){
00305             if(validCaptureMove<altP>(state,opOnboardPlus[0],opOnboardMinus[0],myOnboardPlus[0],lastMove))
00306             {
00307             StandElements localStand(stand);
00308             Ptype capturePtype=unpromote(getPtype(myOnboardPlus[0].ptypeO()));
00309             // 次のmoveを実行すると相手に取っては増える.
00310             localStand.add(capturePtype);
00311             if(notRejectSennichite && localStand.isZero()){
00312               return false;
00313             }
00314             return localStand.geZero();
00315           }
00316         }
00317         else return false;
00318       }
00319       else if(opOnboardPlus.size()==0 && opOnboardMinus.size()==0 
00320               && !isPromoted(myOnboardPlus[0].ptypeO()) ){
00321         // my drop move
00322           StandElements localStand(stand);
00323           localStand.sub(getPtype(myOnboardPlus[0].ptypeO()));
00324           if(localStand.isZero()){
00325             if(notRejectSennichite &&
00326                actualMove.ptypeO()==myOnboardPlus[0].ptypeO() &&
00327                actualMove.isDrop() &&
00328                actualMove.to()==myOnboardPlus[0].pos()) return false;
00329             return true;
00330           }
00331           return localStand.geZero();
00332       }
00333     }
00334   default: return false;
00335   }
00336 }
00337 
00338 std::ostream& osl::search::operator<<(std::ostream& os,osl::search::StateElements const& mps)
00339 {
00340   {
00341     os << "[ MyOnboardPlus(";
00342     for(size_t i=0;i<mps.myOnboardPlus.size();i++)
00343       os << mps.myOnboardPlus[i] << ",\n";
00344     os << "),";
00345   }
00346   {
00347     os << "[ MyOnboardMinus(";
00348     for(size_t i=0;i<mps.myOnboardMinus.size();i++)
00349       os << mps.myOnboardMinus[i] << ",\n";
00350     os << "),";
00351   }
00352   {
00353     os << "[ OpOnboardPlus(";
00354     for(size_t i=0;i<mps.opOnboardPlus.size();i++)
00355       os << mps.opOnboardPlus[i] << ",\n";
00356     os << "),";
00357   }
00358   {
00359     os << "[ OpOnboardMinus(";
00360     for(size_t i=0;i<mps.opOnboardMinus.size();i++)
00361       os << mps.opOnboardMinus[i] << ",\n";
00362     os << "),";
00363   }
00364   return os << "Stand(" << mps.stand << ") ]\n" << std::endl;
00365 }
00366 
00367 #ifdef SHOW_PROBE_COUNTER
00368 struct ProbeCounter{
00369 #ifdef OSL_USE_RACE_DETECTOR
00370   osl::LightMutex mutex;
00371 #endif
00372   osl::misc::CArray<long long int,1024> check,hit;
00373   ProbeCounter(){}
00374   void incCheck(int d){ 
00375 #ifdef OSL_USE_RACE_DETECTOR
00376     osl::LightMutex::scoped_lock lk(mutex);
00377 #endif
00378     check[d]++; 
00379   }
00380   void incHit(int d){ 
00381 #ifdef OSL_USE_RACE_DETECTOR
00382     osl::LightMutex::scoped_lock lk(mutex);
00383 #endif
00384     hit[d]++; 
00385   }
00386   ~ProbeCounter(){
00387     for(int i=0;i<1024;i++){
00388       if(check[i]!=0){
00389         std::cerr << i << " : " << hit[i] << "/" << check[i] << std::endl;
00390       }
00391     }
00392   }
00393 };
00394 ProbeCounter probeCounter;
00395 #endif
00396 
00397 template<osl::Player P>
00398 bool osl::search::MoveStackRejections::
00399 probe(osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int curDepth,osl::Move const& m,int alpha,int checkCountOfAltP)
00400 {
00401   StateElements elements;
00402   elements.addMyMove(m);
00403   assert(m.player()==P);
00404   bool existNormal=false;
00405   for(int i=1;i<curDepth;i+=2){
00406     Move m1=history.lastMove(i);
00407     if(m1.isNormal()){
00408       assert(m1.player()==alt(P));
00409       elements.addOpMove(m1);
00410       existNormal=true;
00411     }
00412     if(elements.isLoop()){
00413       bool notRejectSennichite=osl::eval::betterThan(P,0,alpha) || (i<=checkCountOfAltP*2-1) || (i==curDepth-1);
00414       if(elements.stand.isZero()){
00415         if(!notRejectSennichite) return true;
00416       }
00417       else if(elements.stand.geZero()) return true;
00418     }
00419     Move m2=history.lastMove(i+1);
00420     if(m2.isNormal()){
00421       assert(m2.player()==P);
00422       elements.addMyMove(m2);
00423       existNormal=true;
00424     }
00425 #ifdef SHOW_PROBE_COUNTER
00426     probeCounter.incCheck(i);
00427 #endif
00428     // i==1 -- checkCount=1
00429     // i==3 -- checkCount=2
00430     bool notRejectSennichite=osl::eval::betterThan(P,0,alpha) || (i<=checkCountOfAltP*2-1);
00431     bool notRootMove=(i != curDepth-1);
00432     if(
00433        existNormal && 
00434        elements.canReject<P>(state,notRejectSennichite,notRootMove,m,m2)
00435        ){
00436 #ifdef SHOW_PROBE_COUNTER
00437       probeCounter.incHit(i);
00438 #endif
00439       return true;
00440     }
00441   }
00442   return false;
00443 }
00444 namespace osl
00445 {
00446   namespace search
00447   {
00448     template bool MoveStackRejections::probe<BLACK>(
00449                                                     osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int curDepth,osl::Move const& m,int alpha, int checkCountOfAltP);
00450     template bool MoveStackRejections::probe<WHITE>(
00451                                                     osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int curDepth,osl::Move const& m,int alpha,int checkCountOfAltP);
00452   }
00453 }
00454 
00455 
00456 // ;;; Local Variables:
00457 // ;;; mode:c++
00458 // ;;; c-basic-offset:2
00459 // ;;; End:
00460 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines