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