00001
00002
00003 #include "osl/ntesuki/ntesukiMoveGenerator.h"
00004 #include "osl/ntesuki/ntesukiRecord.h"
00005 #include "osl/state/numEffectState.h"
00006 #include "osl/effect_util/neighboring8Effect.h"
00007 #include "osl/effect_util/neighboring25Direct.h"
00008 #include "osl/move_generator/escape_.h"
00009 #include "osl/move_generator/addEffect_.h"
00010 #include "osl/move_classifier/canAttackInNMoves.h"
00011 #include "osl/move_classifier/moveAdaptor.h"
00012 #include "osl/move_classifier/safeMove.h"
00013 #include "osl/move_generator/allMoves.h"
00014 #include "osl/move_action/store.h"
00015 #include "osl/move_action/safeFilter.h"
00016 #include "osl/effect_util/effectUtil.h"
00017 #include <iostream>
00018 #ifdef NDEBUG
00019 # include "osl/move_generator/escape_.tcc"
00020 # include "osl/move_generator/capture_.tcc"
00021 #endif
00022
00023 #include "osl/move_action/store.h"
00024
00025 namespace osl
00026 {
00027 namespace ntesuki
00028 {
00029 }
00030 }
00031
00032
00033
00034
00035
00036 namespace osl
00037 {
00038 namespace ntesuki
00039 {
00040
00041
00042
00043
00044 inline
00045 bool
00046 hasEffectByBigPieces (const NumEffectState& state,
00047 const Player player,
00048 const Position pos)
00049 {
00050 #if OSL_WORDSIZE == 64
00051 const PieceMask bigPieceMask (container::PieceMaskBase(
00052 PieceMask::numToMask (PtypeTraits<ROOK>::indexMin)
00053 | PieceMask::numToMask (PtypeTraits<ROOK>::indexMin + 1)
00054 | PieceMask::numToMask (PtypeTraits<BISHOP>::indexMin)
00055 | PieceMask::numToMask (PtypeTraits<BISHOP>::indexMin + 1)));
00056
00057 const PieceMask pieceMask = (state.getOnBoardMask (player)
00058 & state.getEffect (pos)
00059 & bigPieceMask);
00060 return pieceMask.any();
00061 #elif OSL_WORDSIZE == 32
00062
00063
00064 PieceMask bigPieceMask;
00065 bigPieceMask.set(PtypeTraits<ROOK>::indexMin);
00066 bigPieceMask.set(PtypeTraits<ROOK>::indexMin + 1);
00067 bigPieceMask.set(PtypeTraits<BISHOP>::indexMin);
00068 bigPieceMask.set(PtypeTraits<BISHOP>::indexMin + 1);
00069 const PieceMask pieceMask = (state.getOnBoardMask (player)
00070 & state.getEffect (pos)
00071 & bigPieceMask);
00072 return pieceMask.any();
00073 #endif
00074 }
00075
00076 template <Player P>
00077 struct CaptureHelper
00078 {
00079 CaptureHelper(const NumEffectState& state,
00080 move_action::Store& action)
00081 : state(state), action(action)
00082 {
00083 }
00084
00085 void operator()(Piece p)
00086 {
00087 move_generator::GenerateCapture::generate(P,state, p.position(), action);
00088 }
00089 private:
00090 const NumEffectState& state;
00091 move_action::Store& action;
00092 };
00093
00094 template <Player P, Ptype T>
00095 static
00096 void
00097 capture(const NumEffectState& state, move_action::Store action)
00098 {
00099 CaptureHelper<P> captureHelper(state, action);
00100 state.forEachOnBoard<PlayerTraits<P>::opponent, T, CaptureHelper<P> >(captureHelper);
00101 }
00102
00103
00104
00105
00106 NtesukiMoveGenerator::NtesukiMoveGenerator(bool verbose)
00107 :verbose(verbose) {}
00108 NtesukiMoveGenerator::~NtesukiMoveGenerator() {}
00109
00110 template <osl::Player T>
00111 static void
00112 generate_all_moves(const NumEffectState& state,
00113 MoveVector& moves)
00114 {
00115 if (state.inCheck(T))
00116 {
00117
00118 GenerateEscapeKing::generate(state, moves);
00119 }
00120 else
00121 {
00122 MoveVector all_moves;
00123
00124 GenerateAllMoves::generate(T, state, all_moves);
00125
00126
00127 using namespace osl::move_classifier;
00128 for (unsigned int i=0; i<all_moves.size(); ++i)
00129 {
00130 const Move m = all_moves[i];
00131 if (m.isDrop()
00132 || PlayerMoveAdaptor<SafeMove>::isMember(state, m))
00133 {
00134 moves.push_back(m);
00135 }
00136 }
00137 }
00138
00139 }
00140 template <Player T>
00141 void NtesukiMoveGenerator::
00142 generateWithRzone(const NumEffectState& state,
00143 NtesukiRecord *record,
00144 int pass_left,
00145 NtesukiMoveList& moves)
00146 {
00147
00148 ntesuki_assert(record->turn() == T);
00149 const Player O = PlayerTraits<T>::opponent;
00150
00151 const Position targetKing
00152 = state.getKingPosition<O>();
00153 if (state.inCheck(T))
00154 {
00155
00156 MoveVector move_candidates;
00157 GenerateEscapeKing::generate(state, move_candidates);
00158 moves = NtesukiMoveList(state, move_candidates);
00159
00160 setOrder<T>(state, moves);
00161 }
00162 else if (pass_left == 0)
00163 {
00164
00165 MoveVector move_candidates;
00166 {
00167 move_action::Store store(move_candidates);
00168 move_action::SafeFilter<T, move_action::Store>
00169 store_safe(state, store);
00170 move_generator::AddEffect<T, true>::generate(state,
00171 targetKing,
00172 store_safe);
00173 }
00174 moves = NtesukiMoveList(state, move_candidates);
00175
00176 for (NtesukiMoveList::iterator move_it = moves.begin();
00177 move_it != moves.end(); move_it++)
00178 {
00179
00180 const Move m = move_it->getMove();
00181 const Position to = m.to();
00182 const Piece atTo = state.getPieceOnBoard(to);
00183 if (m.isDrop() &&
00184 isMajor(m.ptype()) &&
00185 state.countEffect2(O, to) == 1)
00186 {
00187 move_it->setOrder(1);
00188 }
00189 else
00190 {
00191 move_it->setOrder(0);
00192 }
00193 }
00194
00195 moves.push_front(NtesukiMove(Move::PASS(T)));
00196 moves.front().setOrder(0);
00197 }
00198 else if (!record->rzone_move_generation)
00199 {
00200 return generate<T>(state, moves);
00201 }
00202 else
00203 {
00204 int rzone_order = pass_left - 1;
00205 Rzone rzone_cur = record->rzone<T>()[rzone_order];
00206 ntesuki_assert(rzone_cur.any());
00207
00208
00209 MoveVector captures;
00210 {
00211 move_action::Store store(captures);
00212
00213 capture<T, ROOK>(state, store);
00214 capture<T, BISHOP>(state, store);
00215 capture<T, GOLD>(state, store);
00216 capture<T, SILVER>(state, store);
00217 capture<T, KNIGHT>(state, store);
00218 capture<T, LANCE>(state, store);
00219 }
00220 for (size_t i = 0; i < captures.size(); ++i)
00221 {
00222 const Move m = captures[i];
00223 if (move_classifier::SafeMove<T>::isMember(state,
00224 m.ptype(),
00225 m.from(),
00226 m.to()))
00227 {
00228 moves.add(m);
00229 }
00230 }
00231
00232
00233 for (int x = 1; x <=9; ++x)
00234 {
00235 for (int y = 1; y <=9; ++y)
00236 {
00237 bool close_to_target = false;
00238 const Position pos(x,y);
00239 if (NtesukiRecord::use_9rzone == true)
00240 {
00241 for (int dx = -1; dx <=1; dx++)
00242 {
00243 for (int dy = -1; dy <=1; dy++)
00244 {
00245 int xx = x + dx;
00246 int yy = y + dy;
00247 if (xx > 0 && xx < 10 && yy > 0 && yy < 10)
00248 {
00249 ntesuki_assert(xx >= 1 && xx <= 9);
00250 ntesuki_assert(yy >= 1 && yy <= 9);
00251 const Position pos2(xx,yy);
00252 close_to_target |= rzone_cur.test(pos2);
00253 }
00254 }
00255 }
00256 }
00257 else
00258 {
00259 close_to_target = rzone_cur.test(pos);
00260 }
00261 if (close_to_target)
00262 {
00263 MoveVector king_blocks;
00264 {
00265 move_action::Store store2(king_blocks);
00266 move_action::SafeFilter<T, move_action::Store>
00267 store_safe(state, store2);
00268 move_generator::AddEffect<T, false>::generate(state, pos, store_safe);
00269 }
00270 for (size_t i = 0; i < king_blocks.size(); ++i)
00271 {
00272 const Move m = king_blocks[i];
00273 moves.add(m);
00274 }
00275 }
00276 }
00277 }
00278
00279 setOrder<T>(state, moves);
00280 moves.push_front(NtesukiMove(Move::PASS(T)));
00281 moves.front().setOrder(0);
00282 }
00283 }
00284
00285
00286 template <Player T>
00287 void NtesukiMoveGenerator::
00288 generate(const NumEffectState& state,
00289 NtesukiMoveList& moves)
00290 {
00291 MoveVector all_moves;
00292 generate_all_moves<T>(state, all_moves);
00293 moves = NtesukiMoveList(state, all_moves);
00294
00295 setOrder<T>(state, moves);
00296
00297 if (!state.inCheck(T))
00298 {
00299 moves.push_front(NtesukiMove(Move::PASS(T)));
00300 moves.front().setOrder(0);
00301 }
00302 }
00303
00304 template <Player T>
00305 void NtesukiMoveGenerator::
00306 setOrder(const NumEffectState& state,
00307 NtesukiMoveList& moves)
00308 {
00309 const Position opKingPosition =
00310 state.getKingPosition (alt(state.getTurn ()));
00311
00312 for (NtesukiMoveList::iterator move_it = moves.begin();
00313 move_it != moves.end(); move_it++)
00314 {
00315 if (!opKingPosition.isOnBoard())
00316 {
00317 move_it->setOrder(3);
00318 continue;
00319 }
00320 const Move m = move_it->getMove();
00321 const Position from = m.from();
00322 const Position to = m.to();
00323 const Piece atTo = state.getPieceOnBoard (to);
00324
00325
00326 if (move_it->isCheck())
00327 {
00328 move_it->setOrder(0);
00329 }
00330
00331 else if (Neighboring8Effect::hasEffect(state, m.ptypeO(), to,
00332 opKingPosition))
00333 {
00334 move_it->setOrder(1);
00335 }
00336 else if (hasEffectByBigPieces (state, state.getTurn (), from))
00337 {
00338 move_it->setOrder(1);
00339 }
00340 else if ((atTo.isPiece()) &&
00341 (atTo.owner() == alt (state.getTurn ()))&&
00342 (atTo.ptype() != PAWN))
00343 {
00344 move_it->setOrder(1);
00345 }
00346
00347 else if (Neighboring25Direct::hasEffect(state, m.ptypeO(), to,
00348 opKingPosition))
00349 {
00350 move_it->setOrder(2);
00351 }
00352 else if ((atTo.isPiece()) &&
00353 (atTo.owner() == alt (state.getTurn ())))
00354 {
00355 move_it->setOrder(2);
00356 }
00357
00358 else
00359 {
00360 move_it->setOrder(3);
00361 }
00362 }
00363 }
00364
00365 template void NtesukiMoveGenerator::generate<BLACK>(const NumEffectState& state,
00366 NtesukiMoveList& moves);
00367 template void NtesukiMoveGenerator::generate<WHITE>(const NumEffectState& state,
00368 NtesukiMoveList& moves);
00369
00370 template void NtesukiMoveGenerator::generateWithRzone<BLACK>(const NumEffectState& state,
00371 NtesukiRecord* record,
00372 int pass_left,
00373 NtesukiMoveList& moves);
00374 template void NtesukiMoveGenerator::generateWithRzone<WHITE>(const NumEffectState& state,
00375 NtesukiRecord* record,
00376 int pass_left,
00377 NtesukiMoveList& moves);
00378
00379 }
00380 }
00381
00382
00383
00384
00385
00386