simpleState.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
4 #include "osl/state/simpleState.h"
5 #include "osl/state/simpleState.tcc"
6 #include "osl/record/csa.h"
7 #include "osl/record/csaIOError.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 ||
121 num==PtypeTraits<KING>::indexMin+playerToIndex(player))) {
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 /* 片玉しかない問題のため */
148 if (num==PtypeTraits<KING>::indexMin+playerToIndex(alt(player)))
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
452 bool osl::SimpleState::dump() const
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
507 const osl::state::SimpleState osl::state::SimpleState::rotate180() const
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
520 const osl::state::SimpleState osl::state::SimpleState::flipHorizontal() const
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: