00001
00002
00003 #ifndef OSL_CATEGORY_PAWN_H
00004 #define OSL_CATEGORY_PAWN_H
00005
00006 #include "osl/category/categoryTraits.h"
00007 #include "osl/category/categoryEnv.h"
00008 #include "osl/container/moveStack.h"
00009 #include "osl/container/moveVector.h"
00010 namespace osl
00011 {
00012 namespace category
00013 {
00014 struct ForwardPawnWithRookSupport : public FixedProbabilityCategory
00015 {
00016 static FixedValueTable probTable;
00017 static const char *getName() { return "ForwardPawnWithRookSupport"; }
00018 static bool isInCategory(const CategoryEnv& env, Move move)
00019 {
00020 if (! (move.ptype() == PAWN))
00021 return false;
00022 if (move.isDrop())
00023 return false;
00024 const Player player = move.player();
00025 const Offset front = Board_Table.getOffset(player, U);
00026 for (int i = PtypeTraits<ROOK>::indexMin;
00027 i < PtypeTraits<ROOK>::indexLimit; i++)
00028 {
00029 const Piece rook = env.state->getPieceOf(i);
00030 if (! rook.isOnBoardByOwner(player))
00031 continue;
00032 const Offset32 diff(move.to(), rook.position());
00033 if (front == Board_Table.getShortOffset(diff))
00034 return true;
00035 }
00036 return false;
00037 }
00038 };
00039 struct DanglingPawn : public FixedProbabilityCategory
00040 {
00041 static FixedValueTable probTable;
00042 static const char *getName() { return "DanglingPawn"; }
00043 static bool isInCategory(const CategoryEnv& env, Move move)
00044 {
00045 if (! (move.ptype() == PAWN))
00046 return false;
00047 const Player player = move.player();
00048 const Position head
00049 = Board_Table.nextPosition(player, move.to() ,U);
00050 if (! head.canPromote(player))
00051 return false;
00052 if (move.isDrop())
00053 return env.state->getPieceOnBoard(head).isEmpty()
00054 && ((! env.state->hasEffectBy(alt(player), head))
00055 || env.state->hasEffectBy(player, head));
00056 return true;
00057 }
00058 };
00064 struct JoiningPawns : public FixedProbabilityCategory
00065 {
00066 static FixedValueTable probTable;
00067 static const char *getName() { return "JoiningPawns"; }
00068 static bool isInCategory(const CategoryEnv& env, Move move)
00069 {
00070 const Move lastMove=env.history->lastMove();
00071 return move.isDrop()
00072 && (move.ptype() == PAWN)
00073 && lastMove.isNormal()
00074 && (lastMove.capturePtype() == PAWN)
00075 && (Board_Table.nextPosition(move.player(), move.to() ,U)
00076 == lastMove.to());
00077 }
00078 static void generate(const CategoryEnv& env, MoveVector& moves)
00079 {
00080 const Move last_move=env.history->lastMove();
00081 if (! last_move.isNormal())
00082 return;
00083 if (last_move.capturePtype() != PAWN)
00084 return;
00085 const Player P = env.state->getTurn();
00086 if (! env.state->hasPieceOnStand(P, PAWN))
00087 return;
00088 const Position to
00089 = Board_Table.nextPosition(alt(P), last_move.to(), U);
00090 if (env.state->getPieceAt(to) != Piece::EMPTY())
00091 return;
00092 moves.push_back(Move(to, PAWN, P));
00093 }
00094 };
00095
00100 struct PawnBeforePawn : public FixedProbabilityCategory
00101 {
00102 static FixedValueTable probTable;
00103 static const char *getName() { return "PawnBeforePawn"; }
00104 static bool isInCategory(const CategoryEnv& env, Move move)
00105 {
00106 if (env.limit < 1000)
00107 return false;
00108
00109 return move.ptype() == PAWN
00110 && env.state->getPieceAt(Board_Table.nextPosition(move.player(), move.to(), U)).ptype()
00111 == PAWN;
00112 }
00113 static void generate(const CategoryEnv& env, MoveVector& moves)
00114 {
00115 if (env.limit < 1000)
00116 return;
00117
00118 for (int i = PtypeTraits<PAWN>::indexMin;
00119 i < PtypeTraits<PAWN>::indexLimit;
00120 i++)
00121 {
00122 const Player player = env.state->getTurn();
00123 const Piece p = env.state->getPieceOf(i);
00124 const bool hasPawn = env.state->hasPieceOnStand(player, PAWN);
00125 if (p.isOnBoard() && p.ptype() == PAWN
00126 && p.owner() == alt(player))
00127 {
00128 const Position middle = Board_Table.nextPosition(player, p.position(), D);
00129 const Position origin = (Board_Table.nextPosition(player, middle, D));
00130 if (!env.state->getPieceAt(middle).isEmpty())
00131 continue;
00132
00133 const Piece candidate = env.state->getPieceAt(origin);
00134 if (candidate.ptype() == PAWN
00135 && !middle.canPromote(player))
00136 {
00137 moves.push_back(Move(origin, middle, PAWN, PTYPE_EMPTY,
00138 false, player));
00139 }
00140 else if (hasPawn && !env.state->isPawnMaskSet(player, middle.x()))
00141 {
00142 moves.push_back(Move(middle, PAWN, player));
00143 }
00144 }
00145 }
00146 }
00147 };
00148
00154 struct SideAttackDrop : public FixedProbabilityCategory
00155 {
00156 static FixedValueTable probTable;
00157 static const char *getName() { return "SideAttackDrop"; }
00158 static bool isInCategory(const CategoryEnv& env, Move move)
00159 {
00160 if (move.ptype() != PAWN)
00161 return false;
00162 if (! move.isDrop())
00163 return false;
00164
00165 if (move.player() == BLACK)
00166 {
00167 const Position king = env.state->getKingPosition<WHITE>();
00168 if ((king.x() >= 8) && (king.y() <= 3))
00169 {
00170 return (move.to().x() == 9)
00171 && (move.to().y() <= 4);
00172 }
00173 if ((king.x() <= 2) && (king.y() <= 3))
00174 {
00175 return (move.to().x() == 1)
00176 && (move.to().y() <= 4);
00177 }
00178 return false;
00179 }
00180 else
00181 {
00182 assert(move.player() == WHITE);
00183 const Position king = env.state->getKingPosition<BLACK>();
00184 if ((king.x() >= 8) && (king.y() >= 7))
00185 {
00186 return (move.to().x() == 9)
00187 && (move.to().y() >= 6);
00188 }
00189 if ((king.x() <= 2) && (king.y() >= 7))
00190 {
00191 return (move.to().x() == 1)
00192 && (move.to().y() >= 6);
00193 }
00194 return false;
00195 }
00196 }
00197 };
00198
00204 struct SideAttack : public FixedProbabilityCategory
00205 {
00206 static FixedValueTable probTable;
00207 static const char *getName() { return "SideAttack"; }
00208 static bool isInCategory(const CategoryEnv& env, Move move)
00209 {
00210 if (move.ptype() != PAWN)
00211 return false;
00212 if (move.player() == BLACK)
00213 {
00214 const Position king = env.state->getKingPosition<WHITE>();
00215 if ((king.x() >= 8) && (king.y() <= 3))
00216 {
00217 if (move.from() == Position(9,5))
00218 {
00219 return env.state->getPieceOnBoard(Position(9,3)).ptype()
00220 == PAWN;
00221 }
00222 if (move.from() == Position(9,6))
00223 {
00224 return env.state->getPieceOnBoard(Position(9,4)).ptype()
00225 == PAWN;
00226 }
00227 return false;
00228 }
00229 if ((king.x() <= 2) && (king.y() <= 3))
00230 {
00231 if (move.from() == Position(1,5))
00232 {
00233 return env.state->getPieceOnBoard(Position(1,3)).ptype()
00234 == PAWN;
00235 }
00236 if (move.from() == Position(1,6))
00237 {
00238 return env.state->getPieceOnBoard(Position(1,4)).ptype()
00239 == PAWN;
00240 }
00241 return false;
00242 }
00243 return false;
00244 }
00245 else
00246 {
00247 assert(move.player() == WHITE);
00248 const Position king = env.state->getKingPosition<BLACK>();
00249 if ((king.x() >= 8) && (king.y() >= 7))
00250 {
00251 if (move.from() == Position(9,5))
00252 {
00253 return env.state->getPieceOnBoard(Position(9,7)).ptype()
00254 == PAWN;
00255 }
00256 if (move.from() == Position(9,4))
00257 {
00258 return env.state->getPieceOnBoard(Position(9,6)).ptype()
00259 == PAWN;
00260 }
00261 return false;
00262 }
00263 if ((king.x() <= 2) && (king.y() >= 7))
00264 {
00265 if (move.from() == Position(1,5))
00266 {
00267 return env.state->getPieceOnBoard(Position(1,7)).ptype()
00268 == PAWN;
00269 }
00270 if (move.from() == Position(1,4))
00271 {
00272 return env.state->getPieceOnBoard(Position(1,6)).ptype()
00273 == PAWN;
00274 }
00275 return false;
00276 }
00277 return false;
00278 }
00279 }
00280 };
00281
00285 struct DropAfterOpposingPawn : public FixedProbabilityCategory
00286 {
00287 static FixedValueTable probTable;
00288 static const char *getName() { return "DropAfterOpposingPawn"; }
00289 static bool isInCategory(const CategoryEnv& env, Move move)
00290 {
00291 const Move last_move=env.history->lastMove();
00292 if (! last_move.isNormal())
00293 return false;
00294 const Player P = move.player();
00295 return move.isDrop()
00296 && (move.ptype() == PAWN)
00297 && (Board_Table.nextPosition(P,move.to(),U).canPromote(P)
00298 || (move.to() == last_move.from()))
00299 && (last_move.capturePtype() == PAWN)
00300 && (Board_Table.nextPosition(alt(P),last_move.from(),U)
00301 == last_move.to());
00302 }
00303 static void generate(const CategoryEnv& env, MoveVector& out)
00304 {
00305 const Move last_move=env.history->lastMove();
00306 if (! (last_move.isNormal()
00307 && (last_move.capturePtype() == PAWN)))
00308 return;
00309 const Player P = env.state->getTurn();
00310 if (! env.state->hasPieceOnStand(P, PAWN))
00311 return;
00312 Position to = last_move.from();
00313 if (! (Board_Table.nextPosition(alt(P),last_move.from(),U)
00314 == last_move.to()))
00315 return;
00316 Position next = Board_Table.nextPosition(P, to, U);
00317 while (next.isOnBoard() && next.canPromote(P)
00318 && (env.state->getPieceOnBoard(to) == Piece::EMPTY()))
00319 {
00320
00321 out.push_back(Move(to, PAWN, P));
00322 to = next;
00323 next = Board_Table.nextPosition(P, to, U);
00324 }
00325 }
00326 };
00327
00333 struct ImmediateAntiPawnPromotion : public FixedProbabilityCategory
00334 {
00335 static FixedValueTable probTable;
00336 static const char *getName() { return "AntiPawnPromotion!"; }
00337 static bool isInCategory(const CategoryEnv& env, Move move)
00338 {
00339 const Move last_move=env.history->lastMove();
00340 if (! last_move.isNormal())
00341 return false;
00342 const Player P = move.player();
00343 if (move.isDrop()
00344 && (move.ptype() == PAWN)
00345 && (last_move.ptype() == PAWN))
00346 {
00347 const Position focus = Board_Table.nextPosition(P,move.to(),U);
00348 return focus.canPromote(alt(P))
00349 && (Board_Table.nextPosition(P,focus,U)
00350 == last_move.to());
00351 }
00352 return false;
00353 }
00354 static void generate(const CategoryEnv& env, MoveVector& out)
00355 {
00356 const Move last_move=env.history->lastMove();
00357 if (! last_move.isNormal())
00358 return;
00359 const Player P = env.state->getTurn();
00360 if (last_move.ptype() == PAWN)
00361 {
00362 const Position focus =
00363 Board_Table.nextPosition(alt(P),last_move.to(),U);
00364 if (focus.canPromote(alt(P)))
00365 {
00366 const Position target =
00367 Board_Table.nextPosition(alt(P),focus,U);
00368 if ((env.state->getPieceAt(target) == Piece::EMPTY())
00369 && env.state->hasPieceOnStand(P, PAWN)
00370 && (! env.state->isPawnMaskSet(P, target.x())))
00371 {
00372 out.push_back(Move(target, PAWN, P));
00373 }
00374 }
00375 }
00376 }
00377 };
00381 struct GambitPawn : public FixedProbabilityCategory
00382 {
00383 static FixedValueTable probTable;
00384 static const char *getName() { return "GambitPawn"; }
00385 static bool isInCategory(const CategoryEnv& env, Move move)
00386 {
00387 if (move.ptype() != PAWN)
00388 return false;
00389 const Player player = move.player();
00390 const Position to = move.to();
00391 if (env.state->hasEffectByPtype<SILVER>(player, to)
00392 && env.state->hasEffectByPtype<PAWN>(alt(player), to))
00393 return true;
00394 int pawns = env.state->countPiecesOnStand(player, PAWN);
00395 if (move.isDrop())
00396 --pawns;
00397 if (pawns == 0)
00398 return false;
00399 const Position head
00400 = Board_Table.nextPosition(player, to ,U);
00401 if (! env.state->getPieceAt(head).isOnBoardByOwner(alt(player)))
00402 return false;
00403 if (head.canPromote(player) && env.state->hasEffectBy(player, head))
00404 return true;
00405 const Position head2
00406 = Board_Table.nextPosition(player, head ,U);
00407 if (! env.state->getPieceAt(head2).isOnBoardByOwner(alt(player)))
00408 return false;
00409
00410 return ! env.state->hasEffectBy(alt(player), head)
00411 || env.state->hasEffectBy(player, head);
00412 }
00413 };
00417 struct AnchorPawn : public FixedProbabilityCategory
00418 {
00419 static FixedValueTable probTable;
00420 static const char *getName() { return "AnchorPawn"; }
00421 static bool isInCategory(const CategoryEnv& env, Move move)
00422 {
00423 if (move.ptype() != PAWN)
00424 return false;
00425 if (! move.isDrop())
00426 return false;
00427 const Player player = move.player();
00428 const Position to = move.to();
00429 if (! env.state->hasEffectByPtype<GOLD>(player, to))
00430 return false;
00431 if ((player == BLACK && to.y() != 9)
00432 || (player == WHITE && to.y() != 1))
00433 return false;
00434 if (env.state->hasEffectByPtype<ROOK>(alt(player), to))
00435 return true;
00436 const Position head
00437 = Board_Table.nextPosition(player, to ,U);
00438 return env.state->getPieceOnBoard(head).isOnBoardByOwner(player)
00439 && env.state->hasEffectByPtype<ROOK>(alt(player), head);
00440 }
00441 };
00442
00443 struct MoveSaGWithPawn : FixedProbabilityCategory
00444 {
00445 static FixedValueTable probTable;
00446 static const char*getName() { return "MoveSaGWithPawn"; }
00447 static bool isInCategory(const CategoryEnv& env, Move move)
00448 {
00449 if (move.ptype() != PAWN || !move.isDrop())
00450 return false;
00451 const Player player = move.player();
00452 const Player opponent = alt(player);
00453 const Position to = move.to();
00454 const Position target =
00455 Board_Table.nextPosition(player, to ,U);
00456 const Piece piece = env.state->getPieceAt(target);
00457
00458 if (!piece.isEmpty() && piece.owner() == opponent)
00459 {
00460 const Position left =
00461 Board_Table.nextPosition(opponent, target ,L);
00462 const Position right =
00463 Board_Table.nextPosition(opponent, target ,R);
00464 const Position down =
00465 Board_Table.nextPosition(opponent, target ,D);
00466 if (piece.ptype() == GOLD &&
00467 ((left.isOnBoard() && env.state->hasEffectBy(player, left))
00468 || (right.isOnBoard() && env.state->hasEffectBy(player, right))
00469 || (down.isOnBoard() && env.state->hasEffectBy(player, down))))
00470 return true;
00471
00472 const Position down_left =
00473 Board_Table.nextPosition(player, target ,DL);
00474 const Position down_right =
00475 Board_Table.nextPosition(player, target ,DR);
00476 const Position up_left =
00477 Board_Table.nextPosition(player, target ,UL);
00478 const Position up_right =
00479 Board_Table.nextPosition(player, target ,UR);
00480
00481 if (piece.ptype() == SILVER &&
00482 ((down_left.isOnBoard() && env.state->hasEffectBy(player, down_left))
00483 || (down_right.isOnBoard() && env.state->hasEffectBy(player, down_right))
00484 || (up_left.isOnBoard() && env.state->hasEffectBy(player, up_left))
00485 || (up_right.isOnBoard() && env.state->hasEffectBy(player, up_right))))
00486 return true;
00487 }
00488 return false;
00489 }
00490 };
00491
00492 struct PawnStopBishopEffect : public FixedProbabilityCategory
00493 {
00494 static FixedValueTable probTable;
00495 static const char *getName() { return "PawnStopBishopEffect"; }
00496 static bool isInCategory(const CategoryEnv& env, Move move)
00497 {
00498 if (! (move.ptype() == PAWN))
00499 return false;
00500
00501 const Player player = move.player();
00502 const Position target = move.to();
00503 if (!env.state->hasEffectByPtype<BISHOP>(alt(player), target))
00504 return false;
00505
00506 if ((move.isDrop() && env.state->hasEffectBy(player, target))
00507 || env.state->countEffect(player, target) >
00508 env.state->countEffect(alt(player), target))
00509 return true;
00510
00511 return false;
00512 }
00513 };
00514
00515 struct PawnOnLance : public FixedProbabilityCategory
00516 {
00517 static FixedValueTable probTable;
00518 static const char *getName() { return "PawnOnLance"; }
00519 static bool isInCategory(const CategoryEnv& env, Move move)
00520 {
00521 if (move.ptype() != PAWN || ! move.isDrop())
00522 return false;
00523
00524 const Player player = move.player();
00525 const Position target = Board_Table.nextPosition(player, move.to(), U);
00526 if (!target.isOnBoard())
00527 return false;
00528 const Piece piece = env.state->getPieceAt(target);
00529
00530 if (!piece.isEmpty() && piece.owner() == alt(player)
00531 && piece.ptype() == LANCE)
00532 return true;
00533
00534 return false;
00535 }
00536 };
00537
00538 struct PawnOnSilver : public FixedProbabilityCategory
00539 {
00540 static FixedValueTable probTable;
00541 static const char *getName() { return "PawnOnSilver"; }
00542 static bool isInCategory(const CategoryEnv& env, Move move)
00543 {
00544 if (move.ptype() != PAWN)
00545 return false;
00546
00547 const Player player = move.player();
00548 const Position target = Board_Table.nextPosition(player, move.to(), U);
00549 if (!target.isOnBoard())
00550 return false;
00551 const Piece piece = env.state->getPieceAt(target);
00552
00553 if (!piece.isEmpty() && piece.owner() == alt(player)
00554 && piece.ptype() == SILVER)
00555 return true;
00556
00557 return false;
00558 }
00559 };
00560
00561 struct PawnAttackBase : public FixedProbabilityCategory
00562 {
00563 static FixedValueTable probTable;
00564 static const char *getName() { return "PawnAttackBase";}
00565 static bool isInCategory(const CategoryEnv& env, Move move)
00566 {
00567 if (move.ptype() != PAWN || !move.isDrop())
00568 return false;
00569
00570 const Player player = move.player();
00571 const Position king = env.state->getKingPosition(alt(player));
00572
00573 if (move.to().x() < king.x() - 1 || move.to().x() > king.x() + 1)
00574 return false;
00575
00576 if ((player == BLACK && (move.to().y() != 4 || king.y() > 2)) ||
00577 (player == WHITE && (move.to().y() != 6 || king.y() < 8)))
00578 return false;
00579
00580
00581 const Piece target = env.state->getPieceAt(Board_Table.nextPosition(player, move.to(), U));
00582 if (!target.isEmpty())
00583 return false;
00584 return !env.state->hasEffectBy(alt(player), move.to()) ||
00585 env.state->hasEffectBy(player, move.to());
00586 }
00587 };
00588 }
00589 }
00590
00591 #endif
00592
00593
00594
00595