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