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 
00018 #define USE_TEST_PROGRESS
00019 // NewProgressが学習可能な場合に定義 (現在はosl側に変更はないので常に定義)
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           // progress independent
00042           PIECE, ROOK_MOBILITY, BISHOP_MOBILITY, LANCE_MOBILITY,
00043           PIECE_PAIR, KING25_EFFECT,
00044           // opening and ending
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; // index: owner of king
00098         CArray<PieceMask, 2> effect25_supported; // index: owner of king
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         // flat
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, // should be renamed to piece
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; // king is defense
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 // ;;; Local Variables:
00517 // ;;; mode:c++
00518 // ;;; c-basic-offset:2
00519 // ;;; coding:utf-8
00520 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines