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 return true;
00290 }
00291
00292 bool osl::SimpleState::isAlmostValidMove(Move move,bool show_error) const
00293 {
00294 if (show_error)
00295 {
00296 const bool valid = isAlmostValidMove<true>(move);
00297 if (! valid)
00298 std::cerr << *this << " " << move << std::endl;
00299 return valid;
00300 }
00301 else
00302 return isAlmostValidMove<false>(move);
00303 }
00304
00305 template <bool show_error>
00306 bool osl::SimpleState::isAlmostValidMove(Move move) const
00307 {
00308 assert(move.isValid());
00309 assert(turn() == move.player());
00310 assert(isValidMoveByRule(move, true));
00311
00312 const Square from=move.from();
00313 if (from.isPieceStand())
00314 return isAlmostValidDrop<show_error>(move);
00315 const Square to=move.to();
00316
00317 if (! testValidityOtherThanEffect<show_error>(move))
00318 return false;
00319
00320 const Piece from_piece = pieceAt(from);
00321
00322 EffectContent effect=Ptype_Table.getEffect(from_piece.ptypeO(),from,to);
00323 if (!effect.hasUnblockableEffect())
00324 {
00325 const Offset o=effect.offset();
00326 if (o.zero()) {
00327 if (show_error) {
00328 std::cerr << " No such move2 : " << move << std::endl;
00329 }
00330 return false;
00331 }
00332
00333 for (Square p=from+o;p!=to;p+=o) {
00334 if (! pieceAt(p).isEmpty()) {
00335 if (show_error)
00336 std::cerr << " Not space to move : " << move << std::endl;
00337 return false;
00338 }
00339 }
00340 }
00341
00342 assert(isValidMoveByRule(move, true));
00343 return true;
00344 }
00345
00346 bool osl::SimpleState::isValidMoveByRule(Move move,bool show_error)
00347 {
00348 assert(move.isNormal());
00349 const Square from=move.from();
00350 const Square to=move.to();
00351 const Ptype ptype=move.ptype();
00352 const Player turn = move.player();
00353
00354 if (from.isPieceStand())
00355 {
00356
00357 if (! Ptype_Table.canDropTo(turn,ptype,to))
00358 {
00359 if (show_error) std::cerr << " can't drop to : " << move << std::endl;
00360 return false;
00361 }
00362 }
00363 else
00364 {
00365 if (isBasic(move.ptype()) && move.isPromotion())
00366 {
00367 if (show_error) std::cerr << " inconsistent promote " << move << std::endl;
00368 return false;
00369 }
00370 const PtypeO old_ptypeo = move.oldPtypeO();
00371 const EffectContent effect
00372 = Ptype_Table.getEffect(old_ptypeo, Offset32(to,from));
00373
00374 if (!effect.hasUnblockableEffect())
00375 {
00376 const Offset o = effect.offset();
00377 if (o.zero()) {
00378 if (show_error) {
00379 std::cerr << " No such move1 : " << move << std::endl;
00380 }
00381 return false;
00382 }
00383 }
00384
00385 if (move.isPromotion())
00386 {
00387 if (! (canPromote(unpromote(move.ptype()))
00388 && (to.canPromote(move.player())
00389 || from.canPromote(move.player()))))
00390 {
00391 if (show_error)
00392 std::cerr << " illegal promote type or position : " << move << std::endl;
00393 return false;
00394 }
00395 }
00396
00397 if ((! isPromoted(ptype)
00398 && ! Ptype_Table.canDropTo(turn,getPtype(old_ptypeo),to))
00399 && !move.isPromotion())
00400 {
00401 if (show_error)
00402 std::cerr << " must promote to this position : " << move << std::endl;
00403 return false;
00404 }
00405 }
00406 return true;
00407 }
00408
00409 bool osl::SimpleState::isValidMove(Move move,bool show_error) const
00410 {
00411 if (turn() != move.player()) {
00412 if (show_error) {
00413 std::cerr << "invalid player move : " << move << std::endl;
00414 std::cerr << *this;
00415 }
00416 return false;
00417 }
00418 if (! isValidMoveByRule(move, show_error))
00419 return false;
00420 return isAlmostValidMove(move, show_error);
00421 }
00422
00423 #ifndef MINIMAL
00424 bool osl::SimpleState::dump() const
00425 {
00426 return std::cerr << *this << "\n";
00427 }
00428 #endif
00429
00433 const osl::SimpleState
00434 osl::SimpleState::emulateCapture(Piece from, Player new_owner) const {
00435 osl::SimpleState newState;
00436 for(int i=0;i<40;i++){
00437 Piece p=pieceOf(i);
00438 if(p==from){
00439 newState.setPiece(new_owner,Square::STAND(),unpromote(p.ptype()));
00440 }
00441 else{
00442 newState.setPiece(p.owner(),p.square(),p.ptype());
00443 }
00444 }
00445 newState.setTurn(turn());
00446 newState.initPawnMask();
00447 return newState;
00448 }
00449
00453 const osl::SimpleState
00454 osl::SimpleState::emulateHandPiece(Player from, Player to, Ptype ptype) const {
00455 assert(hasPieceOnStand(from, ptype));
00456 assert(from==alt(to));
00457 osl::SimpleState newState;
00458 bool done=false;
00459 for(int i=0;i<40;i++){
00460 if(!usedMask().test(i)) continue;
00461 Piece p=pieceOf(i);
00462 if(!done &&
00463 p.owner()==from &&
00464 !p.isOnBoard() &&
00465 p.ptype()==ptype){
00466 newState.setPiece(to,Square::STAND(),ptype);
00467 done=true;
00468 }
00469 else{
00470 newState.setPiece(p.owner(),p.square(),p.ptype());
00471 }
00472 }
00473 assert(done);
00474 newState.setTurn(turn());
00475 newState.initPawnMask();
00476 return newState;
00477 }
00478
00479 const osl::state::SimpleState osl::state::SimpleState::rotate180() const
00480 {
00481 SimpleState ret;
00482 for (int i=0; i<40; ++i) {
00483 if(!usedMask().test(i)) continue;
00484 const Piece p = pieceOf(i);
00485 ret.setPiece(alt(p.owner()), p.square().rotate180Safe(), p.ptype());
00486 }
00487 ret.setTurn(alt(turn()));
00488 ret.initPawnMask();
00489 return ret;
00490 }
00491
00492 const osl::state::SimpleState osl::state::SimpleState::flipHorizontal() const
00493 {
00494 SimpleState ret;
00495 for (int i=0; i<40; ++i) {
00496 if(!usedMask().test(i)) continue;
00497 const Piece p = pieceOf(i);
00498 ret.setPiece(p.owner(), p.square().flipHorizontal(), p.ptype());
00499 }
00500 ret.setTurn(turn());
00501 ret.initPawnMask();
00502 return ret;
00503 }
00504
00505 bool osl::state::operator==(const SimpleState& st1,const SimpleState& st2)
00506 {
00507 assert(st1.isConsistent(false));
00508 assert(st2.isConsistent(false));
00509 if (st1.turn()!=st2.turn())
00510 return false;
00511 if (st1.pawnMask[0]!=st2.pawnMask[0]) return false;
00512 if (st1.pawnMask[1]!=st2.pawnMask[1]) return false;
00513 for (int y=1;y<=9;y++)
00514 for (int x=9;x>0;x--) {
00515 Piece p1=st1.pieceAt(Square(x,y));
00516 Piece p2=st2.pieceAt(Square(x,y));
00517 if (p1.ptypeO()!=p2.ptypeO()) return false;
00518 }
00519 return true;
00520
00521 }
00522
00523 namespace osl
00524 {
00525 namespace
00526 {
00527 void showStand(std::ostream& os, Player player, PieceStand stand)
00528 {
00529 using namespace osl::record;
00530 if (! stand.any())
00531 return;
00532
00533 os << "P" << csa::show(player);
00534 BOOST_FOREACH(Ptype ptype, PieceStand::order) {
00535 for (unsigned int j=0; j<stand.get(ptype); ++j)
00536 {
00537 os << "00" << csa::show(ptype);
00538 }
00539 }
00540 os << "\n";
00541 }
00542 }
00543 }
00544
00545 std::ostream& osl::state::operator<<(std::ostream& os,const SimpleState& state)
00546 {
00547 for (int y=1;y<=9;y++) {
00548 os << 'P' << y;
00549 for (int x=9;x>0;x--) {
00550 csaShow(os,state.pieceOnBoard(Square(x,y)));
00551 }
00552 os << std::endl;
00553 }
00554
00555 const PieceStand black_stand(BLACK, state);
00556 const PieceStand white_stand(WHITE, state);
00557 showStand(os, BLACK, black_stand);
00558 showStand(os, WHITE, white_stand);
00559
00560 os << state.turn() << std::endl;
00561 return os;
00562 }
00563
00564
00565
00566
00567