All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ntesukiRecord.tcc
Go to the documentation of this file.
1 #include "ntesukiRecord.h"
12 #include "osl/pieceStand.h"
13 
14 template <osl::Player P>
15 void
17 propagate_proof(int pass_left)
18 {
19  for (RecordList::iterator it = same_board_list->begin();
20  it != same_board_list->end(); it++)
21  {
22  if (&(*it) == this)
23  {
24  continue;
25  }
26  if (it->isDominatedByProofPieces<P>(this, pass_left))
27  {
28  if (!it->getValue<P>(pass_left).isFinal())
29  {
30  PieceStand ps = getPDPieces<P>(pass_left);
31  TRY_DFPN;
32  it->setResult<P>(pass_left, getValue<P>(pass_left),
33  getBestMove<P>(pass_left),
34  false, &ps);
35  CATCH_DFPN;
36  }
37  else
38  {
39  if (!it->getValue<P>(pass_left).isCheckmateSuccess())
40  {
41 #ifdef DEBUG
42  std::cerr << <"for " < P << "\tat pass_left:" << pass_left << "\tcontradiction occured\n" << *it << *this;
43  ntesuki_assert(pass_left >0 ||
44  it->getValue<P>(pass_left) == ProofDisproof::LoopDetection() ||
45  getValue<P>(pass_left) == ProofDisproof::LoopDetection());
46 #endif
47  }
48  }
49  }
50  }
51 }
52 
53 template <osl::Player P>
54 void
56 propagate_disproof(int pass_left)
57 {
58  for (RecordList::iterator it = same_board_list->begin();
59  it != same_board_list->end(); it++)
60  {
61  if (&(*it) == this)
62  {
63  continue;
64  }
65  if (it->isDominatedByDisproofPieces<P>(this, pass_left))
66  {
67  if (!it->getValue<P>(pass_left).isFinal())
68  {
69  PieceStand ps = getPDPieces<P>(pass_left);
70  TRY_DFPN;
71  it->setResult<P>(pass_left, getValue<P>(pass_left),
72  getBestMove<P>(pass_left),
73  false, &ps);
74  CATCH_DFPN;
75  }
76  else
77  {
78  if (!it->getValue<P>(pass_left).isCheckmateFail())
79  {
80 #ifdef DEBUG
81  std::cerr << <"for " < P << "\tat pass_left:" << pass_left << "\tcontradiction occured\n" << *it << *this;
82  ntesuki_assert(it->getValue<P>(pass_left) == ProofDisproof::LoopDetection() ||
83  getValue<P>(pass_left) == ProofDisproof::LoopDetection());
84 #endif
85  }
86  }
87  }
88  }
89 }
90 
91 namespace osl
92 {
93  namespace ntesuki
94  {
95  template <class NumEffectState>
96  Ptype getCheapestDrop(Player turn, const NumEffectState& state)
97  {
98  if (state.hasPieceOnStand(turn, PAWN))
99  return PAWN;
100  if (state.hasPieceOnStand(turn, LANCE))
101  return LANCE;
102  if (state.hasPieceOnStand(turn, KNIGHT))
103  return KNIGHT;
104  if (state.hasPieceOnStand(turn, SILVER))
105  return SILVER;
106  if (state.hasPieceOnStand(turn, GOLD))
107  return GOLD;
108  if (state.hasPieceOnStand(turn, BISHOP))
109  return BISHOP;
110  if (state.hasPieceOnStand(turn, ROOK))
111  return ROOK;
112  return PTYPE_EMPTY;
113  }
114  template <class NumEffectState>
115  Ptype getSecondCheapestDrop(Player turn, const NumEffectState& state,
116  Ptype cheapest)
117  {
118  if (cheapest == PAWN)
119  {
120  if (state.hasPieceOnStand(turn, LANCE))
121  return LANCE;
122  if (state.hasPieceOnStand(turn, KNIGHT))
123  return KNIGHT;
124  if (state.hasPieceOnStand(turn, SILVER))
125  return SILVER;
126  if (state.hasPieceOnStand(turn, GOLD))
127  return GOLD;
128  if (state.hasPieceOnStand(turn, BISHOP))
129  return BISHOP;
130  if (state.hasPieceOnStand(turn, ROOK))
131  return ROOK;
132  }
133  return PTYPE_EMPTY;
134  }
135  }
136 }
137 
138 /* ノードの準備
139  * - 深さ固定 checkmate searcher を呼び出す
140  */
141 template <osl::Player T>
142 bool
145 {
146  ntesuki_assert(state->turn() == turn());
147 #ifndef NDEBUG
149 #endif
150  const bool under_attack = state->inCheck(T);
151 
152  ntesuki_assert(!state->inCheck(O));
153 
154  if (already_set_up)
155  {
156  return false;
157  }
158  already_set_up = true;
159 
160  /* 黒が攻めるときの Rzone は白の玉の位置 */
161  rzone<BLACK>()[0] = Rzone(*state, WHITE);
162  rzone<BLACK>()[1] = rzone<BLACK>()[0];
163  /* 白が攻めるときの Rzone は黒の玉の位置 */
164  rzone<WHITE>()[0] = Rzone(*state, BLACK);
165  rzone<WHITE>()[1] = rzone<WHITE>()[0];
166 
167  if (!under_attack)
168  {
169  setUpAttackNode<T>();
170  }
171  else
172  {
173  setUpDefenseNode<T>();
174  }
175  return true;
176 }
177 
178 template <osl::Player T>
179 void
182 {
184 
185  /* 王手がかかっていないときは,相手の手番の即詰は失敗している.
186  */
187  NtesukiMove pass(Move::PASS(T));
188  values<O>()[0] = ProofDisproof::NoCheckmate();
189  best_move<O>()[0] = pass;
190 
191  if (!values<T>()[0].isFinal() &&
192  state->template kingSquare<O>().isOnBoard())
193  {
194  /* 深さ固定 checkmate searcher を呼び出す */
195  FixedDepthSearcher fixed_searcher(*state);
196  PieceStand proof_pieces;
197  Move check_move;
198 
199  const NtesukiResult result_fixed =
200  fixed_searcher.hasCheckmateMove<T>(fixed_search_depth,
201  check_move,
202  proof_pieces);
203  if (result_fixed.isCheckmateSuccess())
204  {
205  NtesukiMove best_move(check_move);
206  best_move.setCheck();
207  best_move.setImmediateCheckmate<T>();
208 
209  TRY_DFPN;
210  setResult<T>(0, result_fixed,
211  best_move, false, &proof_pieces);
212  CATCH_DFPN;
213 
214  }
215  else if (result_fixed.isCheckmateFail())
216  {
217  PieceStand disproof_pieces = getPieceStand<O>();
218  TRY_DFPN;
219  setResult<T>(0, result_fixed,
220  NtesukiMove::INVALID(), false, &disproof_pieces);
221  CATCH_DFPN;
222  }
223  else
224  {
225  TRY_DFPN;
226  setResult<T>(0, result_fixed,
227  NtesukiMove::INVALID(), false);
228  if (!values<T>()[1].isFinal())
229  {
230  setResult<T>(1, ProofDisproof(1, result_fixed.disproof()),
231  NtesukiMove::INVALID(), false);
232  }
233  CATCH_DFPN;
234  }
235  }
236 }
237 
238 template <osl::Player T>
239 void
242 {
244 
245  /* 王手がかかっているので自動的に相手からの n 手すきがかかっている.
246  */
247  for (size_t i = 0; i < SIZE; ++i)
248  {
249  setNtesuki<O>(i);
250  }
251 
252  /* もし自玉が盤面上にあるのなら, fixed depth searcher を呼び出す */
253  if (!values<O>()[0].isFinal() &&
254  state->template kingSquare<T>().isOnBoard())
255  {
256  /* 深さ固定 checkmate searcher を呼び出す */
257  FixedDepthSearcher fixed_searcher(*state);
258  PieceStand proof_pieces;
259  //when called with Move::INVALID() as last move, PawnDropCheckmate is not checked for
260  // the last move
261  const NtesukiResult result_fixed =
262  fixed_searcher.hasEscapeMove<O>(Move::INVALID(),
263  fixed_search_depth,
264  proof_pieces);
265  if (result_fixed.isCheckmateSuccess())
266  {
267  TRY_DFPN;
268  setResult<O>(0, result_fixed,
269  NtesukiMove::INVALID(), false, &proof_pieces);
270  CATCH_DFPN;
271  }
272  else if (result_fixed.isCheckmateFail())
273  {
274  PieceStand disproof_pieces = getPieceStand<T>();
275  NtesukiMove best_move = NtesukiMove::INVALID();
276  /* might want to know the true best move, or
277  mark best move as immediateCheckmate */
278  TRY_DFPN;
279  setResult<O>(0, result_fixed,
280  best_move, false, &disproof_pieces);
281  CATCH_DFPN;
282  }
283  else
284  {
285  TRY_DFPN;
286  setResult<O>(0, result_fixed,
287  NtesukiMove::INVALID(), false);
288  if (!values<O>()[1].isFinal())
289  {
290  setResult<O>(1, ProofDisproof(1, result_fixed.disproof()),
291  NtesukiMove::INVALID(), false);
292  }
293  CATCH_DFPN;
294  }
295  }
296 }
297 
298 /* 手生成を行う
299  */
300 template <osl::Player P>
301 void
304  int pass_left,
305  bool all_moves)
306 {
308 
309  if (all_moves)
310  {
311  mg->generateSlow(P, *state, move_list);
312  }
313  else
314  {
315  mg->generateWithRzoneSlow(P, *state, this, pass_left, move_list);
316  }
317  const Ptype cheapest = getCheapestDrop(P, *state);
318  const Ptype secondCheapest = getSecondCheapestDrop(P, *state, cheapest);
319 
320  for (NtesukiMoveList::iterator move_it = move_list.begin();
321  move_it != move_list.end(); move_it++)
322  {
323  const Move move = move_it->getMove();
324 
325  if (move_it->isPass())
326  {
327  unsigned int p_a = 1, d_a = 1, p_d = 1, d_d = 1;
328  move_it->setHEstimates(p_a, d_a, p_d, d_d);
329  continue;
330  }
331 
332  unsigned int p_a = 1, d_a = 1, p_d = 1, d_d = 1;
333 #if 0
334  if (state->template kingSquare<O>().isOnBoard())
335  {
336  checkmate::LibertyEstimator::attackH(P, *state, move_it->getMove(),
337  p_a, d_a);
338  }
339  if (state->template kingSquare<P>().isOnBoard())
340  {
341  checkmate::LibertyEstimator::defenseH(P, *state, move_it->getMove(),
342  p_d, d_d);
343  }
344 #endif
345 
346  move_it->setHEstimates(p_a, d_a, p_d, d_d);
347 
348  const Square from = move.from();
349  const Square to = move.to();
350  const Ptype ptype = move.ptype();
351 
352  /* 駒のただ捨て(無駄合を含む)を記録 */
353  if (state->hasEffectAt(O, to))
354  {
355  if (from.isPieceStand())
356  {
357  if ((ptype != cheapest) && (ptype != secondCheapest))
358  {
359  move_it->setInterpose();
360  }
361  else if((! state->hasEffectAt(P, to)) // 自分の利きがない
362  && (! state->hasMultipleEffectAt(O, to)))// 焦点でもない
363  {
364  move_it->setInterpose();
365  }
366  }
367  else if ((ptype != KING) &&
368  (move.capturePtype() == PTYPE_EMPTY) &&
369  (! state->hasMultipleEffectAt(P, to)))
370  {
371  move_it->setInterpose();
372  }
373  }
374 
375  /* 無駄な遠い利き */
376  if (delay_lame_long &&
377  from.isPieceStand() &&
378  (isMajor(ptype) || ptype == LANCE) &&
379  (! state->hasMultipleEffectAt(P, to)))
380  {
381  const Square opKingSquare = state->template kingSquare<O>();
382  const Square myKingSquare = state->template kingSquare<P>();
383  bool close_to_king = false;
384  if (opKingSquare.isOnBoard())
385  {
386  int distance = (opKingSquare.x() - to.x()) * (opKingSquare.x() - to.x()) +
387  (opKingSquare.y() - to.y()) * (opKingSquare.y() - to.y());
388  if (distance < 19)
389  {
390  close_to_king = true;
391  }
392  }
393  if (myKingSquare.isOnBoard())
394  {
395  int distance = (myKingSquare.x() - to.x()) * (myKingSquare.x() - to.x()) +
396  (myKingSquare.y() - to.y()) * (myKingSquare.y() - to.y());
397  if (distance < 19)
398  {
399  close_to_king = true;
400  }
401  }
402 
403  if (!close_to_king)
404  {
405  move_it->setLameLong();
406  ntesuki_assert(move_it->isLameLong());
407  }
408  }
409 
410  /* 不成を記録 */
411  if (from.isOnBoard() &&
412  PawnCheckmateMoves::effectiveOnlyIfPawnCheckmate<P>(ptype, from, to))
413  {
414  move_it->setNoPromote();
415  }
416  }
417 }
418 
419 struct
421 {
423 
425  :move(move) {}
426 
428  {
429  return m.getMove() != move->getMove();
430  }
431 };
432 
433 template <osl::Player P>
436 calcProofPiecesOr(int pass_left,
437  const osl::ntesuki::NtesukiMove& move)
438 {
439  ntesuki_assert(turn() == P);
440  PieceStand proof_pieces;
441 
442  const NtesukiRecord* record_child = table->findWithMove(this, move);
443  ntesuki_assert(record_child);
444  proof_pieces = record_child->getPDPieces<P>(pass_left);
445 
446  if (move.isDrop())
447  {
448  proof_pieces.add(move.ptype());
449  }
450  else if (move.getMove().capturePtype() != PTYPE_EMPTY)
451  {
452  proof_pieces.trySub(unpromote(move.getMove().capturePtype()));
453  }
454  return proof_pieces;
455 }
456 
457 template <osl::Player P>
460 calcProofPiecesAnd(int pass_left)
461 {
462  ntesuki_assert(state->turn() == turn());
463 
465  ntesuki_assert(turn() != P);
466  PieceStand proof_pieces;
467 
469  mg->generate<O>(*state, moves);
470 
471  for (NtesukiMoveList::iterator move_it = moves.begin();
472  move_it != moves.end(); move_it++)
473  {
474  const NtesukiMove& move = *move_it;
475  const NtesukiRecord* record_child = table->findWithMove(this, move);
476  if (!record_child)
477  {
478  if (move.isCheck() ||
479  (0 == pass_left &&
480  (!move.isCheck() || move.isNoPromote())))
481  {
482  continue;
483  }
484  else
485  {
486  return piece_stand<P>();
487  }
488  }
489  else if (!record_child->getValue<P>(pass_left).isCheckmateSuccess())
490  {
491  continue;
492  }
493 
494  PieceStand proof_pieces_child = record_child->getPDPieces<P>(pass_left);
495  proof_pieces = proof_pieces.max(proof_pieces_child);
496  }
497 
498  /* monopolized pieces */
499  ntesuki_assert(state);
500 
502  {
503  for (unsigned int i=0; i<PieceStand::order.size(); ++i)
504  {
505  const Ptype ptype = PieceStand::order[i];
506  if (!state->hasPieceOnStand(O, ptype))
507  {
508  const int diff = state->countPiecesOnStand(P, ptype) - proof_pieces.get(ptype);
509  ntesuki_assert(diff >= 0);
510  if (diff) proof_pieces.add(ptype, diff);
511  }
512  }
513  }
514  return proof_pieces;
515 }
516 
517 template <osl::Player A>
518 void
520 setProofPieces(int pass_left,
521  const NtesukiResult& r,
522  const NtesukiMove& best_move,
523  const PieceStand* ps)
524 {
526  PieceStand proof_pieces;
527 
528  if (ps)
529  {
530  /* Immediate checkmate or dominance or oracel prover light
531  */
532  proof_pieces = *ps;
533  }
534  else if (best_move.isPass())
535  {
536  const NtesukiRecord* record_pass = table->findWithMove(this, best_move);
537  ntesuki_assert(record_pass);
538  proof_pieces = record_pass->getPDPieces<A>(pass_left - 1);
539  }
540  else if (best_move.isValid())
541  {
542  proof_pieces = calcProofPiecesOr<A>(pass_left, best_move);
543  }
544  else
545  {
546  /* set_proof_tree_AND
547  */
548  proof_pieces = calcProofPiecesAnd<A>(pass_left);
549  }
550 
551  ntesuki_assert(piece_stand<A>().template hasMoreThan<BLACK>(proof_pieces));
552  for (unsigned int j = pass_left; j < SIZE; j++)
553  {
554  setPDPieces<A>(j, proof_pieces);
555  setPDPieces<D>(j, proof_pieces);//for attack back
556  }
557 }
558 
559 template <osl::Player P>
560 void
562 setDisproofPieces(int pass_left,
563  const NtesukiResult& r,
564  const NtesukiMove& m,
565  const PieceStand* ps)
566 {
568  PieceStand disproof_pieces;
569 
570  if (ps)
571  {
572  /* Immediate checkmate or dominance
573  */
574  disproof_pieces = *ps;
575  }
576  else if (m.isPass())
577  {
578  const NtesukiRecord* record_pass = table->findWithMove(this, m);
579  ntesuki_assert(record_pass);
580 
581  disproof_pieces = record_pass->getPDPieces<P>(pass_left - 1);
582  }
583  else if (m.isValid())
584  {
585  /* set_disproof_tree_OR
586  */
587  ntesuki_assert(turn() != P);
588 
589  const NtesukiRecord* record_child = table->findWithMove(this, m);
590  ntesuki_assert(record_child);
591  disproof_pieces = record_child->getPDPieces<P>(pass_left);
592 
593  if (m.isDrop())
594  {
595  disproof_pieces.add(m.ptype());
596  }
597  else if (m.getMove().capturePtype() != PTYPE_EMPTY)
598  {
599  disproof_pieces.trySub(unpromote(m.getMove().capturePtype()));
600  }
601  }
602  else
603  {
604  /* set_disproof_tree_AND
605  */
606  ntesuki_assert(turn() == P);
607 
609  generateMoves<P>(moves, 0, true);
610 
611  for (NtesukiMoveList::iterator move_it = moves.begin();
612  move_it != moves.end(); move_it++)
613  {
614  const NtesukiRecord* record_child = table->findWithMove(this, *move_it);
615  if (!record_child)
616  {
617  if (move_it->isPass() ||
618  (0 == pass_left &&
619  (!move_it->isCheck() || move_it->isNoPromote())))
620  {
621  continue;
622  }
623  else
624  {
625  setPDPieces<P>(pass_left, piece_stand<O>());
626  return;
627  }
628 
629  }
630 
631  PieceStand disproof_pieces_child = record_child->getPDPieces<P>(pass_left);
632 
633  disproof_pieces = disproof_pieces.max(disproof_pieces_child);
634  }
635 
636  /* monopolized pieces */
637  ntesuki_assert(state);
638  ntesuki_assert(state->turn() == turn());
639 
640  //if (! effect_util::UnblockableCheck::isMember(P, *state))
641  if (true)
642  {
643  for (unsigned int i=0; i<PieceStand::order.size(); ++i)
644  {
645  const Ptype ptype = PieceStand::order[i];
646  if (!state->hasPieceOnStand(P, ptype))
647  {
648  const int diff = state->countPiecesOnStand(O, ptype) - disproof_pieces.get(ptype);
649  ntesuki_assert(diff >= 0);
650  if (diff) disproof_pieces.add(ptype, diff);
651  }
652  }
653  }
654  }
655 
656 #ifndef NDEBUG
657  ntesuki_assert(piece_stand<O>().isSuperiorOrEqualTo(disproof_pieces))
658 #endif
659  setPDPieces<P>(pass_left, disproof_pieces);
660 }
661 
662 template <osl::Player P>
663 void
665 setFinal(int pass_left,
666  const NtesukiResult& r,
667  const NtesukiMove& m,
668  const PieceStand* ps)
669 {
670  if (r.isCheckmateSuccess() && pass_count)
671  {
672  final = true;
673  }
675 
676  if (r.isCheckmateSuccess())
677  {
678  TRY_DFPN;
679  setProofPieces<P>(pass_left, r, m, ps);
680  CATCH_DFPN;
681 
682  for (unsigned int j = pass_left; j < SIZE; j++)
683  {
684  values<P> ()[j] = r;
685  best_move<P>()[j] = m;
686 
687  if (!values<O>()[j].isCheckmateFail())
688  {
689  ntesuki_assert(!values<O>()[j].isCheckmateSuccess());
690 
691  values<O> ()[j] = ProofDisproof::AttackBack();
692  best_move<O>()[j] = m;
693  }
694  }
695 
696  if (use_dominance)
697  {
698  propagate_proof<P>(pass_left);
699  }
700 
701 #ifdef COLLECT_GARBAGE
702  //collect garbage
703  if (turn() == P)
704  {
705  DifferentMove different_move(best_move<P>()[pass_left]);
706  moves.remove_if(different_move);
707  }
708 #endif
709  }
710  else //fail
711  {
713  setDisproofPieces<P>(pass_left, r, m, ps);
714 
715  values<P>()[pass_left] = r;
716  best_move<P>()[pass_left] = m;
717 
718  if (pass_left != 0 &&
719  !values<P>()[pass_left - 1].isCheckmateFail()
720  )
721  {
722  setFinal<P>(pass_left - 1, r, m, ps);
723  }
724 
725  if (use_dominance)
726  {
727  propagate_disproof<P>(pass_left);
728  }
729 
730 #ifdef COLLECT_GARBAGE
731  //collect garbage
732  if (turn() != P)
733  {
734  for (NtesukiMoveList::iterator move_it = moves.begin();
735  move_it != moves.end(); move_it++)
736  {
737  bool not_best_move = true;
738  for (size_t i = 0; i < SIZE; i++)
739  {
740  if (&(*move_it) != best_move<O>()[pass_left]) not_best_move = false;
741  }
742 
743  if (not_best_move)
744  {
745  move_it->clearRecord();
746  }
747  }
748  }
749 #endif
750  }
751 }
752 
753 /* set result
754  * also propagate values to deeper threats if checkmate success
755  * P is the attacker
756  */
757 template <osl::Player P>
758 void
760 setResult(int i, //i tesuki
761  const NtesukiResult& r, //pn/dn of this node at i
762  const NtesukiMove& m, //best move
763  bool bs, //by simulation
764  const PieceStand* ps //when set by fixed depth searcher
765  )
766 {
767  ++written_count;
768  /* TODO something that should dissapear,
769  * as this is a result of a loop gaining/losing pieces
770  */
771  ntesuki_assert(!values<P>()[i].isFinal());
772  ntesuki_assert(best_move<P>()[i].isInvalid());
773 
774  by_simulation = bs;
775 
776  if (r.isFinal())
777  {
778  value_before_final = values<P>()[i];//remember the last pdp for latter use
779  setFinal<P>(i, r, m, ps);
780  }
781  else
782  {
783  values<P>()[i] = r;
784  /* Dominance between lambda order */
785  int order = 0;
786  for (; order < i; order++)
787  {
788  if (values<P>()[order].disproof() > r.disproof())
789  {
790  values<P>()[order] = ProofDisproof(values<P>()[order].proof(),
791  r.disproof());
792  }
793  }
794  ++order;
795  for (; order < (int)SIZE; order++)
796  {
797  /* L^order が AttackBack等で既に disproof されている場合 */
798  if (values<P>()[order].isCheckmateFail()) continue;
799 
800  if (values<P>()[order].disproof() < r.disproof())
801  {
802  values<P>()[order] = ProofDisproof(values<P>()[order].proof(),
803  r.disproof());
804  }
805  }
806  }
807 
808 #ifndef NDEBUG
809  if (by_simulation) ntesuki_assert(r.isFinal());
810 
811  if (m.isValid())
812  {
813  ntesuki_assert(r.isFinal());
814  }
815 
816  if (key.turn() == P &&
817  values<P>()[i].isCheckmateSuccess())
818  {
819  ntesuki_assert(m.isValid());
820  }
821  else if (key.turn() != P &&
822  values<P>()[i].isCheckmateFail())
823  {
824  /* ntesuki_assert(m); */
825  }
826 #endif
827 }
828 
829 /* See if this is dominated by the proof pieces for record
830  */
831 template <osl::Player P>
832 bool
835  int pass_left) const
836 {
837  if (!record->getValue<P>(pass_left).isCheckmateSuccess()) return false;
838 
839  const PieceStand& my_stand = piece_stand<P>();
840  const PieceStand& other_pp = record->getPDPieces<P>(pass_left);
841 
842  return my_stand.isSuperiorOrEqualTo(other_pp);
843 }
844 
845 /* See if this is dominated by the disproof pieces for record
846  */
847 template <osl::Player P>
848 bool
851  int pass_left) const
852 {
854  if (!record->getValue<P>(pass_left).isCheckmateFail()) return false;
855 
856  const PieceStand& my_stand = piece_stand<O>();
857  const PieceStand& other_dp = record->getPDPieces<P>(pass_left);
858 
859  return my_stand.isSuperiorOrEqualTo(other_dp);
860 }
861 
862 /* See if this dominated by record
863  */
864 template <osl::Player P>
865 bool
868 {
869  const PieceStand& mystand = key.getPieceStand();
870  const PieceStand& opstand = record->key.getPieceStand();
871 
872  if (mystand == opstand) return false;
873  return mystand.hasMoreThan<P>(opstand);
874 }
875 
876 /* =============================================================================
877  * accessors
878  */
879 template <osl::Player A>
881 useOld(int pass_left) const
882 {
883  return use_old<A>()[pass_left];
884 }
885 
886 template <osl::Player A>
888 setUseOld(int pass_left,
889  bool value)
890 {
891  use_old<A>()[pass_left] = value;
892 }
893 
894 
895 template <osl::Player P>
897 isLoopWithPath(int pass_left,
898  const PathEncoding& path) const
899 {
901  const list_t& list = loop_path_list<P>()[pass_left];
902  for (list_t::const_iterator it = list.begin(); it != list.end(); it++)
903  {
904  if (*it == path)
905  {
906  return true;
907  }
908  }
909  return false;
910 }
911 
912 template <osl::Player P>
914 setLoopWithPath(int pass_left,
915  const PathEncoding& path)
916 {
918  list_t& list = loop_path_list<P>()[pass_left];
919  list.push_front(path);
920 }
921 
922 template <osl::Player P>
925 getValue(int i) const
926 {
927  ++read_count;
928  return values<P>()[i];
929 }
930 
931 template <osl::Player P>
935  const PathEncoding path) const
936 {
937  ++read_count;
938  if (values<P>()[i].isFinal()) return values<P>()[i];
939  if (isLoopWithPath<P>(i, path))
940  {
942  }
943  return values<P>()[i];
944 }
945 
946 
947 template <osl::Player P>
950 getValueOr(int max_pass_left,
951  const PathEncoding path,
952  IWScheme iwscheme) const
953 {
954  ++read_count;
955  if (values<P>()[max_pass_left].isFinal()) return values<P>()[max_pass_left];
956  if (isLoopWithPath<P>(max_pass_left, path))
957  {
959  }
960 
961  NtesukiResult ret = values<P>()[max_pass_left];
962 
963  if (iwscheme == pn_iw)
964  {
965  unsigned int min_proof = ret.proof();
966  for (int pass_left = 0; pass_left < max_pass_left; ++pass_left)
967  {
968  if (isLoopWithPath<P>(pass_left, path)) continue;
969  const NtesukiResult result = values<P>()[pass_left];
970  ntesuki_assert(result.disproof() <= ret.disproof());
971  min_proof = std::min(min_proof, result.proof());
972  }
973  ret = NtesukiResult(min_proof, ret.disproof());
974  }
975  else if (iwscheme == strict_iw)
976  {
977  for (int pass_left = 0; pass_left < max_pass_left; ++pass_left)
978  {
979  if (isLoopWithPath<P>(pass_left, path)) continue;
980  const NtesukiResult result = values<P>()[pass_left];
981  if (!result.isCheckmateFail())
982  {
983  ret = result;
984  break;
985  }
986  }
987  }
988  return ret;
989 }
990 
991 template <osl::Player P>
994 getValueAnd(int max_pass_left,
995  const PathEncoding path,
996  IWScheme iwscheme,
997  PSScheme psscheme) const
998 {
999  ++read_count;
1000  if (values<P>()[max_pass_left].isFinal()) return values<P>()[max_pass_left];
1001  if (isLoopWithPath<P>(max_pass_left, path))
1002  {
1004  }
1005 
1006  NtesukiResult ret = values<P>()[max_pass_left];
1007  if (psscheme && max_pass_left != 0)
1008  {
1009  /* max_pass_left - 1 まで敵の PN を見て,
1010  * こちらの DN より小さかったら先に読む.
1011  */
1013  const NtesukiResult result_opponent = getValueOr<O>(max_pass_left - 1,
1014  path,
1015  iwscheme);
1016  if (!result_opponent.isFinal() &&
1017  result_opponent.proof() + inversion_cost < ret.disproof())
1018  {
1019  ret = ProofDisproof(result_opponent.disproof(), //最も単純なモデルでは ret.proof()
1020  result_opponent.proof() + inversion_cost);
1021  }
1022  }
1023  return ret;
1024 }
1025 
1026 template <osl::Player P>
1029 getBestMove(int i) const
1030 {
1031  return best_move<P>()[i];
1032 }
1033 
1034 template <osl::Player P>
1035 bool
1037 isNtesuki(int pass_left) const
1038 {
1039  return is_ntesuki<P>()[pass_left];
1040 }
1041 
1042 template <osl::Player P>
1043 void
1045 setNtesuki(int pass_left)
1046 {
1047  //ntesuki_assert(false == is_ntesuki<P>()[pass_left]);
1048  is_ntesuki<P>()[pass_left] = true;
1049 }
1050 
1051 template <osl::Player P>
1052 bool
1054 hasTriedPropagatedOracle(int pass_left) const
1055 {
1056  return propagated_oracle<P>()[pass_left];
1057 }
1058 
1059 template <osl::Player P>
1060 void
1063 {
1064  assert(false == propagated_oracle<P>()[pass_left]);
1065  propagated_oracle<P>()[pass_left] = true;
1066 }
1067 
1068 template <osl::Player P>
1069 bool
1071 isByFixed() const
1072 {
1073  return by_fixed<P>();
1074 }
1075 
1076 template <osl::Player P>
1079 getPDPieces(int pass_left) const
1080 {
1081  return pdpieces<P>()[pass_left];
1082 }
1083 
1084 template <osl::Player P>
1085 void
1087 setPDPieces(int pass_left, const PieceStand p)
1088 {
1089  pdpieces<P>()[pass_left] = p;
1090 }
1091 
1092 // ;;; Local Variables:
1093 // ;;; mode:c++
1094 // ;;; c-basic-offset:2
1095 // ;;; End: