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