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 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:
00228 if(opOnboardMinus.size()==1 && myOnboardMinus.size()==0){
00229
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:
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(!mayRejectSennichite && localStand.isZero()){
00247 return false;
00248 }
00249 return localStand.geZero();
00250 }
00251 }
00252 }
00253 else{
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:
00263 switch(myOnboardMinus.size()){
00264 case 1:
00265 switch(opOnboardMinus.size()){
00266 case 1:
00267 if(opOnboardPlus.size()==0){
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
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:
00288 if(opOnboardPlus.size()==0){
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:
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
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
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
00432
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
00460
00461
00462
00463