effect5x3.cc
Go to the documentation of this file.
00001 /* effect5x3.cc
00002  */
00003 #include "osl/progress/effect5x3.h"
00004 #include "osl/progress/effect5x3Table.h"
00005 #include "osl/pieceStand.h"
00006 #include "osl/container/pieceMask.h"
00007 
00008 osl::progress::
00009 Effect5x3::Effect5x3(const NumEffectState& state)
00010 {
00011   area_progresses[BLACK]=makeProgressArea(WHITE, state, state.kingSquare(BLACK));
00012   area_progresses[WHITE]=makeProgressArea(BLACK, state, state.kingSquare(WHITE));
00013   stand_progresses[WHITE]=makeProgressStand(BLACK, state);
00014   stand_progresses[BLACK]=makeProgressStand(WHITE, state);
00015   progresses[BLACK]=area_progresses[BLACK]+stand_progresses[BLACK];
00016   progresses[WHITE]=area_progresses[WHITE]+stand_progresses[WHITE];
00017 }
00018 
00019 int osl::progress::
00020 Effect5x3::makeProgressAll(Player defense, const NumEffectState& state,
00021                            Square king)
00022 {  
00023   return makeProgressArea(alt(defense), state, king) 
00024     + makeProgressStand(alt(defense), state);
00025 }
00026 
00027 int osl::progress::
00028 Effect5x3::makeProgressArea(Player attack, const NumEffectState& state,
00029                             Square king)
00030 {  
00031   const Square center = Centering5x3::adjustCenter(king);
00032 
00033   const int min_x = center.x() - 2;
00034   const int min_y = center.y() - 1;
00035 
00036   // 利き
00037   int sum_effect = 0;
00038 
00039   for (int dx=0; dx<5; ++dx)
00040     {
00041       for (int dy=0; dy<3; ++dy)
00042         {
00043           const Square target(min_x+dx,min_y+dy);
00044           sum_effect += state.countEffect(attack, target) *
00045             Effect5x3_Table.getAttackEffect(attack,king,dx,dy);
00046         }
00047     }
00048   return sum_effect / 2;
00049 }
00050 
00051 int osl::progress::
00052 Effect5x3::makeProgressStand(Player attack, const NumEffectState& state)
00053 {  
00054   // 持駒
00055   int sum_pieces = 0;
00056   sum_pieces += state.countPiecesOnStand<PAWN>(attack)*Effect5x3Table::StandPAWN;
00057   sum_pieces += state.countPiecesOnStand<LANCE>(attack)*Effect5x3Table::StandLANCE;
00058   sum_pieces += state.countPiecesOnStand<KNIGHT>(attack)*Effect5x3Table::StandKNIGHT;
00059   sum_pieces += state.countPiecesOnStand<SILVER>(attack)*Effect5x3Table::StandSILVER;
00060   sum_pieces += state.countPiecesOnStand<GOLD>(attack)*Effect5x3Table::StandGOLD;
00061   sum_pieces += state.countPiecesOnStand<BISHOP>(attack)*Effect5x3Table::StandBISHOP;
00062   sum_pieces += state.countPiecesOnStand<ROOK>(attack)*Effect5x3Table::StandROOK;
00063   return sum_pieces;
00064 }
00065 
00066 void osl::progress::
00067 Effect5x3::updateStand(int& old_stand, Move last_move)
00068 {
00069   if (last_move.isDrop()) {
00070     const Ptype ptype = last_move.ptype();
00071     old_stand -= Effect5x3_Table.piecesOnStand(ptype);
00072     return;
00073   }
00074   const Ptype ptype = last_move.capturePtype();
00075   if (ptype == PTYPE_EMPTY) {
00076     return;
00077   }
00078   old_stand += Effect5x3_Table.piecesOnStand(unpromote(ptype));
00079 }
00080 
00081 void osl::progress::
00082 Effect5x3::update(const NumEffectState& new_state, Move last_move)
00083 {
00084   const Player pl = last_move.player();
00085   updateStand(stand_progresses[alt(pl)], last_move);
00086 
00087   const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
00088   BoardMask mb = new_state.changedEffects(BLACK), mw = new_state.changedEffects(WHITE);
00089   bool king_move = last_move.ptype() == KING;
00090   if ((king_move && new_state.turn() == BLACK) || mb.anyInRange(Board_Mask_Table5x3_Center.mask(kw)))
00091     area_progresses[WHITE]=makeProgressArea(BLACK,new_state, kw);
00092   if ((king_move && new_state.turn() == WHITE) || mw.anyInRange(Board_Mask_Table5x3_Center.mask(kb)))
00093     area_progresses[BLACK]=makeProgressArea(WHITE,new_state, kb);
00094 
00095   progresses[BLACK]=area_progresses[BLACK]+stand_progresses[BLACK];
00096   progresses[WHITE]=area_progresses[WHITE]+stand_progresses[WHITE];
00097 }
00098 
00099 osl::progress::Effect5x3 osl::progress::
00100 Effect5x3::expect(const NumEffectState&, Move move) const
00101 {
00102   Effect5x3 new_progress = *this;
00103   if (move.capturePtype() != PTYPE_EMPTY) {
00104     const Player alt_pl = alt(move.player());
00105     int old = stand_progresses[alt_pl];
00106     updateStand(new_progress.stand_progresses[alt_pl], move);
00107     new_progress.progresses[alt_pl] += new_progress.stand_progresses[alt_pl] - old;
00108   }
00109   return new_progress;
00110 }
00111 
00112 /* ------------------------------------------------------------------------- */
00113 
00114 osl::progress::
00115 Effect5x3WithBonus::Effect5x3WithBonus(const NumEffectState& state) : Effect5x3(state)
00116 {
00117   progress_bonuses[BLACK]=makeProgressAreaBonus<WHITE>(state, state.kingSquare<BLACK>());
00118   progress_bonuses[WHITE]=makeProgressAreaBonus<BLACK>(state, state.kingSquare<WHITE>());
00119   effect_mask[BLACK] = makeEffectMask<BLACK>(state);
00120   effect_mask[WHITE] = makeEffectMask<WHITE>(state);
00121   updateProgressBonuses(state);
00122 }
00123 
00124 template <osl::Player Defense>
00125 osl::container::PieceMask osl::progress::
00126 Effect5x3WithBonus::makeEffectMask(const NumEffectState &state)
00127 {
00128   const Square king =
00129     state.kingSquare<Defense>();
00130   const Square center =
00131     Centering5x3::adjustCenter(king);
00132 
00133   const int min_x = center.x() - 2;
00134   const int min_y = center.y() - 1;
00135 
00136   PieceMask mask;
00137   for (int dx = 0; dx < 5; ++dx)
00138   {
00139     for (int dy = 0; dy < 3; ++dy)
00140     {
00141       const Square target(min_x+dx, min_y+dy);
00142       mask = mask | state.effectSetAt(target);
00143     }
00144   }
00145   return mask;
00146 }
00147 
00148 inline
00149 int osl::progress::
00150 Effect5x3WithBonus::attackEffect3(const NumEffectState& state, Player attack, Square target)
00151 {
00152   const int a = state.countEffect(attack, target);
00153   if (a <= 1)
00154     return a;
00155   if (state.countEffect(alt(attack), target) > 0
00156       || state.pieceAt(target).isOnBoardByOwner(attack))
00157     return 1;
00158   return 2;
00159 }
00160 
00161 namespace osl
00162 {
00163   namespace
00164   {
00165     template <Player P>
00166     int countPawnLanceKnight(const NumEffectState& state, Square target) 
00167     {
00168       // effect is max 2, pawn and lance cannot have the effect
00169       // to a position at the same time so this is OK
00170       const Square d = target+DirectionPlayerTraits<D,P>::offset();
00171       const Piece pd = state.pieceAt(d);
00172 
00173       // pawn and lance
00174       int count = 0;
00175       if (pd.ptypeO() == newPtypeO(P,PAWN))
00176         ++count;
00177       else if (pd.ptypeO() == newPtypeO(P,LANCE))
00178         ++count;
00179       else if (pd.isEmpty()) 
00180       {
00181         if (state.hasLongEffectAt<LANCE>(P, target))
00182           ++count;
00183       }
00184       else if (pd.isEdge())
00185         return 0;
00186       
00187       // knight
00188       const Piece pdl = state.pieceAt(d+DirectionPlayerTraits<DL,P>::offset());
00189       if (pdl.ptypeO() == newPtypeO(P,KNIGHT))
00190         return count+1;
00191       const Piece pdr = state.pieceAt(d+DirectionPlayerTraits<DR,P>::offset());
00192       if (pdr.ptypeO() == newPtypeO(P,KNIGHT))
00193         return count+1;      
00194       return count;
00195     }
00196   }
00197 }
00198 
00199 template <osl::Player Attack, bool AlwaysPromotable, bool AlwaysNotPromotable>
00200 int osl::progress::
00201 Effect5x3WithBonus::makeProgressAreaBonus(const NumEffectState& state, Square king,
00202                                  Square center)
00203 {  
00204   const int min_x = center.x() - 2;
00205   const int min_y = center.y() - 1;
00206 
00207   // 利き
00208   int sum_effect = 0;
00209 
00210   for (int dy = 0; dy < 3; ++dy)
00211   {
00212     const Square target(king.x(), min_y + dy);
00213     int effect = attackEffect3(state, Attack, target) * 2;
00214     if (effect > 0)
00215     {
00216       if (! AlwaysPromotable
00217           && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
00218       {
00219         effect -= countPawnLanceKnight<Attack>(state, target);
00220         assert(effect >= 0);
00221       }
00222       sum_effect += effect *
00223         Effect5x3_Table.getAttackEffect(Attack, king, target.x() - min_x, dy) / 2;
00224 
00225     }
00226   }
00227   for (int x = king.x() - 1; x >= min_x; --x)
00228   {
00229     int y_count = 0;
00230     int sum = 0;
00231     for (int dy = 0; dy < 3; ++dy)
00232     {
00233       const Square target(x, min_y + dy);
00234       int effect = attackEffect3(state, Attack, target) * 2;
00235       if (effect > 0)
00236       {
00237         if (! AlwaysPromotable
00238             && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
00239         {
00240           if (king.x() - x > 1)
00241             effect = 0;
00242           else
00243             effect -= countPawnLanceKnight<Attack>(state, target);
00244           assert(effect >= 0);
00245         }
00246         sum += effect *
00247           Effect5x3_Table.getAttackEffect(Attack, king, x - min_x, dy) / 2;
00248         y_count++;
00249       }
00250     }
00251     sum_effect += sum;
00252     if (y_count == 3)
00253     {
00254       sum_effect += sum;
00255       break;
00256     }
00257   }
00258   for (int x = king.x() + 1; x < min_x + 5; ++x)
00259   {
00260     int y_count = 0;
00261     int sum = 0;
00262     for (int dy = 0; dy < 3; ++dy)
00263     {
00264       const Square target(x, min_y + dy);
00265       int effect = attackEffect3(state, Attack, target) * 2;
00266       if (effect > 0)
00267       {
00268         if (! AlwaysPromotable
00269             && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
00270         {
00271           if (x - king.x() > 1)
00272             effect = 0;
00273           else
00274             effect -= countPawnLanceKnight<Attack>(state, target);
00275           assert(effect >= 0);
00276         }
00277         sum += effect *
00278           Effect5x3_Table.getAttackEffect(Attack, king, x - min_x, dy) / 2;
00279         y_count++;
00280       }
00281     }
00282     sum_effect += sum;
00283     if (y_count == 3)
00284     {
00285       sum_effect += sum;
00286       break;
00287     }
00288   }
00289   return sum_effect / 2;
00290 }
00291 
00292 template <osl::Player Attack>
00293 int osl::progress::
00294 Effect5x3WithBonus::makeProgressAreaBonus(const NumEffectState& state,
00295                                           Square king)
00296 {  
00297   const Square center = Centering5x3::adjustCenter(king);
00298 
00299   const bool always_promotable = center.squareForBlack<Attack>().y() <= 2;
00300   if (always_promotable)
00301     return makeProgressAreaBonus<Attack,true,false>(state, king, center);
00302   const bool always_notpromotable = center.squareForBlack<Attack>().y() >= 5;
00303   if (always_notpromotable)
00304     return makeProgressAreaBonus<Attack,false,true>(state, king, center);
00305   return makeProgressAreaBonus<Attack,false,false>(state, king, center);
00306 }
00307 
00308 void osl::progress::
00309 Effect5x3WithBonus::update(const NumEffectState& new_state, Move last_move)
00310 {
00311   Effect5x3::update(new_state, last_move);
00312 
00313   const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
00314   BoardMask mask = new_state.changedEffects();
00315   mask.set(last_move.to()); mask.set(last_move.from());
00316 
00317   const bool update_black = mask.anyInRange(Board_Mask_Table5x3_Center.mask(kb));
00318   const bool update_white = mask.anyInRange(Board_Mask_Table5x3_Center.mask(kw));
00319   
00320   if (update_black) 
00321   {
00322     progress_bonuses[BLACK]=makeProgressAreaBonus<WHITE>(new_state,kb);
00323     effect_mask[BLACK] = makeEffectMask<BLACK>(new_state);
00324   }
00325   if (update_white) 
00326   {
00327     progress_bonuses[WHITE]=makeProgressAreaBonus<BLACK>(new_state,kw);
00328     effect_mask[WHITE] = makeEffectMask<WHITE>(new_state);
00329   }
00330   updateProgressBonuses(new_state, update_black, update_white);
00331 }
00332 
00333 osl::progress::Effect5x3WithBonus osl::progress::
00334 Effect5x3WithBonus::expect(const NumEffectState&, Move move) const
00335 {
00336   Effect5x3WithBonus new_progress = *this;
00337   if (move.capturePtype() != PTYPE_EMPTY) {
00338     const Player alt_pl = alt(move.player());
00339     int old = stand_progresses[playerToIndex(alt_pl)];
00340     new_progress.updateStand(alt_pl, move);
00341     new_progress.progresses[playerToIndex(alt_pl)] += new_progress.stand_progresses[playerToIndex(alt_pl)] - old;
00342   }
00343   return new_progress;
00344 }
00345 
00346 void osl::progress::
00347 Effect5x3WithBonus::updateProgressBonuses(const NumEffectState& state, bool update_black, bool update_white)
00348 {
00349   if (update_black && progress_bonuses[BLACK] != 0)
00350   {
00351     const int pieces = countEffectPieces(state, WHITE);
00352     progress_bonuses[BLACK] =
00353       std::min(pieces * pieces * 4,
00354                progress_bonuses[BLACK]);
00355   }
00356   if (update_white && progress_bonuses[WHITE] != 0)
00357   {
00358     const int pieces = countEffectPieces(state, BLACK);
00359     progress_bonuses[WHITE] =
00360       std::min(pieces * pieces * 4,
00361                progress_bonuses[WHITE]);
00362   }
00363 }
00364 
00365 int osl::progress::
00366 Effect5x3WithBonus::countEffectPieces(const NumEffectState &state, Player attack) const
00367 {
00368   PieceMask mask = effect5x3Mask(alt(attack));
00369   mask = mask & state.piecesOnBoard(attack);
00370   return mask.countBit();
00371 }
00372 
00373 /* ------------------------------------------------------------------------- */
00374 // ;;; Local Variables:
00375 // ;;; mode:c++
00376 // ;;; c-basic-offset:2
00377 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines