00001
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, Position to,
00019 int default_prob,
00020 MoveLogProbVector& out)
00021 {
00022 const Player Turn = state.getTurn();
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.getKingPiece(Turn);
00056 const Position target = threatmate_move.to();
00057 out.clear();
00058 move_action::Store store(out);
00059
00060 if (! threatmate_move.isDrop()
00061 && threatmate_move.oldPtype() != KNIGHT)
00062 {
00063 const Offset step = Board_Table.getShortOffsetNotKnight(Offset32(threatmate_move.from(), target));
00064 Position p=threatmate_move.from()+step;
00065 Piece piece=state.getPieceAt(p);
00066 for (; piece.isEmpty(); p+=step, piece=state.getPieceAt(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.position(), store);
00073 else
00074 move_generator::Escape<move_action::Store>::generateBlocking<WHITE,true>
00075 (state, my_king, threatmate_move.from(), piece.position(), store);
00076 }
00077 }
00078
00079 {
00080 mask_t attack = state.selectLong(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.getPieceOf(num).position(), store);
00088 else
00089 move_generator::Escape<move_action::Store>::generateBlocking<WHITE,true>
00090 (state, my_king, target, state.getPieceOf(num).position(), store);
00091 }
00092 }
00093 }
00094
00095 void osl::search::BreakThreatmate::
00096 generateAddEffect(int limit, const NumEffectState& state, Position target,
00097 const MoveVector& all_moves, MoveLogProbVector& out)
00098 {
00099 const Player Turn = state.getTurn();
00100 const int max_prob = state.king8Info(state.getTurn()).liberty() ? limit : 100;
00101 BOOST_FOREACH(Move move, all_moves)
00102 {
00103 const Ptype ptype = move.ptype();
00104 if (ptype == KING)
00105 continue;
00106 if (! move.isDrop())
00107 {
00108 if (isMajor(ptype)
00109 && state.hasEffectByPiece(state.getPieceOnBoard(move.from()), target))
00110 continue;
00111 }
00112 const Position 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);
00116 if (move.capturePtype() != PTYPE_EMPTY)
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
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.getTurn();
00146
00147 MoveVector all_moves;
00148 assert(threatmate_move.isNormal());
00149 const Position 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.hasEffectBy(alt(Turn), target) ? 400 : 100);
00157 generateBreakDrop(limit, state, target, drop_prob, out);
00158 }
00159 else
00160 {
00161
00162 const Position from = threatmate_move.from();
00163 const Offset offset
00164 = Board_Table.getShortOffsetNotKnight(Offset32(target, from));
00165 if (! offset.zero())
00166 {
00167 for (Position to = from + offset; to != target; to += offset)
00168 {
00169 assert(to.isOnBoard());
00170 assert(state.getPieceOnBoard(to) == Piece::EMPTY());
00171 const int drop_prob = (state.hasEffectBy(Turn, to) ? 100 : 400);
00172 generateBreakDrop(limit, state, to, drop_prob, out);
00173
00174 const int move_prob = (state.hasMultipleEffectBy(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.getKingPiece(Turn);
00188 if (my_king.position()
00189 != target+Board_Table.getShortOffset(Offset32(my_king.position(),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 Position to = my_king.position()
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
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.hasEffectBy(alt(Turn), move.to()))
00216 continue;
00217 out.push_back(MoveLogProb(move, king_prob));
00218 }
00219 }
00220
00221
00222 const Position center = my_king.position();
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
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 Position from, MoveLogProbVector& out)
00279 {
00280 const Piece target = state.getPieceAt(from);
00281 if (! target.isPiece())
00282 return;
00283 const Player Turn = state.getTurn();
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.capturePtype() != PTYPE_EMPTY);
00299 const bool sacrifice = state.hasEffectBy(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
00309
00310
00311