ntesukiMoveGenerator.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ntesukiMoveGenerator.cc
Go to the documentation of this file.
1 /* ntesukiMoveGenerator.cc
2 */
3 #include "osl/ntesuki/ntesukiMoveGenerator.h"
4 #include "osl/ntesuki/ntesukiRecord.h"
5 #include "osl/state/numEffectState.h"
6 #include "osl/effect_util/neighboring8Effect.h"
7 #include "osl/effect_util/neighboring25Direct.h"
8 #include "osl/move_generator/escape_.h"
9 #include "osl/move_generator/addEffect_.h"
10 #include "osl/move_classifier/canAttackInNMoves.h"
11 #include "osl/move_classifier/moveAdaptor.h"
12 #include "osl/move_classifier/safeMove.h"
13 #include "osl/move_generator/allMoves.h"
14 #include "osl/move_action/store.h"
15 #include "osl/move_action/safeFilter.h"
16 #include "osl/effect_util/effectUtil.h"
17 #include <iostream>
18 #ifdef NDEBUG
19 # include "osl/move_generator/escape_.tcc"
20 # include "osl/move_generator/capture_.tcc"
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>
77 struct CaptureHelper
78 {
79 CaptureHelper(const NumEffectState& state,
80 move_action::Store& action)
81 : state(state), action(action)
82 {
83 }
84
85 void operator()(Piece p)
86 {
87 move_generator::GenerateCapture::generate(P,state, p.square(), action);
88 }
89 private:
90 const NumEffectState& state;
91 move_action::Store& action;
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 */
106 NtesukiMoveGenerator::NtesukiMoveGenerator(bool verbose)
107 :verbose(verbose) {}
108 NtesukiMoveGenerator::~NtesukiMoveGenerator() {}
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()
132 || PlayerMoveAdaptor<SafeMove>::isMember(state, m))
133 {
134 moves.push_back(m);
135 }
136 }
137 }
138
139 }
140 template <Player T>
141 void NtesukiMoveGenerator::
142 generateWithRzone(const NumEffectState& state,
143 NtesukiRecord *record,
144 int pass_left,
145 NtesukiMoveList& moves)
146 {
147 /* 攻め方の手番で， rzone を使っての手生成. */
148 ntesuki_assert(record->turn() == T);
149 const Player O = PlayerTraits<T>::opponent;
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);
170 move_generator::AddEffect<T, true>::generate(state,
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];
223 if (move_classifier::SafeMove<T>::isMember(state,
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>
287 void NtesukiMoveGenerator::
288 generate(const NumEffectState& state,
289 NtesukiMoveList& moves)
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>
305 void NtesukiMoveGenerator::
306 setOrder(const NumEffectState& state,
307 NtesukiMoveList& moves)
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,
366 NtesukiMoveList& moves);
367 template void NtesukiMoveGenerator::generate<WHITE>(const NumEffectState& state,
368 NtesukiMoveList& moves);
369
370 template void NtesukiMoveGenerator::generateWithRzone<BLACK>(const NumEffectState& state,
371 NtesukiRecord* record,
372 int pass_left,
373 NtesukiMoveList& moves);
374 template void NtesukiMoveGenerator::generateWithRzone<WHITE>(const NumEffectState& state,
375 NtesukiRecord* record,
376 int pass_left,
377 NtesukiMoveList& moves);
378
379 }//ntesuki
380 }//osl
381
382
383 // ;;; Local Variables:
384 // ;;; mode:c++
385 // ;;; c-basic-offset:2
386 // ;;; End: