breakThreatmate.cc
Go to the documentation of this file.
00001 /* breakThreatmate.cc
00002  */
00003 #include "osl/search/breakThreatmate.h"
00004 #include "osl/container/moveLogProbVector.h"
00005 #include "osl/move_generator/addEffectWithEffect.h"
00006 #include "osl/move_generator/capture_.h"
00007 #include "osl/move_generator/pieceOnBoard.h"
00008 #include "osl/move_generator/escape_.h"
00009 #include "osl/move_action/store.h"
00010 #include "osl/checkmate/king8Info.h"
00011 #include "osl/boardTable.h"
00012 #include "osl/ptypeTable.h"
00013 #include "osl/neighboring8.h"
00014 #include <boost/foreach.hpp>
00015 
00016 void osl::search::
00017 BreakThreatmate::generateBreakDrop(int limit,
00018                                    const NumEffectState& state, Square to,
00019                                    int default_prob,
00020                                    MoveLogProbVector& out)
00021 {
00022   const Player Turn = state.turn();
00023   default_prob = std::max(default_prob, 150);
00024   if (state.hasPieceOnStand<PAWN>(Turn))
00025   {
00026     if (! state.isPawnMaskSet(Turn, to.x())
00027         && Ptype_Table.canDropTo(Turn, PAWN, to)
00028         && limit >= default_prob-100)
00029       out.push_back(MoveLogProb(Move(to, PAWN, Turn), default_prob-100));
00030   }
00031   if (state.hasPieceOnStand<LANCE>(Turn)
00032       && Ptype_Table.canDropTo(Turn, LANCE, to)
00033       && limit >= default_prob-50)
00034     out.push_back(MoveLogProb(Move(to, LANCE, Turn), default_prob-50));
00035   if (default_prob > limit)
00036     return;
00037 
00038   if (state.hasPieceOnStand<KNIGHT>(Turn)
00039       && Ptype_Table.canDropTo(Turn, KNIGHT, to))
00040     out.push_back(MoveLogProb(Move(to, KNIGHT, Turn), default_prob));
00041   if (state.hasPieceOnStand<SILVER>(Turn))
00042     out.push_back(MoveLogProb(Move(to, SILVER, Turn), default_prob));
00043   if (state.hasPieceOnStand<GOLD>(Turn))
00044     out.push_back(MoveLogProb(Move(to, GOLD, Turn), default_prob));
00045   if (state.hasPieceOnStand<BISHOP>(Turn))
00046     out.push_back(MoveLogProb(Move(to, BISHOP, Turn), default_prob));
00047   if (state.hasPieceOnStand<ROOK>(Turn))
00048     out.push_back(MoveLogProb(Move(to, ROOK, Turn), default_prob));
00049 }
00050 
00051 void osl::search::BreakThreatmate::findBlockLong(const NumEffectState& state, Move threatmate_move,
00052                                                  MoveVector& out)
00053 {
00054   const Player Turn = alt(threatmate_move.player());
00055   const Piece my_king = state.kingPiece(Turn);
00056   const Square target = threatmate_move.to();
00057   out.clear();
00058   move_action::Store store(out);
00059   // block additional
00060   if (! threatmate_move.isDrop()
00061       && threatmate_move.oldPtype() != KNIGHT)
00062   {
00063     const Offset step = Board_Table.getShortOffsetNotKnight(Offset32(threatmate_move.from(), target));
00064     Square p=threatmate_move.from()+step;
00065     Piece piece=state.pieceAt(p);
00066     for (; piece.isEmpty(); p+=step, piece=state.pieceAt(p))
00067       ;
00068     if (piece.isPiece() && piece.owner() == alt(Turn)
00069         && state.hasEffectByPiece(piece, threatmate_move.from())) {
00070       if (Turn == BLACK)
00071         move_generator::Escape<move_action::Store>::generateBlocking<BLACK,true>
00072           (state, my_king, threatmate_move.from(), piece.square(), store);
00073       else
00074         move_generator::Escape<move_action::Store>::generateBlocking<WHITE,true>
00075           (state, my_king, threatmate_move.from(), piece.square(), store);
00076     }
00077   }
00078   // block long
00079   {
00080     mask_t attack = state.longEffectAt(target, alt(Turn));
00081     while (attack.any()) {
00082       BOOST_STATIC_ASSERT(PtypeFuns<LANCE>::indexNum == PtypeFuns<BISHOP>::indexNum);
00083       BOOST_STATIC_ASSERT(PtypeFuns<LANCE>::indexNum == PtypeFuns<ROOK>::indexNum);
00084       const int num = (attack.takeOneBit()+((PtypeFuns<LANCE>::indexNum)<<5));
00085       if (Turn == BLACK)
00086         move_generator::Escape<move_action::Store>::generateBlocking<BLACK,true>
00087           (state, my_king, target, state.pieceOf(num).square(), store);
00088       else
00089         move_generator::Escape<move_action::Store>::generateBlocking<WHITE,true>
00090           (state, my_king, target, state.pieceOf(num).square(), store);
00091     }
00092   }
00093 }
00094 
00095 void osl::search::BreakThreatmate::
00096 generateAddEffect(int limit, const NumEffectState& state, Square target,
00097                   const MoveVector& all_moves, MoveLogProbVector& out)
00098 {
00099   const Player Turn = state.turn();
00100   const int max_prob = state.king8Info(state.turn()).liberty() ? limit : 100;
00101   BOOST_FOREACH(Move move, all_moves)
00102   {
00103     const Ptype ptype = move.ptype();
00104     if (ptype == KING)
00105       continue;                 // KING_WALK will generate
00106     if (! move.isDrop())
00107     {
00108       if (isMajor(ptype)
00109           && state.hasEffectByPiece(state.pieceOnBoard(move.from()), target))
00110         continue;                       // already have effect
00111     }
00112     const Square to = move.to();
00113     const int me = state.countEffect(Turn, to) + (move.isDrop() ? 1 : 0);
00114     const int op = state.countEffect(alt(Turn), to);
00115     int prob = (move.isDrop() ? 100 : 100); // delay drop
00116     if (move.isCapture())
00117     {
00118       prob -= 50;
00119     }
00120     else
00121     { 
00122       if (isMajor(ptype)
00123           || ((ptype == GOLD || ptype == SILVER)
00124               && (to.x() == 1 || to.x() == 9)))
00125       {
00126         prob += 50;
00127       }
00128       if (! ((me >= 2) || (op == 0)))
00129       {
00130         prob += 300;
00131       }
00132     }
00133     prob = std::min(prob, max_prob);
00134     if (prob <= limit)
00135       out.push_back(MoveLogProb(move, prob));
00136   }
00137 }
00138 
00139 // yoshiki's suggestion 駒取り 50, 普通 100, 駒捨て 400 
00140 void osl::search::BreakThreatmate::
00141 generate(int limit, const NumEffectState& state, Move threatmate_move,
00142          MoveLogProbVector& out)
00143 {
00144   assert(threatmate_move.isNormal());
00145   const Player Turn = state.turn();
00146   
00147   MoveVector all_moves;
00148   assert(threatmate_move.isNormal());
00149   const Square target = threatmate_move.to();
00150   move_generator::GenerateAddEffectWithEffect::generate<false>
00151       (Turn, state, target, all_moves);
00152   generateAddEffect(limit, state, target, all_moves, out);
00153 
00154   if (threatmate_move.isDrop())
00155   {
00156     const int drop_prob = (state.hasEffectAt(alt(Turn), target) ? 400 : 100);
00157     generateBreakDrop(limit, state, target, drop_prob, out);
00158   }
00159   else
00160   {
00161     // not drop
00162     const Square from = threatmate_move.from();
00163     const Offset offset
00164       = Board_Table.getShortOffsetNotKnight(Offset32(target, from));
00165     if (! offset.zero())
00166     {
00167       for (Square to = from + offset; to != target; to += offset) 
00168       {
00169         assert(to.isOnBoard());
00170         assert(state.pieceOnBoard(to) == Piece::EMPTY());
00171         const int drop_prob = (state.hasEffectAt(Turn, to) ? 100 : 400);
00172         generateBreakDrop(limit, state, to, drop_prob, out);
00173 
00174         const int move_prob = (state.hasMultipleEffectAt(Turn, to) ? 100 : 400);
00175         if (move_prob > limit)
00176           continue;
00177         all_moves.clear();
00178         move_generator::GenerateCapture::generate
00179           (Turn, state, to, all_moves);
00180         BOOST_FOREACH(Move move, all_moves)
00181         {
00182           out.push_back(MoveLogProb(move, move_prob));
00183         }
00184       }
00185     }
00186   }
00187   const Piece my_king = state.kingPiece(Turn);
00188   if (my_king.square()
00189       != target+Board_Table.getShortOffset(Offset32(my_king.square(),target)))
00190   {
00191     const checkmate::King8Info king8info = state.king8Info(Turn);
00192     unsigned int drop_candidate = king8info.dropCandidate();
00193     if (drop_candidate) {
00194       const int d = misc::BitOp::bsf(drop_candidate);
00195       const Square to = my_king.square()
00196         + Board_Table.getOffset(Turn, static_cast<Direction>(d));
00197       if (to != target) {
00198         all_moves.clear();
00199         move_generator::GenerateAddEffectWithEffect::generate<false>
00200           (Turn, state, to, all_moves);
00201         generateAddEffect(limit, state, to, all_moves, out);
00202       }
00203     }
00204   }
00205   // king walk
00206   const int king_prob = 100;
00207   if (king_prob <= limit)
00208   {
00209     all_moves.clear();
00210     {
00211       GeneratePieceOnBoard::generate(Turn, state, my_king, all_moves);
00212     }
00213     BOOST_FOREACH(Move move, all_moves)
00214     {
00215       if (state.hasEffectAt(alt(Turn), move.to()))
00216         continue;
00217       out.push_back(MoveLogProb(move, king_prob));
00218     }
00219   }
00220   
00221   // open king road
00222   const Square center = my_king.square();
00223   generateOpenRoad(limit, state, center + DirectionTraits<U>::blackOffset(), out);
00224   generateOpenRoad(limit, state, center + DirectionTraits<UL>::blackOffset(), out);
00225   generateOpenRoad(limit, state, center + DirectionTraits<UR>::blackOffset(), out);
00226   generateOpenRoad(limit, state, center + DirectionTraits<L>::blackOffset(), out);
00227   generateOpenRoad(limit, state, center + DirectionTraits<R>::blackOffset(), out);
00228   generateOpenRoad(limit, state, center + DirectionTraits<D>::blackOffset(), out);
00229   generateOpenRoad(limit, state, center + DirectionTraits<DL>::blackOffset(), out);
00230   generateOpenRoad(limit, state, center + DirectionTraits<DR>::blackOffset(), out);
00231 
00232   // block
00233   findBlockLong(state, threatmate_move, all_moves);
00234   if (! all_moves.empty()) 
00235   {
00236     Ptype cheapest = PTYPE_EMPTY;
00237     if (state.hasPieceOnStand<PAWN>(Turn)) cheapest = PAWN;
00238     else if (state.hasPieceOnStand<LANCE>(Turn)) cheapest = LANCE;
00239     else if (state.hasPieceOnStand<KNIGHT>(Turn)) cheapest = KNIGHT;
00240     int added = 0;
00241     Move chuai_reserve;
00242     BOOST_FOREACH(Move m, all_moves) {
00243       const int d = state.countEffect(Turn, m.to()) + m.isDrop();
00244       const int a = state.countEffect(alt(Turn), m.to());
00245       if (d == 1
00246           || (m.ptype() != cheapest && cheapest != PTYPE_EMPTY
00247               && Ptype_Table.canDropTo(Turn, cheapest, m.to())
00248               && (cheapest != PAWN || ! state.isPawnMaskSet(m.player(), m.to().x()))))
00249         continue;
00250       if (a >= d) {
00251         if (! chuai_reserve.isNormal()) 
00252           chuai_reserve = m;
00253         continue;
00254       }
00255       const int prob = 150+added*50;
00256       if (prob > limit)
00257         break;
00258       out.push_back(MoveLogProb(m, prob));
00259     }
00260     if (added == 0 && chuai_reserve.isNormal() && limit >= 250) {
00261       out.push_back(MoveLogProb(chuai_reserve, 250));
00262       if (chuai_reserve.isDrop() && chuai_reserve.ptype() == KNIGHT && 300 <= limit) {
00263         if (state.hasPieceOnStand<SILVER>(Turn))
00264           out.push_back(MoveLogProb(Move(chuai_reserve.to(),SILVER,Turn), 300));
00265         else if (state.hasPieceOnStand<GOLD>(Turn))
00266           out.push_back(MoveLogProb(Move(chuai_reserve.to(),GOLD,Turn), 300));
00267         else if (state.hasPieceOnStand<BISHOP>(Turn))
00268           out.push_back(MoveLogProb(Move(chuai_reserve.to(),BISHOP,Turn), 300));
00269         else if (state.hasPieceOnStand<ROOK>(Turn))
00270           out.push_back(MoveLogProb(Move(chuai_reserve.to(),ROOK,Turn), 300));
00271       }
00272     }
00273   }
00274 }
00275 
00276 void osl::search::BreakThreatmate::
00277 generateOpenRoad(int limit, const NumEffectState& state, 
00278                  Square from, MoveLogProbVector& out)
00279 {
00280   const Piece target = state.pieceAt(from);
00281   if (! target.isPiece())
00282     return;
00283   const Player Turn = state.turn();
00284   if (target.owner() != Turn)
00285     return;
00286 
00287   const int capture_prob = 50;
00288   const int default_prob = 100;
00289   const int sacrifice_prob = 400;
00290   if (limit < capture_prob)
00291     return;
00292 
00293   MoveVector moves;
00294   GeneratePieceOnBoard::generate(Turn, state, target, moves);
00295 
00296   BOOST_FOREACH(Move move, moves)
00297   {
00298     const bool capture = move.isCapture();
00299     const bool sacrifice = state.hasEffectAt(alt(Turn), move.to());
00300     const int prob = capture ? capture_prob
00301       : (sacrifice ? sacrifice_prob : default_prob);
00302     if (prob <= limit)
00303       out.push_back(MoveLogProb(move, prob));
00304   }
00305 }
00306 
00307 /* ------------------------------------------------------------------------- */
00308 // ;;; Local Variables:
00309 // ;;; mode:c++
00310 // ;;; c-basic-offset:2
00311 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines