00001
00002
00003
00004 #include "osl/state/simpleState.h"
00005 #include "osl/state/simpleState.tcc"
00006 #include "osl/apply_move/applyMove.h"
00007 #include "osl/record/csa.h"
00008 #include "osl/record/csaIOError.h"
00009 #include "osl/pieceTable.h"
00010 #include "osl/pieceStand.h"
00011 #include <boost/foreach.hpp>
00012 #include <iostream>
00013 #include <stdexcept>
00014
00015 osl::SimpleState::SimpleState() {
00016 init();
00017 }
00018
00019 osl::SimpleState::SimpleState(Handicap h) {
00020 init(h);
00021 }
00022
00023 void osl::SimpleState::initPawnMask(){
00024 BOOST_FOREACH(Ptype ptype, PieceStand::order) {
00025 stand_count[BLACK][ptype - PTYPE_BASIC_MIN] = countPiecesOnStandBit(BLACK, ptype);
00026 stand_count[WHITE][ptype - PTYPE_BASIC_MIN] = countPiecesOnStandBit(WHITE, ptype);
00027 }
00028
00029 pawnMask[0].clearAll();
00030 pawnMask[1].clearAll();
00031 for(int num=PtypeTraits<PAWN>::indexMin;
00032 num< PtypeTraits<PAWN>::indexLimit; num++){
00033 Piece p=getPieceOf(num);
00034 Player player=p.owner();
00035 Position pos=p.position();
00036 if(!pos.isPieceStand() && !p.isPromotedNotKingGold()){
00037 if (isPawnMaskSet(player,pos.x()))
00038 {
00039 throw CsaIOError("2FU!");
00040 }
00041 pawnMask[player].set(pos);
00042 }
00043 }
00044 assert(isConsistent(true));
00045 }
00046
00047 void osl::SimpleState::init() {
00048 turn=BLACK;
00049 for (int ipos=0;ipos<Position::SIZE;ipos++) {
00050 setBoard(Position::nth(ipos),Piece::EDGE());
00051 }
00052 for (int y=1;y<=9;y++)
00053 for (int x=9;x>0;x--) {
00054 setBoard(Position(x,y),Piece::EMPTY());
00055 }
00056
00057 stand_mask[BLACK].resetAll();
00058 stand_mask[WHITE].resetAll();
00059 stand_count[BLACK].fill(0);
00060 stand_count[WHITE].fill(0);
00061 used_mask.resetAll();
00062 pawnMask[0].clearAll();
00063 pawnMask[1].clearAll();
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,Position(x,7),PAWN);
00076 setPiece(WHITE,Position(x,3),PAWN);
00077 }
00078
00079 setPiece(BLACK,Position(1,9),LANCE);
00080 setPiece(BLACK,Position(9,9),LANCE);
00081 setPiece(WHITE,Position(1,1),LANCE);
00082 setPiece(WHITE,Position(9,1),LANCE);
00083
00084 setPiece(BLACK,Position(2,9),KNIGHT);
00085 setPiece(BLACK,Position(8,9),KNIGHT);
00086 setPiece(WHITE,Position(2,1),KNIGHT);
00087 setPiece(WHITE,Position(8,1),KNIGHT);
00088
00089 setPiece(BLACK,Position(3,9),SILVER);
00090 setPiece(BLACK,Position(7,9),SILVER);
00091 setPiece(WHITE,Position(3,1),SILVER);
00092 setPiece(WHITE,Position(7,1),SILVER);
00093
00094 setPiece(BLACK,Position(4,9),GOLD);
00095 setPiece(BLACK,Position(6,9),GOLD);
00096 setPiece(WHITE,Position(4,1),GOLD);
00097 setPiece(WHITE,Position(6,1),GOLD);
00098
00099 setPiece(BLACK,Position(5,9),KING);
00100 setPiece(WHITE,Position(5,1),KING);
00101
00102 setPiece(BLACK,Position(8,8),BISHOP);
00103 setPiece(WHITE,Position(2,2),BISHOP);
00104
00105 setPiece(BLACK,Position(2,8),ROOK);
00106 setPiece(WHITE,Position(8,2),ROOK);
00107
00108 initPawnMask();
00109 }
00110
00111
00112 osl::SimpleState::~SimpleState() {}
00113
00114 void osl::SimpleState::setPiece(Player player,Position 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,Position::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 Position pos(x,y);
00165 const Piece p0=getPieceAt(pos);
00166 if (p0.isPiece())
00167 {
00168 if (p0.position()!=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=getPieceOf(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 (isOnBoard(num0))
00193 {
00194 Piece p0=getPieceOf(num0);
00195 Ptype ptype=p0.ptype();
00196 if (unpromote(ptype)!=Piece_Table.getPtypeOf(num0)) {
00197 if (show_error) std::cerr << "ptype of piece[" << num0 << "]="
00198 << ptype << std::endl;
00199 return false;
00200 }
00201 if (!p0.isOnBoard()) {
00202 if (show_error) std::cerr << "mochigoma[" << num0 << "]=true" << std::endl;
00203 return false;
00204 }
00205 Position pos=p0.position();
00206 if (!pos.isOnBoard()) {
00207 if (show_error) std::cerr << "position " << pos << " is not onboard" << std::endl;
00208 return false;
00209 }
00210 Piece p1=getPieceAt(pos);
00211 int num1=p1.number();
00212 if (num0 !=num1) {
00213 if (show_error) std::cerr << "pieces[" << num0 << "]=" << p0 << ",board[" << pos << "] is " << p1 << std::endl;
00214 return false;
00215 }
00216 }
00217 else
00218 {
00219 Piece p0=getPieceOf(num0);
00220 Ptype ptype=p0.ptype();
00221 #ifdef ALLOW_KING_ABSENCE
00222 if (p0.isEmpty() && Piece_Table.getPtypeOf(num0) == KING)
00223 continue;
00224 #endif
00225 if (p0.number()!=num0) {
00226 if (show_error)
00227 std::cerr << "pieces[" << num0 << "] ("
00228 << Piece_Table.getPtypeOf(num0) << ") ="
00229 << p0 << std::endl;
00230 return false;
00231
00232 }
00233 if (ptype!=Piece_Table.getPtypeOf(num0)) {
00234 if (show_error) std::cerr << "ptype of piece[" << num0 << "]="
00235 << ptype << std::endl;
00236 return false;
00237 }
00238 if (! p0.position().isPieceStand()) {
00239 if (show_error) std::cerr << p0 << " must be offboard" << std::endl;
00240 return false;
00241 }
00242 }
00243 }
00244
00245 BOOST_FOREACH(Ptype ptype, PieceStand::order) {
00246 if (countPiecesOnStand(BLACK, ptype)
00247 != countPiecesOnStandBit(BLACK, ptype)) {
00248 if (show_error) std::cerr << "count stand BLACK " << ptype << " inconsistent\n"
00249 << *this << countPiecesOnStand(BLACK, ptype)
00250 << " " << countPiecesOnStandBit(BLACK, ptype) << std::endl;
00251 return false;
00252 }
00253 if (countPiecesOnStand(WHITE, ptype)
00254 != countPiecesOnStandBit(WHITE, ptype)) {
00255 if (show_error) std::cerr << "count stand WHITE " << ptype << " inconsistent\n"
00256 << *this << countPiecesOnStand(WHITE, ptype)
00257 << " " << countPiecesOnStandBit(WHITE, ptype) << std::endl;
00258 return false;
00259 }
00260 }
00261
00262 {
00263 CArray<BitXmask,2> pawnMask1;
00264 pawnMask1[0].clearAll();
00265 pawnMask1[1].clearAll();
00266 for (int num=PtypeTraits<PAWN>::indexMin;
00267 num<PtypeTraits<PAWN>::indexLimit;num++){
00268 if (isOnBoard(num)){
00269 Piece p=getPieceOf(num);
00270 if (!p.isPromotedNotKingGold()){
00271 pawnMask1[playerToIndex(p.owner())].set(p.position());
00272 }
00273 }
00274 }
00275 if ((pawnMask[0]!=pawnMask1[0])
00276 || (pawnMask[1]!=pawnMask1[1]))
00277 {
00278 if (show_error)
00279 std::cerr << "pawnMask "
00280 << pawnMask[0] << "!=" << pawnMask1[0]
00281 << " || " << pawnMask[1] << "!=" << pawnMask1[1]
00282 << std::endl;
00283 return false;
00284 }
00285 }
00286 return true;
00287 }
00288
00289 bool osl::SimpleState::isAlmostValidMove(Move move,bool show_error) const
00290 {
00291 if (show_error)
00292 {
00293 const bool valid = isAlmostValidMove<true>(move);
00294 if (! valid)
00295 std::cerr << *this << " " << move << std::endl;
00296 return valid;
00297 }
00298 else
00299 return isAlmostValidMove<false>(move);
00300 }
00301
00302 template <bool show_error>
00303 bool osl::SimpleState::isAlmostValidMove(Move move) const
00304 {
00305 assert(move.isValid());
00306 assert(getTurn() == move.player());
00307 assert(isValidMoveByRule(move, true));
00308
00309 const Position from=move.from();
00310 const Position to=move.to();
00311 const Piece toPiece=getPieceAt(to);
00312 const Ptype ptype=move.ptype();
00313 const Player turn = move.player();
00314
00315 if (from.isPieceStand())
00316 {
00317
00318 if (! toPiece.isEmpty()) {
00319 if (show_error) std::cerr << "drop on to piece : " << move << std::endl;
00320 return false;
00321 }
00322
00323 if (! hasPieceOnStand(turn,ptype)) {
00324 if (show_error) std::cerr << turn << " don't have : " << ptype << std::endl;
00325 return false;
00326 }
00327
00328 if (ptype==PAWN && isPawnMaskSet(turn, to.x())) {
00329 if (show_error) std::cerr << " Double Pawn : " << move << std::endl;
00330 return false;
00331 }
00332 }
00333 else
00334 {
00335 const Piece from_piece = getPieceAt(from);
00336
00337 if (from_piece.isEmpty()
00338 || (from_piece.owner() != turn))
00339 {
00340 if (show_error)
00341 std::cerr << " No such piece0 : " << move << std::endl;
00342 return false;
00343 }
00344
00345 if (move.isPromote())
00346 {
00347
00348 if (from_piece.ptype() != unpromote(move.ptype()))
00349 {
00350 if (show_error)
00351 std::cerr << " No such piece1 : " << move << std::endl;
00352 return false;
00353 }
00354 if (from_piece.isPromotedNotKingGold())
00355 {
00356 if (show_error)
00357 std::cerr << " can't promote promoted piece : " << move << std::endl;
00358 return false;
00359 }
00360 }
00361 else
00362 {
00363
00364 if (from_piece.ptype() != move.ptype())
00365 {
00366 if (show_error)
00367 std::cerr << " No such piece2 : " << move << std::endl;
00368 return false;
00369 }
00370 }
00371
00372 if (!toPiece.isEmpty() && toPiece.owner()==turn) {
00373 if (show_error) std::cerr << " No move on : " << move << std::endl;
00374 return false;
00375 }
00376
00377 EffectContent effect=Ptype_Table.getEffect(from_piece.ptypeO(),from,to);
00378 if (!effect.hasUnblockableEffect())
00379 {
00380 const Offset o=effect.offset();
00381 if (o.zero()) {
00382 if (show_error) {
00383 std::cerr << " No such move2 : " << move << std::endl;
00384 }
00385 return false;
00386 }
00387
00388 for (Position p=from+o;p!=to;p+=o) {
00389 if (! getPieceAt(p).isEmpty()) {
00390 if (show_error)
00391 std::cerr << " Not space to move : " << move << std::endl;
00392 return false;
00393 }
00394 }
00395 }
00396
00397 if (toPiece.ptype()!=move.capturePtype()) {
00398 if (show_error) std::cerr << " Not such capture : " << move
00399 << std::endl << *this;
00400 return false;
00401 }
00402 }
00403
00404 assert(isValidMoveByRule(move, true));
00405 return true;
00406 }
00407
00408 bool osl::SimpleState::isValidMoveByRule(Move move,bool show_error) const
00409 {
00410 assert(move.isNormal());
00411 const Position from=move.from();
00412 const Position to=move.to();
00413 const Ptype ptype=move.ptype();
00414 const Player turn = move.player();
00415
00416 if (from.isPieceStand())
00417 {
00418
00419 if (! Ptype_Table.canDropTo(turn,ptype,to))
00420 {
00421 if (show_error) std::cerr << " can't drop to : " << move << std::endl;
00422 return false;
00423 }
00424 }
00425 else
00426 {
00427 const PtypeO old_ptypeo = move.oldPtypeO();
00428 const EffectContent effect
00429 = Ptype_Table.getEffect(old_ptypeo, Offset32(to,from));
00430
00431 if (!effect.hasUnblockableEffect())
00432 {
00433 const Offset o = effect.offset();
00434 if (o.zero()) {
00435 if (show_error) {
00436 std::cerr << " No such move1 : " << move << std::endl;
00437 }
00438 return false;
00439 }
00440 }
00441
00442 if (move.isPromote())
00443 {
00444 if (! (canPromote(unpromote(move.ptype()))
00445 && (to.canPromote(move.player())
00446 || from.canPromote(move.player()))))
00447 {
00448 if (show_error)
00449 std::cerr << " illegal promote type or position : " << move << std::endl;
00450 return false;
00451 }
00452 }
00453
00454 if ((! isPromoted(ptype)
00455 && ! Ptype_Table.canDropTo(turn,getPtype(old_ptypeo),to))
00456 && !move.isPromote())
00457 {
00458 if (show_error)
00459 std::cerr << " must promote to this position : " << move << std::endl;
00460 return false;
00461 }
00462 }
00463 return true;
00464 }
00465
00466 bool osl::SimpleState::isValidMove(Move move,bool show_error) const
00467 {
00468 if (getTurn() != move.player()) {
00469 if (show_error) {
00470 std::cerr << "invalid player move : " << move << std::endl;
00471 std::cerr << *this;
00472 }
00473 return false;
00474 }
00475 if (! isValidMoveByRule(move, show_error))
00476 return false;
00477 return isAlmostValidMove(move, show_error);
00478 }
00479
00480 #ifndef MINIMAL
00481 bool osl::SimpleState::dump() const
00482 {
00483 return std::cerr << *this << "\n";
00484 }
00485 #endif
00486
00487 void osl::SimpleState::doSimpleMove(Position from, Position to, int promoteMask)
00488 {
00489 Piece oldPiece;
00490 int num;
00491 if(getTurn()==BLACK) {
00492 apply_move::ApplyDoUndoSimpleMove<BLACK,SimpleState>::
00493 prologue(*this, from, to, promoteMask, oldPiece, num);
00494 }
00495 else{
00496 apply_move::ApplyDoUndoSimpleMove<WHITE,SimpleState>::
00497 prologue(*this, from, to, promoteMask, oldPiece, num);
00498 }
00499 if (promoteMask!=0 && num<PtypeTraits<PAWN>::indexLimit)
00500 clearPawn(getTurn(), from);
00501 }
00502
00503 void osl::SimpleState::doDropMove(Position to,Ptype ptype)
00504 {
00505 Piece oldPiece;
00506 int num, numIndex, numLow;
00507 if(getTurn()==BLACK) {
00508 apply_move::ApplyDoUndoDropMove<BLACK,SimpleState>::
00509 prologue(*this, ptype, to, oldPiece, num, numIndex, numLow);
00510 }
00511 else{
00512 apply_move::ApplyDoUndoDropMove<WHITE,SimpleState>::
00513 prologue(*this, ptype, to, oldPiece, num, numIndex, numLow);
00514 }
00515 if (ptype==PAWN)
00516 setPawn(getTurn(),to);
00517 }
00518
00519 void osl::SimpleState::doCaptureMove(Position from, Position to, Piece target,int promoteMask)
00520
00521 {
00522 Piece oldPiece;
00523 int num0, num1;
00524 int num1Index;
00525 mask_t num1Mask;
00526 Ptype capturePtype;
00527 if(getTurn()==BLACK) {
00528 apply_move::ApplyDoUndoCaptureMove<BLACK,SimpleState>::
00529 prologue(*this, from, to, target, promoteMask,
00530 capturePtype, oldPiece, num0, num1, num1Index, num1Mask);
00531 }
00532 else{
00533 apply_move::ApplyDoUndoCaptureMove<WHITE,SimpleState>::
00534 prologue(*this, from, to, target, promoteMask,
00535 capturePtype, oldPiece, num0, num1, num1Index, num1Mask);
00536 }
00537 if (capturePtype==PAWN)
00538 clearPawn(alt(getTurn()),to);
00539 if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
00540 clearPawn(getTurn(),from);
00541 }
00542
00546 const osl::SimpleState
00547 osl::SimpleState::emulateCapture(Piece from, Player new_owner) const {
00548 osl::SimpleState newState;
00549 for(int i=0;i<40;i++){
00550 Piece p=getPieceOf(i);
00551 if(p==from){
00552 newState.setPiece(new_owner,Position::STAND(),unpromote(p.ptype()));
00553 }
00554 else{
00555 newState.setPiece(p.owner(),p.position(),p.ptype());
00556 }
00557 }
00558 newState.setTurn(getTurn());
00559 newState.initPawnMask();
00560 return newState;
00561 }
00562
00566 const osl::SimpleState
00567 osl::SimpleState::emulateHandPiece(Player from, Player to, Ptype ptype) const {
00568 assert(hasPieceOnStand(from, ptype));
00569 assert(from==alt(to));
00570 osl::SimpleState newState;
00571 bool done=false;
00572 for(int i=0;i<40;i++){
00573 Piece p=getPieceOf(i);
00574 if(!done &&
00575 p.owner()==from &&
00576 !p.isOnBoard() &&
00577 p.ptype()==ptype){
00578 newState.setPiece(to,Position::STAND(),ptype);
00579 done=true;
00580 }
00581 else{
00582 newState.setPiece(p.owner(),p.position(),p.ptype());
00583 }
00584 }
00585 assert(done);
00586 newState.setTurn(getTurn());
00587 newState.initPawnMask();
00588 return newState;
00589 }
00590
00591 const osl::state::SimpleState osl::state::SimpleState::rotate180() const
00592 {
00593 SimpleState ret;
00594 for (int i=0; i<40; ++i) {
00595 const Piece p = getPieceOf(i);
00596 ret.setPiece(alt(p.owner()), p.position().rotate180Safe(), p.ptype());
00597 }
00598 ret.setTurn(alt(getTurn()));
00599 ret.initPawnMask();
00600 return ret;
00601 }
00602
00603 const osl::state::SimpleState osl::state::SimpleState::flipHorizontal() const
00604 {
00605 SimpleState ret;
00606 for (int i=0; i<40; ++i) {
00607 const Piece p = getPieceOf(i);
00608 ret.setPiece(p.owner(), p.position().flipHorizontal(), p.ptype());
00609 }
00610 ret.setTurn(getTurn());
00611 ret.initPawnMask();
00612 return ret;
00613 }
00614
00615 bool osl::state::operator==(const SimpleState& st1,const SimpleState& st2)
00616 {
00617 assert(st1.isConsistent(false));
00618 assert(st2.isConsistent(false));
00619 if (st1.turn!=st2.turn)
00620 return false;
00621 if (st1.pawnMask[0]!=st2.pawnMask[0]) return false;
00622 if (st1.pawnMask[1]!=st2.pawnMask[1]) return false;
00623 for (int y=1;y<=9;y++)
00624 for (int x=9;x>0;x--) {
00625 Piece p1=st1.getPieceAt(Position(x,y));
00626 Piece p2=st2.getPieceAt(Position(x,y));
00627 if (p1.ptypeO()!=p2.ptypeO()) return false;
00628 }
00629 return true;
00630
00631 }
00632
00633 namespace osl
00634 {
00635 namespace
00636 {
00637 void showStand(std::ostream& os, Player player, PieceStand stand)
00638 {
00639 using namespace osl::record;
00640 if (! stand.any())
00641 return;
00642
00643 os << "P" << csa::show(player);
00644 BOOST_FOREACH(Ptype ptype, PieceStand::order) {
00645 for (unsigned int j=0; j<stand.get(ptype); ++j)
00646 {
00647 os << "00" << csa::show(ptype);
00648 }
00649 }
00650 os << "\n";
00651 }
00652 }
00653 }
00654
00655 std::ostream& osl::state::operator<<(std::ostream& os,const SimpleState& state)
00656 {
00657 for (int y=1;y<=9;y++) {
00658 os << 'P' << y;
00659 for (int x=9;x>0;x--) {
00660 csaShow(os,state.getPieceOnBoard(Position(x,y)));
00661 }
00662 os << std::endl;
00663 }
00664
00665 const PieceStand black_stand(BLACK, state);
00666 const PieceStand white_stand(WHITE, state);
00667 showStand(os, BLACK, black_stand);
00668 showStand(os, WHITE, white_stand);
00669
00670 os << state.getTurn() << std::endl;
00671 return os;
00672 }
00673
00674
00675
00676
00677