addEffect8.tcc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
addEffect8.tcc
Go to the documentation of this file.
1 #ifndef _MOVE_GENERATOR_ADD_EFFECT8_TCC
2 #define _MOVE_GENERATOR_ADD_EFFECT8_TCC
3 #include "osl/move_generator/addEffect8.h"
4 #include "osl/move_generator/pieceOnBoard.h"
5 #include "osl/move_generator/addEffect8Table.h"
6 #include "osl/misc/loki.h"
7
8 #include <boost/static_assert.hpp>
9
10
11 namespace osl
12 {
13 namespace move_generator
14 {
15 namespace addeffect8{
26 template <Player P,Ptype T,class Action>
27 void generateShortDrop(NumEffectState const& state,Square target,Action& action)
28 {
29 Square targetForP=target.squareForBlack(P);
30 for(int i=0;;i++){
31 Square pos=Add_Effect8_Table.getDropSquare(T,targetForP,i);
32 if(pos.isPieceStand()) break;
33 pos=pos.squareForBlack<P>();
34 if(state.pieceAt(pos).isEmpty() &&
35 (T!=PAWN || !state.isPawnMaskSet<P>(pos.x()))){
36 if((T==BISHOP || T==ROOK) &&
37 state.hasEffectByNotPinnedAndKing(alt(P),pos)) continue;
38 action.dropMove(pos,T,P);
39 }
40 }
41 }
42
53 template <Player P,Ptype T,class Action>
54 void generateLongDropWithOffset(NumEffectState const& state,Square to,Square from, Offset offset,int countMax,Action& action){
55 const Player altP=PlayerTraits<P>::opponent;
56 int count=0;
57 for(;;){
58 Piece p;
59 for(;(p=state.pieceAt(from)).isEmpty();from+=offset){
60 if(T==LANCE)
61 action.dropMove(from,T,P);
62 else if(!state.hasEffectAt<altP>(from)){
63 action.dropMove(from,T,P);
64 if(++count>=countMax) return;
65 }
66 }
67 if(!p.isOnBoardByOwner<P>()) return;
68 if(!Ptype_Table.getEffect(p.ptypeO(),from,to).hasEffect()) return;
69 from+=offset;
70 }
71 }
72
82 template <Player P,Ptype T,class Action>
83 void generateLongDrop(NumEffectState const& state,Square target,Action& action)
84 {
85 BOOST_STATIC_ASSERT(T==ROOK || T==BISHOP || T==LANCE);
86 // 8近傍以内へのdropはshort扱いで作る．
87 generateShortDrop<P,T,Action>(state,target,action);
88 Square targetForP=target.squareForBlack(P);
89 // 8近傍に駒がある時(王手にならない)に直接方向の利き
90 for(int i=0;;i++){
91 Offset offset=Add_Effect8_Table.getLongDropDirect(T,targetForP,i);
92 if(offset.zero()) break;
93 offset=offset.blackOffset<P>();
94 Square pos=target+offset;
95 assert(pos.isOnBoard());
96 Square from=pos+offset;
97 if(state.pieceAt(pos).isEmpty()){
98 Piece p=state.pieceAt(from);
99 // 一つ置いて短い利きの時のみOK
100 if(!p.isOnBoardByOwner<P>() ||
101 !state.hasEffectByPiece(p,pos)) continue;
102 from+=offset;
103 }
104 generateLongDropWithOffset<P,T,Action>(state,pos,from,offset,2,action);
105 }
106 for(int i=0;;i++){
107 PO po=Add_Effect8_Table.getLongDropSquare(T,targetForP,i);
108 if(po.first.isPieceStand()) break;
109 Square pos=po.first.squareForBlack<P>();
110 Offset offset=po.second.blackOffset<P>();
111 assert(!offset.zero());
112 generateLongDropWithOffset<P,T,Action>(state,pos-offset,pos,offset,2,action);
113 }
114 if(T==BISHOP){
115 for(int i=0;;i++){
116 POO poo=Add_Effect8_Table.getLongDrop2Square(T,targetForP,i);
117 if(poo.first.isPieceStand()) break;
118 Square pos=poo.first.squareForBlack<P>();
119 Offset offset1=poo.second.first.blackOffset<P>();
120 assert(!offset1.zero());
121 Offset offset2=poo.second.second.blackOffset<P>();
122 assert(!offset2.zero());
123 Piece p=state.pieceAt(pos);
124 if(p.isEmpty()){
125 generateLongDropWithOffset<P,T,Action>(state,pos-offset1,
126 pos,offset1,2,action);
127 generateLongDropWithOffset<P,T,Action>(state,pos-offset2,
128 pos+offset2,offset2,1,
129 action);
130 }
131 else if(p.isOnBoardByOwner<P>()){
132 if(state.hasEffectByPiece(p,pos-offset1)){
133 generateLongDropWithOffset<P,T,Action>(state,pos-offset1,
134 pos+offset1,offset1,
135 2,action);
136 }
137 if(state.hasEffectByPiece(p,pos-offset2)){
138 generateLongDropWithOffset<P,T,Action>(state,pos-offset2,
139 pos+offset2,offset2,
140 2,action);
141 }
142 }
143 }
144 }
145 }
146
155 template <Player P,Ptype T,class Action>
156 void generateShortMove(NumEffectState const& state,Piece attacker,
157 Square target, Action& action)
158 {
159 Square from=attacker.square();
160 Offset32 o32=Offset32(from,target).blackOffset32<P>();
161 for(int i=0;;i++){
162 Offset o=Add_Effect8_Table.getShortMoveOffset(false,T,o32,i);
163 if(o.zero()) break;
164 Square pos=target+o.blackOffset<P>();
165 if((T!=KNIGHT && pos.isEdge()) ||
166 (T==KNIGHT && !pos.isOnBoard())) continue;
167 if((T==PAWN ? pos.canPromote<P>() :
168 (PtypeTraits<T>::isBasic
169 && !PtypePlayerTraits<T,P>::canDropTo(pos))))
170 continue;
171 Piece p=state.pieceAt(pos);
172 if(p.isEmpty()){
173 if(!state.pinOrOpen(P).test(attacker.number()) ||
174 state.pinnedCanMoveTo<P>(attacker,pos))
175 action.simpleMove(from,pos,T,false,P);
176 }
177 }
178 }
179
186 template<Player P>
187 bool findBlocker(NumEffectState const& state,Piece attacker, Square target, Square from,Square& pos,Piece& blocker, Offset offset)
188 {
189 if(state.hasEffectByPiece(attacker,pos)){
190 blocker=state.pieceAt(pos);
191 if(!blocker.isEmpty()) return blocker.isOnBoardByOwner<P>();
192 pos-=offset;
193 if(abs(pos.x()-target.x())>1 || abs(pos.y()-target.y())>1)
194 return false;
195 blocker=state.pieceAt(pos);
196 return blocker.isOnBoardByOwner<P>();
197 }
198 else{
199 // TODO effectedNumTableを使える?
200 for(Square pos1=from+offset;pos1!=pos;pos1+=offset){
201 Piece p=state.pieceAt(pos1);
202 if(!p.isEmpty()){
203 if(!p.isOnBoardByOwner<P>()) return false;
204 if(!Ptype_Table.getEffect(p.ptypeO(),pos1,pos).hasEffect()){
205 blocker=p;
206 for(pos1+=offset;pos1!=pos;pos1+=offset){
207 p=state.pieceAt(pos1);
208 if(!p.isEmpty()){
209 if(!p.isOnBoardByOwner<P>() ||
210 !Ptype_Table.getEffect(p.ptypeO(),pos1,pos).hasEffect()) return false;
211 }
212 }
213 pos=blocker.square();
214 return true;
215 }
216 if(pos1==pos-offset &&
217 (pos+offset).isOnBoard() &&
218 !Ptype_Table.getEffect(p.ptypeO(),pos1,pos+offset).hasEffect()){
219 blocker=p;
220 pos=blocker.square();
221 return true;
222 }
223 return false;
224 }
225 }
226 return false;
227 }
228 }
241 template<Player P,Ptype T>
242 bool canAddLongEffect(NumEffectState const& state,Square from,Square to,Piece& blocker,Offset offset)
243 {
244 for(Square pos=to+offset;pos!=from;pos+=offset){
245 Piece p=state.pieceAt(pos);
246 if(!p.isEmpty()){
247 if(!p.isOnBoardByOwner<P>() ||
248 !Ptype_Table.getEffect(p.ptypeO(),pos,to).hasEffect()){
249 blocker=p;
250 assert(!blocker.isEdge());
251 return false;
252 }
253 }
254 }
255 return true;
256 }
268 template<Player P,Ptype T>
269 bool canAddLongEffect(NumEffectState const& state,Square from,Square to,Piece& blocker)
270 {
271 Offset offset=Board_Table.getShortOffset(Offset32(from,to));
272 return canAddLongEffect<P,T>(state,from,to,blocker,offset);
273 }
284 template <Player P,Ptype T,class Action>
285 void generateLongMove(NumEffectState const& state,Piece attacker,
286 Square target, Action& action)
287 {
288 Square from=attacker.square();
289 // 飛車，角はpromoteできる時はpromoteする手を生成済み
290 if((T==ROOK || T==BISHOP) && from.canPromote<P>())
291 return;
292 Offset32 o32=Offset32(from,target).blackOffset32<P>();
293 // 間の味方の駒のopen
294 OffsetPair op=Add_Effect8_Table.getBetweenOffset(T,o32);
295 if(!op.first.zero()){
296 Square pos=target+op.first.blackOffset<P>();
297 Offset offset=op.second.blackOffset<P>();
298 if(pos.isOnBoard()){
299 Piece blocker=Piece::EMPTY();
300 if(findBlocker<P>(state,attacker,target,from,pos,blocker,offset)){
301 Direction d=longToShort(Board_Table.getLongDirection<BLACK>(Offset32(pos,from).blackOffset32<P>()));
302 // std::cerr << "blocker=" << blocker << ",d=" << d << std::endl;
303 PieceOnBoard<Action,true>::template generate<P,true>(
304 state,blocker,action,1<<primDir(d));
305 }
306 }
307 }
308 if(T==LANCE) return;
309 // 移動後に短い利きで迫る
310 // promoteなし
311 for(int i=0;;i++){
312 Offset o=Add_Effect8_Table.getShortMoveOffset(false,T,o32,i);
313 if(o.zero()) break;
314 Square pos=target+o.blackOffset<P>();
315 if(!pos.isOnBoard()) continue;
316 if ((!canPromote(T) || !pos.canPromote<P>()) &&
317 state.hasEffectByPiece(attacker,pos) &&
318 state.pieceAt(pos).isEmpty()){
319 if(!state.pinOrOpen(P).test(attacker.number()) ||
320 state.pinnedCanMoveTo<P>(attacker,pos))
321 action.simpleMove(from,pos,T,false,P);
322 }
323 }
324 // 移動後に長い利きで迫る
325 for(int i=0;;i++){
326 OffsetPair op=Add_Effect8_Table.getLongMoveOffset(T,o32,i);
327 if(op.first.zero()) break;
328 Square pos1=target+op.first.blackOffset<P>();
329 Square pos2=target+op.second.blackOffset<P>();
330 Piece blocker=Piece::EMPTY();
331 if(pos1.isOnBoard() && pos2.isOnBoard() &&
332 state.pieceAt(pos1).isEmpty() &&
333 (!canPromote(T) || !pos1.canPromote<P>()) &&
334 state.hasEffectByPiece(attacker,pos1) &&
335 canAddLongEffect<P,T>(state,pos1,pos2,blocker)){
336 if(!state.pinOrOpen(P).test(attacker.number()) ||
337 state.pinnedCanMoveTo<P>(attacker,pos1))
338 action.simpleMove(from,pos1,T,false,P);
339 }
340 }
341 }
342
346 template <Player P,Ptype T,class Action>
347 class ShortPieceAction
348 {
349 NumEffectState const& state;
350 Square target;
351 Action& action;
352 public:
353 ShortPieceAction(NumEffectState const& s,Square p,Action& a)
354 :state(s),target(p),action(a)
355 {}
359 void operator()(Piece p)
360 {
361 if (p.isPromotedNotKingGold())
362 {
363 generateShortMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
364 }
365 else
366 {
367 generateShortMove<P,T,Action>(state,p,target,action);
368 }
369 }
370 };
371
375 template <Player P,class Action>
376 class GoldAction
377 {
378 NumEffectState const& state;
379 Square target;
380 Action& action;
381 public:
382 GoldAction(NumEffectState const& s,Square p,Action& a)
383 :state(s),target(p),action(a)
384 {}
388 void operator()(Piece p)
389 {
390 generateShortMove<P,GOLD,Action>(state,p,target,action);
391 }
392 };
393
397 template <Player P,Ptype T,class Action>
398 class LongPieceAction
399 {
400 NumEffectState const& state;
401 Square target;
402 Action& action;
403 public:
404 LongPieceAction(NumEffectState const& s,Square p,Action& a)
405 :state(s),target(p),action(a)
406 {}
410 void operator()(Piece p)
411 {
412 if (p.isPromotedNotKingGold())
413 {
414 if (T==LANCE)
415 generateShortMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
416 else
417 generateLongMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
418 }
419 else
420 {
421 generateLongMove<P,T,Action>(state,p,target,action);
422 }
423 }
424 };
425
426 template<Player P,Ptype T,class Action>
427 void generateShort(const NumEffectState& state,Square target,
428 Action& action)
429 {
430 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
431 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
432 typedef ShortPieceAction<P,T,Action> action_t;
433 action_t gkAction(state,target,action);
434 state.template forEachOnBoard<P,T,action_t>(gkAction);
436 if (state.template hasPieceOnStand<T>(P)){
437 generateShortDrop<P,T,Action>(state,target,action);
438 }
439 }
440
441 template<Player P,Ptype T,class Action>
442 void generateLong(const NumEffectState& state,Square target,
443 Action& action)
444 {
445 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
446 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
447 typedef LongPieceAction<P,T,Action> action_t;
448 action_t gkAction(state,target,action);
449 state.template forEachOnBoard<P,T,action_t>(gkAction);
450 }
451
452 template<Player P,class Action>
453 void generateGold(const NumEffectState& state,Square target,
454 Action& action)
455 {
456 typedef GoldAction<P,Action> action_t;
457 action_t gkAction(state,target,action);
458 state.template forEachOnBoard<P,GOLD,action_t>(gkAction);
460 if (state.template hasPieceOnStand<GOLD>(P)){
461 generateShortDrop<P,GOLD,Action>(state,target,action);
462 }
463 }
464 }
465
466 template<Player P>
467 template<class Action>
468 void AddEffect8<P>::
469 generateBigDrop(const NumEffectState& state,Action& action)
470 {
471 using namespace addeffect8;
472 Square target=state.kingSquare<PlayerTraits<P>::opponent>();
473 if (state.template hasPieceOnStand<BISHOP>(P)){
474 generateLongDrop<P,BISHOP,Action>(state,target,action);
475 }
476 if (state.template hasPieceOnStand<ROOK>(P)){
477 generateLongDrop<P,ROOK,Action>(state,target,action);
478 }
479 }
480
481 template<Player P>
482 template<class Action>
483 void AddEffect8<P>::
484 generateNotBigDrop(const NumEffectState& state,Action& action)
485 {
486 using namespace addeffect8;
487 Square target=state.kingSquare<PlayerTraits<P>::opponent>();
488 generateShort<P,PAWN,Action>(state,target,action);
489 generateLong<P,LANCE,Action>(state,target,action);
490 if (state.template hasPieceOnStand<LANCE>(P)){
491 generateLongDrop<P,LANCE,Action>(state,target,action);
492 }
493 generateShort<P,KNIGHT,Action>(state,target,action);
494 generateShort<P,SILVER,Action>(state,target,action);
495 generateGold<P,Action>(state,target,action);
496 // no king move
497 generateLong<P,BISHOP,Action>(state,target,action);
498 generateLong<P,ROOK,Action>(state,target,action);
499 }
500
501 template<Player P>
502 template<class Action>
503 void AddEffect8<P>::
504 generate(const NumEffectState& state,Action& action)
505 {
506 generateNotBigDrop(state,action);
507 generateBigDrop(state,action);
508 }
509 }
510 }
511 #endif /* _MOVE_GENERATOR_ADD_EFFECT8_TCC */
512 // ;;; Local Variables:
513 // ;;; mode:c++
514 // ;;; c-basic-offset:2
515 // ;;; End: