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::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:
00228 if(opOnboardMinus.size()==1 && myOnboardMinus.size()==0){
00229
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:
00239 if(opOnboardMinus.size()==1){
00240 if(myOnboardMinus.size()==0){
00241 StandElements localStand(stand);
00242
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{
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:
00262 switch(myOnboardMinus.size()){
00263 case 1:
00264 switch(opOnboardMinus.size()){
00265 case 1:
00266 if(opOnboardPlus.size()==0){
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
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:
00287 if(opOnboardPlus.size()==0){
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:
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
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
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
00429
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
00457
00458
00459
00460