All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
breakThreatmate.cc
Go to the documentation of this file.
1 /* breakThreatmate.cc
2  */
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::
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();
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)
72  (state, my_king, threatmate_move.from(), piece.square(), store);
73  else
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()) {
84  const int num = (attack.takeOneBit()+((PtypeFuns<LANCE>::indexNum)<<5));
85  if (Turn == BLACK)
87  (state, my_king, target, state.pieceOf(num).square(), store);
88  else
90  (state, my_king, target, state.pieceOf(num).square(), store);
91  }
92  }
93 }
94 
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
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
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();
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 
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: