minorPiece.h
Go to the documentation of this file.
00001 /* testEval.h
00002  */
00003 
00004 #ifndef EVAL_ML_MINORPIECE_H
00005 #define EVAL_ML_MINORPIECE_H
00006 
00007 #include "osl/eval/ml/midgame.h"
00008 #include "osl/eval/ml/weights.h"
00009 #include "osl/eval/ml/evalStagePair.h"
00010 #include "osl/misc/carray.h"
00011 #include "osl/state/numEffectState.h"
00012 #include "osl/container/tripleInt.h"
00013 #include "osl/container/pieceVector.h"
00014 
00015 namespace osl
00016 {
00017   namespace eval
00018   {
00019     namespace ml
00020     {
00021       class PawnDrop
00022       {
00023       public:
00024         enum { ONE_DIM = 9, DIM = ONE_DIM * 2};
00025         static void setUp(const Weights &weights,int stage);
00026       };
00027 
00028       class PawnDropY
00029       {
00030       public:
00031         enum { ONE_DIM = 81, DIM = ONE_DIM * 2};
00032         static void setUp(const Weights &weights,int stage);
00033       };
00034 
00035       class PawnDropBoth
00036       {
00037         friend class PawnDrop;
00038         friend class PawnDropY;
00039         friend class PawnDropX;
00040         friend class PawnDropPawnStand;
00041         friend class PawnDropPawnStandX;
00042         friend class PawnDropPawnStandY;
00043         friend class PawnDropNonDrop;
00044         friend class PawnStateKingRelative;
00045       private:
00046         enum { BOTH_ON_BOARD, SELF_ON_BOARD, OPP_ON_BOARD, BOTH_ON_STAND };
00047         static CArray<MultiInt, 9> attack_table, defense_table;
00048         static CArray<MultiInt, 81> attack_y_table, defense_y_table;
00049         static CArray<MultiInt, 90> x_table;
00050         static CArray<MultiInt, 18> stand_table;
00051         static CArray<MultiInt, 90> x_stand_table;
00052         static CArray<MultiInt, 162> y_stand_table;
00053         static CArray<MultiInt, 10> drop_non_drop_table;
00054         static CArray<MultiInt, 36> state_king_relative_table;
00055         template <Player Owner>
00056         static int indexY(const Piece king, int x)
00057         {
00058           assert(Owner == king.owner());
00059           const int king_y = (Owner == BLACK ?
00060                               king.square().y() : 10 - king.square().y());
00061           return std::abs(x - king.square().x()) * 9 + king_y - 1;
00062         }
00063         static int index(const Square king, int x)
00064         {
00065           return std::abs(x - king.x());
00066         }
00067         template <bool Attack>
00068         static int indexX(const Piece king, int x)
00069         {
00070           const int king_x = king.square().x();
00071           const int target_x = (king_x > 5 ? 10 - king_x : king_x);
00072           if (king_x >= 6 || (king.owner() == WHITE && king_x == 5))
00073             x = 10 - x;
00074           return (x - 1) * 5 + target_x - 1 + (Attack ? 0 : 45);
00075         }
00076       public:
00077         static MultiInt value(
00078                          int attack_index, int defense_index, 
00079                          int attack_index_y, int defense_index_y,
00080                          int attack_index_x, int defense_index_x)
00081         {
00082           return (attack_table[attack_index] +
00083                   defense_table[defense_index] +
00084                   attack_y_table[attack_index_y] +
00085                   defense_y_table[defense_index_y] +
00086                   x_table[attack_index_x] +
00087                   x_table[defense_index_x]);
00088         }
00089         static MultiInt standValue(
00090                               int attack_index, int defense_index, 
00091                               int attack_index_y, int defense_index_y,
00092                               int attack_index_x, int defense_index_x)
00093         {
00094           return (stand_table[attack_index] +
00095                   stand_table[defense_index + 9] +
00096                   y_stand_table[attack_index_y] +
00097                   y_stand_table[defense_index_y + 81] +
00098                   x_stand_table[attack_index_x] +
00099                   x_stand_table[defense_index_x]);
00100         }
00101         static MultiInt eval(const NumEffectState &state);
00102         template<Player P>
00103         static MultiInt evalWithUpdate(const NumEffectState &state,
00104                                              Move moved,
00105                                              MultiInt &last_value)
00106         {
00107           const Player altP=PlayerTraits<P>::opponent;
00108           Ptype captured = moved.capturePtype();
00109           if (moved.ptype() == KING ||
00110               (moved.isDrop() && moved.ptype() == PAWN &&
00111                !state.hasPieceOnStand<PAWN>(P)) ||
00112               (captured != PTYPE_EMPTY &&
00113                unpromote(captured) == PAWN &&
00114                state.countPiecesOnStand<PAWN>(P) == 1))
00115           {
00116             return eval(state);
00117           }
00118 
00119           MultiInt result(last_value);
00120           const CArray<Square, 2> king_bw = {{ state.kingSquare<BLACK>(), state.kingSquare<WHITE>() }};
00121           const CArray<Square, 2> kings = {{ king_bw[playerToIndex(P)], king_bw[playerToIndex(alt(P))] }};
00122           const CArray<Piece, 2> king_piece = {{ state.kingPiece(P),
00123                                                  state.kingPiece(alt(P)) }};
00124           if (moved.oldPtype() == PAWN) 
00125           {
00126             if (moved.isDrop())
00127             {
00128               const int attack_index = index(kings[1], moved.to().x());
00129               const int defense_index = index(kings[0], moved.to().x());
00130               const int attack_index_x =
00131                 indexX<true>(king_piece[1], moved.to().x());
00132               const int defense_index_x =
00133                 indexX<false>(king_piece[0], moved.to().x());
00134 
00135               const int attack_index_y = indexY<altP>(king_piece[1], moved.to().x());
00136               const int defense_index_y = indexY<P>(king_piece[0], moved.to().x());
00137               const int index_x = (moved.to().x() > 5 ? 10 -
00138                                    moved.to().x() : moved.to().x());
00139               if (state.isPawnMaskSet<altP>(moved.to().x()))
00140               {
00141                 if (P == BLACK)
00142                 {
00143                   result -= drop_non_drop_table[index_x - 1 + 5];
00144                   result += drop_non_drop_table[index_x - 1];
00145                   result -=
00146                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00147                                               OPP_ON_BOARD * 9];
00148                   result +=
00149                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00150                                               SELF_ON_BOARD * 9];
00151                 }
00152                 else
00153                 {
00154                   result -= drop_non_drop_table[index_x - 1];
00155                   result += drop_non_drop_table[index_x - 1 + 5];
00156                   result -=
00157                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00158                                               SELF_ON_BOARD * 9];
00159                   result +=
00160                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00161                                               OPP_ON_BOARD * 9];
00162                 }
00163                 result +=
00164                   state_king_relative_table[std::abs(king_bw[BLACK].x() -
00165                                                      moved.to().x()) +
00166                                             BOTH_ON_BOARD * 9];
00167                 result -=
00168                   state_king_relative_table[std::abs(king_bw[WHITE].x() -
00169                                                      moved.to().x()) +
00170                                             BOTH_ON_BOARD * 9];
00171               }
00172               else
00173               {
00174                 result -=
00175                   state_king_relative_table[std::abs(king_bw[BLACK].x() -
00176                                                      moved.to().x()) +
00177                                             BOTH_ON_STAND * 9];
00178                 result +=
00179                   state_king_relative_table[std::abs(king_bw[WHITE].x() -
00180                                                      moved.to().x()) +
00181                                             BOTH_ON_STAND * 9];
00182                 if (P == BLACK)
00183                 {
00184                   result += drop_non_drop_table[index_x - 1];
00185                   result -= drop_non_drop_table[index_x - 1 + 5];
00186                   result +=
00187                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00188                                               SELF_ON_BOARD * 9];
00189                   result -=
00190                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00191                                               OPP_ON_BOARD * 9];
00192                 }
00193                 else
00194                 {
00195                   result += drop_non_drop_table[index_x - 1 + 5];
00196                   result -= drop_non_drop_table[index_x - 1];
00197                   result +=
00198                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00199                                               OPP_ON_BOARD * 9];
00200                   result -=
00201                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00202                                               SELF_ON_BOARD * 9];
00203                 }
00204               }
00205               if (P == BLACK)
00206               {
00207                 result -= value(attack_index, defense_index, attack_index_y, 
00208                                 defense_index_y, attack_index_x, defense_index_x);
00209                 if (state.hasPieceOnStand<PAWN>(P))
00210                 {
00211                   result -= standValue(attack_index, defense_index, attack_index_y, 
00212                                        defense_index_y, attack_index_x, defense_index_x);
00213                 }
00214               }
00215               else
00216               {
00217                 result += value(attack_index, defense_index, attack_index_y, 
00218                                 defense_index_y, attack_index_x, defense_index_x);
00219                 if (state.hasPieceOnStand<PAWN>(P))
00220                 {
00221                   result += standValue(attack_index, defense_index, attack_index_y, 
00222                                        defense_index_y, attack_index_x, defense_index_x);
00223                 }
00224               }
00225             }
00226             if (moved.isPromotion())
00227             {
00228               const int attack_index = index(kings[1], moved.to().x());
00229               const int defense_index = index(kings[0], moved.to().x());
00230               const int attack_index_x =
00231                 indexX<true>(king_piece[1], moved.to().x());
00232               const int defense_index_x =
00233                 indexX<false>(king_piece[0], moved.to().x());
00234               const int attack_index_y = indexY<altP>(king_piece[1], moved.to().x());
00235               const int defense_index_y = indexY<P>(king_piece[0], moved.to().x());
00236               if (P == BLACK)
00237               {
00238                 result += value(attack_index, defense_index, attack_index_y, 
00239                                 defense_index_y, attack_index_x, defense_index_x);
00240                 if (state.hasPieceOnStand<PAWN>(P))
00241                 {
00242                   result += standValue(attack_index, defense_index, attack_index_y, 
00243                                        defense_index_y, attack_index_x, defense_index_x);
00244                 }
00245               }
00246               else
00247               {
00248                 result -= value(attack_index, defense_index, attack_index_y, 
00249                                 defense_index_y, attack_index_x, defense_index_x);
00250                 if (state.hasPieceOnStand<PAWN>(P))
00251                 {
00252                   result -= standValue(attack_index, defense_index, attack_index_y, 
00253                                        defense_index_y, attack_index_x, defense_index_x);
00254                 }
00255               }
00256               const int index_x = (moved.to().x() > 5 ? 10 -
00257                                    moved.to().x() : moved.to().x());
00258               if (state.isPawnMaskSet<altP>(moved.to().x()))
00259               {
00260                 result -=
00261                   state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00262                                             BOTH_ON_BOARD * 9];
00263                 result +=
00264                   state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00265                                             BOTH_ON_BOARD * 9];
00266                 if (P == BLACK)
00267                 {
00268                   result += drop_non_drop_table[index_x - 1 + 5];
00269                   result -= drop_non_drop_table[index_x - 1];
00270                   result +=
00271                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00272                                               OPP_ON_BOARD * 9];
00273                   result -=
00274                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00275                                               SELF_ON_BOARD * 9];
00276                 }
00277                 else
00278                 {
00279                   result += drop_non_drop_table[index_x - 1];
00280                   result -= drop_non_drop_table[index_x - 1 + 5];
00281                   result +=
00282                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00283                                               SELF_ON_BOARD * 9];
00284                   result -=
00285                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00286                                               OPP_ON_BOARD * 9];
00287                 }
00288               }
00289               else
00290               {
00291                 result +=
00292                   state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00293                                             BOTH_ON_STAND * 9];
00294                 result -=
00295                   state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00296                                             BOTH_ON_STAND * 9];
00297                 if (captured == PAWN)
00298                 {
00299                   result -=
00300                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00301                                               BOTH_ON_BOARD * 9];
00302                   result +=
00303                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00304                                               BOTH_ON_BOARD * 9];
00305                 }
00306                 else
00307                 {
00308                   if (P == BLACK)
00309                   {
00310                     result -= drop_non_drop_table[index_x - 1];
00311                     result += drop_non_drop_table[index_x - 1 + 5];
00312                     result -=
00313                       state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00314                                                 SELF_ON_BOARD * 9];
00315                     result +=
00316                       state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00317                                                 OPP_ON_BOARD * 9];
00318                   }
00319                   else
00320                   {
00321                     result -= drop_non_drop_table[index_x - 1 + 5];
00322                     result += drop_non_drop_table[index_x - 1];
00323                     result -=
00324                       state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00325                                                 OPP_ON_BOARD * 9];
00326                     result +=
00327                       state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00328                                                 SELF_ON_BOARD * 9];
00329                   }
00330                 }
00331               }
00332             }
00333           }
00334 
00335           if (captured == PAWN)
00336           {
00337             const int attack_index = index(kings[0], moved.to().x());
00338             const int defense_index = index(kings[1], moved.to().x());
00339             const int attack_index_x =
00340               indexX<true>(king_piece[0], moved.to().x());
00341             const int defense_index_x =
00342               indexX<false>(king_piece[1], moved.to().x());
00343             const int attack_index_y = indexY<P>(king_piece[0], moved.to().x());
00344             const int defense_index_y = indexY<altP>(king_piece[1], moved.to().x());
00345             if (P == BLACK)
00346             {
00347               result -= value(attack_index, defense_index, attack_index_y, 
00348                               defense_index_y, attack_index_x, defense_index_x);
00349               if (state.hasPieceOnStand<PAWN>(alt(P)))
00350               {
00351                 result -= standValue(attack_index, defense_index, attack_index_y, 
00352                                      defense_index_y, attack_index_x, defense_index_x);
00353               }
00354             }
00355             else
00356             {
00357               result += value(attack_index, defense_index, attack_index_y, 
00358                               defense_index_y, attack_index_x, defense_index_x);
00359               if (state.hasPieceOnStand<PAWN>(alt(moved.player())))
00360               {
00361                 result += standValue(attack_index, defense_index, attack_index_y, 
00362                                      defense_index_y, attack_index_x, defense_index_x);
00363               }
00364             }
00365             if (!(moved.ptype() == PPAWN && moved.isPromotion())) // promote is already handled above
00366             {
00367               const int index_x =
00368                 (moved.to().x() > 5 ? 10 - moved.to().x() : moved.to().x());
00369               if (state.isPawnMaskSet<P>(moved.to().x()))
00370               {
00371                 result -=
00372                   state_king_relative_table[std::abs(king_bw[BLACK].x() -
00373                                                      moved.to().x()) +
00374                                             BOTH_ON_BOARD * 9];
00375                 result +=
00376                   state_king_relative_table[std::abs(king_bw[WHITE].x() -
00377                                                      moved.to().x()) +
00378                                             BOTH_ON_BOARD * 9];
00379                 if (P == BLACK)
00380                 {
00381                   result += drop_non_drop_table[index_x - 1];
00382                   result -= drop_non_drop_table[index_x - 1 + 5];
00383                   result +=
00384                     state_king_relative_table[std::abs(king_bw[BLACK].x() -
00385                                                        moved.to().x()) +
00386                                               SELF_ON_BOARD * 9];
00387                   result -=
00388                     state_king_relative_table[std::abs(king_bw[WHITE].x() -
00389                                                        moved.to().x()) +
00390                                               OPP_ON_BOARD * 9];
00391                 }
00392                 else
00393                 {
00394                   result += drop_non_drop_table[index_x - 1 + 5];
00395                   result -= drop_non_drop_table[index_x - 1];
00396                   result +=
00397                     state_king_relative_table[std::abs(king_bw[BLACK].x() -
00398                                                        moved.to().x()) +
00399                                               OPP_ON_BOARD * 9];
00400                   result -=
00401                     state_king_relative_table[std::abs(king_bw[WHITE].x() -
00402                                                        moved.to().x()) +
00403                                               SELF_ON_BOARD * 9];
00404                 }
00405               }
00406               else
00407               {
00408                 if (P == BLACK)
00409                 {
00410                   result -= drop_non_drop_table[index_x - 1 + 5];
00411                   result += drop_non_drop_table[index_x - 1];
00412                   result -=
00413                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00414                                               OPP_ON_BOARD * 9];
00415                   result +=
00416                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00417                                               SELF_ON_BOARD * 9];
00418                 }
00419                 else
00420                 {
00421                   result -= drop_non_drop_table[index_x - 1];
00422                   result += drop_non_drop_table[index_x - 1 + 5];
00423                   result -=
00424                     state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00425                                               SELF_ON_BOARD * 9];
00426                   result +=
00427                     state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00428                                               OPP_ON_BOARD * 9];
00429                 }
00430                 result +=
00431                   state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
00432                                             BOTH_ON_STAND * 9];
00433                 result -=
00434                   state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
00435                                             BOTH_ON_STAND * 9];
00436               }
00437             }
00438           }
00439           return result;
00440         }
00441       };
00442 
00443       class PawnDropX
00444       {
00445       public:
00446         enum { ONE_DIM = 90, DIM = ONE_DIM * EvalStages };
00447         static void setUp(const Weights &weights);
00448       };
00449 
00450       class PawnDropPawnStand
00451       {
00452       public:
00453         enum { ONE_DIM = 18, DIM = ONE_DIM * EvalStages };
00454         static void setUp(const Weights &weights);
00455       };
00456       class PawnDropPawnStandX
00457       {
00458       public:
00459         enum { ONE_DIM = 90, DIM = ONE_DIM * EvalStages };
00460         static void setUp(const Weights &weights);
00461       };
00462       class PawnDropPawnStandY
00463       {
00464       public:
00465         enum { ONE_DIM = 162, DIM = ONE_DIM * EvalStages };
00466         static void setUp(const Weights &weights);
00467       };
00468 
00469       class PawnDropNonDrop
00470       {
00471       public:
00472         enum { ONE_DIM = 10, DIM = ONE_DIM * EvalStages };
00473         static void setUp(const Weights &weights);
00474       };
00475 
00476       class PawnStateKingRelative
00477       {
00478       public:
00479         enum { ONE_DIM = 36, DIM = ONE_DIM * EvalStages };
00480         static void setUp(const Weights &weights);
00481       };
00482 
00483       class NoPawnOnStand
00484       {
00485       public:
00486         enum { DIM = 1 };
00487       private:
00488         static MultiInt weight;
00489       public:
00490         static void setUp(const Weights &weights,int stage);
00491         static MultiInt eval(const NumEffectState &state, int black_pawn_count)
00492         {
00493           if (black_pawn_count > 9 && !state.hasPieceOnStand<PAWN>(WHITE))
00494             return -weight;
00495           else if (black_pawn_count < 9 && !state.hasPieceOnStand<PAWN>(BLACK))
00496             return weight;
00497 
00498           return MultiInt();
00499         }
00500       };
00501 
00502       struct PawnAdvanceUtil
00503       {
00504         static int index(Player P, Square pos)
00505         {
00506           return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
00507         }
00508         static bool cantAdvance(const NumEffectState &state, const Piece pawn)
00509         {
00510           return cantAdvance(state, pawn.ptypeO(), pawn.square());
00511         }
00512         static bool cantAdvance(const NumEffectState &state,
00513                                 const PtypeO ptypeO, const Square position)
00514         {
00515           assert(getPtype(ptypeO) == PAWN);
00516           return state.pieceAt(Board_Table.nextSquare(getOwner(ptypeO),
00517                                                            position,
00518                                                            U)).isOnBoardByOwner(getOwner(ptypeO));
00519         }
00520       };
00521       struct PawnAdvanceAll : public PawnAdvanceUtil
00522       {
00523         template <osl::Player P> 
00524         static void adjust(int index, MultiInt& values);
00525         template<Player P>
00526         static void evalWithUpdateBang(const NumEffectState &state, Move moved,
00527                                        MultiInt& last_value);
00528       };
00529 
00530       class PawnAdvance : public PawnAdvanceUtil
00531       {
00532       public:
00533         enum { DIM = 9 };
00534       private:
00535         static CArray<MultiInt, 9> table;
00536         friend struct PawnAdvanceAll;
00537       public:
00538         static void setUp(const Weights &weights,int stage);
00539         static MultiInt eval(const NumEffectState &state);
00540       };
00541 
00542       class SilverFeatures
00543       {
00544       public:
00545         static MultiInt eval(const NumEffectState &state);
00546       protected:
00547         template <Player P>
00548         static int indexRetreat(Square pos)
00549         {
00550           return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
00551         }
00552         template<Player P>
00553         static bool canRetreat(const NumEffectState &state,
00554                                const Piece silver);
00555         template <Player P>
00556         static MultiInt evalOne(const NumEffectState &state,
00557                                 const Piece silver,
00558                                 const CArray<Square, 2> &kings)
00559         {
00560           MultiInt result;
00561           if (!canRetreat<P>(state,silver))
00562           {
00563             result += retreat_table[indexRetreat<P>(silver.square())];
00564           }
00565           const Square up =
00566             silver.square() + DirectionPlayerTraits<U, P>::offset();
00567           if (up.isOnBoard())
00568           {
00569             const Piece up_piece = state.pieceAt(up);
00570             if (up_piece.isEmpty() &&
00571                 (state.hasEffectByPtype<PAWN>(alt(P), up) ||
00572                  !state.isPawnMaskSet<PlayerTraits<P>::opponent>(silver.square().x())))
00573             {
00574               const int x_diff =
00575                 std::abs(kings[P].x() - silver.square().x());
00576               const int y_diff = (P == BLACK ?
00577                                   silver.square().y() - kings[P].y() :
00578                                   kings[P].y() - silver.square().y());
00579               result += head_table[x_diff + 9 * (y_diff + 8)];
00580             }
00581           }
00582           return result;
00583         }
00584         static CArray<MultiInt, 153> head_table;
00585         static CArray<MultiInt, 9> retreat_table;
00586       };
00587 
00588       class SilverHeadPawnKingRelative : public SilverFeatures
00589       {
00590       public:
00591         enum { ONE_DIM = 153, DIM = ONE_DIM * EvalStages };
00592         static void setUp(const Weights &weights);
00593       };
00594 
00595       class SilverRetreat : public SilverFeatures
00596       {
00597       public:
00598         enum { DIM = 9 };
00599         static void setUp(const Weights &weights,int stage);
00600       };
00601 
00602       class GoldFeatures
00603       {
00604       public:
00605         static MultiInt eval(const NumEffectState &state);
00606       protected:
00607         template <Player P>
00608         static int indexRetreat(Square pos)
00609         {
00610           return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
00611         }
00612         static int indexSideX(Square pos)
00613         {
00614           return (pos.x() > 5 ? 9 - pos.x() : pos.x() - 1);
00615         }
00616         template <Player P>
00617         static int indexSideY(Square pos)
00618         {
00619           return (P == BLACK ? (pos.y() - 1) : (9 - pos.y())) + 5;
00620         }
00621         template<Player P>
00622         static bool canRetreat(const NumEffectState &state,
00623                                const Piece gold);
00624         template<Player P>
00625         static bool canMoveToSide(const NumEffectState &state,
00626                                   const Piece gold)
00627         {
00628           Square r = gold.square() + DirectionPlayerTraits<R, P>::offset();
00629           Square l = gold.square() + DirectionPlayerTraits<L, P>::offset();
00630           // check effect is from lesser pieces?
00631           if ((!r.isOnBoard() ||
00632                state.pieceAt(r).isOnBoardByOwner(gold.owner()) ||
00633                state.hasEffectAt(alt(gold.owner()), r)) &&
00634               (!l.isOnBoard() ||
00635                state.pieceAt(l).isOnBoardByOwner(gold.owner()) ||
00636                state.hasEffectAt(alt(gold.owner()), l)))
00637           {
00638             return false;
00639           }
00640           return true;
00641         }
00642         template <Player P>
00643         static MultiInt evalOne(const NumEffectState &state,
00644                                 const Piece gold,
00645                                 const CArray<Square, 2> &kings)
00646         {
00647           assert(P==gold.owner());
00648           MultiInt result;
00649           if (!canRetreat<P>(state, gold))
00650           {
00651             result += retreat_table[indexRetreat<P>(gold.square())];
00652           }
00653           if (!canMoveToSide<P>(state, gold))
00654           {
00655             result += side_table[indexSideX(gold.square())] +
00656               side_table[indexSideY<P>(gold.square())];
00657           }
00658           const Square uur = gold.square().neighbor<P,UUR>();
00659           const Square uul = gold.square().neighbor<P,UUL>();
00660           if ((state.pieceAt(uul).isEmpty() && !state.hasEffectAt(P, uul))
00661               || (state.pieceAt(uur).isEmpty() && !state.hasEffectAt(P, uur)))
00662           {
00663             assert(state.kingSquare(gold.owner()) == kings[gold.owner()]);
00664             const Square king = kings[P];
00665             const int x_diff = std::abs(king.x() - gold.square().x());
00666             const int y_diff = (P == BLACK ?
00667                                 gold.square().y() - king.y() :
00668                                 king.y() - gold.square().y());
00669             result += knight_table[x_diff + 9 * (y_diff + 8)];
00670           }
00671           return result;
00672         }
00673         static CArray<MultiInt, 153> knight_table;
00674         static CArray<MultiInt, 9> retreat_table;
00675         static CArray<MultiInt, 14> side_table;
00676       };
00677 
00678       class GoldKnightKingRelative : public GoldFeatures
00679       {
00680       public:
00681         enum { ONE_DIM = 153, DIM = ONE_DIM * EvalStages };
00682         static void setUp(const Weights &weights);
00683       };
00684 
00685       class GoldRetreat : public GoldFeatures
00686       {
00687       public:
00688         enum { DIM = 9 };
00689         static void setUp(const Weights &weights,int stage);
00690       };
00691 
00692       class GoldSideMove : public GoldFeatures
00693       {
00694       public:
00695         enum { ONE_DIM = 14, DIM = ONE_DIM * EvalStages };
00696         static void setUp(const Weights &weights);
00697       };
00698 
00699       class KnightAdvance
00700       {
00701       public:
00702         enum { DIM = 9 };
00703       private:
00704         static CArray<MultiInt, 9> table;
00705         static int index(Player P, Square pos)
00706         {
00707           return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
00708         }
00709         template<Player P>
00710         static bool cantAdvance(const NumEffectState &state,
00711                                 const Piece knight);
00712       public:
00713         static void setUp(const Weights &weights,int stage);
00714         static MultiInt eval(const NumEffectState &state);
00715       };
00716 
00717       class AllGold
00718       {
00719       public:
00720         enum { DIM = 1 };
00721         static void setUp(const Weights &weights,int stage);
00722         static MultiInt eval(int black_major_count)
00723         {
00724           if (black_major_count == 4)
00725             return weight;
00726           else if (black_major_count == 0)
00727             return -weight;
00728 
00729           return MultiInt();
00730         }
00731       private:
00732         static MultiInt weight;
00733       };
00734 
00735       class PtypeY
00736       {
00737       public:
00738         enum { DIM = PTYPE_SIZE * 9 };
00739         static void setUp(const Weights &weights,int stage);
00740         static MultiInt eval(const NumEffectState &state);
00741         template<Player P>
00742         static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
00743                                   MultiInt const& last_value);
00744       private:
00745         static CArray<MultiInt, 144> table;
00746         static int index(const Piece piece)
00747         {
00748           return index(piece.owner(), piece.ptype(), piece.square());
00749         }
00750         static int index(const Player player, const Ptype ptype, const Square pos)
00751         {
00752           const int y = (player == BLACK ? pos.y() : 10 - pos.y()) - 1;
00753           return ptype * 9 + y;
00754         }
00755       };
00756 
00757       class PtypeX
00758       {
00759       public:
00760         enum { DIM = PTYPE_SIZE * 5 };
00761         static void setUp(const Weights &weights,int stage);
00762         static MultiInt eval(const NumEffectState &state);
00763         template<Player P>
00764         static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
00765                                   MultiInt const& last_value);
00766       private:
00767         static CArray<MultiInt, 80> table;
00768         static int index(const Piece piece)
00769         {
00770           return index(piece.owner(), piece.ptype(), piece.square());
00771         }
00772         static int index(const Player, const Ptype ptype, const Square pos)
00773         {
00774           const int x = (pos.x() > 5 ? 10 - pos.x() : pos.x()) - 1;
00775           return ptype * 5 + x;
00776         }
00777       };
00778 
00779       class KnightCheck
00780       {
00781         friend class KnightCheckY;
00782       public:
00783         enum { DIM = 1 };
00784         static void setUp(const Weights &weights,int stage);
00785         static MultiInt eval(const NumEffectState &state);
00786         template <Player Defense>
00787         static bool canCheck(const NumEffectState &state)
00788         {
00789           const Square king = state.kingSquare<Defense>();
00790           const Player offense = PlayerTraits<Defense>::opponent;
00791           const Square ul =
00792             king + DirectionPlayerTraits<UUL, Defense>::offset();
00793           const Square ur =
00794             king + DirectionPlayerTraits<UUR, Defense>::offset();
00795           if (ul.isOnBoard())
00796           {
00797             const Piece p = state.pieceAt(ul);
00798             if (!state.hasEffectAt<Defense>(ul) &&
00799                 ((p.isEmpty() && state.hasPieceOnStand<KNIGHT>(offense)) ||
00800                  (!p.isOnBoardByOwner<offense>() &&
00801                   state.hasEffectByPtypeStrict<KNIGHT>(offense, ul))))
00802               return true;
00803           }
00804           if (ur.isOnBoard())
00805           {
00806             const Piece p = state.pieceAt(ur);
00807             if (!state.hasEffectAt<Defense>(ur) &&
00808                 ((p.isEmpty() && state.hasPieceOnStand<KNIGHT>(offense)) ||
00809                  (!p.isOnBoardByOwner<offense>() &&
00810                   state.hasEffectByPtypeStrict<KNIGHT>(offense, ur))))
00811               return true;
00812           }
00813           return false;
00814         }
00815         static MultiInt value(int index_y) { return weight + y_table[index_y]; }
00816       private:
00817         static MultiInt weight;
00818         template <Player King>
00819         static int indexY(int y) 
00820         {
00821           return (King == BLACK ? y - 1 : 9 - y) ;
00822         }
00823         static CArray<MultiInt, 9> y_table;
00824       };
00825 
00826       class KnightCheckY
00827       {
00828       public:
00829         enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages };
00830         static void setUp(const Weights &weights);
00831       };
00832 
00833       class KnightHead
00834       {
00835         friend class KnightHeadOppPiecePawnOnStand;
00836       public:
00837         enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages};
00838         static void setUp(const Weights &weights);
00839         static MultiInt eval(const NumEffectState &state);
00840       private:
00841         static CArray<MultiInt, 9> table;
00842         static CArray<MultiInt, 144> opp_table;
00843       };
00844 
00845       class KnightHeadOppPiecePawnOnStand
00846       {
00847       public:
00848         enum { ONE_DIM = 9 * 16, DIM = ONE_DIM * EvalStages};
00849         static void setUp(const Weights &weights);
00850       private:
00851       };
00852 
00853       class PawnPtypeOPtypeO
00854       {
00855         friend class PawnPtypeOPtypeOY;
00856       public:
00857         enum { ONE_DIM = 1024, DIM = ONE_DIM * EvalStages };
00858         static void setUp(const Weights &weights);
00859         static MultiInt eval(const NumEffectState &state);
00860         template<Player P>
00861         static MultiInt evalWithUpdate(const NumEffectState &state,
00862                                         Move moved,
00863                                         const CArray2d<int, 2, 9> &pawns,
00864                                         const MultiInt &last_value);
00865       private:
00866         static int index(Player P, PtypeO up, PtypeO up_up)
00867         {
00868           if (P == WHITE)
00869           {
00870             up = altIfPiece(up);
00871             up_up = altIfPiece(up_up);
00872           }
00873           return (up - PTYPEO_MIN) * 32 + (up_up - PTYPEO_MIN);
00874         }
00875         static int indexY(Player P, PtypeO up, PtypeO up_up, int y)
00876         {
00877           const int y_index = (P == BLACK ? y - 1 : 9 - y);
00878           return index(P, up, up_up) + 1024 * y_index;
00879         }
00880         static CArray<MultiInt, 1024> table;
00881         static CArray<MultiInt, 9216> y_table;
00882       };
00883 
00884       class PromotedMinorPieces
00885       {
00886         friend class PromotedMinorPiecesY;
00887       public:
00888         enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages };
00889         static void setUp(const Weights &weights);
00890         static MultiInt eval(const NumEffectState &state);
00891         static MultiInt evalWithUpdate(
00892           const NumEffectState &state,
00893           Move moved,
00894           const MultiInt &last_values);
00895         template <int Sign>
00896         static void adjust(int index, int index_attack, int index_defense,
00897                            MultiInt &result);
00898       private:
00899         template <Player P>
00900         static void evalOne(const NumEffectState &state,
00901                             const PieceMask promoted,
00902                             MultiInt &result);
00903         template <bool attack, Player owner>
00904         static int indexY(const Square king, int x_diff)
00905         {
00906           const int y = (owner == BLACK ? king.y() : 10 - king.y());
00907           return x_diff + (y - 1) * 9 + (attack ? 0 : 81);
00908         }
00909         static CArray<MultiInt, 9> table;
00910         static CArray<MultiInt, 162> y_table;
00911       };
00912       class NonPawnAttacked
00913       {
00914         friend class NonPawnAttackedKingRelative;
00915       public:
00916         enum { ONE_DIM = 64, DIM = ONE_DIM * EvalStages };
00917         static void setUp(const Weights &weights);
00918         static void eval(const NumEffectState &state, MultiIntPair& out);
00919         template<Player P>
00920         static void evalWithUpdateBang(
00921           const NumEffectState &state,
00922           Move moved,
00923           const CArray<PieceMask, 2> &effected_mask,
00924           MultiIntPair &last_value_and_out);
00925         template <int Sign>
00926         static void adjust(int black_turn_king_attack,
00927                            int black_turn_king_defense,
00928                            int white_turn_king_attack,
00929                            int white_turn_king_defense,
00930                            MultiIntPair &result);
00931       private:
00932         static int index(bool same_turn, bool has_support, Ptype ptype)
00933         {
00934           return ptype + (same_turn ? 0 : PTYPE_SIZE) +
00935             (has_support ? 0 : PTYPE_SIZE * 2);
00936         }
00937         template <bool Attack>
00938         static int indexK(Square king, bool same_turn, bool has_support,
00939                           Square position, Player owner, Ptype ptype)
00940         {
00941           const int x_diff = std::abs(position.x() - king.x());
00942           const int y_diff = (owner == BLACK ?
00943                               position.y() - king.y() :
00944                               king.y() - position.y());
00945           return ((ptype + (same_turn ? 0 : PTYPE_SIZE) +
00946                    (has_support ? 0 : PTYPE_SIZE * 2)) * 9 + x_diff) * 17 +
00947             y_diff + 8 + (Attack ? 0 : 9792);
00948         }
00949         template <bool Attack>
00950         static int indexK(Square king, bool same_turn, bool has_support,
00951                           Piece piece)
00952         {
00953           return indexK<Attack>(king, same_turn, has_support,
00954                                 piece.square(), piece.owner(),
00955                                 piece.ptype());
00956         }
00957 
00958         template <Player Attacked>
00959         static void updateEffectChanged(
00960           const NumEffectState &state,
00961           const CArray<PieceMask, 2> &effected_mask,
00962           const CArray<PieceMask, 2> &new_mask,
00963           int moved_piece_number,
00964           MultiIntPair &result)
00965         {
00966           CArray<Square, 2> kings = {{ state.kingSquare<BLACK>(),
00967                                          state.kingSquare<WHITE>() }};
00968           // old without, new with
00969           PieceMask black_old = (~effected_mask[alt(Attacked)]) & new_mask[alt(Attacked)] & state.piecesOnBoard(Attacked);
00970           black_old.reset(moved_piece_number);
00971           while (black_old.any())
00972           {
00973             const Piece piece = state.pieceOf(black_old.takeOneBit());
00974             const bool has_support =
00975               new_mask[Attacked].test(piece.number());
00976             const int index_king_black_turn_attack =
00977               indexK<true>(kings[alt(Attacked)], Attacked == BLACK, has_support, piece);
00978             const int index_king_white_turn_attack =
00979               indexK<true>(kings[alt(Attacked)], Attacked == WHITE, has_support, piece);
00980             const int index_king_black_turn_defense =
00981               indexK<false>(kings[Attacked], Attacked == BLACK, has_support, piece);
00982             const int index_king_white_turn_defense =
00983               indexK<false>(kings[Attacked], Attacked == WHITE, has_support, piece);
00984             adjust<Attacked == BLACK ? 1 : -1>(
00985               index_king_black_turn_attack, index_king_black_turn_defense,
00986               index_king_white_turn_attack, index_king_white_turn_defense,
00987               result);
00988           }
00989 
00990           // old with, new without
00991           PieceMask black_new = effected_mask[alt(Attacked)] & (~new_mask[alt(Attacked)]) & state.piecesOnBoard(Attacked);
00992           black_new.reset(moved_piece_number);
00993           while (black_new.any())
00994           {
00995             const Piece piece = state.pieceOf(black_new.takeOneBit());
00996             const bool has_support =
00997               effected_mask[Attacked].test(piece.number());
00998             const int index_king_black_turn_attack =
00999               indexK<true>(kings[alt(Attacked)], Attacked == BLACK, has_support, piece);
01000             const int index_king_white_turn_attack =
01001               indexK<true>(kings[alt(Attacked)], Attacked == WHITE, has_support, piece);
01002             const int index_king_black_turn_defense =
01003               indexK<false>(kings[Attacked], Attacked == BLACK, has_support, piece);
01004             const int index_king_white_turn_defense =
01005               indexK<false>(kings[Attacked], Attacked == WHITE, has_support, piece);
01006             adjust<Attacked == BLACK ? -1 : 1>(
01007               index_king_black_turn_attack, index_king_black_turn_defense,
01008               index_king_white_turn_attack, index_king_white_turn_defense,
01009               result);
01010           }
01011           // old with, new with, self with, self without
01012           PieceMask black_self_old = effected_mask[alt(Attacked)] & new_mask[alt(Attacked)] &
01013             effected_mask[Attacked] & (~new_mask[Attacked]) & state.piecesOnBoard(Attacked);
01014           black_self_old.reset(moved_piece_number);
01015           while (black_self_old.any())
01016           {
01017             const Piece piece = state.pieceOf(black_self_old.takeOneBit());
01018             const int index_king_black_turn_attack =
01019               indexK<true>(kings[alt(Attacked)], Attacked == BLACK, false, piece);
01020             const int index_king_white_turn_attack =
01021               indexK<true>(kings[alt(Attacked)], Attacked == WHITE, false, piece);
01022             const int index_king_black_turn_defense =
01023               indexK<false>(kings[Attacked], Attacked == BLACK, false, piece);
01024             const int index_king_white_turn_defense =
01025               indexK<false>(kings[Attacked], Attacked == WHITE, false, piece);
01026             const int index_king_black_turn_attack_old =
01027               indexK<true>(kings[alt(Attacked)], Attacked == BLACK, true, piece);
01028             const int index_king_white_turn_attack_old =
01029               indexK<true>(kings[alt(Attacked)], Attacked == WHITE, true, piece);
01030             const int index_king_black_turn_defense_old =
01031               indexK<false>(kings[Attacked], Attacked == BLACK, true, piece);
01032             const int index_king_white_turn_defense_old =
01033               indexK<false>(kings[Attacked], Attacked == WHITE, true, piece);
01034             adjust<Attacked == BLACK ? -1 : 1>(
01035               index_king_black_turn_attack_old, index_king_black_turn_defense_old,
01036               index_king_white_turn_attack_old, index_king_white_turn_defense_old,
01037               result);
01038             adjust<Attacked == BLACK ? 1 : -1>(
01039               index_king_black_turn_attack, index_king_black_turn_defense,
01040               index_king_white_turn_attack, index_king_white_turn_defense,
01041               result);
01042           }
01043           // old with, new with, self without, self with
01044           PieceMask black_self_new = effected_mask[alt(Attacked)] & new_mask[alt(Attacked)] &
01045             (~effected_mask[Attacked]) & new_mask[Attacked] & state.piecesOnBoard(Attacked);
01046           black_self_new.reset(moved_piece_number);
01047           while (black_self_new.any())
01048           {
01049             const Piece piece = state.pieceOf(black_self_new.takeOneBit());
01050             const int index_king_black_turn_attack =
01051               indexK<true>(kings[alt(Attacked)], Attacked == BLACK, true, piece);
01052             const int index_king_white_turn_attack =
01053               indexK<true>(kings[alt(Attacked)], Attacked == WHITE, true, piece);
01054             const int index_king_black_turn_defense =
01055               indexK<false>(kings[Attacked], Attacked == BLACK, true, piece);
01056             const int index_king_white_turn_defense =
01057               indexK<false>(kings[Attacked], Attacked == WHITE, true, piece);
01058             const int index_king_black_turn_attack_old =
01059               indexK<true>(kings[alt(Attacked)], Attacked == BLACK, false, piece);
01060             const int index_king_white_turn_attack_old =
01061               indexK<true>(kings[alt(Attacked)], Attacked == WHITE, false, piece);
01062             const int index_king_black_turn_defense_old =
01063               indexK<false>(kings[Attacked], Attacked == BLACK, false, piece);
01064             const int index_king_white_turn_defense_old =
01065               indexK<false>(kings[Attacked], Attacked == WHITE, false, piece);
01066 
01067             adjust<Attacked == BLACK ? -1 : 1>(
01068               index_king_black_turn_attack_old, index_king_black_turn_defense_old,
01069               index_king_white_turn_attack_old, index_king_white_turn_defense_old,
01070               result);
01071             adjust<Attacked == BLACK ? 1 : -1>(
01072               index_king_black_turn_attack, index_king_black_turn_defense,
01073               index_king_white_turn_attack, index_king_white_turn_defense,
01074               result);
01075           }
01076         }
01077         static CArray<MultiInt, 64> table;
01078         static CArray<MultiInt, 19584> king_table;
01079       };
01080 
01081       class NonPawnAttackedKingRelative
01082       {
01083       public:
01084         enum { ONE_DIM = 19584, DIM = ONE_DIM * EvalStages};
01085         static void setUp(const Weights &weights);
01086       };
01087 
01088       class PromotedMinorPiecesY
01089       {
01090       public:
01091         enum { ONE_DIM = 162, DIM = ONE_DIM * EvalStages };
01092         static void setUp(const Weights &weights);
01093       };
01094 
01095       class PawnPtypeOPtypeOY
01096       {
01097       public:
01098         enum { ONE_DIM = 9216, DIM = ONE_DIM * EvalStages };
01099         static void setUp(const Weights &weights);
01100       };
01101 
01102       class NonPawnAttackedPtype
01103       {
01104       public:
01105         enum { ONE_DIM = 1024, DIM = ONE_DIM * EvalStages};
01106         static void setUp(const Weights &weights);
01107         static void eval(const NumEffectState &state,
01108                          CArray<PieceMask, 40> &attacked_mask,
01109                          MultiIntPair& out);
01110         template<Player P>
01111         static void evalWithUpdateBang(
01112           const NumEffectState &state,
01113           Move moved,
01114           const CArray<PieceMask, 2> &effected_mask,
01115           CArray<PieceMask, 40> &attacked_mask,
01116           MultiIntPair &last_value_and_out);
01117       private:
01118         static int index(bool same_turn, bool has_support, Ptype ptype,
01119                          Ptype attack_ptype)
01120         {
01121           return (ptype + (same_turn ? 0 : PTYPE_SIZE) +
01122                   (has_support ? 0 : PTYPE_SIZE * 2)) * 16 + attack_ptype;
01123         }
01124         template <int Sign>
01125         static void adjust(int black, int white, MultiIntPair &result)
01126         {
01127           if(Sign>0){
01128             result[BLACK] += table[black];
01129             result[WHITE] += table[white];
01130           }
01131           else{
01132             result[BLACK] -= table[black];
01133             result[WHITE] -= table[white];
01134           }
01135         }
01136         template <bool Plus>
01137         static void evalOnePiece(const Player player,
01138                                  const Ptype ptype,
01139                                  const Ptype attack_ptype,
01140                                  bool with_support,
01141                                  MultiIntPair &result)
01142         {
01143           const int index_black_turn = index(BLACK == player, with_support,
01144                                              ptype, attack_ptype);
01145           const int index_white_turn = index(WHITE == player, with_support,
01146                                              ptype, attack_ptype);
01147           if (Plus)
01148             adjust<1>(index_black_turn, index_white_turn, result);
01149           else
01150             adjust<-1>(index_black_turn, index_white_turn, result);
01151         }
01152         template <Player P>
01153         static void updateChanged(const NumEffectState &state,
01154                                   const Piece p,
01155                                   Move moved,
01156                                   int captured_number,
01157                                   const CArray<PieceMask, 2> &effected_mask,
01158                                   const CArray<PieceMask, 2> &new_mask,
01159                                   CArray<PieceMask, 40> &attacked_mask,
01160                                   MultiIntPair &result)
01161         {
01162           // old without, new with
01163           PieceMask old = (~effected_mask[alt(P)]) & new_mask[alt(P)] & state.piecesOnBoard(P);
01164           old.reset(p.number());
01165           while (old.any())
01166           {
01167             const Piece piece = state.pieceOf(old.takeOneBit());
01168             const bool has_support =
01169               new_mask[P].test(piece.number());
01170             PieceMask attacking =
01171               state.effectSetAt(piece.square()) &
01172               state.piecesOnBoard(alt(P));
01173             attacked_mask[piece.number()] = attacking;
01174             while (attacking.any())
01175             {
01176               const Piece attack = state.pieceOf(attacking.takeOneBit());
01177               evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
01178                                        has_support, result);
01179             }
01180           }
01181           // old with, new without
01182           PieceMask new_without = effected_mask[alt(P)] & (~new_mask[alt(P)]) & state.piecesOnBoard(P);
01183           new_without.reset(p.number());
01184           while (new_without.any())
01185           {
01186             const Piece piece = state.pieceOf(new_without.takeOneBit());
01187             const bool has_support =
01188               effected_mask[P].test(piece.number());
01189             PieceMask attacking = attacked_mask[piece.number()];
01190             if (moved.isPromotion() && attacking.test(p.number()))
01191             {
01192               evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
01193                                        has_support, result);
01194               attacking.reset(p.number());
01195             }
01196             if (captured_number != -1 && attacking.test(captured_number))
01197             {
01198               evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
01199                                        has_support, result);
01200               attacking.reset(captured_number);
01201             }
01202             while (attacking.any())
01203             {
01204               const Piece attack = state.pieceOf(attacking.takeOneBit());
01205               evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
01206                                        has_support, result);
01207             }
01208           }
01209           // old with, new with, self with, self without
01210           PieceMask self_old = effected_mask[alt(P)] &
01211             new_mask[alt(P)] &
01212             effected_mask[P] & (~new_mask[P]) & state.piecesOnBoard(P);
01213           self_old.reset(p.number());
01214           while (self_old.any())
01215           {
01216             const Piece piece = state.pieceOf(self_old.takeOneBit());
01217             PieceMask old_attacking = attacked_mask[piece.number()];
01218             if (moved.isPromotion() && old_attacking.test(p.number()))
01219             {
01220               evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
01221                                        true, result);
01222               old_attacking.reset(p.number());
01223             }
01224             if (captured_number != -1 && old_attacking.test(captured_number))
01225             {
01226               evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
01227                                        true, result);
01228               old_attacking.reset(captured_number);
01229             }
01230             while (old_attacking.any())
01231             {
01232               const Piece attack = state.pieceOf(old_attacking.takeOneBit());
01233               evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
01234                                        true, result);
01235             }
01236             PieceMask new_attacking = state.effectSetAt(piece.square())
01237               & state.piecesOnBoard(alt(P));
01238             attacked_mask[piece.number()] = new_attacking;
01239             while (new_attacking.any())
01240             {
01241               const Piece attack = state.pieceOf(new_attacking.takeOneBit());
01242               evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
01243                                        false, result);
01244             }
01245           }
01246           // old with, new with, self without, self with
01247           PieceMask self_new_with = effected_mask[alt(P)] &
01248             new_mask[alt(P)] &
01249             (~effected_mask[P]) & new_mask[P] & state.piecesOnBoard(P);
01250           self_new_with.reset(p.number());
01251           while (self_new_with.any())
01252           {
01253             const Piece piece = state.pieceOf(self_new_with.takeOneBit());
01254             PieceMask old_attacking = attacked_mask[piece.number()];
01255             if (moved.isPromotion() && old_attacking.test(p.number()))
01256             {
01257               evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
01258                                        false, result);
01259               old_attacking.reset(p.number());
01260             }
01261             if (captured_number != -1 && old_attacking.test(captured_number))
01262             {
01263               evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
01264                                        false, result);
01265               old_attacking.reset(captured_number);
01266             }
01267             while (old_attacking.any())
01268             {
01269               const Piece attack = state.pieceOf(old_attacking.takeOneBit());
01270               evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
01271                                        false, result);
01272             }
01273             PieceMask new_attacking = state.effectSetAt(piece.square())
01274               & state.piecesOnBoard(alt(P));
01275             attacked_mask[piece.number()] = new_attacking;
01276             while (new_attacking.any())
01277             {
01278               const Piece attack = state.pieceOf(new_attacking.takeOneBit());
01279               evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
01280                                        true, result);
01281             }
01282           }
01283           // old with, new with, support unchanged, attack changed
01284           PieceMask effected = effected_mask[P];
01285           effected ^= new_mask[P];
01286           effected = ~effected;
01287           PieceMask attack_changed = effected_mask[alt(P)] &
01288             new_mask[alt(P)] &
01289             effected & state.piecesOnBoard(P) &
01290             state.effectedChanged(alt(P));
01291           attack_changed.reset(p.number());
01292           while (attack_changed.any())
01293           {
01294             const Piece attacked = state.pieceOf(attack_changed.takeOneBit());
01295             PieceMask attack_old_mask = attacked_mask[attacked.number()];
01296             PieceMask attack_new_mask = state.effectSetAt(attacked.square()) & state.piecesOnBoard(alt(P));
01297             if (captured_number != -1 &&
01298                 attack_old_mask.test(captured_number))
01299             {
01300               evalOnePiece<P != BLACK>(P, attacked.ptype(),
01301                                        moved.capturePtype(),
01302                                        new_mask[P].test(attacked.number()),
01303                                        result);
01304               attack_old_mask.reset(captured_number);
01305             }
01306             if (moved.isPromotion() &&
01307                 attack_old_mask.test(p.number()))
01308             {
01309               evalOnePiece<P != BLACK>(P, attacked.ptype(),
01310                                        moved.oldPtype(),
01311                                new_mask[P].test(attacked.number()),
01312                                        result);
01313               attack_old_mask.reset(p.number());
01314             }
01315             if (moved.isPromotion() &&
01316                 attack_new_mask.test(p.number()))
01317             {
01318               evalOnePiece<P == BLACK>(P, attacked.ptype(),
01319                                        moved.ptype(),
01320                                        new_mask[P].test(attacked.number()),
01321                                        result);
01322               attack_new_mask.reset(p.number());
01323             }
01324             PieceMask gone = attack_old_mask & (~attack_new_mask);
01325             while (gone.any())
01326             {
01327               const Piece attacking = state.pieceOf(gone.takeOneBit());
01328               evalOnePiece<P != BLACK>(P, attacked.ptype(),
01329                                        attacking.ptype(),
01330                                        effected_mask[P].test(attacked.number()),
01331                                        result);
01332             }
01333             PieceMask added = (~attack_old_mask) & attack_new_mask;
01334             while (added.any())
01335             {
01336               const Piece attacking = state.pieceOf(added.takeOneBit());
01337               evalOnePiece<P == BLACK>(P, attacked.ptype(),
01338                                        attacking.ptype(),
01339                                        new_mask[P].test(attacked.number()),
01340                                        result);
01341             }
01342 
01343             attacked_mask[attacked.number()] = state.effectSetAt(attacked.square()) & state.piecesOnBoard(alt(P));
01344           }
01345         }
01346 
01347         static CArray<MultiInt, 1024> table;
01348       };
01349 
01350       class NonPawnAttackedPtypePair
01351       {
01352       public:
01353         enum {
01354           ONE_DIM = (PTYPE_SIZE * 2 * PTYPE_SIZE)*(PTYPE_SIZE * 2 * PTYPE_SIZE),
01355           DIM = ONE_DIM * EvalStages,     
01356         };
01357         static void setUp(const Weights &weights);
01358         template <Player Owner>
01359         static MultiInt evalOne(const NumEffectState &state);   
01360         static MultiInt eval(const NumEffectState &state);      
01361         static int index1(const NumEffectState &state, Piece piece)
01362         {
01363           const Ptype attack_ptype
01364             = state.findCheapAttack(alt(piece.owner()), piece.square()).ptype();
01365           const bool has_support = state.hasEffectAt(piece.owner(),
01366                                                      piece.square());
01367           return (piece.ptype() + 
01368                   (has_support ? 0 : PTYPE_SIZE)) * PTYPE_SIZE + attack_ptype;
01369         }
01370         static int index2(int i0, int i1) 
01371         {
01372           return i0 * PTYPE_SIZE * 2 * PTYPE_SIZE + i1;
01373         }         
01374         static CArray<MultiInt, ONE_DIM> table;
01375       };      
01376 
01377       class PtypeCount
01378       {
01379         friend class PtypeCountXY;
01380         friend class PtypeCountXYAttack;
01381       public:
01382         enum { ONE_DIM = 160, DIM = ONE_DIM * EvalStages };
01383         static void setUp(const Weights &weights);
01384         template<osl::Player P,osl::Ptype T>
01385         static MultiInt evalPlayerPtype(const CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
01386                                         const CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
01387                                         const osl::CArray<int,2> &kings_x,
01388                                         const osl::CArray<int,2> &kings_y);
01389         static void eval(const NumEffectState &state,
01390                          const CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
01391                          const CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
01392                          MultiInt &out);
01393         template<Player P>
01394         static void evalWithUpdateBang(
01395           const NumEffectState &state,
01396           Move last_move,
01397           CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
01398           CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
01399           MultiInt &last_value_and_out,unsigned int &ptypeo_mask);
01400       private:
01401         static int indexCount(Ptype ptype, int count)
01402         {
01403           return Ptype_Table.getIndexMin(unpromote(ptype)) +
01404             (isPromoted(ptype) ? 40 : 0) +
01405             count - 1;
01406         }
01407         static int indexBoardCount(Ptype ptype, int count)
01408         {
01409           return Ptype_Table.getIndexMin(unpromote(ptype)) +
01410             (isPromoted(ptype) ? 40 : 0) + 80 +
01411             count - 1;
01412         }
01413         static int indexCountX(Ptype ptype, int count, int x)
01414         {
01415           return x - 1 + 5 *
01416             (Ptype_Table.getIndexMin(unpromote(ptype)) +
01417              (isPromoted(ptype) ? 40 : 0) +
01418              count - 1);
01419         }
01420         static int indexCountY(Ptype ptype, int count, int y)
01421         {
01422           return y - 1 + 9 *
01423             (Ptype_Table.getIndexMin(unpromote(ptype)) +
01424              (isPromoted(ptype) ? 40 : 0) +
01425              count - 1) + 800;
01426         }
01427         static int indexBoardCountX(Ptype ptype, int count, int x)
01428         {
01429           return x - 1 + 5 *
01430             (Ptype_Table.getIndexMin(unpromote(ptype)) +
01431              (isPromoted(ptype) ? 40 : 0) +
01432              count - 1) + 400;
01433         }
01434         static int indexBoardCountY(Ptype ptype, int count, int y)
01435         {
01436           return y - 1 + 9 *
01437             (Ptype_Table.getIndexMin(unpromote(ptype)) +
01438              (isPromoted(ptype) ? 40 : 0) +
01439              count - 1) + 720 + 800;
01440         }
01441         template<Ptype T>
01442         static int indexCount(int count)
01443         {
01444           return  PtypeTraits<T>::indexMin+ (isPromoted(T) ? 40 : 0)  +
01445             count - 1;
01446         }
01447         template<Ptype T>
01448         static int indexBoardCount(int count)
01449         {
01450           return PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0)+ 80 +
01451             count - 1;
01452         }
01453         template<Ptype T>
01454         static int indexCountX(int count, int x)
01455         {
01456           return x - 1 + 5 *
01457             (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01458              count - 1);
01459         }
01460         template<Ptype T>
01461         static int indexCountY(int count, int y)
01462         {
01463           return y - 1 + 9 *
01464             (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01465              count - 1) + 800;
01466         }
01467         template<Ptype T>
01468         static int indexBoardCountX(int count, int x)
01469         {
01470           return x - 1 + 5 *
01471             (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01472            count - 1) + 400;
01473         }
01474         template<Ptype T>
01475         static int indexBoardCountY(int count, int y)
01476         {
01477           return y - 1 + 9 *
01478             (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01479              count - 1) + 720 + 800;
01480         }
01481         static MultiInt valueAll(Ptype ptype, int count, int my_king_x, int my_king_y, int op_king_x, int op_king_y)
01482         {
01483           assert(count>0);
01484           return 
01485             xy_table_diff[indexCountX(ptype, count, my_king_x)]+
01486             xy_table_diff[indexCountY(ptype, count, my_king_y)]+
01487             xy_attack_table_diff[indexCountX(ptype,count, op_king_x)]+
01488             xy_attack_table_diff[indexCountY(ptype, count, op_king_y)];
01489         }
01490         static MultiInt valueBoardAll(Ptype ptype, int count, int my_king_x, int my_king_y, int op_king_x, int op_king_y)
01491         {
01492           assert(count>0);
01493           return 
01494             xy_table_diff[indexBoardCountX(ptype, count, my_king_x)]+
01495             xy_table_diff[indexBoardCountY(ptype, count, my_king_y)]+
01496             xy_attack_table_diff[indexBoardCountX(ptype,count, op_king_x)]+
01497             xy_attack_table_diff[indexBoardCountY(ptype, count, op_king_y)];
01498         }
01499         static CArray<MultiInt, 160> table;
01500         static CArray<MultiInt, 2240> xy_table;
01501         static CArray<MultiInt, 2240> xy_attack_table;
01502         static CArray<MultiInt, 2240> xy_table_diff;
01503         static CArray<MultiInt, 2240> xy_attack_table_diff;
01504       };
01505 
01506       class PtypeCountXY
01507       {
01508       public:
01509         enum { ONE_DIM = 2240, DIM = ONE_DIM * EvalStages };
01510         static void setUp(const Weights &weights);
01511       };
01512       class PtypeCountXYAttack
01513       {
01514       public:
01515         enum { ONE_DIM = 2240, DIM = ONE_DIM * EvalStages };
01516         static void setUp(const Weights &weights);
01517       };
01518 
01519       class LanceEffectPieceKingRelative
01520       {
01521       public:
01522         enum { ONE_DIM = 9792, DIM = ONE_DIM * EvalStages };
01523         static void setUp(const Weights &weights);
01524         static MultiInt eval(const NumEffectState &state);
01525       private:
01526         static int index(Player p, Square pos, Square king,
01527                          PtypeO ptypeO, bool attack)
01528         {
01529           const int y_diff = (p == BLACK ? king.y() - pos.y() : pos.y() - king.y());
01530           const int x_diff = std::abs(king.x() - pos.x());
01531           if (p == WHITE)
01532           {
01533             ptypeO = alt(ptypeO);
01534           }
01535           return y_diff + 8 + x_diff * 17 + (ptypeO - PTYPEO_MIN) * 17 * 9 +
01536             (attack ? 0 : 4896);
01537         }
01538         static CArray<MultiInt, 9792> table;
01539       };
01540 
01541       class PtypeYPawnY
01542       {
01543       public:
01544         enum { ONE_DIM = 1440, DIM = ONE_DIM * EvalStages };
01545         static MultiInt eval(const NumEffectState &state,
01546                              const CArray2d<int, 2, 9> &pawns);
01547         template<Player P>
01548         static void evalWithUpdateBang(const NumEffectState &state,
01549                                        Move moved,
01550                                        const CArray2d<int, 2, 9> &pawns,
01551                                        MultiInt& last_value);
01552         static void setUp(const Weights &weights);
01553       private:
01554         static int index(Player player, Ptype ptype, int y, int pawn_y)
01555         {
01556           if (player == WHITE)
01557           {
01558             y = 10 - y;
01559             pawn_y = (10 - pawn_y) % 10;
01560           }
01561           return pawn_y + 10 * (y - 1 + 9 * ptype);
01562         }
01563         static CArray<MultiInt, 1440> table;
01564       };
01565 
01566       class GoldAndSilverNearKing
01567       {
01568         friend class GoldAndSilverNearKingCombination;
01569       public:
01570         enum { ONE_DIM = 1215, DIM = ONE_DIM * EvalStages };
01571         static void setUp(const Weights &weights);
01572         static MultiInt eval(const NumEffectState &state,
01573                               const CArray2d<int, 2, 3> &gs_count);
01574       private:
01575         template <Player Defense>
01576         static int index(const Square king, int distance0, int count)
01577         {
01578           int king_x = (king.x() > 5 ? 10 - king.x() : king.x());
01579           int king_y = (Defense == WHITE ? 10 - king.y() : king.y());
01580           return king_x - 1 + 5 * (king_y - 1+ 9 * (distance0 + 3 * count));
01581         }
01582         template <Player P>
01583         static MultiInt evalOne(const NumEffectState &state,
01584                                  const CArray2d<int, 2, 3> &gs_count);
01585         template <Player Defense>
01586         static int indexCombination(const Square king, int count0,
01587                              int count1, int count2)
01588         {
01589           int king_x = (king.x() > 5 ? 10 - king.x() : king.x());
01590           int king_y = (Defense == WHITE ? 10 - king.y() : king.y());
01591           return king_x + 5 * (king_y + 9 * (std::min(5,count0) + 6 *
01592                                              (std::min(5,count1) + 6 * std::min(5,count2))));
01593         }
01594         static CArray<MultiInt, 1215> table;
01595         static CArray<MultiInt, 9720> combination_table;
01596       };
01597 
01598       class GoldAndSilverNearKingCombination
01599       {
01600       public:
01601         enum { ONE_DIM = 9720, DIM = ONE_DIM * EvalStages };
01602         static void setUp(const Weights &weights);
01603       private:
01604       };
01605 
01606       class PtypeCombination
01607       {
01608       public:
01609         enum { ONE_DIM = 8192, DIM = ONE_DIM * EvalStages };
01610         static void setUp(const Weights &weights);
01611         static MultiInt eval(unsigned int ptypeo_mask);
01612       private:
01613         template <Player P>
01614         static MultiInt evalOne(unsigned int ptypeo_mask)
01615         {
01616           int index = 0;
01617           if (P==BLACK) index=((ptypeo_mask>>19)&0x1fc0)|((ptypeo_mask>>18)&0x3f);
01618           else index=((ptypeo_mask>>3)&0x1fc0)|((ptypeo_mask>>2)&0x3f);
01619           if (P == BLACK)
01620             return table[index];
01621           else
01622             return -table[index];
01623         }
01624         static CArray<MultiInt, 8192> table;
01625       };
01626       class SilverFork
01627       {
01628         static std::pair<int,int> matchRook(const NumEffectState& state, Piece rook,
01629                                             const CArray<bool,2>& has_silver,
01630                                             Square& silver_drop);
01631         static std::pair<int,int> matchGold(const NumEffectState& state, Piece gold, 
01632                                             const CArray<bool,2>& has_silver,
01633                                             Square& silver_drop);
01634       public:
01635         enum { ONE_DIM = 5*2, DIM = ONE_DIM * EvalStages };
01636         static void setUp(const Weights &weights);
01637         static MultiIntPair eval(const NumEffectState& state,
01638                                  CArray<std::pair<Square,int>,2>& silver_drop);
01639         static CArray<MultiInt, ONE_DIM> table;
01640       };
01641       class BishopRookFork
01642       {
01643       public:
01644         enum { 
01645           DROP_DIM = PTYPE_SIZE*PTYPE_SIZE, 
01646           ONE_DIM = 2*DROP_DIM*2, DIM = ONE_DIM * EvalStages 
01647         };
01648         static const Square isBishopForkSquare(const NumEffectState& state, Player defense, const Square a, const Square b, bool maybe_empty=false);
01649         static const Square isRookForkSquare(const NumEffectState& state, Player defense, const Square a, const Square b);
01650         static int bishopIndex(Ptype a, Ptype b) { return a * PTYPE_SIZE + b; }
01651         static int rookIndex(Ptype a, Ptype b) { return bishopIndex(a,b) + DROP_DIM; }
01652         static void setUp(const Weights &weights);
01653         template <Player Defense>
01654         static MultiIntPair evalOne(const NumEffectState& state, const PieceVector& target,
01655                                     std::pair<Square,int>& bishop_drop,
01656                                     std::pair<Square,int>& rook_drop);
01657         static MultiIntPair eval(const NumEffectState& state,
01658                                  CArray<std::pair<Square,int>,2>& bishop_drop,
01659                                  CArray<std::pair<Square,int>,2>& rook_drop);
01660         static CArray<MultiInt, ONE_DIM> table;
01661       private:
01662         static const Square findDropInLine
01663         (const NumEffectState& state, Player defense, 
01664          const Square a, const Square b, Piece king);
01665         static bool testCenter(const NumEffectState& state, Player defense, 
01666                                const Square a, const Square b, Piece king,
01667                                Square center, bool maybe_empty=false);
01668       };
01669 
01670       class KnightFork
01671       {
01672       public:
01673         enum { 
01674           DROP_DIM = PTYPE_SIZE*PTYPE_SIZE, ONE_DIM = DROP_DIM*2*2, 
01675           DIM = ONE_DIM * EvalStages
01676         };
01677         static void setUp(const Weights &weights);
01678         template <Player Defense>
01679         static MultiIntPair evalOne(const NumEffectState& state,
01680                                     bool has_knight,
01681                                     BoardMask& knight_fork_squares, 
01682                                     std::pair<Square,int>& knight_drop);
01683         static MultiIntPair eval(const NumEffectState& state, 
01684                                  CArray<BoardMask,2>& knight_fork_squares,
01685                                  CArray<std::pair<Square,int>,2>& knight_drop);
01686         template <Player P>
01687         static MultiIntPair evalWithUpdate(const NumEffectState& state, 
01688                                            Move moved,
01689                                            CArray<BoardMask,2>& knight_fork_squares,
01690                                            CArray<std::pair<Square,int>,2>& knight_drop);
01691         static CArray<MultiInt, ONE_DIM> table;
01692 
01693         static bool isForkSquare(const NumEffectState& state, Player defense, 
01694                                    int y, int x0, int x1);
01695         static int index(Ptype a, Ptype b)
01696         {
01697           return a * PTYPE_SIZE + b;
01698         }
01699         static bool isTarget(Ptype ptype) 
01700         {
01701           ptype = unpromote(ptype);
01702           return ptype != PAWN && ptype != LANCE && ptype != KNIGHT;
01703         }
01704       private:
01705         template <Player P, Player Defense>
01706         static void updateSquares
01707         (const NumEffectState& state, Move moved,
01708          BoardMask& knight_fork_squares);
01709         template <osl::Player Defense>
01710         static MultiIntPair accumulate
01711         (const NumEffectState& state,
01712          bool has_knight, const BoardMask& knight_fork_squares,
01713          std::pair<Square,int>& knight_drop);
01714       };
01715 
01716       class SilverAdvance26
01717       {
01718       public:
01719         enum { ONE_DIM = 1, DIM = ONE_DIM*EvalStages };
01720         static void setUp(const Weights &weights);
01721         static MultiInt eval(const NumEffectState &state);
01722       private:
01723         static CArray<MultiInt, ONE_DIM> table;
01724       };
01725 
01726       class Promotion37
01727       {
01728       public:
01729         enum { ONE_DIM = PTYPE_SIZE, DIM = ONE_DIM*EvalStages };
01730         static void setUp(const Weights &weights);
01731         static MultiInt eval(const NumEffectState &state);
01732         template<Player P>
01733         static MultiInt evalOne(const NumEffectState &state, int rank);
01734         template<Player P>
01735         static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
01736                                        MultiInt const& last_value);
01737 
01738         static CArray<MultiInt, ONE_DIM> table;
01739       };
01740     }
01741   }
01742 }
01743 
01744 #endif // EVAL_ML_MINORPIECE_H
01745 // ;;; Local Variables:
01746 // ;;; mode:c++
01747 // ;;; c-basic-offset:2
01748 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines