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