00001
00002
00003 #ifndef _CHECKMATE_IMMEDIATE_CHECKMATE_TCC
00004 #define _CHECKMATE_IMMEDIATE_CHECKMATE_TCC
00005 #include "osl/checkmate/immediateCheckmate.h"
00006 #include "osl/checkmate/immediateCheckmateTable.h"
00007 #include "osl/move_classifier/kingOpenMove.h"
00008 #include "osl/effect_util/effectUtil.h"
00009 #include "osl/effect_util/additionalEffect.h"
00010 #include "osl/directionTraits.h"
00011 #include "osl/pieceTable.h"
00012 #include "osl/misc/bitOp.h"
00013 #include "osl/misc/mask.h"
00014
00015 namespace osl
00016 {
00017 namespace checkmate
00018 {
00019 namespace detail {
00020 using osl::misc::BitOp;
00021 template<Player P>
00022 bool blockingVerticalAttack(NumEffectState const& state,Position pos)
00023 {
00024 PieceMask effect=state.getEffect(pos)&
00025 state.getEffect(pos+DirectionPlayerTraits<U,P>::offset());
00026 mask_t mask=effect.getMask(1);
00027 mask&=(state.getOnBoardMask(P).getMask(1)<<8);
00028 if((mask&mask_t::makeDirect(PtypeFuns<LANCE>::indexMask<<8)).none()){
00029 mask&=mask_t::makeDirect(PtypeFuns<ROOK>::indexMask<<8);
00030 while(mask.any()){
00031 int num=mask.takeOneBit()+NumBitmapEffect::longToNumOffset;
00032 Position from=state.getPieceOf(num).position();
00033 assert(from.isOnBoard());
00034 if(from.isU<P>(pos)) goto found;
00035 }
00036 return false;
00037 found:;
00038 }
00039 const Offset offset=DirectionPlayerTraits<U,P>::offset();
00040 pos+=offset;
00041 const Player altP=PlayerTraits<P>::opponent;
00042 for(int i=0;i<3;i++,pos+=offset){
00043 Piece p=state.getPieceAt(pos);
00044 if(p.canMoveOn<altP>()){
00045 if(state.countEffect(P,pos)==1) return true;
00046 if(!p.isEmpty()) return false;
00047 }
00048 else return false;
00049 }
00050 return false;
00051 }
00052 template<Player P>
00053 bool blockingDiagonalAttack(NumEffectState const& state,Position pos,Position target,
00054 King8Info canMoveMask)
00055 {
00056 const Player altP=PlayerTraits<P>::opponent;
00057 Position to=target-DirectionPlayerTraits<U,P>::offset();
00058
00059 if((canMoveMask.value&(0x10000<<U))==0) return false;
00060 PieceMask effect=state.getEffect(to)&state.getEffect(pos);
00061 mask_t mask=effect.getMask(1);
00062 mask&=(state.getOnBoardMask(P).getMask(1)<<8);
00063 mask&=mask_t::makeDirect(PtypeFuns<BISHOP>::indexMask<<8);
00064 while(mask.any()){
00065 int num=mask.takeOneBit()+NumBitmapEffect::longToNumOffset;
00066 Position from=state.getPieceOf(num).position();
00067 assert(from.isOnBoard());
00068 Offset offset=Board_Table.getShort8OffsetUnsafe(to,from);
00069 if(to+offset != pos) continue;
00070 if(state.countEffect(P,to)==1) return true;
00071
00072 if(!state.getPieceAt(to).isEmpty()) return false;
00073 Position pos1=to-offset;
00074
00075 Piece p=state.getPieceAt(pos1);
00076 if(p.canMoveOn<altP>() &&
00077 state.countEffect(P,pos1)==1){
00078 return true;
00079 }
00080 }
00081 return false;
00082 }
00083 template<Player P,bool canDrop,bool setBestMove>
00084 bool hasKnightCheckmate(NumEffectState const& state,
00085 Position target,
00086 Position pos,
00087 King8Info canMoveMask,
00088 Move& bestMove, mask_t mask1)
00089 {
00090 if(!pos.isOnBoard()) return false;
00091 const Player altP=PlayerTraits<P>::opponent;
00092 Piece p=state.getPieceAt(pos);
00093 if(p.canMoveOn<P>() &&
00094 !state.hasEffectNotMask(altP,pos,~state.pinOrOpen(altP))
00095 ){
00096 mask_t mask=state.getEffect(pos).getMask<KNIGHT>()&mask1;
00097 if(mask.any()){
00098 if(blockingVerticalAttack<P>(state,pos) ||
00099 blockingDiagonalAttack<P>(state,pos,target,canMoveMask)) return false;
00100 if(setBestMove){
00101 int num=mask.takeOneBit()+(PtypeFuns<KNIGHT>::indexNum<<5);
00102 Piece p1=state.getPieceOf(num);
00103 Position from=p1.position();
00104 bestMove=Move(from,pos,KNIGHT,p.ptype(),false,P);
00105 }
00106 return true;
00107 }
00108 else if(canDrop && p.isEmpty()){
00109 if(blockingVerticalAttack<P>(state,pos) ||
00110 blockingDiagonalAttack<P>(state,pos,target,canMoveMask)) return false;
00111 if(setBestMove)
00112 bestMove=Move(pos,KNIGHT,P);
00113 return true;
00114 }
00115 }
00116 return false;
00117 }
00118
00119
00120 template<Player P,bool setBestMove>
00121 bool hasCheckmateMoveKnight(NumEffectState const& state, Position target,
00122 King8Info canMoveMask,Move& bestMove)
00123 {
00124
00125 if((canMoveMask.value&0xff00)!=0) return false;
00126 mask_t mask=mask_t::makeDirect(PtypeFuns<KNIGHT>::indexMask);
00127 mask&=state.getOnBoardMask(P).getMask<KNIGHT>();
00128 mask&= ~state.promotedPieces().getMask<KNIGHT>();
00129 mask&= ~state.pinOrOpen(P).getMask<KNIGHT>();
00130 if(state.hasPieceOnStand<KNIGHT>(P)){
00131 Position pos=target-DirectionPlayerTraits<UUR,P>::offset();
00132 if(hasKnightCheckmate<P,true,setBestMove>(state,target,pos,canMoveMask,bestMove,mask))
00133 return true;
00134 pos=target-DirectionPlayerTraits<UUL,P>::offset();
00135 return hasKnightCheckmate<P,true,setBestMove>(state,target,pos,canMoveMask,bestMove,mask);
00136 }
00137 else{
00138 Position pos=target-DirectionPlayerTraits<UUR,P>::offset();
00139 if(hasKnightCheckmate<P,false,setBestMove>(state,target,pos,canMoveMask,bestMove,mask))
00140 return true;
00141 pos=target-DirectionPlayerTraits<UUL,P>::offset();
00142 return hasKnightCheckmate<P,false,setBestMove>(state,target,pos,canMoveMask,bestMove,mask);
00143 }
00144 return false;
00145 }
00146 template<Player P,bool setBestMove>
00147 bool slowCheckDrop(NumEffectState const& state,Position target,
00148 Ptype ptype,King8Info canMoveMask,Move& bestMove)
00149 {
00150 unsigned int dropMask=(canMoveMask.value&0xff)
00151 &Immediate_Checkmate_Table.ptypeDropMask(ptype,canMoveMask);
00152
00153 assert(dropMask!=0);
00154 while(dropMask!=0){
00155 int i=BitOp::takeOneBit(dropMask);
00156 Direction d=static_cast<Direction>(i);
00157 unsigned int blockingMask=Immediate_Checkmate_Table.blockingMask(ptype,d) &
00158 (canMoveMask.value>>16);
00159 Position drop=target-Board_Table.getOffset<P>(d);
00160 if(blockingMask!=0){
00161 NumBitmapEffect effect=state.getEffect(drop);
00162 mask_t longEffect=effect.getMask(1)&NumBitmapEffect::longEffectMask();
00163 longEffect&=(state.getOnBoardMask(P).getMask(1)<<8);
00164 if(longEffect.any()){
00165 do{
00166 int j=BitOp::takeOneBit(blockingMask);
00167 Direction d1=static_cast<Direction>(j);
00168 Position pos=target-Board_Table.getOffset<P>(d1);
00169 NumBitmapEffect effect1=state.getEffect(pos);
00170 if(effect1.countEffect(P)>1) continue;
00171 mask_t longEffect1=effect1.getMask(1)&longEffect;
00172 if(!longEffect1.any()) continue;
00173
00174 int num=longEffect1.takeOneBit()+NumBitmapEffect::longToNumOffset;
00175 if(Board_Table.isBetween(drop,state.getPieceOf(num).position(),pos))
00176 goto tryNext;
00177 }while(blockingMask!=0);
00178 }
00179 }
00180
00181 if(setBestMove)
00182 bestMove=Move(drop,ptype,P);
00183 return true;
00184 tryNext:;
00185 }
00186 return false;
00187 }
00188 }
00189 }
00190 }
00191
00192
00193 template<osl::Player P,bool setBestMove>
00194 bool osl::checkmate::ImmediateCheckmate::
00195 hasCheckmateDrop(NumEffectState const& state, Position target,
00196 King8Info canMoveMask,Move& bestMove)
00197 {
00198 typedef misc::GeneralMask<unsigned short> mask_t;
00199 mask_t dropPtypeMask=mask_t::makeDirect(Immediate_Checkmate_Table.dropPtypeMask(canMoveMask));
00200 while(dropPtypeMask.any()){
00201 Ptype ptype=static_cast<Ptype>(dropPtypeMask.takeOneBit()+PTYPE_BASIC_MIN);
00202 if(state.hasPieceOnStand(P,ptype) &&
00203 detail::slowCheckDrop<P,setBestMove>(state,target,ptype,canMoveMask,
00204 bestMove))
00205 return true;
00206 }
00207 return false;
00208 }
00209
00210 template<osl::Player P,bool setBestMove>
00211 bool osl::checkmate::ImmediateCheckmate::
00212 slowHasCheckmateMoveDirPiece(NumEffectState const& state, Position target,
00213 King8Info canMoveMask,Direction d,Position pos,Piece p,Ptype ptype,Move& bestMove){
00214 const Player altP=PlayerTraits<P>::opponent;
00215
00216 if(ptype==PROOK){
00217 int dx=target.x()-pos.x();
00218 int dy=target.y()-pos.y();
00219 if(abs(dx)==1 && abs(dy)==1){
00220 {
00221 Position pos1=pos+Offset(dx,0);
00222 Piece p1=state.getPieceAt(pos1);
00223 if(!p1.isEmpty()){
00224 {
00225
00226
00227
00228
00229
00230
00231
00232 Position pos2=pos+Offset(2*dx,0);
00233 if(state.getPieceAt(pos2).template canMoveOn<altP>()){
00234 NumBitmapEffect effect2=state.getEffect(pos2);
00235 if(effect2.countEffect(P)==0 ||
00236 (effect2.countEffect(P)==1 &&
00237 effect2.test(p.number())))
00238 return false;
00239 }
00240 }
00241 {
00242
00243
00244
00245
00246
00247 if(p.position()==target-Offset(0,2*dy) &&
00248 state.hasEffectByPiece(p1,pos))
00249 return false;
00250 }
00251 }
00252 }
00253 {
00254 Position pos1=pos+Offset(0,dy);
00255 Piece p1=state.getPieceAt(pos1);
00256 if(!p1.isEmpty()){
00257 Position pos2=pos+Offset(0,2*dy);
00258 {
00259 if(state.getPieceAt(pos2).template canMoveOn<altP>()){
00260 NumBitmapEffect effect2=state.getEffect(pos2);
00261 if(effect2.countEffect(P)==0 ||
00262 (effect2.countEffect(P)==1 &&
00263 effect2.test(p.number())))
00264 return false;
00265
00266 }
00267 {
00268
00269
00270
00271
00272 if(p.position()==target-Offset(2*dx,0) &&
00273 state.hasEffectByPiece(p1,pos))
00274 return false;
00275 }
00276 }
00277 }
00278 }
00279 }
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289 mask_t mask=mask_t::makeDirect((canMoveMask.value>>16)&Immediate_Checkmate_Table.noEffectMask(ptype,d));
00290 if(mask.any()){
00291 int num=p.number();
00292 NumBitmapEffect effect2=state.getEffect(pos);
00293 effect2.reset(num+8);
00294 mask_t longEffect2=effect2.getMask(1)&NumBitmapEffect::longEffectMask();
00295 longEffect2&=(state.getOnBoardMask(P).getMask(1)<<8);
00296 do {
00297 Direction d1=static_cast<Direction>(mask.takeOneBit());
00298 Position pos1=target-Board_Table.getOffset<P>(d1);
00299 NumBitmapEffect effect1=state.getEffect(pos1);
00300 int count=effect1.countEffect(P);
00301
00302 if(effect1.test(num)) count--;
00303 if(count==0) return false;
00304
00305 mask_t longEffect1=effect1.getMask(1)&longEffect2;
00306 while(longEffect1.any()){
00307 int num1=longEffect1.takeOneBit()+NumBitmapEffect::longToNumOffset;
00308 if(Board_Table.isBetween(pos,state.getPieceOf(num1).position(),pos1))
00309 count--;
00310 if(count==0) return false;
00311 }
00312 } while (mask.any());
00313 }
00314
00315 if(move_classifier::KingOpenMove<P>::isMember(state,ptype,p.position(),pos)) return false;
00316 if(setBestMove){
00317 bestMove=Move(p.position(),pos,ptype,
00318 state.getPieceAt(pos).ptype(),
00319 ptype!=p.ptype(),P);
00320 }
00321 return true;
00322 }
00323
00324 template<osl::Player P,bool setBestMove>
00325 bool osl::checkmate::ImmediateCheckmate::
00326 hasCheckmateMoveDirPiece(NumEffectState const& state, Position target,
00327 King8Info canMoveMask,Direction d,Position pos,Piece p,Move& bestMove){
00328 Position from=p.position();
00329 Ptype ptype=p.ptype();
00330
00331 {
00332 const Player altP=PlayerTraits<P>::opponent;
00333 Direction d1=Board_Table.getShort8Unsafe<P>(from,pos);
00334 if(d1!=DIRECTION_INVALID_VALUE){
00335 int num=state.longEffectNumTable()[p.number()][P==BLACK ? d1 : inverse(d1)];
00336 if(num != EMPTY_NUM && state.getPieceOf(num).isOnBoardByOwner<altP>())
00337 return false;
00338 }
00339 }
00340 if(canPromote(ptype) &&
00341 (from.canPromote<P>() || pos.canPromote<P>())){
00342 Ptype pptype=promote(ptype);
00343 if((((canMoveMask.value>>8)|0x100)&
00344 Immediate_Checkmate_Table.noEffectMask(pptype,d))==0){
00345 if(slowHasCheckmateMoveDirPiece<P,setBestMove>(state,target,canMoveMask,d,pos,p,pptype,bestMove)) return true;
00346 }
00347 if (ptype==PAWN || isMajorBasic(ptype))
00348 return false;
00349 }
00350 if((((canMoveMask.value>>8)|0x100)&
00351 Immediate_Checkmate_Table.noEffectMask(ptype,d))==0){
00352 if(slowHasCheckmateMoveDirPiece<P,setBestMove>(state,target,canMoveMask,d,pos,p,ptype,bestMove)) return true;
00353 }
00354 return false;
00355 }
00356
00357 template<osl::Player P,bool setBestMove>
00358 bool osl::checkmate::ImmediateCheckmate::
00359 hasCheckmateMoveDir(NumEffectState const& state, Position target,
00360 King8Info canMoveMask,Direction d,Move& bestMove){
00361 Position pos=target-Board_Table.getOffset<P>(d);
00362 if(state.countEffect(P,pos)<2 &&
00363 !effect_util::AdditionalEffect::hasEffect(state,pos,P)) return false;
00364 PieceMask pieceMask=state.getOnBoardMask(P)&state.getEffect(pos);
00365 assert(pos.isOnBoard());
00366
00367 pieceMask.reset(KingTraits<P>::index);
00368 for(int i=0;i<=PieceMask::numToIndex(40);i++){
00369 mask_t mask=pieceMask.getMask(i);
00370 while (mask.any()){
00371 const int num=mask.takeOneBit()+i*32;
00372 if(hasCheckmateMoveDirPiece<P,setBestMove>(state,target,canMoveMask,d,pos,state.getPieceOf(num),bestMove)) return true;
00373 }
00374 }
00375 return false;
00376 }
00377
00378
00379 template<osl::Player P,bool setBestMove>
00380 bool osl::checkmate::ImmediateCheckmate::
00381 hasCheckmateMove(NumEffectState const& state, Position target,
00382 King8Info canMoveMask,Move& bestMove)
00383 {
00384 assert(! state.inCheck());
00385 typedef misc::GeneralMask<unsigned int> mask_t;
00386 mask_t mask2=mask_t::makeDirect((canMoveMask.value>>24)&0xff);
00387 while(mask2.any()){
00388 Direction d=static_cast<Direction>(mask2.takeOneBit());
00389 if(hasCheckmateMoveDir<P,setBestMove>(state,target,canMoveMask,d,bestMove)) return true;
00390 }
00391 return false;
00392 }
00393
00394 template<osl::Player P>
00395 bool osl::checkmate::ImmediateCheckmate::
00396 hasCheckmateMove(NumEffectState const& state, King8Info canMoveMask)
00397 {
00398 const Player altP=PlayerTraits<P>::opponent;
00399 const Position target=state.getKingPosition(altP);
00400 assert(target.isOnBoard());
00401
00402 Move dummy;
00403 if(hasCheckmateMove<P,false>(state,target,canMoveMask,dummy)) return true;
00404 if(detail::hasCheckmateMoveKnight<P,false>(state,target,canMoveMask,dummy)) return true;
00405 return hasCheckmateDrop<P,false>(state,target,canMoveMask,dummy);
00406 }
00407
00408 template<osl::Player P>
00409 bool osl::checkmate::ImmediateCheckmate::
00410 hasCheckmateMove(NumEffectState const& state)
00411 {
00412 const Player altP=PlayerTraits<P>::opponent;
00413 const Position target=state.getKingPosition(altP);
00414 assert(target.isOnBoard());
00415 King8Info canMoveMask(state.Iking8Info(altP));
00416 return hasCheckmateMove<P>(state, canMoveMask);
00417 }
00418
00419 template<osl::Player P>
00420 bool osl::checkmate::ImmediateCheckmate::
00421 hasCheckmateMove(NumEffectState const& state, King8Info canMoveMask,
00422 Position target, Move& bestMove)
00423 {
00424 assert(! state.inCheck());
00425 assert(target.isOnBoard());
00426
00427 if(hasCheckmateMove<P,true>(state,target,canMoveMask,bestMove)) return true;
00428 if(detail::hasCheckmateMoveKnight<P,true>(state,target,canMoveMask,bestMove)) return true;
00429 return hasCheckmateDrop<P,true>(state,target,canMoveMask,bestMove);
00430 }
00431
00432 template<osl::Player P>
00433 bool osl::checkmate::ImmediateCheckmate::
00434 hasCheckmateMove(NumEffectState const& state,Move& bestMove)
00435 {
00436 const Player altP=PlayerTraits<P>::opponent;
00437 const Position target=state.getKingPosition(altP);
00438 King8Info canMoveMask(state.Iking8Info(altP));
00439 return hasCheckmateMove<P>(state, canMoveMask, target, bestMove);
00440 }
00441
00442 #endif
00443
00444
00445
00446
00447