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
00039 {
00040 EVAL, OPENING, ENDGAME, PROGRESS_INDEPENDENT,
00041 PROGRESS,
00042
00043 PIECE, ROOK_MOBILITY, BISHOP_MOBILITY, LANCE_MOBILITY,
00044 PIECE_PAIR, KING25_EFFECT,
00045
00046 KING_PIECE_OPENING, KING_PIECE_ENDING,
00047 PIECE_STAND_OPENING, PIECE_STAND_ENDING,
00048 PAWN_DROP_OPENING, PAWN_DROP_ENDING,
00049 PTYPE_X_OPENING, PTYPE_X_ENDING,
00050 PTYPE_Y_OPENING, PTYPE_Y_ENDING,
00051 KING25_EACH_OPENING, KING25_EACH_ENDING,
00052 NO_PAWN_OPENING, NO_PAWN_ENDING,
00053 GOLD_RETREAT_OPENING, GOLD_RETREAT_ENDING,
00054 SILVER_RETREAT_OPENING, SILVER_RETREAT_ENDING,
00055 KNIGHT_BLOCKED_OPENING, KNIGHT_BLOCKED_ENDING,
00056 KINGX_BLOCKED_OPENING, KINGX_BLOCKED_ENDING,
00057 ROOK_PAWN_OPENING, ROOK_PAWN_ENDING,
00058 PIN_OPENING, PIN_ENDING,
00059 ALL_GOLD_OPENING, ALL_GOLD_ENDING,
00060 ANAGUMA_EMPTY_OPENING, ANAGUMA_EMPTY_ENDING,
00061 STAND_EXCEPT_PAWN_OPENING, STAND_EXCEPT_PAWN_ENDING,
00062 FEATURE_LIMIT
00063 };
00064 CArray<int, FEATURE_LIMIT> values;
00065 };
00066
00067 class OpenMidEndingEval
00068 {
00069 private:
00070 enum { INVALID=EvalTraits<BLACK>::MAX_VALUE+1 };
00071 enum {
00073 ProgressIndependentValueLimit = 4000
00074 };
00075 enum LoadStatus { Zero=0, Loaded, Random };
00076 static volatile LoadStatus initialized_flag;
00077 static Weights piece_pair_weights;
00078 #ifdef USE_TEST_PROGRESS
00079 typedef osl::progress::ml::NewProgress progress_t;
00080 #else
00081 typedef osl::progress::Effect5x3 progress_t;
00082 #endif
00083 progress_t progress;
00084 MultiIntPair kingx_blocked, king25_effect_each;
00085 MultiIntPair king25_both_side,king_rook_bishop;
00086 MultiIntPair piece_stand_turn, non_pawn_attacked,
00087 non_pawn_attacked_ptype, piece_fork_turn;
00088 MultiInt ptypey, ptypex, king_table_value;
00089 MultiInt piece_stand_value, recalculated_stage_value, pawn_advance;
00090 MultiInt rook_mobility, bishop_mobility, lance_mobility;
00091 MultiInt knight_advance, pawn_drop, promoted_minor_piece, rook_pawn,
00092 rook_effect, bishop_effect, bishop_head, nosupport, ptype_yy, king3pieces;
00093 MultiInt rook_promote_defense;
00094 MultiInt piece_stand_combination, piece_stand_y, knight_check,
00095 knight_head, pawn_ptypeo, ptype_count_value, lance_effect_piece,
00096 ptype_y_pawn_y, bishop_and_king, rook_silver_knight, bishop_silver_knight;
00097 CArray<BoardMask, 2> knight_fork_squares;
00098 CArray<PieceMask, 2> effect25;
00099 CArray<PieceMask, 2> effect25_supported;
00100 CArray<PieceMask, 2> effected_mask;
00101 CArray<PieceMask, 2> effected_mask_for_attacked;
00102 CArray<PieceMask, 40> attacked_mask;
00103 CArray<int, 5> black_vertical, white_vertical,
00104 black_king_vertical, white_king_vertical;
00105
00106 CArray<int,2> piece_pair_king_value;
00107 CArray<int, 2> non_pawn_stand_count;
00108 CArray2d<int, 2, 3> gs_near_king_count;
00109 CArray2d<int, 2, PTYPE_SIZE> ptype_count, ptype_board_count;
00110 CArray<std::pair<Square,int>, 2> knight_drop, silver_drop, bishop_drop, rook_drop;
00111 CArray2d<int, 2, 9> pawns;
00112 int progress_independent_value,
00113 recalculated_value, piece_pair_value;
00114 int black_pawn_count;
00115 int black_major_count, black_gold_count;
00116 int black_attack_effect, black_attack_piece,
00117 white_attack_effect, white_attack_piece,
00118 black_attack_supported_piece, white_attack_supported_piece;
00119 int black_defense_effect, black_defense_piece,
00120 white_defense_effect, white_defense_piece;
00121 mutable int cache;
00122 Player turn;
00123 unsigned int ptypeo_mask;
00124 CArray<bool, 2> can_check;
00125 bool use_progress_independent_value_limit;
00126 static const int ROUND_UP = 2;
00127 static int roundUp(int v)
00128 {
00129 return v & (~(ROUND_UP-1));
00130 }
00131 void updateGoldSilverNearKing(const NumEffectState &state)
00132 {
00133 const CArray<Square,2> kings = {{
00134 state.kingSquare(BLACK),
00135 state.kingSquare(WHITE),
00136 }};
00137 gs_near_king_count.fill(0);
00138 for (int i = PtypeTraits<GOLD>::indexMin;
00139 i < PtypeTraits<GOLD>::indexLimit; ++i)
00140 {
00141 const Piece p = state.pieceOf(i);
00142 if (p.isOnBoard())
00143 {
00144 const Square pos = p.square();
00145 const int y_diff = std::abs(pos.y() - kings[p.owner()].y());
00146 const int x_diff = std::abs(pos.x() - kings[p.owner()].x());
00147 if (y_diff <= 2 && x_diff <= 3)
00148 {
00149 ++gs_near_king_count[p.owner()][std::max(x_diff, y_diff) - 1];
00150 }
00151 }
00152 }
00153 for (int i = PtypeTraits<SILVER>::indexMin;
00154 i < PtypeTraits<SILVER>::indexLimit; ++i)
00155 {
00156 const Piece p = state.pieceOf(i);
00157 if (p.isOnBoard())
00158 {
00159 const Square pos = p.square();
00160 const int y_diff = std::abs(pos.y() - kings[p.owner()].y());
00161 const int x_diff = std::abs(pos.x() - kings[p.owner()].x());
00162 if (y_diff <= 2 && x_diff <= 3)
00163 {
00164 ++gs_near_king_count[p.owner()][std::max(x_diff, y_diff) - 1];
00165 }
00166 }
00167 }
00168 }
00169 public:
00170 explicit OpenMidEndingEval(const NumEffectState &state, bool limit_progress_independent_value=! OslConfig::hasByoyomi());
00171 void changeTurn() { }
00172 static bool initialized()
00173 {
00174 return initialized_flag;
00175 }
00176 static bool setUp(const char *filename);
00177 static bool setUp();
00178 static std::string defaultFilename();
00179 int progressIndependentValue() const
00180 {
00181 return progress_independent_value + recalculated_value + piece_pair_value
00182 + piece_pair_king_value[BLACK] + piece_pair_king_value[WHITE];
00183 }
00184 void debug() const;
00185 MultiInt stageValue() const
00186 {
00187 return king_table_value + piece_stand_value +
00188 king25_effect_each[BLACK] + king25_effect_each[WHITE] +
00189 ptypex + ptypey + rook_mobility + bishop_mobility + lance_mobility +
00190 rook_effect + bishop_effect +
00191 piece_stand_combination + piece_stand_turn[turn] +
00192 rook_pawn + pawn_drop + piece_stand_y + knight_check +
00193 pawn_advance + pawn_ptypeo + promoted_minor_piece +
00194 nosupport +
00195 non_pawn_attacked[turn] + non_pawn_attacked_ptype[turn] +
00196 ptype_yy + king3pieces + bishop_head + knight_head
00197 + rook_promote_defense +
00198 ptype_count_value + lance_effect_piece + ptype_y_pawn_y +
00199 bishop_and_king + piece_fork_turn[turn] + rook_silver_knight + bishop_silver_knight +
00200 recalculated_stage_value;
00201 }
00202 int openingValue() const
00203 {
00204 return (king_table_value[0] +
00205 piece_stand_value[0] +
00206 king25_effect_each[BLACK][0] + king25_effect_each[WHITE][0] +
00207 ptypex[0] +
00208 ptypey[0] +
00209 rook_mobility[0] +
00210 bishop_mobility[0] +
00211 lance_mobility[0] +
00212 rook_effect[0] +
00213 bishop_effect[0] +
00214 piece_stand_combination[0] +
00215 piece_stand_turn[turn][0] +
00216 rook_pawn[0] +
00217 pawn_drop[0] +
00218 piece_stand_y[0] +
00219 knight_check[0] +
00220 pawn_advance[0] +
00221 pawn_ptypeo[0] +
00222 promoted_minor_piece[0] +
00223 nosupport[0] +
00224 non_pawn_attacked[turn][0] +
00225 non_pawn_attacked_ptype[turn][0] +
00226 ptype_yy[0] +
00227 king3pieces[0] +
00228 bishop_head[0] +
00229 knight_head[0] +
00230 rook_promote_defense[0] +
00231 ptype_count_value[0] +
00232 lance_effect_piece[0] +
00233 ptype_y_pawn_y[0] +
00234 bishop_and_king[0] +
00235 piece_fork_turn[turn][0] +
00236 rook_silver_knight[0] +
00237 bishop_silver_knight[0] +
00238 recalculated_stage_value[0]);
00239 }
00240 int midgameValue() const
00241 {
00242 return (king_table_value[1] +
00243 piece_stand_value[1] +
00244 king25_effect_each[BLACK][1] + king25_effect_each[WHITE][1] +
00245 ptypex[1] +
00246 ptypey[1] +
00247 rook_mobility[1] +
00248 bishop_mobility[1] +
00249 lance_mobility[1] +
00250 rook_effect[1] +
00251 bishop_effect[1] +
00252 piece_stand_combination[1] +
00253 piece_stand_turn[turn][1] +
00254 rook_pawn[1] +
00255 pawn_drop[1] +
00256 piece_stand_y[1] +
00257 knight_check[1] +
00258 pawn_advance[1] +
00259 pawn_ptypeo[1] +
00260 promoted_minor_piece[1] +
00261 nosupport[1] +
00262 non_pawn_attacked[turn][1] +
00263 non_pawn_attacked_ptype[turn][1] +
00264 ptype_yy[1] +
00265 king3pieces[1] +
00266 bishop_head[1] +
00267 knight_head[1] +
00268 rook_promote_defense[1] +
00269 ptype_count_value[1] +
00270 lance_effect_piece[1] +
00271 ptype_y_pawn_y[1] +
00272 bishop_and_king[1] +
00273 piece_fork_turn[turn][1] +
00274 rook_silver_knight[1] +
00275 bishop_silver_knight[1] +
00276 recalculated_stage_value[1]);
00277 }
00278 int midgame2Value() const
00279 {
00280 return (king_table_value[2] +
00281 piece_stand_value[2] +
00282 king25_effect_each[BLACK][2] + king25_effect_each[WHITE][2] +
00283 ptypex[2] +
00284 ptypey[2] +
00285 rook_mobility[2] +
00286 bishop_mobility[2] +
00287 lance_mobility[2] +
00288 rook_effect[2] +
00289 bishop_effect[2] +
00290 piece_stand_combination[2] +
00291 piece_stand_turn[turn][2] +
00292 rook_pawn[2] +
00293 pawn_drop[2] +
00294 piece_stand_y[2] +
00295 knight_check[2] +
00296 pawn_advance[2] +
00297 pawn_ptypeo[2] +
00298 promoted_minor_piece[2] +
00299 nosupport[2] +
00300 non_pawn_attacked[turn][2] +
00301 non_pawn_attacked_ptype[turn][2] +
00302 ptype_yy[2] +
00303 king3pieces[2] +
00304 bishop_head[2] +
00305 knight_head[2] +
00306 rook_promote_defense[2] +
00307 ptype_count_value[2] +
00308 lance_effect_piece[2] +
00309 ptype_y_pawn_y[2] +
00310 bishop_and_king[2] +
00311 piece_fork_turn[turn][2] +
00312 rook_silver_knight[2] +
00313 bishop_silver_knight[2] +
00314 recalculated_stage_value[2]);
00315 }
00316 int endgameValue() const
00317 {
00318 return (king_table_value[EndgameIndex] +
00319 piece_stand_value[EndgameIndex] +
00320 king25_effect_each[BLACK][EndgameIndex] + king25_effect_each[WHITE][EndgameIndex] +
00321 ptypex[EndgameIndex] +
00322 ptypey[EndgameIndex] +
00323 rook_mobility[EndgameIndex] +
00324 bishop_mobility[EndgameIndex] +
00325 lance_mobility[EndgameIndex] +
00326 rook_effect[EndgameIndex] +
00327 bishop_effect[EndgameIndex] +
00328 piece_stand_combination[EndgameIndex] +
00329 piece_stand_turn[turn][EndgameIndex] +
00330 rook_pawn[EndgameIndex] +
00331 pawn_drop[EndgameIndex] +
00332 piece_stand_y[EndgameIndex] +
00333 pawn_advance[EndgameIndex] +
00334 knight_check[EndgameIndex] +
00335 pawn_ptypeo[EndgameIndex] +
00336 promoted_minor_piece[EndgameIndex] +
00337 nosupport[EndgameIndex] +
00338 non_pawn_attacked[turn][EndgameIndex] +
00339 non_pawn_attacked_ptype[turn][EndgameIndex] +
00340 ptype_yy[EndgameIndex] +
00341 king3pieces[EndgameIndex] +
00342 bishop_head[EndgameIndex] +
00343 knight_head[EndgameIndex] +
00344 rook_promote_defense[EndgameIndex] +
00345 ptype_count_value[EndgameIndex] +
00346 lance_effect_piece[EndgameIndex] +
00347 ptype_y_pawn_y[EndgameIndex] +
00348 bishop_and_king[EndgameIndex] +
00349 piece_fork_turn[turn][EndgameIndex] +
00350 rook_silver_knight[EndgameIndex] +
00351 bishop_silver_knight[EndgameIndex] +
00352 recalculated_stage_value[EndgameIndex]);
00353 }
00354 void invalidateCache() { cache=INVALID; }
00355 static int progressIndependentValueAdjusted(int value, int progress,
00356 int progress_max)
00357 {
00358 if (value > ProgressIndependentValueLimit) {
00359 int diff = value - ProgressIndependentValueLimit;
00360 value = ProgressIndependentValueLimit
00361 + diff * progress/progress_max;
00362 }
00363 else if (value < -ProgressIndependentValueLimit) {
00364 int diff = value + ProgressIndependentValueLimit;
00365 value = -ProgressIndependentValueLimit
00366 + diff * progress/progress_max;
00367 }
00368 return value;
00369 }
00370 int composeOpenMidEndgame() const
00371 {
00372 const int progress_max = NewProgress::maxProgress(), c = progress_max/2;
00373 const int progress = this->progress.progress();
00374 int progress_independent = use_progress_independent_value_limit
00375 ? progressIndependentValueAdjusted
00376 (progressIndependentValue(), progress, progress_max)
00377 : progressIndependentValue();
00378 int sum = progress_independent * progress_max;
00379 if (progress < c)
00380 {
00381 sum += openingValue() * 2*(c - progress);
00382 sum += midgameValue() * 2*progress;
00383 }
00384 else
00385 {
00386 sum += midgameValue() * 2*(progress_max - progress);
00387 sum += endgameValue() * 2*(progress - c);
00388 }
00389 return sum;
00390 }
00391 #ifdef EVAL_QUAD
00392 int composeOpenMid2Endgame() const
00393 {
00394 const int progress_max = NewProgress::maxProgress();
00395 const int progress = this->progress.progress();
00396 const int c0 = progress_max/3, c1 = c0*2;
00397 #ifndef NDEBUG
00398 const int w2 = progress_max - c1;
00399 #endif
00400 assert(c0 == w2);
00401 int progress_independent = use_progress_independent_value_limit
00402 ? progressIndependentValueAdjusted
00403 (progressIndependentValue(), progress, progress_max)
00404 : progressIndependentValue();
00405 int sum = progress_independent * c0;
00406 const MultiInt stage_sum = stageValue();
00407 if (progress < c0)
00408 {
00409 sum += stage_sum[0] * (c0 - progress);
00410 sum += stage_sum[1] * progress;
00411 }
00412 else if (progress < c1)
00413 {
00414 sum += stage_sum[1] * (c1 - progress);
00415 sum += stage_sum[2] * (progress-c0);
00416 }
00417 else
00418 {
00419 sum += stage_sum[2] * (progress_max - progress);
00420 sum += stage_sum[3] * (progress - c1);
00421 }
00422 return sum;
00423 }
00424 #endif
00425 int value() const
00426 {
00427 if (cache==INVALID)
00428 {
00429 #ifdef USE_TEST_PROGRESS
00430 # ifdef EVAL_QUAD
00431 cache = roundUp(composeOpenMid2Endgame());
00432 # else
00433 cache = roundUp(composeOpenMidEndgame());
00434 # endif
00435 #else
00436 # ifdef EVAL_QUAD
00437 # error "not supported"
00438 # else
00439 cache = roundUp(progressIndependentValue() * 16 +
00440 openingValue() * (16 - progress.progress16().value()) +
00441 endgameValue() * progress.progress16().value());
00442 # endif
00443 #endif
00444 }
00445 return cache;
00446 }
00447 const Move suggestMove(const NumEffectState& state) const
00448 {
00449 assert(turn == state.turn());
00450 Move suggest;
00451 int best_value = 0;
00452 if (! rook_drop[turn].first.isPieceStand()) {
00453 assert(state.hasPieceOnStand(turn, ROOK));
00454 suggest = Move(rook_drop[turn].first, ROOK, turn);
00455 best_value = rook_drop[turn].second;
00456 }
00457 assert(best_value >= 0);
00458 if (bishop_drop[turn].second > best_value) {
00459 assert(! bishop_drop[turn].first.isPieceStand());
00460 assert(state.hasPieceOnStand(turn, BISHOP));
00461 suggest = Move(bishop_drop[turn].first, BISHOP, turn);
00462 best_value = bishop_drop[turn].second;
00463 }
00464 if (silver_drop[turn].second > best_value) {
00465 assert(! silver_drop[turn].first.isPieceStand());
00466 assert(state.hasPieceOnStand(turn, SILVER));
00467 suggest = Move(silver_drop[turn].first, SILVER, turn);
00468 best_value = silver_drop[turn].second;
00469 }
00470 if (knight_drop[turn].second > best_value
00471 && state.hasPieceOnStand(turn, KNIGHT)) {
00472 assert(! knight_drop[turn].first.isPieceStand());
00473 suggest = Move(knight_drop[turn].first, KNIGHT, turn);
00474 best_value = knight_drop[turn].second;
00475 }
00476 return suggest;
00477 }
00478 int expect(const NumEffectState &state, Move move) const;
00479 template<Player P>
00480 void updateSub(const NumEffectState &new_state, Move last_move);
00481 void update(const NumEffectState &new_state, Move last_move);
00482 const Progress32 progress32() const
00483 {
00484 return Progress32(progress.progress16(BLACK).value()
00485 + progress.progress16(WHITE).value());
00486 }
00487 const Progress16 progress16() const { return progress.progress16(); }
00488 public:
00489 static int infty()
00490 {
00491 #ifdef USE_TEST_PROGRESS
00492 # ifdef EVAL_QUAD
00493 assert(NewProgress::maxProgress() % 3 == 0);
00494 return 57984 * (NewProgress::maxProgress()/3);
00495 # else
00496 return 57984 * NewProgress::maxProgress();
00497 # endif
00498 #else
00499 return 57984 * 16;
00500 #endif
00501 }
00502 static int captureValue(PtypeO ptypeO) {
00503 assert(isValidPtypeO(ptypeO));
00504 return roundUp((-PieceEval::value(ptypeO) +
00505 PieceEval::value(captured(ptypeO))) * seeScale());
00506 }
00507 static int seeScale() {
00508 #ifdef USE_TEST_PROGRESS
00509 # ifdef EVAL_QUAD
00510 assert(NewProgress::maxProgress() % 3 == 0);
00511 return (NewProgress::maxProgress()/3);
00512 # else
00513 return NewProgress::maxProgress();
00514 # endif
00515 #else
00516 return 16;
00517 #endif
00518 }
00519
00520 OpenMidEndingEvalDebugInfo debugInfo(const NumEffectState &state);
00521 static void setRandom();
00522 static void resetWeights(const int *w, size_t length);
00523 static OpenMidEndingPtypeTable Piece_Value;
00524 bool progressIndependentValueLimit() const {
00525 return use_progress_independent_value_limit;
00526 }
00527 private:
00528 template <class Reader>
00529 static void doResetWeights(Reader& reader);
00530 };
00531 }
00532 }
00533 }
00534
00535 #endif // EVAL_ML_OPENMIDENDINGEVAL_H
00536
00537
00538
00539
00540