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