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 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, // recalculated_value
00107           ENTER_KING_DEFENSE,
00108           KING25_EFFECT_ATTACK, // end recalculated_value
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; // index: owner of king
00154         CArray<PieceMask, 2> effect25_supported; // index: owner of king
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         // flat
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, // should be renamed to piece
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; // king is defense
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 // ;;; Local Variables:
00458 // ;;; mode:c++
00459 // ;;; c-basic-offset:2
00460 // ;;; coding:utf-8
00461 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines