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.position().y() : 10 - king.position().y());
00061 return std::abs(x - king.position().x()) * 9 + king_y - 1;
00062 }
00063 static int index(const Position 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.position().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<Position, 2> king_bw = {{ state.getKingPosition<BLACK>(), state.getKingPosition<WHITE>() }};
00121 const CArray<Position, 2> kings = {{ king_bw[playerToIndex(P)], king_bw[playerToIndex(alt(P))] }};
00122 const CArray<Piece, 2> king_piece = {{ state.getKingPiece(P),
00123 state.getKingPiece(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.isPromote())
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.isPromote()))
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, Position 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.position());
00511 }
00512 static bool cantAdvance(const NumEffectState &state,
00513 const PtypeO ptypeO, const Position position)
00514 {
00515 assert(getPtype(ptypeO) == PAWN);
00516 return state.getPieceAt(Board_Table.nextPosition(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 class 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(Position 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<Position, 2> &kings)
00559 {
00560 MultiInt result;
00561 if (!canRetreat<P>(state,silver))
00562 {
00563 result += retreat_table[indexRetreat<P>(silver.position())];
00564 }
00565 const Position up =
00566 silver.position() + DirectionPlayerTraits<U, P>::offset();
00567 if (up.isOnBoard())
00568 {
00569 const Piece up_piece = state.getPieceAt(up);
00570 if (up_piece.isEmpty() &&
00571 (state.hasEffectByPtype<PAWN>(PlayerTraits<P>::opponent, up) ||
00572 !state.isPawnMaskSet<PlayerTraits<P>::opponent>(silver.position().x())))
00573 {
00574 const int x_diff =
00575 std::abs(kings[P].x() - silver.position().x());
00576 const int y_diff = (P == BLACK ?
00577 silver.position().y() - kings[P].y() :
00578 kings[P].y() - silver.position().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(Position pos)
00609 {
00610 return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
00611 }
00612 static int indexSideX(Position pos)
00613 {
00614 return (pos.x() > 5 ? 9 - pos.x() : pos.x() - 1);
00615 }
00616 template <Player P>
00617 static int indexSideY(Position 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 Position r = gold.position() + DirectionPlayerTraits<R, P>::offset();
00629 Position l = gold.position() + DirectionPlayerTraits<L, P>::offset();
00630
00631 if ((!r.isOnBoard() ||
00632 state.getPieceAt(r).isOnBoardByOwner(gold.owner()) ||
00633 state.hasEffectBy(alt(gold.owner()), r)) &&
00634 (!l.isOnBoard() ||
00635 state.getPieceAt(l).isOnBoardByOwner(gold.owner()) ||
00636 state.hasEffectBy(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<Position, 2> &kings)
00646 {
00647 MultiInt result;
00648 if (!canRetreat<P>(state, gold))
00649 {
00650 result += retreat_table[indexRetreat<P>(gold.position())];
00651 }
00652 if (!canMoveToSide<P>(state, gold))
00653 {
00654 result += side_table[indexSideX(gold.position())] +
00655 side_table[indexSideY<P>(gold.position())];
00656 }
00657 const Position uur =
00658 Board_Table.nextPosition(gold.owner(), gold.position(), UUR);
00659 const Position uul =
00660 Board_Table.nextPosition(gold.owner(), gold.position(), UUL);
00661 if ((uul.isOnBoard() && state.getPieceAt(uul).isEmpty() &&
00662 !state.hasEffectBy(gold.owner(), uul)) ||
00663 (uur.isOnBoard() && state.getPieceAt(uur).isEmpty() &&
00664 !state.hasEffectBy(gold.owner(), uur)))
00665 {
00666 assert(state.getKingPosition(gold.owner()) == kings[gold.owner()]);
00667 const Position king = kings[gold.owner()];
00668 const int x_diff = std::abs(king.x() - gold.position().x());
00669 const int y_diff = (gold.owner() == BLACK ?
00670 gold.position().y() - king.y() :
00671 king.y() - gold.position().y());
00672 result += knight_table[x_diff + 9 * (y_diff + 8)];
00673 }
00674 return result;
00675 }
00676 static CArray<MultiInt, 153> knight_table;
00677 static CArray<MultiInt, 9> retreat_table;
00678 static CArray<MultiInt, 14> side_table;
00679 };
00680
00681 class GoldKnightKingRelative : public GoldFeatures
00682 {
00683 public:
00684 enum { ONE_DIM = 153, DIM = ONE_DIM * EvalStages };
00685 static void setUp(const Weights &weights);
00686 };
00687
00688 class GoldRetreat : public GoldFeatures
00689 {
00690 public:
00691 enum { DIM = 9 };
00692 static void setUp(const Weights &weights,int stage);
00693 };
00694
00695 class GoldSideMove : public GoldFeatures
00696 {
00697 public:
00698 enum { ONE_DIM = 14, DIM = ONE_DIM * EvalStages };
00699 static void setUp(const Weights &weights);
00700 };
00701
00702 class KnightAdvance
00703 {
00704 public:
00705 enum { DIM = 9 };
00706 private:
00707 static CArray<MultiInt, 9> table;
00708 static int index(Player P, Position pos)
00709 {
00710 return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
00711 }
00712 template<Player P>
00713 static bool cantAdvance(const NumEffectState &state,
00714 const Piece knight);
00715 public:
00716 static void setUp(const Weights &weights,int stage);
00717 static MultiInt eval(const NumEffectState &state);
00718 };
00719
00720 class AllGold
00721 {
00722 public:
00723 enum { DIM = 1 };
00724 static void setUp(const Weights &weights,int stage);
00725 static MultiInt eval(int black_major_count)
00726 {
00727 if (black_major_count == 4)
00728 return weight;
00729 else if (black_major_count == 0)
00730 return -weight;
00731
00732 return MultiInt();
00733 }
00734 private:
00735 static MultiInt weight;
00736 };
00737
00738 class PtypeY
00739 {
00740 public:
00741 enum { DIM = PTYPE_SIZE * 9 };
00742 static void setUp(const Weights &weights,int stage);
00743 static MultiInt eval(const NumEffectState &state);
00744 template<Player P>
00745 static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
00746 MultiInt const& last_value);
00747 private:
00748 static CArray<MultiInt, 144> table;
00749 static int index(const Piece piece)
00750 {
00751 return index(piece.owner(), piece.ptype(), piece.position());
00752 }
00753 static int index(const Player player, const Ptype ptype, const Position pos)
00754 {
00755 const int y = (player == BLACK ? pos.y() : 10 - pos.y()) - 1;
00756 return ptype * 9 + y;
00757 }
00758 };
00759
00760 class PtypeX
00761 {
00762 public:
00763 enum { DIM = PTYPE_SIZE * 5 };
00764 static void setUp(const Weights &weights,int stage);
00765 static MultiInt eval(const NumEffectState &state);
00766 template<Player P>
00767 static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
00768 MultiInt const& last_value);
00769 private:
00770 static CArray<MultiInt, 80> table;
00771 static int index(const Piece piece)
00772 {
00773 return index(piece.owner(), piece.ptype(), piece.position());
00774 }
00775 static int index(const Player, const Ptype ptype, const Position pos)
00776 {
00777 const int x = (pos.x() > 5 ? 10 - pos.x() : pos.x()) - 1;
00778 return ptype * 5 + x;
00779 }
00780 };
00781
00782 class KnightCheck
00783 {
00784 friend class KnightCheckY;
00785 public:
00786 enum { DIM = 1 };
00787 static void setUp(const Weights &weights,int stage);
00788 static MultiInt eval(const NumEffectState &state);
00789 template <Player Defense>
00790 static bool canCheck(const NumEffectState &state)
00791 {
00792 const Position king = state.getKingPosition<Defense>();
00793 const Player offense = PlayerTraits<Defense>::opponent;
00794 const Position ul =
00795 king + DirectionPlayerTraits<UUL, Defense>::offset();
00796 const Position ur =
00797 king + DirectionPlayerTraits<UUR, Defense>::offset();
00798 if (ul.isOnBoard())
00799 {
00800 const Piece p = state.getPieceAt(ul);
00801 if (!state.hasEffectBy<Defense>(ul) &&
00802 ((p.isEmpty() && state.hasPieceOnStand<KNIGHT>(offense)) ||
00803 (!p.isOnBoardByOwner<offense>() &&
00804 state.hasEffectByPtypeStrict<KNIGHT>(offense, ul))))
00805 return true;
00806 }
00807 if (ur.isOnBoard())
00808 {
00809 const Piece p = state.getPieceAt(ur);
00810 if (!state.hasEffectBy<Defense>(ur) &&
00811 ((p.isEmpty() && state.hasPieceOnStand<KNIGHT>(offense)) ||
00812 (!p.isOnBoardByOwner<offense>() &&
00813 state.hasEffectByPtypeStrict<KNIGHT>(offense, ur))))
00814 return true;
00815 }
00816 return false;
00817 }
00818 static MultiInt value(int index_y) { return weight + y_table[index_y]; }
00819 private:
00820 static MultiInt weight;
00821 template <Player King>
00822 static int indexY(int y)
00823 {
00824 return (King == BLACK ? y - 1 : 9 - y) ;
00825 }
00826 static CArray<MultiInt, 9> y_table;
00827 };
00828
00829 class KnightCheckY
00830 {
00831 public:
00832 enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages };
00833 static void setUp(const Weights &weights);
00834 };
00835
00836 class KnightHead
00837 {
00838 friend class KnightHeadOppPiecePawnOnStand;
00839 public:
00840 enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages};
00841 static void setUp(const Weights &weights);
00842 static MultiInt eval(const NumEffectState &state);
00843 private:
00844 static CArray<MultiInt, 9> table;
00845 static CArray<MultiInt, 144> opp_table;
00846 };
00847
00848 class KnightHeadOppPiecePawnOnStand
00849 {
00850 public:
00851 enum { ONE_DIM = 9 * 16, DIM = ONE_DIM * EvalStages};
00852 static void setUp(const Weights &weights);
00853 private:
00854 };
00855
00856 class PawnPtypeOPtypeO
00857 {
00858 friend class PawnPtypeOPtypeOY;
00859 public:
00860 enum { ONE_DIM = 1024, DIM = ONE_DIM * EvalStages };
00861 static void setUp(const Weights &weights);
00862 static MultiInt eval(const NumEffectState &state);
00863 template<Player P>
00864 static MultiInt evalWithUpdate(const NumEffectState &state,
00865 Move moved,
00866 const CArray2d<int, 2, 9> &pawns,
00867 const MultiInt &last_value);
00868 private:
00869 static int index(Player P, PtypeO up, PtypeO up_up)
00870 {
00871 if (P == WHITE)
00872 {
00873 up = altIfPiece(up);
00874 up_up = altIfPiece(up_up);
00875 }
00876 return (up - PTYPEO_MIN) * 32 + (up_up - PTYPEO_MIN);
00877 }
00878 static int indexY(Player P, PtypeO up, PtypeO up_up, int y)
00879 {
00880 const int y_index = (P == BLACK ? y - 1 : 9 - y);
00881 return index(P, up, up_up) + 1024 * y_index;
00882 }
00883 static CArray<MultiInt, 1024> table;
00884 static CArray<MultiInt, 9216> y_table;
00885 };
00886
00887 class PromotedMinorPieces
00888 {
00889 friend class PromotedMinorPiecesY;
00890 public:
00891 enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages };
00892 static void setUp(const Weights &weights);
00893 static MultiInt eval(const NumEffectState &state);
00894 static MultiInt evalWithUpdate(
00895 const NumEffectState &state,
00896 Move moved,
00897 const MultiInt &last_values);
00898 template <int Sign>
00899 static void adjust(int index, int index_attack, int index_defense,
00900 MultiInt &result);
00901 private:
00902 template <Player P>
00903 static void evalOne(const NumEffectState &state,
00904 const PieceMask promoted,
00905 MultiInt &result);
00906 template <bool attack, Player owner>
00907 static int indexY(const Position king, int x_diff)
00908 {
00909 const int y = (owner == BLACK ? king.y() : 10 - king.y());
00910 return x_diff + (y - 1) * 9 + (attack ? 0 : 81);
00911 }
00912 static CArray<MultiInt, 9> table;
00913 static CArray<MultiInt, 162> y_table;
00914 };
00915 class NonPawnAttacked
00916 {
00917 friend class NonPawnAttackedKingRelative;
00918 public:
00919 enum { ONE_DIM = 64, DIM = ONE_DIM * EvalStages };
00920 static void setUp(const Weights &weights);
00921 static void eval(const NumEffectState &state, MultiIntPair& out);
00922 template<Player P>
00923 static void evalWithUpdateBang(
00924 const NumEffectState &state,
00925 Move moved,
00926 const CArray<PieceMask, 2> &effected_mask,
00927 MultiIntPair &last_value_and_out);
00928 template <int Sign>
00929 static void adjust(int black_turn_king_attack,
00930 int black_turn_king_defense,
00931 int white_turn_king_attack,
00932 int white_turn_king_defense,
00933 MultiIntPair &result);
00934 private:
00935 static int index(bool same_turn, bool has_support, Ptype ptype)
00936 {
00937 return ptype + (same_turn ? 0 : PTYPE_SIZE) +
00938 (has_support ? 0 : PTYPE_SIZE * 2);
00939 }
00940 template <bool Attack>
00941 static int indexK(Position king, bool same_turn, bool has_support,
00942 Position position, Player owner, Ptype ptype)
00943 {
00944 const int x_diff = std::abs(position.x() - king.x());
00945 const int y_diff = (owner == BLACK ?
00946 position.y() - king.y() :
00947 king.y() - position.y());
00948 return ((ptype + (same_turn ? 0 : PTYPE_SIZE) +
00949 (has_support ? 0 : PTYPE_SIZE * 2)) * 9 + x_diff) * 17 +
00950 y_diff + 8 + (Attack ? 0 : 9792);
00951 }
00952 template <bool Attack>
00953 static int indexK(Position king, bool same_turn, bool has_support,
00954 Piece piece)
00955 {
00956 return indexK<Attack>(king, same_turn, has_support,
00957 piece.position(), piece.owner(),
00958 piece.ptype());
00959 }
00960
00961 template <Player Attacked>
00962 static void updateEffectChanged(
00963 const NumEffectState &state,
00964 const CArray<PieceMask, 2> &effected_mask,
00965 const CArray<PieceMask, 2> &new_mask,
00966 int moved_piece_number,
00967 MultiIntPair &result)
00968 {
00969 CArray<Position, 2> kings = {{ state.getKingPosition<BLACK>(),
00970 state.getKingPosition<WHITE>() }};
00971
00972 PieceMask black_old = (~effected_mask[PlayerTraits<Attacked>::opponent]) & new_mask[PlayerTraits<Attacked>::opponent] & state.getOnBoardMask(Attacked);
00973 black_old.reset(moved_piece_number);
00974 while (black_old.any())
00975 {
00976 const Piece piece = state.getPieceOf(black_old.takeOneBit());
00977 const bool has_support =
00978 new_mask[Attacked].test(piece.number());
00979 const int index_king_black_turn_attack =
00980 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == BLACK, has_support, piece);
00981 const int index_king_white_turn_attack =
00982 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == WHITE, has_support, piece);
00983 const int index_king_black_turn_defense =
00984 indexK<false>(kings[Attacked], Attacked == BLACK, has_support, piece);
00985 const int index_king_white_turn_defense =
00986 indexK<false>(kings[Attacked], Attacked == WHITE, has_support, piece);
00987 adjust<Attacked == BLACK ? 1 : -1>(
00988 index_king_black_turn_attack, index_king_black_turn_defense,
00989 index_king_white_turn_attack, index_king_white_turn_defense,
00990 result);
00991 }
00992
00993
00994 PieceMask black_new = effected_mask[PlayerTraits<Attacked>::opponent] & (~new_mask[PlayerTraits<Attacked>::opponent]) & state.getOnBoardMask(Attacked);
00995 black_new.reset(moved_piece_number);
00996 while (black_new.any())
00997 {
00998 const Piece piece = state.getPieceOf(black_new.takeOneBit());
00999 const bool has_support =
01000 effected_mask[PlayerTraits<Attacked>::index].test(piece.number());
01001 const int index_king_black_turn_attack =
01002 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == BLACK, has_support, piece);
01003 const int index_king_white_turn_attack =
01004 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == WHITE, has_support, piece);
01005 const int index_king_black_turn_defense =
01006 indexK<false>(kings[Attacked], Attacked == BLACK, has_support, piece);
01007 const int index_king_white_turn_defense =
01008 indexK<false>(kings[Attacked], Attacked == WHITE, has_support, piece);
01009 adjust<Attacked == BLACK ? -1 : 1>(
01010 index_king_black_turn_attack, index_king_black_turn_defense,
01011 index_king_white_turn_attack, index_king_white_turn_defense,
01012 result);
01013 }
01014
01015 PieceMask black_self_old = effected_mask[PlayerTraits<Attacked>::opponent] & new_mask[PlayerTraits<Attacked>::opponent] &
01016 effected_mask[Attacked] & (~new_mask[Attacked]) & state.getOnBoardMask(Attacked);
01017 black_self_old.reset(moved_piece_number);
01018 while (black_self_old.any())
01019 {
01020 const Piece piece = state.getPieceOf(black_self_old.takeOneBit());
01021 const int index_king_black_turn_attack =
01022 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == BLACK, false, piece);
01023 const int index_king_white_turn_attack =
01024 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == WHITE, false, piece);
01025 const int index_king_black_turn_defense =
01026 indexK<false>(kings[Attacked], Attacked == BLACK, false, piece);
01027 const int index_king_white_turn_defense =
01028 indexK<false>(kings[Attacked], Attacked == WHITE, false, piece);
01029 const int index_king_black_turn_attack_old =
01030 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == BLACK, true, piece);
01031 const int index_king_white_turn_attack_old =
01032 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == WHITE, true, piece);
01033 const int index_king_black_turn_defense_old =
01034 indexK<false>(kings[Attacked], Attacked == BLACK, true, piece);
01035 const int index_king_white_turn_defense_old =
01036 indexK<false>(kings[Attacked], Attacked == WHITE, true, piece);
01037 adjust<Attacked == BLACK ? -1 : 1>(
01038 index_king_black_turn_attack_old, index_king_black_turn_defense_old,
01039 index_king_white_turn_attack_old, index_king_white_turn_defense_old,
01040 result);
01041 adjust<Attacked == BLACK ? 1 : -1>(
01042 index_king_black_turn_attack, index_king_black_turn_defense,
01043 index_king_white_turn_attack, index_king_white_turn_defense,
01044 result);
01045 }
01046
01047 PieceMask black_self_new = effected_mask[PlayerTraits<Attacked>::opponent] & new_mask[PlayerTraits<Attacked>::opponent] &
01048 (~effected_mask[Attacked]) & new_mask[Attacked] & state.getOnBoardMask(Attacked);
01049 black_self_new.reset(moved_piece_number);
01050 while (black_self_new.any())
01051 {
01052 const Piece piece = state.getPieceOf(black_self_new.takeOneBit());
01053 const int index_king_black_turn_attack =
01054 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == BLACK, true, piece);
01055 const int index_king_white_turn_attack =
01056 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == WHITE, true, piece);
01057 const int index_king_black_turn_defense =
01058 indexK<false>(kings[Attacked], Attacked == BLACK, true, piece);
01059 const int index_king_white_turn_defense =
01060 indexK<false>(kings[Attacked], Attacked == WHITE, true, piece);
01061 const int index_king_black_turn_attack_old =
01062 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == BLACK, false, piece);
01063 const int index_king_white_turn_attack_old =
01064 indexK<true>(kings[PlayerTraits<Attacked>::opponent], Attacked == WHITE, false, piece);
01065 const int index_king_black_turn_defense_old =
01066 indexK<false>(kings[Attacked], Attacked == BLACK, false, piece);
01067 const int index_king_white_turn_defense_old =
01068 indexK<false>(kings[Attacked], Attacked == WHITE, false, piece);
01069
01070 adjust<Attacked == BLACK ? -1 : 1>(
01071 index_king_black_turn_attack_old, index_king_black_turn_defense_old,
01072 index_king_white_turn_attack_old, index_king_white_turn_defense_old,
01073 result);
01074 adjust<Attacked == BLACK ? 1 : -1>(
01075 index_king_black_turn_attack, index_king_black_turn_defense,
01076 index_king_white_turn_attack, index_king_white_turn_defense,
01077 result);
01078 }
01079 }
01080 static CArray<MultiInt, 64> table;
01081 static CArray<MultiInt, 19584> king_table;
01082 };
01083
01084 class NonPawnAttackedKingRelative
01085 {
01086 public:
01087 enum { ONE_DIM = 19584, DIM = ONE_DIM * EvalStages};
01088 static void setUp(const Weights &weights);
01089 };
01090
01091 class PromotedMinorPiecesY
01092 {
01093 public:
01094 enum { ONE_DIM = 162, DIM = ONE_DIM * EvalStages };
01095 static void setUp(const Weights &weights);
01096 };
01097
01098 class PawnPtypeOPtypeOY
01099 {
01100 public:
01101 enum { ONE_DIM = 9216, DIM = ONE_DIM * EvalStages };
01102 static void setUp(const Weights &weights);
01103 };
01104
01105 class NonPawnAttackedPtype
01106 {
01107 public:
01108 enum { ONE_DIM = 1024, DIM = ONE_DIM * EvalStages};
01109 static void setUp(const Weights &weights);
01110 static void eval(const NumEffectState &state,
01111 CArray<PieceMask, 40> &attacked_mask,
01112 MultiIntPair& out);
01113 template<Player P>
01114 static void evalWithUpdateBang(
01115 const NumEffectState &state,
01116 Move moved,
01117 const CArray<PieceMask, 2> &effected_mask,
01118 CArray<PieceMask, 40> &attacked_mask,
01119 MultiIntPair &last_value_and_out);
01120 private:
01121 static int index(bool same_turn, bool has_support, Ptype ptype,
01122 Ptype attack_ptype)
01123 {
01124 return (ptype + (same_turn ? 0 : PTYPE_SIZE) +
01125 (has_support ? 0 : PTYPE_SIZE * 2)) * 16 + attack_ptype;
01126 }
01127 template <int Sign>
01128 static void adjust(int black, int white, MultiIntPair &result)
01129 {
01130 if(Sign>0){
01131 result[BLACK] += table[black];
01132 result[WHITE] += table[white];
01133 }
01134 else{
01135 result[BLACK] -= table[black];
01136 result[WHITE] -= table[white];
01137 }
01138 }
01139 template <bool Plus>
01140 static void evalOnePiece(const Player player,
01141 const Ptype ptype,
01142 const Ptype attack_ptype,
01143 bool with_support,
01144 MultiIntPair &result)
01145 {
01146 const int index_black_turn = index(BLACK == player, with_support,
01147 ptype, attack_ptype);
01148 const int index_white_turn = index(WHITE == player, with_support,
01149 ptype, attack_ptype);
01150 if (Plus)
01151 adjust<1>(index_black_turn, index_white_turn, result);
01152 else
01153 adjust<-1>(index_black_turn, index_white_turn, result);
01154 }
01155 template <Player P>
01156 static void updateChanged(const NumEffectState &state,
01157 const Piece p,
01158 Move moved,
01159 int captured_number,
01160 const CArray<PieceMask, 2> &effected_mask,
01161 const CArray<PieceMask, 2> &new_mask,
01162 CArray<PieceMask, 40> &attacked_mask,
01163 MultiIntPair &result)
01164 {
01165
01166 PieceMask old = (~effected_mask[PlayerTraits<P>::opponent]) & new_mask[PlayerTraits<P>::opponent] & state.getOnBoardMask(P);
01167 old.reset(p.number());
01168 while (old.any())
01169 {
01170 const Piece piece = state.getPieceOf(old.takeOneBit());
01171 const bool has_support =
01172 new_mask[PlayerTraits<P>::index].test(piece.number());
01173 PieceMask attacking =
01174 state.getEffect(piece.position()) &
01175 state.getOnBoardMask(PlayerTraits<P>::opponent);
01176 attacked_mask[piece.number()] = attacking;
01177 while (attacking.any())
01178 {
01179 const Piece attack = state.getPieceOf(attacking.takeOneBit());
01180 evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
01181 has_support, result);
01182 }
01183 }
01184
01185 PieceMask new_without = effected_mask[PlayerTraits<P>::opponent] & (~new_mask[PlayerTraits<P>::opponent]) & state.getOnBoardMask(P);
01186 new_without.reset(p.number());
01187 while (new_without.any())
01188 {
01189 const Piece piece = state.getPieceOf(new_without.takeOneBit());
01190 const bool has_support =
01191 effected_mask[PlayerTraits<P>::index].test(piece.number());
01192 PieceMask attacking = attacked_mask[piece.number()];
01193 if (moved.isPromote() && attacking.test(p.number()))
01194 {
01195 evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
01196 has_support, result);
01197 attacking.reset(p.number());
01198 }
01199 if (captured_number != -1 && attacking.test(captured_number))
01200 {
01201 evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
01202 has_support, result);
01203 attacking.reset(captured_number);
01204 }
01205 while (attacking.any())
01206 {
01207 const Piece attack = state.getPieceOf(attacking.takeOneBit());
01208 evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
01209 has_support, result);
01210 }
01211 }
01212
01213 PieceMask self_old = effected_mask[PlayerTraits<P>::opponent] &
01214 new_mask[PlayerTraits<P>::opponent] &
01215 effected_mask[P] & (~new_mask[P]) & state.getOnBoardMask(P);
01216 self_old.reset(p.number());
01217 while (self_old.any())
01218 {
01219 const Piece piece = state.getPieceOf(self_old.takeOneBit());
01220 PieceMask old_attacking = attacked_mask[piece.number()];
01221 if (moved.isPromote() && old_attacking.test(p.number()))
01222 {
01223 evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
01224 true, result);
01225 old_attacking.reset(p.number());
01226 }
01227 if (captured_number != -1 && old_attacking.test(captured_number))
01228 {
01229 evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
01230 true, result);
01231 old_attacking.reset(captured_number);
01232 }
01233 while (old_attacking.any())
01234 {
01235 const Piece attack = state.getPieceOf(old_attacking.takeOneBit());
01236 evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
01237 true, result);
01238 }
01239 PieceMask new_attacking = state.getEffect(piece.position())
01240 & state.getOnBoardMask(PlayerTraits<P>::opponent);
01241 attacked_mask[piece.number()] = new_attacking;
01242 while (new_attacking.any())
01243 {
01244 const Piece attack = state.getPieceOf(new_attacking.takeOneBit());
01245 evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
01246 false, result);
01247 }
01248 }
01249
01250 PieceMask self_new_with = effected_mask[PlayerTraits<P>::opponent] &
01251 new_mask[PlayerTraits<P>::opponent] &
01252 (~effected_mask[P]) & new_mask[P] & state.getOnBoardMask(P);
01253 self_new_with.reset(p.number());
01254 while (self_new_with.any())
01255 {
01256 const Piece piece = state.getPieceOf(self_new_with.takeOneBit());
01257 PieceMask old_attacking = attacked_mask[piece.number()];
01258 if (moved.isPromote() && old_attacking.test(p.number()))
01259 {
01260 evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
01261 false, result);
01262 old_attacking.reset(p.number());
01263 }
01264 if (captured_number != -1 && old_attacking.test(captured_number))
01265 {
01266 evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
01267 false, result);
01268 old_attacking.reset(captured_number);
01269 }
01270 while (old_attacking.any())
01271 {
01272 const Piece attack = state.getPieceOf(old_attacking.takeOneBit());
01273 evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
01274 false, result);
01275 }
01276 PieceMask new_attacking = state.getEffect(piece.position())
01277 & state.getOnBoardMask(PlayerTraits<P>::opponent);
01278 attacked_mask[piece.number()] = new_attacking;
01279 while (new_attacking.any())
01280 {
01281 const Piece attack = state.getPieceOf(new_attacking.takeOneBit());
01282 evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
01283 true, result);
01284 }
01285 }
01286
01287 PieceMask effected = effected_mask[P];
01288 effected ^= new_mask[P];
01289 effected = ~effected;
01290 PieceMask attack_changed = effected_mask[PlayerTraits<P>::opponent] &
01291 new_mask[PlayerTraits<P>::opponent] &
01292 effected & state.getOnBoardMask(P) &
01293 state.effectedChanged(PlayerTraits<P>::opponent);
01294 attack_changed.reset(p.number());
01295 while (attack_changed.any())
01296 {
01297 const Piece attacked = state.getPieceOf(attack_changed.takeOneBit());
01298 PieceMask attack_old_mask = attacked_mask[attacked.number()];
01299 PieceMask attack_new_mask = state.getEffect(attacked.position()) & state.getOnBoardMask(PlayerTraits<P>::opponent);
01300 if (captured_number != -1 &&
01301 attack_old_mask.test(captured_number))
01302 {
01303 evalOnePiece<P != BLACK>(P, attacked.ptype(),
01304 moved.capturePtype(),
01305 new_mask[P].test(attacked.number()),
01306 result);
01307 attack_old_mask.reset(captured_number);
01308 }
01309 if (moved.isPromote() &&
01310 attack_old_mask.test(p.number()))
01311 {
01312 evalOnePiece<P != BLACK>(P, attacked.ptype(),
01313 moved.oldPtype(),
01314 new_mask[P].test(attacked.number()),
01315 result);
01316 attack_old_mask.reset(p.number());
01317 }
01318 if (moved.isPromote() &&
01319 attack_new_mask.test(p.number()))
01320 {
01321 evalOnePiece<P == BLACK>(P, attacked.ptype(),
01322 moved.ptype(),
01323 new_mask[P].test(attacked.number()),
01324 result);
01325 attack_new_mask.reset(p.number());
01326 }
01327 PieceMask gone = attack_old_mask & (~attack_new_mask);
01328 while (gone.any())
01329 {
01330 const Piece attacking = state.getPieceOf(gone.takeOneBit());
01331 evalOnePiece<P != BLACK>(P, attacked.ptype(),
01332 attacking.ptype(),
01333 effected_mask[P].test(attacked.number()),
01334 result);
01335 }
01336 PieceMask added = (~attack_old_mask) & attack_new_mask;
01337 while (added.any())
01338 {
01339 const Piece attacking = state.getPieceOf(added.takeOneBit());
01340 evalOnePiece<P == BLACK>(P, attacked.ptype(),
01341 attacking.ptype(),
01342 new_mask[P].test(attacked.number()),
01343 result);
01344 }
01345
01346 attacked_mask[attacked.number()] = state.getEffect(attacked.position()) & state.getOnBoardMask(PlayerTraits<P>::opponent);
01347 }
01348 }
01349
01350 static CArray<MultiInt, 1024> table;
01351 };
01352
01353 class NonPawnAttackedPtypePair
01354 {
01355 public:
01356 enum {
01357 ONE_DIM = (PTYPE_SIZE * 2 * PTYPE_SIZE)*(PTYPE_SIZE * 2 * PTYPE_SIZE),
01358 DIM = ONE_DIM * EvalStages,
01359 };
01360 static void setUp(const Weights &weights);
01361 template <Player Owner>
01362 static MultiInt evalOne(const NumEffectState &state);
01363 static MultiInt eval(const NumEffectState &state);
01364 static int index1(const NumEffectState &state, Piece piece)
01365 {
01366 const Ptype attack_ptype
01367 = state.findCheapThreat(alt(piece.owner()), piece.position()).ptype();
01368 const bool has_support = state.hasEffectBy(piece.owner(),
01369 piece.position());
01370 return (piece.ptype() +
01371 (has_support ? 0 : PTYPE_SIZE)) * PTYPE_SIZE + attack_ptype;
01372 }
01373 static int index2(int i0, int i1)
01374 {
01375 return i0 * PTYPE_SIZE * 2 * PTYPE_SIZE + i1;
01376 }
01377 static CArray<MultiInt, ONE_DIM> table;
01378 };
01379
01380 class PtypeCount
01381 {
01382 friend class PtypeCountXY;
01383 friend class PtypeCountXYAttack;
01384 public:
01385 enum { ONE_DIM = 160, DIM = ONE_DIM * EvalStages };
01386 static void setUp(const Weights &weights);
01387 template<osl::Player P,osl::Ptype T>
01388 static MultiInt evalPlayerPtype(const CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
01389 const CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
01390 const osl::CArray<int,2> &kings_x,
01391 const osl::CArray<int,2> &kings_y);
01392 static void eval(const NumEffectState &state,
01393 const CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
01394 const CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
01395 MultiInt &out);
01396 template<Player P>
01397 static void evalWithUpdateBang(
01398 const NumEffectState &state,
01399 Move last_move,
01400 CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
01401 CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
01402 MultiInt &last_value_and_out,unsigned int &ptypeo_mask);
01403 private:
01404 static int indexCount(Ptype ptype, int count)
01405 {
01406 return Ptype_Table.getIndexMin(unpromote(ptype)) +
01407 (isPromoted(ptype) ? 40 : 0) +
01408 count - 1;
01409 }
01410 static int indexBoardCount(Ptype ptype, int count)
01411 {
01412 return Ptype_Table.getIndexMin(unpromote(ptype)) +
01413 (isPromoted(ptype) ? 40 : 0) + 80 +
01414 count - 1;
01415 }
01416 static int indexCountX(Ptype ptype, int count, int x)
01417 {
01418 return x - 1 + 5 *
01419 (Ptype_Table.getIndexMin(unpromote(ptype)) +
01420 (isPromoted(ptype) ? 40 : 0) +
01421 count - 1);
01422 }
01423 static int indexCountY(Ptype ptype, int count, int y)
01424 {
01425 return y - 1 + 9 *
01426 (Ptype_Table.getIndexMin(unpromote(ptype)) +
01427 (isPromoted(ptype) ? 40 : 0) +
01428 count - 1) + 800;
01429 }
01430 static int indexBoardCountX(Ptype ptype, int count, int x)
01431 {
01432 return x - 1 + 5 *
01433 (Ptype_Table.getIndexMin(unpromote(ptype)) +
01434 (isPromoted(ptype) ? 40 : 0) +
01435 count - 1) + 400;
01436 }
01437 static int indexBoardCountY(Ptype ptype, int count, int y)
01438 {
01439 return y - 1 + 9 *
01440 (Ptype_Table.getIndexMin(unpromote(ptype)) +
01441 (isPromoted(ptype) ? 40 : 0) +
01442 count - 1) + 720 + 800;
01443 }
01444 template<Ptype T>
01445 static int indexCount(int count)
01446 {
01447 return PtypeTraits<T>::indexMin+ (isPromoted(T) ? 40 : 0) +
01448 count - 1;
01449 }
01450 template<Ptype T>
01451 static int indexBoardCount(int count)
01452 {
01453 return PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0)+ 80 +
01454 count - 1;
01455 }
01456 template<Ptype T>
01457 static int indexCountX(int count, int x)
01458 {
01459 return x - 1 + 5 *
01460 (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01461 count - 1);
01462 }
01463 template<Ptype T>
01464 static int indexCountY(int count, int y)
01465 {
01466 return y - 1 + 9 *
01467 (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01468 count - 1) + 800;
01469 }
01470 template<Ptype T>
01471 static int indexBoardCountX(int count, int x)
01472 {
01473 return x - 1 + 5 *
01474 (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01475 count - 1) + 400;
01476 }
01477 template<Ptype T>
01478 static int indexBoardCountY(int count, int y)
01479 {
01480 return y - 1 + 9 *
01481 (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
01482 count - 1) + 720 + 800;
01483 }
01484 static MultiInt valueAll(Ptype ptype, int count, int my_king_x, int my_king_y, int op_king_x, int op_king_y)
01485 {
01486 assert(count>0);
01487 return
01488 xy_table_diff[indexCountX(ptype, count, my_king_x)]+
01489 xy_table_diff[indexCountY(ptype, count, my_king_y)]+
01490 xy_attack_table_diff[indexCountX(ptype,count, op_king_x)]+
01491 xy_attack_table_diff[indexCountY(ptype, count, op_king_y)];
01492 }
01493 static MultiInt valueBoardAll(Ptype ptype, int count, int my_king_x, int my_king_y, int op_king_x, int op_king_y)
01494 {
01495 assert(count>0);
01496 return
01497 xy_table_diff[indexBoardCountX(ptype, count, my_king_x)]+
01498 xy_table_diff[indexBoardCountY(ptype, count, my_king_y)]+
01499 xy_attack_table_diff[indexBoardCountX(ptype,count, op_king_x)]+
01500 xy_attack_table_diff[indexBoardCountY(ptype, count, op_king_y)];
01501 }
01502 static CArray<MultiInt, 160> table;
01503 static CArray<MultiInt, 2240> xy_table;
01504 static CArray<MultiInt, 2240> xy_attack_table;
01505 static CArray<MultiInt, 2240> xy_table_diff;
01506 static CArray<MultiInt, 2240> xy_attack_table_diff;
01507 };
01508
01509 class PtypeCountXY
01510 {
01511 public:
01512 enum { ONE_DIM = 2240, DIM = ONE_DIM * EvalStages };
01513 static void setUp(const Weights &weights);
01514 };
01515 class PtypeCountXYAttack
01516 {
01517 public:
01518 enum { ONE_DIM = 2240, DIM = ONE_DIM * EvalStages };
01519 static void setUp(const Weights &weights);
01520 };
01521
01522 class LanceEffectPieceKingRelative
01523 {
01524 public:
01525 enum { ONE_DIM = 9792, DIM = ONE_DIM * EvalStages };
01526 static void setUp(const Weights &weights);
01527 static MultiInt eval(const NumEffectState &state);
01528 private:
01529 static int index(Player p, Position pos, Position king,
01530 PtypeO ptypeO, bool attack)
01531 {
01532 const int y_diff = (p == BLACK ? king.y() - pos.y() : pos.y() - king.y());
01533 const int x_diff = std::abs(king.x() - pos.x());
01534 if (p == WHITE)
01535 {
01536 ptypeO = alt(ptypeO);
01537 }
01538 return y_diff + 8 + x_diff * 17 + (ptypeO - PTYPEO_MIN) * 17 * 9 +
01539 (attack ? 0 : 4896);
01540 }
01541 static CArray<MultiInt, 9792> table;
01542 };
01543
01544 class PtypeYPawnY
01545 {
01546 public:
01547 enum { ONE_DIM = 1440, DIM = ONE_DIM * EvalStages };
01548 static MultiInt eval(const NumEffectState &state,
01549 const CArray2d<int, 2, 9> &pawns);
01550 template<Player P>
01551 static void evalWithUpdateBang(const NumEffectState &state,
01552 Move moved,
01553 const CArray2d<int, 2, 9> &pawns,
01554 MultiInt& last_value);
01555 static void setUp(const Weights &weights);
01556 private:
01557 static int index(Player player, Ptype ptype, int y, int pawn_y)
01558 {
01559 if (player == WHITE)
01560 {
01561 y = 10 - y;
01562 pawn_y = (10 - pawn_y) % 10;
01563 }
01564 return pawn_y + 10 * (y - 1 + 9 * ptype);
01565 }
01566 static CArray<MultiInt, 1440> table;
01567 };
01568
01569 class GoldAndSilverNearKing
01570 {
01571 friend class GoldAndSilverNearKingCombination;
01572 public:
01573 enum { ONE_DIM = 1215, DIM = ONE_DIM * EvalStages };
01574 static void setUp(const Weights &weights);
01575 static MultiInt eval(const NumEffectState &state,
01576 const CArray2d<int, 2, 3> &gs_count);
01577 private:
01578 template <Player Defense>
01579 static int index(const Position king, int distance0, int count)
01580 {
01581 int king_x = (king.x() > 5 ? 10 - king.x() : king.x());
01582 int king_y = (Defense == WHITE ? 10 - king.y() : king.y());
01583 return king_x - 1 + 5 * (king_y - 1+ 9 * (distance0 + 3 * count));
01584 }
01585 template <Player P>
01586 static MultiInt evalOne(const NumEffectState &state,
01587 const CArray2d<int, 2, 3> &gs_count);
01588 template <Player Defense>
01589 static int indexCombination(const Position king, int count0,
01590 int count1, int count2)
01591 {
01592 int king_x = (king.x() > 5 ? 10 - king.x() : king.x());
01593 int king_y = (Defense == WHITE ? 10 - king.y() : king.y());
01594 return king_x + 5 * (king_y + 9 * (std::min(5,count0) + 6 *
01595 (std::min(5,count1) + 6 * std::min(5,count2))));
01596 }
01597 static CArray<MultiInt, 1215> table;
01598 static CArray<MultiInt, 9720> combination_table;
01599 };
01600
01601 class GoldAndSilverNearKingCombination
01602 {
01603 public:
01604 enum { ONE_DIM = 9720, DIM = ONE_DIM * EvalStages };
01605 static void setUp(const Weights &weights);
01606 private:
01607 };
01608
01609 class PtypeCombination
01610 {
01611 public:
01612 enum { ONE_DIM = 8192, DIM = ONE_DIM * EvalStages };
01613 static void setUp(const Weights &weights);
01614 static MultiInt eval(unsigned int ptypeo_mask);
01615 private:
01616 template <Player P>
01617 static MultiInt evalOne(unsigned int ptypeo_mask)
01618 {
01619 int index = 0;
01620 if (P==BLACK) index=((ptypeo_mask>>19)&0x1fc0)|((ptypeo_mask>>18)&0x3f);
01621 else index=((ptypeo_mask>>3)&0x1fc0)|((ptypeo_mask>>2)&0x3f);
01622 if (P == BLACK)
01623 return table[index];
01624 else
01625 return -table[index];
01626 }
01627 static CArray<MultiInt, 8192> table;
01628 };
01629 class SilverFork
01630 {
01631 static std::pair<int,int> matchRook(const NumEffectState& state, Piece rook,
01632 const CArray<bool,2>& has_silver,
01633 Position& silver_drop);
01634 static std::pair<int,int> matchGold(const NumEffectState& state, Piece gold,
01635 const CArray<bool,2>& has_silver,
01636 Position& silver_drop);
01637 public:
01638 enum { ONE_DIM = 5*2, DIM = ONE_DIM * EvalStages };
01639 static void setUp(const Weights &weights);
01640 static MultiIntPair eval(const NumEffectState& state,
01641 CArray<std::pair<Position,int>,2>& silver_drop);
01642 static CArray<MultiInt, ONE_DIM> table;
01643 };
01644 class BishopRookFork
01645 {
01646 public:
01647 enum {
01648 DROP_DIM = PTYPE_SIZE*PTYPE_SIZE,
01649 ONE_DIM = 2*DROP_DIM*2, DIM = ONE_DIM * EvalStages
01650 };
01651 static const Position isBishopForkPosition(const NumEffectState& state, Player defense, const Position a, const Position b);
01652 static const Position isRookForkPosition(const NumEffectState& state, Player defense, const Position a, const Position b);
01653 static int bishopIndex(Ptype a, Ptype b) { return a * PTYPE_SIZE + b; }
01654 static int rookIndex(Ptype a, Ptype b) { return bishopIndex(a,b) + DROP_DIM; }
01655 static void setUp(const Weights &weights);
01656 template <Player Defense>
01657 static MultiIntPair evalOne(const NumEffectState& state, const PieceVector& target,
01658 std::pair<Position,int>& bishop_drop,
01659 std::pair<Position,int>& rook_drop);
01660 static MultiIntPair eval(const NumEffectState& state,
01661 CArray<std::pair<Position,int>,2>& bishop_drop,
01662 CArray<std::pair<Position,int>,2>& rook_drop);
01663 static CArray<MultiInt, ONE_DIM> table;
01664 private:
01665 static const Position findDropInLine
01666 (const NumEffectState& state, Player defense,
01667 const Position a, const Position b, Piece king);
01668 static bool testCenter(const NumEffectState& state, Player defense,
01669 const Position a, const Position b, Piece king,
01670 Position center);
01671 };
01672
01673 class KnightFork
01674 {
01675 public:
01676 enum {
01677 DROP_DIM = PTYPE_SIZE*PTYPE_SIZE, ONE_DIM = DROP_DIM*2*2,
01678 DIM = ONE_DIM * EvalStages
01679 };
01680 static void setUp(const Weights &weights);
01681 template <Player Defense>
01682 static MultiIntPair evalOne(const NumEffectState& state,
01683 const CArray<PieceVector,10>& pieces, bool has_knight,
01684 std::pair<Position,int>& knight_drop);
01685 static MultiIntPair eval(const NumEffectState& state,
01686 CArray<std::pair<Position,int>,2>& knight_drop);
01687 static CArray<MultiInt, ONE_DIM> table;
01688
01689 static bool isForkPosition(const NumEffectState& state, Player defense,
01690 int y, int x0, int x1);
01691 static int index(Ptype a, Ptype b)
01692 {
01693 return a * PTYPE_SIZE + b;
01694 }
01695 };
01696
01697 }
01698 }
01699 }
01700
01701 #endif // EVAL_ML_MINORPIECE_H
01702
01703
01704
01705