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