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