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