00001
00002
00003 #include "osl/move_probability/stateInfo.h"
00004 #include "osl/move_probability/feature.h"
00005 #include "osl/checkmate/fixedDepthSearcher.h"
00006 #include "osl/checkmate/immediateCheckmateTable.h"
00007 #include "osl/effect_util/sendOffSquare.h"
00008 #include "osl/book/bookInMemory.h"
00009 #include "osl/hashKey.h"
00010 #include "osl/bits/ptypeTraits.h"
00011 #include <iostream>
00012
00013 void osl::move_probability::
00014 StateInfo::clearOldCache()
00015 {
00016 const osl::Player turn = state->turn();
00017 threatmate_move = Move();
00018 attack_shadow.fill(false);
00019 pin[BLACK] = state->pin(BLACK);
00020 pin[WHITE] = state->pin(WHITE);
00021 move_candidate_exists[BLACK] = king8Info(BLACK).hasMoveCandidate<WHITE>(*state);
00022 move_candidate_exists[WHITE] = king8Info(WHITE).hasMoveCandidate<BLACK>(*state);
00023
00024 checkmate_defender[BLACK] = findCheckmateDefender(*state, BLACK);
00025 checkmate_defender[WHITE] = findCheckmateDefender(*state, WHITE);
00026
00027 sendoffs.clear();
00028 if (state->hasChangedEffects())
00029 changed_effects = state->changedEffects(alt(turn));
00030 else
00031 changed_effects.invalidate();
00032 threatened[turn] = state->inCheck(turn)
00033 ? state->kingPiece(turn) : state->findThreatenedPiece(turn);
00034 threatened[alt(turn)] = state->findThreatenedPiece(alt(turn));
00035
00036 {
00037 possible_threatmate_ptype
00038 = checkmate::Immediate_Checkmate_Table.dropPtypeMask(king8Info(alt(state->turn())));
00039 const Square king = state->kingSquare(alt(state->turn()));
00040 const CArray<Direction,2> directions = {{ UUL, UUR }};
00041 for (Direction d: directions) {
00042 Square knight_attack = king - Board_Table.getOffset(state->turn(), d);
00043 if (state->pieceAt(knight_attack).isEmpty()
00044 && ! state->hasEffectAt(alt(state->turn()), knight_attack)) {
00045 possible_threatmate_ptype |= (1<<(KNIGHT-PTYPE_BASIC_MIN));
00046 break;
00047 }
00048 }
00049 for (int p=PTYPE_BASIC_MIN; p<=PTYPE_MAX; ++p) {
00050 if (possible_threatmate_ptype & (1<<p))
00051 if (state->hasPieceOnStand(state->turn(), static_cast<Ptype>(p)))
00052 p &= ~(1<<p);
00053 }
00054 }
00055 bookmove.fill(Move());
00056 }
00057
00058 void osl::move_probability::
00059 StateInfo::finishUpdate()
00060 {
00061 copy.copyFrom(*state);
00062 const osl::Player turn = state->turn();
00063 const Square king = state->kingSquare(alt(turn));
00064 effect_util::SendOffSquare::find(turn, *state, king, sendoffs);
00065
00066 updatePinnedGenerals(BLACK);
00067 updatePinnedGenerals(WHITE);
00068
00069 makePinOfLongPieces();
00070 for (int d=SHORT8_DIRECTION_MIN; d<=SHORT8_DIRECTION_MAX; ++d) {
00071 Piece p = state->pieceAt(state->kingMobilityAbs(alt(turn), (Direction)d));
00072 if (p.isOnBoardByOwner(alt(turn)))
00073 king8_long_pieces.push_back(p);
00074 }
00075 BlockLong::updateCache(*this);
00076 if (! history->hasLastMove() || !history->lastMove().isNormal()) {
00077 last_move_ptype5 = PTYPE_EMPTY;
00078 last_add_effect = PieceMask();
00079 } else {
00080 last_move_ptype5 = unpromote(history->lastMove().ptype());
00081 if (last_move_ptype5 == SILVER)
00082 last_move_ptype5 = GOLD;
00083 else if (last_move_ptype5 == KNIGHT)
00084 last_move_ptype5 = LANCE;
00085 else if (isMajor(last_move_ptype5))
00086 last_move_ptype5 = KNIGHT;
00087 last_add_effect = state->effectedMask(alt(turn))
00088 & state->effectedChanged(alt(turn));
00089 }
00090 PatternCommon::updateCache(*this);
00091 {
00092 MoveVector all;
00093 static const BookInMemory& book = BookInMemory::instance();
00094 book.find(HashKey(*state), all);
00095 for (size_t i=0; i<bookmove.size(); ++i)
00096 if (all.size() > i)
00097 bookmove[i] = all[i];
00098 }
00099 dirty = false;
00100 }
00101
00102 void osl::move_probability::
00103 StateInfo::makePinOfLongPieces()
00104 {
00105 using namespace osl;
00106 if (state->inCheck())
00107 return;
00108 for (int i=0; i<40; ++i) {
00109 const Piece p = state->pieceOf(i);
00110 if (!p.isOnBoard() || p.ptype() == KING)
00111 continue;
00112 CArray<mask_t,2> long_effect = {{
00113 state->longEffectAt(p.square(), BLACK),
00114 state->longEffectAt(p.square(), WHITE),
00115 }};
00116 if (long_effect[0].none() || long_effect[1].none()) continue;
00117 CArray<Piece,2> attack_piece;
00118 {
00119 attack_piece[0] = state->findLongAttackAt(p, U);
00120 attack_piece[1] = state->findLongAttackAt(p, D);
00121 if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
00122 && attack_piece[0].owner() != attack_piece[1].owner()) {
00123 pin_by_opposing_sliders.push_back(p);
00124 continue;
00125 }
00126 }
00127 if ((long_effect[0] & mask_t::makeDirect(PtypeFuns<ROOK>::indexMask)).any()
00128 && (long_effect[0] & mask_t::makeDirect(PtypeFuns<ROOK>::indexMask)).any())
00129 {
00130 attack_piece[0] = state->findLongAttackAt(p, L);
00131 attack_piece[1] = state->findLongAttackAt(p, R);
00132 if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
00133 && attack_piece[0].owner() != attack_piece[1].owner()) {
00134 pin_by_opposing_sliders.push_back(p);
00135 continue;
00136 }
00137 }
00138 if ((long_effect[0] & mask_t::makeDirect(PtypeFuns<BISHOP>::indexMask)).any()
00139 && (long_effect[0] & mask_t::makeDirect(PtypeFuns<BISHOP>::indexMask)).any())
00140 {
00141 attack_piece[0] = state->findLongAttackAt(p, UL);
00142 attack_piece[1] = state->findLongAttackAt(p, DR);
00143 if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
00144 && attack_piece[0].owner() != attack_piece[1].owner()) {
00145 pin_by_opposing_sliders.push_back(p);
00146 continue;
00147 }
00148 attack_piece[0] = state->findLongAttackAt(p, UR);
00149 attack_piece[1] = state->findLongAttackAt(p, DL);
00150 if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
00151 && attack_piece[0].owner() != attack_piece[1].owner()) {
00152 pin_by_opposing_sliders.push_back(p);
00153 continue;
00154 }
00155 }
00156 }
00157 }
00158
00159 std::pair<osl::Piece,osl::Square> osl::move_probability::
00160 StateInfo::findCheckmateDefender(const NumEffectState& state, Player king)
00161 {
00162 const King8Info king8info = state.king8Info(king);
00163 const unsigned int spaces = king8info.spaces();
00164 if (spaces == 0 || (spaces & (spaces-1)))
00165 return std::make_pair(Piece::EMPTY(), Square());
00166 const Square sq = state.kingSquare(king)
00167 + Board_Table.getOffset(king, (Direction)misc::BitOp::bsf(spaces));
00168 assert(state.pieceAt(sq).isEmpty());
00169 if (state.countEffect(king, sq) != 2 || ! state.hasEffectAt(alt(king), sq))
00170 return std::make_pair(Piece::EMPTY(), Square());
00171 unsigned int drop_candidate = king8info.libertyDropMask();
00172 drop_candidate &= 0xff00;
00173 drop_candidate += spaces;
00174 mask_t drop_ptype=mask_t::makeDirect
00175 (checkmate::Immediate_Checkmate_Table.dropPtypeMaskOf(drop_candidate));
00176 while(drop_ptype.any()){
00177 Ptype ptype=static_cast<Ptype>(drop_ptype.takeOneBit()+PTYPE_BASIC_MIN);
00178 if (state.hasPieceOnStand(alt(king),ptype))
00179 return std::make_pair(state.findCheapAttack(king, sq), sq);
00180 }
00181 return std::make_pair(Piece::EMPTY(), Square());
00182 }
00183
00184 void osl::move_probability::
00185 StateInfo::updatePinnedGenerals(Player owner)
00186 {
00187 exchange_pins[owner].clear();
00188 PieceMask attacked = state->piecesOnBoard(owner)
00189 & state->effectedMask(owner) & state->effectedMask(alt(owner));
00190 while (attacked.any()) {
00191 const Piece p = state->pieceOf(attacked.takeOneBit());
00192 const int a = state->countEffect(alt(owner), p.square());
00193 const int d = state->countEffect(owner, p.square());
00194 if (d != a)
00195 continue;
00196 const Piece attack_p = state->findCheapAttack(alt(owner), p.square());
00197 const Piece support = state->findCheapAttack(owner, p.square());
00198 if (support.ptype() == PAWN || support.ptype() == LANCE)
00199 continue;
00200 unsigned int directions = Ptype_Table.getMoveMask(support.ptype());
00201 while (directions) {
00202 Direction d = static_cast<Direction>(misc::BitOp::bsf(directions));
00203 directions &= directions-1;
00204 Square target = support.square() + Board_Table.getOffset(owner, d);
00205 if (target == p.square())
00206 continue;
00207 Piece tp = state->pieceAt(target);
00208 if (tp.isEmpty() || tp.isOnBoardByOwner(owner)) {
00209 assert(state->hasEffectByPiece(support, target));
00210 if (state->countEffect(owner, target)
00211 <= state->countEffect(alt(owner), target)+1
00212 - state->hasEffectByPiece(attack_p, target)
00213 && ! state->hasEffectIf(support.ptypeO(), target, p.square()))
00214 exchange_pins[owner].push_back
00215 (PinnedGeneral(support, p, target));
00216 }
00217 }
00218 }
00219 }
00220
00221 osl::Move osl::move_probability::
00222 StateInfo::findShortThreatmate(const NumEffectState& state, Move last_move)
00223 {
00224 if (state.inCheck())
00225 return Move();
00226 NumEffectState copy(state);
00227 copy.changeTurn();
00228 checkmate::FixedDepthSearcher searcher(copy);
00229
00230 Move best_move;
00231 const ProofDisproof pdp
00232 = searcher.hasCheckmateMoveOfTurn(2, best_move);
00233 if (pdp.isCheckmateSuccess())
00234 return best_move;
00235 if (pdp.isFinal())
00236 return Move();
00237 if (last_move.isNormal() && Neighboring8Direct::hasEffect
00238 (state, last_move.ptypeO(), last_move.to(), state.kingSquare(state.turn()))) {
00239 const ProofDisproof pdp4
00240 = searcher.hasCheckmateMoveOfTurn(4, best_move);
00241 if (pdp4.isCheckmateSuccess())
00242 return best_move;
00243 if (state.hasPieceOnStand<GOLD>(alt(state.turn()))) {
00244 const ProofDisproof pdp6
00245 = searcher.hasCheckmateMoveOfTurn(6, best_move);
00246 if (pdp6.isCheckmateSuccess())
00247 return best_move;
00248 }
00249 }
00250 return Move();
00251 }
00252
00253 bool osl::move_probability::operator==(const StateInfo& l, const StateInfo& r)
00254 {
00255 for (int x=1; x<=9; ++x) {
00256 for (int y=1; y<=9; ++y) {
00257 const Square position(x,y);
00258 if (! (l.pattern_cache[position.index()]
00259 == r.pattern_cache[position.index()]))
00260 return false;
00261 }
00262 }
00263 return HashKey(*l.state) == HashKey(*r.state)
00264 && *l.history == *r.history
00265 && l.pin_by_opposing_sliders == r.pin_by_opposing_sliders
00266 && l.king8_long_pieces == r.king8_long_pieces
00267 && l.threatened == r.threatened
00268 && l.long_attack_cache == r.long_attack_cache
00269 && l.attack_shadow == r.attack_shadow
00270 && l.progress16 == r.progress16
00271 && l.last_move_ptype5 == r.last_move_ptype5
00272 && l.last_add_effect == r.last_add_effect
00273 && l.pin == r.pin && l.threatmate_move == r.threatmate_move
00274 && l.sendoffs == r.sendoffs
00275 && l.exchange_pins == r.exchange_pins
00276 && l.move_candidate_exists == r.move_candidate_exists
00277 && l.checkmate_defender == r.checkmate_defender
00278 && HashKey(l.copy) == HashKey(r.copy);
00279 }
00280
00281
00282
00283
00284