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::Capture<P>::generate(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 (EffectUtil::isKingInCheck(T, state))
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 (EffectUtil::isKingInCheck(T, state))
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 move_action::Store store(move_candidates);
00167 move_action::SafeFilter<T, state::NumEffectState, move_action::Store>
00168 store_safe(state, store);
00169 move_generator::AddEffect<T, true>::generate(state,
00170 targetKing,
00171 store_safe);
00172 moves = NtesukiMoveList(state, move_candidates);
00173
00174 for (NtesukiMoveList::iterator move_it = moves.begin();
00175 move_it != moves.end(); move_it++)
00176 {
00177
00178 const Move m = move_it->getMove();
00179 const Position to = m.to();
00180 const Piece atTo = state.getPieceOnBoard(to);
00181 if (m.isDrop() &&
00182 isMajor(m.ptype()) &&
00183 state.countEffect2(O, to) == 1)
00184 {
00185 move_it->setOrder(1);
00186 }
00187 else
00188 {
00189 move_it->setOrder(0);
00190 }
00191 }
00192
00193 moves.push_front(NtesukiMove(Move::PASS(T)));
00194 moves.front().setOrder(0);
00195 }
00196 else if (!record->rzone_move_generation)
00197 {
00198 return generate<T>(state, moves);
00199 }
00200 else
00201 {
00202 int rzone_order = pass_left - 1;
00203 Rzone rzone_cur = record->rzone<T>()[rzone_order];
00204 ntesuki_assert(rzone_cur.any());
00205
00206
00207 MoveVector captures;
00208 move_action::Store store(captures);
00209
00210 capture<T, ROOK>(state, store);
00211 capture<T, BISHOP>(state, store);
00212 capture<T, GOLD>(state, store);
00213 capture<T, SILVER>(state, store);
00214 capture<T, KNIGHT>(state, store);
00215 capture<T, LANCE>(state, store);
00216
00217 for (size_t i = 0; i < captures.size(); ++i)
00218 {
00219 const Move m = captures[i];
00220 if (move_classifier::SafeMove<T>::isMember(state,
00221 m.ptype(),
00222 m.from(),
00223 m.to()))
00224 {
00225 moves.add(m);
00226 }
00227 }
00228
00229
00230 for (int x = 1; x <=9; ++x)
00231 {
00232 for (int y = 1; y <=9; ++y)
00233 {
00234 bool close_to_target = false;
00235 const Position pos(x,y);
00236 if (NtesukiRecord::use_9rzone == true)
00237 {
00238 for (int dx = -1; dx <=1; dx++)
00239 {
00240 for (int dy = -1; dy <=1; dy++)
00241 {
00242 int xx = x + dx;
00243 int yy = y + dy;
00244 if (xx > 0 && xx < 10 && yy > 0 && yy < 10)
00245 {
00246 ntesuki_assert(xx >= 1 && xx <= 9);
00247 ntesuki_assert(yy >= 1 && yy <= 9);
00248 const Position pos2(xx,yy);
00249 close_to_target |= rzone_cur.test(pos2);
00250 }
00251 }
00252 }
00253 }
00254 else
00255 {
00256 close_to_target = rzone_cur.test(pos);
00257 }
00258 if (close_to_target)
00259 {
00260 MoveVector king_blocks;
00261 move_action::Store store2(king_blocks);
00262 move_action::SafeFilter<T, state::NumEffectState, move_action::Store>
00263 store_safe(state, store2);
00264 move_generator::AddEffect<T, false>::generate(state, pos, store_safe);
00265 for (size_t i = 0; i < king_blocks.size(); ++i)
00266 {
00267 const Move m = king_blocks[i];
00268 moves.add(m);
00269 }
00270 }
00271 }
00272 }
00273
00274 setOrder<T>(state, moves);
00275 moves.push_front(NtesukiMove(Move::PASS(T)));
00276 moves.front().setOrder(0);
00277 }
00278 }
00279
00280
00281 template <Player T>
00282 void NtesukiMoveGenerator::
00283 generate(const NumEffectState& state,
00284 NtesukiMoveList& moves)
00285 {
00286 MoveVector all_moves;
00287 generate_all_moves<T>(state, all_moves);
00288 moves = NtesukiMoveList(state, all_moves);
00289
00290 setOrder<T>(state, moves);
00291
00292 if (!EffectUtil::isKingInCheck(T, state))
00293 {
00294 moves.push_front(NtesukiMove(Move::PASS(T)));
00295 moves.front().setOrder(0);
00296 }
00297 }
00298
00299 template <Player T>
00300 void NtesukiMoveGenerator::
00301 setOrder(const NumEffectState& state,
00302 NtesukiMoveList& moves)
00303 {
00304 const Position opKingPosition =
00305 state.getKingPosition (alt(state.getTurn ()));
00306
00307 for (NtesukiMoveList::iterator move_it = moves.begin();
00308 move_it != moves.end(); move_it++)
00309 {
00310 if (!opKingPosition.isOnBoard())
00311 {
00312 move_it->setOrder(3);
00313 continue;
00314 }
00315 const Move m = move_it->getMove();
00316 const Position from = m.from();
00317 const Position to = m.to();
00318 const Piece atTo = state.getPieceOnBoard (to);
00319
00320
00321 if (move_it->isCheck())
00322 {
00323 move_it->setOrder(0);
00324 }
00325
00326 else if (Neighboring8Effect::hasEffect(state, m.ptypeO(), to,
00327 opKingPosition))
00328 {
00329 move_it->setOrder(1);
00330 }
00331 else if (hasEffectByBigPieces (state, state.getTurn (), from))
00332 {
00333 move_it->setOrder(1);
00334 }
00335 else if ((atTo.isPiece()) &&
00336 (atTo.owner() == alt (state.getTurn ()))&&
00337 (atTo.ptype() != PAWN))
00338 {
00339 move_it->setOrder(1);
00340 }
00341
00342 else if (Neighboring25Direct::hasEffect(state, m.ptypeO(), to,
00343 opKingPosition))
00344 {
00345 move_it->setOrder(2);
00346 }
00347 else if ((atTo.isPiece()) &&
00348 (atTo.owner() == alt (state.getTurn ())))
00349 {
00350 move_it->setOrder(2);
00351 }
00352
00353 else
00354 {
00355 move_it->setOrder(3);
00356 }
00357 }
00358 }
00359
00360 template void NtesukiMoveGenerator::generate<BLACK>(const NumEffectState& state,
00361 NtesukiMoveList& moves);
00362 template void NtesukiMoveGenerator::generate<WHITE>(const NumEffectState& state,
00363 NtesukiMoveList& moves);
00364
00365 template void NtesukiMoveGenerator::generateWithRzone<BLACK>(const NumEffectState& state,
00366 NtesukiRecord* record,
00367 int pass_left,
00368 NtesukiMoveList& moves);
00369 template void NtesukiMoveGenerator::generateWithRzone<WHITE>(const NumEffectState& state,
00370 NtesukiRecord* record,
00371 int pass_left,
00372 NtesukiMoveList& moves);
00373
00374 }
00375 }
00376
00377
00378
00379
00380
00381