00001
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
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
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
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
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
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
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
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
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
00889
00890
00891
00892