00001 #ifndef _GENERATER_ADD_EFFECT_WITH_EFFECT_TCC
00002 #define _GENERATER_ADD_EFFECT_WITH_EFFECT_TCC
00003
00004 #include "osl/move_generator/addEffectWithEffect.h"
00005 #include "osl/move_generator/open.h"
00006 #include "osl/move_generator/open.tcc"
00007 #include "osl/move_generator/pieceOnBoard.tcc"
00008 #include "osl/checkmate/king8Info.h"
00009
00010
00011
00012 namespace osl
00013 {
00014 namespace move_generator
00015 {
00016 namespace detail
00017 {
00029 template<osl::Player P,class Action>
00030 void generateMovePiecePtypeMask(const NumEffectState& state,Piece p,Position to,Piece toP,Action& action,unsigned int ptypeMask)
00031 {
00032 assert(p.isOnBoardByOwner<P>());
00033 assert(toP==state.getPieceAt(to));
00034 Ptype ptype=p.ptype();
00035 Position from=p.position();
00036 if(canPromote(ptype) &&
00037 (to.canPromote<P>() || from.canPromote<P>())){
00038 Ptype pptype=osl::promote(ptype);
00039 if(((1<<pptype)&ptypeMask)!=0)
00040 action.unknownMove(from,to,toP,pptype,true,P);
00041 if(Move::ignoreUnpromote<P>(ptype,from,to)) return;
00042 }
00043
00044 if(((1<<ptype)&ptypeMask)!=0)
00045 action.unknownMove(p.position(),to,toP,ptype,false,P);
00046 }
00057 template<osl::Player P,class Action>
00058 void generateMoveToPtypeMaskWithPieceMask(const NumEffectState& state,Position to,Piece toP,Action& action,unsigned int ptypeMask,PieceMask pieceMask)
00059 {
00060 if(pieceMask.test(KingTraits<P>::index)){
00061 const Player altP=PlayerTraits<P>::opponent;
00062 if(!state.hasEffectBy<altP>(to)){
00063 action.unknownMove(state.getKingPosition<P>(),to,toP,KING,false,P);
00064 }
00065 pieceMask.reset(KingTraits<P>::index);
00066 }
00067 while (pieceMask.any()){
00068 const int num=pieceMask.takeOneBit();
00069 Piece p=state.getPieceOf(num);
00070 if(state.pinOrOpen(P).test(num)){
00071 Direction d=state.pinnedDir<P>(p);
00072 Direction d1=Board_Table.template getShort8Unsafe<P>(p.position(),to);
00073 if(primDir(d)!=primDirUnsafe(d1)) continue;
00074 }
00075 generateMovePiecePtypeMask<P,Action>(state,p,to,toP,action,ptypeMask);
00076 }
00077 }
00078 template<osl::Player P,class Action>
00079 void generateMoveToPtypeMask(const NumEffectState& state,Position to,Piece toP,Action& action,unsigned int ptypeMask)
00080 {
00081 PieceMask pieceMask=state.getOnBoardMask(P)&state.getEffect(to);
00082 const Player altP=PlayerTraits<P>::opponent;
00083 pieceMask.reset(KingTraits<P>::index);
00084 pieceMask &= ~state.pinOrOpen(altP);
00085 generateMoveToPtypeMaskWithPieceMask<P,Action>(state,to,toP,action,ptypeMask,pieceMask);
00086 }
00087 #ifndef GENERATE_PAWNDROP_CHECKMATE
00088
00091 template<osl::Player P>
00092 bool blockingU(const NumEffectState& state,Position pos)
00093 {
00094 const osl::Player altP=PlayerTraits<P>::opponent;
00095 NumBitmapEffect effect=state.getEffect(pos);
00096 mask_t mask=(effect.getMask(1)& NumBitmapEffect::longEffectMask());
00097 mask&=state.getOnBoardMask(P).getMask(1)<<8;
00098 while(mask.any()){
00099 int num=mask.takeOneBit()+NumBitmapEffect::longToNumOffset;
00100 Position from=state.getPieceOf(num).position();
00101 if( (P==BLACK ? from.y()>=pos.y() : pos.y()>=from.y()) ){
00102 Position shadowPos=pos+Board_Table.getShortOffset(Offset32(pos,from));
00103 assert((P==BLACK ? shadowPos.y()<=pos.y() : pos.y()<=shadowPos.y()) );
00104 Piece p=state.getPieceAt(shadowPos);
00105 if(p.canMoveOn<altP>() && !state.hasMultipleEffectBy(P,shadowPos)){
00106 return true;
00107 }
00108 }
00109 }
00110 return false;
00111 }
00112 #endif
00113
00119 template<osl::Player P,int DirType,class Action>
00120 void generateDir(const NumEffectState& state,Position target,Action& action,bool& hasPawnCheckmate,Offset dirOffset,Direction Dir,Direction primDir,int ptypeMaskNotKing)
00121 {
00122 const Player altP=PlayerTraits<P>::opponent;
00123 Position pos=target-dirOffset;
00124 if(!pos.isOnBoard()) return;
00125 Piece p=state.getPieceAt(pos);
00126 if(p.isOnBoardByOwner<P>()){
00127 if(DirType==0 && state.hasEffectLong<LANCE>(P,pos)){
00128 PieceOnBoard<Action>::template generate<P,true>(state,p,action,1<<primDir);
00129 }
00130 return;
00131 }
00132 if((state.Iking8Info(altP)&(1ull<<(40+Dir)))!=0){
00133
00134
00135 generateMoveToPtypeMask<P,Action>(state,pos,p,action,
00136 ptypeMaskNotKing);
00137 }
00138 if(DirType !=0) return;
00139 if(p.isEmpty()){
00140 Position pos1=state.kingMobilityOfPlayer(altP,Dir);
00141 mask_t lance_mask=state.selectLong<LANCE>(pos1,P);
00142 if(lance_mask.any()){
00143 Piece p1=state.getPieceAt(pos1);
00144 if(p1.isOnBoardByOwner<P>()){
00145 PieceOnBoard<Action>::template generate<P,true>(state,p1,action,1<<primDir);
00146
00147 if(state.hasEffectByPiece(p1,pos)){
00148 PieceOnBoard<Action>::template generatePiece<P>(state,p1,pos,Piece::EMPTY(),action);
00149 }
00150 }
00151 else if(p1.isOnBoardByOwner<altP>()){
00152 assert(!lance_mask.hasMultipleBit());
00153 int num=lance_mask.bsf()+PtypeFuns<LANCE>::indexNum*32;
00154 Piece p2=state.getPieceOf(num);
00155 action.unknownMove(p2.position(),pos1,p1,LANCE,false,P);
00156 }
00157 }
00158
00159
00160 if(! state.isPawnMaskSet<P>(target.x()) &&
00161 state.hasPieceOnStand<PAWN>(P)){
00162
00163 #ifndef GENERATE_PAWNDROP_CHECKMATE
00164 if(((state.Iking8Info(altP)&(0xff00ull|(1ull<<(U+24))))^(1ull<<(U+24)))!=0 || blockingU<P>(state,pos))
00165 action.dropMove(pos,PAWN,P);
00166 else
00167 hasPawnCheckmate=true;
00168 #else
00169 action.dropMove(pos,PAWN,P);
00170 #endif
00171 }
00172 if(state.hasPieceOnStand<LANCE>(P)){
00173 action.dropMove(pos,LANCE,P);
00174 for(pos-=DirectionPlayerTraits<U,P>::offset();
00175 pos!=pos1;pos-=DirectionPlayerTraits<U,P>::offset()){
00176 action.dropMove(pos,LANCE,P);
00177 }
00178 }
00179 }
00180 }
00181
00182 template<osl::Player P,int DirType,class Action,Direction Dir>
00183 void generateDir(const NumEffectState& state,Position target,Action& action,bool& hasPawnCheckmate)
00184 {
00185 generateDir<P,DirType,Action>(state,target,action,hasPawnCheckmate,
00186 DirectionPlayerTraits<Dir,P>::offset(),Dir,DirectionTraits<Dir>::primDir,DirectionTraits<Dir>::ptypeMaskNotKing);
00187 }
00194 template<osl::Player P,int DirType,class Action>
00195 void generateDirNotKing(const NumEffectState& state,Position target,Action& action,CArray<unsigned char,8>& pieceMobility, int& spaces, PieceMask const& notPieceMask,Offset dirOffset,Direction Dir,Direction primDir,int ptypeMask,Direction dirByBlack
00196 )
00197 {
00198 const Player altP=PlayerTraits<P>::opponent;
00199 Position pos=target-dirOffset;
00200 if(!pos.isOnBoard()){
00201 pieceMobility[dirByBlack]=pos.uintValue();
00202 return;
00203 }
00204 Piece p=state.getPieceAt(pos);
00205 if(p.canMoveOn<P>()){
00206
00207 const PieceMask pieceMask=state.getOnBoardMask(P)&state.getEffect(pos)¬PieceMask & ~state.getEffect(target);
00208 if(pieceMask.any())
00209 detail:: template generateMoveToPtypeMaskWithPieceMask<P,Action>(state,pos,p,action,
00210 ptypeMask,pieceMask);
00211 }
00212 Position nextPosition=pos;
00213 if(p.isEmpty()){
00214 spaces|=(1u<<Dir);
00215 if(DirType==0 && ! state.isPawnMaskSet<P>(target.x()) &&
00216 state.hasPieceOnStand<PAWN>(P))
00217 action.dropMove(pos,PAWN,P);
00218 do{
00219 pos-=dirOffset;
00220 p=state.getPieceAt(pos);
00221 } while(p.isEmpty());
00222 }
00223 if(p.isOnBoardByOwner<P>() && state.hasEffectByPiece(p,target)){
00224 for(;;){
00225 Piece p1=state.longEffectOfDirection(P,p,inverse(Dir));
00226 if(!p1.isOnBoardByOwner<P>()){
00227 break;
00228 }
00229 p=p1;
00230 }
00231 pos=p.position()-dirOffset;
00232 while((p=state.getPieceAt(pos)).isEmpty())
00233 pos-=dirOffset;
00234 }
00235 else if (p.isOnBoardByOwner<altP>() && state.hasEffectByPiece(p,target)){
00236
00237 Piece p1=state.longEffectOfDirection(altP,p,Dir);
00238 if(p1.isOnBoardByOwner<P>()){
00239 if(pos!=nextPosition){
00240 Position from=p1.position();
00241 PieceOnBoard<Action>::template generatePiece<P>(state,p1,pos,p,action);
00242 }
00243 pos=p1.position();
00244 p=p1;
00245 }
00246 else{
00247 pos=p.position()-dirOffset;
00248 while((p=state.getPieceAt(pos)).isEmpty())
00249 pos-=dirOffset;
00250 }
00251 }
00252 pieceMobility[dirByBlack]=pos.uintValue();
00253 if(p.isOnBoardByOwner<P>()){
00254 Piece p1=state.longEffectOfDirection(P,p,inverse(Dir));
00255 if(p1.isOnBoardByOwner<P>()){
00256 Open<Action>::template generate<P>(state,p,action,target,primDir);
00257 }
00258 }
00259 else if(p.isOnBoardByOwner<altP>() && pos!=nextPosition){
00260 if(DirType==0){
00261 mask_t lance_mask=state.selectLong<LANCE>(pos,P);
00262 if(lance_mask.any()){
00263 assert(!lance_mask.hasMultipleBit());
00264 int num=lance_mask.bsf()+PtypeFuns<LANCE>::indexNum*32;
00265 if(!state.pinOrOpen(P).test(num)){
00266 Piece p2=state.getPieceOf(num);
00267 action.unknownMove(p2.position(),pos,p,LANCE,false,P);
00268 }
00269 }
00270 }
00271 if(DirType <= 1){
00272 mask_t rook_mask=state.effectBit<ROOK>(P,pos);
00273 while(rook_mask.any()){
00274 int num=rook_mask.takeOneBit()+PtypeFuns<ROOK>::indexNum*32;
00275 Piece p2=state.getPieceOf(num);
00276 if(p2.position()==target) continue;
00277 PieceOnBoard<Action>::template generatePiece<P>(state,p2,pos,p,action);
00278 }
00279 }
00280 if(DirType == 2){
00281 mask_t bishop_mask=state.effectBit<BISHOP>(P,pos);
00282
00283 while(bishop_mask.any()){
00284 int num=bishop_mask.takeOneBit()+PtypeFuns<BISHOP>::indexNum*32;
00285 Piece p2=state.getPieceOf(num);
00286 if(p2.position()==target) continue;
00287 PieceOnBoard<Action>::template generatePiece<P>(state,p2,pos,p,action);
00288 }
00289 }
00290 }
00291
00292
00293
00294 if(DirType == 0){
00295 if(state.hasPieceOnStand<LANCE>(P)){
00296 for(pos+=DirectionPlayerTraits<U,P>::offset();
00297 pos!=target;pos+=DirectionPlayerTraits<U,P>::offset()){
00298 if(state.getPieceAt(pos).isEmpty())
00299 action.dropMove(pos,LANCE,P);
00300 }
00301 }
00302 }
00303 }
00304
00305 template<osl::Player P,int DirType,class Action,Direction Dir>
00306 void generateDirNotKing(const NumEffectState& state,Position target,Action& action,CArray<unsigned char,8>& pieceMobility, int& spaces, PieceMask const& notPieceMask)
00307 {
00308 generateDirNotKing<P,DirType,Action>(state,target,action,pieceMobility,spaces,notPieceMask,
00309 DirectionPlayerTraits<Dir,P>::offset(),Dir,DirectionTraits<Dir>::primDir,DirectionTraits<Dir>::ptypeMask,DirectionPlayerTraits<Dir,P>::directionByBlack);
00310
00311 }
00312 template<osl::Player P,osl::Direction Dir,class Action,bool hasKnight>
00313 void generateKnightDir(const NumEffectState& state,Position target,Action& action)
00314 {
00315 Position pos=target-DirectionPlayerTraits<Dir,P>::offset();
00316 if(!pos.isOnBoard()) return;
00317 Piece p=state.getPieceAt(pos);
00318 if(!p.canMoveOn<P>()) return;
00319 mask_t mask=state.effectBit<KNIGHT>(P, pos);
00320 mask &= ~state.promotedPieces().getMask<KNIGHT>();
00321
00322 mask &= ~state.pinOrOpen(P).getMask(PtypeFuns<KNIGHT>::indexNum);
00323 while(mask.any()){
00324 const int num = mask.takeOneBit()+PtypeFuns<KNIGHT>::indexNum*32;
00325 Piece p1=state.getPieceOf(num);
00326 action.unknownMove(p1.position(),pos,p,KNIGHT,false,P);
00327 }
00328 if(hasKnight && p.isEmpty()){
00329 action.dropMove(pos,KNIGHT,P);
00330 }
00331 }
00332 template<osl::Player P,class Action>
00333 void generateKnightAll(const NumEffectState& state,Position target,Action& action)
00334 {
00335 if(state.hasPieceOnStand<KNIGHT>(P)){
00336 detail::generateKnightDir<P,UUL,Action,true>(state,target,action);
00337 detail::generateKnightDir<P,UUR,Action,true>(state,target,action);
00338 }
00339 else{
00340 detail::generateKnightDir<P,UUL,Action,false>(state,target,action);
00341 detail::generateKnightDir<P,UUR,Action,false>(state,target,action);
00342 }
00343 }
00344 template <osl::Player P,class Action>
00345 void generateDrop(Position target,Action& action,int spaceMask,osl::Ptype T,int dirMask,Offset offset)
00346 {
00347 if((spaceMask&dirMask)!=0){
00348 Position pos=target-offset;
00349 action.dropMove(pos,T,P);
00350 }
00351 }
00352 template <osl::Player P,class Action,Direction Dir>
00353 void generateDropDir(Position target,Action& action,int spaceMask,osl::Ptype T)
00354 {
00355 generateDrop<P,Action>(target,action,spaceMask,T,(1<<Dir),DirectionPlayerTraits<Dir,P>::offset());
00356 }
00357 template<Player P,class Action,bool mustCareSilver>
00358 void generateOpenOrCapture(const NumEffectState& state,Position target,Piece p,int num,Action& action)
00359 {
00360
00361 Direction d=Board_Table.template getShort8<P>(p.position(),target);
00362 Position mid=state.getMobility((P==BLACK ? d : inverse(d)),num);
00363 assert(mid.isOnBoard());
00364 const Player altP=PlayerTraits<P>::opponent;
00365 Position mid1=state.kingMobilityOfPlayer(altP,d);
00366 if(mid==mid1){
00367 Piece p1=state.getPieceAt(mid);
00368 assert(p1.isPiece());
00369 Position target_next=target-Board_Table.getShort8OffsetUnsafe(p.position(),target);
00370 if((P==BLACK ? p1.pieceIsBlack() : !p1.pieceIsBlack())){
00371
00372 PieceOnBoard<Action>::template generate<P,true>(state,p1,action,(1<<primDir(d)));
00373
00374 if(state.hasEffectByPiece(p1,target_next)){
00375
00376 if(mustCareSilver && p1.ptype()==SILVER &&
00377 (P==BLACK ? target.y()>mid.y() : target.y()<mid.y())){
00378
00379 if(!state.pinOrOpen(P).test(p1.number())){
00380 action.unknownMove(mid,target_next,Piece::EMPTY(),SILVER,false,P);
00381 }
00382 }
00383 else
00384 PieceOnBoard<Action>::template generatePiece<P>(state,p1,target_next,Piece::EMPTY(),action);
00385 }
00386 }
00387 else{
00388
00389 if(mid==target_next)
00390 return;
00391 PieceOnBoard<Action>::template generatePiece<P>(state,p,mid,p1,action);
00392 }
00393 }
00394 }
00395
00396 template<osl::Player P,class Action>
00397 void generateRookLongMove(const NumEffectState& state,Position target,Action& action)
00398 {
00399 const Player altP=PlayerTraits<P>::opponent;
00400 for(int num=PtypeTraits<ROOK>::indexMin;num<PtypeTraits<ROOK>::indexLimit;num++){
00401
00402 if(state.pinOrOpen(altP).test(num)) continue;
00403 Piece p=state.getPieceOf(num);
00404 if(!p.isOnBoardByOwner<P>()) continue;
00405 if(target.isULRD(p.position())){
00406 generateOpenOrCapture<P,Action,false>(state,target,p,num,action);
00407 continue;
00408 }
00409 int target_x=target.x();
00410 int target_y=target.y();
00411 int rook_x=p.position().x();
00412 int rook_y=p.position().y();
00413 if(p.isPromoted()){
00414 if((unsigned int)(target_x-rook_x+1)>2u){
00415 if((unsigned int)(target_y-rook_y+1)>2u){
00416 {
00417 Position pos(rook_x,target_y);
00418 Piece p1=state.getPieceAt(pos);
00419 if(state.getEffect(pos).test(num) &&
00420 p1.canMoveOn<P>() &&
00421 state.kingMobilityAbs(altP,R).uintValue() >= pos.uintValue() &&
00422 pos.uintValue() >= state.kingMobilityAbs(altP,L).uintValue() &&
00423 (!state.pinOrOpen(P).test(num) ||
00424 p.position().isUD(state.getKingPosition<P>()))
00425 ){
00426 action.unknownMove(p.position(),pos,p1,PROOK,false,P);
00427 }
00428 }
00429 {
00430 Position pos(target_x,rook_y);
00431 Piece p1=state.getPieceAt(pos);
00432 if(state.getEffect(pos).test(num) &&
00433 p1.canMoveOn<P>() &&
00434 state.kingMobilityAbs(altP,U).uintValue() >= pos.uintValue() &&
00435 pos.uintValue() >= state.kingMobilityAbs(altP,D).uintValue() &&
00436 (!state.pinOrOpen(P).test(num) ||
00437 p.position().isLR(state.getKingPosition<P>()))
00438 ){
00439 action.unknownMove(p.position(),pos,p1,PROOK,false,P);
00440 }
00441 }
00442 }
00443 else{
00444 int min_x=state.kingMobilityAbs(altP,L).x();
00445 int max_x=state.kingMobilityAbs(altP,R).x();
00446 if(target_x>rook_x) max_x=target_x-2;
00447 else min_x=target_x+2;
00448 min_x=std::max(min_x,rook_x-1);
00449 max_x=std::min(max_x,rook_x+1);
00450 for(int x=min_x;x<=max_x;x++){
00451 Position pos=Position::makeNoCheck(x,target_y);
00452 Piece p1=state.getPieceAt(pos);
00453 if(p1.canMoveOn<P>())
00454 PieceOnBoard<Action>::template generatePiecePtype<P,PROOK>(state,p,pos,p1,action);
00455 }
00456 }
00457 }
00458 else if((unsigned int)(target_y-rook_y+1)>2u){
00459 int min_y=state.kingMobilityAbs(altP,D).y();
00460 int max_y=state.kingMobilityAbs(altP,U).y();
00461 if(target_y>rook_y) max_y=target_y-2;
00462 else min_y=target_y+2;
00463 min_y=std::max(min_y,rook_y-1);
00464 max_y=std::min(max_y,rook_y+1);
00465 for(int y=min_y;y<=max_y;y++){
00466 Position pos=Position::makeNoCheck(target_x,y);
00467 Piece p1=state.getPieceAt(pos);
00468 if(p1.canMoveOn<P>())
00469 PieceOnBoard<Action>::template generatePiecePtype<P,PROOK>(state,p,pos,p1,action);
00470 }
00471 }
00472 }
00473 else{
00474
00475 if((unsigned int)(target_x-rook_x+1)>2u){
00476 Position pos(rook_x,target_y);
00477 Piece p1=state.getPieceAt(pos);
00478 if(state.getEffect(pos).test(num) &&
00479 p1.canMoveOn<P>() &&
00480 state.kingMobilityAbs(altP,R).uintValue() >= pos.uintValue() &&
00481 pos.uintValue() >= state.kingMobilityAbs(altP,L).uintValue() &&
00482 (!state.pinOrOpen(P).test(num) ||
00483 p.position().isUD(state.getKingPosition<P>()))
00484 ){
00485 if(Position::canPromoteY<P>(rook_y) || Position::canPromoteY<P>(target_y)){
00486 action.unknownMove(p.position(),pos,p1,PROOK,true,P);
00487 }
00488 else action.unknownMove(p.position(),pos,p1,ROOK,false,P);
00489 }
00490 }
00491
00492 if((unsigned int)(target_y-rook_y+1)>2u){
00493 Position pos(target_x,rook_y);
00494 Piece p1=state.getPieceAt(pos);
00495 if(state.getEffect(pos).test(num) &&
00496 p1.canMoveOn<P>() &&
00497 state.kingMobilityAbs(altP,U).uintValue() >= pos.uintValue() &&
00498 pos.uintValue() >= state.kingMobilityAbs(altP,D).uintValue() &&
00499 (!state.pinOrOpen(P).test(num) ||
00500 p.position().isLR(state.getKingPosition<P>()))
00501 ){
00502 if(Position::canPromoteY<P>(rook_y)){
00503 action.unknownMove(p.position(),pos,p1,PROOK,true,P);
00504 }
00505 else
00506 action.unknownMove(p.position(),pos,p1,ROOK,false,P);
00507 }
00508 }
00509 }
00510 }
00511 }
00512 template<osl::Player P,class Action>
00513 void generateRookLongMoveNotKing(const NumEffectState& state,Position target,Action& action,CArray<unsigned char,8> const& pieceMobility)
00514 {
00515 for(int num=PtypeTraits<ROOK>::indexMin;num<PtypeTraits<ROOK>::indexLimit;num++){
00516 Piece p=state.getPieceOf(num);
00517 if(!p.isOnBoardByOwner<P>()) continue;
00518 if(target.isULRD(p.position())){
00519 continue;
00520 }
00521 int target_x=target.x();
00522 int target_y=target.y();
00523 int rook_x=p.position().x();
00524 int rook_y=p.position().y();
00525 if(p.isPromoted()){
00526 if((unsigned int)(target_x-rook_x+1)>2u){
00527 if((unsigned int)(target_y-rook_y+1)>2u){
00528 {
00529 Position pos(rook_x,target_y);
00530 Piece p1=state.getPieceAt(pos);
00531 if(p1.canMoveOn<P>() &&
00532 pieceMobility[R] > pos.uintValue() &&
00533 pos.uintValue() > pieceMobility[L] &&
00534 state.getEffect(pos).test(num)
00535 ){
00536 action.unknownMove(p.position(),pos,p1,PROOK,false,P);
00537 }
00538 }
00539 {
00540 Position pos(target_x,rook_y);
00541 Piece p1=state.getPieceAt(pos);
00542 if(p1.canMoveOn<P>() &&
00543 pieceMobility[U] > pos.uintValue() &&
00544 pos.uintValue() > pieceMobility[D] &&
00545 state.getEffect(pos).test(num)){
00546 action.unknownMove(p.position(),pos,p1,PROOK,false,P);
00547 }
00548 }
00549 }
00550 else{
00551 int min_x=Position::makeDirect(pieceMobility[L]).x()+1;
00552 int max_x=Position::makeDirect(pieceMobility[R]).x()-1;
00553 if(target_x>rook_x) max_x=target_x-2;
00554 else min_x=target_x+2;
00555 min_x=std::max(min_x,rook_x-1);
00556 max_x=std::min(max_x,rook_x+1);
00557 for(int x=min_x;x<=max_x;x++){
00558 Position pos=Position::makeNoCheck(x,target_y);
00559 Piece p1=state.getPieceAt(pos);
00560 if(p1.canMoveOn<P>())
00561 action.unknownMove(p.position(),pos,p1,PROOK,false,P);
00562 }
00563 }
00564 }
00565 else if((unsigned int)(target_y-rook_y+1)>2u){
00566 int min_y=Position::makeDirect(pieceMobility[D]).y()+1;
00567 int max_y=Position::makeDirect(pieceMobility[U]).y()-1;
00568 if(target_y>rook_y) max_y=target_y-2;
00569 else min_y=target_y+2;
00570 min_y=std::max(min_y,rook_y-1);
00571 max_y=std::min(max_y,rook_y+1);
00572 for(int y=min_y;y<=max_y;y++){
00573 Position pos=Position::makeNoCheck(target_x,y);
00574 Piece p1=state.getPieceAt(pos);
00575 if(p1.canMoveOn<P>())
00576 action.unknownMove(p.position(),pos,p1,PROOK,false,P);
00577 }
00578 }
00579 }
00580 else{
00581
00582 if((unsigned int)(target_x-rook_x+1)>2u){
00583 Position pos(rook_x,target_y);
00584 Piece p1=state.getPieceAt(pos);
00585 if(p1.canMoveOn<P>() &&
00586 pieceMobility[R] > pos.uintValue() &&
00587 pos.uintValue() > pieceMobility[L] &&
00588 state.getEffect(pos).test(num)
00589 ){
00590 if(Position::canPromoteY<P>(rook_y) || Position::canPromoteY<P>(target_y)){
00591 action.unknownMove(p.position(),pos,p1,PROOK,true,P);
00592 }
00593 else
00594 action.unknownMove(p.position(),pos,p1,ROOK,false,P);
00595 }
00596 }
00597
00598 if((unsigned int)(target_y-rook_y+1)>2u){
00599 Position pos(target_x,rook_y);
00600 Piece p1=state.getPieceAt(pos);
00601 if(p1.template canMoveOn<P>() &&
00602 pieceMobility[U] > pos.uintValue() &&
00603 pos.uintValue() > pieceMobility[D] &&
00604 state.getEffect(pos).test(num)
00605 ){
00606 if(Position::canPromoteY<P>(rook_y)){
00607 action.unknownMove(p.position(),pos,p1,PROOK,true,P);
00608 }
00609 else
00610 action.unknownMove(p.position(),pos,p1,ROOK,false,P);
00611 }
00612 }
00613 }
00614 }
00615 }
00616 template<Player P,Ptype T,class Action>
00617 void generateBishopLongMove(const NumEffectState& state,Position target,Action& action,Piece p,int num)
00618 {
00619 const Player altP=PlayerTraits<P>::opponent;
00620 int target_x=target.x();
00621 int target_y=target.y();
00622 int target_xPy=target_x+target_y;
00623 int target_xMy=target_x-target_y;
00624 int bishop_x=p.position().x();
00625 int bishop_y=p.position().y();
00626 int bishop_xPy=bishop_x+bishop_y;
00627 int bishop_xMy=bishop_x-bishop_y;
00628 if(((target_xPy^bishop_xPy)&1)!=0){
00629 if(T==BISHOP) return;
00630
00631 if((unsigned int)(target_xPy-bishop_xPy+1)<=2u){
00632 Position ul=state.kingMobilityAbs(altP,UL);
00633 Position dr=state.kingMobilityAbs(altP,DR);
00634 int min_xMy=ul.x()-ul.y();
00635 int max_xMy=dr.x()-dr.y();
00636 if(target_xMy>bishop_xMy) max_xMy=target_xMy-4;
00637 else min_xMy=target_xMy+4;
00638 min_xMy=std::max(min_xMy,bishop_xMy-1);
00639 max_xMy=std::min(max_xMy,bishop_xMy+1);
00640 for(int xMy=min_xMy;xMy<=max_xMy;xMy+=2){
00641 int pos_x=(target_xPy+xMy)>>1;
00642 int pos_y=(target_xPy-xMy)>>1;
00643 Position pos=Position::makeNoCheck(pos_x,pos_y);
00644 Piece p1=state.getPieceAt(pos);
00645 if(p1.canMoveOn<P>())
00646 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00647 }
00648 }
00649 else if((unsigned int)(target_xMy-bishop_xMy+1)<=2u){
00650 Position dl=state.kingMobilityAbs(altP,DL);
00651 Position ur=state.kingMobilityAbs(altP,UR);
00652 int min_xPy=dl.x()+dl.y();
00653 int max_xPy=ur.x()+ur.y();
00654 if(target_xPy>bishop_xPy) max_xPy=target_xPy-4;
00655 else min_xPy=target_xPy+4;
00656 min_xPy=std::max(min_xPy,bishop_xPy-1);
00657 max_xPy=std::min(max_xPy,bishop_xPy+1);
00658 for(int xPy=min_xPy;xPy<=max_xPy;xPy+=2){
00659 int pos_x=(xPy+target_xMy)>>1;
00660 int pos_y=(xPy-target_xMy)>>1;
00661 Position pos=Position::makeNoCheck(pos_x,pos_y);
00662 Piece p1=state.getPieceAt(pos);
00663 if(p1.canMoveOn<P>())
00664 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00665 }
00666 }
00667 return;
00668 }
00669
00670 if((unsigned int)(target_xPy-bishop_xPy+2)>4u){
00671 int pos_x=(bishop_xPy+target_xMy)>>1;
00672 int pos_y=(bishop_xPy-target_xMy)>>1;
00673 Position pos=Position::makeNoCheck(pos_x,pos_y);
00674 if(pos.isOnBoard()){
00675 Piece p1=state.getPieceAt(pos);
00676 if(state.getEffect(pos).test(num) &&
00677 p1.canMoveOn<P>() &&
00678 state.kingMobilityAbs(altP,UR).uintValue() >= pos.uintValue() &&
00679 pos.uintValue() >= state.kingMobilityAbs(altP,DL).uintValue()
00680 ){
00681 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00682 }
00683 }
00684 }
00685 else if(target_xPy==bishop_xPy){
00686 generateOpenOrCapture<P,Action,true>(state,target,p,num,action);
00687 return;
00688 }
00689
00690 if((unsigned int)(target_xMy-bishop_xMy+2)>4u){
00691 int pos_x=(target_xPy+bishop_xMy)>>1;
00692 int pos_y=(target_xPy-bishop_xMy)>>1;
00693 Position pos=Position::makeNoCheck(pos_x,pos_y);
00694 if(pos.isOnBoard()){
00695 Piece p1=state.getPieceAt(pos);
00696 if(state.getEffect(pos).test(num) &&
00697 p1.canMoveOn<P>() &&
00698 state.kingMobilityAbs(altP,DR).uintValue() >= pos.uintValue() &&
00699 pos.uintValue() >= state.kingMobilityAbs(altP,UL).uintValue()
00700 ){
00701 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00702 }
00703 }
00704 }
00705 else if(target_xMy==bishop_xMy){
00706 generateOpenOrCapture<P,Action,true>(state,target,p,num,action);
00707 return;
00708 }
00709
00710 }
00711 template<osl::Player P,Ptype T,class Action>
00712 void generateBishopLongMoveNotKing(const NumEffectState& state,Position target,Action& action,CArray<unsigned char,8> const& pieceMobility,Piece p,int num)
00713 {
00714 int target_x=target.x();
00715 int target_y=target.y();
00716 int target_xPy=target_x+target_y;
00717 int target_xMy=target_x-target_y;
00718 int bishop_x=p.position().x();
00719 int bishop_y=p.position().y();
00720 int bishop_xPy=bishop_x+bishop_y;
00721 int bishop_xMy=bishop_x-bishop_y;
00722 if(((target_xPy^bishop_xPy)&1)!=0){
00723 if(T!=PBISHOP) return;
00724
00725 if((unsigned int)(target_xPy-bishop_xPy+1)<=2u){
00726 Position ul=Position::makeDirect(pieceMobility[UL]);
00727 Position dr=Position::makeDirect(pieceMobility[DR]);
00728 int min_xMy=ul.x()-ul.y()+2;
00729 int max_xMy=dr.x()-dr.y()-2;
00730 if(target_xMy>bishop_xMy) max_xMy=target_xMy-4;
00731 else min_xMy=target_xMy+4;
00732 min_xMy=std::max(min_xMy,bishop_xMy-1);
00733 max_xMy=std::min(max_xMy,bishop_xMy+1);
00734 for(int xMy=min_xMy;xMy<=max_xMy;xMy+=2){
00735 int pos_x=(target_xPy+xMy)>>1;
00736 int pos_y=(target_xPy-xMy)>>1;
00737 Position pos=Position::makeNoCheck(pos_x,pos_y);
00738 Piece p1=state.getPieceAt(pos);
00739 if(p1.canMoveOn<P>())
00740 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00741 }
00742 return;
00743 }
00744 else if((unsigned int)(target_xMy-bishop_xMy+1)<=2u){
00745 Position dl=Position::makeDirect(pieceMobility[DL]);
00746 Position ur=Position::makeDirect(pieceMobility[UR]);
00747 int min_xPy=dl.x()+dl.y()+2;
00748 int max_xPy=ur.x()+ur.y()-2;
00749 if(target_xPy>bishop_xPy) max_xPy=target_xPy-4;
00750 else min_xPy=target_xPy+4;
00751 min_xPy=std::max(min_xPy,bishop_xPy-1);
00752 max_xPy=std::min(max_xPy,bishop_xPy+1);
00753 for(int xPy=min_xPy;xPy<=max_xPy;xPy+=2){
00754 int pos_x=(xPy+target_xMy)>>1;
00755 int pos_y=(xPy-target_xMy)>>1;
00756 Position pos=Position::makeNoCheck(pos_x,pos_y);
00757 Piece p1=state.getPieceAt(pos);
00758 if(p1.canMoveOn<P>())
00759 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00760 }
00761 }
00762 return;
00763 }
00764
00765 if((unsigned int)(target_xPy-bishop_xPy+2)>4u){
00766 int pos_x=(bishop_xPy+target_xMy)>>1;
00767 int pos_y=(bishop_xPy-target_xMy)>>1;
00768 Position pos=Position::makeNoCheck(pos_x,pos_y);
00769 if(pos.isOnBoard()){
00770 if(pieceMobility[UR] > pos.uintValue() &&
00771 pos.uintValue() > pieceMobility[DL] &&
00772 state.getEffect(pos).test(num)){
00773 Piece p1=state.getPieceAt(pos);
00774 if(p1.canMoveOn<P>())
00775 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00776 }
00777 }
00778 }
00779
00780 if((unsigned int)(target_xMy-bishop_xMy+2)>4u){
00781 int pos_x=(target_xPy+bishop_xMy)>>1;
00782 int pos_y=(target_xPy-bishop_xMy)>>1;
00783 Position pos=Position::makeNoCheck(pos_x,pos_y);
00784 if(pos.isOnBoard()){
00785 if(pieceMobility[DR] > pos.uintValue() &&
00786 pos.uintValue() > pieceMobility[UL] &&
00787 state.getEffect(pos).test(num)
00788 ){
00789 Piece p1=state.getPieceAt(pos);
00790 if(p1.canMoveOn<P>())
00791 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
00792 }
00793 }
00794 }
00795 }
00796
00797 template<Player P,class Action>
00798 void generateDropGold(const NumEffectState& state,Position target,Action& action,int spaces)
00799 {
00800 if(!state.hasPieceOnStand<GOLD>(P)) return;
00801 unsigned int gold_mask=spaces&((1<<U)|(1<<UR)|(1<<UL)|(1<<L)|(1<<R)|(1<<D));
00802 if(gold_mask==0) return;
00803 generateDropDir<P,Action,U>(target,action,gold_mask,GOLD);
00804 generateDropDir<P,Action,UL>(target,action,gold_mask,GOLD);
00805 generateDropDir<P,Action,UR>(target,action,gold_mask,GOLD);
00806 generateDropDir<P,Action,L>(target,action,gold_mask,GOLD);
00807 generateDropDir<P,Action,R>(target,action,gold_mask,GOLD);
00808 generateDropDir<P,Action,D>(target,action,gold_mask,GOLD);
00809 }
00810 template<Player P,class Action>
00811 void generateDropSilver(const NumEffectState& state,Position target,Action& action,int spaces)
00812 {
00813 if(!state.hasPieceOnStand<SILVER>(P)) return;
00814 unsigned int silver_mask=spaces&((1<<U)|(1<<UR)|(1<<UL)|(1<<DL)|(1<<DR));
00815 if(silver_mask ==0) return;
00816
00817 generateDropDir<P,Action,DL>(target,action,silver_mask,SILVER);
00818 generateDropDir<P,Action,DR>(target,action,silver_mask,SILVER);
00819 generateDropDir<P,Action,U>(target,action,silver_mask,SILVER);
00820 generateDropDir<P,Action,UL>(target,action,silver_mask,SILVER);
00821 generateDropDir<P,Action,UR>(target,action,silver_mask,SILVER);
00822 }
00826 template<Player P,class Action,bool allEmpty>
00827 void generateDropBishop(const NumEffectState& state,Position target,Action& action,Position ul,Position dr,Position ur,Position dl)
00828 {
00829 for(Position pos=dl+DirectionPlayerTraits<DL,P>::offset();
00830 pos!=target;pos+=DirectionPlayerTraits<DL,P>::offset())
00831 if(allEmpty || state.getPieceAt(pos).isEmpty())
00832 action.dropMove(pos,BISHOP,P);
00833 for(Position pos=dr-DirectionPlayerTraits<UL,P>::offset();
00834 pos!=target;pos-=DirectionPlayerTraits<UL,P>::offset())
00835 if(allEmpty || state.getPieceAt(pos).isEmpty())
00836 action.dropMove(pos,BISHOP,P);
00837 for(Position pos=ul+DirectionPlayerTraits<UL,P>::offset();
00838 pos!=target;pos+=DirectionPlayerTraits<UL,P>::offset())
00839 if(allEmpty || state.getPieceAt(pos).isEmpty())
00840 action.dropMove(pos,BISHOP,P);
00841 for(Position pos=ur-DirectionPlayerTraits<DL,P>::offset();
00842 pos!=target;pos-=DirectionPlayerTraits<DL,P>::offset())
00843 if(allEmpty || state.getPieceAt(pos).isEmpty())
00844 action.dropMove(pos,BISHOP,P);
00845 }
00846
00847 template<Player P,class Action,bool allEmpty>
00848 void generateDropRook(const NumEffectState& state,Position target,Action& action,Position l,Position r,Position d,Position u)
00849 {
00850 for(Position pos=u-DirectionPlayerTraits<D,P>::offset();
00851 pos!=target;pos-=DirectionPlayerTraits<D,P>::offset())
00852 if(allEmpty || state.getPieceAt(pos).isEmpty())
00853 action.dropMove(pos,ROOK,P);
00854 for(Position pos=l+DirectionPlayerTraits<L,P>::offset();
00855 pos!=target;pos+=DirectionPlayerTraits<L,P>::offset())
00856 if(allEmpty || state.getPieceAt(pos).isEmpty())
00857 action.dropMove(pos,ROOK,P);
00858 for(Position pos=r-DirectionPlayerTraits<L,P>::offset();
00859 pos!=target;pos-=DirectionPlayerTraits<L,P>::offset())
00860 if(allEmpty || state.getPieceAt(pos).isEmpty())
00861 action.dropMove(pos,ROOK,P);
00862 for(Position pos=d+DirectionPlayerTraits<D,P>::offset();
00863 pos!=target;pos+=DirectionPlayerTraits<D,P>::offset())
00864 if(allEmpty || state.getPieceAt(pos).isEmpty())
00865 action.dropMove(pos,ROOK,P);
00866 }
00867 template<osl::Player P,class Action>
00868 void generateKing(const NumEffectState& state,Position target,Action& action,bool &hasPawnCheckmate)
00869 {
00870
00871 const Player altP=PlayerTraits<P>::opponent;
00872 assert(target==state.getKingPosition(altP));
00873 generateDir<P,0,Action,U>(state,target,action,hasPawnCheckmate);
00874 generateKnightAll<P,Action>(state,target,action);
00875 generateDir<P,2,Action,UL>(state,target,action,hasPawnCheckmate);
00876 generateDir<P,2,Action,UR>(state,target,action,hasPawnCheckmate);
00877 generateDir<P,1,Action,L>(state,target,action,hasPawnCheckmate);
00878 generateDir<P,1,Action,R>(state,target,action,hasPawnCheckmate);
00879 generateDir<P,1,Action,D>(state,target,action,hasPawnCheckmate);
00880 generateDir<P,2,Action,DL>(state,target,action,hasPawnCheckmate);
00881 generateDir<P,2,Action,DR>(state,target,action,hasPawnCheckmate);
00882 detail::generateRookLongMove<P,Action>(state,target,action);
00883 for(int num=PtypeTraits<BISHOP>::indexMin;num<PtypeTraits<BISHOP>::indexLimit;num++){
00884
00885 if(state.pinOrOpen(altP).test(num)) continue;
00886 Piece p=state.getPieceOf(num);
00887 if(!p.isOnBoardByOwner<P>()) continue;
00888 if(p.isPromoted())
00889 generateBishopLongMove<P,PBISHOP,Action>(state,target,action,p,num);
00890 else
00891 generateBishopLongMove<P,BISHOP,Action>(state,target,action,p,num);
00892 }
00893 int spaces=King8Info(state.Iking8Info(altP)).spaces();
00894 generateDropGold<P,Action>(state,target,action,spaces);
00895 generateDropSilver<P,Action>(state,target,action,spaces);
00896
00897 if(state.hasPieceOnStand<BISHOP>(P)){
00898 generateDropBishop<P,Action,true>(state,target,action,
00899 state.kingMobilityOfPlayer(altP,UL),
00900 state.kingMobilityOfPlayer(altP,DR),
00901 state.kingMobilityOfPlayer(altP,UR),
00902 state.kingMobilityOfPlayer(altP,DL));
00903 }
00904 if(state.hasPieceOnStand<ROOK>(P)){
00905 Position l,r,d,u;
00906 l=state.kingMobilityOfPlayer(altP,L);
00907 r=state.kingMobilityOfPlayer(altP,R);
00908 d=state.kingMobilityOfPlayer(altP,D);
00909 u=state.kingMobilityOfPlayer(altP,U);
00910 generateDropRook<P,Action,true>(state,target,action,l,r,d,u);
00911 }
00912 }
00913 template<osl::Player P,class Action>
00914 void generateNotKing(const NumEffectState& state,Position target,Action& action)
00915 {
00916 int spaces=0;
00917 CArray<unsigned char,8> pieceMobility;
00918 PieceMask notPieceMask;
00919 notPieceMask.setAll();
00920 int num=state.getPieceAt(target).number();
00921 if(num != EMPTY_NUM){
00922 notPieceMask.reset(num);
00923 }
00924 generateDirNotKing<P,0,Action,U>(state,target,action,pieceMobility,spaces,notPieceMask);
00925 generateKnightAll<P,Action>(state,target,action);
00926 generateDirNotKing<P,2,Action,UL>(state,target,action,pieceMobility,spaces,notPieceMask);
00927 generateDirNotKing<P,2,Action,UR>(state,target,action,pieceMobility,spaces,notPieceMask);
00928 generateDirNotKing<P,1,Action,L>(state,target,action,pieceMobility,spaces,notPieceMask);
00929 generateDirNotKing<P,1,Action,R>(state,target,action,pieceMobility,spaces,notPieceMask);
00930 generateDirNotKing<P,1,Action,D>(state,target,action,pieceMobility,spaces,notPieceMask);
00931 generateDirNotKing<P,2,Action,DL>(state,target,action,pieceMobility,spaces,notPieceMask);
00932 generateDirNotKing<P,2,Action,DR>(state,target,action,pieceMobility,spaces,notPieceMask);
00933
00934 generateRookLongMoveNotKing<P,Action>(state,target,action,pieceMobility);
00935
00936 for(int num=PtypeTraits<BISHOP>::indexMin;num<PtypeTraits<BISHOP>::indexLimit;num++){
00937 Piece p=state.getPieceOf(num);
00938 if(!p.isOnBoardByOwner<P>()) continue;
00939 if(p.isPromoted())
00940 generateBishopLongMoveNotKing<P,PBISHOP,Action>(state,target,action,pieceMobility,p,num);
00941 else
00942 generateBishopLongMoveNotKing<P,BISHOP,Action>(state,target,action,pieceMobility,p,num);
00943 }
00944 generateDropGold<P,Action>(state,target,action,spaces);
00945 generateDropSilver<P,Action>(state,target,action,spaces);
00946 if(state.hasPieceOnStand<BISHOP>(P)){
00947 Position ul,dr,dl,ur;
00948 ul=Position::makeDirect(pieceMobility[P==BLACK ? UL : DR]);
00949 dr=Position::makeDirect(pieceMobility[P==BLACK ? DR : UL]);
00950 ur=Position::makeDirect(pieceMobility[P==BLACK ? UR : DL]);
00951 dl=Position::makeDirect(pieceMobility[P==BLACK ? DL : UR]);
00952 generateDropBishop<P,Action,false>(state,target,action,ul,dr,ur,dl);
00953 }
00954 if(state.hasPieceOnStand<ROOK>(P)){
00955 Position l,r,d,u;
00956 l=Position::makeDirect(pieceMobility[P==BLACK ? L : R]);
00957 r=Position::makeDirect(pieceMobility[P==BLACK ? R : L]);
00958 d=Position::makeDirect(pieceMobility[P==BLACK ? D : U]);
00959 u=Position::makeDirect(pieceMobility[P==BLACK ? U : D]);
00960 generateDropRook<P,Action,false>(state,target,action,l,r,d,u);
00961 }
00962 }
00963 }
00964 template <class Action>
00965 template <osl::Player P,bool isAttackToKing>
00966 void osl::move_generator::AddEffectWithEffect<Action>::
00967 generate(const NumEffectState& state,Position target,Action& action,bool &hasPawnCheckmate)
00968 {
00969 if(!isAttackToKing){
00970 detail::template generateNotKing<P,Action>(state,target,action);
00971 }
00972 else{
00973 detail::template generateKing<P,Action>(state,target,action,hasPawnCheckmate);
00974 }
00975 }
00976 template<bool isAttackToKing>
00977 void osl::move_generator::GenerateAddEffectWithEffect::
00978 generate(Player player, const NumEffectState& state, Position target,
00979 move_action::Store& store)
00980 {
00981 using namespace osl::move_action;
00982 bool dummy;
00983 if(player==BLACK){
00984 AddEffectWithEffect<Store>::generate<BLACK,isAttackToKing>(state,target,store,dummy);
00985 }
00986 else{
00987 AddEffectWithEffect<Store>::generate<WHITE,isAttackToKing>(state,target,store,dummy);
00988 }
00989 }
00990
00991 }
00992 }
00993 #endif
00994
00995
00996
00997