All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
numEffectState.cc
Go to the documentation of this file.
1 /* numEffectState.cc
2  */
7 
8 #include <iostream>
9 #include <emmintrin.h>
10 typedef __v2di v2di;
11 
13  const NumEffectState& st2)
14 {
15  assert(st1.isConsistent(true));
16  assert(st2.isConsistent(true));
17  if (!(st1.effects == st2.effects))
18  return false;
19  if (!(st1.pieces_onboard == st2.pieces_onboard))
20  return false;
21  if (!(st1.promoted == st2.promoted))
22  return false;
23  if (!(st1.pin_or_open == st2.pin_or_open))
24  return false;
25  if (!(st1.king_mobility == st2.king_mobility))
26  return false;
27  if (!(st1.king8infos == st2.king8infos))
28  return false;
29  return (static_cast<const SimpleState&>(st1)
30  == static_cast<const SimpleState&>(st2));
31 }
32 
35 {
36  return King8Info(Iking8Info(king));
37 }
38 
39 template<osl::Player P>
41 {
43 #ifdef ALLOW_KING_ABSENCE
44  if (kingSquare<P>().isPieceStand())
45  return;
46 #endif
47  king8infos[P]=King8Info::make<altP>(*this,kingSquare<P>()).uint64Value();
48 }
49 
52  : SimpleState(st),effects(st)
53 {
54  pieces_onboard[0].resetAll();
55  pieces_onboard[1].resetAll();
56  promoted.resetAll();
57  effects.effected_mask[0].resetAll();
58  effects.effected_mask[1].resetAll();
59  effects.effected_changed_mask[0].resetAll();
60  effects.effected_changed_mask[1].resetAll();
61  for(int num=0;num<40;num++){
62  Piece p=pieceOf(num);
63  if (p.isOnBoard()){
64  pieces_onboard[p.owner()].set(num);
65  if (p.isPromoted())
66  promoted.set(num);
67  for(int i=0;i<2;i++){
68  Player pl=indexToPlayer(i);
69  if(hasEffectAt(pl,p.square()))
70  {
71  effects.effected_mask[i].set(num);
72  effects.effected_changed_mask[i].set(num);
73  }
74  }
75  }
76  }
79  if(kingSquare<BLACK>().isOnBoard())
80  makeKing8Info<BLACK>();
81  if(kingSquare<WHITE>().isOnBoard())
82  makeKing8Info<WHITE>();
83 }
86 {
87 }
88 
90 NumEffectState::selectCheapPiece(PieceMask effect) const
91 {
92  if (! effect.any())
93  return Piece::EMPTY();
94  mask_t pieces = effect.selectBit<PAWN>(), ppieces;
95  if (pieces.any())
96  {
97  ppieces = pieces & promoted.getMask<PAWN>();
98  pieces &= ~ppieces;
99  if (pieces.any())
100  return pieceOf(pieces.bsf()+PtypeFuns<PAWN>::indexNum*32);
101  return pieceOf(ppieces.bsf()+PtypeFuns<PAWN>::indexNum*32);
102  }
103  pieces = effect.selectBit<LANCE>();
104  if (pieces.any())
105  {
106  ppieces = pieces & promoted.getMask<LANCE>();
107  pieces &= ~ppieces;
108  if (pieces.any())
109  return pieceOf(pieces.bsf()+PtypeFuns<LANCE>::indexNum*32);
110  return pieceOf(ppieces.bsf()+PtypeFuns<LANCE>::indexNum*32);
111  }
112  mask_t king = effect.selectBit<KING>();
113  effect.clearBit<KING>();
114  if (effect.none())
115  return pieceOf(king.bsf()+PtypeFuns<KING>::indexNum*32);
116  // depends on current piece numbers: <FU 0>, KE 18, GI 22, KI 26, <OU 30>, <KY 32>, KA 36, HI 38,
117 #if OSL_WORDSIZE == 64
118  const int index = 0;
119 #else
120  const int index = effect.getMask(0).any() ? 0 : 1;
121 #endif
122  ppieces = effect.getMask(index) & promoted.getMask(index);
123  pieces = effect.getMask(index) & ~ppieces;
124  const int num = pieces.any()
125  ? (ppieces.any() ? std::min(pieces.bsf(),ppieces.bsf()) : pieces.bsf())
126  : ppieces.bsf();
127  return pieceOf(num + index*32);
128 }
129 
132 {
133  assert(! inCheck(P));
134  PieceMask pieces = piecesOnBoard(P) & effectedMask(alt(P));
135  PieceMask nolance = pieces; nolance.clearBit<LANCE>();
136  int pp=-1, npp=-1, ret=-1;
137  const int lance_index = PtypeFuns<LANCE>::indexNum; // 64bit: 0, 32bit: 1
138  for (int i=lance_index; i>=0; --i) {
139  mask_t all = nolance.getMask(i);
140  mask_t promoted = all & promotedPieces().getMask(i);
141  mask_t notpromoted = all & ~promoted;
142  if (promoted.any()) {
143  pp = promoted.bsr() + i*32;
144  notpromoted &= ~Ptype_Table.getMaskLow(Piece_Table.getPtypeOf(pp));
145  }
146  if (notpromoted.any())
147  npp = notpromoted.bsr() + i*32;
148  ret = std::max(pp, npp);
150  return pieceOf(ret);
151  }
152  mask_t lance = pieces.selectBit<LANCE>();
153  if (lance.any()) {
154  mask_t plance = lance & promotedPieces().getMask(lance_index);
155  if (plance.any())
156  return pieceOf(plance.bsr()+lance_index*32);
157  return pieceOf(lance.bsr()+lance_index*32);
158  }
159  if (ret >= 0) {
160  assert(Piece_Table.getPtypeOf(ret) == PAWN);
161  return pieceOf(ret);
162  }
163  return Piece::EMPTY();
164 }
165 
166 bool osl::state::
168 {
169  if (! last_move.isNormal())
170  return false;
171  const Square from = last_move.from(), to = last_move.to();
172  if (last_move.ptype() == KING) {
173  if (last_move.isCapture()
174  && hasEffectIf(last_move.capturePtypeO(), to, from))
175  return true;
176  return hasEffectAt(turn(), from);
177  }
178  if (last_move.isCapture())
179  return hasEffectIf(last_move.capturePtypeO(), to,
180  kingSquare(alt(turn())))
181  && !Board_Table.isBetweenSafe(from, to,
182  kingSquare(alt(turn())));
183  const Piece piece = pieceOnBoard(to);
184  if (! pin(alt(turn())).test(piece.number()))
185  return false;
186  if (last_move.isDrop() || last_move.oldPtype() == KNIGHT)
187  return true;
188  const Direction d=pinnedDir(piece);
189  return primDir(d)
190  !=primDirUnsafe(Board_Table.getShort8Unsafe(piece.owner(), from,to));
191 }
192 
194 {
195  assert(turn() == move.player());
196  if (move.isPass()) {
197  makeMovePass();
198  return;
199  }
200 
201  assert(isAlmostValidMove(move));
202  const Square from=move.from();
203  const Square to=move.to();
204  if (from.isPieceStand())
205  {
206  doDropMove(to,move.ptype());
207  }
208  else
209  {
210  const Piece captured = pieceOnBoard(to);
211  if (captured != Piece::EMPTY())
212  {
213  doCaptureMove(from,to,captured,move.promoteMask());
214  }
215  else
216  {
217  doSimpleMove(from,to,move.promoteMask());
218  }
219  }
220  changeTurn();
221 }
222 
224 doSimpleMove(Square from, Square to, int promoteMask)
225 {
226  Piece oldPiece;
227  int num;
228  PtypeO oldPtypeO, newPtypeO;
229  CArray<PieceMask,2> pin_or_open_backup;
230  KingMobility king_mobility_backup;
231  PieceMask promoted_backup;
232  CArray<PieceMask,2> effected_mask_backup;
233  CArray<PieceMask,2> effected_changed_mask_backup;
234  CArray<uint64_t,2> king8infos_backup;
235  mobility::MobilityTable mobilityTable;
236  if (turn()==BLACK){
237  prologueSimple(Player2Type<BLACK>(), from, to, promoteMask,
238  oldPiece, num, oldPtypeO, newPtypeO,
239  pin_or_open_backup, king_mobility_backup,
240  promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
241  }
242  else{
243  prologueSimple(Player2Type<WHITE>(), from, to, promoteMask,
244  oldPiece, num, oldPtypeO, newPtypeO,
245  pin_or_open_backup, king_mobility_backup,
246  promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
247  }
248  if (promoteMask!=0 && num < PtypeTraits<PAWN>::indexLimit)
249  clearPawn(turn(),from);
250 }
252 doCaptureMove(Square from, Square to, Piece target, int promoteMask)
253 {
254  Piece oldPiece;
255  PtypeO oldPtypeO, capturePtypeO, newPtypeO;
256  int num0, num1, num1Index;
257  mask_t num1Mask;
258  CArray<PieceMask,2> pin_or_open_backup;
259  KingMobility king_mobility_backup;
260  PieceMask promoted_backup;
261  CArray<PieceMask,2> effected_mask_backup;
262  CArray<PieceMask,2> effected_changed_mask_backup;
263  CArray<uint64_t,2> king8infos_backup;
264  mobility::MobilityTable mobilityTable;
265  if(turn()==BLACK){
266  prologueCapture(Player2Type<BLACK>(), from, to, target, promoteMask, oldPiece, oldPtypeO,
267  capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask,
268  pin_or_open_backup, king_mobility_backup,
269  promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
270  }
271  else{
272  prologueCapture(Player2Type<WHITE>(), from, to, target, promoteMask, oldPiece, oldPtypeO,
273  capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask,
274  pin_or_open_backup, king_mobility_backup,
275  promoted_backup, effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
276  }
277  const Ptype capturePtype=target.ptype();
278  if (capturePtype==PAWN)
279  clearPawn(alt(turn()),to);
280  if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
281  clearPawn(turn(),from);
282 }
283 
286 {
287  Piece oldPiece;
288  PtypeO ptypeO;
289  int num, numIndex;
290  mask_t numMask;
291  CArray<PieceMask,2> pin_or_open_backup;
292  KingMobility king_mobility_backup;
293  CArray<PieceMask,2> effected_mask_backup;
294  CArray<PieceMask,2> effected_changed_mask_backup;
295  CArray<uint64_t,2> king8infos_backup;
296  mobility::MobilityTable mobilityTable;
297  if(turn()==BLACK){
298  prologueDrop(Player2Type<BLACK>(), to, ptype, oldPiece, num, ptypeO, numIndex, numMask,
299  pin_or_open_backup, king_mobility_backup,
300  effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
301  }
302  else{
303  prologueDrop(Player2Type<WHITE>(), to, ptype, oldPiece, num, ptypeO, numIndex, numMask,
304  pin_or_open_backup, king_mobility_backup,
305  effected_mask_backup, effected_changed_mask_backup,king8infos_backup,mobilityTable);
306  }
307  if (ptype==PAWN)
308  setPawn(turn(),to);
309 }
310 
311 template<osl::Player P>
313 prologueSimple(Player2Type<P>, Square from, Square to, int promoteMask,
314  Piece& oldPiece, int& num,
315  PtypeO& oldPtypeO, PtypeO& new_ptypeo,
316  CArray<PieceMask,2>& pin_or_open_backup,
317  KingMobility& king_mobility_backup,
318  PieceMask& promoted_backup,
319  CArray<PieceMask,2>& effected_mask_backup,
320  CArray<PieceMask,2>& effected_changed_mask_backup,
321  CArray<uint64_t,2>& king8infos_backup,
322  MobilityTable &mobility_backup)
323 {
324  mobility_backup = effects.mobilityTable;
325  pin_or_open_backup = pin_or_open;
326  king_mobility_backup = king_mobility;
327  effected_mask_backup = effects.effected_mask;
328  effected_changed_mask_backup = effects.effected_changed_mask;
329  king8infos_backup=king8infos;
330 
331  oldPiece=pieceAt(from);
332  Piece newPiece=oldPiece.promoteWithMask(promoteMask);
333  newPiece+=(to-from);
334  num=oldPiece.number();
335 
336  oldPtypeO=oldPiece.ptypeO();
337  new_ptypeo=newPiece.ptypeO();
338  // 自分自身の効きを外す
339  setPieceOf(num,newPiece);
340  effects.clearChangedEffects();
341  effects.clearEffectedChanged();
342  effects.template doEffect<NumBitmapEffect::Sub,true>(*this,oldPtypeO,from,num);
343  // 自分自身がブロックしていたpromote?の延長
344  // あるいは自分自身のブロック
345  effects.effectedNumTable[num].clear();
346  setBoard(to,newPiece);
347  effects.template doBlockAt<NumBitmapEffect::Sub,true>(*this,to,num);
348  setBoard(from,Piece::EMPTY());
349  effects.template doBlockAt<NumBitmapEffect::Add,true>(*this,from,num);
350  effects.template doEffect<NumBitmapEffect::Add,true>(*this,new_ptypeo,to,num);
351 
352  if (oldPtypeO == newPtypeO(P,KING))
353  makePinOpen(P);
354  else {
355  Direction lastD=UL;
356  pin_or_open[P].reset(num);
357  recalcPinOpen(from,lastD,P);
358  recalcPinOpen(to,lastD,P);
359  }
360  {
361  Direction lastD=UL;
362  pin_or_open[alt(P)].reset(num);
363  recalcPinOpen(from,lastD,alt(P));
364  recalcPinOpen(to,lastD,alt(P));
365  }
366  promoted_backup = promoted;
367  if (promoteMask)
368  promoted.set(num);
369  if(hasEffectAt(BLACK,to))
370  effects.effected_mask[BLACK].set(num);
371  else
372  effects.effected_mask[BLACK].reset(num);
373  if(hasEffectAt(WHITE,to))
374  effects.effected_mask[WHITE].set(num);
375  else
376  effects.effected_mask[WHITE].reset(num);
377  effects.effected_changed_mask[BLACK].set(num);
378  effects.effected_changed_mask[WHITE].set(num);
379  {
380  BoardMask changed=changedEffects(BLACK)|changedEffects(WHITE);
381  changed.set(from);
382  changed.set(to);
383  if(changed.anyInRange(Board_Mask_Table3x3.mask(kingSquare<BLACK>()))
384  || pin_or_open[BLACK]!=pin_or_open_backup[BLACK])
385  makeKing8Info<BLACK>();
386  if(changed.anyInRange(Board_Mask_Table3x3.mask(kingSquare<WHITE>()))
387  || pin_or_open[WHITE]!=pin_or_open_backup[WHITE])
388  makeKing8Info<WHITE>();
389  }
390 }
391 
393 epilogueSimple(Square from, Square to, Piece oldPiece,
394  int num, PtypeO oldPtypeO, PtypeO newPtypeO,
395  const CArray<PieceMask,2>& pin_or_open_backup,
396  const KingMobility& king_mobility_backup,
397  const PieceMask& promoted_backup,
398  const CArray<PieceMask,2>& effected_mask_backup,
399  const CArray<PieceMask,2>& effected_changed_mask_backup,
400  const CArray<uint64_t,2>& king8infos_backup,
401  const MobilityTable & mobility_backup)
402 {
403  setPieceOf(num,oldPiece);
404  effects.doEffect<NumBitmapEffect::Sub,false>(*this,newPtypeO,to,num);
405  setBoard(from,oldPiece);
406  effects.effectedNumTable[num].clear();
407  effects.doBlockAt<NumBitmapEffect::Sub,false>(*this,from,num);
408  setBoard(to,Piece::EMPTY());
409  effects.doBlockAt<NumBitmapEffect::Add,false>(*this,to,num);
410  effects.doEffect<NumBitmapEffect::Add,false>(*this,oldPtypeO,from,num);
411  effects.invalidateChangedEffects();
412  pin_or_open = pin_or_open_backup;
413  king_mobility = king_mobility_backup;
414  promoted = promoted_backup;
415  effects.effected_mask = effected_mask_backup;
416  effects.effected_changed_mask = effected_changed_mask_backup;
417  effects.mobilityTable = mobility_backup;
418  king8infos = king8infos_backup;
419 }
420 
421 template<osl::Player P>
423 prologueDrop(Player2Type<P>, Square to, Ptype ptype,
424  Piece& oldPiece, int& num, PtypeO& ptypeO,
425  int& numIndex, mask_t& numMask,
426  CArray<PieceMask,2>& pin_or_open_backup,
427  KingMobility& king_mobility_backup,
428  CArray<PieceMask,2>& effected_mask_backup,
429  CArray<PieceMask,2>& effected_changed_mask_backup,
430  CArray<uint64_t,2>& king8infos_backup,
431  MobilityTable &mobility_backup)
432 {
433  king8infos_backup = king8infos;
434  mobility_backup = effects.mobilityTable;
435  pin_or_open_backup = pin_or_open;
436  king_mobility_backup = king_mobility;
437  effected_mask_backup = effects.effected_mask;
438  effected_changed_mask_backup = effects.effected_changed_mask;
439 #if OSL_WORDSIZE == 64
440  numIndex=0;
441 #elif OSL_WORDSIZE == 32
442  numIndex=Ptype_Table.getIndex(ptype);
443 #endif
444  const mask_t ownMochigoma=
445  standMask(P).getMask(numIndex) & Ptype_Table.getMaskLow(ptype);
446  assert(ownMochigoma.any());
447  numMask=ownMochigoma.lowestBit();
448  int numLow = ownMochigoma.bsf();
449  num = numLow|(numIndex<<5);
450  oldPiece=pieceOf(num);
451  Piece newPiece=oldPiece;
452  newPiece+=to-Square::STAND();
453  ptypeO=newPiece.ptypeO();
454  setPieceOf(num,newPiece);
455  effects.clearChangedEffects();
456  effects.clearEffectedChanged();
457  effects.template doBlockAt<NumBitmapEffect::Sub,true>(*this,to,num);
458  effects.template doEffect<NumBitmapEffect::Add,true>(*this,ptypeO,to,num);
459  setBoard(to,newPiece);
460  standMask(P).xorMask(numIndex,numMask);
461  stand_count[P][ptype-PTYPE_BASIC_MIN]--;
462  pieces_onboard[P].xorMask(numIndex,numMask);
463  {
464  Direction lastD=UL;
465  recalcPinOpen(to,lastD,P);
466  }
467  {
468  Direction lastD=UL;
469  recalcPinOpen(to,lastD,alt(P));
470  }
471  if(hasEffectAt(BLACK,to))
472  effects.effected_mask[BLACK].set(num);
473  else
474  effects.effected_mask[BLACK].reset(num);
475  if (hasEffectAt(WHITE,to))
476  effects.effected_mask[WHITE].set(num);
477  else
478  effects.effected_mask[WHITE].reset(num);
479  effects.effected_changed_mask[BLACK].set(num);
480  effects.effected_changed_mask[WHITE].set(num);
481  {
482  BoardMask changed=changedEffects(BLACK)|changedEffects(WHITE);
483  changed.set(to);
484  if(changed.anyInRange(Board_Mask_Table3x3.mask(kingSquare<BLACK>()))
485  || pin_or_open[BLACK]!=pin_or_open_backup[BLACK])
486  makeKing8Info<BLACK>();
487  if(changed.anyInRange(Board_Mask_Table3x3.mask(kingSquare<WHITE>()))
488  || pin_or_open[WHITE]!=pin_or_open_backup[WHITE])
489  makeKing8Info<WHITE>();
490  }
491 }
492 
493 template<osl::Player P>
495 epilogueDrop(Player2Type<P>, Square to, Ptype ptype, Piece oldPiece,
496  int num, PtypeO ptypeO, int numIndex, mask_t numMask,
497  const CArray<PieceMask,2>& pin_or_open_backup,
498  const KingMobility& king_mobility_backup,
499  const CArray<PieceMask,2>& effected_mask_backup,
500  const CArray<PieceMask,2>& effected_changed_mask_backup,
501  const CArray<uint64_t,2>& king8infos_backup,
502  const MobilityTable& mobility_backup)
503 {
504  standMask(P).xorMask(numIndex,numMask);
505  stand_count[P][ptype-PTYPE_BASIC_MIN]++;
506  pieces_onboard[P].xorMask(numIndex,numMask);
507  setBoard(to,Piece::EMPTY());
508  effects.template doEffect<NumBitmapEffect::Sub,false>(*this,ptypeO,to,num);
509  effects.template doBlockAt<NumBitmapEffect::Add,false>(*this,to,num);
510  setPieceOf(num,oldPiece);
511  effects.effectedNumTable[num].clear();
512  effects.invalidateChangedEffects();
513  pin_or_open = pin_or_open_backup;
514  king_mobility = king_mobility_backup;
515  effects.effected_mask = effected_mask_backup;
516  effects.effected_changed_mask = effected_changed_mask_backup;
517  effects.mobilityTable = mobility_backup;
518  king8infos = king8infos_backup;
519 }
520 
521 template<osl::Player P>
523 prologueCapture(Player2Type<P>, Square from, Square to, Piece target,
524  int promoteMask,
525  Piece& oldPiece, PtypeO& oldPtypeO, PtypeO& capturePtypeO,
526  PtypeO& new_ptypeo, int& num0, int& num1,
527  int& num1Index, mask_t& num1Mask,
528  CArray<PieceMask,2>& pin_or_open_backup,
529  KingMobility& king_mobility_backup,
530  PieceMask& promoted_backup,
531  CArray<PieceMask,2>& effected_mask_backup,
532  CArray<PieceMask,2>& effected_changed_mask_backup,
533  CArray<uint64_t,2>& king8infos_backup,
534  MobilityTable &mobility_backup)
535 {
536  mobility_backup = effects.mobilityTable;
537  pin_or_open_backup = pin_or_open;
538  king_mobility_backup = king_mobility;
539  effected_mask_backup = effects.effected_mask;
540  effected_changed_mask_backup = effects.effected_changed_mask;
541  king8infos_backup = king8infos;
542 
543  num1=target.number();
544  num1Index=PieceMask::numToIndex(num1);
545  num1Mask=PieceMask::numToMask(num1);
546  pieces_onboard[PlayerTraits<P>::opponent].xorMask(num1Index,num1Mask);
547  standMask(P).xorMask(num1Index,num1Mask);
548  oldPiece=pieceAt(from);
549  Piece newPiece=oldPiece.promoteWithMask(promoteMask);
550  newPiece+=(to-from);
551  num0=oldPiece.number();
552  setPieceOf(num0,newPiece);
553  setPieceOf(num1,target.captured());
554 
555  oldPtypeO=oldPiece.ptypeO();
556  new_ptypeo=newPiece.ptypeO();
557  capturePtypeO=target.ptypeO();
558  stand_count[P][unpromote(getPtype(capturePtypeO))-PTYPE_BASIC_MIN]++;
559  effects.clearChangedEffects();
560  effects.clearEffectedChanged();
561  effects.setChangedPieces(effectSetAt(to));
562  effects.template doEffect<NumBitmapEffect::Sub,true>(*this,capturePtypeO,to,num1);
563  effects.template doEffect<NumBitmapEffect::Sub,true>(*this,oldPtypeO,from,num0);
564  setBoard(from,Piece::EMPTY());
565  effects.template doBlockAt<NumBitmapEffect::Add,true>(*this,from,num0);
566  effects.effectedNumTable[num0]=effects.effectedNumTable[num1];
567  effects.effectedNumTable[num1].clear();
568  setBoard(to,newPiece);
569  effects.template doEffect<NumBitmapEffect::Add,true>(*this,new_ptypeo,to,num0);
570 
571  if (oldPtypeO == newPtypeO(P,KING))
572  makePinOpen(P);
573  else {
574  Direction lastD=UL;
575  pin_or_open[P].reset(num0);
576  pin_or_open[P].reset(num1); // captured is not pin
577  recalcPinOpen(from,lastD,P);
578  recalcPinOpen(to,lastD,P);
579  }
580  {
581  Direction lastD=UL;
582  pin_or_open[alt(P)].reset(num0);
583  pin_or_open[alt(P)].reset(num1); // captured is not pin
584  recalcPinOpen(from,lastD,alt(P));
585  recalcPinOpen(to,lastD,alt(P));
586  }
587  promoted_backup = promoted;
588  promoted.reset(num1);
589  effects.effected_mask[BLACK].reset(num1);
590  effects.effected_mask[WHITE].reset(num1);
591  if (promoteMask)
592  promoted.set(num0);
593  if(hasEffectAt(BLACK,to))
594  effects.effected_mask[BLACK].set(num0);
595  else
596  effects.effected_mask[BLACK].reset(num0);
597  if(hasEffectAt(WHITE,to))
598  effects.effected_mask[WHITE].set(num0);
599  else
600  effects.effected_mask[WHITE].reset(num0);
601  effects.effected_changed_mask[BLACK].set(num0);
602  effects.effected_changed_mask[WHITE].set(num0);
603  {
604  BoardMask changed=changedEffects(BLACK)|changedEffects(WHITE);
605  changed.set(from);
606  changed.set(to);
607  if(changed.anyInRange(Board_Mask_Table3x3.mask(kingSquare<BLACK>()))
608  || pin_or_open[BLACK]!=pin_or_open_backup[BLACK])
609  makeKing8Info<BLACK>();
610  if(changed.anyInRange(Board_Mask_Table3x3.mask(kingSquare<WHITE>()))
611  || pin_or_open[WHITE]!=pin_or_open_backup[WHITE])
612  makeKing8Info<WHITE>();
613  }
614 }
615 
616 template<osl::Player P>
618 epilogueCapture(Player2Type<P>, Square from, Square to, Piece target,
619  Piece oldPiece, PtypeO oldPtypeO, PtypeO capturePtypeO,
620  PtypeO newPtypeO, int num0, int num1,
621  int num1Index, mask_t num1Mask,
622  const CArray<PieceMask,2>& pin_or_open_backup,
623  const KingMobility& king_mobility_backup,
624  const PieceMask& promoted_backup,
625  const CArray<PieceMask,2>& effected_mask_backup,
626  const CArray<PieceMask,2>& effected_changed_mask_backup,
627  const CArray<uint64_t,2>& king8infos_backup,
628  const MobilityTable &mobility_backup)
629 {
630  standMask(P).xorMask(num1Index,num1Mask);
631  stand_count[P][unpromote(getPtype(capturePtypeO))-PTYPE_BASIC_MIN]--;
632  pieces_onboard[PlayerTraits<P>::opponent].xorMask(num1Index,num1Mask);
633  effects.effectedNumTable[num1]=effects.effectedNumTable[num0];
634  effects.effectedNumTable[num0].clear();
635  setPieceOf(num0,oldPiece);
636  setPieceOf(num1,target);
637  effects.template doEffect<NumBitmapEffect::Sub,false>(*this,newPtypeO,to,num0);
638  setBoard(from,oldPiece);
639  setBoard(to,target);
640  effects.template doBlockAt<NumBitmapEffect::Sub,false>(*this,from,num0);
641  effects.template doEffect<NumBitmapEffect::Add,false>(*this,capturePtypeO,to,num1);
642  effects.template doEffect<NumBitmapEffect::Add,false>(*this,oldPtypeO,from,num0);
643  effects.invalidateChangedEffects();
644  pin_or_open = pin_or_open_backup;
645  king_mobility = king_mobility_backup;
646  promoted = promoted_backup;
647  effects.effected_mask = effected_mask_backup;
648  effects.effected_changed_mask = effected_changed_mask_backup;
649  effects.mobilityTable = mobility_backup;
650  king8infos = king8infos_backup;
651 }
652 
653 
654 #ifndef MINIMAL
656 {
657  if (!SimpleState::isConsistent(showError))
658  {
659  if (showError)
660  std::cerr << "error before effect\n";
661  return false;
662  }
663  effect::NumSimpleEffectTable effects1(*this);
664  if (!(effects1==effects))
665  {
666  if (showError)
667  {
668  std::cerr << "Effect error 1" << std::endl;
669  std::cerr << *this;
670  for(int y=1;y<=9;y++)
671  for(int x=9;x>0;x--)
672  {
673  Square pos(x,y);
674  if (!(effects1.effectSetAt(pos)==effects.effectSetAt(pos)))
675  {
676  std::cerr << pos << ",real=" << effects.effectSetAt(pos) << ",ideal=" << effects1.effectSetAt(pos) << std::endl;
677  }
678  }
679  for(int num=0;num<=39;num++){
680  for(int i=0;i<8;i++){
681  Direction d=static_cast<Direction>(i);
682  if(effects.effectedNumTable[num][d]!=effects1.effectedNumTable[num][d]){
683  std::cerr << "piece=" << pieceOf(num) << ",num=" << num << ",d=" << d << ",v1=" << effects.effectedNumTable[num][d] << ",v2=" << effects1.effectedNumTable[num][d] << std::endl;
684  }
685  }
686  }
687  std::cerr << effects.effectedNumTable << std::endl;
688  }
689  return false;
690  }
691  for (int z=0; z<2; ++z) {
692  const Player p = indexToPlayer(z);
693 #ifdef ALLOW_KING_ABSENCE
694  if (kingSquare(p).isPieceStand())
695  continue;
696 #endif
697  const PieceMask pin2 = effect_util::Pin::make(*this, p);
698  if (pin(p) != pin2) {
699  if (showError)
700  std::cerr << "pin for " << p << " differs " << pin(p) << " " << pin2 << "\n";
701  return false;
702  }
703  King8Info king8info2 = King8Info::make(alt(p), *this);
704  if (King8Info(Iking8Info(p)).uint64Value() != king8info2.uint64Value()) {
705  if (showError)
706  std::cerr << "king8info for " << p << " differs \n" << King8Info(Iking8Info(p)) << "\n" << king8info2 << "\n";
707  return false;
708  }
709  }
710  for (int i=0; i<Piece::SIZE; ++i) {
711  const Piece p = pieceOf(i);
712  if (p.isOnBoard()) {
713  if (promoted.test(i) != p.isPromoted()) {
714  if (showError)
715  std::cerr << "promoted differs " << p << " " << promoted << " " << promoted.test(i) << "\n";
716  return false;
717  }
718  }
719  }
720  return true;
721 }
722 #endif
723 
724 bool osl::state::NumEffectState::isConsistent(const NumEffectState& prev, Move moved, bool show_error) const
725 {
726  // test changedEffects
727  const CArray<BoardMask,2> changed_squares
728  = {{ changedEffects(BLACK), changedEffects(WHITE) }};
729  const BoardMask changed_all = changed_squares[BLACK] | changed_squares[WHITE];
730  CArray<BoardMask, Piece::SIZE> each_effect, prev_effect;
731  for (int i=0; i<Piece::SIZE; ++i) {
732  each_effect[i].clear();
733  prev_effect[i].clear();
734  }
735  for (int x=1; x<=9; ++x) {
736  for (int y=1; y<=9; ++y) {
737  const Square sq(x, y);
738  for (int i=0; i<Piece::SIZE; ++i) {
739  if (effectSetAt(sq).test(i))
740  each_effect[i].set(sq);
741  if (prev.effectSetAt(sq).test(i))
742  prev_effect[i].set(sq);
743  }
744  if (! changed_all.test(sq))
745  {
746  if (effectSetAt(sq) != prev.effectSetAt(sq)) {
747 #ifndef MINIMAL
748  if (show_error)
749  std::cerr << "changedEffects unset\n" << *this << moved << sq << "\n";
750 #endif
751  return false;
752  }
753  }
754  for (int i=0; i<2; ++i)
755  {
756  const Player pl = indexToPlayer(i);
757  if (! changed_squares[pl].test(sq))
758  {
759  if ((effectSetAt(sq) & piecesOnBoard(pl))
760  != (prev.effectSetAt(sq) & prev.piecesOnBoard(pl))) {
761 #ifndef MINIMAL
762  if (show_error)
763  std::cerr << "changedEffects unset for " << pl << "\n" << *this << moved << sq << "\n";
764 #endif
765  return false;
766  }
767  }
768  }
769  }
770  }
771  // test changedPieces()
772  const NumBitmapEffect changed_effect_pieces = changedPieces();
773  for (int i=0; i<Piece::SIZE; ++i) {
774  if (each_effect[i] == prev_effect[i])
775  continue;
776  if (! changed_effect_pieces.test(i)) {
777 #ifndef MINIMAL
778  if (show_error)
779  std::cerr << "changedPieces() unset\n" << *this << moved << i
780  << " " << each_effect[i] << " != " << prev_effect[i] << "\n";
781 #endif
782  return false;
783  }
784  }
785  // test effectedChanged(Player pl)
786  for (int i=0; i<Piece::SIZE; ++i)
787  {
788  for (int j=0; j<2; ++j)
789  {
790  const Player pl = indexToPlayer(j);
791  if (prev.pieceOf(i).square() == moved.to())
792  continue; // captured
793  if (prev.effectedMask(pl).test(i) != effectedMask(pl).test(i)) {
794  if (! effectedChanged(pl).test(i)) {
795 #ifndef MINIMAL
796  if (show_error)
797  std::cerr << "effectedChanged(" << pl << ") unset\n" << *this << moved << i
798  << " " << prev.effectedChanged(pl) << " != " << prev.effectedChanged(WHITE) << "\n";
799 #endif
800  return false;
801  }
802  }
803  }
804  }
805  return true;
806 }
807 
808 template <bool show_error>
809 bool
810 #if (defined __GNUC__) && (! defined GPSONE) && (! defined GPSUSIONE)
811 __attribute__ ((used,noinline))
812 #endif
814  assert(move.isValid());
815  assert(move.isNormal());
816  assert(this->turn() == move.player());
817  assert(isValidMoveByRule(move, true));
818 
819  const Square from=move.from();
820  if (from.isPieceStand()) // 打つ手
821  return isAlmostValidDrop<show_error>(move);
822  const Square to=move.to();
823  const Piece from_piece = this->pieceAt(from);
824 
825  if (! testValidityOtherThanEffect<show_error>(move))
826  return false;
827  if(!hasEffectByPiece(from_piece,to)){
828  if (show_error) {
829  std::cerr << " No such move2 : " << move << std::endl;
830  }
831  return false;
832  }
833  return true;
834 }
835 
837 isAlmostValidMove(Move move,bool show_error) const{
838 #ifdef MINIMAL
839  show_error=false;
840 #endif
841  if(show_error)
842  return isAlmostValidMove<true>(move);
843  else
844  return isAlmostValidMove<false>(move);
845 }
846 
847 #ifndef MINIMAL
848 void osl::state::NumEffectState::showEffect(std::ostream& os) const
849 {
850  os<< static_cast<SimpleState const&>(*this);
851  for(int y=1;y<=9;y++){
852  os << 'P' << y;
853  for(int x=9;x>0;x--){
854  Square pos(x,y);
855  os << record::csa::show(pieceAt(pos)) << effectSetAt(pos);
856  }
857  os << std::endl;
858  }
859  // 持ち駒の表示
860  for(int num=0;num<Piece::SIZE;num++){
861  if (standMask(BLACK).test(num)){
862  os << "P+00" << record::csa::show(Piece_Table.getPtypeOf(num))
863  << std::endl;
864  }
865  else if (standMask(WHITE).test(num)){
866  os << "P-00" << record::csa::show(Piece_Table.getPtypeOf(num))
867  << std::endl;
868  }
869  }
870 }
871 #endif
872 
875 {
876  PieceMask pins;
877  if(target.isPieceStand()) return pins;
878  PieceMask mask=piecesOnBoard(alt(defense));
879  makePinOpenDir<UL>(target,pins,mask,defense);
880  makePinOpenDir<U>(target,pins,mask,defense);
881  makePinOpenDir<UR>(target,pins,mask,defense);
882  makePinOpenDir<L>(target,pins,mask,defense);
883  makePinOpenDir<R>(target,pins,mask,defense);
884  makePinOpenDir<DL>(target,pins,mask,defense);
885  makePinOpenDir<D>(target,pins,mask,defense);
886  makePinOpenDir<DR>(target,pins,mask,defense);
887  return pins;
888 }
889 
892 {
893  pin_or_open[defense]=makePinOpen(kingSquare(defense),defense);
894 }
895 
897 allEffectAt(Player attack, Ptype ptype, Square target) const
898 {
899  switch (ptype) {
900  case PAWN: case PPAWN:
901  return allEffectAt<PAWN>(attack, target);
902  case LANCE: case PLANCE:
903  return allEffectAt<LANCE>(attack, target);
904  case KNIGHT: case PKNIGHT:
905  return allEffectAt<KNIGHT>(attack, target);
906  case SILVER: case PSILVER:
907  return allEffectAt<SILVER>(attack, target);
908  case GOLD:
909  return allEffectAt<GOLD>(attack, target);
910  case BISHOP: case PBISHOP:
911  return allEffectAt<BISHOP>(attack, target);
912  case ROOK: case PROOK:
913  return allEffectAt<ROOK>(attack, target);
914  case KING:
915  return allEffectAt<KING>(attack, target);
916  default:
917  assert(0);
918  }
919  return mask_t();
920 }
921 
923 {
924 #ifndef MINIMAL
925  (*this).used_mask=src.used_mask;
926 #endif
927  (*this).stand_mask=src.stand_mask;
928 #if defined(__i386__) || defined(__x86_64__)
929  {
930  v2di b16=*((v2di*)&src.board[16]);
931  v2di b20=*((v2di*)&src.board[20]);
932  v2di b24=*((v2di*)&src.board[24]);
933  v2di b32=*((v2di*)&src.board[32]);
934  v2di b36=*((v2di*)&src.board[36]);
935  v2di b40=*((v2di*)&src.board[40]);
936  v2di b48=*((v2di*)&src.board[48]);
937  v2di b52=*((v2di*)&src.board[52]);
938  v2di b56=*((v2di*)&src.board[56]);
939 
940  *((v2di*)&(*this).board[16])=b16;
941  *((v2di*)&(*this).board[20])=b20;
942  *((v2di*)&(*this).board[24])=b24;
943  *((v2di*)&(*this).board[32])=b32;
944  *((v2di*)&(*this).board[36])=b36;
945  *((v2di*)&(*this).board[40])=b40;
946  *((v2di*)&(*this).board[48])=b48;
947  *((v2di*)&(*this).board[52])=b52;
948  *((v2di*)&(*this).board[56])=b56;
949 
950 
951  v2di b64=*((v2di*)&src.board[64]);
952  v2di b68=*((v2di*)&src.board[68]);
953  v2di b72=*((v2di*)&src.board[72]);
954 
955  v2di b80=*((v2di*)&src.board[80]);
956  v2di b84=*((v2di*)&src.board[84]);
957  v2di b88=*((v2di*)&src.board[88]);
958 
959  v2di b96=*((v2di*)&src.board[96]);
960  v2di b100=*((v2di*)&src.board[100]);
961  v2di b104=*((v2di*)&src.board[104]);
962 
963 
964  *((v2di*)&(*this).board[64])=b64;
965  *((v2di*)&(*this).board[68])=b68;
966  *((v2di*)&(*this).board[72])=b72;
967 
968  *((v2di*)&(*this).board[80])=b80;
969  *((v2di*)&(*this).board[84])=b84;
970  *((v2di*)&(*this).board[88])=b88;
971 
972  *((v2di*)&(*this).board[96])=b96;
973  *((v2di*)&(*this).board[100])=b100;
974  *((v2di*)&(*this).board[104])=b104;
975 
976  v2di b112=*((v2di*)&src.board[112]);
977  v2di b116=*((v2di*)&src.board[116]);
978  v2di b120=*((v2di*)&src.board[120]);
979 
980  v2di b128=*((v2di*)&src.board[128]);
981  v2di b132=*((v2di*)&src.board[132]);
982  v2di b136=*((v2di*)&src.board[136]);
983 
984  v2di b144=*((v2di*)&src.board[144]);
985  v2di b148=*((v2di*)&src.board[148]);
986  v2di b152=*((v2di*)&src.board[152]);
987 
988  *((v2di*)&(*this).board[112])=b112;
989  *((v2di*)&(*this).board[116])=b116;
990  *((v2di*)&(*this).board[120])=b120;
991 
992  *((v2di*)&(*this).board[128])=b128;
993  *((v2di*)&(*this).board[132])=b132;
994  *((v2di*)&(*this).board[136])=b136;
995 
996  *((v2di*)&(*this).board[144])=b144;
997  *((v2di*)&(*this).board[148])=b148;
998  *((v2di*)&(*this).board[152])=b152;
999 
1000  v2di p0=*((v2di*)&src.pieces[0]);
1001  v2di p4=*((v2di*)&src.pieces[4]);
1002  v2di p8=*((v2di*)&src.pieces[8]);
1003  v2di p12=*((v2di*)&src.pieces[12]);
1004  v2di p16=*((v2di*)&src.pieces[16]);
1005  v2di p20=*((v2di*)&src.pieces[20]);
1006  v2di p24=*((v2di*)&src.pieces[24]);
1007  v2di p28=*((v2di*)&src.pieces[28]);
1008  v2di p32=*((v2di*)&src.pieces[32]);
1009  v2di p36=*((v2di*)&src.pieces[36]);
1010  *((v2di*)&(*this).pieces[0])=p0;
1011  *((v2di*)&(*this).pieces[4])=p4;
1012  *((v2di*)&(*this).pieces[8])=p8;
1013  *((v2di*)&(*this).pieces[12])=p12;
1014  *((v2di*)&(*this).pieces[16])=p16;
1015  *((v2di*)&(*this).pieces[20])=p20;
1016  *((v2di*)&(*this).pieces[24])=p24;
1017  *((v2di*)&(*this).pieces[28])=p28;
1018  *((v2di*)&(*this).pieces[32])=p32;
1019  *((v2di*)&(*this).pieces[36])=p36;
1020  }
1021 #else
1022  for(int x=1;x<=9;x++)
1023  for(int y=1;y<=9;y++)
1024  (*this).board[Square(x,y).index()]=src.board[Square(x,y).index()];
1025  (*this).pieces=src.pieces;
1026 #endif
1027  (*this).pawnMask=src.pawnMask;
1028  this->stand_count = src.stand_count;
1029  this->player_to_move=src.player_to_move;
1030  effects.copyFrom(src.effects);
1031  this->pieces_onboard=src.pieces_onboard;
1032  (*this).promoted=src.promoted;
1033  (*this).pin_or_open=src.pin_or_open;
1034  (*this).king_mobility=src.king_mobility;
1035  (*this).king8infos=src.king8infos;
1036 }
1037 
1039 {
1040  copyFrom(NumEffectState(src));
1041 }
1042 
1043 namespace osl
1044 {
1045  // explicit template instantiation
1046 
1047  template bool NumEffectState::
1048  hasEffectByWithRemove<BLACK>(Square, Square) const;
1049  template bool NumEffectState::
1050  hasEffectByWithRemove<WHITE>(Square, Square) const;
1051  template void NumEffectState::makeKing8Info<BLACK>();
1052  template void NumEffectState::makeKing8Info<WHITE>();
1053 
1054 
1055  template void NumEffectState::
1056  prologueSimple(Player2Type<BLACK>, Square, Square, int, Piece&, int&,
1057  PtypeO&, PtypeO&, CArray<PieceMask,2>&, KingMobility&,
1058  PieceMask&, CArray<PieceMask,2>&, CArray<PieceMask,2>&,
1059  CArray<uint64_t,2>&, MobilityTable&);
1060  template void NumEffectState::
1061  prologueSimple(Player2Type<WHITE>, Square, Square, int, Piece&, int&,
1062  PtypeO&, PtypeO&, CArray<PieceMask,2>&, KingMobility&,
1063  PieceMask&, CArray<PieceMask,2>&, CArray<PieceMask,2>&,
1064  CArray<uint64_t,2>&, MobilityTable&);
1065 
1066  template void NumEffectState::
1067  prologueCapture(Player2Type<BLACK>, Square, Square, Piece, int, Piece&,
1068  PtypeO&, PtypeO&, PtypeO&, int&, int&, int&, mask_t&,
1069  CArray<PieceMask,2>&, KingMobility&, PieceMask&,
1070  CArray<PieceMask,2>&, CArray<PieceMask,2>&,
1071  CArray<uint64_t,2>&, MobilityTable&);
1072  template void NumEffectState::
1073  prologueCapture(Player2Type<WHITE>, Square, Square, Piece, int, Piece&,
1074  PtypeO&, PtypeO&, PtypeO&, int&, int&, int&, mask_t&,
1075  CArray<PieceMask,2>&, KingMobility&, PieceMask&,
1076  CArray<PieceMask,2>&, CArray<PieceMask,2>&,
1077  CArray<uint64_t,2>&, MobilityTable&);
1078 
1079  template void NumEffectState::
1080  prologueDrop(Player2Type<BLACK>, Square, Ptype, Piece&, int&, PtypeO&,
1081  int&, mask_t&, CArray<PieceMask,2>&, KingMobility&,
1082  CArray<PieceMask,2>&, CArray<PieceMask,2>&,
1083  CArray<uint64_t,2>&, MobilityTable&);
1084  template void NumEffectState::
1085  prologueDrop(Player2Type<WHITE>, Square, Ptype, Piece&, int&, PtypeO&,
1086  int&, mask_t&, CArray<PieceMask,2>&, KingMobility&,
1087  CArray<PieceMask,2>&, CArray<PieceMask,2>&,
1088  CArray<uint64_t,2>&, MobilityTable&);
1089 
1090  template void NumEffectState::
1091  epilogueCapture(Player2Type<BLACK>, Square, Square, Piece, Piece, PtypeO, PtypeO,
1092  PtypeO, int, int, int, mask_t, const CArray<PieceMask,2>&,
1093  const KingMobility&, const PieceMask&, const CArray<PieceMask,2>&,
1094  const CArray<PieceMask,2>&, const CArray<uint64_t,2>&,
1095  const MobilityTable&);
1096  template void NumEffectState::
1097  epilogueCapture(Player2Type<WHITE>, Square, Square, Piece, Piece, PtypeO, PtypeO,
1098  PtypeO, int, int, int, mask_t, const CArray<PieceMask,2>&,
1099  const KingMobility&, const PieceMask&, const CArray<PieceMask,2>&,
1100  const CArray<PieceMask,2>&, const CArray<uint64_t,2>&,
1101  const MobilityTable&);
1102  template void NumEffectState::
1103  epilogueDrop(Player2Type<BLACK>, Square, Ptype, Piece, int, PtypeO, int, mask_t,
1104  const CArray<PieceMask,2>&, const KingMobility&, const CArray<PieceMask,2>&,
1105  const CArray<PieceMask,2>&, const CArray<uint64_t,2>&, const MobilityTable&);
1106  template void NumEffectState::
1107  epilogueDrop(Player2Type<WHITE>, Square, Ptype, Piece, int, PtypeO, int, mask_t,
1108  const CArray<PieceMask,2>&, const KingMobility&, const CArray<PieceMask,2>&,
1109  const CArray<PieceMask,2>&, const CArray<uint64_t,2>&, const MobilityTable&);
1110 
1111 }
1112 
1113 /* ------------------------------------------------------------------------- */
1114 // ;;; Local Variables:
1115 // ;;; mode:c++
1116 // ;;; c-basic-offset:2
1117 // ;;; End: