All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
simpleState.cc
Go to the documentation of this file.
1 /* simpleState.cc
2  */
3 
6 #include "osl/record/csa.h"
8 #include "osl/pieceTable.h"
9 #include "osl/pieceStand.h"
10 #include <boost/foreach.hpp>
11 #include <iostream>
12 #include <stdexcept>
13 
14 osl::SimpleState::SimpleState() {
15  init();
16 }
17 
18 osl::SimpleState::SimpleState(Handicap h) {
19  init(h);
20 }
21 
22 void osl::SimpleState::initPawnMask(){
23  BOOST_FOREACH(Ptype ptype, PieceStand::order) {
24  stand_count[BLACK][ptype - PTYPE_BASIC_MIN] = countPiecesOnStandBit(BLACK, ptype);
25  stand_count[WHITE][ptype - PTYPE_BASIC_MIN] = countPiecesOnStandBit(WHITE, ptype);
26  }
27 
28  pawnMask[0].clearAll();
29  pawnMask[1].clearAll();
30  for(int num=PtypeTraits<PAWN>::indexMin;
31  num< PtypeTraits<PAWN>::indexLimit; num++){
32  Piece p=pieceOf(num);
33  Player player=p.owner();
34  Square pos=p.square();
35  if(!pos.isPieceStand() && !p.isPromotedNotKingGold()){
36  if (isPawnMaskSet(player,pos.x()))
37  {
38  throw CsaIOError("2FU!");
39  }
40  pawnMask[player].set(pos);
41  }
42  }
43  assert(isConsistent(true));
44 }
45 
46 void osl::SimpleState::init() {
47  player_to_move=BLACK;
48  for (int ipos=0;ipos<Square::SIZE;ipos++) {
49  setBoard(Square::nth(ipos),Piece::EDGE());
50  }
51  for (int y=1;y<=9;y++)
52  for (int x=9;x>0;x--) {
53  setBoard(Square(x,y),Piece::EMPTY());
54  }
55  // promoteMask.clearAll();
56  stand_mask[BLACK].resetAll();
57  stand_mask[WHITE].resetAll();
58  stand_count[BLACK].fill(0);
59  stand_count[WHITE].fill(0);
60  used_mask.resetAll();
61  pawnMask[0].clearAll();
62  pawnMask[1].clearAll();
63  for (int num=0;num<Piece::SIZE;num++){
64  pieces[num]=Piece(WHITE,Piece_Table.getPtypeOf(num),num,Square::STAND());
65  }
66 }
67 
68 
69 void osl::SimpleState::init(Handicap h) {
70  init();
71  if (h != HIRATE) {
72  std::cerr << "unsupported handicap\n";
73  throw std::runtime_error("unsupported handicap");
74  }
75  // 歩
76  for (int x=9;x>0;x--) {
77  setPiece(BLACK,Square(x,7),PAWN);
78  setPiece(WHITE,Square(x,3),PAWN);
79  }
80  //
81  setPiece(BLACK,Square(1,9),LANCE);
82  setPiece(BLACK,Square(9,9),LANCE);
83  setPiece(WHITE,Square(1,1),LANCE);
84  setPiece(WHITE,Square(9,1),LANCE);
85  //
86  setPiece(BLACK,Square(2,9),KNIGHT);
87  setPiece(BLACK,Square(8,9),KNIGHT);
88  setPiece(WHITE,Square(2,1),KNIGHT);
89  setPiece(WHITE,Square(8,1),KNIGHT);
90  //
91  setPiece(BLACK,Square(3,9),SILVER);
92  setPiece(BLACK,Square(7,9),SILVER);
93  setPiece(WHITE,Square(3,1),SILVER);
94  setPiece(WHITE,Square(7,1),SILVER);
95  //
96  setPiece(BLACK,Square(4,9),GOLD);
97  setPiece(BLACK,Square(6,9),GOLD);
98  setPiece(WHITE,Square(4,1),GOLD);
99  setPiece(WHITE,Square(6,1),GOLD);
100  //
101  setPiece(BLACK,Square(5,9),KING);
102  setPiece(WHITE,Square(5,1),KING);
103  //
104  setPiece(BLACK,Square(8,8),BISHOP);
105  setPiece(WHITE,Square(2,2),BISHOP);
106  //
107  setPiece(BLACK,Square(2,8),ROOK);
108  setPiece(WHITE,Square(8,2),ROOK);
109 
110  initPawnMask();
111 }
112 
113 
114 osl::SimpleState::~SimpleState() {}
115 
116 void osl::SimpleState::setPiece(Player player,Square pos,Ptype ptype) {
117  int num;
118  for (num=0;num<40;num++) {
119  if (!used_mask.test(num) && Piece_Table.getPtypeOf(num)==unpromote(ptype)
120  && (ptype!=KING ||
122  used_mask.set(num);
123 
124  Piece p(player,ptype,num,pos);
125  setPieceOf(num,p);
126  if (pos.isPieceStand())
127  stand_mask[player].set(num);
128  else{
129  setBoard(pos,p);
130  if (ptype==PAWN)
131  pawnMask[player].set(pos);
132  }
133  return;
134  }
135  }
136  std::cerr << "osl::SimpleState::setPiece! maybe too many pieces "
137  << ptype << " " << pos << " " << player << "\n";
138  abort();
139 }
140 
141 void osl::SimpleState::setPieceAll(Player player) {
142  for (int num=0;num<40;num++) {
143  if (!used_mask.test(num)) {
144  used_mask.set(num);
145  stand_mask[player].set(num);
146  Player pplayer = player;
147  /* 片玉しかない問題のため */
149  {
150  pplayer=alt(player);
151  }
152  Piece p(pplayer,Piece_Table.getPtypeOf(num),num,Square::STAND());
153  setPieceOf(num,p);
154  }
155  }
156 }
157 
158 // check
159 bool osl::SimpleState::isConsistent(bool show_error) const
160 {
161  // board上の要素のconsistency
162  for (int y=1;y<=9;y++)
163  {
164  for (int x=9;x>=1;x--)
165  {
166  const Square pos(x,y);
167  const Piece p0=pieceAt(pos);
168  if (p0.isPiece())
169  {
170  if (p0.square()!=pos)
171  {
172  if (show_error) {
173  std::cerr << p0 << " must be put at " << pos << std::endl;
174  }
175  return false;
176  }
177  int num=p0.number();
178  if (! PieceTable::validNumber(num) || !used_mask.test(num)) {
179  if (show_error) std::cerr << "NotUsed, num=" << num << std::endl;
180  return false;
181  }
182  Piece p1=pieceOf(num);
183  if (p0!=p1) {
184  if (show_error) std::cerr << "board[" << pos << "]!="
185  << "piece[" << num << "]" << std::endl;
186  return false;
187  }
188  }
189  }
190  }
191  // piecesのconsistency
192  for (int num0=0; num0<Piece::SIZE; num0++)
193  {
194  if(!usedMask().test(num0)) continue;
195  if (isOnBoard(num0))
196  {
197  Piece p0=pieceOf(num0);
198  Ptype ptype=p0.ptype();
199  if (unpromote(ptype)!=Piece_Table.getPtypeOf(num0)) {
200  if (show_error) std::cerr << "ptype of piece[" << num0 << "]="
201  << ptype << std::endl;
202  return false;
203  }
204  if (!p0.isOnBoard()) {
205  if (show_error) std::cerr << "mochigoma[" << num0 << "]=true" << std::endl;
206  return false;
207  }
208  Square pos=p0.square();
209  if (!pos.isOnBoard()) {
210  if (show_error) std::cerr << "position " << pos << " is not onboard" << std::endl;
211  return false;
212  }
213  Piece p1=pieceAt(pos);
214  int num1=p1.number();
215  if (num0 !=num1) {
216  if (show_error) std::cerr << "pieces[" << num0 << "]=" << p0 << ",board[" << pos << "] is " << p1 << std::endl;
217  return false;
218  }
219  }
220  else
221  {
222  Piece p0=pieceOf(num0);
223  Ptype ptype=p0.ptype();
224 #ifdef ALLOW_KING_ABSENCE
225  if (p0.isEmpty() && Piece_Table.getPtypeOf(num0) == KING)
226  continue;
227 #endif
228  if (p0.number()!=num0) {
229  if (show_error)
230  std::cerr << "pieces[" << num0 << "] ("
231  << Piece_Table.getPtypeOf(num0) << ") ="
232  << p0 << std::endl;
233  return false;
234 
235  }
236  if (ptype!=Piece_Table.getPtypeOf(num0)) {
237  if (show_error) std::cerr << "ptype of piece[" << num0 << "]="
238  << ptype << std::endl;
239  return false;
240  }
241  if (! p0.square().isPieceStand()) {
242  if (show_error) std::cerr << p0 << " must be offboard" << std::endl;
243  return false;
244  }
245  }
246  }
247  // mask
248  BOOST_FOREACH(Ptype ptype, PieceStand::order) {
249  if (countPiecesOnStand(BLACK, ptype)
250  != countPiecesOnStandBit(BLACK, ptype)) {
251  if (show_error) std::cerr << "count stand BLACK " << ptype << " inconsistent\n"
252  << *this << countPiecesOnStand(BLACK, ptype)
253  << " " << countPiecesOnStandBit(BLACK, ptype) << std::endl;
254  return false;
255  }
256  if (countPiecesOnStand(WHITE, ptype)
257  != countPiecesOnStandBit(WHITE, ptype)) {
258  if (show_error) std::cerr << "count stand WHITE " << ptype << " inconsistent\n"
259  << *this << countPiecesOnStand(WHITE, ptype)
260  << " " << countPiecesOnStandBit(WHITE, ptype) << std::endl;
261  return false;
262  }
263  }
264  // pawnMask;
265  {
266  CArray<BitXmask,2> pawnMask1;
267  pawnMask1[0].clearAll();
268  pawnMask1[1].clearAll();
269  for (int num=PtypeTraits<PAWN>::indexMin;
270  num<PtypeTraits<PAWN>::indexLimit;num++){
271  if (isOnBoard(num)){
272  Piece p=pieceOf(num);
273  if (!p.isPromotedNotKingGold()){
274  pawnMask1[playerToIndex(p.owner())].set(p.square());
275  }
276  }
277  }
278  if ((pawnMask[0]!=pawnMask1[0])
279  || (pawnMask[1]!=pawnMask1[1]))
280  {
281  if (show_error)
282  std::cerr << "pawnMask "
283  << pawnMask[0] << "!=" << pawnMask1[0]
284  << " || " << pawnMask[1] << "!=" << pawnMask1[1]
285  << std::endl;
286  return false;
287  }
288  }
289  // illegal position for piece
290  for (int i=0; i<nthLimit<PAWN>(); ++i) {
291  const Piece pawn = nth<PAWN>(i);
292  if (! pawn.isPromoted() && pawn.isOnBoard()
293  && pawn.square().squareForBlack(pawn.owner()).y() == 1) {
294  if (show_error)
295  std::cerr << "pawn " << pawn << std::endl;
296  return false;
297  }
298  }
299  for (int i=0; i<nthLimit<LANCE>(); ++i) {
300  const Piece lance = nth<LANCE>(i);
301  if (! lance.isPromoted() && lance.isOnBoard()
302  && lance.square().squareForBlack(lance.owner()).y() == 1) {
303  if (show_error)
304  std::cerr << "lance " << lance << std::endl;
305  return false;
306  }
307  }
308  for (int i=0; i<nthLimit<KNIGHT>(); ++i) {
309  const Piece knight = nth<KNIGHT>(i);
310  if (! knight.isPromoted() && knight.isOnBoard()
311  && knight.square().squareForBlack(knight.owner()).y() == 1) {
312  if (show_error)
313  std::cerr << "knight " << knight << std::endl;
314  return false;
315  }
316  }
317  return true;
318 }
319 
320 bool osl::SimpleState::isAlmostValidMove(Move move,bool show_error) const
321 {
322  if (show_error)
323  {
324  const bool valid = isAlmostValidMove<true>(move);
325  if (! valid)
326  std::cerr << *this << " " << move << std::endl;
327  return valid;
328  }
329  else
330  return isAlmostValidMove<false>(move);
331 }
332 
333 template <bool show_error>
334 bool osl::SimpleState::isAlmostValidMove(Move move) const
335 {
336  assert(move.isValid());
337  assert(turn() == move.player());
338  assert(isValidMoveByRule(move, true));
339 
340  const Square from=move.from();
341  if (from.isPieceStand()) // 打つ手
342  return isAlmostValidDrop<show_error>(move);
343  const Square to=move.to();
344 
345  if (! testValidityOtherThanEffect<show_error>(move))
346  return false;
347 
348  const Piece from_piece = pieceAt(from);
349  // その offsetの動きがptypeに関してvalidか?
350  EffectContent effect=Ptype_Table.getEffect(from_piece.ptypeO(),from,to);
351  if (!effect.hasUnblockableEffect())
352  {
353  const Offset o=effect.offset();
354  if (o.zero()) {
355  if (show_error) {
356  std::cerr << " No such move2 : " << move << std::endl;
357  }
358  return false;
359  }
360  // 離れた動きの時に間が全部空いているか?
361  for (Square p=from+o;p!=to;p+=o) {
362  if (! pieceAt(p).isEmpty()) {
363  if (show_error)
364  std::cerr << " Not space to move : " << move << std::endl;
365  return false;
366  }
367  }
368  }
369 
370  assert(isValidMoveByRule(move, true));
371  return true;
372 }
373 
374 bool osl::SimpleState::isValidMoveByRule(Move move,bool show_error)
375 {
376  assert(move.isNormal());
377  const Square from=move.from();
378  const Square to=move.to();
379  const Ptype ptype=move.ptype();
380  const Player turn = move.player();
381 
382  if (from.isPieceStand()) // 打つ手
383  {
384  // 動けない場所ではないか?
385  if (! Ptype_Table.canDropTo(turn,ptype,to))
386  {
387  if (show_error) std::cerr << " can't drop to : " << move << std::endl;
388  return false;
389  }
390  }
391  else
392  {
393  if (isBasic(move.ptype()) && move.isPromotion())
394  {
395  if (show_error) std::cerr << " inconsistent promote " << move << std::endl;
396  return false;
397  }
398  const PtypeO old_ptypeo = move.oldPtypeO();
399  const EffectContent effect
400  = Ptype_Table.getEffect(old_ptypeo, Offset32(to,from));
401  // その offsetの動きがptypeに関してvalidか?
402  if (!effect.hasUnblockableEffect())
403  {
404  const Offset o = effect.offset();
405  if (o.zero()) {
406  if (show_error) {
407  std::cerr << " No such move1 : " << move << std::endl;
408  }
409  return false;
410  }
411  }
412  // promoteしている時にpromote可能か
413  if (move.isPromotion())
414  {
415  if (! (canPromote(unpromote(move.ptype()))
416  && (to.canPromote(move.player())
417  || from.canPromote(move.player()))))
418  {
419  if (show_error)
420  std::cerr << " illegal promote type or position : " << move << std::endl;
421  return false;
422  }
423  }
424  // promoteしていない時に強制promoteでないか?
425  if ((! isPromoted(ptype)
426  && ! Ptype_Table.canDropTo(turn,getPtype(old_ptypeo),to))
427  && !move.isPromotion())
428  {
429  if (show_error)
430  std::cerr << " must promote to this position : " << move << std::endl;
431  return false;
432  }
433  }
434  return true;
435 }
436 
437 bool osl::SimpleState::isValidMove(Move move,bool show_error) const
438 {
439  if (turn() != move.player()) {
440  if (show_error) {
441  std::cerr << "invalid player move : " << move << std::endl;
442  std::cerr << *this;
443  }
444  return false;
445  }
446  if (! isValidMoveByRule(move, show_error) || ! move.isValid())
447  return false;
448  return isAlmostValidMove(move, show_error);
449 }
450 
451 #ifndef MINIMAL
453 {
454  return std::cerr << *this << "\n";
455 }
456 #endif
457 
461 const osl::SimpleState
462 osl::SimpleState::emulateCapture(Piece from, Player new_owner) const {
463  osl::SimpleState newState;
464  for(int i=0;i<40;i++){
465  Piece p=pieceOf(i);
466  if(p==from){
467  newState.setPiece(new_owner,Square::STAND(),unpromote(p.ptype()));
468  }
469  else{
470  newState.setPiece(p.owner(),p.square(),p.ptype());
471  }
472  }
473  newState.setTurn(turn());
474  newState.initPawnMask();
475  return newState;
476 }
477 
481 const osl::SimpleState
482 osl::SimpleState::emulateHandPiece(Player from, Player to, Ptype ptype) const {
483  assert(hasPieceOnStand(from, ptype));
484  assert(from==alt(to));
485  osl::SimpleState newState;
486  bool done=false;
487  for(int i=0;i<40;i++){
488  if(!usedMask().test(i)) continue;
489  Piece p=pieceOf(i);
490  if(!done &&
491  p.owner()==from &&
492  !p.isOnBoard() &&
493  p.ptype()==ptype){
494  newState.setPiece(to,Square::STAND(),ptype);
495  done=true;
496  }
497  else{
498  newState.setPiece(p.owner(),p.square(),p.ptype());
499  }
500  }
501  assert(done);
502  newState.setTurn(turn());
503  newState.initPawnMask();
504  return newState;
505 }
506 
508 {
509  SimpleState ret;
510  for (int i=0; i<40; ++i) {
511  if(!usedMask().test(i)) continue;
512  const Piece p = pieceOf(i);
513  ret.setPiece(alt(p.owner()), p.square().rotate180Safe(), p.ptype());
514  }
515  ret.setTurn(alt(turn()));
516  ret.initPawnMask();
517  return ret;
518 }
519 
521 {
522  SimpleState ret;
523  for (int i=0; i<40; ++i) {
524  if(!usedMask().test(i)) continue;
525  const Piece p = pieceOf(i);
526  ret.setPiece(p.owner(), p.square().flipHorizontal(), p.ptype());
527  }
528  ret.setTurn(turn());
529  ret.initPawnMask();
530  return ret;
531 }
532 
533 bool osl::state::operator==(const SimpleState& st1,const SimpleState& st2)
534 {
535  assert(st1.isConsistent(false));
536  assert(st2.isConsistent(false));
537  if (st1.turn()!=st2.turn())
538  return false;
539  if (st1.pawnMask[0]!=st2.pawnMask[0]) return false;
540  if (st1.pawnMask[1]!=st2.pawnMask[1]) return false;
541  for (int y=1;y<=9;y++)
542  for (int x=9;x>0;x--) {
543  Piece p1=st1.pieceAt(Square(x,y));
544  Piece p2=st2.pieceAt(Square(x,y));
545  if (p1.ptypeO()!=p2.ptypeO()) return false;
546  }
547  return true;
548 
549 }
550 
551 namespace osl
552 {
553  namespace
554  {
555  void showStand(std::ostream& os, Player player, PieceStand stand)
556  {
557  using namespace osl::record;
558  if (! stand.any())
559  return;
560 
561  os << "P" << csa::show(player);
562  BOOST_FOREACH(Ptype ptype, PieceStand::order) {
563  for (unsigned int j=0; j<stand.get(ptype); ++j)
564  {
565  os << "00" << csa::show(ptype);
566  }
567  }
568  os << "\n";
569  }
570  } // anonymous namespace
571 } // namespace osl
572 
573 std::ostream& osl::state::operator<<(std::ostream& os,const SimpleState& state)
574 {
575  for (int y=1;y<=9;y++) {
576  os << 'P' << y;
577  for (int x=9;x>0;x--) {
578  csaShow(os,state.pieceOnBoard(Square(x,y)));
579  }
580  os << std::endl;
581  }
582  // 持ち駒の表示
583  const PieceStand black_stand(BLACK, state);
584  const PieceStand white_stand(WHITE, state);
585  showStand(os, BLACK, black_stand);
586  showStand(os, WHITE, white_stand);
587 
588  os << state.turn() << std::endl;
589  return os;
590 }
591 
592 // ;;; Local Variables:
593 // ;;; mode:c++
594 // ;;; c-basic-offset:2
595 // ;;; End: