pieceOnBoard.tcc
Go to the documentation of this file.
1 #ifndef OSL_GENERATE_PIECE_MOVES_TCC
2 #define OSL_GENERATE_PIECE_MOVES_TCC
3 #include "osl/move_generator/pieceOnBoard.h"
4 #include "osl/move_generator/move_action.h"
5 #include "osl/bits/king8Info.h"
6 
7 namespace osl
8 {
9  namespace move_generator
10  {
11  namespace piece_on_board
12  {
13  /**
14  * ROOK, BISHOP, PROOK, PBISHOPのlong方向の手生成
15  * CanPはNoPromoteかCanPromote, CheckPromoteのみ
16  * NoPromoteはpromoteできない点からの後ろ,横のdirection
17  * CanPromoteはpromoteできる点から
18  * CheckPromoteはpromoteできない点からの前向き direction
19  */
20  template <Player P,class Action,PromoteType CanP,Direction Dir,bool notPromoteCapture>
21  inline void
22  generateLong(NumEffectState const& state,Piece p,const Piece *ptr,Square from,Action& action,Int2Type<true>,Move moveBase,Ptype ptype)
23  {
24  int num=p.number();
25  const Direction shortDir=longToShort(Dir);
26  Square limit=state.mobilityOf((P==BLACK ? shortDir : inverse(shortDir)),num);
27  const Piece *limitPtr=state.getPiecePtr(limit);
28  assert(ptype!=LANCE);
29  const Offset offset=DirectionPlayerTraits<Dir,P>::offset();
30  assert(!offset.zero());
31  ptr+=offset.intValue();
32  Square to=from+offset;
33  Move m=moveBase.newAddTo(offset);
34  if(CanP==CheckPromoteType || CanP==CanPromoteType){
35  if(CanP==CheckPromoteType){
36  // promoteできない数
37  int count=(P==BLACK ? from.y1()-5 : 7-from.y1());
38  for(int i=0;i<count;i++){
39  if(ptr==limitPtr){
40  Piece p1= *limitPtr;
41  if(!notPromoteCapture && p1.canMoveOn<P>())
42  action.unknownMove(from,to,p1,ptype,false,P,m.newAddCapture(p1));
43  return;
44  }
45  action.simpleMove(from,to,ptype,false,P,m);
46  ptr+=offset.intValue();
47  to+=offset; m=m.newAddTo(offset);
48  }
49  }
50  if(notPromoteCapture) return;
51  while(ptr!=limitPtr){
52  assert(from.canPromote<P>() || to.canPromote<P>());
53  action.simpleMove(from,to,::osl::promote(ptype),true,P,m.promote());
54  ptr+=offset.intValue();
55  to+=offset;
56  m=m.newAddTo(offset);
57  }
58  Piece p1= *limitPtr;
59  if(p1.canMoveOn<P>()){
60  m=m.newAddCapture(p1);
61  assert(from.canPromote<P>() || to.canPromote<P>());
62  action.unknownMove(from,to,p1,::osl::promote(ptype),true,P,m.promote());
63  }
64  }
65  else{ // NoPromote
66  while(ptr!=limitPtr){
67  action.simpleMove(from,to,ptype,false,P,m);
68  ptr+=offset.intValue();
69  to+=offset; m=m.newAddTo(offset);
70  }
71  if(notPromoteCapture) return;
72  Piece p1= *limitPtr;
73  if(p1.canMoveOn<P>()){
74  m=m.newAddCapture(p1);
75  action.unknownMove(from,to,p1,ptype,false,P,m);
76  }
77  }
78  }
79  template <Player P,class Action,PromoteType CanP,Direction Dir,bool notPromoteCapture>
80  inline void
81  generateLong(NumEffectState const&,Piece,const Piece *, Square,Action&,Int2Type<false>,Move,Ptype)
82  {
83  }
84 
85  template <Player P,Ptype T,class Action,PromoteType CanP,Direction Dir,bool notPromoteCapture>
86  inline void
87  generateLong(NumEffectState const& state,Piece p,const Piece *ptr, Square pos,Action& action,Move moveBase,Ptype ptype)
88  {
89  generateLong<P,Action,
90  (CanP != CheckPromoteType ? CanP : (DirectionTraits<Dir>::canPromoteTo ? CheckPromoteType : NoPromoteType)),
91  Dir,notPromoteCapture>(state,p,ptr,pos,action,
92  Int2Type<(PtypeTraits<T>::moveMask & DirectionTraits<Dir>::mask) !=0>(),moveBase,ptype);
93  }
94 
95  /**
96  * 短い利きの動き
97  * CanPromoteType - promote可能な動きの時
98  * MustPromoteType - 2段目の歩,3,4段目の桂馬
99  */
100  template <Player P,class Action,PromoteType CanP,Direction Dir,bool notPromoteCapture>
101  void
102  generateShort(const Piece *ptr,Square from,Action& action,Int2Type<true>,Move moveBase,Ptype ptype)
103  {
104  const Offset offset=DirectionPlayerTraits<Dir,P>::offset();
105  Piece p1=ptr[offset.intValue()];
106  Square to=from+offset;
107  Move m=moveBase.newAddTo(offset).newAddCapture(p1);
108  if ((notPromoteCapture ? p1.isEmpty() : p1.canMoveOn<P>())){
109  if (!notPromoteCapture && (CanP==CanPromoteType || CanP==MustPromoteType))
110  action.unknownMove(from,to,p1,::osl::promote(ptype),true,P,m.promote());
111  if (CanP!=MustPromoteType)
112  action.unknownMove(from,to,p1,ptype,false,P,m);
113  }
114  }
115 
116  template <Player P,class Action,PromoteType CanP,Direction Dir,bool notPromoteCapture>
117  void
118  generateShort(const Piece */*ptr*/,Square /*from*/,Action& /*action*/,Int2Type<false>,Move /*moveBase*/,Ptype /*ptype*/)
119  {
120  }
121 
122  template <Player P,Ptype T,class Action,PromoteType CanP,Direction Dir,bool notPromoteCapture>
123  void
124  generateShort(const Piece *ptr,Square from,Action& action,Move moveBase,Ptype /*ptype*/)
125  {
126  generateShort<P,Action,
127  (CanP != CheckPromoteType ? CanP : (DirectionTraits<Dir>::canPromoteTo ? CanPromoteType : NoPromoteType)),
128  Dir,notPromoteCapture>(ptr,from,action,
129  Int2Type<(PtypeTraits<T>::moveMask & DirectionTraits<Dir>::mask) !=0>(),
130  moveBase,T);
131  }
132 
133  template <Player P,Ptype T,class Action,PromoteType CanP,bool useDirMask,bool notPromoteCapture>
134  inline void
135  generatePtypePromote(const NumEffectState& state,Piece p, Action& action,Square from,int dirMask)
136  {
137  const Ptype ptype=(T==GOLD ? p.ptype() : T);
138  Move moveBase=Move(from,from,ptype,(Ptype)0,false,P);
139  const Piece *ptr=state.getPiecePtr(from);
140  if(!useDirMask || (dirMask&(1<<UL))==0){
141  generateShort<P,T,Action,CanP,UL,notPromoteCapture>(ptr,from,action,moveBase,ptype);
142  generateShort<P,T,Action,CanP,DR,notPromoteCapture>(ptr,from,action,moveBase,ptype);
143  generateLong<P,T,Action,CanP,LONG_UL,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
144  generateLong<P,T,Action,CanP,LONG_DR,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
145  }
146  if(!useDirMask || (dirMask&(1<<UR))==0){
147  generateShort<P,T,Action,CanP,UR,notPromoteCapture>(ptr,from,action,moveBase,ptype);
148  generateShort<P,T,Action,CanP,DL,notPromoteCapture>(ptr,from,action,moveBase,ptype);
149  generateLong<P,T,Action,CanP,LONG_UR,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
150  generateLong<P,T,Action,CanP,LONG_DL,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
151  }
152  if(!useDirMask || (dirMask&(1<<U))==0){
153  generateShort<P,T,Action,CanP,U,notPromoteCapture>(ptr,from,action,moveBase,ptype);
154  generateShort<P,T,Action,CanP,D,notPromoteCapture>(ptr,from,action,moveBase,ptype);
155  generateLong<P,T,Action,CanP,LONG_U,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
156  generateLong<P,T,Action,CanP,LONG_D,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
157  }
158  if(!useDirMask || (dirMask&(1<<L))==0){
159  generateShort<P,T,Action,CanP,L,notPromoteCapture>(ptr,from,action,moveBase,ptype);
160  generateShort<P,T,Action,CanP,R,notPromoteCapture>(ptr,from,action,moveBase,ptype);
161  generateLong<P,T,Action,CanP,LONG_L,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
162  generateLong<P,T,Action,CanP,LONG_R,notPromoteCapture>(state,p,ptr,from,action,moveBase,ptype);
163  }
164  generateShort<P,T,Action,CanP,UUL,notPromoteCapture>(ptr,from,action,moveBase,ptype);
165  generateShort<P,T,Action,CanP,UUR,notPromoteCapture>(ptr,from,action,moveBase,ptype);
166  }
167 
168  template <Player P,Direction Dir,class Action,bool notPromoteCapture>
169  inline void
170  generateKingDir(const Piece *ptr, Square from,Action& action,unsigned int liberty,Move const& moveBase)
171  {
172  if((liberty&(1<<Dir))!=0){
173  const Offset offset=DirectionPlayerTraits<Dir,P>::offset();
174  Move m=moveBase.newAddTo(offset);
175  Square to=from+offset;
176  Piece p1=ptr[offset.intValue()];
177  assert(p1.canMoveOn<P>());
178  if(notPromoteCapture && !p1.isEmpty()) return;
179  m=m.newAddCapture(p1);
180  action.unknownMove(from,to,p1,KING,false,P,m);
181  }
182  }
183 
184  template <Player P,class Action,bool useDirMask,bool notPromoteCapture>
185  inline void
186  generateKing(const NumEffectState& state, Action& action,Square pos,int dirMask)
187  {
188  King8Info king8info(state.Iking8Info(P));
189  unsigned int liberty=king8info.liberty();
190  Move moveBase(pos,pos,KING,(Ptype)0,false,P);
191  const Piece *ptr=state.getPiecePtr(pos);
192  if(!useDirMask || (dirMask&(1<<UL))==0){
193  generateKingDir<P,UL,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
194  generateKingDir<P,DR,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
195  }
196  if(!useDirMask || (dirMask&(1<<U))==0){
197  generateKingDir<P,U,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
198  generateKingDir<P,D,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
199  }
200  if(!useDirMask || (dirMask&(1<<UR))==0){
201  generateKingDir<P,UR,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
202  generateKingDir<P,DL,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
203  }
204  if(!useDirMask || (dirMask&(1<<L))==0){
205  generateKingDir<P,L,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
206  generateKingDir<P,R,Action,notPromoteCapture>(ptr,pos,action,liberty,moveBase);
207  }
208  }
209 
210  template <Player P,class Action,bool useDirMask,bool notPromoteCapture>
211  inline void
212  generateLance(const NumEffectState& state, Piece p,Action& action,Square from,int dirMask)
213  {
214  if(!useDirMask || (dirMask&(1<<U))==0){
215  const Offset offset=DirectionPlayerTraits<U,P>::offset();
216  Square limit=state.mobilityOf((P==BLACK ? U : D),p.number());
217  Square to=limit;
218  Piece p1=state.pieceAt(to);
219  int limity=(P==BLACK ? to.y() : 10-to.y());
220  int fromy=(P==BLACK ? from.y() : 10-from.y());
221  int ycount=fromy-limity-1;
222  Move m(from,to,LANCE,(Ptype)0,false,P);
223  switch(limity){
224  case 4: case 5: case 6: case 7: case 8: case 9:{
225  if(!notPromoteCapture && p1.canMoveOn<P>())
226  action.unknownMove(from,to,p1,LANCE,false,P,m.newAddCapture(p1));
227  m=m.newAddTo(-offset); to-=offset;
228  goto escape4;
229  }
230  case 3:
231  if(!notPromoteCapture && p1.canMoveOn<P>()){
232  Move m1=m.newAddCapture(p1);
233  action.unknownMove(from,to,p1,PLANCE,true,P,m1.promote());
234  action.unknownMove(from,to,p1,LANCE,false,P,m1);
235  }
236  m=m.newAddTo(-offset); to-=offset;
237  goto escape4;
238  case 2:
239  if(!notPromoteCapture && p1.canMoveOn<P>()){
240  Move m1=m.newAddCapture(p1);
241  action.unknownMove(from,to,p1,PLANCE,true,P,m1.promote());
242  }
243  if(fromy==3) return;
244  m=m.newAddTo(-offset); to-=offset;
245  ycount=fromy-4;
246  goto escape2;
247  case 0:
248  m=m.newAddTo(-offset); to-=offset;
249  if(!notPromoteCapture)
250  action.simpleMove(from,to,PLANCE,true,P,m.promote());
251  goto join01;
252  case 1:
253  if(!notPromoteCapture && p1.canMoveOn<P>()){
254  action.unknownMove(from,to,p1,PLANCE,true,P,m.newAddCapture(p1).promote());
255  }
256  join01:
257  if(fromy==2) return;
258  m=m.newAddTo(-offset); to-=offset;
259  if(fromy==3){
260  if(!notPromoteCapture)
261  action.simpleMove(from,to,PLANCE,true,P,m.promote());
262  return;
263  }
264  ycount=fromy-4;
265  goto escape01;
266  default: assert(0);
267  }
268  escape01:
269  if(!notPromoteCapture)
270  action.simpleMove(from,to,PLANCE,true,P,m.promote());
271  m=m.newAddTo(-offset); to-=offset;
272  escape2:
273  if(!notPromoteCapture)
274  action.simpleMove(from,to,PLANCE,true,P,m.promote());
275  action.simpleMove(from,to,LANCE,false,P,m);
276  m=m.newAddTo(-offset); to-=offset;
277  escape4:
278  while(ycount-->0){
279  action.simpleMove(from,to,LANCE,false,P,m);
280  m=m.newAddTo(-offset);
281  to-=offset;
282  }
283  }
284  return;
285  }
286 
287  template <Player P,class Action,bool useDirMask,bool notPromoteCapture>
288  inline void
289  generatePawn(const NumEffectState& state, Piece p,Action& action,Square from,int dirMask)
290  {
291  assert(from == p.square());
292  if(!useDirMask || (dirMask&(1<<U))==0){
293  if(notPromoteCapture && (P==BLACK ? from.yLe<4>() : from.yGe<6>())) return;
294  const Offset offset=DirectionPlayerTraits<U,P>::offset();
295  Square to=from+offset;
296  Piece p1=state.pieceAt(to);
297  if(notPromoteCapture){
298  if(p1.isEmpty())
299  action.simpleMove(from,to,PAWN,false,P);
300  return;
301  }
302  if(p1.canMoveOn<P>()){
303  if(P==BLACK ? to.yLe<3>() : to.yGe<7>()){ // canPromote
304  if(notPromoteCapture) return;
305  Move m(from,to,PPAWN,PTYPE_EMPTY,true,P);
306  action.unknownMove(from,to,p1,PPAWN,true,P,
307  m.newAddCapture(p1));
308  }
309  else{
310  Move m(from,to,PAWN,PTYPE_EMPTY,false,P);
311  action.unknownMove(from,to,p1,PAWN,false,P,m.newAddCapture(p1));
312  }
313  }
314  }
315  }
316 }
317  template <class Action,bool notPromoteCapture>
318  template <Player P,Ptype T,bool useDirMask>
319  void PieceOnBoard<Action,notPromoteCapture>::
320  generatePtypeUnsafe(const NumEffectState& state,Piece p, Action& action,int dirMask)
321  {
322  using piece_on_board::generatePtypePromote;
323  using piece_on_board::generateKing;
324  using piece_on_board::generateLance;
325  using piece_on_board::generatePawn;
326  const Square from=p.square();
327  if(T==KING){
328  generateKing<P,Action,useDirMask,notPromoteCapture>(state,action,from,dirMask);
329  }
330  else if(T==LANCE){
331  generateLance<P,Action,useDirMask,notPromoteCapture>(state,p,action,from,dirMask);
332  }
333  else if(T==PAWN){
334  generatePawn<P,Action,useDirMask,notPromoteCapture>(state,p,action,from,dirMask);
335  }
336  else if(canPromote(T)){
337  if(PtypePlayerTraits<T,P>::mustPromote(from))
338  generatePtypePromote<P,T,Action,MustPromoteType,useDirMask,notPromoteCapture>(state,p,action,from,dirMask);
339  else if(PtypePlayerTraits<T,P>::canPromote(from))
340  generatePtypePromote<P,T,Action,CanPromoteType,useDirMask,notPromoteCapture>(state,p,action,from,dirMask);
341  else if(PtypePlayerTraits<T,P>::checkPromote(from))
342  generatePtypePromote<P,T,Action,CheckPromoteType,useDirMask,notPromoteCapture>(state,p,action,from,dirMask);
343  else
344  generatePtypePromote<P,T,Action,NoPromoteType,useDirMask,notPromoteCapture>(state,p,action,from,dirMask);
345  }
346  else
347  generatePtypePromote<P,T,Action,NoPromoteType,useDirMask,notPromoteCapture>(state,p,action,from,dirMask);
348  }
349 
350  template <class Action,bool notPromoteCapture>
351 template <Player P,Ptype T,bool useDirMask>
352  void PieceOnBoard<Action,notPromoteCapture>::
353 generatePtype(const NumEffectState& state,Piece p, Action& action,int dirMask)
354 {
355  int num=p.number();
356 // if(T==SILVER) std::cerr << "p=" << p << std::endl;
357  if(state.pin(P).test(num)){
358  if(T==KNIGHT) return;
359  Direction d=state.pinnedDir<P>(p);
360  dirMask|=(~(1<<primDir(d)));
361 // std::cerr << "pinned direction=" << d << ",dirMask=" << dirMask << std::endl;
362  generatePtypeUnsafe<P,T,true>(state,p,action,dirMask);
363  }
364  else{
365  generatePtypeUnsafe<P,T,useDirMask>(state,p,action,dirMask);
366  }
367 }
368  template <class Action,bool notPromoteCapture>
369 template <Player P,bool useDirmask>
370  void PieceOnBoard<Action,notPromoteCapture>::
371 generate(const NumEffectState& state,Piece p, Action& action,int dirMask)
372 {
373 
374  switch(p.ptype()){
375  case PPAWN: case PLANCE: case PKNIGHT: case PSILVER: case GOLD:
376  generatePtype<P,GOLD,useDirmask>(state,p,action,dirMask); break;
377  case PAWN:
378  generatePtype<P,PAWN,useDirmask>(state,p,action,dirMask); break;
379  case LANCE:
380  generatePtype<P,LANCE,useDirmask>(state,p,action,dirMask); break;
381  case KNIGHT:
382  generatePtype<P,KNIGHT,useDirmask>(state,p,action,dirMask); break;
383  case SILVER:
384  generatePtype<P,SILVER,useDirmask>(state,p,action,dirMask); break;
385  case BISHOP:
386  generatePtype<P,BISHOP,useDirmask>(state,p,action,dirMask); break;
387  case PBISHOP:
388  generatePtype<P,PBISHOP,useDirmask>(state,p,action,dirMask); break;
389  case ROOK:
390  generatePtype<P,ROOK,useDirmask>(state,p,action,dirMask); break;
391  case PROOK:
392  generatePtype<P,PROOK,useDirmask>(state,p,action,dirMask); break;
393  case KING:
394  generatePtype<P,KING,useDirmask>(state,p,action,dirMask); break;
395  default: break;
396  }
397 }
398 } // namespace move_generator
399 } // namespace osl
400 
401 #endif /* _GENERATE_PIECE_MOVES_TCC */
402 // ;;; Local Variables:
403 // ;;; mode:c++
404 // ;;; c-basic-offset:2
405 // ;;; End:
406