feature.cc
Go to the documentation of this file.
00001 /* feature.cc
00002  */
00003 #include "osl/move_probability/feature.h"
00004 #include "osl/checkmate/checkmateIfCapture.h"
00005 #include "osl/neighboring8.h"
00006 #include <iostream>
00007 
00008 osl::move_probability::
00009 Feature::~Feature()
00010 {
00011 }
00012 
00013 
00014 void osl::move_probability::PatternCommon::
00015 updateCache(StateInfo& info)
00016 {
00017   for (int x=1; x<=9; ++x) {
00018     for (int y=1; y<=9; ++y) {
00019       const Square position(x,y);
00020       updateCacheOne(position, info);
00021     }
00022   }
00023 }
00024 
00025 void osl::move_probability::PatternCommon::
00026 updateCacheOne(Square position, StateInfo& info)
00027 {
00028   const NumEffectState& state = *info.state;
00029   StateInfo::pattern_square_t& cache
00030     = info.pattern_cache[position.index()];
00031   cache.fill(-1);
00032   const CArray<Square,2> kings = {{
00033       state.kingSquare(BLACK),
00034       state.kingSquare(WHITE),
00035     }};
00036   const Player turn = state.turn();
00037   int cur = 0;
00038 
00039   Piece target = state.pieceAt(position);
00040   PtypeO ptypeo = target.ptypeO();
00041   if (turn == WHITE)
00042     ptypeo = altIfPiece(ptypeo);
00043   size_t basic = ptypeOIndex(ptypeo)*SquareDim;
00044   std::pair<Ptype,Ptype> pair;
00045   ToEffect::supportAttack(state, position,
00046                           info.pin[turn], info.pin[alt(turn)],
00047                           turn, pair);
00048   int effect9 = classifyEffect9(state, turn, position);
00049   cache[cur++] = basic + pair.first;
00050   cache[cur++] = basic + AttackBase + pair.second;
00051   cache[cur++] = basic + EffectBase + effect9;
00052   assert(pair.first != PTYPE_EDGE);
00053   assert(pair.second != PTYPE_EDGE);
00054   if (isPiece(ptypeo)) {
00055     if (info.attack_shadow[target.number()][turn])
00056       cache[cur++] = basic + PTYPE_EDGE;
00057     if (info.attack_shadow[target.number()][alt(turn)])
00058       cache[cur++] = basic + AttackBase + PTYPE_EDGE;
00059   }
00060   assert(basic + EffectBase + effect9 < PatternCacheSize);
00061   int op_king_distance = abs(kings[alt(turn)].x()-position.x())
00062     + abs(kings[alt(turn)].y()-position.y());
00063   if (op_king_distance == 0) // KING
00064     op_king_distance = state.king8Info(alt(turn)).libertyCount();
00065   else
00066     --op_king_distance;
00067   if (op_king_distance < OpKingSize)
00068     cache[cur++] = basic + OpKingBase + op_king_distance;
00069   int my_king_distance = abs(kings[turn].x()-position.x())
00070     + abs(kings[turn].y()-position.y());
00071   if (my_king_distance == 0) // KING
00072     my_king_distance = state.king8Info(turn).libertyCount();
00073   else
00074     --my_king_distance;
00075   if (my_king_distance < MyKingSize)
00076     cache[cur++] = basic + MyKingBase + my_king_distance;
00077   // promotion
00078   if (position.canPromote(turn))
00079     cache[cur++] = basic + PromotionBase;
00080   else if (position.canPromote(alt(turn)))
00081     cache[cur++] = basic + PromotionBase + 1;
00082   if (target.isPiece()) {
00083     // pin or open
00084     if (state.pinOrOpen(turn).test(target.number()))
00085       cache[cur++] = basic + PinOpenBase + (target.owner() == turn);
00086     if (state.pinOrOpen(alt(turn)).test(target.number()))
00087       cache[cur++] = basic + PinOpenBase + 2 + (target.owner() == alt(turn));
00088     // last to
00089     if (info.history->hasLastMove()) {
00090       if (info.history->lastMove().to() == position)
00091         cache[cur++] = basic + LastToBase;
00092       for (int i=1; i<4; ++i) {
00093         if (! info.history->hasLastMove(i+1))
00094           break;
00095         if (info.history->lastMove(i+1).to() == position)
00096           cache[cur++] = basic + LastToBase + i;
00097       }
00098     }
00099   }
00100   // last effect changed
00101   if (info.history->hasLastMove()) {
00102     if (info.changed_effects.test(position))
00103       cache[cur++] = basic + LastEffectChangedBase;
00104     if (target.isPiece() && info.last_add_effect.test(target.number())) {
00105       int ptype_index = info.last_move_ptype5 - PTYPE_BASIC_MIN + 1;
00106       cache[cur++] = basic + LastEffectChangedBase + ptype_index;
00107     }
00108   }
00109 }
00110 
00111 
00112 
00113 void osl::move_probability::
00114 BlockLong::updateCache(StateInfo& info)
00115 {
00116   const NumEffectState& state = *info.state;
00117   for (int i=PtypeTraits<LANCE>::indexMin;
00118        i<PtypeTraits<LANCE>::indexLimit; ++i) {
00119     const Piece p = state.pieceOf(i);
00120     if (! p.isOnBoard() || p.isPromoted())
00121       continue;
00122     const Direction d = p.owner() == BLACK ? U : D;
00123     makeLongAttackOne(info, p, d);
00124   }
00125   for (int i=PtypeTraits<BISHOP>::indexMin;
00126        i<PtypeTraits<BISHOP>::indexLimit; ++i) {
00127     const Piece p = state.pieceOf(i);
00128     if (! p.isOnBoard())
00129       continue;
00130     makeLongAttackOne(info, p, UL);
00131     makeLongAttackOne(info, p, UR);
00132     makeLongAttackOne(info, p, DL);
00133     makeLongAttackOne(info, p, DR);
00134   }
00135   for (int i=PtypeTraits<ROOK>::indexMin;
00136        i<PtypeTraits<ROOK>::indexLimit; ++i) {
00137     const Piece p = state.pieceOf(i);
00138     if (! p.isOnBoard())
00139       continue;
00140     makeLongAttackOne(info, p, L);
00141     makeLongAttackOne(info, p, R);
00142     makeLongAttackOne(info, p, U);
00143     makeLongAttackOne(info, p, D);
00144   }
00145 }
00146 
00147 void osl::move_probability::
00148 BlockLong::makeLongAttackOne(StateInfo& info,
00149                              Piece piece, Direction d)
00150 {
00151   const NumEffectState& state = *info.state;
00152   StateInfo::long_attack_t& out
00153     = info.long_attack_cache[piece.number()][d];
00154   const Player turn = state.turn();
00155   const PtypeO attacking = (turn == BLACK)
00156     ? piece.ptypeO() : alt(piece.ptypeO());
00157   Square attack_to = state.mobilityOf(d, piece.number());
00158   Square attack_to2 = attack_to;
00159   assert(! attack_to.isPieceStand());
00160   if (attack_to.isEdge())
00161     attack_to -= Board_Table.getOffsetForBlack(d);
00162   else {
00163     const Offset o = Board_Table.getOffsetForBlack(d);
00164     attack_to2 += o;    // allow edge if neighboring
00165     if (state.pieceAt(attack_to2).isEmpty()) {
00166       do { 
00167         attack_to2 += o;
00168       } while (state.pieceAt(attack_to2).isEmpty());
00169       if (state.pieceAt(attack_to2).isEdge())
00170         attack_to2 -= o;
00171     }
00172   }
00173   PtypeO attacked = state.pieceOnBoard(attack_to).ptypeO();
00174   if (isPiece(attacked) && turn == WHITE)
00175     attacked = alt(attacked);
00176   int index = (longAttackIndex(attacking)*PTYPEO_SIZE
00177                + ptypeOIndex(attacked))*OptionSize;
00178   out.push_back(index);
00179   if (Neighboring8::isNeighboring8(attack_to, state.kingSquare(turn)))
00180     out.push_back(index + 1); // 1,King8
00181   if (! state.hasEffectAt(turn, attack_to))
00182     out.push_back(index + 2); // 2,HasSupport;
00183   if (attack_to.canPromote(alt(turn)))
00184     out.push_back(index + 3); // 3,Promotable;
00185   Piece attacked2 = state.pieceAt(attack_to2);
00186   if (attacked2.isOnBoardByOwner(turn)) { 
00187     out.push_back(index + 4); // 4,Shadowing;
00188     if (! state.hasEffectAt(turn, attack_to2))
00189       out.push_back(index + 5); // 5,
00190     if (attack_to2.canPromote(alt(turn)))
00191       out.push_back(index + 6); // 6,
00192     info.attack_shadow[attacked2.number()][piece.owner()] = true;
00193   }
00194   if (info.threatmate_move.isNormal()) {
00195     Square threat_at = info.threatmate_move.to();
00196     if (threat_at == attack_to
00197         || (! Board_Table.getShortOffsetNotKnight(Offset32(threat_at, attack_to)).zero()
00198             && Board_Table.isBetween(threat_at,
00199                                      piece.square(), attack_to)))
00200       out.push_back(index + 7); // 7, threatmate block?
00201   }
00202 }
00203 
00204 
00205 bool osl::move_probability::
00206 CheckmateIfCapture::hasSafeCapture(NumEffectState& state, Move move)
00207 {
00208   return ! checkmate::CheckmateIfCapture::effectiveAttack(state, move, 0);
00209 }
00210 
00211 
00212 // ;;; Local Variables:
00213 // ;;; mode:c++
00214 // ;;; c-basic-offset:2
00215 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines