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