00001
00002
00003
00004 #include "osl/simpleState.h"
00005 #include "osl/simpleState.tcc"
00006 #include "osl/csa.h"
00007 #include "osl/bits/pieceTable.h"
00008 #include "osl/bits/pieceStand.h"
00009 #include <iostream>
00010 #include <stdexcept>
00011
00012 osl::SimpleState::SimpleState() {
00013 init();
00014 }
00015
00016 osl::SimpleState::SimpleState(Handicap h) {
00017 init(h);
00018 }
00019
00020 void osl::SimpleState::initPawnMask(){
00021 for (Ptype ptype: PieceStand::order) {
00022 stand_count[BLACK][ptype - PTYPE_BASIC_MIN] = countPiecesOnStandBit(BLACK, ptype);
00023 stand_count[WHITE][ptype - PTYPE_BASIC_MIN] = countPiecesOnStandBit(WHITE, ptype);
00024 }
00025
00026 pawnMask[0].clearAll();
00027 pawnMask[1].clearAll();
00028 for(int num=PtypeTraits<PAWN>::indexMin;
00029 num< PtypeTraits<PAWN>::indexLimit; num++){
00030 Piece p=pieceOf(num);
00031 Player player=p.owner();
00032 Square pos=p.square();
00033 if(!pos.isPieceStand() && !p.isPromotedNotKingGold()){
00034 if (isPawnMaskSet(player,pos.x()))
00035 {
00036 throw CsaIOError("2FU!");
00037 }
00038 pawnMask[player].set(pos);
00039 }
00040 }
00041 assert(isConsistent(true));
00042 }
00043
00044 void osl::SimpleState::init() {
00045 player_to_move=BLACK;
00046 for (int ipos=0;ipos<Square::SIZE;ipos++) {
00047 setBoard(Square::nth(ipos),Piece::EDGE());
00048 }
00049 for (int y=1;y<=9;y++)
00050 for (int x=9;x>0;x--) {
00051 setBoard(Square(x,y),Piece::EMPTY());
00052 }
00053
00054 stand_mask[BLACK].resetAll();
00055 stand_mask[WHITE].resetAll();
00056 stand_count[BLACK].fill(0);
00057 stand_count[WHITE].fill(0);
00058 used_mask.resetAll();
00059 pawnMask[0].clearAll();
00060 pawnMask[1].clearAll();
00061 for (int num=0;num<Piece::SIZE;num++){
00062 pieces[num]=Piece(WHITE,Piece_Table.getPtypeOf(num),num,Square::STAND());
00063 }
00064 }
00065
00066
00067 void osl::SimpleState::init(Handicap h) {
00068 init();
00069 if (h != HIRATE) {
00070 std::cerr << "unsupported handicap\n";
00071 throw std::runtime_error("unsupported handicap");
00072 }
00073
00074 for (int x=9;x>0;x--) {
00075 setPiece(BLACK,Square(x,7),PAWN);
00076 setPiece(WHITE,Square(x,3),PAWN);
00077 }
00078
00079 setPiece(BLACK,Square(1,9),LANCE);
00080 setPiece(BLACK,Square(9,9),LANCE);
00081 setPiece(WHITE,Square(1,1),LANCE);
00082 setPiece(WHITE,Square(9,1),LANCE);
00083
00084 setPiece(BLACK,Square(2,9),KNIGHT);
00085 setPiece(BLACK,Square(8,9),KNIGHT);
00086 setPiece(WHITE,Square(2,1),KNIGHT);
00087 setPiece(WHITE,Square(8,1),KNIGHT);
00088
00089 setPiece(BLACK,Square(3,9),SILVER);
00090 setPiece(BLACK,Square(7,9),SILVER);
00091 setPiece(WHITE,Square(3,1),SILVER);
00092 setPiece(WHITE,Square(7,1),SILVER);
00093
00094 setPiece(BLACK,Square(4,9),GOLD);
00095 setPiece(BLACK,Square(6,9),GOLD);
00096 setPiece(WHITE,Square(4,1),GOLD);
00097 setPiece(WHITE,Square(6,1),GOLD);
00098
00099 setPiece(BLACK,Square(5,9),KING);
00100 setPiece(WHITE,Square(5,1),KING);
00101
00102 setPiece(BLACK,Square(8,8),BISHOP);
00103 setPiece(WHITE,Square(2,2),BISHOP);
00104
00105 setPiece(BLACK,Square(2,8),ROOK);
00106 setPiece(WHITE,Square(8,2),ROOK);
00107
00108 initPawnMask();
00109 }
00110
00111
00112 osl::SimpleState::~SimpleState() {}
00113
00114 void osl::SimpleState::setPiece(Player player,Square pos,Ptype ptype) {
00115 int num;
00116 for (num=0;num<40;num++) {
00117 if (!used_mask.test(num) && Piece_Table.getPtypeOf(num)==unpromote(ptype)
00118 && (ptype!=KING ||
00119 num==PtypeTraits<KING>::indexMin+playerToIndex(player))) {
00120 used_mask.set(num);
00121
00122 Piece p(player,ptype,num,pos);
00123 setPieceOf(num,p);
00124 if (pos.isPieceStand())
00125 stand_mask[player].set(num);
00126 else{
00127 setBoard(pos,p);
00128 if (ptype==PAWN)
00129 pawnMask[player].set(pos);
00130 }
00131 return;
00132 }
00133 }
00134 std::cerr << "osl::SimpleState::setPiece! maybe too many pieces "
00135 << ptype << " " << pos << " " << player << "\n";
00136 abort();
00137 }
00138
00139 void osl::SimpleState::setPieceAll(Player player) {
00140 for (int num=0;num<40;num++) {
00141 if (!used_mask.test(num)) {
00142 used_mask.set(num);
00143 stand_mask[player].set(num);
00144 Player pplayer = player;
00145
00146 if (num==PtypeTraits<KING>::indexMin+playerToIndex(alt(player)))
00147 {
00148 pplayer=alt(player);
00149 }
00150 Piece p(pplayer,Piece_Table.getPtypeOf(num),num,Square::STAND());
00151 setPieceOf(num,p);
00152 }
00153 }
00154 }
00155
00156
00157 bool osl::SimpleState::isConsistent(bool show_error) const
00158 {
00159
00160 for (int y=1;y<=9;y++)
00161 {
00162 for (int x=9;x>=1;x--)
00163 {
00164 const Square pos(x,y);
00165 const Piece p0=pieceAt(pos);
00166 if (p0.isPiece())
00167 {
00168 if (p0.square()!=pos)
00169 {
00170 if (show_error) {
00171 std::cerr << p0 << " must be put at " << pos << std::endl;
00172 }
00173 return false;
00174 }
00175 int num=p0.number();
00176 if (! PieceTable::validNumber(num) || !used_mask.test(num)) {
00177 if (show_error) std::cerr << "NotUsed, num=" << num << std::endl;
00178 return false;
00179 }
00180 Piece p1=pieceOf(num);
00181 if (p0!=p1) {
00182 if (show_error) std::cerr << "board[" << pos << "]!="
00183 << "piece[" << num << "]" << std::endl;
00184 return false;
00185 }
00186 }
00187 }
00188 }
00189
00190 for (int num0=0; num0<Piece::SIZE; num0++)
00191 {
00192 if(!usedMask().test(num0)) continue;
00193 if (isOnBoard(num0))
00194 {
00195 Piece p0=pieceOf(num0);
00196 Ptype ptype=p0.ptype();
00197 if (unpromote(ptype)!=Piece_Table.getPtypeOf(num0)) {
00198 if (show_error) std::cerr << "ptype of piece[" << num0 << "]="
00199 << ptype << std::endl;
00200 return false;
00201 }
00202 if (!p0.isOnBoard()) {
00203 if (show_error) std::cerr << "mochigoma[" << num0 << "]=true" << std::endl;
00204 return false;
00205 }
00206 Square pos=p0.square();
00207 if (!pos.isOnBoard()) {
00208 if (show_error) std::cerr << "position " << pos << " is not onboard" << std::endl;
00209 return false;
00210 }
00211 Piece p1=pieceAt(pos);
00212 int num1=p1.number();
00213 if (num0 !=num1) {
00214 if (show_error) std::cerr << "pieces[" << num0 << "]=" << p0 << ",board[" << pos << "] is " << p1 << std::endl;
00215 return false;
00216 }
00217 }
00218 else
00219 {
00220 Piece p0=pieceOf(num0);
00221 Ptype ptype=p0.ptype();
00222 #ifdef ALLOW_KING_ABSENCE
00223 if (p0.isEmpty() && Piece_Table.getPtypeOf(num0) == KING)
00224 continue;
00225 #endif
00226 if (p0.number()!=num0) {
00227 if (show_error)
00228 std::cerr << "pieces[" << num0 << "] ("
00229 << Piece_Table.getPtypeOf(num0) << ") ="
00230 << p0 << std::endl;
00231 return false;
00232
00233 }
00234 if (ptype!=Piece_Table.getPtypeOf(num0)) {
00235 if (show_error) std::cerr << "ptype of piece[" << num0 << "]="
00236 << ptype << std::endl;
00237 return false;
00238 }
00239 if (! p0.square().isPieceStand()) {
00240 if (show_error) std::cerr << p0 << " must be offboard" << std::endl;
00241 return false;
00242 }
00243 }
00244 }
00245
00246 for (Ptype ptype: PieceStand::order) {
00247 if (countPiecesOnStand(BLACK, ptype)
00248 != countPiecesOnStandBit(BLACK, ptype)) {
00249 if (show_error) std::cerr << "count stand BLACK " << ptype << " inconsistent\n"
00250 << *this << countPiecesOnStand(BLACK, ptype)
00251 << " " << countPiecesOnStandBit(BLACK, ptype) << std::endl;
00252 return false;
00253 }
00254 if (countPiecesOnStand(WHITE, ptype)
00255 != countPiecesOnStandBit(WHITE, ptype)) {
00256 if (show_error) std::cerr << "count stand WHITE " << ptype << " inconsistent\n"
00257 << *this << countPiecesOnStand(WHITE, ptype)
00258 << " " << countPiecesOnStandBit(WHITE, ptype) << std::endl;
00259 return false;
00260 }
00261 }
00262
00263 {
00264 CArray<BitXmask,2> pawnMask1;
00265 pawnMask1[0].clearAll();
00266 pawnMask1[1].clearAll();
00267 for (int num=PtypeTraits<PAWN>::indexMin;
00268 num<PtypeTraits<PAWN>::indexLimit;num++){
00269 if (isOnBoard(num)){
00270 Piece p=pieceOf(num);
00271 if (!p.isPromotedNotKingGold()){
00272 pawnMask1[playerToIndex(p.owner())].set(p.square());
00273 }
00274 }
00275 }
00276 if ((pawnMask[0]!=pawnMask1[0])
00277 || (pawnMask[1]!=pawnMask1[1]))
00278 {
00279 if (show_error)
00280 std::cerr << "pawnMask "
00281 << pawnMask[0] << "!=" << pawnMask1[0]
00282 << " || " << pawnMask[1] << "!=" << pawnMask1[1]
00283 << std::endl;
00284 return false;
00285 }
00286 }
00287
00288 for (int i=0; i<nthLimit<PAWN>(); ++i) {
00289 const Piece pawn = nth<PAWN>(i);
00290 if (! pawn.isPromoted() && pawn.isOnBoard()
00291 && pawn.square().squareForBlack(pawn.owner()).y() == 1) {
00292 if (show_error)
00293 std::cerr << "pawn " << pawn << std::endl;
00294 return false;
00295 }
00296 }
00297 for (int i=0; i<nthLimit<LANCE>(); ++i) {
00298 const Piece lance = nth<LANCE>(i);
00299 if (! lance.isPromoted() && lance.isOnBoard()
00300 && lance.square().squareForBlack(lance.owner()).y() == 1) {
00301 if (show_error)
00302 std::cerr << "lance " << lance << std::endl;
00303 return false;
00304 }
00305 }
00306 for (int i=0; i<nthLimit<KNIGHT>(); ++i) {
00307 const Piece knight = nth<KNIGHT>(i);
00308 if (! knight.isPromoted() && knight.isOnBoard()
00309 && knight.square().squareForBlack(knight.owner()).y() == 1) {
00310 if (show_error)
00311 std::cerr << "knight " << knight << std::endl;
00312 return false;
00313 }
00314 }
00315 return true;
00316 }
00317
00318 bool osl::SimpleState::isAlmostValidMove(Move move,bool show_error) const
00319 {
00320 if (show_error)
00321 {
00322 const bool valid = isAlmostValidMove<true>(move);
00323 if (! valid)
00324 std::cerr << *this << " " << move << std::endl;
00325 return valid;
00326 }
00327 else
00328 return isAlmostValidMove<false>(move);
00329 }
00330
00331 template <bool show_error>
00332 bool osl::SimpleState::isAlmostValidMove(Move move) const
00333 {
00334 assert(move.isValid());
00335 assert(turn() == move.player());
00336 assert(isValidMoveByRule(move, true));
00337
00338 const Square from=move.from();
00339 if (from.isPieceStand())
00340 return isAlmostValidDrop<show_error>(move);
00341 const Square to=move.to();
00342
00343 if (! testValidityOtherThanEffect<show_error>(move))
00344 return false;
00345
00346 const Piece from_piece = pieceAt(from);
00347
00348 EffectContent effect=Ptype_Table.getEffect(from_piece.ptypeO(),from,to);
00349 if (!effect.hasUnblockableEffect())
00350 {
00351 const Offset o=effect.offset();
00352 if (o.zero()) {
00353 if (show_error) {
00354 std::cerr << " No such move2 : " << move << std::endl;
00355 }
00356 return false;
00357 }
00358
00359 for (Square p=from+o;p!=to;p+=o) {
00360 if (! pieceAt(p).isEmpty()) {
00361 if (show_error)
00362 std::cerr << " Not space to move : " << move << std::endl;
00363 return false;
00364 }
00365 }
00366 }
00367
00368 assert(isValidMoveByRule(move, true));
00369 return true;
00370 }
00371
00372 bool osl::SimpleState::isValidMoveByRule(Move move,bool show_error)
00373 {
00374 assert(move.isNormal());
00375 const Square from=move.from();
00376 const Square to=move.to();
00377 const Ptype ptype=move.ptype();
00378 const Player turn = move.player();
00379
00380 if (from.isPieceStand())
00381 {
00382
00383 if (! Ptype_Table.canDropTo(turn,ptype,to))
00384 {
00385 if (show_error) std::cerr << " can't drop to : " << move << std::endl;
00386 return false;
00387 }
00388 }
00389 else
00390 {
00391 if (isBasic(move.ptype()) && move.isPromotion())
00392 {
00393 if (show_error) std::cerr << " inconsistent promote " << move << std::endl;
00394 return false;
00395 }
00396 const PtypeO old_ptypeo = move.oldPtypeO();
00397 const EffectContent effect
00398 = Ptype_Table.getEffect(old_ptypeo, Offset32(to,from));
00399
00400 if (!effect.hasUnblockableEffect())
00401 {
00402 const Offset o = effect.offset();
00403 if (o.zero()) {
00404 if (show_error) {
00405 std::cerr << " No such move1 : " << move << std::endl;
00406 }
00407 return false;
00408 }
00409 }
00410
00411 if (move.isPromotion())
00412 {
00413 if (! (canPromote(unpromote(move.ptype()))
00414 && (to.canPromote(move.player())
00415 || from.canPromote(move.player()))))
00416 {
00417 if (show_error)
00418 std::cerr << " illegal promote type or position : " << move << std::endl;
00419 return false;
00420 }
00421 }
00422
00423 if ((! isPromoted(ptype)
00424 && ! Ptype_Table.canDropTo(turn,getPtype(old_ptypeo),to))
00425 && !move.isPromotion())
00426 {
00427 if (show_error)
00428 std::cerr << " must promote to this position : " << move << std::endl;
00429 return false;
00430 }
00431 }
00432 return true;
00433 }
00434
00435 bool osl::SimpleState::isValidMove(Move move,bool show_error) const
00436 {
00437 if (turn() != move.player()) {
00438 if (show_error) {
00439 std::cerr << "invalid player move : " << move << std::endl;
00440 std::cerr << *this;
00441 }
00442 return false;
00443 }
00444 if (! isValidMoveByRule(move, show_error) || ! move.isValid())
00445 return false;
00446 return isAlmostValidMove(move, show_error);
00447 }
00448
00449 #ifndef MINIMAL
00450 bool osl::SimpleState::dump() const
00451 {
00452 return static_cast<bool>(std::cerr << *this << "\n");
00453 }
00454 #endif
00455
00459 const osl::SimpleState
00460 osl::SimpleState::emulateCapture(Piece from, Player new_owner) const {
00461 osl::SimpleState newState;
00462 for(int i=0;i<40;i++){
00463 Piece p=pieceOf(i);
00464 if(p==from){
00465 newState.setPiece(new_owner,Square::STAND(),unpromote(p.ptype()));
00466 }
00467 else{
00468 newState.setPiece(p.owner(),p.square(),p.ptype());
00469 }
00470 }
00471 newState.setTurn(turn());
00472 newState.initPawnMask();
00473 return newState;
00474 }
00475
00479 const osl::SimpleState
00480 osl::SimpleState::emulateHandPiece(Player from, Player to, Ptype ptype) const {
00481 assert(hasPieceOnStand(from, ptype));
00482 assert(from==alt(to));
00483 osl::SimpleState newState;
00484 bool done=false;
00485 for(int i=0;i<40;i++){
00486 if(!usedMask().test(i)) continue;
00487 Piece p=pieceOf(i);
00488 if(!done &&
00489 p.owner()==from &&
00490 !p.isOnBoard() &&
00491 p.ptype()==ptype){
00492 newState.setPiece(to,Square::STAND(),ptype);
00493 done=true;
00494 }
00495 else{
00496 newState.setPiece(p.owner(),p.square(),p.ptype());
00497 }
00498 }
00499 assert(done);
00500 newState.setTurn(turn());
00501 newState.initPawnMask();
00502 return newState;
00503 }
00504
00505 const osl::SimpleState osl::SimpleState::rotate180() const
00506 {
00507 SimpleState ret;
00508 for (int i=0; i<40; ++i) {
00509 if(!usedMask().test(i)) continue;
00510 const Piece p = pieceOf(i);
00511 ret.setPiece(alt(p.owner()), p.square().rotate180Safe(), p.ptype());
00512 }
00513 ret.setTurn(alt(turn()));
00514 ret.initPawnMask();
00515 return ret;
00516 }
00517
00518 const osl::SimpleState osl::SimpleState::flipHorizontal() const
00519 {
00520 SimpleState ret;
00521 for (int i=0; i<40; ++i) {
00522 if(!usedMask().test(i)) continue;
00523 const Piece p = pieceOf(i);
00524 ret.setPiece(p.owner(), p.square().flipHorizontal(), p.ptype());
00525 }
00526 ret.setTurn(turn());
00527 ret.initPawnMask();
00528 return ret;
00529 }
00530
00531 bool osl::operator==(const SimpleState& st1,const SimpleState& st2)
00532 {
00533 assert(st1.isConsistent(false));
00534 assert(st2.isConsistent(false));
00535 if (st1.turn()!=st2.turn())
00536 return false;
00537 if (st1.pawnMask[0]!=st2.pawnMask[0]) return false;
00538 if (st1.pawnMask[1]!=st2.pawnMask[1]) return false;
00539 for (int y=1;y<=9;y++)
00540 for (int x=9;x>0;x--) {
00541 Piece p1=st1.pieceAt(Square(x,y));
00542 Piece p2=st2.pieceAt(Square(x,y));
00543 if (p1.ptypeO()!=p2.ptypeO()) return false;
00544 }
00545 return true;
00546
00547 }
00548
00549 namespace osl
00550 {
00551 namespace
00552 {
00553 void showStand(std::ostream& os, Player player, PieceStand stand)
00554 {
00555 if (! stand.any())
00556 return;
00557
00558 os << "P" << csa::show(player);
00559 for (Ptype ptype: PieceStand::order) {
00560 for (unsigned int j=0; j<stand.get(ptype); ++j)
00561 {
00562 os << "00" << csa::show(ptype);
00563 }
00564 }
00565 os << "\n";
00566 }
00567 }
00568 }
00569
00570 std::ostream& osl::operator<<(std::ostream& os,const SimpleState& state)
00571 {
00572 for (int y=1;y<=9;y++) {
00573 os << 'P' << y;
00574 for (int x=9;x>0;x--) {
00575 os << csa::show(state.pieceOnBoard(Square(x,y)));
00576 }
00577 os << std::endl;
00578 }
00579
00580 const PieceStand black_stand(BLACK, state);
00581 const PieceStand white_stand(WHITE, state);
00582 showStand(os, BLACK, black_stand);
00583 showStand(os, WHITE, white_stand);
00584
00585 os << state.turn() << std::endl;
00586 return os;
00587 }
00588
00589
00590
00591
00592