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 stageValue()[0];
00260 }
00261 int midgameValue() const
00262 {
00263 return stageValue()[1];
00264 }
00265 int midgame2Value() const
00266 {
00267 return stageValue()[2];
00268 }
00269 int endgameValue() const
00270 {
00271 return stageValue()[EndgameIndex];
00272 }
00273 void invalidateCache() { cache=INVALID; }
00274 static int progressIndependentValueAdjusted(int value, int progress,
00275 int progress_max)
00276 {
00277 if (value > ProgressIndependentValueLimit) {
00278 int diff = value - ProgressIndependentValueLimit;
00279 value = ProgressIndependentValueLimit
00280 + diff * progress/progress_max;
00281 }
00282 else if (value < -ProgressIndependentValueLimit) {
00283 int diff = value + ProgressIndependentValueLimit;
00284 value = -ProgressIndependentValueLimit
00285 + diff * progress/progress_max;
00286 }
00287 return value;
00288 }
00289 int composeOpenMidEndgame() const
00290 {
00291 const int progress_max = NewProgress::maxProgress(), c = progress_max/2;
00292 const int progress = this->progress.progress();
00293 int progress_independent = use_progress_independent_value_limit
00294 ? progressIndependentValueAdjusted
00295 (progressIndependentValue(), progress, progress_max)
00296 : progressIndependentValue();
00297 int sum = progress_independent * progress_max;
00298 if (progress < c)
00299 {
00300 sum += openingValue() * 2*(c - progress);
00301 sum += midgameValue() * 2*progress;
00302 }
00303 else
00304 {
00305 sum += midgameValue() * 2*(progress_max - progress);
00306 sum += endgameValue() * 2*(progress - c);
00307 }
00308 return sum;
00309 }
00310 #ifdef EVAL_QUAD
00311 int composeOpenMid2Endgame() const
00312 {
00313 const int progress_max = NewProgress::maxProgress();
00314 const int progress = this->progress.progress();
00315 const int c0 = progress_max/3, c1 = c0*2;
00316 #ifndef NDEBUG
00317 const int w2 = progress_max - c1;
00318 #endif
00319 assert(c0 == w2);
00320 int progress_independent = use_progress_independent_value_limit
00321 ? progressIndependentValueAdjusted
00322 (progressIndependentValue(), progress, progress_max)
00323 : progressIndependentValue();
00324 int sum = progress_independent * c0;
00325 const MultiInt stage_sum = stageValue();
00326 if (progress < c0)
00327 {
00328 sum += stage_sum[0] * (c0 - progress);
00329 sum += stage_sum[1] * progress;
00330 }
00331 else if (progress < c1)
00332 {
00333 sum += stage_sum[1] * (c1 - progress);
00334 sum += stage_sum[2] * (progress-c0);
00335 }
00336 else
00337 {
00338 sum += stage_sum[2] * (progress_max - progress);
00339 sum += stage_sum[3] * (progress - c1);
00340 }
00341 return sum;
00342 }
00343 #endif
00344 int value() const
00345 {
00346 if (cache==INVALID)
00347 {
00348 #ifdef USE_TEST_PROGRESS
00349 # ifdef EVAL_QUAD
00350 cache = roundUp(composeOpenMid2Endgame());
00351 # else
00352 cache = roundUp(composeOpenMidEndgame());
00353 # endif
00354 #else
00355 # ifdef EVAL_QUAD
00356 # error "not supported"
00357 # else
00358 cache = roundUp(progressIndependentValue() * 16 +
00359 openingValue() * (16 - progress.progress16().value()) +
00360 endgameValue() * progress.progress16().value());
00361 # endif
00362 #endif
00363 }
00364 return cache;
00365 }
00366 const Move suggestMove(const NumEffectState& state) const
00367 {
00368 assert(turn == state.turn());
00369 Move suggest;
00370 int best_value = 0;
00371 if (! rook_drop[turn].first.isPieceStand()) {
00372 assert(state.hasPieceOnStand(turn, ROOK));
00373 suggest = Move(rook_drop[turn].first, ROOK, turn);
00374 best_value = rook_drop[turn].second;
00375 }
00376 assert(best_value >= 0);
00377 if (bishop_drop[turn].second > best_value) {
00378 assert(! bishop_drop[turn].first.isPieceStand());
00379 assert(state.hasPieceOnStand(turn, BISHOP));
00380 suggest = Move(bishop_drop[turn].first, BISHOP, turn);
00381 best_value = bishop_drop[turn].second;
00382 }
00383 if (silver_drop[turn].second > best_value) {
00384 assert(! silver_drop[turn].first.isPieceStand());
00385 assert(state.hasPieceOnStand(turn, SILVER));
00386 suggest = Move(silver_drop[turn].first, SILVER, turn);
00387 best_value = silver_drop[turn].second;
00388 }
00389 if (knight_drop[turn].second > best_value
00390 && state.hasPieceOnStand(turn, KNIGHT)) {
00391 assert(! knight_drop[turn].first.isPieceStand());
00392 suggest = Move(knight_drop[turn].first, KNIGHT, turn);
00393 best_value = knight_drop[turn].second;
00394 }
00395 return suggest;
00396 }
00397 int expect(const NumEffectState &state, Move move) const;
00398 template<Player P>
00399 void updateSub(const NumEffectState &new_state, Move last_move);
00400 void update(const NumEffectState &new_state, Move last_move);
00401 const Progress32 progress32() const
00402 {
00403 return Progress32(progress.progress16(BLACK).value()
00404 + progress.progress16(WHITE).value());
00405 }
00406 const Progress16 progress16() const { return progress.progress16(); }
00407 int progressValue() const { return progress.progress(); }
00408 int progressMax() const { return progress.maxProgress(); }
00409 public:
00410 static int infty()
00411 {
00412 #ifdef USE_TEST_PROGRESS
00413 # ifdef EVAL_QUAD
00414 assert(NewProgress::maxProgress() % 3 == 0);
00415 return 57984 * (NewProgress::maxProgress()/3);
00416 # else
00417 return 57984 * NewProgress::maxProgress();
00418 # endif
00419 #else
00420 return 57984 * 16;
00421 #endif
00422 }
00423 static int captureValue(PtypeO ptypeO) {
00424 assert(isValidPtypeO(ptypeO));
00425 return roundUp((-PieceEval::value(ptypeO) +
00426 PieceEval::value(captured(ptypeO))) * seeScale());
00427 }
00428 static int seeScale() {
00429 #ifdef USE_TEST_PROGRESS
00430 # ifdef EVAL_QUAD
00431 assert(NewProgress::maxProgress() % 3 == 0);
00432 return (NewProgress::maxProgress()/3);
00433 # else
00434 return NewProgress::maxProgress();
00435 # endif
00436 #else
00437 return 16;
00438 #endif
00439 }
00440
00441 OpenMidEndingEvalDebugInfo debugInfo(const NumEffectState &state);
00442 static void setRandom();
00443 static void resetWeights(const int *w, size_t length);
00444 static OpenMidEndingPtypeTable Piece_Value;
00445 bool progressIndependentValueLimit() const {
00446 return use_progress_independent_value_limit;
00447 }
00448 private:
00449 template <class Reader>
00450 static void doResetWeights(Reader& reader);
00451 };
00452 }
00453 }
00454 }
00455
00456 #endif // EVAL_ML_OPENMIDENDINGEVAL_H
00457
00458
00459
00460
00461