00001
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()))
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
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
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
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
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
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
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
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
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
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
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
01746
01747
01748