00001
00002
00003 #ifndef QUIESCENCEGENERATOR_TCC
00004 #define QUIESCENCEGENERATOR_TCC
00005
00006 #include "osl/search/quiescenceGenerator.h"
00007 #include "osl/search/breakThreatmate.h"
00008 #include "osl/effect_util/unblockableEffect.h"
00009 #include "osl/effect_util/sendOffSquare.h"
00010 #include "osl/effect_util/additionalEffect.h"
00011 #include "osl/effect_util/shadowEffect.h"
00012 #include "osl/effect_util/neighboring8Direct.h"
00013 #include "osl/effect_util/effectUtil.h"
00014 #include "osl/effect_util/pin.h"
00015 #include "osl/move_generator/attackToPinned.h"
00016 #include "osl/move_generator/addEffectWithEffect.h"
00017 #include "osl/neighboring8.h"
00018
00019 template <osl::Player P>
00020 template <osl::Ptype PTYPE, bool has_dont_capture>
00021 void osl::search::QuiescenceGenerator<P>::
00022 capture(const NumEffectState& state, MoveVector& moves, Piece dont_capture)
00023 {
00024 mask_t pieces = state.effectedMask(P).template selectBit<PTYPE>()
00025 & state.piecesOnBoard(alt(P)).getMask(PtypeFuns<PTYPE>::indexNum);
00026
00027 if (has_dont_capture && dont_capture.isPiece() && (dont_capture.ptype() == PTYPE))
00028 {
00029 while (pieces.any()) {
00030 const Piece target = state.pieceOf(pieces.takeOneBit()+PtypeFuns<PTYPE>::indexNum*32);
00031 if (target != dont_capture)
00032 capture(state, target.square(), moves);
00033 }
00034 }
00035 else
00036 {
00037 while (pieces.any()) {
00038 const Piece target = state.pieceOf(pieces.takeOneBit()+PtypeFuns<PTYPE>::indexNum*32);
00039 capture(state, target.square(), moves);
00040 }
00041 }
00042 if (((PTYPE == KNIGHT) || (PTYPE == BISHOP))
00043 && state.hasPieceOnStand<LANCE>(P))
00044 {
00045
00046
00047
00048
00049 MoveVector::const_iterator original_end = moves.end();
00050 for (MoveVector::const_iterator p=moves.begin(); p!=original_end; ++p)
00051 {
00052 const Square from = p->from();
00053 if ((p->oldPtype() == PAWN)
00054 && (state.hasEffectAt<PlayerTraits<P>::opponent>(p->to())))
00055 {
00056 move_generator::AdditionalLance<P>::generate(state, from, moves);
00057 }
00058 }
00059 }
00060 }
00061
00062 template <osl::Player P> inline
00063 void osl::search::QuiescenceGenerator<P>::
00064 attackMajorPieceFirstSelection(const NumEffectState& state,
00065 PieceMask pins, const MoveVector& all_moves,
00066 MoveVector& moves,
00067 MoveVector& expensive_drops)
00068 {
00069 BOOST_FOREACH(Move m, all_moves)
00070 {
00071 const Square to = m.to();
00072 {
00073 const int defense = state.countEffect(alt(P),to, pins);
00074 int offense = state.countEffect(P,to) + (m.isDrop() ? 1 : 0);
00075 if (defense >= offense)
00076 offense += AdditionalEffect::count2(state, to, P);
00077 if (m.ptype() != PAWN)
00078 {
00079 if (defense > offense)
00080 continue;
00081 }
00082 else
00083 {
00084 if (defense && (offense==1))
00085 {
00086 if (! (state.hasEffectByPtype<ROOK>(alt(P),to)
00087 && state.hasEffectByPtype<BISHOP>(alt(P),to)))
00088 continue;
00089 }
00090 }
00091 const Ptype ptype = m.ptype();
00092 if ((defense >= offense)
00093 && (unpromote(ptype) != PAWN))
00094 continue;
00095 if (ptype != PAWN)
00096 {
00097 const Square front_position
00098 = to + DirectionPlayerTraits<U,P>::offset();
00099 const Piece front_piece = state.pieceAt(front_position);
00100 if (front_piece.ptypeO() == newPtypeO(alt(P),PAWN))
00101 continue;
00102 }
00103 if (m.isDrop() && (m.ptype() == PAWN)
00104 && to.canPromote<P>())
00105 {
00106
00107 const Square back_position
00108 = to + DirectionPlayerTraits<D,P>::offset();
00109 if (state.pieceOnBoard(back_position).isEmpty())
00110 moves.push_back(Move(back_position, PAWN, P));
00111 }
00112 const int ptype_value = eval::Ptype_Eval_Table.value(ptype);
00113 const bool is_large_piece
00114 = (ptype_value > eval::PtypeEvalTraits<BISHOP>::val);
00115 if ((m.isDrop()
00116 && (ptype_value > eval::PtypeEvalTraits<KNIGHT>::val))
00117 || (is_large_piece && defense))
00118 expensive_drops.push_back(m);
00119 else
00120 moves.push_back(m);
00121 }
00122 }
00123 }
00124
00125 template <osl::Player P> inline
00126 void osl::search::QuiescenceGenerator<P>::
00127 attackMajorPieceSecondSelection(bool target_has_support,
00128 const MoveVector& src,
00129 MoveVector& out)
00130 {
00131 BOOST_FOREACH(Move m, src)
00132 {
00133 const Ptype ptype = m.ptype();
00134 if (target_has_support
00135 && (eval::Ptype_Eval_Table.value(ptype)
00136 >= eval::PtypeEvalTraits<GOLD>::val))
00137 continue;
00138
00139 out.push_back(m);
00140 }
00141 }
00142
00143 template <osl::Player P>
00144 void osl::search::QuiescenceGenerator<P>::
00145 attackMajorPieceZerothSelection(const NumEffectState& state,
00146 const MoveVector& src,
00147 Square target,
00148 MoveVector& open_out,
00149 MoveVector& out)
00150 {
00151 BOOST_FOREACH(Move m, src)
00152 {
00153 assert(!ShouldPromoteCut::canIgnoreAndNotDrop<P>(m));
00154 const bool is_open
00155 = (! m.isDrop())
00156 && state.hasEffectAt<P>(m.from())
00157 && (state.hasEffectByPtype<LANCE>(P, m.from())
00158 || state.hasEffectByPtype<BISHOP>(P, m.from())
00159 || state.hasEffectByPtype<ROOK>(P, m.from()))
00160 && ! state.hasEffectIf(m.ptypeO(), m.to(), target);
00161
00162 const bool may_overlap = m.isCaptureOrPromotion();
00163 if (is_open)
00164 {
00165 if (! may_overlap
00166 || state.hasEffectAt<PlayerTraits<P>::opponent>(m.to()))
00167 open_out.push_back(m);
00168 }
00169 else
00170 {
00171 if (! may_overlap)
00172 out.push_back(m);
00173 }
00174 }
00175 }
00176
00177 template <osl::Player P>
00178 void osl::search::QuiescenceGenerator<P>::
00179 attackMajorPiece(const NumEffectState& state, PieceMask pins,
00180 MoveVector& moves)
00181 {
00182 using namespace move_action;
00183 MoveVector work;
00184 MoveVector unsupported, supported;
00185 assert(PtypeTraits<BISHOP>::indexLimit == PtypeTraits<ROOK>::indexMin);
00186 for (int i = PtypeTraits<BISHOP>::indexMin;
00187 i < PtypeTraits<ROOK>::indexLimit; i++)
00188 {
00189 const Piece p = state.pieceOf(i);
00190 if (p.isOnBoardByOwner<PlayerTraits<P>::opponent>())
00191 {
00192 const Square target = p.square();
00193 assert(isMajor(p.ptype()));
00194 const bool unstable_rook = (p.ptype() == ROOK)
00195 && (state.pieceAt(target + DirectionPlayerTraits<U, PlayerTraits<P>::opponent>::offset())
00196 != Piece::EMPTY());
00197 work.clear();
00198 if (state.hasEffectAt(alt(P), target) && (! unstable_rook))
00199 {
00200 move_generator::GenerateAddEffectWithEffect::generate<false>
00201 (P, state, target, work);
00202 attackMajorPieceZerothSelection(state, work, target, moves, supported);
00203 }
00204 else if (unstable_rook || (! state.hasEffectAt(P, target)))
00205 {
00206
00207 move_generator::GenerateAddEffectWithEffect::generate<false>
00208 (P, state, target, work);
00209 attackMajorPieceZerothSelection(state, work, target, moves, unsupported);
00210 }
00211 }
00212 }
00213
00214
00215 MoveVector drops_supported, drops_unsupported;
00216 attackMajorPieceFirstSelection(state, pins, unsupported, moves,
00217 drops_unsupported);
00218 attackMajorPieceFirstSelection(state, pins, supported, moves,
00219 drops_supported);
00220
00221 if (moves.size() > 5)
00222 return;
00223 attackMajorPieceSecondSelection(false, drops_unsupported, moves);
00224 if (moves.size() > 5)
00225 return;
00226 attackMajorPieceSecondSelection(true, drops_supported, moves);
00227 }
00228
00229 template <osl::Player P>
00230 void osl::search::QuiescenceGenerator<P>::
00231 escapeNormalPiece(const NumEffectState& state,
00232 Piece escape, MoveVector& moves, bool add_support_only)
00233 {
00234 assert(escape.ptype() != KING);
00235 using namespace move_action;
00236 MoveVector all_moves;
00237 const Piece attack_piece
00238 = state.findCheapAttack(alt(P), escape.square());
00239 const int attack_ptype_value
00240 = eval::Ptype_Eval_Table.value(unpromote(attack_piece.ptype()));
00241 const Square escape_from = escape.square();
00242 if (! add_support_only)
00243 {
00244 GenerateEscape<P>::generateCheap(state, escape, all_moves);
00245 BOOST_FOREACH(Move m, all_moves)
00246 {
00247 const Square to = m.to();
00248 if (m.isDrop())
00249 {
00250 if (! state.hasEffectAt<P>(to))
00251 continue;
00252 #ifdef QSEARCH_EXPENSIVE_BLOCK
00253 if (eval::Ptype_Eval_Table.value(m.ptype()) > attack_ptype_value)
00254 continue;
00255 #else
00256 if (m.ptype() != PAWN)
00257 continue;
00258 #endif
00259 moves.push_back(m);
00260 }
00261 else
00262 {
00263 if (m.from() != escape_from)
00264 {
00265
00266 if (! state.hasMultipleEffectAt(P, to))
00267 continue;
00268 if (eval::Ptype_Eval_Table.value(m.ptype()) > attack_ptype_value)
00269 continue;
00270 }
00271
00272
00273 assert(! ShouldPromoteCut::canIgnoreMove<P>(m));
00274 if (! m.isCaptureOrPromotion())
00275 {
00276 moves.push_back(m);
00277 }
00278 }
00279 }
00280 }
00281
00282 if (unpromote(attack_piece.ptype()) == PAWN)
00283 return;
00284 if ((eval::Ptype_Eval_Table.value(escape.ptype()) - attack_ptype_value)
00285 >= (eval::PtypeEvalTraits<BISHOP>::val - eval::PtypeEvalTraits<KNIGHT>::val))
00286 return;
00287 if (state.hasEffectAt<P>(escape_from)
00288 || (state.countEffect(alt(P), escape_from) != 1))
00289 return;
00290 all_moves.clear();
00291 move_generator::GenerateAddEffectWithEffect::generate<false>
00292 (P, state, escape_from, all_moves);
00293 const size_t escape_moves = moves.size();
00294 MoveVector not_drop;
00295 BOOST_FOREACH(Move m, all_moves)
00296 {
00297 const Square to = m.to();
00298 if (m.isDrop())
00299 {
00300 if (state.hasEffectAt<PlayerTraits<P>::opponent>(to)
00301 && (! state.hasEffectAt<P>(to)))
00302 continue;
00303
00304 if ((m.ptype() != PAWN) && (m.ptype() != LANCE))
00305 continue;
00306 moves.push_back(m);
00307 }
00308 else
00309 {
00310
00311 const int defense = state.countEffect(P,to);
00312 const int offense = state.countEffect(alt(P),to);
00313 if (offense >= defense)
00314 continue;
00315
00316
00317 assert(! ShouldPromoteCut::canIgnoreMove<P>(m));
00318 if (! m.isCaptureOrPromotion())
00319 {
00320 moves.push_back(m);
00321 }
00322 }
00323 }
00324
00325 if (state.hasEffectByPtype<BISHOP>(alt(P), escape_from)
00326 && state.hasPieceOnStand<BISHOP>(P))
00327 {
00328 const Piece bishop = state.findAttackAt<BISHOP>(alt(P), escape_from);
00329 assert(unpromote(bishop.ptype()) == BISHOP);
00330 {
00331 Square p = bishop.square();
00332 const Offset offset = Board_Table.getShortOffset(Offset32(p,escape_from));
00333 p += offset;
00334 while (state.pieceAt(p).isEmpty())
00335 {
00336 if (state.hasEffectAt<P>(p))
00337 {
00338 moves.push_back(Move(p, BISHOP, P));
00339 break;
00340 }
00341 p += offset;
00342 }
00343 }
00344 }
00345
00346 if (escape_moves == moves.size())
00347 moves.push_back(not_drop.begin(), not_drop.end());
00348 }
00349
00350 template <osl::Player P>
00351 void osl::search::QuiescenceGenerator<P>::
00352 escapeAll(const NumEffectState& state, MoveVector& moves)
00353 {
00354
00355 const PieceMask pieces = state.effectedMask(alt(P)) & state.piecesOnBoard(P);
00356 bool found_attacked_piece = false;
00357 mask_t m = pieces.selectBit<ROOK>();
00358 while (m.any())
00359 {
00360 const Piece p = state.pieceOf(m.takeOneBit()+PtypeFuns<ROOK>::indexNum*32);
00361 assert(p.isOnBoardByOwner<P>()
00362 && state.hasEffectAt<PlayerTraits<P>::opponent>(p.square()));
00363 found_attacked_piece = true;
00364 escapeNormalPiece(state, p, moves);
00365 }
00366 m = pieces.selectBit<BISHOP>();
00367 while (m.any())
00368 {
00369 const Piece p = state.pieceOf(m.takeOneBit()+PtypeFuns<BISHOP>::indexNum*32);
00370 assert(p.isOnBoardByOwner<P>()
00371 && state.hasEffectAt<PlayerTraits<P>::opponent>(p.square()));
00372 found_attacked_piece = true;
00373 escapeNormalPiece(state, p, moves);
00374 }
00375
00376 if (found_attacked_piece)
00377 goto finish;
00378 m = pieces.selectBit<GOLD>();
00379 while (m.any())
00380 {
00381 const Piece p = state.pieceOf(m.takeOneBit()+PtypeFuns<GOLD>::indexNum*32);
00382 assert(p.isOnBoardByOwner<P>()
00383 && state.hasEffectAt<PlayerTraits<P>::opponent>(p.square()));
00384 escapeNormalPiece(state, p, moves);
00385 goto finish;
00386 }
00387 m = pieces.selectBit<SILVER>();
00388 while (m.any())
00389 {
00390 const Piece p = state.pieceOf(m.takeOneBit()+PtypeFuns<SILVER>::indexNum*32);
00391 assert(p.isOnBoardByOwner<P>()
00392 && state.hasEffectAt<PlayerTraits<P>::opponent>(p.square()));
00393 escapeNormalPiece(state, p, moves);
00394 goto finish;
00395 }
00396 m = pieces.selectBit<KNIGHT>();
00397 while (m.any())
00398 {
00399
00400 const Piece p = state.pieceOf(m.takeOneBit()+PtypeFuns<KNIGHT>::indexNum*32);
00401 assert(p.isOnBoardByOwner<P>()
00402 && state.hasEffectAt<PlayerTraits<P>::opponent>(p.square()));
00403 escapeNormalPiece(state, p, moves, p.ptype()==PKNIGHT);
00404 goto finish;
00405 }
00406 m = pieces.selectBit<LANCE>();
00407 while (m.any())
00408 {
00409
00410 const Piece p = state.pieceOf(m.takeOneBit()+PtypeFuns<LANCE>::indexNum*32);
00411 assert(p.isOnBoardByOwner<P>()
00412 && state.hasEffectAt<PlayerTraits<P>::opponent>(p.square()));
00413 escapeNormalPiece(state, p, moves, true);
00414 goto finish;
00415 }
00416 m = pieces.selectBit<PAWN>();
00417 while (m.any())
00418 {
00419
00420 const Piece p = state.pieceOf(m.takeOneBit()+PtypeFuns<PAWN>::indexNum*32);
00421 assert(p.isOnBoardByOwner<P>()
00422 && state.hasEffectAt<PlayerTraits<P>::opponent>(p.square()));
00423 escapeNormalPiece(state, p, moves, true);
00424 goto finish;
00425 }
00426 finish:
00427 return;
00428 }
00429
00430 template <osl::Player P>
00431 template <class EvalT>
00432 void osl::search::QuiescenceGenerator<P>::
00433 escapeFromLastMoveOtherThanPawn(const NumEffectState& state, Move last_move,
00434 MoveVector& moves)
00435 {
00436 if (! last_move.isNormal())
00437 return;
00438 assert(last_move.ptype() != PAWN);
00439
00440 PieceVector targets;
00441 const Square from = last_move.to();
00442 EffectUtil::findThreat<EvalT>(state, from, last_move.ptypeO(), targets);
00443 if (targets.empty())
00444 return;
00445 assert(targets[0].ptype() != KING);
00446
00447 escapeNormalPiece(state, targets[0], moves,
00448 (last_move.ptype() != PAWN)
00449 && (eval::Ptype_Eval_Table.value(targets[0].ptype())
00450 <= eval::Ptype_Eval_Table.value(KNIGHT)));
00451 if (targets.size() > 1)
00452 escapeNormalPiece(state, targets[1], moves,
00453 (last_move.ptype() != PAWN)
00454 && (eval::Ptype_Eval_Table.value(targets[1].ptype())
00455 <= eval::Ptype_Eval_Table.value(KNIGHT)));
00456 }
00457
00458 template <osl::Player P>
00459 bool osl::search::QuiescenceGenerator<P>::
00460 escapeByMoveOnly(const NumEffectState& state, Piece piece, MoveVector& moves)
00461 {
00462 assert(piece.isOnBoardByOwner<P>());
00463
00464 MoveVector all_moves;
00465 GeneratePieceOnBoard::generate(state.turn(),state,piece,all_moves);
00466
00467 const Player Opponent = PlayerTraits<P>::opponent;
00468 const Square from = piece.square();
00469
00470 const bool consider_shadowing
00471 = state.hasEffectByPtype<LANCE>(Opponent, from)
00472 || state.hasEffectByPtype<ROOK>(Opponent, from)
00473 || state.hasEffectByPtype<BISHOP>(Opponent, from);
00474 const bool is_major = isMajor(piece.ptype());
00475 const bool chase_danger
00476 = (! state.hasEffectAt(P, from)
00477 && (state.hasMultipleEffectAt(alt(P), from)
00478 || AdditionalEffect::hasEffect(state, from, alt(P))));
00479 BOOST_FOREACH(Move m, all_moves)
00480 {
00481 assert(m.from() == piece.square());
00482 if (m.isCapture())
00483 continue;
00484 const Square to = m.to();
00485 const bool safe_position
00486 = (consider_shadowing
00487 ? (! state.hasEffectByWithRemove<Opponent>(to, from))
00488 : (! state.hasEffectAt<Opponent>(to)));
00489 if (safe_position)
00490 {
00491 if (! is_major || ! chase_danger)
00492 return true;
00493 if (! to.canPromote<Opponent>())
00494 return true;
00495 if ((to - from) != Board_Table.getShortOffset(Offset32(to, from)))
00496 return true;
00497 }
00498 moves.push_back(m);
00499 }
00500 return false;
00501 }
00502
00503 template <osl::Player P>
00504 void osl::search::QuiescenceGenerator<P>::
00505 check(const NumEffectState& state, PieceMask pins, MoveVector& moves,
00506 bool no_liberty)
00507 {
00508 Square8 sendoffs;
00509 const Square king_position = state.kingSquare(alt(P));
00510 effect_util::SendOffSquare::find<P>(state, king_position, sendoffs);
00511 check(state, pins, no_liberty, sendoffs, moves);
00512 }
00513
00514
00515 template <osl::Player P>
00516 void osl::search::QuiescenceGenerator<P>::
00517 check(const NumEffectState& state, PieceMask pins, bool no_liberty,
00518 const Square8& sendoffs, MoveVector& moves)
00519 {
00520 using namespace move_action;
00521 MoveVector all_moves;
00522 const Square king_position = state.kingSquare(alt(P));
00523 move_generator::GenerateAddEffectWithEffect::generate<true>
00524 (P, state, king_position, all_moves);
00525
00526 MoveVector merginal_moves;
00527 BOOST_FOREACH(Move m, all_moves)
00528 {
00529
00530 assert(! ShouldPromoteCut::canIgnoreAndNotDrop<P>(m));
00531 if (m.isPromotion())
00532 continue;
00533 const Square to = m.to();
00534 const Ptype captured = m.capturePtype();
00535
00536 if ((captured != PTYPE_EMPTY)
00537 && (eval::Ptype_Eval_Table.value(captured)
00538 >= eval::PtypeEvalTraits<KNIGHT>::val))
00539 continue;
00540 const bool is_open
00541 = (! m.isDrop())
00542 && state.hasEffectAt<P>(m.from())
00543 && (state.hasEffectByPtype<LANCE>(P, m.from())
00544 || state.hasEffectByPtype<BISHOP>(P, m.from())
00545 || state.hasEffectByPtype<ROOK>(P, m.from()))
00546 && ! state.hasEffectIf(m.ptypeO(), m.to(), king_position);
00547 if (! is_open)
00548 {
00549 if ((m.ptype() != PAWN) && (m.ptype() != KNIGHT))
00550 {
00551
00552 const Square front_position
00553 = to + DirectionPlayerTraits<U,P>::offset();
00554 const Piece front_piece = state.pieceAt(front_position);
00555 if (front_piece.ptypeO() == newPtypeO(alt(P),PAWN))
00556 continue;
00557 }
00558 if (! sendoffs.isMember(to))
00559 {
00560 const int defense = state.countEffect(alt(P),to, pins);
00561 int offense = state.countEffect(P,to) + no_liberty;
00562 const bool may_effective = offense && (! sendoffs.empty());
00563 if (m.isDrop())
00564 ++offense;
00565 if (defense >= offense)
00566 offense += AdditionalEffect::count2(state, to, P);
00567 if (defense >= offense)
00568 offense += ShadowEffect::count2(state, to, P);
00569 if (m.ptype() == KNIGHT)
00570 {
00571 const Square front_position
00572 = to + DirectionPlayerTraits<U,P>::offset();
00573 if (state.hasEffectAt<P>(front_position))
00574 offense+=1;
00575 }
00576 if (defense > offense)
00577 {
00578 const bool side_attack
00579 = (king_position.x() == 1 || king_position.x() == 9)
00580 && m.ptype() == PAWN;
00581 if (! side_attack)
00582 continue;
00583 }
00584 else if (defense == offense)
00585 {
00586 if ((unpromote(m.ptype()) == PAWN)
00587 || state.hasEffectByPtype<PAWN>(P, to)
00588 || state.hasEffectByPtype<LANCE>(P, to))
00589 moves.push_back(m);
00590 else if (may_effective)
00591 merginal_moves.push_back(m);
00592 continue;
00593 }
00594 }
00595 }
00596 if (m.isDrop() && (m.ptype() == PAWN)
00597 && to.canPromote<P>())
00598 {
00599
00600 const Square back_position
00601 = to + DirectionPlayerTraits<D,P>::offset();
00602 if (state.pieceOnBoard(back_position).isEmpty())
00603 moves.push_back(Move(back_position, PAWN, P));
00604 }
00605 moves.push_back(m);
00606 }
00607 if (moves.size() < 3)
00608 moves.push_back(merginal_moves.begin(), merginal_moves.end());
00609 }
00610
00611 template <osl::Player P>
00612 void osl::search::QuiescenceGenerator<P>::
00613 promote(const NumEffectState& state, PieceMask pins, MoveVector& moves)
00614 {
00615 using namespace move_action;
00616 MoveVector all_moves;
00617 move_generator::Promote<P>::generate(state, all_moves);
00618
00619 BOOST_FOREACH(Move m, all_moves)
00620 {
00621 const Square to = m.to();
00622 const int defense = state.countEffect(alt(P),to, pins);
00623 int offense = state.countEffect(P,to);
00624 if (defense >= offense)
00625 offense += AdditionalEffect::count2(state, to, P);
00626 if (m.ptype() == PPAWN
00627 && defense && offense + 1 >= defense)
00628 {
00629
00630 if (m.ptype() == PPAWN)
00631 {
00632
00633 for (int i = PtypeTraits<ROOK>::indexMin;
00634 i < PtypeTraits<ROOK>::indexLimit; ++i)
00635 {
00636 const Piece rook = state.pieceOf(i);
00637 if (! rook.isOnBoardByOwner<P>() || rook.ptype() == PROOK
00638 || rook.square().template canPromote<P>())
00639 continue;
00640 const Square mid(m.from().x(), rook.square().y());
00641 if (state.pieceOnBoard(mid).isEmpty()
00642 && state.isEmptyBetween(m.from(), mid)
00643 && state.isEmptyBetween(rook.square(), mid))
00644 {
00645 const Move m(rook.square(), mid, ROOK, PTYPE_EMPTY, false, P);
00646 moves.push_back(m);
00647 }
00648 }
00649 if (state.hasPieceOnStand<LANCE>(P))
00650 move_generator::AdditionalLance<P>::generate(state, m.from(), moves);
00651
00652 }
00653 }
00654 if (defense > offense)
00655 {
00656 continue;
00657 }
00658 if ((defense == offense)
00659 && (m.ptype() != PPAWN))
00660 continue;
00661
00662 moves.push_back(m);
00663 }
00664 }
00665
00666 template <osl::Player P>
00667 void osl::search::QuiescenceGenerator<P>::
00668 attackKing8(const NumEffectState& state, PieceMask pins, MoveVector& moves)
00669 {
00670 using namespace move_action;
00671 MoveVector all_moves;
00672
00673 MoveVector not8;
00674 MoveVector not_drop;
00675 MoveVector major_drop;
00676 move_generator::AddEffect8<P>::generate(state, all_moves);
00677
00678 const Square king_position = state.kingSquare(alt(P));
00679 const int king_x = king_position.x();
00680 BOOST_FOREACH(Move m, all_moves)
00681 {
00682
00683 assert(! ShouldPromoteCut::canIgnoreAndNotDrop<P>(m));
00684 assert(! m.isPromotion());
00685 const Square to = m.to();
00686 #ifndef NDEBUG
00687 const Ptype captured = m.capturePtype();
00688 assert(captured==PTYPE_EMPTY);
00689 #endif
00690
00691 const Ptype ptype = m.ptype();
00692
00693 const int defense = state.countEffect(alt(P),to,pins);
00694 int offense = state.countEffect(P,to) + (m.isDrop() ? 1 : 0);
00695 if (defense >= offense)
00696 offense += AdditionalEffect::count2(state, to, P);
00697 if (ptype == PAWN)
00698 {
00699 const Square head = to + DirectionPlayerTraits<U,P>::offset();
00700 if (state.hasEffectAt<P>(head))
00701 ++offense;
00702 }
00703 if (defense > offense)
00704 continue;
00705 if (defense == offense)
00706 {
00707 if (ptype != PAWN)
00708 continue;
00709 }
00710 if (isMajor(ptype))
00711 {
00712 if (defense == 0)
00713 {
00714
00715 if (isPromoted(ptype) && to.x() == king_x
00716 && abs(to.y() - king_position.y()) <= 2)
00717 moves.push_back(m);
00718 else if (m.isDrop())
00719 major_drop.push_back(m);
00720 else
00721 not_drop.push_back(m);
00722 }
00723 continue;
00724 }
00725 if (Ptype_Table.getMoveMask(m.ptype()) == PtypeTraits<GOLD>::moveMask)
00726 {
00727 const int y = to.y();
00728 if (((P == BLACK) && (y == 1))
00729 || ((P == WHITE) && (y == 9)))
00730 continue;
00731 }
00732
00733 if (ptype != PAWN)
00734 {
00735 if (state.hasEffectByPtype<PAWN>(alt(P), to))
00736 continue;
00737 if (state.hasEffectByPtype<LANCE>(alt(P), to))
00738 {
00739 not_drop.push_back(m);
00740 continue;
00741 }
00742 }
00743 if (! Neighboring8::isNeighboring8(king_position, to))
00744 not8.push_back(m);
00745 else if (! m.isDrop())
00746 not_drop.push_back(m);
00747 else
00748 moves.push_back(m);
00749 }
00750 const size_t minimum_moves
00751 = (king_position.squareForBlack<P>().y() == 1) ? 3 : 2;
00752 for (MoveVector::const_iterator p=not8.begin();
00753 (p!=not8.end()) && (moves.size() <= minimum_moves); ++p)
00754 {
00755 moves.push_back(*p);
00756 }
00757 for (MoveVector::const_iterator p=not_drop.begin();
00758 (p!=not_drop.end()) && (moves.size() <= minimum_moves); ++p)
00759 {
00760 moves.push_back(*p);
00761 }
00762 for (MoveVector::const_iterator p=major_drop.begin();
00763 (p!=major_drop.end()) && (moves.size() <= minimum_moves); ++p)
00764 {
00765 moves.push_back(*p);
00766 }
00767 }
00768
00769 template <osl::Player P>
00770 void osl::search::QuiescenceGenerator<P>::
00771 attackToPinned(const NumEffectState& state, PieceMask pins, MoveVector& moves)
00772 {
00773 using namespace move_action;
00774 MoveVector all_moves;
00775 move_generator::AttackToPinned<P>::generate(state, all_moves);
00776
00777 BOOST_FOREACH(Move m, all_moves)
00778 {
00779
00780 assert(!ShouldPromoteCut::canIgnoreAndNotDrop<P>(m));
00781 if (m.isPromotion())
00782 continue;
00783 const Square to = m.to();
00784 const Ptype captured = m.capturePtype();
00785
00786 if (captured != PTYPE_EMPTY)
00787 continue;
00788
00789 const Ptype ptype = m.ptype();
00790
00791 const int defense = state.countEffect(alt(P),to,pins);
00792 int offense = state.countEffect(P,to) + (m.isDrop() ? 1 : 0);
00793 if (defense >= offense)
00794 offense += AdditionalEffect::count2(state, to, P);
00795 if (ptype == PAWN)
00796 {
00797 const Square head = to + DirectionPlayerTraits<U,P>::offset();
00798 if (state.hasEffectAt<P>(head))
00799 ++offense;
00800 }
00801 if (defense > offense)
00802 continue;
00803 if (defense == offense)
00804 {
00805 if (ptype != PAWN)
00806 continue;
00807 }
00808
00809 if (ptype != PAWN)
00810 {
00811 const Square front_position
00812 = to + DirectionPlayerTraits<U,P>::offset();
00813 const Piece front_piece = state.pieceAt(front_position);
00814 if (front_piece.ptypeO() == newPtypeO(alt(P),PAWN))
00815 continue;
00816 }
00817 moves.push_back(m);
00818 }
00819 }
00820
00821 template <osl::Player P>
00822 void osl::search::QuiescenceGenerator<P>::
00823 utilizePromoted(const NumEffectState& state, Piece target,
00824 MoveVector& moves)
00825 {
00826 if (! target.isPromoted())
00827 return;
00828 if (
00829 target.ptype() == ROOK
00830 || target.ptype() == BISHOP)
00831 return;
00832
00833 MoveVector all_moves;
00834 move_generator::GeneratePieceOnBoard::generate(P,state, target, all_moves);
00835
00836 MoveVector others;
00837 const Player Opponent = PlayerTraits<P>::opponent;
00838 bool has_good_capture = false;
00839 bool may_have_additional = false;
00840 BOOST_FOREACH(Move m, all_moves)
00841 {
00842 assert(m.from() == target.square());
00843 if (m.isCapture())
00844 {
00845 if (m.capturePtype() != PAWN)
00846 has_good_capture =true;
00847 continue;
00848 }
00849
00850 const Square to = m.to();
00851 int offense = state.countEffect(P, to);
00852 const int defense = state.countEffect(Opponent, to);
00853 const int additional = AdditionalEffect::count2(state, to, P);
00854 if (defense >= offense)
00855 {
00856 offense += additional;
00857 may_have_additional |= (additional > 0);
00858 }
00859 if (defense >= offense)
00860 {
00861 others.push_back(m);
00862 continue;
00863 }
00864 moves.push_back(m);
00865 }
00866 if ((! has_good_capture) && may_have_additional)
00867 moves.push_back(others.begin(), others.end());
00868 }
00869
00870 template <osl::Player P>
00871 void osl::search::QuiescenceGenerator<P>::
00872 breakThreatmate(const NumEffectState& state,
00873 Move threatmate, PieceMask pins, MoveVector& moves)
00874 {
00875 MoveVector all_moves, major_piece, major_sacrifice;
00876 assert(threatmate.isNormal());
00877 const Square target = threatmate.to();
00878
00879
00880 move_generator::GenerateAddEffectWithEffect::generate<false>
00881 (P, state, target, all_moves);
00882
00883 BOOST_FOREACH(Move m, all_moves)
00884 {
00885 const Ptype ptype = m.ptype();
00886 if (ptype == KING)
00887 continue;
00888 if (! m.isDrop())
00889 {
00890 assert(!ShouldPromoteCut::canIgnoreAndNotDrop<P>(m));
00891 if (m.isPromotion())
00892 continue;
00893 if (isMajor(ptype)
00894 && state.hasEffectByPiece(state.pieceOnBoard(m.from()), target))
00895 continue;
00896 }
00897 const Square to = m.to();
00898 const int me = state.countEffect(P, to) + (m.isDrop() ? 1 : 0);
00899 const int op = state.countEffect(alt(P), to, pins);
00900 if ((me >= 2) || (op == 0))
00901 {
00902 if (isMajor(ptype))
00903 {
00904 if (op)
00905 major_sacrifice.push_back(m);
00906 else
00907 major_piece.push_back(m);
00908 }
00909 else
00910 {
00911 if (m.isDrop() && (ptype == GOLD || ptype == SILVER)
00912 && (to.x() == 1 || to.x() == 9))
00913 major_piece.push_back(m);
00914 else
00915 moves.push_back(m);
00916 }
00917 }
00918 }
00919 all_moves.clear();
00920
00921 if (threatmate.isDrop())
00922 {
00923
00924 if (state.hasPieceOnStand<PAWN>(P)
00925 && ! state.isPawnMaskSet(P, target.x())
00926 && PtypePlayerTraits<PAWN,P>::canDropTo(target))
00927 moves.push_back(Move(target, PAWN, P));
00928 else if (state.hasPieceOnStand<LANCE>(P)
00929 && PtypePlayerTraits<LANCE,P>::canDropTo(target))
00930 moves.push_back(Move(target, LANCE, P));
00931 else if (state.hasPieceOnStand<KNIGHT>(P)
00932 && PtypePlayerTraits<KNIGHT,P>::canDropTo(target))
00933 moves.push_back(Move(target, KNIGHT, P));
00934 else if (state.hasPieceOnStand<SILVER>(P))
00935 moves.push_back(Move(target, SILVER, P));
00936 else if (state.hasPieceOnStand<GOLD>(P))
00937 moves.push_back(Move(target, GOLD, P));
00938 }
00939
00940 BreakThreatmate::findBlockLong(state, threatmate, all_moves);
00941 if (! all_moves.empty())
00942 {
00943 Ptype cheapest = PTYPE_EMPTY;
00944 if (state.hasPieceOnStand<PAWN>(P)) cheapest = PAWN;
00945 else if (state.hasPieceOnStand<LANCE>(P)) cheapest = LANCE;
00946 else if (state.hasPieceOnStand<KNIGHT>(P)) cheapest = KNIGHT;
00947 BOOST_FOREACH(Move m, all_moves) {
00948 const int d = state.countEffect(P, m.to()) + m.isDrop();
00949 const int a = state.countEffect(alt(P), m.to());
00950 if (a >= d && ! (d >= 2 && m.ptype() == PAWN))
00951 continue;
00952 if (m.ptype() != cheapest && cheapest != PTYPE_EMPTY && Ptype_Table.canDropTo(P, cheapest, m.to()))
00953 continue;
00954 moves.push_back(m);
00955 break;
00956 }
00957 all_moves.clear();
00958 }
00959
00960
00961 const Square king_position = state.kingSquare(P);
00962
00963 {
00964 for (int i=SHORT8_DIRECTION_MIN; i<=SHORT8_DIRECTION_MAX; ++i)
00965 {
00966 const Piece p = state.pieceAt(Board_Table.nextSquare
00967 (P,king_position,Direction(i)));
00968 if (! (p.isPiece() && p.owner() == P))
00969 continue;
00970 if (state.hasEffectAt(alt(P), p.square()))
00971 continue;
00972 move_generator::GeneratePieceOnBoard::generate(P,state, p, all_moves);
00973 }
00974 BOOST_FOREACH(Move m, all_moves)
00975 {
00976 assert(! m.isDrop());
00977 assert(!ShouldPromoteCut::canIgnoreAndNotDrop<P>(m));
00978 if (m.isPromotion())
00979 continue;
00980 const Ptype captured = m.capturePtype();
00981 if ((captured != PTYPE_EMPTY)
00982 && (eval::Ptype_Eval_Table.value(captured)
00983 >= eval::PtypeEvalTraits<KNIGHT>::val))
00984 continue;
00985 moves.push_back(m);
00986 }
00987 }
00988
00989 const size_t minimum_moves = 8;
00990 for (MoveVector::const_iterator p=major_piece.begin();
00991 p!=major_piece.end() && moves.size() < minimum_moves; ++p)
00992 {
00993 moves.push_back(*p);
00994 }
00995 for (MoveVector::const_iterator p=major_sacrifice.begin();
00996 p!=major_sacrifice.end() && moves.size() < minimum_moves; ++p)
00997 {
00998 moves.push_back(*p);
00999 }
01000 }
01001
01002 template <osl::Player P>
01003 void osl::search::QuiescenceGenerator<P>::
01004 attackGoldWithPawn(const NumEffectState& state, PieceMask pins,
01005 MoveVector& moves)
01006 {
01007 using namespace move_action;
01008
01009 const bool has_pawn = state.hasPieceOnStand<PAWN>(P);
01010 const bool has_lance = state.hasPieceOnStand<LANCE>(P);
01011 const bool has_knight = state.hasPieceOnStand<KNIGHT>(P);
01012 const bool has_silver = state.hasPieceOnStand<SILVER>(P);
01013 for (int i = PtypeTraits<GOLD>::indexMin;
01014 i < PtypeTraits<GOLD>::indexLimit; ++i)
01015 {
01016 const Piece p = state.pieceOf(i);
01017 if (! p.isOnBoardByOwner<PlayerTraits<P>::opponent>())
01018 continue;
01019 const Square head = p.square() + DirectionPlayerTraits<D,P>::offset();
01020 if (state.pieceAt(head).isEmpty())
01021 {
01022
01023 const int defense = state.countEffect(alt(P), head, pins);
01024 int attack = state.countEffect(P, head)
01025 + state.hasEffectByPtype<BISHOP>(P, p.square());
01026 if (defense >= attack)
01027 attack += AdditionalEffect::count2(state, head, P);
01028
01029
01030 if (! head.canPromote<P>())
01031 {
01032 const Square origin = head + DirectionPlayerTraits<D,P>::offset();
01033 if (defense <= attack
01034 || state.hasEffectByPtype<BISHOP>(P, origin))
01035 {
01036 const Piece candidate = state.pieceAt(origin);
01037 if (candidate.ptype() == PAWN && candidate.owner() == P)
01038 {
01039 const Move move(origin, head, PAWN, PTYPE_EMPTY, false, P);
01040 moves.push_back(move);
01041 ++attack;
01042 }
01043 }
01044 }
01045
01046 if (defense <= attack)
01047 {
01048 if (has_pawn && !state.template isPawnMaskSet<P>(head.x()))
01049 {
01050 const Move move(head, PAWN, P);
01051 moves.push_back(move);
01052 }
01053 if (has_lance)
01054 {
01055 const Move move(head, LANCE, P);
01056 moves.push_back(move);
01057 }
01058 if (has_silver)
01059 {
01060 const Move move(head, SILVER, P);
01061 moves.push_back(move);
01062 }
01063 }
01064 const bool generate_long_lance = has_lance
01065 && (! state.hasPieceOnStand<PAWN>(alt(P))
01066 || state.template isPawnMaskSet<PlayerTraits<P>::opponent>(head.x()));
01067 if (generate_long_lance)
01068 {
01069 for (Square to=head + DirectionPlayerTraits<D,P>::offset();
01070 state.pieceAt(to).isEmpty();
01071 to+=DirectionPlayerTraits<D,P>::offset())
01072 {
01073 const int defense = state.countEffect(alt(P), to, pins);
01074 const int attack = state.countEffect(P, to);
01075 if (defense > attack)
01076 continue;
01077 const Move move(to, LANCE, P);
01078 moves.push_back(move);
01079 }
01080 }
01081 }
01082
01083 if (! state.pieceAt(head).isEdge())
01084 {
01085 const Square knight_l = head+DirectionPlayerTraits<DL,P>::offset();
01086 attackWithKnight(state, pins, knight_l, has_knight, moves);
01087 const Square knight_r = head+DirectionPlayerTraits<DR,P>::offset();
01088 attackWithKnight(state, pins, knight_r, has_knight, moves);
01089 }
01090 }
01091 }
01092
01093 template <osl::Player P>
01094 void osl::search::QuiescenceGenerator<P>::
01095 attackWithKnight(const NumEffectState& state, PieceMask pins,
01096 Square attack_from,
01097 bool has_knight, MoveVector& moves)
01098 {
01099 if (state.pieceAt(attack_from) != Piece::EMPTY())
01100 return;
01101
01102 const int defense = state.countEffect(alt(P), attack_from, pins);
01103 int attack = state.countEffect(P, attack_from);
01104
01105 if (defense == 1
01106 && (attack == 1 || (has_knight && attack == 0)))
01107 {
01108 const Piece gold = state.findAttackAt<GOLD>(alt(P), attack_from);
01109 if (gold.ptype() == GOLD)
01110 {
01111
01112 const Square guarded
01113 = gold.square()+DirectionPlayerTraits<U,P>::offset();
01114 if (state.pieceAt(guarded).isOnBoardByOwner(alt(P))
01115 && (state.countEffect(alt(P), guarded)
01116 <= state.countEffect(P, guarded)))
01117 ++attack;
01118 }
01119
01120 const Square head = attack_from + DirectionPlayerTraits<U,P>::offset();
01121 const Piece head_piece = state.pieceOnBoard(head);
01122 if (head_piece.isOnBoardByOwner<PlayerTraits<P>::opponent>()) {
01123 if (state.hasEffectByPiece(head_piece, attack_from)
01124 && state.hasEffectByPtype<BISHOP>(P, head))
01125 ++attack;
01126 }
01127 }
01128
01129 if (defense > attack)
01130 return;
01131
01132 if (has_knight)
01133 {
01134 const Move drop(attack_from, KNIGHT, P);
01135 moves.push_back(drop);
01136 }
01137
01138 if (defense < attack)
01139 {
01140 mask_t mask=state.effectSetAt(attack_from).getMask(PtypeFuns<KNIGHT>::indexNum);
01141 mask &= mask_t::makeDirect(PtypeFuns<KNIGHT>::indexMask);
01142 mask &= state.piecesOnBoard(P).getMask(PtypeFuns<KNIGHT>::indexNum);
01143 BOOST_STATIC_ASSERT(PtypeTraits<KNIGHT>::indexLimit < 32);
01144 while (mask.any())
01145 {
01146 const int n = mask.takeOneBit();
01147 const Piece knight = state.pieceOf(n);
01148 if (knight.isPromoted())
01149 continue;
01150
01151 const Move move(knight.square(), attack_from, KNIGHT, PTYPE_EMPTY, false, P);
01152 assert(state.isAlmostValidMove<false>(move));
01153 moves.push_back(move);
01154 }
01155 }
01156 }
01157
01158 template <osl::Player P>
01159 void osl::search::QuiescenceGenerator<P>::
01160 attackKnightWithPawn(const NumEffectState& state, PieceMask pins,
01161 MoveVector& moves)
01162 {
01163 using namespace move_action;
01164
01165 const bool has_pawn = state.hasPieceOnStand<PAWN>(P);
01166 for (int i = PtypeTraits<KNIGHT>::indexMin;
01167 i < PtypeTraits<KNIGHT>::indexLimit; ++i)
01168 {
01169 const Piece p = state.pieceOf(i);
01170 if (p.isOnBoard() && p.ptype() == KNIGHT && p.owner() == alt(P))
01171 {
01172 const Square head = p.square()+DirectionPlayerTraits<D,P>::offset();
01173
01174 if (state.pieceAt(head).isEmpty())
01175 {
01176 const int defense = state.countEffect(alt(P), head, pins);
01177 const int offense = state.countEffect(P, head);
01178 if ((defense <= offense)
01179 && (! head.canPromote<P>()))
01180 {
01181 const Square origin = head+DirectionPlayerTraits<D,P>::offset();
01182 const Piece candidate = state.pieceAt(origin);
01183 if (candidate.ptype() == PAWN && candidate.owner() == P)
01184 {
01185 const Move move(origin, head, PAWN, PTYPE_EMPTY, false, P);
01186 moves.push_back(move);
01187 }
01188 }
01189 if (has_pawn && !state.template isPawnMaskSet<P>(head.x())
01190 && (defense <= offense+1))
01191 {
01192 const Move move(head, PAWN, P);
01193 moves.push_back(move);
01194 }
01195 }
01196 }
01197 }
01198 }
01199
01200 template <osl::Player P>
01201 void osl::search::QuiescenceGenerator<P>::
01202 attackSilverWithPawn(const NumEffectState& state, PieceMask pins,
01203 MoveVector& moves)
01204 {
01205 using namespace move_action;
01206
01207 const bool has_pawn = state.hasPieceOnStand<PAWN>(P);
01208 const bool has_lance = state.hasPieceOnStand<LANCE>(P);
01209 const bool has_knight = state.hasPieceOnStand<KNIGHT>(P);
01210 const bool has_silver = state.hasPieceOnStand<SILVER>(P);
01211 const Square opponent_king = state.kingSquare(alt(P));
01212 for (int i = PtypeTraits<SILVER>::indexMin;
01213 i < PtypeTraits<SILVER>::indexLimit; ++i)
01214 {
01215 const Piece p = state.pieceOf(i);
01216 if (! p.isOnBoardByOwner<PlayerTraits<P>::opponent>())
01217 continue;
01218
01219 const Square head = p.square()+DirectionPlayerTraits<D,P>::offset();
01220 if (state.pieceAt(head).isEmpty())
01221 {
01222 const int defense = state.countEffect(alt(P), head, pins);
01223 int attack = state.countEffect(P, head)
01224 + state.hasEffectByPtype<BISHOP>(P, p.square());
01225 if (defense >= attack)
01226 attack += AdditionalEffect::count2(state, head, P);
01227 const bool near_king
01228 = Neighboring8Direct::hasEffect(state, p.ptypeO(), p.square(),
01229 opponent_king);
01230 if (defense > attack)
01231 {
01232 if (! near_king)
01233 continue;
01234
01235 }
01236 if (! head.canPromote<P>())
01237 {
01238 const Square origin = head+DirectionPlayerTraits<D,P>::offset();
01239 const Piece candidate = state.pieceAt(origin);
01240 if (candidate.ptype() == PAWN && candidate.owner() == P)
01241 {
01242 const Move move(origin, head, PAWN, PTYPE_EMPTY, false, P);
01243 moves.push_back(move);
01244 }
01245 }
01246 if (has_pawn && !state.template isPawnMaskSet<P>(head.x()))
01247 {
01248 const Move move(head, PAWN, P);
01249 moves.push_back(move);
01250 }
01251 if (! near_king)
01252 continue;
01253 if (defense <= attack)
01254 {
01255 if (has_lance)
01256 {
01257 const Move move(head, LANCE, P);
01258 moves.push_back(move);
01259 }
01260 if (has_silver)
01261 {
01262 const Move move(head, SILVER, P);
01263 moves.push_back(move);
01264 }
01265 }
01266 }
01267
01268 if (! state.pieceAt(head).isEdge())
01269 {
01270 const Square knight_l = head+DirectionPlayerTraits<DL,P>::offset();
01271 attackWithKnight(state, pins, knight_l, has_knight, moves);
01272 const Square knight_r = head+DirectionPlayerTraits<DR,P>::offset();
01273 attackWithKnight(state, pins, knight_r, has_knight, moves);
01274 }
01275
01276 const CArray<Square,2> side = {{
01277 p.square() + DirectionTraits<L>::blackOffset(),
01278 p.square() + DirectionTraits<R>::blackOffset(),
01279 }};
01280 BOOST_FOREACH(Square s, side) {
01281 if (! state.pieceAt(s).isEmpty())
01282 continue;
01283 if (state.countEffect(P, s)
01284 < state.countEffect(alt(P), s))
01285 continue;
01286 MoveVector candidate;
01287 move_generator::GenerateCapture::generate(P,state, s, candidate);
01288
01289 BOOST_FOREACH(Move m, candidate) {
01290 if (m.isPromotion()
01291 || state.hasEffectByPiece(state.pieceOnBoard(m.from()),
01292 p.square()))
01293 continue;
01294 assert(! ShouldPromoteCut::canIgnoreMove<P>(m));
01295 moves.push_back(m);
01296 }
01297 }
01298 }
01299 }
01300
01301 template <osl::Player P>
01302 void osl::search::QuiescenceGenerator<P>::
01303 kingWalk(const NumEffectState& state, MoveVector& moves)
01304 {
01305 const Piece my_king = state.kingPiece<P>();
01306 MoveVector all_moves;
01307 move_generator::GeneratePieceOnBoard::generate(P,state, my_king, all_moves);
01308
01309 BOOST_FOREACH(Move m, all_moves)
01310 {
01311 if (state.hasEffectAt(alt(P), m.to()))
01312 continue;
01313 moves.push_back(m);
01314 }
01315 }
01316
01317 template <osl::Player P>
01318 void osl::search::QuiescenceGenerator<P>::
01319 escapeKing(const NumEffectState& state, MoveVector& moves)
01320 {
01321 MoveVector all_moves;
01322 GenerateEscape<P>::generateCheap(state, state.template kingPiece<P>(), all_moves);
01323
01324 BOOST_FOREACH(Move m, all_moves)
01325 {
01326 const Square to = m.to();
01327 if (m.isDrop())
01328 {
01329
01330 if (! state.hasEffectAt<P>(to))
01331 {
01332 if (! ((m.ptype() == PAWN)
01333 && state.hasMultipleEffectAt(alt(P), to)))
01334 continue;
01335 }
01336 }
01337 else if (m.ptype() != KING)
01338 {
01339
01340 if (! m.isCapture())
01341 {
01342 if (! state.hasMultipleEffectAt(P, to))
01343 {
01344 if (! ((m.ptype() == PAWN)
01345 && state.hasMultipleEffectAt(alt(P), to)))
01346 continue;
01347 }
01348 }
01349 }
01350 moves.push_back(m);
01351 }
01352 }
01353
01354 template <osl::Player P>
01355 bool osl::search::QuiescenceGenerator<P>::
01356 escapeKingInTakeBack(const NumEffectState& state, MoveVector& moves,
01357 bool check_by_lance)
01358 {
01359 bool has_safe_move = false;
01360 assert(moves.empty());
01361 MoveVector all_moves;
01362 GenerateEscape<P>::generate(state, state.template kingPiece<P>(), all_moves);
01363
01364 Square last_drop_to = Square::STAND();
01365 MoveVector drops;
01366 BOOST_FOREACH(Move m, all_moves)
01367 {
01368 const Square to = m.to();
01369 if (m.ptype() == KING)
01370 {
01371
01372 has_safe_move = true;
01373 continue;
01374 }
01375 if (m.isCapture())
01376 {
01377 moves.push_back(m);
01378 continue;
01379 }
01380
01381 const int attack_count = state.countEffect(alt(P),to);
01382 const int defense_count
01383 = state.countEffect(P,to) + (m.isDrop() ? 1 : 0);
01384 if (defense_count <= attack_count)
01385 continue;
01386 if ((attack_count == 1) && (! check_by_lance))
01387 {
01388
01389 has_safe_move = true;
01390 continue;
01391 }
01392
01393
01394
01395 if (to != last_drop_to)
01396 {
01397 last_drop_to = to;
01398 drops.push_back(m);
01399 }
01400 }
01401 if (! has_safe_move)
01402 moves.push_back(drops.begin(), drops.end());
01403 return has_safe_move;
01404 }
01405
01406 template <osl::Player P>
01407 void osl::search::QuiescenceGenerator<P>::
01408 advanceBishop(const NumEffectState& state, MoveVector& moves)
01409 {
01410 for (int i = PtypeTraits<BISHOP>::indexMin;
01411 i < PtypeTraits<BISHOP>::indexLimit; ++i)
01412 {
01413 const Piece bishop = state.pieceOf(i);
01414 if (! bishop.isOnBoardByOwner<P>())
01415 continue;
01416 if (bishop.ptype() != BISHOP)
01417 continue;
01418 const Square from = bishop.square();
01419 if (state.hasEffectAt<PlayerTraits<P>::opponent>(from))
01420 continue;
01421 advanceBishop<UL>(state, from, moves);
01422 advanceBishop<UR>(state, from, moves);
01423 }
01424 }
01425
01426 template <osl::Player P>
01427 template <osl::Direction DIR>
01428 void osl::search::QuiescenceGenerator<P>::
01429 advanceBishop(const NumEffectState& state,
01430 const Square from, MoveVector& moves)
01431 {
01432 const Offset offset = DirectionPlayerTraits<DIR,P>::offset();
01433 for (Square to=from+offset;; to+=offset)
01434 {
01435 if (! state.pieceAt(to).isEmpty())
01436 break;
01437 if (to.canPromote<P>())
01438 break;
01439 if (state.hasEffectAt<PlayerTraits<P>::opponent>(to))
01440 continue;
01441 const Move move(from, to, BISHOP, PTYPE_EMPTY, false, P);
01442 assert(state.isAlmostValidMove<false>(move));
01443 moves.push_back(move);
01444 }
01445 }
01446
01447 template <osl::Player P>
01448 template <class EvalT>
01449 void osl::search::QuiescenceGenerator<P>::
01450 escapeFromLastMove(const NumEffectState& state, Move last_move, MoveVector& moves)
01451 {
01452 if (! last_move.isNormal())
01453 return;
01454 if (last_move.ptype() != PAWN)
01455 {
01456 escapeFromLastMoveOtherThanPawn<EvalT>(state, last_move, moves);
01457 return;
01458 }
01459 const Square attack_from = last_move.to();
01460 const Square attack_to = attack_from+DirectionPlayerTraits<D,P>::offset();
01461 const Piece target = state.pieceOnBoard(attack_to);
01462 if (! target.isOnBoardByOwner<P>())
01463 return;
01464
01465 using namespace move_action;
01466 MoveVector all_moves;
01467 GenerateEscape<P>::generate(state, target, all_moves);
01468
01469 BOOST_FOREACH(Move m, all_moves)
01470 {
01471 assert(! m.isDrop());
01472 const Square to = m.to();
01473
01474 const int defense = state.countEffect(P, to);
01475 const int offense = state.countEffect(alt(P), to);
01476 if (offense > defense)
01477 continue;
01478 if (to == attack_from)
01479 {
01480
01481 if (offense == defense)
01482 continue;
01483 assert(m.capturePtype() == PAWN);
01484 assert(! ShouldPromoteCut::canIgnoreMove<P>(m));
01485 moves.push_back(m);
01486 continue;
01487 }
01488 assert(m.from() == attack_to);
01489 if ((offense == defense)
01490 && (m.isCapture()))
01491 continue;
01492
01493
01494 assert(! ShouldPromoteCut::canIgnoreMove<P>(m));
01495 if (! m.isPromotion())
01496 {
01497 moves.push_back(m);
01498 }
01499 }
01500 }
01501
01502 template <osl::Player P>
01503 void osl::search::QuiescenceGenerator<P>::
01504 dropMajorPiece(const NumEffectState& state, MoveVector& moves)
01505 {
01506 move_generator::SafeDropMajorPiece<P>::generateMoves(state, moves);
01507 }
01508
01509 template <osl::Player P>
01510 void osl::search::QuiescenceGenerator<P>::
01511 dropMajorPiece3(const NumEffectState& state, MoveVector& moves, const HistoryTable& table)
01512 {
01513 FixedCapacityVector<Move, 27*2> all;
01514 move_generator::SafeDropMajorPiece<P>::generateMoves(state, all);
01515 FixedCapacityVector<std::pair<int,Move>, 27*2> selected;
01516 BOOST_FOREACH(Move m, all)
01517 selected.push_back(std::make_pair(table.value(m), m));
01518 std::sort(selected.begin(), selected.end());
01519 for (int i=0; i<std::min(3, (int)selected.size()); ++i)
01520 moves.push_back(selected[selected.size()-1-i].second);
01521 }
01522
01523 #endif
01524
01525
01526
01527