00001
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
00021 if (ptype==KING)
00022 return ProofNumberTable::Liberty(0,false);
00023
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
00048
00049 const bool has_effect
00050 = (Ptype_Table.getMoveMask(ptype) & dirToMask(dir));
00051 int dx=Board_Table.getDxForBlack(dir)*2;
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
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
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;
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
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
00133 table->pmajor_liberty.fill(8);
00134 for (int l=0; l<0x100; l++) {
00135 for (int m=0; m<0x100; m++) {
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
00154 table->promote_liberty.fill(8);
00155 for (int l=0; l<0x100; l++) {
00156 for (int m=0; m<0x100; m++) {
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
00182 table->other_move_liberty.fill(8);
00183 for (int l=0; l<0x100; l++) {
00184 for (int m=0; m<0x100; m++) {
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
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
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
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
00364
00365
00366
00367
00368