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 mayRejectSennichite,bool isRootMove,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(!mayRejectSennichite && 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(!mayRejectSennichite && 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           if(isRootMove) return stand.gtZero();
00256           else return stand.geZero(); 
00257         }
00258       }
00259       return false;
00260     default: return false;
00261     }
00262   case 1:  // myPlus=1
00263     switch(myOnboardMinus.size()){
00264     case 1:  // myPlus=1, myMinus=1
00265       switch(opOnboardMinus.size()){
00266       case 1:   // myPlus=1, myMinus=1, opMinus=1
00267         if(opOnboardPlus.size()==0){ // my capture move
00268           if(validCaptureMove<P>(state,myOnboardMinus[0],myOnboardPlus[0],opOnboardMinus[0],lastMove))
00269             {
00270             StandElements localStand(stand);
00271             Ptype capturePtype=unpromote(getPtype(opOnboardMinus[0].ptypeO()));
00272             // altPに関して減りすぎた分を増やす?
00273             // 相手に取って減っているはずなので,それをキャンセルする
00274             localStand.add(capturePtype);
00275             if(localStand.isZero()){
00276               assert(actualMove.player()==P);
00277               if(!mayRejectSennichite &&
00278                  actualMove.ptypeO()==myOnboardPlus[0].ptypeO() &&
00279                  actualMove.from()==myOnboardMinus[0].pos() &&
00280                  actualMove.to()==myOnboardPlus[0].pos()) return false;
00281               return true;
00282             }
00283             return localStand.geZero();
00284           }
00285         }
00286         return false;
00287       case 0:   // myPlus=1, myMinus=1, opMinus=0
00288         if(opOnboardPlus.size()==0){ // my simple move
00289           if(validSimpleMove<P>(state,myOnboardMinus[0],myOnboardPlus[0],lastMove)){
00290             if(stand.isZero()){
00291               assert(actualMove.player()==P);
00292               if(!mayRejectSennichite &&
00293                  actualMove.ptypeO()==myOnboardPlus[0].ptypeO() &&
00294                  actualMove.from()==myOnboardMinus[0].pos() &&
00295                  actualMove.to()==myOnboardPlus[0].pos()) return false;
00296               return true;
00297             }
00298             return stand.geZero();
00299           }
00300         }
00301         return false;
00302       }
00303     case 0:    // myPlus=1, myMinus=0
00304       if(opOnboardPlus.size()==1){
00305         if(opOnboardMinus.size()==1){
00306             if(validCaptureMove<altP>(state,opOnboardPlus[0],opOnboardMinus[0],myOnboardPlus[0],lastMove))
00307             {
00308             StandElements localStand(stand);
00309             Ptype capturePtype=unpromote(getPtype(myOnboardPlus[0].ptypeO()));
00310             // 次のmoveを実行すると相手に取っては増える.
00311             localStand.add(capturePtype);
00312             if(!mayRejectSennichite && localStand.isZero()){
00313               return false;
00314             }
00315             return localStand.geZero();
00316           }
00317         }
00318         else return false;
00319       }
00320       else if(opOnboardPlus.size()==0 && opOnboardMinus.size()==0 
00321               && !isPromoted(myOnboardPlus[0].ptypeO()) ){
00322         // my drop move
00323           StandElements localStand(stand);
00324           localStand.sub(getPtype(myOnboardPlus[0].ptypeO()));
00325           if(localStand.isZero()){
00326             if(!mayRejectSennichite &&
00327                actualMove.ptypeO()==myOnboardPlus[0].ptypeO() &&
00328                actualMove.isDrop() &&
00329                actualMove.to()==myOnboardPlus[0].pos()) return false;
00330             return true;
00331           }
00332           return localStand.geZero();
00333       }
00334     }
00335   default: return false;
00336   }
00337 }
00338 
00339 std::ostream& osl::search::operator<<(std::ostream& os,osl::search::StateElements const& mps)
00340 {
00341   {
00342     os << "[ MyOnboardPlus(";
00343     for(size_t i=0;i<mps.myOnboardPlus.size();i++)
00344       os << mps.myOnboardPlus[i] << ",\n";
00345     os << "),";
00346   }
00347   {
00348     os << "[ MyOnboardMinus(";
00349     for(size_t i=0;i<mps.myOnboardMinus.size();i++)
00350       os << mps.myOnboardMinus[i] << ",\n";
00351     os << "),";
00352   }
00353   {
00354     os << "[ OpOnboardPlus(";
00355     for(size_t i=0;i<mps.opOnboardPlus.size();i++)
00356       os << mps.opOnboardPlus[i] << ",\n";
00357     os << "),";
00358   }
00359   {
00360     os << "[ OpOnboardMinus(";
00361     for(size_t i=0;i<mps.opOnboardMinus.size();i++)
00362       os << mps.opOnboardMinus[i] << ",\n";
00363     os << "),";
00364   }
00365   return os << "Stand(" << mps.stand << ") ]\n" << std::endl;
00366 }
00367 
00368 #ifdef SHOW_PROBE_COUNTER
00369 struct ProbeCounter{
00370 #ifdef OSL_USE_RACE_DETECTOR
00371   osl::LightMutex mutex;
00372 #endif
00373   osl::misc::CArray<long long int,1024> check,hit;
00374   ProbeCounter(){}
00375   void incCheck(int d){ 
00376 #ifdef OSL_USE_RACE_DETECTOR
00377     osl::LightMutex::scoped_lock lk(mutex);
00378 #endif
00379     check[d]++; 
00380   }
00381   void incHit(int d){ 
00382 #ifdef OSL_USE_RACE_DETECTOR
00383     osl::LightMutex::scoped_lock lk(mutex);
00384 #endif
00385     hit[d]++; 
00386   }
00387   ~ProbeCounter(){
00388     for(int i=0;i<1024;i++){
00389       if(check[i]!=0){
00390         std::cerr << i << " : " << hit[i] << "/" << check[i] << std::endl;
00391       }
00392     }
00393   }
00394 };
00395 ProbeCounter probeCounter;
00396 #endif
00397 
00398 template<osl::Player P>
00399 bool osl::search::MoveStackRejections::
00400 probe(osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int ply,osl::Move const& m,int alpha,int checkCountOfAltP)
00401 {
00402   StateElements elements;
00403   elements.addMyMove(m);
00404   assert(m.player()==P);
00405   bool existNormal=false;
00406   for(int i=1;i<ply;i+=2){
00407     Move m1=history.lastMove(i);
00408     if(m1.isNormal()){
00409       assert(m1.player()==alt(P));
00410       elements.addOpMove(m1);
00411       existNormal=true;
00412     }
00413     else if(m1.isInvalid()) return false;
00414     if(elements.isLoop()){
00415       bool mayRejectSennichite=osl::eval::notLessThan(P,alpha,0) && (i>checkCountOfAltP*2-1);
00416       if(elements.stand.isZero()){
00417         if(mayRejectSennichite) return true;
00418       }
00419       else if(elements.stand.geZero()) return true;
00420     }
00421     Move m2=history.lastMove(i+1);
00422     if(m2.isNormal()){
00423       assert(m2.player()==P);
00424       elements.addMyMove(m2);
00425       existNormal=true;
00426     }
00427     else if(m2.isInvalid()) return false;
00428 #ifdef SHOW_PROBE_COUNTER
00429     probeCounter.incCheck(i);
00430 #endif
00431     // i==1 -- checkCount=1
00432     // i==3 -- checkCount=2
00433     bool mayRejectSennichite=osl::eval::notLessThan(P,alpha,0) && (i>checkCountOfAltP*2-1);
00434     bool isRootMove=(i == ply-1);
00435     if(
00436        existNormal && 
00437        elements.canReject<P>(state,mayRejectSennichite,isRootMove,m,m2)
00438        ){
00439 #ifdef SHOW_PROBE_COUNTER
00440       probeCounter.incHit(i);
00441 #endif
00442       return true;
00443     }
00444   }
00445   return false;
00446 }
00447 namespace osl
00448 {
00449   namespace search
00450   {
00451     template bool MoveStackRejections::probe<BLACK>(
00452                                                     osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int ply,osl::Move const& m,int alpha, int checkCountOfAltP);
00453     template bool MoveStackRejections::probe<WHITE>(
00454                                                     osl::state::NumEffectState const& state,osl::container::MoveStack const& history,int ply,osl::Move const& m,int alpha,int checkCountOfAltP);
00455   }
00456 }
00457 
00458 
00459 // ;;; Local Variables:
00460 // ;;; mode:c++
00461 // ;;; c-basic-offset:2
00462 // ;;; End:
00463 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines