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   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   // その offsetの動きがptypeに関してvalidか?
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     // その offsetの動きがptypeに関してvalidか?
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     // promoteしている時にpromote可能か
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     // promoteしていない時に強制promoteでないか?
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   } // anonymous namespace
00543 } // namespace osl
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 // ;;; Local Variables:
00565 // ;;; mode:c++
00566 // ;;; c-basic-offset:2
00567 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines