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