progressEval.cc
Go to the documentation of this file.
00001 /* progressEval.cc
00002  */
00003 #include "osl/eval/progressEval.h"
00004 #include "osl/container/pieceValues.h"
00005 #include "osl/state/numEffectState.h"
00006 #include "osl/oslConfig.h"
00007 #include <boost/filesystem.hpp>
00008 #include <iostream>
00009 #include <cstdio>
00010 
00011 BOOST_STATIC_ASSERT((osl::eval::ProgressEval::ROUND_UP 
00012                      & (osl::eval::ProgressEval::ROUND_UP-1))
00013                     == 0);
00014 #ifndef MINIMAL
00015 template <class Opening>
00016 osl::CArray<int, osl::PTYPEO_SIZE> osl::eval::ProgressEvalGeneral<Opening>::capture_values;
00017 
00018 template <class Opening>
00019 int osl::eval::
00020 ProgressEvalGeneral<Opening>::expect(const NumEffectState& state, Move move) const 
00021 {
00022   if (move.isPass())
00023     return value();
00024   progress_t new_progress = current_progress.expect(state, move);
00025   return composeValue(opening_eval.expect(state, move),
00026                       endgame_eval.expect(state, move), 
00027                       progress16(), new_progress.progress16(BLACK),
00028                       new_progress.progress16(WHITE),
00029                       defense_effect.progress16(BLACK),
00030                       defense_effect.progress16(WHITE),
00031                       minor_piece_bonus.value(progress16(),
00032                                               progress16bonus(BLACK),
00033                                               progress16bonus(WHITE)),
00034                       progress_independent_bonus,
00035                       progress_dependent_bonus);
00036 }
00037 
00038 template <class Opening>
00039 void osl::eval::
00040 ProgressEvalGeneral<Opening>::setUpInternal(const char *filename_given)
00041 {
00042   // read weights if exists
00043   std::string filename;
00044   if (filename_given)
00045     filename = filename_given;
00046   else {
00047     filename = OslConfig::home();
00048     filename += "/data/progresseval.txt";
00049   }
00050   if (boost::filesystem::exists(filename.c_str())) {
00051     if (OslConfig::verbose())
00052       std::cerr << "loading " << filename << "\n";
00053     CArray<int, AdjustableDimension> w;
00054     FILE *fp = fopen(filename.c_str(), "r");
00055     for (size_t i=0; i<w.size(); ++i) {
00056       if (fscanf(fp, "%d", &w[i]) != 1) {
00057         std::cerr << filename << " read failed " << i << "\n";
00058         break;
00059       }
00060     }
00061     fclose(fp);
00062     resetWeights(&w[0]);
00063   }
00064 
00065   // others
00066   for (int i=0; i<PTYPEO_SIZE; ++i) {
00067     // 序盤を使用
00068     const PtypeO ptypeo = static_cast<PtypeO>(i+PTYPEO_MIN);
00069     capture_values[i] = composeValue(opening_eval_t::captureValue(ptypeo), 0, 
00070                                      Progress16(0), Progress16(0), Progress16(0),
00071                                      Progress16(0), Progress16(0), 0, 0, 0);
00072   }
00073 }
00074 
00075 template <class Opening>
00076 void osl::eval::
00077 ProgressEvalGeneral<Opening>::resetWeights(const int *w)
00078 {
00079   opening_eval_t::resetWeights(w);
00080   endgame_eval_t::resetWeights(w+PTYPE_SIZE);
00081 }
00082 
00083 template <class Opening>
00084 osl::eval::
00085 ProgressEvalGeneral<Opening>::ProgressEvalGeneral(const NumEffectState& state) 
00086   : opening_eval(state), endgame_eval(state),
00087     current_progress(state), defense_effect(state),
00088     minor_piece_bonus(state), major_pieces(0),
00089     cache(INVALID)
00090 {
00091   for (int i = PtypeTraits<ROOK>::indexMin;
00092        i < PtypeTraits<ROOK>::indexLimit; ++i)
00093   {
00094     if (state.pieceOf(i).owner() == osl::BLACK)
00095       ++major_pieces;
00096   }
00097   for (int i = PtypeTraits<BISHOP>::indexMin;
00098        i < PtypeTraits<BISHOP>::indexLimit; ++i)
00099   {
00100     if (state.pieceOf(i).owner() == osl::BLACK)
00101       ++major_pieces;
00102   }
00103   can_check_pieces.fill(0);
00104   // knight and pawn are intentionally omitted
00105   initializeCheckPiece<BLACK, ROOK>(state);
00106   initializeCheckPiece<BLACK, BISHOP>(state);
00107   initializeCheckPiece<BLACK, GOLD>(state);
00108   initializeCheckPiece<BLACK, SILVER>(state);
00109   initializeCheckPiece<BLACK, LANCE>(state);
00110   initializeCheckPiece<WHITE, ROOK>(state);
00111   initializeCheckPiece<WHITE, BISHOP>(state);
00112   initializeCheckPiece<WHITE, GOLD>(state);
00113   initializeCheckPiece<WHITE, SILVER>(state);
00114   initializeCheckPiece<WHITE, LANCE>(state);
00115   rook_mobility = calculateMobilityBonusRook(state);
00116   bishop_mobility = calculateMobilityBonusBishop(state);
00117   lance_mobility = calculateMobilityBonusLance(state);
00118   progress_independent_bonus = calculateMobilityBonus();
00119   progress_independent_bonus += calculateAttackRooks(state);
00120   progress_independent_bonus += calculateSilverPenalty(state);
00121   progress_independent_bonus += calculateGoldPenalty(state);
00122   attack_bonus[BLACK] = calculateAttackBonusEach<WHITE>(state);
00123   attack_bonus[WHITE] = calculateAttackBonusEach<BLACK>(state);
00124   progress_dependent_bonus  = attackBonusScale(attack_bonus[BLACK], WHITE);
00125   progress_dependent_bonus += attackBonusScale(attack_bonus[WHITE], BLACK);
00126   progress_dependent_bonus += calculatePinBonus(state);
00127   progress_independent_bonus += calculateKnightCheck(state);
00128   progress_independent_bonus += calculateRookRankBonus(state);
00129   progress_independent_bonus += calculateEnterKingBonus<BLACK>(state);
00130   progress_independent_bonus += calculateEnterKingBonus<WHITE>(state);
00131   progress_independent_bonus += calculateMiddleKingBonus<BLACK>(state);
00132   progress_independent_bonus += calculateMiddleKingBonus<WHITE>(state);
00133   assert(initialized());
00134 }
00135 
00136 template <class Opening>
00137 template<osl::Player P, osl::Ptype PTYPE>
00138 void osl::eval::
00139 ProgressEvalGeneral<Opening>::initializeCheckPiece(
00140   const NumEffectState &state)
00141 {
00142   if (state.hasPieceOnStand<PTYPE>(P))
00143   {
00144     int count = state.countPiecesOnStand(P, PTYPE);
00145     initializeCheckPieceDir<P, PTYPE, UL, LONG_UL>(state, count);
00146     initializeCheckPieceDir<P, PTYPE, U, LONG_U>(state, count);
00147     initializeCheckPieceDir<P, PTYPE, UR, LONG_UR>(state, count);
00148     initializeCheckPieceDir<P, PTYPE, L, LONG_L>(state, count);
00149     initializeCheckPieceDir<P, PTYPE, R, LONG_R>(state, count);
00150     initializeCheckPieceDir<P, PTYPE, DL, LONG_DL>(state, count);
00151     initializeCheckPieceDir<P, PTYPE, D, LONG_D>(state, count);
00152     initializeCheckPieceDir<P, PTYPE, DR, LONG_DR>(state, count);
00153   }
00154 }
00155 
00156 template <class Opening>
00157 template<osl::Player P, osl::Ptype PTYPE, osl::Direction Dir, osl::Direction LongDir>
00158 void osl::eval::
00159 ProgressEvalGeneral<Opening>::initializeCheckPieceDir(
00160   const NumEffectState &,
00161   int count)
00162 {
00163   if (PtypeTraits<PTYPE>::moveMask & (DirectionTraits<Dir>::mask
00164                                       | DirectionTraits<LongDir>::mask))
00165     can_check_pieces[P][Dir] = count;
00166 }
00167 
00168 template <class Opening>
00169 int osl::eval::
00170 ProgressEvalGeneral<Opening>::calculateMobilityBonusRook(const NumEffectState& state)
00171 {
00172   using namespace osl::mobility;
00173   int val=0;
00174   for(int i=PtypeTraits<ROOK>::indexMin;
00175       i<PtypeTraits<ROOK>::indexLimit;++i){
00176     Piece p=state.pieceOf(i);
00177     if(p.isOnBoardByOwner<BLACK>()){
00178       int vc= RookMobility::countVerticalAll(BLACK,state,p);
00179       int hc= RookMobility::countHorizontalAll(BLACK,state,p);
00180       if(p.isPromoted()){
00181        val+=MobilityTable::prookVertical[vc];
00182        val+=MobilityTable::prookHorizontal[hc];
00183       }
00184       else{
00185        val+=MobilityTable::rookVertical[vc];
00186        val+=MobilityTable::rookHorizontal[hc];
00187       }
00188     }
00189     else if(p.isOnBoardByOwner<WHITE>()){
00190       int vc= RookMobility::countVerticalAll(WHITE,state,p);
00191       int hc= RookMobility::countHorizontalAll(WHITE,state,p);
00192       if(p.isPromoted()){
00193        val-=MobilityTable::prookVertical[vc];
00194        val-=MobilityTable::prookHorizontal[hc];
00195       }
00196       else{
00197        val-=MobilityTable::rookVertical[vc];
00198        val-=MobilityTable::rookHorizontal[hc];
00199       }
00200     }
00201   }
00202   return val;
00203 }
00204 
00205 template <class Opening>
00206 int osl::eval::
00207 ProgressEvalGeneral<Opening>::calculateMobilityBonusBishop(const NumEffectState& state)
00208 {
00209   using namespace osl::mobility;
00210   int val=0;
00211   for(int i=PtypeTraits<BISHOP>::indexMin;
00212       i<PtypeTraits<BISHOP>::indexLimit;++i){
00213     Piece p=state.pieceOf(i);
00214     if(p.isOnBoardByOwner<BLACK>()){
00215       int c= BishopMobility::countAll(BLACK,state,p);
00216       if(p.isPromoted())
00217        val+=MobilityTable::pbishop[c];
00218       else
00219        val+=MobilityTable::bishop[c];
00220     }
00221     else if(p.isOnBoardByOwner<WHITE>()){
00222       int c= BishopMobility::countAll(WHITE,state,p);
00223       if(p.isPromoted())
00224        val-=MobilityTable::pbishop[c];
00225       else
00226        val-=MobilityTable::bishop[c];
00227     }
00228   }
00229   return val;
00230 }
00231 
00232 template <class Opening>
00233 int osl::eval::
00234 ProgressEvalGeneral<Opening>::calculateMobilityBonusLance(const NumEffectState& state)
00235 {
00236   using namespace osl::mobility;
00237   int val=0;
00238   for(int i=PtypeTraits<LANCE>::indexMin;
00239       i<PtypeTraits<LANCE>::indexLimit;++i){
00240     Piece p=state.pieceOf(i);
00241     if(p.isOnBoardByOwner<BLACK>() && !p.isPromoted()){
00242       int c= LanceMobility::countAll(BLACK,state,p);
00243       val+=MobilityTable::lance[c];
00244     }
00245     else if(p.isOnBoardByOwner<WHITE>()  && !p.isPromoted()){
00246       int c= LanceMobility::countAll(WHITE,state,p);
00247       val-=MobilityTable::lance[c];
00248     }
00249   }
00250   return val;
00251 }
00252 
00253 template <class Opening> inline
00254 int osl::eval::
00255 ProgressEvalGeneral<Opening>::calculateMobilityBonus() const
00256 {
00257   using namespace osl::mobility;
00258   int val=rook_mobility + bishop_mobility + lance_mobility;
00259   return val*128/100 * 12;
00260 }
00261 
00262 template <class Opening>
00263 void osl::eval::
00264 ProgressEvalGeneral<Opening>::update(
00265   const NumEffectState& new_state, Move last_move)
00266 {
00267   if (last_move.isPass())
00268     return;
00269   const Ptype captured = last_move.capturePtype();
00270   if (last_move.isDrop())
00271   {
00272     const Ptype ptype = last_move.ptype();
00273     if (ptype == ROOK)
00274     {
00275       --can_check_pieces[playerToIndex(last_move.player())][U];
00276       --can_check_pieces[playerToIndex(last_move.player())][D];
00277       --can_check_pieces[playerToIndex(last_move.player())][L];
00278       --can_check_pieces[playerToIndex(last_move.player())][R];
00279     }
00280     else if (ptype == BISHOP)
00281     {
00282       --can_check_pieces[playerToIndex(last_move.player())][UL];
00283       --can_check_pieces[playerToIndex(last_move.player())][DL];
00284       --can_check_pieces[playerToIndex(last_move.player())][UR];
00285       --can_check_pieces[playerToIndex(last_move.player())][DR];
00286     }
00287     if (ptype == GOLD)
00288     {
00289       --can_check_pieces[playerToIndex(last_move.player())][U];
00290       --can_check_pieces[playerToIndex(last_move.player())][D];
00291       --can_check_pieces[playerToIndex(last_move.player())][L];
00292       --can_check_pieces[playerToIndex(last_move.player())][R];
00293       --can_check_pieces[playerToIndex(last_move.player())][UL];
00294       --can_check_pieces[playerToIndex(last_move.player())][UR];
00295     }
00296     else if (ptype == SILVER)
00297     {
00298       --can_check_pieces[playerToIndex(last_move.player())][U];
00299       --can_check_pieces[playerToIndex(last_move.player())][UL];
00300       --can_check_pieces[playerToIndex(last_move.player())][DL];
00301       --can_check_pieces[playerToIndex(last_move.player())][UR];
00302       --can_check_pieces[playerToIndex(last_move.player())][DR];
00303     }
00304     if (ptype == LANCE)
00305     {
00306       --can_check_pieces[playerToIndex(last_move.player())][U];
00307     }
00308   }
00309 
00310   if (captured != PTYPE_EMPTY)
00311   {
00312     const Ptype captured_base = unpromote(captured);
00313     if (isMajor(captured_base))
00314     {
00315       if (last_move.player() == BLACK)
00316         ++major_pieces;
00317       else
00318         --major_pieces;
00319     }
00320     if (captured_base == ROOK)
00321     {
00322       ++can_check_pieces[playerToIndex(last_move.player())][U];
00323       ++can_check_pieces[playerToIndex(last_move.player())][D];
00324       ++can_check_pieces[playerToIndex(last_move.player())][L];
00325       ++can_check_pieces[playerToIndex(last_move.player())][R];
00326     }
00327     else if (captured_base == BISHOP)
00328     {
00329       ++can_check_pieces[playerToIndex(last_move.player())][UL];
00330       ++can_check_pieces[playerToIndex(last_move.player())][DL];
00331       ++can_check_pieces[playerToIndex(last_move.player())][UR];
00332       ++can_check_pieces[playerToIndex(last_move.player())][DR];
00333     }
00334     if (captured_base == GOLD)
00335     {
00336       ++can_check_pieces[playerToIndex(last_move.player())][U];
00337       ++can_check_pieces[playerToIndex(last_move.player())][D];
00338       ++can_check_pieces[playerToIndex(last_move.player())][L];
00339       ++can_check_pieces[playerToIndex(last_move.player())][R];
00340       ++can_check_pieces[playerToIndex(last_move.player())][UL];
00341       ++can_check_pieces[playerToIndex(last_move.player())][UR];
00342     }
00343     else if (captured_base == SILVER)
00344     {
00345       ++can_check_pieces[playerToIndex(last_move.player())][U];
00346       ++can_check_pieces[playerToIndex(last_move.player())][UL];
00347       ++can_check_pieces[playerToIndex(last_move.player())][DL];
00348       ++can_check_pieces[playerToIndex(last_move.player())][UR];
00349       ++can_check_pieces[playerToIndex(last_move.player())][DR];
00350     }
00351     if (captured_base == LANCE)
00352     {
00353       ++can_check_pieces[playerToIndex(last_move.player())][U];
00354     }
00355   }
00356   opening_eval.update(new_state, last_move);
00357   endgame_eval.update(new_state, last_move);
00358   current_progress.update(new_state, last_move);
00359   defense_effect.update(new_state, last_move);
00360   minor_piece_bonus.update(new_state, last_move);
00361 
00362   if (new_state.longEffectChanged<ROOK>())
00363     rook_mobility = calculateMobilityBonusRook(new_state);
00364   if (new_state.longEffectChanged<BISHOP>())
00365     bishop_mobility = calculateMobilityBonusBishop(new_state);
00366   if (new_state.longEffectChanged<LANCE>())
00367     lance_mobility = calculateMobilityBonusLance(new_state);
00368 
00369   progress_independent_bonus = calculateMobilityBonus();
00370   progress_independent_bonus += calculateAttackRooks(new_state);
00371   progress_independent_bonus += calculateSilverPenalty(new_state);
00372   progress_independent_bonus += calculateGoldPenalty(new_state);
00373   
00374   {
00375     bool capture_or_drop = last_move.isDrop() || last_move.capturePtype() != PTYPE_EMPTY;
00376     const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
00377     BoardMask mask = new_state.changedEffects();
00378     mask.set(last_move.from()); mask.set(last_move.to());
00379     if ((capture_or_drop && new_state.turn() == BLACK)
00380         || mask.anyInRange(Board_Mask_Table3x3.mask(kb)))
00381       attack_bonus[BLACK] = calculateAttackBonusEach<WHITE>(new_state);
00382     if ((capture_or_drop && new_state.turn() == WHITE)
00383         || mask.anyInRange(Board_Mask_Table3x3.mask(kw)))
00384       attack_bonus[WHITE] = calculateAttackBonusEach<BLACK>(new_state);
00385   }
00386   progress_dependent_bonus  = attackBonusScale(attack_bonus[BLACK], WHITE);
00387   progress_dependent_bonus += attackBonusScale(attack_bonus[WHITE], BLACK);
00388   progress_dependent_bonus += calculatePinBonus(new_state);
00389   progress_independent_bonus += calculateKnightCheck(new_state);
00390   progress_independent_bonus += calculateRookRankBonus(new_state);
00391   progress_independent_bonus += calculateEnterKingBonus<BLACK>(new_state);
00392   progress_independent_bonus += calculateEnterKingBonus<WHITE>(new_state);
00393   progress_independent_bonus += calculateMiddleKingBonus<BLACK>(new_state);
00394   progress_independent_bonus += calculateMiddleKingBonus<WHITE>(new_state);
00395   invalidateCache();
00396 }
00397 
00398 template <class Opening>
00399 int osl::eval::
00400 ProgressEvalGeneral<Opening>::calculatePinBonus(
00401   const NumEffectState& state) const
00402 {
00403   const Piece black_king = state.kingPiece<BLACK>();
00404   const Piece white_king = state.kingPiece<WHITE>();
00405   int bonus = 0;
00406   PieceMask white_mask = pin_mask[WHITE] = state.pin(WHITE);
00407   PieceMask black_mask = pin_mask[BLACK] = state.pin(BLACK);
00408   while (white_mask.any())
00409   {
00410     const Piece piece = state.pieceOf(white_mask.takeOneBit());
00411     bonus -= endgame_eval.valueOf(
00412       black_king, white_king,
00413       piece) / 4;
00414   }
00415 
00416   while (black_mask.any())
00417   {
00418     const Piece piece = state.pieceOf(black_mask.takeOneBit());
00419     bonus -= endgame_eval.valueOf(
00420       black_king, white_king,
00421       piece) / 4;
00422   }
00423         
00424   return bonus * progress16().value() / 16;
00425 }
00426 
00427 template <class Opening>
00428 int osl::eval::
00429 ProgressEvalGeneral<Opening>::calculateAttackRooks(
00430   const NumEffectState& state) const
00431 {
00432   int rooks = 0;
00433   for(int i = PtypeTraits<ROOK>::indexMin;
00434       i < PtypeTraits<ROOK>::indexLimit; ++i)
00435   {
00436     const Piece rook = state.pieceOf(i);
00437     if (rook.isOnBoard() && rook.square().canPromote(rook.owner()) &&
00438         state.kingPiece(alt(rook.owner())).square().canPromote(rook.owner()))
00439     {
00440       if (rook.owner() == BLACK)
00441         ++rooks;
00442       else
00443         --rooks;
00444     }
00445   }
00446   if (rooks == 2)
00447     return (PtypeEvalTraits<KNIGHT>::val + PtypeEvalTraits<PAWN>::val) * 16;
00448   else if (rooks == -2)
00449     return -(PtypeEvalTraits<KNIGHT>::val + PtypeEvalTraits<PAWN>::val) * 16;
00450 
00451   return 0;
00452 }
00453 
00454 template <class Opening>
00455 int osl::eval::
00456 ProgressEvalGeneral<Opening>::calculateAttackBonus(
00457   const NumEffectState& state) const
00458 {
00459   return attackBonusScale(calculateAttackBonusEach<BLACK>(state), BLACK) +
00460     attackBonusScale(calculateAttackBonusEach<WHITE>(state), WHITE);
00461 }
00462 
00463 template <class Opening>
00464 template <osl::Player Attack, osl::Direction Dir>
00465 int osl::eval::
00466 ProgressEvalGeneral<Opening>::calculateAttackBonusOne(
00467   const NumEffectState& state) const
00468 {
00469   const Player defense = PlayerTraits<Attack>::opponent;
00470   const Square king = state.kingSquare<defense>();
00471 
00472   const Square target = king + DirectionPlayerTraits<Dir, defense>::offset();
00473   int result = 0;
00474 
00475   const Piece p = state.pieceAt(target);
00476   if (! p.isEdge() && (Dir != UUR || Attack != BLACK || p.isOnBoard()))
00477   {
00478     int effect_diff = (state.countEffect(Attack, target) -
00479                        state.countEffect(PlayerTraits<Attack>::opponent, target));
00480     if ((effect_diff >= 0 && p.isEmpty()) ||
00481         (effect_diff >= 1 && !p.isEmpty() &&
00482          p.owner() ==alt(Attack)))
00483     {
00484       if (Dir == UL || Dir == U || Dir == UR)
00485         result = PtypeEvalTraits<PAWN>::val * 3 * 16;
00486       else if (Dir == L || Dir == R)
00487         result = (PtypeEvalTraits<PAWN>::val * 1 +
00488                    PtypeEvalTraits<PAWN>::val / 2) * 16;
00489       else
00490         result = PtypeEvalTraits<PAWN>::val * 1 * 16;
00491 
00492       if ((effect_diff > 0 &&
00493            (target.canPromote<Attack>() ||
00494             state.hasEffectByPtype<GOLD>(Attack,target) ||
00495             state.hasEffectByPtype<SILVER>(Attack,target) ||
00496             state.hasEffectByPtype<ROOK>(Attack,target) ||
00497             state.hasEffectByPtype<BISHOP>(Attack,target))) ||
00498           (p.isEmpty() &&
00499            can_check_pieces[Attack][Dir] > 0))
00500         result += PtypeEvalTraits<PAWN>::val * 16;
00501     }
00502   }
00503 
00504   if (Attack == BLACK)
00505     return result;
00506   else
00507     return -result;
00508 }
00509 
00510 // P is attacking player
00511 template <class Opening>
00512 template <osl::Player P>
00513 int osl::eval::
00514 ProgressEvalGeneral<Opening>::calculateAttackBonusEach(
00515   const NumEffectState& state) const
00516 {
00517   int result = 0;
00518   result += calculateAttackBonusOne<P, UL>(state);
00519   result += calculateAttackBonusOne<P, U>(state);
00520   result += calculateAttackBonusOne<P, UR>(state);
00521   result += calculateAttackBonusOne<P, L>(state);
00522   result += calculateAttackBonusOne<P, R>(state);
00523   result += calculateAttackBonusOne<P, DL>(state);
00524   result += calculateAttackBonusOne<P, D>(state);
00525   result += calculateAttackBonusOne<P, DR>(state);
00526   return result;
00527 }
00528 
00529 template <class Opening>
00530 int osl::eval::
00531 ProgressEvalGeneral<Opening>::calculateSilverPenalty(
00532   const NumEffectState &state) const
00533 {
00534   int result = 0;
00535   const int bonus = PtypeEvalTraits<PAWN>::val / 4 * 16;
00536   for (int i = PtypeTraits<SILVER>::indexMin;
00537        i < PtypeTraits<SILVER>::indexLimit; ++i)
00538   {
00539     const Piece silver = state.pieceOf(i);
00540     if (!silver.isOnBoard() || silver.isPromoted())
00541       continue;
00542 
00543     if (silver.square().y() >= 4 && silver.square().y() <= 6)
00544     {
00545       Square dl = Board_Table.nextSquare(silver.owner(),
00546                                              silver.square(), DL);
00547       Square dr = Board_Table.nextSquare(silver.owner(),
00548                                              silver.square(), DR);
00549       if ((!dl.isOnBoard() ||
00550            state.pieceAt(dl).isOnBoardByOwner(silver.owner()) ||
00551            state.hasEffectAt(alt(silver.owner()), dl)) &&
00552           (!dr.isOnBoard() ||
00553            state.pieceAt(dr).isOnBoardByOwner(silver.owner()) ||
00554            state.hasEffectAt(alt(silver.owner()), dr)))
00555       {
00556         if (silver.owner() == BLACK)
00557           result -= bonus;
00558         else
00559           result += bonus;
00560       }
00561     }
00562             
00563   }
00564   return result;
00565 }
00566 
00567 template <class Opening>
00568 int osl::eval::
00569 ProgressEvalGeneral<Opening>::calculateGoldPenalty(
00570   const NumEffectState &state) const
00571 {
00572   int result = 0;
00573   const int bonus = PtypeEvalTraits<PAWN>::val / 4 * 16;
00574   for (int i = PtypeTraits<GOLD>::indexMin;
00575        i < PtypeTraits<GOLD>::indexLimit; ++i)
00576   {
00577     const Piece gold = state.pieceOf(i);
00578     if (!gold.isOnBoard())
00579       continue;
00580 
00581     if (gold.square().y() >= 4 && gold.square().y() <= 6)
00582     {
00583       Square d = Board_Table.nextSquare(gold.owner(),
00584                                             gold.square(), D);
00585       if ((state.pieceAt(d).isOnBoardByOwner(gold.owner()) ||
00586            state.hasEffectAt(alt(gold.owner()), d)))
00587       {
00588         if (gold.owner() == BLACK)
00589           result -= bonus;
00590         else
00591           result += bonus;
00592       }
00593     }
00594             
00595   }
00596   return result;
00597 }
00598 
00599 template <class Opening>
00600 int osl::eval::
00601 ProgressEvalGeneral<Opening>::calculateKnightCheck(
00602   const NumEffectState& state) const
00603 {
00604   return calculateKnightCheckEach<BLACK>(state) +
00605     calculateKnightCheckEach<WHITE>(state);
00606 }
00607 
00608 // P is attacking player
00609 template <class Opening>
00610 template <osl::Player P>
00611 int osl::eval::
00612 ProgressEvalGeneral<Opening>::calculateKnightCheckEach(
00613   const NumEffectState& state) const
00614 {
00615   const int bonus = (P == BLACK ? 1 : -1) *
00616     (PtypeEvalTraits<PAWN>::val * 3 + PtypeEvalTraits<PAWN>::val / 2) * 16;
00617   const Square king = state.kingSquare<PlayerTraits<P>::opponent>();
00618   const Square up = king +
00619     DirectionPlayerTraits<U,PlayerTraits<P>::opponent>::offset();
00620   if (!state.hasEffectAt<PlayerTraits<P>::opponent>(king)
00621       && ! state.pieceAt(up).isEdge())
00622   {
00623     const Square ur =
00624       up + DirectionPlayerTraits<UR,PlayerTraits<P>::opponent>::offset();
00625     if (! state.pieceAt(ur).isEdge() && 
00626         state.pieceAt(ur).isEmpty() &&
00627         !state.hasEffectAt<PlayerTraits<P>::opponent>(ur) &&
00628         (state.hasPieceOnStand<KNIGHT>(P) ||
00629          state.hasEffectByPtype<KNIGHT>(P, ur)))
00630     {
00631       if (state.hasPieceOnStand<GOLD>(P))
00632         return bonus;
00633       else
00634         return bonus / 2;
00635     }
00636 
00637     const Square ul =
00638       up + DirectionPlayerTraits<UL,PlayerTraits<P>::opponent>::offset();
00639     if (! state.pieceAt(ul).isEdge() &&
00640         state.pieceAt(ul).isEmpty() &&
00641         !state.hasEffectAt<PlayerTraits<P>::opponent>(ul) &&
00642         (state.hasPieceOnStand<KNIGHT>(P) ||
00643          state.hasEffectByPtype<KNIGHT>(P, ul)))
00644     {
00645       if (state.hasPieceOnStand<GOLD>(P))
00646         return bonus;
00647       else
00648         return bonus / 2;
00649     }
00650   }
00651   return 0;
00652 }
00653 
00654 // P is defense player
00655 template <class Opening>
00656 template <osl::Player P>
00657 int osl::eval::
00658 ProgressEvalGeneral<Opening>::calculateEnterKingBonus(
00659   const NumEffectState& state) const
00660 {
00661   const Square king = state.kingSquare<P>();
00662 
00663   if ((P == BLACK && king.y() > 4) ||
00664       (P == WHITE && king.y() < 6))
00665   {
00666     return 0;
00667   }
00668 
00669   // If not the last rank, check one rank above
00670   if ((P == BLACK && king.y() >= 2) ||
00671       (P == WHITE && king.y() <= 8))
00672   {
00673     const int y = P == BLACK ? king.y() - 1 : king.y() + 1;
00674     const int min_x = std::max(1, king.x() - 1);
00675     const int max_x = std::min(9, king.x() + 1);
00676     bool found_opening = false;
00677     for (int x = min_x; x <= max_x; ++x)
00678     {
00679       Square pos(x, y);
00680       Piece piece = state.pieceAt(pos);
00681       if (piece.isEmpty())
00682       {
00683         if (!state.hasEffectAt<PlayerTraits<P>::opponent>(pos))
00684           found_opening = true;
00685         else if (state.countEffect(P, pos) <=
00686                  state.countEffect(alt(P), pos))
00687           return 0;
00688       }
00689       else if (piece.owner() == alt(P))
00690       {
00691         return 0;
00692       }
00693       else if (piece.owner() == P)
00694       {
00695         if (state.countEffect(P, pos) <
00696             state.countEffect(alt(P), pos))
00697           return 0;
00698       }
00699       else
00700         abort();
00701     }
00702     if (!found_opening)
00703       return 0;
00704   }
00705 
00706   return PtypeEvalTraits<PAWN>::val * 16 * PlayerTraits<P>::offsetMul * 4;
00707 }
00708 
00709 // P is defense player
00710 template <class Opening>
00711 template <osl::Player P>
00712 int osl::eval::
00713 ProgressEvalGeneral<Opening>::calculateMiddleKingBonus(
00714   const NumEffectState& state) const
00715 {
00716   const Square king = state.kingSquare<P>();
00717 
00718   if ((P == BLACK && king.y() >= 6 && major_pieces == 4) ||
00719       (P == WHITE && king.y() <= 4 && major_pieces == 0))
00720   {
00721     return PtypeEvalTraits<PAWN>::val * 2 * 16 * PlayerTraits<P>::offsetMul;
00722   }
00723   return 0;
00724 }
00725 
00726 template<class Opening>
00727 int osl::eval::
00728 ProgressEvalGeneral<Opening>::calculateRookRankBonus(
00729   const NumEffectState& state) const
00730 {
00731   int bonus = 0;
00732   for (int i = PtypeTraits<ROOK>::indexMin;
00733        i < PtypeTraits<ROOK>::indexLimit; ++i)
00734   {
00735     const Piece rook = state.pieceOf(i);
00736     const Player owner = rook.owner();
00737     const int target_y = owner == BLACK ? 3 : 7;
00738     const int inbetween_y = owner == BLACK ? 4 : 6;
00739     if (rook.isOnBoard() && !rook.square().canPromote(owner))
00740     {
00741       const Piece rank5 = state.pieceAt(Square(rook.square().x(), 5));
00742       const Piece rank4 = state.pieceAt(Square(rook.square().x(),
00743                                                     inbetween_y));
00744       const Square rank3_pos(rook.square().x(), target_y);
00745       if (state.hasEffectByPtype<SILVER>(
00746             owner,
00747             Square(rook.square().x(),
00748             inbetween_y)) &&
00749           !rank5.isOnBoardByOwner(alt(owner)) &&
00750           !state.pieceAt(rank3_pos).isOnBoardByOwner(owner) &&
00751           state.countEffect(alt(owner), 
00752                             Square(rook.square().x(), target_y)) <= 1 &&
00753           state.countEffect(owner,
00754                             Square(rook.square().x(), inbetween_y)) >=
00755           state.countEffect(alt(owner),
00756                             Square(rook.square().x(), inbetween_y)))
00757       {
00758         if (rook.owner() == BLACK)
00759           bonus += PtypeEvalTraits<PAWN>::val * 2 * 16;
00760         else
00761           bonus -= PtypeEvalTraits<PAWN>::val * 2 * 16;
00762       }
00763       else if (((rank5.isOnBoardByOwner(owner) &&
00764                  rank5.ptype() == PAWN &&
00765                  state.hasEffectByPiece(rook, rank5.square())) ||
00766                 (rank4.isOnBoardByOwner(owner) &&
00767                  rank4.ptype() == PAWN &&
00768                  state.hasEffectByPiece(rook, rank4.square()))) &&
00769                !state.hasEffectAt(alt(owner),
00770                                       rank3_pos) &&
00771                   state.countEffect(alt(owner),
00772                                     Square(rook.square().x(),
00773                                                   inbetween_y)) <= 1)
00774       {
00775         if (rook.owner() == BLACK)
00776           bonus += PtypeEvalTraits<PAWN>::val * 2 * 16;
00777         else
00778           bonus -= PtypeEvalTraits<PAWN>::val * 2 * 16;
00779       }
00780       else if (state.hasEffectByPiece(rook, rank3_pos) &&
00781                !state.hasEffectAt(alt(owner), rank3_pos) &&
00782                !state.isPawnMaskSet(owner, rook.square().x()))
00783       {
00784         if (rook.owner() == BLACK)
00785           bonus += PtypeEvalTraits<PAWN>::val * 16;
00786         else
00787           bonus -= PtypeEvalTraits<PAWN>::val * 16;
00788       }
00789     }
00790   }
00791   return bonus;
00792 }
00793 
00794 template <class Opening>
00795 void osl::eval::
00796 ProgressEvalGeneral<Opening>::setValues(const SimpleState& state,
00797                                         Progress16 progress16,
00798                                         PieceValues& out)
00799 {
00800   PieceValues opening, endgame;
00801   const NumEffectState nstate(state);
00802   const progress_t progress(nstate);
00803   const defense_t defense_effect(nstate);
00804   const MinorPieceBonus minor_piece_bonus(state);
00805   opening_eval_t::setValues(state, opening);
00806   endgame_eval_t::setValues(state, endgame);
00807   for (int i=0; i<Piece::SIZE; ++i)
00808   {
00809     out[i] = composeValue(opening[i] & (~1), endgame[i] & (~1), progress16,
00810                           progress.progress16(BLACK),
00811                           progress.progress16(WHITE),
00812                           defense_effect.progress16(BLACK),
00813                           defense_effect.progress16(WHITE),
00814                           minor_piece_bonus.value(progress16,
00815                                                   progress.progress16bonus(BLACK),
00816                                                   progress.progress16bonus(WHITE)), 0, 0);
00817   }
00818 }
00819 
00820 template <class Opening>
00821 void osl::eval::
00822 ProgressEvalGeneral<Opening>::setValues(const SimpleState& state, PieceValues& out)
00823 {
00824   const NumEffectState nstate(state);
00825   const progress_t progress(nstate);
00826   setValues(state, progress.progress16(), out);
00827 }
00828 
00829 template <class Opening>
00830 osl::eval::ProgressDebugInfo osl::eval::
00831 ProgressEvalGeneral<Opening>::debugInfo(const NumEffectState& state) const
00832 {
00833   ProgressDebugInfo debug_info;
00834   debug_info.eval = value();
00835   debug_info.opening = openingValue();
00836   debug_info.endgame = endgameValue();
00837   debug_info.progress = current_progress.progress16().value();
00838   debug_info.progress_bonus = attackDefenseBonus();
00839   debug_info.progress_independent_bonus = progress_independent_bonus;
00840   debug_info.progress_dependent_bonus = progress_dependent_bonus;
00841   debug_info.minor_piece_bonus = minorPieceValue();
00842 
00843   debug_info.black_danger = current_progress.progress16bonus(BLACK).value();
00844   debug_info.white_danger = current_progress.progress16bonus(WHITE).value();
00845   debug_info.black_defense = defense_effect.progress16(BLACK).value();
00846   debug_info.white_defense = defense_effect.progress16(WHITE).value();
00847 
00848   debug_info.mobility_bonus = calculateMobilityBonus();
00849   debug_info.two_rook_bonus = calculateAttackRooks(state);
00850   debug_info.knight_check_bonus = calculateKnightCheck(state);
00851   debug_info.rook_rank_bonus = calculateRookRankBonus(state);
00852   debug_info.enter_king_bonus = calculateEnterKingBonus<BLACK>(state) +
00853     calculateEnterKingBonus<WHITE>(state);
00854   debug_info.middle_king_bonus = calculateMiddleKingBonus<BLACK>(state) +
00855     calculateMiddleKingBonus<WHITE>(state);
00856   debug_info.silver_penalty = calculateSilverPenalty(state);
00857   debug_info.gold_penalty = calculateGoldPenalty(state);
00858 
00859   debug_info.king8_attack_bonus = calculateAttackBonus(state);
00860   debug_info.pin_bonus = calculatePinBonus(state);
00861 
00862   debug_info.minor_piece_bonus_info =
00863     minor_piece_bonus.debugInfo(progress16(),
00864                                 progress16bonus(BLACK),
00865                                 progress16bonus(WHITE));
00866 
00867   return debug_info;
00868 }
00869 
00870 namespace osl
00871 {
00872   namespace eval
00873   {
00874     template class ProgressEvalGeneral<progress_eval_opening_t>;
00875   }
00876 }
00877 #endif
00878 /* ------------------------------------------------------------------------- */
00879 // ;;; Local Variables:
00880 // ;;; mode:c++
00881 // ;;; c-basic-offset:2
00882 // ;;; coding:utf-8
00883 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines