00001
00002
00003
00004 #ifndef EVAL_ML_OPENMIDENDINGEVAL_H
00005 #define EVAL_ML_OPENMIDENDINGEVAL_H
00006
00007 #include "osl/eval/ml/weights.h"
00008 #include "osl/eval/ml/pieceEval.h"
00009 #include "osl/eval/ml/evalStagePair.h"
00010 #include "osl/eval/evalTraits.h"
00011 #include "osl/eval/pieceEval.h"
00012 #include "osl/state/numEffectState.h"
00013 #include "osl/progress/progress32.h"
00014 #include "osl/progress/effect5x3.h"
00015 #include "osl/progress/ml/newProgress.h"
00016 #include "osl/container/tripleInt.h"
00017 #include "osl/oslConfig.h"
00018
00019 #define USE_TEST_PROGRESS
00020
00021 #define LEARN_TEST_PROGRESS
00022
00023 namespace osl
00024 {
00025 namespace eval
00026 {
00027 namespace ml
00028 {
00029 using namespace osl::progress::ml;
00030 class OpenMidEndingPtypeTable : public PtypeEvalTable
00031 {
00032 public:
00033 OpenMidEndingPtypeTable();
00034 };
00035
00036 struct OpenMidEndingEvalDebugInfo
00037 {
00038 enum StageFeature
00039 {
00040 KING_PIECE_RELATIVE,
00041 PIECE_STAND,
00042 KING25_EFFECT_EACH,
00043 PTYPEX,
00044 PTYPEY,
00045 ROOK_MOBILITY,
00046 BISHOP_MOBILITY,
00047 LANCE_MOBILITY,
00048 ROOK_EFFECT,
00049 BISHOP_EFFECT,
00050 PIECE_STAND_COMBINATION,
00051 PIECE_STAND_TURN,
00052 ROOK_PAWN,
00053 PAWN_DROP,
00054 PIECE_STAND_Y,
00055 KNIGHT_CHECK,
00056 PAWN_ADVANCE,
00057 PAWN_PTYPEO,
00058 PROMOTED_MINOR_PIECE,
00059 KING_PIECE_RELATIVE_NOSUPPORT,
00060 NON_PAWN_ATTACKED,
00061 NON_PAWN_ATTACKED_PTYPE,
00062 PTYPE_YY,
00063 KING3PIECES,
00064 BISHOP_HEAD,
00065 KNIGHT_HEAD,
00066 ROOK_PROMOTE_DEFENSE,
00067 PTYPE_COUNT,
00068 LANCE_EFFECT_PIECE,
00069 PTYPE_Y_PAWN_Y,
00070 BISHOP_AND_KING,
00071 PIECE_FORK_TURN,
00072 ROOK_SILVER_KNIGHT,
00073 BISHOP_SILVER_KNIGHT,
00074 KING25_EFFECT_SUPPORTED,
00075 KING_ROOK_BISHOP,
00076 KING_X_BLOCKED3,
00077 GOLD_RETREAT,
00078 SILVER_RETREAT,
00079 ALL_GOLD,
00080 ALL_MAJOR,
00081 KING25_EFFECT_DEFENSE,
00082 ANAGUMA_EMPTY,
00083 NO_PAWN_ON_STAND,
00084 NON_PAWN_PIECE_STAND,
00085 PIN_PTYPE_ALL,
00086 KING_MOBILITY,
00087 GOLD_AND_SILVER_NEAR_KING,
00088 PTYPE_COMBINATION,
00089 KING25_BOTH_SIDE,
00090 KING25_MOBILITY,
00091 BISHOP_STAND_FILE5,
00092 MAJOR_CHECK_WITH_CAPTURE,
00093 SILVER_ADVANCE26,
00094 KING25_EFFECT3,
00095 BISHOP_BISHOP_PIECE,
00096 ROOK_ROOK,
00097 ROOK_ROOK_PIECE,
00098 KING25_EFFECT_COUNT_COMBINATION,
00099 NON_PAWN_ATTACKED_PTYPE_PAIR,
00100 ATTACK_MAJORS_IN_BASE,
00101 STAGE_FEATURE_LIMIT
00102 };
00103 enum ProgressIndependentFeature
00104 {
00105 PIECE,
00106 BISHOP_EXCHANGE_SILVER_KING,
00107 ENTER_KING_DEFENSE,
00108 KING25_EFFECT_ATTACK,
00109 PIECE_PAIR,
00110 PIECE_PAIR_KING,
00111 PROGRESS_INDEPENDENT_FEATURE_LIMIT
00112 };
00113 int value;
00114 int progress;
00115 CArray<int, PROGRESS_INDEPENDENT_FEATURE_LIMIT> progress_independent_values;
00116 CArray<MultiInt, STAGE_FEATURE_LIMIT> stage_values;
00117
00118 static const char *name(ProgressIndependentFeature);
00119 static const char *name(StageFeature);
00120 };
00121
00122 class OpenMidEndingEval
00123 {
00124 private:
00125 enum { INVALID=EvalTraits<BLACK>::MAX_VALUE+1 };
00126 enum {
00128 ProgressIndependentValueLimit = 4000
00129 };
00130 enum LoadStatus { Zero=0, Loaded, Random };
00131 static volatile LoadStatus initialized_flag;
00132 static Weights piece_pair_weights;
00133 #ifdef USE_TEST_PROGRESS
00134 typedef osl::progress::ml::NewProgress progress_t;
00135 #else
00136 typedef osl::progress::Effect5x3 progress_t;
00137 #endif
00138 progress_t progress;
00139 MultiIntPair kingx_blocked, king25_effect_each;
00140 MultiIntPair king25_both_side,king_rook_bishop;
00141 MultiIntPair piece_stand_turn, non_pawn_attacked,
00142 non_pawn_attacked_ptype, piece_fork_turn;
00143 MultiInt ptypey, ptypex, king_table_value;
00144 MultiInt piece_stand_value, recalculated_stage_value, pawn_advance;
00145 MultiInt rook_mobility, bishop_mobility, lance_mobility;
00146 MultiInt knight_advance, pawn_drop, promoted_minor_piece, rook_pawn,
00147 rook_effect, bishop_effect, bishop_head, nosupport, ptype_yy, king3pieces;
00148 MultiInt rook_promote_defense;
00149 MultiInt piece_stand_combination, piece_stand_y, knight_check,
00150 knight_head, pawn_ptypeo, ptype_count_value, lance_effect_piece,
00151 ptype_y_pawn_y, bishop_and_king, rook_silver_knight, bishop_silver_knight;
00152 CArray<BoardMask, 2> knight_fork_squares;
00153 CArray<PieceMask, 2> effect25;
00154 CArray<PieceMask, 2> effect25_supported;
00155 CArray<PieceMask, 2> effected_mask;
00156 CArray<PieceMask, 2> effected_mask_for_attacked;
00157 CArray<PieceMask, 40> attacked_mask;
00158 CArray<int, 5> black_vertical, white_vertical,
00159 black_king_vertical, white_king_vertical;
00160
00161 CArray<int,2> piece_pair_king_value;
00162 CArray<int, 2> non_pawn_stand_count;
00163 CArray2d<int, 2, 3> gs_near_king_count;
00164 CArray2d<int, 2, PTYPE_SIZE> ptype_count, ptype_board_count;
00165 CArray<std::pair<Square,int>, 2> knight_drop, silver_drop, bishop_drop, rook_drop;
00166 CArray2d<int, 2, 9> pawns;
00167 int progress_independent_value,
00168 recalculated_value, piece_pair_value;
00169 int black_pawn_count;
00170 int black_major_count, black_gold_count;
00171 int black_attack_effect, black_attack_piece,
00172 white_attack_effect, white_attack_piece,
00173 black_attack_supported_piece, white_attack_supported_piece;
00174 int black_defense_effect, black_defense_piece,
00175 white_defense_effect, white_defense_piece;
00176 mutable int cache;
00177 Player turn;
00178 unsigned int ptypeo_mask;
00179 CArray<bool, 2> can_check;
00180 bool use_progress_independent_value_limit;
00181 static const int ROUND_UP = 2;
00182 static int roundUp(int v)
00183 {
00184 return v & (~(ROUND_UP-1));
00185 }
00186 void updateGoldSilverNearKing(const NumEffectState &state)
00187 {
00188 const CArray<Square,2> kings = {{
00189 state.kingSquare(BLACK),
00190 state.kingSquare(WHITE),
00191 }};
00192 gs_near_king_count.fill(0);
00193 for (int i = PtypeTraits<GOLD>::indexMin;
00194 i < PtypeTraits<GOLD>::indexLimit; ++i)
00195 {
00196 const Piece p = state.pieceOf(i);
00197 if (p.isOnBoard())
00198 {
00199 const Square pos = p.square();
00200 const int y_diff = std::abs(pos.y() - kings[p.owner()].y());
00201 const int x_diff = std::abs(pos.x() - kings[p.owner()].x());
00202 if (y_diff <= 2 && x_diff <= 3)
00203 {
00204 ++gs_near_king_count[p.owner()][std::max(x_diff, y_diff) - 1];
00205 }
00206 }
00207 }
00208 for (int i = PtypeTraits<SILVER>::indexMin;
00209 i < PtypeTraits<SILVER>::indexLimit; ++i)
00210 {
00211 const Piece p = state.pieceOf(i);
00212 if (p.isOnBoard())
00213 {
00214 const Square pos = p.square();
00215 const int y_diff = std::abs(pos.y() - kings[p.owner()].y());
00216 const int x_diff = std::abs(pos.x() - kings[p.owner()].x());
00217 if (y_diff <= 2 && x_diff <= 3)
00218 {
00219 ++gs_near_king_count[p.owner()][std::max(x_diff, y_diff) - 1];
00220 }
00221 }
00222 }
00223 }
00224 public:
00225 explicit OpenMidEndingEval(const NumEffectState &state, bool limit_progress_independent_value=! OslConfig::hasByoyomi());
00226 void changeTurn() { }
00227 static bool initialized()
00228 {
00229 return initialized_flag;
00230 }
00231 static bool setUp(const char *filename);
00232 static bool setUp();
00233 static std::string defaultFilename();
00234 int progressIndependentValue() const
00235 {
00236 return progress_independent_value + recalculated_value + piece_pair_value
00237 + piece_pair_king_value[BLACK] + piece_pair_king_value[WHITE];
00238 }
00239 void debug() const;
00240 MultiInt stageValue() const
00241 {
00242 return king_table_value + piece_stand_value +
00243 king25_effect_each[BLACK] + king25_effect_each[WHITE] +
00244 ptypex + ptypey + rook_mobility + bishop_mobility + lance_mobility +
00245 rook_effect + bishop_effect +
00246 piece_stand_combination + piece_stand_turn[turn] +
00247 rook_pawn + pawn_drop + piece_stand_y + knight_check +
00248 pawn_advance + pawn_ptypeo + promoted_minor_piece +
00249 nosupport +
00250 non_pawn_attacked[turn] + non_pawn_attacked_ptype[turn] +
00251 ptype_yy + king3pieces + bishop_head + knight_head
00252 + rook_promote_defense +
00253 ptype_count_value + lance_effect_piece + ptype_y_pawn_y +
00254 bishop_and_king + piece_fork_turn[turn] + rook_silver_knight + bishop_silver_knight +
00255 recalculated_stage_value;
00256 }
00257 int openingValue() const
00258 {
00259 return (king_table_value[0] +
00260 piece_stand_value[0] +
00261 king25_effect_each[BLACK][0] + king25_effect_each[WHITE][0] +
00262 ptypex[0] +
00263 ptypey[0] +
00264 rook_mobility[0] +
00265 bishop_mobility[0] +
00266 lance_mobility[0] +
00267 rook_effect[0] +
00268 bishop_effect[0] +
00269 piece_stand_combination[0] +
00270 piece_stand_turn[turn][0] +
00271 rook_pawn[0] +
00272 pawn_drop[0] +
00273 piece_stand_y[0] +
00274 knight_check[0] +
00275 pawn_advance[0] +
00276 pawn_ptypeo[0] +
00277 promoted_minor_piece[0] +
00278 nosupport[0] +
00279 non_pawn_attacked[turn][0] +
00280 non_pawn_attacked_ptype[turn][0] +
00281 ptype_yy[0] +
00282 king3pieces[0] +
00283 bishop_head[0] +
00284 knight_head[0] +
00285 rook_promote_defense[0] +
00286 ptype_count_value[0] +
00287 lance_effect_piece[0] +
00288 ptype_y_pawn_y[0] +
00289 bishop_and_king[0] +
00290 piece_fork_turn[turn][0] +
00291 rook_silver_knight[0] +
00292 bishop_silver_knight[0] +
00293 recalculated_stage_value[0]);
00294 }
00295 int midgameValue() const
00296 {
00297 return (king_table_value[1] +
00298 piece_stand_value[1] +
00299 king25_effect_each[BLACK][1] + king25_effect_each[WHITE][1] +
00300 ptypex[1] +
00301 ptypey[1] +
00302 rook_mobility[1] +
00303 bishop_mobility[1] +
00304 lance_mobility[1] +
00305 rook_effect[1] +
00306 bishop_effect[1] +
00307 piece_stand_combination[1] +
00308 piece_stand_turn[turn][1] +
00309 rook_pawn[1] +
00310 pawn_drop[1] +
00311 piece_stand_y[1] +
00312 knight_check[1] +
00313 pawn_advance[1] +
00314 pawn_ptypeo[1] +
00315 promoted_minor_piece[1] +
00316 nosupport[1] +
00317 non_pawn_attacked[turn][1] +
00318 non_pawn_attacked_ptype[turn][1] +
00319 ptype_yy[1] +
00320 king3pieces[1] +
00321 bishop_head[1] +
00322 knight_head[1] +
00323 rook_promote_defense[1] +
00324 ptype_count_value[1] +
00325 lance_effect_piece[1] +
00326 ptype_y_pawn_y[1] +
00327 bishop_and_king[1] +
00328 piece_fork_turn[turn][1] +
00329 rook_silver_knight[1] +
00330 bishop_silver_knight[1] +
00331 recalculated_stage_value[1]);
00332 }
00333 int midgame2Value() const
00334 {
00335 return (king_table_value[2] +
00336 piece_stand_value[2] +
00337 king25_effect_each[BLACK][2] + king25_effect_each[WHITE][2] +
00338 ptypex[2] +
00339 ptypey[2] +
00340 rook_mobility[2] +
00341 bishop_mobility[2] +
00342 lance_mobility[2] +
00343 rook_effect[2] +
00344 bishop_effect[2] +
00345 piece_stand_combination[2] +
00346 piece_stand_turn[turn][2] +
00347 rook_pawn[2] +
00348 pawn_drop[2] +
00349 piece_stand_y[2] +
00350 knight_check[2] +
00351 pawn_advance[2] +
00352 pawn_ptypeo[2] +
00353 promoted_minor_piece[2] +
00354 nosupport[2] +
00355 non_pawn_attacked[turn][2] +
00356 non_pawn_attacked_ptype[turn][2] +
00357 ptype_yy[2] +
00358 king3pieces[2] +
00359 bishop_head[2] +
00360 knight_head[2] +
00361 rook_promote_defense[2] +
00362 ptype_count_value[2] +
00363 lance_effect_piece[2] +
00364 ptype_y_pawn_y[2] +
00365 bishop_and_king[2] +
00366 piece_fork_turn[turn][2] +
00367 rook_silver_knight[2] +
00368 bishop_silver_knight[2] +
00369 recalculated_stage_value[2]);
00370 }
00371 int endgameValue() const
00372 {
00373 return (king_table_value[EndgameIndex] +
00374 piece_stand_value[EndgameIndex] +
00375 king25_effect_each[BLACK][EndgameIndex] + king25_effect_each[WHITE][EndgameIndex] +
00376 ptypex[EndgameIndex] +
00377 ptypey[EndgameIndex] +
00378 rook_mobility[EndgameIndex] +
00379 bishop_mobility[EndgameIndex] +
00380 lance_mobility[EndgameIndex] +
00381 rook_effect[EndgameIndex] +
00382 bishop_effect[EndgameIndex] +
00383 piece_stand_combination[EndgameIndex] +
00384 piece_stand_turn[turn][EndgameIndex] +
00385 rook_pawn[EndgameIndex] +
00386 pawn_drop[EndgameIndex] +
00387 piece_stand_y[EndgameIndex] +
00388 pawn_advance[EndgameIndex] +
00389 knight_check[EndgameIndex] +
00390 pawn_ptypeo[EndgameIndex] +
00391 promoted_minor_piece[EndgameIndex] +
00392 nosupport[EndgameIndex] +
00393 non_pawn_attacked[turn][EndgameIndex] +
00394 non_pawn_attacked_ptype[turn][EndgameIndex] +
00395 ptype_yy[EndgameIndex] +
00396 king3pieces[EndgameIndex] +
00397 bishop_head[EndgameIndex] +
00398 knight_head[EndgameIndex] +
00399 rook_promote_defense[EndgameIndex] +
00400 ptype_count_value[EndgameIndex] +
00401 lance_effect_piece[EndgameIndex] +
00402 ptype_y_pawn_y[EndgameIndex] +
00403 bishop_and_king[EndgameIndex] +
00404 piece_fork_turn[turn][EndgameIndex] +
00405 rook_silver_knight[EndgameIndex] +
00406 bishop_silver_knight[EndgameIndex] +
00407 recalculated_stage_value[EndgameIndex]);
00408 }
00409 void invalidateCache() { cache=INVALID; }
00410 static int progressIndependentValueAdjusted(int value, int progress,
00411 int progress_max)
00412 {
00413 if (value > ProgressIndependentValueLimit) {
00414 int diff = value - ProgressIndependentValueLimit;
00415 value = ProgressIndependentValueLimit
00416 + diff * progress/progress_max;
00417 }
00418 else if (value < -ProgressIndependentValueLimit) {
00419 int diff = value + ProgressIndependentValueLimit;
00420 value = -ProgressIndependentValueLimit
00421 + diff * progress/progress_max;
00422 }
00423 return value;
00424 }
00425 int composeOpenMidEndgame() const
00426 {
00427 const int progress_max = NewProgress::maxProgress(), c = progress_max/2;
00428 const int progress = this->progress.progress();
00429 int progress_independent = use_progress_independent_value_limit
00430 ? progressIndependentValueAdjusted
00431 (progressIndependentValue(), progress, progress_max)
00432 : progressIndependentValue();
00433 int sum = progress_independent * progress_max;
00434 if (progress < c)
00435 {
00436 sum += openingValue() * 2*(c - progress);
00437 sum += midgameValue() * 2*progress;
00438 }
00439 else
00440 {
00441 sum += midgameValue() * 2*(progress_max - progress);
00442 sum += endgameValue() * 2*(progress - c);
00443 }
00444 return sum;
00445 }
00446 #ifdef EVAL_QUAD
00447 int composeOpenMid2Endgame() const
00448 {
00449 const int progress_max = NewProgress::maxProgress();
00450 const int progress = this->progress.progress();
00451 const int c0 = progress_max/3, c1 = c0*2;
00452 #ifndef NDEBUG
00453 const int w2 = progress_max - c1;
00454 #endif
00455 assert(c0 == w2);
00456 int progress_independent = use_progress_independent_value_limit
00457 ? progressIndependentValueAdjusted
00458 (progressIndependentValue(), progress, progress_max)
00459 : progressIndependentValue();
00460 int sum = progress_independent * c0;
00461 const MultiInt stage_sum = stageValue();
00462 if (progress < c0)
00463 {
00464 sum += stage_sum[0] * (c0 - progress);
00465 sum += stage_sum[1] * progress;
00466 }
00467 else if (progress < c1)
00468 {
00469 sum += stage_sum[1] * (c1 - progress);
00470 sum += stage_sum[2] * (progress-c0);
00471 }
00472 else
00473 {
00474 sum += stage_sum[2] * (progress_max - progress);
00475 sum += stage_sum[3] * (progress - c1);
00476 }
00477 return sum;
00478 }
00479 #endif
00480 int value() const
00481 {
00482 if (cache==INVALID)
00483 {
00484 #ifdef USE_TEST_PROGRESS
00485 # ifdef EVAL_QUAD
00486 cache = roundUp(composeOpenMid2Endgame());
00487 # else
00488 cache = roundUp(composeOpenMidEndgame());
00489 # endif
00490 #else
00491 # ifdef EVAL_QUAD
00492 # error "not supported"
00493 # else
00494 cache = roundUp(progressIndependentValue() * 16 +
00495 openingValue() * (16 - progress.progress16().value()) +
00496 endgameValue() * progress.progress16().value());
00497 # endif
00498 #endif
00499 }
00500 return cache;
00501 }
00502 const Move suggestMove(const NumEffectState& state) const
00503 {
00504 assert(turn == state.turn());
00505 Move suggest;
00506 int best_value = 0;
00507 if (! rook_drop[turn].first.isPieceStand()) {
00508 assert(state.hasPieceOnStand(turn, ROOK));
00509 suggest = Move(rook_drop[turn].first, ROOK, turn);
00510 best_value = rook_drop[turn].second;
00511 }
00512 assert(best_value >= 0);
00513 if (bishop_drop[turn].second > best_value) {
00514 assert(! bishop_drop[turn].first.isPieceStand());
00515 assert(state.hasPieceOnStand(turn, BISHOP));
00516 suggest = Move(bishop_drop[turn].first, BISHOP, turn);
00517 best_value = bishop_drop[turn].second;
00518 }
00519 if (silver_drop[turn].second > best_value) {
00520 assert(! silver_drop[turn].first.isPieceStand());
00521 assert(state.hasPieceOnStand(turn, SILVER));
00522 suggest = Move(silver_drop[turn].first, SILVER, turn);
00523 best_value = silver_drop[turn].second;
00524 }
00525 if (knight_drop[turn].second > best_value
00526 && state.hasPieceOnStand(turn, KNIGHT)) {
00527 assert(! knight_drop[turn].first.isPieceStand());
00528 suggest = Move(knight_drop[turn].first, KNIGHT, turn);
00529 best_value = knight_drop[turn].second;
00530 }
00531 return suggest;
00532 }
00533 int expect(const NumEffectState &state, Move move) const;
00534 template<Player P>
00535 void updateSub(const NumEffectState &new_state, Move last_move);
00536 void update(const NumEffectState &new_state, Move last_move);
00537 const Progress32 progress32() const
00538 {
00539 return Progress32(progress.progress16(BLACK).value()
00540 + progress.progress16(WHITE).value());
00541 }
00542 const Progress16 progress16() const { return progress.progress16(); }
00543 public:
00544 static int infty()
00545 {
00546 #ifdef USE_TEST_PROGRESS
00547 # ifdef EVAL_QUAD
00548 assert(NewProgress::maxProgress() % 3 == 0);
00549 return 57984 * (NewProgress::maxProgress()/3);
00550 # else
00551 return 57984 * NewProgress::maxProgress();
00552 # endif
00553 #else
00554 return 57984 * 16;
00555 #endif
00556 }
00557 static int captureValue(PtypeO ptypeO) {
00558 assert(isValidPtypeO(ptypeO));
00559 return roundUp((-PieceEval::value(ptypeO) +
00560 PieceEval::value(captured(ptypeO))) * seeScale());
00561 }
00562 static int seeScale() {
00563 #ifdef USE_TEST_PROGRESS
00564 # ifdef EVAL_QUAD
00565 assert(NewProgress::maxProgress() % 3 == 0);
00566 return (NewProgress::maxProgress()/3);
00567 # else
00568 return NewProgress::maxProgress();
00569 # endif
00570 #else
00571 return 16;
00572 #endif
00573 }
00574
00575 OpenMidEndingEvalDebugInfo debugInfo(const NumEffectState &state);
00576 static void setRandom();
00577 static void resetWeights(const int *w, size_t length);
00578 static OpenMidEndingPtypeTable Piece_Value;
00579 bool progressIndependentValueLimit() const {
00580 return use_progress_independent_value_limit;
00581 }
00582 private:
00583 template <class Reader>
00584 static void doResetWeights(Reader& reader);
00585 };
00586 }
00587 }
00588 }
00589
00590 #endif // EVAL_ML_OPENMIDENDINGEVAL_H
00591
00592
00593
00594
00595