All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
oracleProverLight.tcc
Go to the documentation of this file.
1 /* oracleProverLight.tcc
2  */
9 #include "osl/apply_move/applyMoveWithPath.h"
12 #ifdef NDEBUG
15 //# include "osl/move_generator/escape.tcc"
16 #endif
17 
18 using namespace osl;
19 using namespace osl::ntesuki;
20 
21 /* Helper classes
22  */
23 template <class Searcher, Player P>
24 class
27 {
30  unsigned int pass_left;
31 public:
32  bool result;
33 
35  const NtesukiRecord* record_orig,
36  unsigned int pass_left)
37  : searcher(searcher), record_orig(record_orig), pass_left(pass_left)
38  {}
39 
41  {
43  result = (*searcher).template defense<O>(record_orig, pass_left);
44  }
45 };
46 
47 template <class Searcher, Player P>
50 {
53  unsigned int pass_left;
54 
55 public:
56  bool result;
57 
59  const NtesukiRecord* record_orig,
60  unsigned int pass_left)
61  : searcher(searcher), record_orig(record_orig), pass_left(pass_left)
62  {}
63 
65  {
67  result = (*searcher).template attack<O>(record_orig, pass_left);
68  }
69 };
70 
71 /* Utility
72  */
73 
74 /* Still cannot see if is safe move */
75 template <Player P>
76 static bool
78  const osl::Move& m,
79  int pass_left)
80 {
81  if (!m.isValid()) return false;
82  if (!state.isValidMove(m, false)) return false;
83  if (m.isDrop()) return true;
84  return move_classifier::SafeMove<P>::isMember(state, m.ptype(), m.from(), m.to());
85 }
86 
87 /* adjust the captuer ptype of a move */
88 template <Player P>
89 static osl::Move
91  osl::Move candidate)
92 {
93  if (! candidate.isDrop())
94  {
95  const osl::Piece p = state.pieceOnBoard(candidate.to());
96  candidate=setCapture(candidate,p);
97  }
98  return candidate;
99 }
100 
101 
102 /* The worker
103  */
104 
105 /* attack */
106 template <Player P>
107 bool
108 OracleProverLight::
109 attack(const NtesukiRecord* record_orig,
110  const unsigned int pass_left)
111 {
112  const Player attacker = P;
113  ntesuki_assert(P == state.turn());
114 
115  if (!record_orig ||
116  !record_orig->getValue<attacker>(pass_left)
117  .isCheckmateSuccess() ||
118  !record_orig->getBestMove<attacker>(pass_left).isValid())
119  {
120  return false;
121  }
122 
123  Move check_move;
124  FixedDepthSearcher fixed_searcher(state);
125 
126  if (!state.inCheck(P) &&
127  fixed_searcher.hasCheckmateMove<P>(NtesukiRecord::fixed_search_depth,
128  check_move).isCheckmateSuccess())
129  {
130  /* Immediate Checkmate */
131  return true;
132  }
133 
134  /* Simulation 元が immediate checkmate ならこの先は simulate できない */
135  const NtesukiMove best_move_orig = record_orig->getBestMove<attacker>(pass_left);
136  if (best_move_orig.isImmediateCheckmate())
137  {
138  return false;
139  }
140 
141  /* n が少ないときの結果を参照 */
142  if ((pass_left > 0) &&
143  record_orig->getValue<attacker>(pass_left - 1).isCheckmateSuccess())
144  {
145  return attack<P>(record_orig, pass_left - 1);
146  }
147 
148  const Move move = adjustMove<P>(state, best_move_orig.move());
149 
150  /* invalid move となってしまった */
151  if (!is_safe_move<P>(state, move, pass_left))
152  {
153  return false;
154  }
156  isMember(state, move));
157  /* 即詰探索中は王手のみ読む */
158  if(0 == pass_left && !move_is_check)
159  {
160  return false;
161  }
162 
163  /* 以前は check だったのが今は違ってしまった・その逆 */
164  if (best_move_orig.isCheck() != move_is_check)
165  {
166  return false;
167  }
168 
169  /* 以前の bestMove を実行 */
170  const NtesukiRecord* record_child_orig = table.findWithMoveConst(record_orig,
171  best_move_orig);
172  if (!record_child_orig)
173  {
174  //ntesuki_assert (record_orig->isBySimulation());
175  return false;
176  }
177  //ntesuki_assert(record_child_orig);
178 
180  record_child_orig,
181  pass_left);
182  TRY_DFPN;
183  ApplyMoveWithPath<P>::doUndoMove(state, path, move, helper);
184  CATCH_DFPN;
185 
186  return helper.result;
187 }
188 
189 /* defense */
190 template <Player P>
191 bool OracleProverLight::
192 defense(const NtesukiRecord* record_orig,
193  const unsigned int pass_left)
194 {
195  const Player attacker = PlayerTraits<P>::opponent;
196 
197  ntesuki_assert(P == state.turn());
198  if (!record_orig ||
199  !record_orig->getValue<attacker>(pass_left)
201  {
202  return false;
203  }
204 
205  /* 攻撃側に王手がかかっていないか調べる */
206  if (state.inCheck(attacker))
207  {
208  return false;
209  }
210 
211  /* 現在王手になっているかどうか */
212  if ((pass_left == 0) &&
213  !state.inCheck(P))
214  {
215  return false;
216  }
217 
218  /* n が少ないときの結果を参照 */
219  if (pass_left > 0 &&
220  record_orig->getValue<attacker>(pass_left - 1).isCheckmateSuccess())
221  {
222  return defense<P>(record_orig, pass_left - 1);
223  }
224 
225  /* 手の生成 */
227  mg->generateSlow(P, state, moves);
228  if (moves.empty()) return true;
229 
230  /* 受ける手の実行 */
231  for (NtesukiMoveList::iterator move_it = moves.begin();
232  move_it != moves.end(); move_it++)
233  {
234  NtesukiMove& move = *move_it;
235  if (isscheme != NtesukiRecord::normal_is &&
236  isscheme != NtesukiRecord::delay_is &&
237  move.isCheck() && pass_left > 0) continue;
238 
239  ntesuki_assert(move.isPass() || move.isNormal());
240 
241  const NtesukiRecord *record_child_orig = table.findWithMoveConst(record_orig, move);
242  if (!record_child_orig ||
243  !record_child_orig->getValue<attacker>(pass_left).isCheckmateSuccess())
244  {
245  return false;
246  }
247 
248  int pass_left_child = pass_left;
249  if (move.isPass()) --pass_left_child;
250  DefenseHelper<OracleProverLight, P> helper(this, record_child_orig, pass_left_child);
251  TRY_DFPN;
252  ApplyMoveWithPath<P>::doUndoMoveOrPass(state, path, move.move(), helper);
253  CATCH_DFPN;
254  if (false == helper.result) return false;
255  }
256 
257  return true;
258 }
259 
260 /* Publice interface
261  */
262 template <Player P>
263 bool
264 OracleProverLight::
265 startFromAttack(NtesukiRecord* record,
266  const NtesukiRecord* record_orig,
267  const unsigned int pass_left)
268 {
269  const Player attacker = P;
270  if (!record || !record_orig) return false;
271 
272  if (!record->getPieceStand<attacker>().isSuperiorOrEqualTo
273  (record_orig->getPDPieces<attacker>(pass_left)))
274  {
275  return false;
276  }
277 
278  ntesuki_assert(record_orig->getValue<attacker>(pass_left).isCheckmateSuccess());
279 
280  if (attack<P>(record_orig, pass_left))
281  {
282 #ifndef NDEBUG
283  const NtesukiMove m = (record_orig->getBestMove<attacker>(pass_left));
284  ntesuki_assert(m.isValid());
286 #endif
287 
288  TRY_DFPN;
289  const PieceStand ps = record->getPieceStand<attacker>();
290  record->setResult<attacker>(pass_left, ProofDisproof::Checkmate(),
291  record_orig->getBestMove<attacker>(pass_left),
292  true, &ps);
293  CATCH_DFPN;
294  return true;
295  }
296  return false;
297 }
298 
299 template <Player P>
300 bool
301 OracleProverLight::
302 startFromDefense(NtesukiRecord* record,
303  const NtesukiRecord* record_orig,
304  const unsigned int pass_left)
305 {
306  const Player attacker = PlayerTraits<P>::opponent;
307  if (!record || !record_orig) return false;
308 
309  if (!record->getPieceStand<attacker>().isSuperiorOrEqualTo
310  (record_orig->getPDPieces<attacker>(pass_left)))
311  {
312  return false;
313  }
314 
315  ntesuki_assert(record_orig->getValue<attacker>(pass_left).isCheckmateSuccess());
316 
317  if (defense<P>(record_orig, pass_left))
318  {
319  TRY_DFPN;
320  const PieceStand ps = record->getPieceStand<attacker>();
321  record->setResult<attacker>(pass_left, ProofDisproof::Checkmate(),
322  record_orig->getBestMove<attacker>(pass_left),
323  true, &ps);
324  CATCH_DFPN;
325  return true;
326  }
327  return false;
328 }
329 
330 // ;;; Local Variables:
331 // ;;; mode:c++
332 // ;;; c-basic-offset:2
333 // ;;; End: