All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ntesukiMoveGenerator.cc
Go to the documentation of this file.
1 /* ntesukiMoveGenerator.cc
2  */
14 #include "osl/move_action/store.h"
15 #include "osl/move_action/safeFilter.h"
17 #include <iostream>
18 #ifdef NDEBUG
21 #endif
22 
23 #include "osl/move_action/store.h"
24 
25 namespace osl
26 {
27  namespace ntesuki
28  {
29  }
30 }
31 
32 /*
33  * n 手すき探索で用いる move generator.
34  */
35 
36 namespace osl
37 {
38  namespace ntesuki
39  {
40  /* ----------------------------------------------------------------------
41  * Utility
42  * ----------------------------------------------------------------------
43  */
44  inline
45  bool
46  hasEffectByBigPieces (const NumEffectState& state,
47  const Player player,
48  const Square pos)
49  {
50 #if OSL_WORDSIZE == 64
51  const PieceMask bigPieceMask (container::PieceMaskBase(
52  PieceMask::numToMask (PtypeTraits<ROOK>::indexMin)
53  | PieceMask::numToMask (PtypeTraits<ROOK>::indexMin + 1)
54  | PieceMask::numToMask (PtypeTraits<BISHOP>::indexMin)
55  | PieceMask::numToMask (PtypeTraits<BISHOP>::indexMin + 1)));
56 
57  const PieceMask pieceMask = (state.piecesOnBoard (player)
58  & state.effectAt (pos)
59  & bigPieceMask);
60  return pieceMask.any();
61 #elif OSL_WORDSIZE == 32
62  // TODO: 多分このコードで64bit 環境と共通にできると思うんだけど
63  // 締切まではそのままに
64  PieceMask bigPieceMask;
65  bigPieceMask.set(PtypeTraits<ROOK>::indexMin);
66  bigPieceMask.set(PtypeTraits<ROOK>::indexMin + 1);
67  bigPieceMask.set(PtypeTraits<BISHOP>::indexMin);
68  bigPieceMask.set(PtypeTraits<BISHOP>::indexMin + 1);
69  const PieceMask pieceMask = (state.piecesOnBoard (player)
70  & state.effectAt (pos)
71  & bigPieceMask);
72  return pieceMask.any();
73 #endif
74  }
75 
76  template <Player P>
78  {
79  CaptureHelper(const NumEffectState& state,
81  : state(state), action(action)
82  {
83  }
84 
85  void operator()(Piece p)
86  {
88  }
89  private:
90  const NumEffectState& state;
92  };
93 
94  template <Player P, Ptype T>
95  static
96  void
97  capture(const NumEffectState& state, move_action::Store action)
98  {
99  CaptureHelper<P> captureHelper(state, action);
100  state.forEachOnBoard<PlayerTraits<P>::opponent, T, CaptureHelper<P> >(captureHelper);
101  }
102 
103 
104  /* NtesukiMoveGenerator
105  */
107  :verbose(verbose) {}
109 
110  template <osl::Player T>
111  static void
112  generate_all_moves(const NumEffectState& state,
113  MoveVector& moves)
114  {
115  if (state.inCheck(T))
116  {
117  // 王手がかかっている時は防ぐ手のみを生成
118  GenerateEscapeKing::generate(state, moves);
119  }
120  else
121  {
122  MoveVector all_moves;
123  // そうでなければ全ての手を生成
124  GenerateAllMoves::generate(T, state, all_moves);
125  // この指手は,玉の素抜きがあったり,打歩詰の可能性があるので
126  // 確認が必要
127  using namespace osl::move_classifier;
128  for (unsigned int i=0; i<all_moves.size(); ++i)
129  {
130  const Move m = all_moves[i];
131  if (m.isDrop()
133  {
134  moves.push_back(m);
135  }
136  }
137  }
138 
139  }
140  template <Player T>
142  generateWithRzone(const NumEffectState& state,
143  NtesukiRecord *record,
144  int pass_left,
146  {
147  /* 攻め方の手番で, rzone を使っての手生成. */
148  ntesuki_assert(record->turn() == T);
150 
151  const Square targetKing
152  = state.kingSquare<O>();
153  if (state.inCheck(T))
154  {
155  /* 自玉に王手がかかっている場合は,全合法手を生成 */
156  MoveVector move_candidates;
157  GenerateEscapeKing::generate(state, move_candidates);
158  moves = NtesukiMoveList(state, move_candidates);
159 
160  setOrder<T>(state, moves);
161  }
162  else if (pass_left == 0)
163  {
164  /* 詰み探索の場合には,王手のみ生成 */
165  MoveVector move_candidates;
166  {
167  move_action::Store store(move_candidates);
168  move_action::SafeFilter<T, move_action::Store>
169  store_safe(state, store);
171  targetKing,
172  store_safe);
173  }
174  moves = NtesukiMoveList(state, move_candidates);
175 
176  for (NtesukiMoveList::iterator move_it = moves.begin();
177  move_it != moves.end(); move_it++)
178  {
179  /* 大駒のただ捨ては遅らせる */
180  const Move m = move_it->getMove();
181  const Square to = m.to();
182  const Piece atTo = state.pieceOnBoard(to);
183  if (m.isDrop() &&
184  isMajor(m.ptype()) &&
185  state.countEffect2(O, to) == 1)
186  {
187  move_it->setOrder(1);
188  }
189  else
190  {
191  move_it->setOrder(0);
192  }
193  }
194 
195  moves.push_front(NtesukiMove(Move::PASS(T)));
196  moves.front().setOrder(0);
197  }
198  else if (!record->rzone_move_generation)
199  {
200  return generate<T>(state, moves);
201  }
202  else
203  {
204  int rzone_order = pass_left - 1;
205  Rzone rzone_cur = record->rzone<T>()[rzone_order];
206  ntesuki_assert(rzone_cur.any());
207 
208  /* 取る手を生成 */
209  MoveVector captures;
210  {
211  move_action::Store store(captures);
212 
213  capture<T, ROOK>(state, store);
214  capture<T, BISHOP>(state, store);
215  capture<T, GOLD>(state, store);
216  capture<T, SILVER>(state, store);
217  capture<T, KNIGHT>(state, store);
218  capture<T, LANCE>(state, store);
219  }
220  for (size_t i = 0; i < captures.size(); ++i)
221  {
222  const Move m = captures[i];
224  m.ptype(),
225  m.from(),
226  m.to()))
227  {
228  moves.add(m);
229  }
230  }
231 
232  /* 玉が逃げそうな位置に利きをつける手を生成 */
233  for (int x = 1; x <=9; ++x)
234  {
235  for (int y = 1; y <=9; ++y)
236  {
237  bool close_to_target = false;
238  const Square pos(x,y);
239  if (NtesukiRecord::use_9rzone == true)
240  {
241  for (int dx = -1; dx <=1; dx++)
242  {
243  for (int dy = -1; dy <=1; dy++)
244  {
245  int xx = x + dx;
246  int yy = y + dy;
247  if (xx > 0 && xx < 10 && yy > 0 && yy < 10)
248  {
249  ntesuki_assert(xx >= 1 && xx <= 9);
250  ntesuki_assert(yy >= 1 && yy <= 9);
251  const Square pos2(xx,yy);
252  close_to_target |= rzone_cur.test(pos2);
253  }
254  }
255  }
256  }
257  else
258  {
259  close_to_target = rzone_cur.test(pos);
260  }
261  if (close_to_target)
262  {
263  MoveVector king_blocks;
264  {
265  move_action::Store store2(king_blocks);
266  move_action::SafeFilter<T, move_action::Store>
267  store_safe(state, store2);
268  move_generator::AddEffect<T, false>::generate(state, pos, store_safe);
269  }
270  for (size_t i = 0; i < king_blocks.size(); ++i)
271  {
272  const Move m = king_blocks[i];
273  moves.add(m);
274  }
275  }
276  }
277  }
278 
279  setOrder<T>(state, moves);
280  moves.push_front(NtesukiMove(Move::PASS(T)));
281  moves.front().setOrder(0);
282  }
283  }
284 
285 
286  template <Player T>
288  generate(const NumEffectState& state,
290  {
291  MoveVector all_moves;
292  generate_all_moves<T>(state, all_moves);
293  moves = NtesukiMoveList(state, all_moves);
294 
295  setOrder<T>(state, moves);
296 
297  if (!state.inCheck(T))
298  {
299  moves.push_front(NtesukiMove(Move::PASS(T)));
300  moves.front().setOrder(0);
301  }
302  }//generate
303 
304  template <Player T>
306  setOrder(const NumEffectState& state,
308  {
309  const Square opKingSquare =
310  state.kingSquare (alt(state.turn ()));
311 
312  for (NtesukiMoveList::iterator move_it = moves.begin();
313  move_it != moves.end(); move_it++)
314  {
315  if (!opKingSquare.isOnBoard())
316  {
317  move_it->setOrder(3);
318  continue;
319  }
320  const Move m = move_it->getMove();
321  const Square from = m.from();
322  const Square to = m.to();
323  const Piece atTo = state.pieceOnBoard (to);
324 
325  /* order == 0 : 王手 */
326  if (move_it->isCheck())
327  {
328  move_it->setOrder(0);
329  }
330  /* order == 1 : 王の近傍への利き, 大駒の道, 小駒以外を取る */
331  else if (Neighboring8Effect::hasEffect(state, m.ptypeO(), to,
332  opKingSquare))
333  {
334  move_it->setOrder(1);
335  }
336  else if (hasEffectByBigPieces (state, state.turn (), from))
337  {
338  move_it->setOrder(1);
339  }
340  else if ((atTo.isPiece()) &&
341  (atTo.owner() == alt (state.turn ()))&&
342  (atTo.ptype() != PAWN))
343  {
344  move_it->setOrder(1);
345  }
346  /* order == 2 : 王の25近傍,小駒を取る */
347  else if (Neighboring25Direct::hasEffect(state, m.ptypeO(), to,
348  opKingSquare))
349  {
350  move_it->setOrder(2);
351  }
352  else if ((atTo.isPiece()) &&
353  (atTo.owner() == alt (state.turn ())))
354  {
355  move_it->setOrder(2);
356  }
357  /* order > 2 : それ以外の手 */
358  else
359  {
360  move_it->setOrder(3);
361  }
362  }
363  }
364 
365  template void NtesukiMoveGenerator::generate<BLACK>(const NumEffectState& state,
367  template void NtesukiMoveGenerator::generate<WHITE>(const NumEffectState& state,
369 
370  template void NtesukiMoveGenerator::generateWithRzone<BLACK>(const NumEffectState& state,
371  NtesukiRecord* record,
372  int pass_left,
374  template void NtesukiMoveGenerator::generateWithRzone<WHITE>(const NumEffectState& state,
375  NtesukiRecord* record,
376  int pass_left,
378 
379  }//ntesuki
380 }//osl
381 
382 
383 // ;;; Local Variables:
384 // ;;; mode:c++
385 // ;;; c-basic-offset:2
386 // ;;; End: