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_UL; j<=LONG_DR; ++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 for(int i=0;i<0x10000;i++){
00098 const unsigned int liberty = (i>>8)&0xff;
00099 const int liberty_count = misc::BitOp::countBit(liberty);
00100 if (liberty_count <= 2)
00101 continue;
00102
00103 for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00104 int minimum_liberty = liberty_count;
00105 Ptype ptype=static_cast<Ptype>(k);
00106 if (ptype == KING)
00107 continue;
00108 for (int j=0;j<8;j++) {
00109
00110 if ((i&(0x1<<j))==0)
00111 continue;
00112 if ((i&(0x100<<j))!=0)
00113 continue;
00114 const Direction dir=static_cast<Direction>(j);
00115
00116 const bool has_effect
00117 = (Ptype_Table.getMoveMask(ptype)
00118 & (dirToMask(dir) | dirToMask(shortToLong(dir))));
00119 if (! has_effect)
00120 continue;
00121 const int e = table->liberties[liberty][k][j].liberty;
00122 assert(e);
00123 minimum_liberty = std::min(minimum_liberty, e);
00124 }
00125 for (int l=minimum_liberty; l<liberty_count; ++l)
00126 {
00127 for(int num=Ptype_Table.getIndexMin(ptype);
00128 num<Ptype_Table.getIndexLimit(ptype);num++)
00129 table->drop_liberty[i][l].set(num);
00130 }
00131 }
00132 }
00133
00134 table->pmajor_liberty.fill(8);
00135 for (int l=0; l<0x100; l++) {
00136 for (int m=0; m<0x100; m++) {
00137 if (l & m)
00138 continue;
00139 int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00140 if (min_liberty > 1)
00141 {
00142 for (int j=0; j<8; j++) {
00143 if ((m&(0x1<<j))==0)
00144 continue;
00145 const int pr = table->liberties[l][PROOK][j].liberty;
00146 const int pb = table->liberties[l][PBISHOP][j].liberty;
00147 min_liberty = std::min(min_liberty, std::min(pr,pb));
00148 assert(min_liberty);
00149 }
00150 }
00151 table->pmajor_liberty[l][m] = min_liberty;
00152 }
00153 }
00154
00155 table->promote_liberty.fill(8);
00156 for (int l=0; l<0x100; l++) {
00157 for (int m=0; m<0x100; m++) {
00158 if (l & m)
00159 continue;
00160 int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00161 if (min_liberty > 1)
00162 {
00163 for (int j=0; j<8; j++) {
00164 if ((m&(0x1<<j))==0)
00165 continue;
00166 for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00167 Ptype ptype=static_cast<Ptype>(k);
00168 if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
00169 continue;
00170 Liberty e = table->liberties[l][k][j];
00171 if (! e.has_effect)
00172 continue;
00173 assert(e.liberty);
00174 min_liberty = std::min(min_liberty, (int)e.liberty);
00175 assert(min_liberty);
00176 }
00177 }
00178 }
00179 table->promote_liberty[l][m] = min_liberty;
00180 }
00181 }
00182
00183 table->other_move_liberty.fill(8);
00184 for (int l=0; l<0x100; l++) {
00185 for (int m=0; m<0x100; m++) {
00186 if (l & m)
00187 continue;
00188 int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00189 if (min_liberty > 1)
00190 {
00191 for (int j=0; j<8; j++) {
00192 if ((m&(0x1<<j))==0)
00193 continue;
00194 for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00195 Ptype ptype=static_cast<Ptype>(k);
00196 if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
00197 continue;
00198 if (j == U
00199 && (ptype == GOLD || ptype == PPAWN || ptype == PLANCE
00200 || ptype == PKNIGHT || ptype == PSILVER))
00201 continue;
00202 Liberty e = table->liberties[l][k][j];
00203 if (! e.has_effect)
00204 continue;
00205 assert(e.liberty);
00206 min_liberty = std::min(min_liberty, (int)e.liberty);
00207 assert(min_liberty);
00208 }
00209 }
00210 }
00211 table->other_move_liberty[l][m] = min_liberty;
00212 }
00213 }
00214 }
00215
00216 int osl::checkmate::
00217 ProofNumberTable::countLiberty(const NumEffectState& state, Move move) const
00218 {
00219 const Player attack = move.player();
00220 const Position king = state.getKingPosition(alt(attack));
00221 const King8Info info = King8Info::make(attack, state);
00222 return countLiberty(state, info.libertyCount(), move, king, info);
00223 }
00224
00225 int osl::checkmate::
00226 ProofNumberTable::libertyAfterAllDrop(const NumEffectState& state) const
00227 {
00228 const Player attack = state.getTurn();
00229 const King8Info info = King8Info::make(attack, state);
00230 return libertyAfterAllDrop(state, attack, info);
00231 }
00232
00233 int osl::checkmate::
00234 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state,
00235 Player attack,
00236 King8Info info, Position king) const
00237 {
00238 bool has_pmajor = false;
00239 {
00240 for (int i = PtypeTraits<BISHOP>::indexMin;
00241 i < PtypeTraits<ROOK>::indexLimit; i++)
00242 {
00243
00244 const Piece p = state.getPieceOf(i);
00245 assert(isMajor(p.ptype()));
00246 if (! p.isOnBoardByOwner(attack))
00247 continue;
00248 if (king.positionForBlack(attack).y() > 3
00249 && ! isPromoted(p.ptype()))
00250 {
00251 if (! p.position().canPromote(attack))
00252 continue;
00253 }
00254 if (Neighboring8Direct::hasEffect(state, p.ptypeO(), p.position(),
00255 king))
00256 {
00257
00258 has_pmajor = true;
00259 break;
00260 }
00261 }
00262 }
00263 if (has_pmajor)
00264 {
00265 int result = table->pmajor_liberty[info.liberty()][info.moveCandidate()];
00266 assert(result);
00267 return result;
00268 }
00269 bool promoted_area = king.positionForBlack(attack).y() < 3;
00270 if (! promoted_area)
00271 {
00272 const Position u = king + Board_Table.getOffset(alt(attack), U);
00273 promoted_area = state.hasEffectByPtype<GOLD>(attack, u);
00274 }
00275 if (promoted_area)
00276 {
00277 int result = table->promote_liberty[info.liberty()][info.moveCandidate()];
00278 assert(result);
00279 return result;
00280 }
00281 int result = table->other_move_liberty[info.liberty()][info.moveCandidate()];
00282 assert(result);
00283 return result;
00284 }
00285
00286 int osl::checkmate::
00287 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state) const
00288 {
00289 const Player attack = state.getTurn();
00290 const Position king = state.getKingPosition(alt(attack));
00291 const King8Info info = King8Info::make(attack, state);
00292 return libertyAfterAllMove(state, attack, info, king);
00293 }
00294
00295 int osl::checkmate::
00296 ProofNumberTable::disproofAfterAllCheck(const NumEffectState& state,
00297 Player attack,
00298 King8Info info) const
00299 {
00300 int num_checks = misc::BitOp::countBit(info.moveCandidate());
00301 int drop_scale = state.hasPieceOnStand(attack, GOLD)
00302 + state.hasPieceOnStand(attack, SILVER);
00303 if (drop_scale)
00304 num_checks += misc::BitOp::countBit(info.dropCandidate()) * drop_scale;
00305 return std::max(1, num_checks);
00306 }
00307
00308 const osl::checkmate::ProofDisproof osl::checkmate::
00309 ProofNumberTable::attackEstimation(const NumEffectState& state,
00310 Player attack,
00311 King8Info info, Position king) const
00312 {
00313 int p = libertyAfterAllDrop(state, attack, info);
00314 if (p >= 2)
00315 {
00316 p = std::min(p, libertyAfterAllMove(state, attack, info, king));
00317 }
00318 return ProofDisproof(p, disproofAfterAllCheck(state, attack, info));
00319 }
00320
00321 const osl::checkmate::ProofDisproof osl::checkmate::
00322 ProofNumberTable::attackEstimation(const NumEffectState& state) const
00323 {
00324 const Player attack = state.getTurn();
00325 const Position king = state.getKingPosition(alt(attack));
00326 const King8Info info = King8Info::make(attack, state);
00327 return attackEstimation(state, attack, info, king);
00328 }
00329
00330 int osl::checkmate::
00331 ProofNumberTable::libertyAfterAllCheck(const NumEffectState& state) const
00332 {
00333 return attackEstimation(state).proof();
00334 }
00335
00336
00337
00338
00339
00340
00341
00342