openMidEndingEval.h
Go to the documentation of this file.
00001 /* openMidEndingEval.h
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 // NewProgressが学習可能な場合に定義 (現在はosl側に変更はないので常に定義)
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           // progress independent
00043           PIECE, ROOK_MOBILITY, BISHOP_MOBILITY, LANCE_MOBILITY,
00044           PIECE_PAIR, KING25_EFFECT,
00045           // opening and ending
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; // index: owner of king
00099         CArray<PieceMask, 2> effect25_supported; // index: owner of king
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         // flat
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, // should be renamed to piece
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; // king is defense
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 // ;;; Local Variables:
00537 // ;;; mode:c++
00538 // ;;; c-basic-offset:2
00539 // ;;; coding:utf-8
00540 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines