00001
00002
00003 #include "osl/checkmate/proofNumberTable.h"
00004 #include "osl/checkmate/immediateCheckmate.h"
00005 #include "osl/effect_util/neighboring8Direct.h"
00006 #include "osl/bits/boardTable.h"
00007 #include "osl/bits/ptypeTable.h"
00008 #include "osl/oslConfig.h"
00009
00010 osl::checkmate::ProofNumberTable osl::checkmate::Proof_Number_Table;
00011 osl::checkmate::EdgeTable osl::checkmate::Edge_Table;
00012
00013 static osl::SetUpRegister _initializer([](){
00014 osl::checkmate::Proof_Number_Table.init();
00015 osl::checkmate::Edge_Table.init();
00016 });
00017
00018 namespace osl
00019 {
00020 namespace
00021 {
00022 using namespace osl::checkmate;
00026 const checkmate::ProofNumberTable::Liberty
00027 effectiveCheckShort(Ptype ptype,Direction dir,unsigned int mask)
00028 {
00029 assert(isShort(dir));
00030
00031 if (ptype==KING)
00032 return ProofNumberTable::Liberty(0,false);
00033
00034 const bool has_effect
00035 = (Ptype_Table.getMoveMask(ptype)
00036 & (dirToMask(dir) | dirToMask(shortToLong(dir))));
00037 int dx=Board_Table.getDxForBlack(dir);
00038 int dy=Board_Table.getDyForBlack(dir);
00039 int count = 0;
00040 for (int l=0;l<8;l++) {
00041 if ((mask&(1<<l))==0)
00042 continue;
00043 Direction dir1=static_cast<Direction>(l);
00044 int dx1=Board_Table.getDxForBlack(dir1);
00045 int dy1=Board_Table.getDyForBlack(dir1);
00046 Offset32 o32(dx-dx1,dy-dy1);
00047 if ((dx != dx1 || dy != dy1)
00048 && !Ptype_Table.getEffect(newPtypeO(BLACK,ptype),o32).hasEffect())
00049 ++count;
00050 }
00051 return ProofNumberTable::Liberty(std::max(count,1), has_effect);
00052 }
00053 const checkmate::ProofNumberTable::Liberty
00054 effectiveCheckLong(Ptype ptype,Direction dir,unsigned int mask)
00055 {
00056 assert(isLong(dir));
00057
00058
00059 const bool has_effect
00060 = (Ptype_Table.getMoveMask(ptype) & dirToMask(dir));
00061 int dx=Board_Table.getDxForBlack(dir)*2;
00062 int dy=Board_Table.getDyForBlack(dir)*2;
00063 int count = 0;
00064 for (int l=0;l<8;l++) {
00065 if ((mask&(1<<l))==0)
00066 continue;
00067 Direction dir1=static_cast<Direction>(l);
00068 int dx1=Board_Table.getDxForBlack(dir1);
00069 int dy1=Board_Table.getDyForBlack(dir1);
00070 Offset32 o32(dx-dx1,dy-dy1);
00071 if (!Ptype_Table.getEffect(newPtypeO(BLACK,ptype),o32).hasEffect())
00072 ++count;
00073 }
00074 return ProofNumberTable::Liberty(std::max(count,1), has_effect);
00075 }
00076 }
00077 }
00078
00079 void osl::checkmate::
00080 ProofNumberTable::init()
00081 {
00082
00083 for (int i=0; i<0x100; i++) {
00084 for (int k=PTYPE_PIECE_MIN; k<=PTYPE_MAX; k++) {
00085 const Ptype ptype=static_cast<Ptype>(k);
00086 assert(isPiece(ptype));
00087 for (int j=0; j<8; j++) {
00088 Direction dir=static_cast<Direction>(j);
00089 const Liberty e = effectiveCheckShort(ptype,dir,i);
00090 liberties[i][k][j] = e;
00091 }
00092 int longs = 0;
00093 for (int j=LONG_DIRECTION_MIN; j<=LONG_DIRECTION_MAX; ++j,++longs) {
00094 Direction dir=static_cast<Direction>(j);
00095 const Liberty e = effectiveCheckLong(ptype,dir,i);
00096 liberties[i][k][j] = e;
00097 }
00098 assert(longs == 8);
00099 }
00100 }
00101
00102 drop_liberty.fill(0);
00103 for(int i=0;i<0x10000;i++){
00104 const unsigned int liberty = (i>>8)&0xff;
00105 const int liberty_count = misc::BitOp::countBit(liberty);
00106 if (liberty_count <= 2)
00107 continue;
00108
00109 for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00110 int minimum_liberty = liberty_count;
00111 Ptype ptype=static_cast<Ptype>(k);
00112 if (ptype == KING)
00113 continue;
00114 for (int j=0;j<8;j++) {
00115
00116 if ((i&(0x1<<j))==0)
00117 continue;
00118 if ((i&(0x100<<j))!=0)
00119 continue;
00120 const Direction dir=static_cast<Direction>(j);
00121
00122 const bool has_effect
00123 = (Ptype_Table.getMoveMask(ptype)
00124 & (dirToMask(dir) | dirToMask(shortToLong(dir))));
00125 if (! has_effect)
00126 continue;
00127 const int e = liberties[liberty][k][j].liberty;
00128 assert(e);
00129 minimum_liberty = std::min(minimum_liberty, e);
00130 }
00131 for (int l=minimum_liberty; l<liberty_count; ++l)
00132 {
00133 drop_liberty[i][l] |= (1<<(ptype-GOLD));
00134 }
00135 }
00136 }
00137
00138 pmajor_liberty.fill(8);
00139 for (int l=0; l<0x100; l++) {
00140 for (int m=0; m<0x100; m++) {
00141 if (l & m)
00142 continue;
00143 int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00144 if (min_liberty > 1)
00145 {
00146 for (int j=0; j<8; j++) {
00147 if ((m&(0x1<<j))==0)
00148 continue;
00149 const int pr = liberties[l][PROOK][j].liberty;
00150 const int pb = liberties[l][PBISHOP][j].liberty;
00151 min_liberty = std::min(min_liberty, std::min(pr,pb));
00152 assert(min_liberty);
00153 }
00154 }
00155 pmajor_liberty[l][m] = min_liberty;
00156 }
00157 }
00158
00159 promote_liberty.fill(8);
00160 for (int l=0; l<0x100; l++) {
00161 for (int m=0; m<0x100; m++) {
00162 if (l & m)
00163 continue;
00164 int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00165 if (min_liberty > 1)
00166 {
00167 for (int j=0; j<8; j++) {
00168 if ((m&(0x1<<j))==0)
00169 continue;
00170 for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00171 Ptype ptype=static_cast<Ptype>(k);
00172 if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
00173 continue;
00174 Liberty e = liberties[l][k][j];
00175 if (! e.has_effect)
00176 continue;
00177 assert(e.liberty);
00178 min_liberty = std::min(min_liberty, (int)e.liberty);
00179 assert(min_liberty);
00180 }
00181 }
00182 }
00183 promote_liberty[l][m] = min_liberty;
00184 }
00185 }
00186
00187 other_move_liberty.fill(8);
00188 for (int l=0; l<0x100; l++) {
00189 for (int m=0; m<0x100; m++) {
00190 if (l & m)
00191 continue;
00192 int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
00193 if (min_liberty > 1)
00194 {
00195 for (int j=0; j<8; j++) {
00196 if ((m&(0x1<<j))==0)
00197 continue;
00198 for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
00199 Ptype ptype=static_cast<Ptype>(k);
00200 if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
00201 continue;
00202 if (j == U
00203 && (ptype == GOLD || ptype == PPAWN || ptype == PLANCE
00204 || ptype == PKNIGHT || ptype == PSILVER))
00205 continue;
00206 Liberty e = liberties[l][k][j];
00207 if (! e.has_effect)
00208 continue;
00209 assert(e.liberty);
00210 min_liberty = std::min(min_liberty, (int)e.liberty);
00211 assert(min_liberty);
00212 }
00213 }
00214 }
00215 other_move_liberty[l][m] = min_liberty;
00216 }
00217 }
00218 }
00219
00220 int osl::checkmate::
00221 ProofNumberTable::countLiberty(const NumEffectState& state, Move move) const
00222 {
00223 const Player attack = move.player();
00224 const Square king = state.kingSquare(alt(attack));
00225 const King8Info info(state.Iking8Info(alt(attack)));
00226 return countLiberty(state, info.libertyCount(), move, king, info);
00227 }
00228
00229 int osl::checkmate::
00230 ProofNumberTable::libertyAfterAllDrop(const NumEffectState& state, Player attack,
00231 King8Info info) const
00232 {
00233 assert(state.turn() == attack);
00234 int result = info.libertyCount()-1;
00235 if (result < 2)
00236 return 1;
00237 const unsigned int ld_mask = info.libertyDropMask();
00238 uint8_t ptype_mask = 0;
00239 for (int p=GOLD; p<=ROOK; ++p)
00240 ptype_mask |= state.hasPieceOnStand(attack, static_cast<Ptype>(p)) << (p-GOLD);
00241 for (;
00242 result > 1
00243 && (ptype_mask & drop_liberty[ld_mask][result-1]);
00244 --result)
00245 {
00246 }
00247 return result;
00248 }
00249
00250 int osl::checkmate::
00251 ProofNumberTable::libertyAfterAllDrop(const NumEffectState& state) const
00252 {
00253 const Player attack = state.turn();
00254 const King8Info info(state.Iking8Info(alt(attack)));
00255 return libertyAfterAllDrop(state, attack, info);
00256 }
00257
00258 int osl::checkmate::
00259 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state,
00260 Player attack,
00261 King8Info info, Square king) const
00262 {
00263 bool has_pmajor = false;
00264 {
00265 for (int i = PtypeTraits<BISHOP>::indexMin;
00266 i < PtypeTraits<ROOK>::indexLimit; i++)
00267 {
00268
00269 const Piece p = state.pieceOf(i);
00270 assert(isMajor(p.ptype()));
00271 if (! p.isOnBoardByOwner(attack))
00272 continue;
00273 if (king.squareForBlack(attack).y() > 3
00274 && ! isPromoted(p.ptype()))
00275 {
00276 if (! p.square().canPromote(attack))
00277 continue;
00278 }
00279 if (Neighboring8Direct::hasEffect(state, p.ptypeO(), p.square(),
00280 king))
00281 {
00282
00283 has_pmajor = true;
00284 break;
00285 }
00286 }
00287 }
00288 int moveCandidate;
00289 if(attack==BLACK)
00290 moveCandidate = info.moveCandidateMask<BLACK>(state);
00291 else
00292 moveCandidate = info.moveCandidateMask<WHITE>(state);
00293 if (has_pmajor)
00294 {
00295 int result = pmajor_liberty[info.liberty()][moveCandidate];
00296 assert(result);
00297 return result;
00298 }
00299 bool promoted_area = king.squareForBlack(attack).y() < 3;
00300 if (! promoted_area)
00301 {
00302 const Square u = king + Board_Table.getOffset(alt(attack), U);
00303 promoted_area = state.hasEffectByPtype<GOLD>(attack, u);
00304 }
00305 if (promoted_area)
00306 {
00307 int result = promote_liberty[info.liberty()][moveCandidate];
00308 assert(result);
00309 return result;
00310 }
00311 int result = other_move_liberty[info.liberty()][moveCandidate];
00312 assert(result);
00313 return result;
00314 }
00315
00316 int osl::checkmate::
00317 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state) const
00318 {
00319 const Player attack = state.turn();
00320 const Square king = state.kingSquare(alt(attack));
00321 const King8Info info(state.Iking8Info(alt(attack)));
00322 return libertyAfterAllMove(state, attack, info, king);
00323 }
00324
00325 int osl::checkmate::
00326 ProofNumberTable::disproofAfterAllCheck(const NumEffectState& state,
00327 Player attack,
00328 King8Info info) const
00329 {
00330 int num_checks;
00331 num_checks=info.countMoveCandidate(attack,state);
00332 int drop_scale = state.hasPieceOnStand<GOLD>(attack)
00333 + state.hasPieceOnStand<SILVER>(attack);
00334 if (drop_scale)
00335 num_checks += misc::BitOp::countBit(info.dropCandidate()) * drop_scale;
00336 return std::max(1, num_checks);
00337 }
00338
00339 const osl::checkmate::ProofDisproof osl::checkmate::
00340 ProofNumberTable::attackEstimation(const NumEffectState& state,
00341 Player attack,
00342 King8Info info, Square king) const
00343 {
00344 int p = libertyAfterAllDrop(state, attack, info);
00345 if (p >= 2)
00346 {
00347 p = std::min(p, libertyAfterAllMove(state, attack, info, king));
00348 }
00349 return ProofDisproof(p, disproofAfterAllCheck(state, attack, info));
00350 }
00351
00352 const osl::checkmate::ProofDisproof osl::checkmate::
00353 ProofNumberTable::attackEstimation(const NumEffectState& state) const
00354 {
00355 const Player attack = state.turn();
00356 const Square king = state.kingSquare(alt(attack));
00357 const King8Info info(state.Iking8Info(alt(attack)));
00358 return attackEstimation(state, attack, info, king);
00359 }
00360
00361 int osl::checkmate::
00362 ProofNumberTable::libertyAfterAllCheck(const NumEffectState& state) const
00363 {
00364 return attackEstimation(state).proof();
00365 }
00366
00367
00368
00369 void osl::checkmate::EdgeTable::init()
00370 {
00371 edge_mask.fill(~(0xfull << 48));
00372 for (int x=1; x<=9; ++x) {
00373 for (int y=1; y<=9; ++y) {
00374 Square king(x,y);
00375 for (int d=DIRECTION_MIN; d<=SHORT8_DIRECTION_MAX; ++d) {
00376 Square target = king+Board_Table.getOffset(BLACK, Direction(d));
00377 if (target.x() <= 1 || target.x() >= 9 || target.y() <=1 || target.y() >=9)
00378 edge_mask[BLACK][king.index()] &= ~(0x100ull<<d);
00379 target = king+Board_Table.getOffset(WHITE, Direction(d));
00380 if (target.x() <= 1 || target.x() >= 9 || target.y() <=1 || target.y() >=9)
00381 edge_mask[WHITE][king.index()] &= ~(0x100ull<<d);
00382 }
00383 }
00384 }
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394