simpleState.cc
Go to the documentation of this file.
00001 /* simpleState.cc
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   //  promoteMask.clearAll();
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 // check
00159 bool osl::SimpleState::isConsistent(bool show_error) const
00160 {
00161   // board上の要素のconsistency
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   // piecesのconsistency
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   // mask
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   // pawnMask;
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   // illegal position for piece
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   // その offsetの動きがptypeに関してvalidか?
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     // その offsetの動きがptypeに関してvalidか?
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     // promoteしている時にpromote可能か
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     // promoteしていない時に強制promoteでないか?
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   } // anonymous namespace
00571 } // namespace osl
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 // ;;; Local Variables:
00593 // ;;; mode:c++
00594 // ;;; c-basic-offset:2
00595 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines