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
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){
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++){
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>() :
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
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++){
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++){
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>
348  {
349  NumEffectState const& state;
351  Action& action;
352  public:
353  ShortPieceAction(NumEffectState const& s,Square p,Action& a)
354  :state(s),target(p),action(a)
355  {}
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>
377  {
378  NumEffectState const& state;
380  Action& action;
381  public:
382  GoldAction(NumEffectState const& s,Square p,Action& a)
383  :state(s),target(p),action(a)
384  {}
389  {
390  generateShortMove<P,GOLD,Action>(state,p,target,action);
391  }
392  };
393 
397  template <Player P,Ptype T,class Action>
399  {
400  NumEffectState const& state;
402  Action& action;
403  public:
404  LongPieceAction(NumEffectState const& s,Square p,Action& a)
405  :state(s),target(p),action(a)
406  {}
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  {
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  {
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: