proofNumberTable.cc
Go to the documentation of this file.
00001 /* proofNumberTable.cc
00002  */
00003 #include "osl/checkmate/proofNumberTable.h"
00004 #include "osl/checkmate/immediateCheckmate.h"
00005 #include "osl/effect_util/neighboring8Direct.h"
00006 #include "osl/boardTable.h"
00007 #include "osl/ptypeTable.h"
00008 
00009 namespace
00010 {
00011   using namespace osl;
00012   using namespace osl::checkmate;
00016   const osl::checkmate::ProofNumberTable::Liberty
00017   effectiveCheckShort(Ptype ptype,Direction dir,unsigned int mask)
00018   {
00019     assert(isShort(dir));
00020     // 王は8近傍に移動できない
00021     if (ptype==KING) 
00022       return ProofNumberTable::Liberty(0,false);
00023     // ptypeがdir方向に利きを持たない場合も空王手の場合があるので作成
00024     const bool has_effect 
00025       = (Ptype_Table.getMoveMask(ptype)
00026          & (dirToMask(dir) | dirToMask(shortToLong(dir))));
00027     int dx=Board_Table.getDxForBlack(dir);
00028     int dy=Board_Table.getDyForBlack(dir);
00029     int count = 0;
00030     for (int l=0;l<8;l++) {
00031       if ((mask&(1<<l))==0) 
00032         continue;
00033       Direction dir1=static_cast<Direction>(l);
00034       int dx1=Board_Table.getDxForBlack(dir1);
00035       int dy1=Board_Table.getDyForBlack(dir1);
00036       Offset32 o32(dx-dx1,dy-dy1);
00037       if ((dx != dx1 || dy != dy1)
00038           && !Ptype_Table.getEffect(newPtypeO(BLACK,ptype),o32).hasEffect())
00039         ++count;
00040     }
00041     return ProofNumberTable::Liberty(std::max(count,1), has_effect);
00042   }
00043   const osl::checkmate::ProofNumberTable::Liberty
00044   effectiveCheckLong(Ptype ptype,Direction dir,unsigned int mask)
00045   {
00046     assert(isLong(dir));
00047     // ptypeがdir方向に利きを持たなくても2マス離れた空王手で8近傍に
00048     // 利きが増える場合があるので作成
00049     const bool has_effect 
00050       = (Ptype_Table.getMoveMask(ptype) & dirToMask(dir));
00051     int dx=Board_Table.getDxForBlack(dir)*2; // 1マス遠くから
00052     int dy=Board_Table.getDyForBlack(dir)*2;
00053     int count = 0;
00054     for (int l=0;l<8;l++) {
00055       if ((mask&(1<<l))==0) 
00056         continue;
00057       Direction dir1=static_cast<Direction>(l);
00058       int dx1=Board_Table.getDxForBlack(dir1);
00059       int dy1=Board_Table.getDyForBlack(dir1);
00060       Offset32 o32(dx-dx1,dy-dy1);
00061       if (!Ptype_Table.getEffect(newPtypeO(BLACK,ptype),o32).hasEffect())
00062         ++count;
00063     }
00064     return ProofNumberTable::Liberty(std::max(count,1), has_effect);
00065   }
00066 }
00067 
00068 osl::checkmate::
00069 ProofNumberTable::Table::Table()
00070 {
00071 }
00072 
00073 osl::checkmate::
00074 ProofNumberTable::ProofNumberTable()
00075   : table(new Table())
00076 {
00077   // liberties
00078   for (int i=0; i<0x100; i++) {
00079     for (int k=PTYPE_PIECE_MIN; k<=PTYPE_MAX; k++) {
00080       const Ptype ptype=static_cast<Ptype>(k);
00081       assert(isPiece(ptype));
00082       for (int j=0; j<8; j++) {
00083         Direction dir=static_cast<Direction>(j);
00084         const Liberty e = effectiveCheckShort(ptype,dir,i);
00085         table->liberties[i][k][j] = e;
00086       }
00087       int longs = 0;
00088       for (int j=LONG_DIRECTION_MIN; j<=LONG_DIRECTION_MAX; ++j,++longs) {
00089         Direction dir=static_cast<Direction>(j);
00090         const Liberty e = effectiveCheckLong(ptype,dir,i);
00091         table->liberties[i][k][j] = e;
00092       }
00093       assert(longs == 8);
00094     }
00095   }
00096   // drop_liberty
00097   table->drop_liberty.fill(0);
00098   for(int i=0;i<0x10000;i++){
00099     const unsigned int liberty = (i>>8)&0xff;
00100     const int liberty_count = misc::BitOp::countBit(liberty);
00101     if (liberty_count <= 2)
00102       continue;                 // low enough
00103     
00104     for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00105       int minimum_liberty = liberty_count;
00106       Ptype ptype=static_cast<Ptype>(k);
00107       if (ptype == KING)
00108         continue;
00109       for (int j=0;j<8;j++) {
00110         // 有効王手でない
00111         if ((i&(0x1<<j))==0) 
00112           continue;
00113         if ((i&(0x100<<j))!=0)
00114           continue;
00115         const Direction dir=static_cast<Direction>(j);
00116         // ptypeがdir方向に利きを持つか
00117         const bool has_effect 
00118           = (Ptype_Table.getMoveMask(ptype)
00119              & (dirToMask(dir) | dirToMask(shortToLong(dir))));
00120         if (! has_effect)
00121           continue;
00122         const int e = table->liberties[liberty][k][j].liberty;
00123         assert(e);
00124         minimum_liberty = std::min(minimum_liberty, e);
00125       }
00126       for (int l=minimum_liberty; l<liberty_count; ++l)
00127       {
00128         table->drop_liberty[i][l] |= (1<<(ptype-GOLD));
00129       }
00130     }
00131   }
00132   // pmajor_liberty
00133   table->pmajor_liberty.fill(8);
00134   for (int l=0; l<0x100; l++) { // liberty
00135     for (int m=0; m<0x100; m++) {       // move_mask
00136       if (l & m)
00137         continue;
00138       int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00139       if (min_liberty > 1)
00140       {
00141         for (int j=0; j<8; j++) {
00142           if ((m&(0x1<<j))==0)
00143             continue;
00144           const int pr = table->liberties[l][PROOK][j].liberty;
00145           const int pb = table->liberties[l][PBISHOP][j].liberty;
00146           min_liberty = std::min(min_liberty, std::min(pr,pb));
00147           assert(min_liberty);
00148         }
00149       }
00150       table->pmajor_liberty[l][m] = min_liberty;
00151     }
00152   }
00153   // promote_liberty
00154   table->promote_liberty.fill(8);
00155   for (int l=0; l<0x100; l++) { // liberty
00156     for (int m=0; m<0x100; m++) {       // move_mask
00157       if (l & m)
00158         continue;
00159       int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00160       if (min_liberty > 1)
00161       {
00162         for (int j=0; j<8; j++) {
00163           if ((m&(0x1<<j))==0)
00164             continue;
00165           for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00166             Ptype ptype=static_cast<Ptype>(k);
00167             if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
00168               continue;
00169             Liberty e = table->liberties[l][k][j];
00170             if (! e.has_effect)
00171               continue;
00172             assert(e.liberty); 
00173             min_liberty = std::min(min_liberty, (int)e.liberty);
00174             assert(min_liberty);
00175           }
00176         }
00177       }
00178       table->promote_liberty[l][m] = min_liberty;
00179     }
00180   }
00181   // other_move_liberty
00182   table->other_move_liberty.fill(8);
00183   for (int l=0; l<0x100; l++) { // liberty
00184     for (int m=0; m<0x100; m++) {       // move_mask
00185       if (l & m)
00186         continue;
00187       int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00188       if (min_liberty > 1)
00189       {
00190         for (int j=0; j<8; j++) {
00191           if ((m&(0x1<<j))==0)
00192             continue;
00193           for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00194             Ptype ptype=static_cast<Ptype>(k);
00195             if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
00196               continue;
00197             if (j == U 
00198                 && (ptype == GOLD || ptype == PPAWN || ptype == PLANCE
00199                     || ptype == PKNIGHT || ptype == PSILVER))
00200               continue;
00201             Liberty e = table->liberties[l][k][j];
00202             if (! e.has_effect)
00203               continue;
00204             assert(e.liberty); 
00205             min_liberty = std::min(min_liberty, (int)e.liberty);
00206             assert(min_liberty);
00207           }
00208         }
00209       }
00210       table->other_move_liberty[l][m] = min_liberty;
00211     }
00212   }
00213 }
00214 
00215 int osl::checkmate::
00216 ProofNumberTable::countLiberty(const NumEffectState& state, Move move) const
00217 {
00218   const Player attack = move.player();
00219   const Square king = state.kingSquare(alt(attack));
00220   const King8Info info(state.Iking8Info(alt(attack)));
00221   return countLiberty(state, info.libertyCount(), move, king, info);
00222 }
00223 
00224 int osl::checkmate::
00225 ProofNumberTable::libertyAfterAllDrop(const NumEffectState& state, Player attack,
00226                                       King8Info info) const
00227 {
00228   assert(state.turn() == attack);
00229   int result = info.libertyCount()-1;
00230   if (result < 2)
00231     return 1;
00232   const unsigned int ld_mask = info.libertyDropMask();
00233   uint8_t ptype_mask = 0;
00234   for (int p=GOLD; p<=ROOK; ++p)
00235     ptype_mask |= state.hasPieceOnStand(attack, static_cast<Ptype>(p)) << (p-GOLD);
00236   for (; 
00237        result > 1
00238          && (ptype_mask & table->drop_liberty[ld_mask][result-1]);
00239        --result)
00240   {
00241   }
00242   return result;        
00243 }
00244 
00245 int osl::checkmate::
00246 ProofNumberTable::libertyAfterAllDrop(const NumEffectState& state) const
00247 {
00248   const Player attack = state.turn();
00249   const King8Info info(state.Iking8Info(alt(attack)));
00250   return libertyAfterAllDrop(state, attack, info);
00251 }
00252 
00253 int osl::checkmate::
00254 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state,
00255                                       Player attack,
00256                                       King8Info info, Square king) const
00257 {
00258   bool has_pmajor = false;
00259   {
00260     for (int i = PtypeTraits<BISHOP>::indexMin;
00261          i < PtypeTraits<ROOK>::indexLimit; i++)
00262     {
00263       // move maskを見て8マス調べる方が良いか?
00264       const Piece p = state.pieceOf(i);
00265       assert(isMajor(p.ptype()));
00266       if (! p.isOnBoardByOwner(attack))
00267         continue;
00268       if (king.squareForBlack(attack).y() > 3 // 1段おまけ
00269           && ! isPromoted(p.ptype()))
00270       {
00271         if (! p.square().canPromote(attack))
00272           continue;
00273       }
00274       if (Neighboring8Direct::hasEffect(state, p.ptypeO(), p.square(),
00275                                         king))
00276       {
00277         // 本当はそこにbitが立っているかを判定したい.
00278         has_pmajor = true;
00279         break;
00280       }
00281     }
00282   }
00283   int moveCandidate;
00284   if(attack==BLACK)
00285     moveCandidate = info.moveCandidateMask<BLACK>(state);
00286   else
00287     moveCandidate = info.moveCandidateMask<WHITE>(state);
00288   if (has_pmajor)
00289   {
00290     int result = table->pmajor_liberty[info.liberty()][moveCandidate];
00291     assert(result);
00292     return result;
00293   }
00294   bool promoted_area = king.squareForBlack(attack).y() < 3;
00295   if (! promoted_area)
00296   {
00297     const Square u = king + Board_Table.getOffset(alt(attack), U);
00298     promoted_area = state.hasEffectByPtype<GOLD>(attack, u);
00299   }
00300   if (promoted_area)
00301   {
00302     int result = table->promote_liberty[info.liberty()][moveCandidate];
00303     assert(result);
00304     return result;
00305   }
00306   int result = table->other_move_liberty[info.liberty()][moveCandidate];
00307   assert(result);
00308   return result;
00309 }
00310 
00311 int osl::checkmate::
00312 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state) const
00313 {
00314   const Player attack = state.turn();
00315   const Square king = state.kingSquare(alt(attack));
00316   const King8Info info(state.Iking8Info(alt(attack)));
00317   return libertyAfterAllMove(state, attack, info, king);
00318 }
00319 
00320 int osl::checkmate::
00321 ProofNumberTable::disproofAfterAllCheck(const NumEffectState& state, 
00322                                         Player attack,
00323                                         King8Info info) const
00324 {
00325   int num_checks;
00326   num_checks=info.countMoveCandidate(attack,state);
00327   int drop_scale = state.hasPieceOnStand<GOLD>(attack) 
00328     + state.hasPieceOnStand<SILVER>(attack);  
00329   if (drop_scale)
00330     num_checks += misc::BitOp::countBit(info.dropCandidate()) * drop_scale;
00331   return std::max(1, num_checks);
00332 }
00333 
00334 const osl::checkmate::ProofDisproof osl::checkmate::
00335 ProofNumberTable::attackEstimation(const NumEffectState& state,
00336                                    Player attack,
00337                                    King8Info info, Square king) const
00338 {
00339   int p = libertyAfterAllDrop(state, attack, info);
00340   if (p >= 2)
00341   {
00342     p = std::min(p, libertyAfterAllMove(state, attack, info, king));
00343   }
00344   return ProofDisproof(p, disproofAfterAllCheck(state, attack, info));
00345 }
00346 
00347 const osl::checkmate::ProofDisproof osl::checkmate::
00348 ProofNumberTable::attackEstimation(const NumEffectState& state) const
00349 {
00350   const Player attack = state.turn();
00351   const Square king = state.kingSquare(alt(attack));
00352   const King8Info info(state.Iking8Info(alt(attack)));
00353   return attackEstimation(state, attack, info, king);
00354 }
00355 
00356 int osl::checkmate::
00357  ProofNumberTable::libertyAfterAllCheck(const NumEffectState& state) const
00358 {
00359   return attackEstimation(state).proof();
00360 }
00361 
00362 /* ------------------------------------------------------------------------- */
00363 // ;;; Local Variables:
00364 // ;;; mode:c++
00365 // ;;; c-basic-offset:2
00366 // ;;; End:
00367 
00368 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines