breakThreatmate.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
breakThreatmate.cc
Go to the documentation of this file.
1 /* breakThreatmate.cc
2 */
3 #include "osl/search/breakThreatmate.h"
4 #include "osl/container/moveLogProbVector.h"
5 #include "osl/move_generator/addEffectWithEffect.h"
6 #include "osl/move_generator/capture_.h"
7 #include "osl/move_generator/pieceOnBoard.h"
8 #include "osl/move_generator/escape_.h"
9 #include "osl/move_action/store.h"
10 #include "osl/checkmate/king8Info.h"
11 #include "osl/boardTable.h"
12 #include "osl/ptypeTable.h"
13 #include "osl/neighboring8.h"
14 #include <boost/foreach.hpp>
15
16 void osl::search::
17 BreakThreatmate::generateBreakDrop(int limit,
18 const NumEffectState& state, Square to,
19 int default_prob,
20 MoveLogProbVector& out)
21 {
22 const Player Turn = state.turn();
23 default_prob = std::max(default_prob, 150);
24 if (state.hasPieceOnStand<PAWN>(Turn))
25 {
26 if (! state.isPawnMaskSet(Turn, to.x())
27 && Ptype_Table.canDropTo(Turn, PAWN, to)
28 && limit >= default_prob-100)
29 out.push_back(MoveLogProb(Move(to, PAWN, Turn), default_prob-100));
30 }
31 if (state.hasPieceOnStand<LANCE>(Turn)
32 && Ptype_Table.canDropTo(Turn, LANCE, to)
33 && limit >= default_prob-50)
34 out.push_back(MoveLogProb(Move(to, LANCE, Turn), default_prob-50));
35 if (default_prob > limit)
36 return;
37
38 if (state.hasPieceOnStand<KNIGHT>(Turn)
39 && Ptype_Table.canDropTo(Turn, KNIGHT, to))
40 out.push_back(MoveLogProb(Move(to, KNIGHT, Turn), default_prob));
41 if (state.hasPieceOnStand<SILVER>(Turn))
42 out.push_back(MoveLogProb(Move(to, SILVER, Turn), default_prob));
43 if (state.hasPieceOnStand<GOLD>(Turn))
44 out.push_back(MoveLogProb(Move(to, GOLD, Turn), default_prob));
45 if (state.hasPieceOnStand<BISHOP>(Turn))
46 out.push_back(MoveLogProb(Move(to, BISHOP, Turn), default_prob));
47 if (state.hasPieceOnStand<ROOK>(Turn))
48 out.push_back(MoveLogProb(Move(to, ROOK, Turn), default_prob));
49 }
50
51 void osl::search::BreakThreatmate::findBlockLong(const NumEffectState& state, Move threatmate_move,
52 MoveVector& out)
53 {
54 const Player Turn = alt(threatmate_move.player());
55 const Piece my_king = state.kingPiece(Turn);
56 const Square target = threatmate_move.to();
57 out.clear();
58 move_action::Store store(out);
59 // block additional
60 if (! threatmate_move.isDrop()
61 && threatmate_move.oldPtype() != KNIGHT)
62 {
63 const Offset step = Board_Table.getShortOffsetNotKnight(Offset32(threatmate_move.from(), target));
64 Square p=threatmate_move.from()+step;
65 Piece piece=state.pieceAt(p);
66 for (; piece.isEmpty(); p+=step, piece=state.pieceAt(p))
67 ;
68 if (piece.isPiece() && piece.owner() == alt(Turn)
69 && state.hasEffectByPiece(piece, threatmate_move.from())) {
70 if (Turn == BLACK)
71 move_generator::Escape<move_action::Store>::generateBlocking<BLACK,true>
72 (state, my_king, threatmate_move.from(), piece.square(), store);
73 else
74 move_generator::Escape<move_action::Store>::generateBlocking<WHITE,true>
75 (state, my_king, threatmate_move.from(), piece.square(), store);
76 }
77 }
78 // block long
79 {
80 mask_t attack = state.longEffectAt(target, alt(Turn));
81 while (attack.any()) {
82 BOOST_STATIC_ASSERT(PtypeFuns<LANCE>::indexNum == PtypeFuns<BISHOP>::indexNum);
83 BOOST_STATIC_ASSERT(PtypeFuns<LANCE>::indexNum == PtypeFuns<ROOK>::indexNum);
84 const int num = (attack.takeOneBit()+((PtypeFuns<LANCE>::indexNum)<<5));
85 if (Turn == BLACK)
86 move_generator::Escape<move_action::Store>::generateBlocking<BLACK,true>
87 (state, my_king, target, state.pieceOf(num).square(), store);
88 else
89 move_generator::Escape<move_action::Store>::generateBlocking<WHITE,true>
90 (state, my_king, target, state.pieceOf(num).square(), store);
91 }
92 }
93 }
94
95 void osl::search::BreakThreatmate::
96 generateAddEffect(int limit, const NumEffectState& state, Square target,
97 const MoveVector& all_moves, MoveLogProbVector& out)
98 {
99 const Player Turn = state.turn();
100 const int max_prob = state.king8Info(state.turn()).liberty() ? limit : 100;
101 BOOST_FOREACH(Move move, all_moves)
102 {
103 const Ptype ptype = move.ptype();
104 if (ptype == KING)
105 continue; // KING_WALK will generate
106 if (! move.isDrop())
107 {
108 if (isMajor(ptype)
109 && state.hasEffectByPiece(state.pieceOnBoard(move.from()), target))
110 continue; // already have effect
111 }
112 const Square to = move.to();
113 const int me = state.countEffect(Turn, to) + (move.isDrop() ? 1 : 0);
114 const int op = state.countEffect(alt(Turn), to);
115 int prob = (move.isDrop() ? 100 : 100); // delay drop
116 if (move.isCapture())
117 {
118 prob -= 50;
119 }
120 else
121 {
122 if (isMajor(ptype)
123 || ((ptype == GOLD || ptype == SILVER)
124 && (to.x() == 1 || to.x() == 9)))
125 {
126 prob += 50;
127 }
128 if (! ((me >= 2) || (op == 0)))
129 {
130 prob += 300;
131 }
132 }
133 prob = std::min(prob, max_prob);
134 if (prob <= limit)
135 out.push_back(MoveLogProb(move, prob));
136 }
137 }
138
139 // yoshiki's suggestion 駒取り 50, 普通 100, 駒捨て 400
140 void osl::search::BreakThreatmate::
141 generate(int limit, const NumEffectState& state, Move threatmate_move,
142 MoveLogProbVector& out)
143 {
144 assert(threatmate_move.isNormal());
145 const Player Turn = state.turn();
146
147 MoveVector all_moves;
148 assert(threatmate_move.isNormal());
149 const Square target = threatmate_move.to();
150 move_generator::GenerateAddEffectWithEffect::generate<false>
151 (Turn, state, target, all_moves);
152 generateAddEffect(limit, state, target, all_moves, out);
153
154 if (threatmate_move.isDrop())
155 {
156 const int drop_prob = (state.hasEffectAt(alt(Turn), target) ? 400 : 100);
157 generateBreakDrop(limit, state, target, drop_prob, out);
158 }
159 else
160 {
161 // not drop
162 const Square from = threatmate_move.from();
163 const Offset offset
164 = Board_Table.getShortOffsetNotKnight(Offset32(target, from));
165 if (! offset.zero())
166 {
167 for (Square to = from + offset; to != target; to += offset)
168 {
169 assert(to.isOnBoard());
170 assert(state.pieceOnBoard(to) == Piece::EMPTY());
171 const int drop_prob = (state.hasEffectAt(Turn, to) ? 100 : 400);
172 generateBreakDrop(limit, state, to, drop_prob, out);
173
174 const int move_prob = (state.hasMultipleEffectAt(Turn, to) ? 100 : 400);
175 if (move_prob > limit)
176 continue;
177 all_moves.clear();
178 move_generator::GenerateCapture::generate
179 (Turn, state, to, all_moves);
180 BOOST_FOREACH(Move move, all_moves)
181 {
182 out.push_back(MoveLogProb(move, move_prob));
183 }
184 }
185 }
186 }
187 const Piece my_king = state.kingPiece(Turn);
188 if (my_king.square()
189 != target+Board_Table.getShortOffset(Offset32(my_king.square(),target)))
190 {
191 const checkmate::King8Info king8info = state.king8Info(Turn);
192 unsigned int drop_candidate = king8info.dropCandidate();
193 if (drop_candidate) {
194 const int d = misc::BitOp::bsf(drop_candidate);
195 const Square to = my_king.square()
196 + Board_Table.getOffset(Turn, static_cast<Direction>(d));
197 if (to != target) {
198 all_moves.clear();
199 move_generator::GenerateAddEffectWithEffect::generate<false>
200 (Turn, state, to, all_moves);
201 generateAddEffect(limit, state, to, all_moves, out);
202 }
203 }
204 }
205 // king walk
206 const int king_prob = 100;
207 if (king_prob <= limit)
208 {
209 all_moves.clear();
210 {
211 GeneratePieceOnBoard::generate(Turn, state, my_king, all_moves);
212 }
213 BOOST_FOREACH(Move move, all_moves)
214 {
215 if (state.hasEffectAt(alt(Turn), move.to()))
216 continue;
217 out.push_back(MoveLogProb(move, king_prob));
218 }
219 }
220
221 // open king road
222 const Square center = my_king.square();
223 generateOpenRoad(limit, state, center + DirectionTraits<U>::blackOffset(), out);
224 generateOpenRoad(limit, state, center + DirectionTraits<UL>::blackOffset(), out);
225 generateOpenRoad(limit, state, center + DirectionTraits<UR>::blackOffset(), out);
226 generateOpenRoad(limit, state, center + DirectionTraits<L>::blackOffset(), out);
227 generateOpenRoad(limit, state, center + DirectionTraits<R>::blackOffset(), out);
228 generateOpenRoad(limit, state, center + DirectionTraits<D>::blackOffset(), out);
229 generateOpenRoad(limit, state, center + DirectionTraits<DL>::blackOffset(), out);
230 generateOpenRoad(limit, state, center + DirectionTraits<DR>::blackOffset(), out);
231
232 // block
233 findBlockLong(state, threatmate_move, all_moves);
234 if (! all_moves.empty())
235 {
236 Ptype cheapest = PTYPE_EMPTY;
237 if (state.hasPieceOnStand<PAWN>(Turn)) cheapest = PAWN;
238 else if (state.hasPieceOnStand<LANCE>(Turn)) cheapest = LANCE;
239 else if (state.hasPieceOnStand<KNIGHT>(Turn)) cheapest = KNIGHT;
240 int added = 0;
241 Move chuai_reserve;
242 BOOST_FOREACH(Move m, all_moves) {
243 const int d = state.countEffect(Turn, m.to()) + m.isDrop();
244 const int a = state.countEffect(alt(Turn), m.to());
245 if (d == 1
246 || (m.ptype() != cheapest && cheapest != PTYPE_EMPTY
247 && Ptype_Table.canDropTo(Turn, cheapest, m.to())
248 && (cheapest != PAWN || ! state.isPawnMaskSet(m.player(), m.to().x()))))
249 continue;
250 if (a >= d) {
251 if (! chuai_reserve.isNormal())
252 chuai_reserve = m;
253 continue;
254 }
255 const int prob = 150+added*50;
256 if (prob > limit)
257 break;
258 out.push_back(MoveLogProb(m, prob));
259 }
260 if (added == 0 && chuai_reserve.isNormal() && limit >= 250) {
261 out.push_back(MoveLogProb(chuai_reserve, 250));
262 if (chuai_reserve.isDrop() && chuai_reserve.ptype() == KNIGHT && 300 <= limit) {
263 if (state.hasPieceOnStand<SILVER>(Turn))
264 out.push_back(MoveLogProb(Move(chuai_reserve.to(),SILVER,Turn), 300));
265 else if (state.hasPieceOnStand<GOLD>(Turn))
266 out.push_back(MoveLogProb(Move(chuai_reserve.to(),GOLD,Turn), 300));
267 else if (state.hasPieceOnStand<BISHOP>(Turn))
268 out.push_back(MoveLogProb(Move(chuai_reserve.to(),BISHOP,Turn), 300));
269 else if (state.hasPieceOnStand<ROOK>(Turn))
270 out.push_back(MoveLogProb(Move(chuai_reserve.to(),ROOK,Turn), 300));
271 }
272 }
273 }
274 }
275
276 void osl::search::BreakThreatmate::
277 generateOpenRoad(int limit, const NumEffectState& state,
278 Square from, MoveLogProbVector& out)
279 {
280 const Piece target = state.pieceAt(from);
281 if (! target.isPiece())
282 return;
283 const Player Turn = state.turn();
284 if (target.owner() != Turn)
285 return;
286
287 const int capture_prob = 50;
288 const int default_prob = 100;
289 const int sacrifice_prob = 400;
290 if (limit < capture_prob)
291 return;
292
293 MoveVector moves;
294 GeneratePieceOnBoard::generate(Turn, state, target, moves);
295
296 BOOST_FOREACH(Move move, moves)
297 {
298 const bool capture = move.isCapture();
299 const bool sacrifice = state.hasEffectAt(alt(Turn), move.to());
300 const int prob = capture ? capture_prob
301 : (sacrifice ? sacrifice_prob : default_prob);
302 if (prob <= limit)
303 out.push_back(MoveLogProb(move, prob));
304 }
305 }
306
307 /* ------------------------------------------------------------------------- */
308 // ;;; Local Variables:
309 // ;;; mode:c++
310 // ;;; c-basic-offset:2
311 // ;;; End: