stateInfo.cc
Go to the documentation of this file.
00001 /* stateInfo.cc
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/record/opening/bookInMemory.h"
00009 #include "osl/hash/hashKey.h"
00010 #include "osl/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);    // need everytime
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     BOOST_FOREACH(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); // depends on attack_shadow, last_add_effect
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 // ;;; Local Variables:
00282 // ;;; mode:c++
00283 // ;;; c-basic-offset:2
00284 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines