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