attackKing.cc
Go to the documentation of this file.
00001 
00004 #include "osl/eval/endgame/attackKing.h"
00005 #include "osl/eval/pieceEval.h"
00006 #include "osl/misc/carray.h"
00007 
00008 // YSSの評価値を真似
00009 // http://www32.ocn.ne.jp/~yss/book.html#SEC3
00010 //
00011 // 先手の玉に対する後手の駒の相対位置による増減割合。X軸については対称である。
00012 //        0   1   2   3   4   5   6   7   8 (X距離)
00013 // 
00014 //   +8   50  50  50  50  50  50  50  50  50
00015 //   +7   50  50  50  50  50  50  50  50  50
00016 //   +6   62  60  58  52  50  50  50  50  50
00017 //   +5   80  78  72  67  55  51  50  50  50
00018 //   +4  100  99  95  87  78  69  50  50  50
00019 //   +3  140 130 110 100  95  75  54  50  50
00020 //   +2  170 160 142 114  98  80  62  55  50  <--- 2段真上を最大とする。
00021 //   +1  170 165 150 121  94  78  58  52  50
00022 //    0  170 145 137 115  91  75  57  50  50  <--- 中心。左隅(0 0)に王がいるとする
00023 //   -1  132 132 129 102  84  71  51  50  50
00024 //   -2  100  97  95  85  70  62  50  50  50
00025 //   -3   90  85  80  68  60  53  50  50  50
00026 //   -4   70  66  62  55  52  50  50  50  50
00027 //   -5   54  53  51  50  50  50  50  50  50
00028 //   -6   50  50  50  50  50  50  50  50  50
00029 //   -7   50  50  50  50  50  50  50  50  50
00030 //   -8   50  50  50  50  50  50  50  50  50
00031 
00032 namespace osl
00033 {
00034   namespace
00035   {
00036     const CArray<int,19*9> yss_bonus = {{
00037       // 桂,香は一段下げるため,+9 から -9 まで取る
00038          50,  50,  50,  50,  50,  50,  0,  0,  0, 
00039          50,  50,  50,  50,  50,  50,  0,  0,  0, 
00040          50,  50,  50,  50,  50,  50,  0,  0,  0, 
00041          62,  60,  58,  52,  50,  50,  0,  0,  0, 
00042          80,  78,  72,  67,  55,  51,  0,  0,  0, 
00043         100,  99,  95,  87,  78,  69,  0,  0,  0, 
00044         140, 130, 110, 100,  95,  75,  0,  0,  0, 
00045         170, 160, 142, 114,  98,  80,  0,  0,  0,
00046         170, 165, 150, 121,  94,  78,  0,  0,  0, 
00047         170, 145, 137, 115,  91,  75,  0,  0,  0,
00048         132, 132, 129, 102,  84,  71,  0,  0,  0, 
00049         100,  97,  95,  85,  70,  62,  0,  0,  0, 
00050          90,  85,  80,  68,  60,  53,  0,  0,  0, 
00051          70,  66,  62,  55,  52,  50,  0,  0,  0, 
00052          54,  53,  51,  50,  50,  50,  0,  0,  0, 
00053          50,  50,  50,  50,  50,  50,  0,  0,  0, 
00054          50,  50,  50,  50,  50,  50,  0,  0,  0, 
00055          50,  50,  50,  50,  50,  50,  0,  0,  0,
00056          50,  50,  50,  50,  50,  50,  0,  0,  0, 
00057     }};
00058     inline int toEven(int value) 
00059     {
00060       if (value % 2 == 0)
00061         return value;
00062       if (value > 0)
00063         return value - 1;
00064       return value + 1;
00065     }
00066     inline int multiply(int value, int bonus)
00067     {
00068       // yss では持駒の付加価値が2割程度あるため1.2で割る
00069       return toEven(value * bonus / 120); 
00070     }
00071     inline void adhoc_adjust(int& value, double scale)
00072     {
00073       value = toEven(static_cast<int>(value * scale));
00074     }
00075   } // anonymous namespace
00076 } // namespace osl
00077 
00078 void osl::eval::endgame::AttackKing::
00079 Table::adhoc_edge_king_1(const Player player,
00080                          const Square king,
00081                          const Square attack)
00082 {
00083   for (int ptype = PPAWN; ptype <= ROOK; ptype++)
00084   {
00085     if (ptype != KING)
00086     {
00087       adhoc_adjust(valueOf(king, player, attack,
00088                            static_cast<osl::Ptype>(ptype)), 1.25);
00089     }
00090   }
00091 }
00092 
00093 void osl::eval::endgame::AttackKing::
00094 Table::adhoc_edge_king_2(const Player player,
00095                          const Square king,
00096                          const Square attack)
00097 {
00098   adhoc_adjust(valueOf(king, player, attack,
00099                        GOLD), 1.25);
00100   adhoc_adjust(valueOf(king, player, attack,
00101                        SILVER), 1.25);
00102   for (int ptype = PPAWN; ptype <= PSILVER; ptype++)
00103   {
00104     adhoc_adjust(valueOf(king, player, attack,
00105                          static_cast<osl::Ptype>(ptype)), 1.25);
00106   }
00107 }
00108 
00109 osl::eval::endgame::AttackKing::
00110 Table::Table()
00111 {
00112   // WHITEのKINGに対するBLACKの価値を書き,最後に反転させる.
00113   data.fill(0);
00114   for (int king_x=1; king_x<=9; ++king_x)
00115   {
00116     for (int king_y=1; king_y<=9; ++king_y)
00117     {
00118       const Square king(king_x, king_y);
00119       for (int p=PTYPE_PIECE_MIN; p<=PTYPE_MAX; ++p)
00120       {
00121         const Ptype ptype = static_cast<Ptype>(p);
00122         assert(isPiece(ptype));
00123         const Ptype basic_type = unpromote(ptype);
00124 
00125         const int ptype_value
00126           = Ptype_Eval_Table.value(newPtypeO(BLACK,ptype));
00127         // 持駒
00128         const int stand_bonus 
00129           = (isMajorBasic(basic_type) 
00130              ? Ptype_Eval_Table.value(newPtypeO(BLACK,PAWN))
00131              : 0);
00132         valueOf(king, WHITE, Square::STAND(), ptype) = +ptype_value
00133           + stand_bonus;
00134         if (ptype == KNIGHT || ptype == LANCE)
00135           adhoc_adjust(valueOf(king, WHITE, Square::STAND(), ptype), 0.85);
00136         if (ptype == GOLD || ptype == SILVER)
00137           adhoc_adjust(valueOf(king, WHITE, Square::STAND(), ptype), 1.1);
00138 
00139         // 盤上
00140         for (int attack_x=1; attack_x<=9; ++attack_x)
00141         {
00142           const int relative_x = abs(king_x - attack_x);
00143           for (int attack_y=1; attack_y<=9; ++attack_y)
00144           {
00145             const Square attacker(attack_x, attack_y);
00146             if (basic_type == KING)
00147             {
00148               // 玉はそのまま
00149               valueOf(king, WHITE, attacker, ptype) = ptype_value;
00150               continue;
00151             }
00152 
00153             const int relative_y_white_king 
00154               = (((ptype == KNIGHT)||(ptype == LANCE))
00155                  ? attack_y - king_y - 1 // 桂香は一段遠くから評価
00156                  : attack_y - king_y);
00157 
00158             const int bonus_white_king
00159               = yss_bonus[relative_x + (-relative_y_white_king+9)*9];
00160 
00161             const int black_attack =  multiply(ptype_value,bonus_white_king);
00162 
00163             if (isMajorBasic(basic_type))
00164             {
00165               // 大駒は攻撃に利いていれば max を取る
00166               const int relative_y = abs(king_y - attack_y);
00167               const int diff1 = king_x + king_y - (attack_x + attack_y);
00168               const int diff2 = king_x - king_y - (attack_x - attack_y);
00169 
00170               if ((basic_type == ROOK &&
00171                    relative_y <= 1) ||
00172                   (basic_type == BISHOP &&
00173                    ((-1 <= diff1 && diff1 <= 1) ||
00174                     (-1 <= diff2 && diff2 <= 1))))
00175               {
00176                 valueOf(king, WHITE, attacker, ptype) 
00177                   = EvalTraits<BLACK>::max(ptype_value, black_attack);
00178                 // 玉と同じ筋の方のボーナスを高くする
00179                 if (relative_y == 0)
00180                 {
00181                   adhoc_adjust(valueOf(king, WHITE, attacker, ptype),
00182                                0.98);
00183                 }
00184               }
00185               else
00186               {
00187                 // その他は 90 に
00188                 valueOf(king, WHITE, attacker, ptype) 
00189                   = multiply(ptype_value, 90);
00190               }
00191               continue;
00192             }
00193             //成れない歩と桂は減点
00194             if ((ptype == PAWN && attack_y >= 5) ||
00195                 (ptype == KNIGHT && attack_y >= 6))
00196             {
00197               int new_black_attack = black_attack;
00198               adhoc_adjust(new_black_attack, 0.95);
00199               valueOf(king, WHITE, attacker, ptype) = new_black_attack;
00200             }
00201             else
00202               valueOf(king, WHITE, attacker, ptype) = black_attack;
00203           }
00204         }
00205       }
00206     }
00207   }
00208   for (int king_x=1; king_x<=9; ++king_x)
00209   {
00210     for (int king_y=1; king_y<=9; ++king_y)
00211     {
00212       const Square king(king_x, king_y);
00213       // 1つしか動けない香は歩と同じ点数に
00214       for (int x=1; x<=9; ++x)
00215       {
00216         const Square b(x,2);
00217         valueOf(king, WHITE, b, LANCE) = valueOf(king, WHITE, b, PAWN);
00218       }
00219       if (king_y <= 7)
00220       {
00221         adhoc_adjust(valueOf(king, WHITE, Square(king_x, king_y + 2), PAWN),
00222                      1.25);
00223       }
00224       // 1段目の金類は価値を半分に
00225       for (int x=1; x<=9; ++x)
00226       {
00227         const Square b(x,1);
00228         if (x <= 2 || x >= 8)
00229         {
00230           adhoc_adjust(valueOf(king, WHITE, b, GOLD),    0.25);
00231           adhoc_adjust(valueOf(king, WHITE, b, PSILVER), 0.25);
00232         }
00233         else
00234         {
00235           adhoc_adjust(valueOf(king, WHITE, b, GOLD),    0.5);
00236           adhoc_adjust(valueOf(king, WHITE, b, PSILVER), 0.5);
00237         }
00238         adhoc_adjust(valueOf(king, WHITE, b, PKNIGHT), 0.5);
00239         adhoc_adjust(valueOf(king, WHITE, b, PLANCE),  0.5);
00240         adhoc_adjust(valueOf(king, WHITE, b, PPAWN),   0.5);
00241       }
00242       // 1段玉に対する3段目の駒は価値を1.25倍に
00243       if (king_y == 1)
00244       {
00245         for (int x = 1; x <= 9; ++x) {
00246           const Square three(x, 3);
00247           for (int ptype = PPAWN; ptype <= ROOK; ptype++)
00248           {
00249             if (ptype != KING && ptype != ROOK && ptype != PROOK)
00250               adhoc_adjust(valueOf(king, WHITE, three,
00251                                    static_cast<osl::Ptype>(ptype)), 1.25);
00252           }
00253         }
00254       }
00255       if (king_y <= 2)
00256       {
00257         for (int x = std::max(king_x - 1, 2);
00258              x <= std::min(king_x + 1, 8); x++)
00259         {
00260           adhoc_adjust(valueOf(king, WHITE, Square(x, 4), PAWN),
00261                        1.25);
00262         }
00263       }
00264       // 端玉に対するボーナス
00265       if (king_x == 1 || king_x == 9)
00266       {
00267         int next = king_x == 1 ? 2 : 8;
00268         adhoc_edge_king_1(WHITE, king, Square(next, king_y));
00269         if (king_y < 9)
00270         {
00271           adhoc_edge_king_1(WHITE, king, Square(next, king_y + 1));
00272         }
00273         if (king_y < 8)
00274         {
00275           // 3段目は 1.25 * 1.25 倍されるけど気にしない
00276           adhoc_edge_king_1(WHITE, king, Square(next, king_y + 2));
00277         }
00278       }
00279       if (king_x < 6)
00280       {
00281         valueOf(king, WHITE, Square(9, 9), LANCE) = 0;
00282         valueOf(king, WHITE, Square(9, 8), LANCE) = 0;
00283         valueOf(king, WHITE, Square(9, 7), LANCE) = 0;
00284         valueOf(king, WHITE, Square(8, 9), KNIGHT) = 0;
00285 
00286         valueOf(king, WHITE, Square(9, 1), GOLD) = 0;
00287         valueOf(king, WHITE, Square(9, 1), SILVER) = 0;
00288         valueOf(king, WHITE, Square(9, 1), PSILVER) = 0;
00289         valueOf(king, WHITE, Square(8, 1), GOLD) = 0;
00290         valueOf(king, WHITE, Square(8, 1), SILVER) = 0;
00291         valueOf(king, WHITE, Square(8, 1), PSILVER) = 0;
00292       }
00293 
00294       if (king_x > 4)
00295       {
00296         valueOf(king, WHITE, Square(1, 9), LANCE) = 0;
00297         valueOf(king, WHITE, Square(1, 8), LANCE) = 0;
00298         valueOf(king, WHITE, Square(1, 7), LANCE) = 0;
00299         valueOf(king, WHITE, Square(2, 9), KNIGHT) = 0;
00300 
00301         valueOf(king, WHITE, Square(1, 1), GOLD) = 0;
00302         valueOf(king, WHITE, Square(1, 1), PSILVER) = 0;
00303         valueOf(king, WHITE, Square(1, 1), SILVER) = 0;
00304         valueOf(king, WHITE, Square(2, 1), GOLD) = 0;
00305         valueOf(king, WHITE, Square(2, 1), SILVER) = 0;
00306         valueOf(king, WHITE, Square(2, 1), PSILVER) = 0;
00307       }
00308     }
00309   }
00310   adhoc_edge_king_2(WHITE, Square(1, 1), Square(3, 2));
00311   adhoc_edge_king_2(WHITE, Square(1, 2), Square(3, 3));
00312   adhoc_edge_king_2(WHITE, Square(9, 1), Square(7, 2));
00313   adhoc_edge_king_2(WHITE, Square(9, 2), Square(7, 3));
00314 
00315   for (int x = 1; x <= 9; x++)
00316   {
00317     for (int y = 1; y <= 9; y++)
00318     {
00319       adhoc_adjust(valueOf(Square(1,1), WHITE, Square(x, y), GOLD), 1.05);
00320       adhoc_adjust(valueOf(Square(9,1), WHITE, Square(x, y), GOLD), 1.05);
00321       adhoc_adjust(valueOf(Square(1,1), WHITE, Square(x, y), SILVER), 1.05);
00322       adhoc_adjust(valueOf(Square(9,1), WHITE, Square(x, y), SILVER), 1.05);
00323       adhoc_adjust(valueOf(Square(1,1), WHITE, Square(x, y), BISHOP), 0.95);
00324       adhoc_adjust(valueOf(Square(1,1), WHITE, Square(x, y), PBISHOP), 0.95);
00325       adhoc_adjust(valueOf(Square(9,1), WHITE, Square(x, y), BISHOP), 0.95);
00326       adhoc_adjust(valueOf(Square(9,1), WHITE, Square(x, y), PBISHOP), 0.95);
00327       for (int ptype = PPAWN; ptype <= PSILVER; ptype++)
00328       {
00329         adhoc_adjust(valueOf(Square(1, 1), WHITE, Square(x,y),
00330                              static_cast<osl::Ptype>(ptype)), 1.05);
00331         adhoc_adjust(valueOf(Square(9, 1), WHITE, Square(x,y),
00332                              static_cast<osl::Ptype>(ptype)), 1.05);
00333       }
00334     }
00335   }
00336   adhoc_adjust(valueOf(Square(1,1), WHITE, Square::STAND(), BISHOP), 0.95);
00337   adhoc_adjust(valueOf(Square(9,1), WHITE, Square::STAND(), BISHOP), 0.95);
00338 
00339   // BLACK/WHITE 反転
00340   for (int king_x=1; king_x<=9; ++king_x) {
00341     for (int king_y=1; king_y<=9; ++king_y) {
00342       const Square king_b(king_x, king_y);
00343       const Square king_w = king_b.rotate180();
00344       
00345       for (int p=PTYPE_PIECE_MIN; p<=PTYPE_MAX; ++p) {
00346         const Ptype ptype = static_cast<Ptype>(p);
00347         assert(isPiece(ptype));
00348 
00349         // 持駒
00350         valueOf(king_b, BLACK, Square::STAND(), ptype) 
00351           = - valueOf(king_w, WHITE, Square::STAND(), ptype);
00352 
00353         // 盤上
00354         for (int attack_x=1; attack_x<=9; ++attack_x) {
00355           for (int attack_y=1; attack_y<=9; ++attack_y) {
00356             const Square attack_b(attack_x, attack_y); // white へのblackの攻撃
00357             const Square attack_w = attack_b.rotate180();
00358 
00359             valueOf(king_b, BLACK, attack_w, ptype) 
00360               = - valueOf(king_w, WHITE, attack_b, ptype);
00361           }
00362         }
00363       }
00364     }
00365   }
00366 }
00367 
00368 void osl::eval::endgame::AttackKing::
00369 saveText(const char *filename)
00370 {
00371   table.saveText(filename);
00372 }
00373 
00374 // ;;; Local Variables:
00375 // ;;; mode:c++
00376 // ;;; c-basic-offset:2
00377 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines