All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ntesukiRecord.h
Go to the documentation of this file.
1 #ifndef _NTESUKI_NTESUKI_RECORD_H
2 #define _NTESUKI_NTESUKI_RECORD_H
6 #include "osl/ntesuki/rzone.h"
8 #include "osl/checkmate/checkAssert.h"
9 #include "osl/misc/carray.h"
10 #include "osl/state/hashEffectState.h"
12 #include "osl/pathEncoding.h"
13 #include <iosfwd>
14 
15 namespace osl
16 {
17  namespace ntesuki
18  {
19  class NtesukiRecord;
20  class PathEncodingList : public slist<PathEncoding>
21  {
22  };
23 
25  class NtesukiTable;
26 
33  {
34  public:
35  typedef slist<NtesukiRecord> RecordList;
36  typedef slist<NtesukiRecord*> RecordPList;
40  static const unsigned int SIZE = 2;
41  enum IWScheme { no_iw = 0,
42  strict_iw = 1,
43  pn_iw = 2 };
44 
45  enum PSScheme { no_ps = 0,
46  pn_ps = 1 };
47 
48  enum ISScheme { no_is = 0,
49  tonshi_is = 1,
50  delay_is = 2,
51  normal_is = 3 };
52 
56  static unsigned int fixed_search_depth;
57  static unsigned int inversion_cost;
58  static bool use_dominance;
59  static int pass_count;
60  static bool max_for_split;
62  static bool delay_lame_long;
63  static bool use_9rzone;
64 
65  static NumEffectState *state;
68 
69  /* DAG関係の統計情報 */
70  static unsigned int split_count ,
72 
73  /* Visit Lock */
74  class VisitLock;
75  class UnVisitLock;
76 
79 
81  unsigned short distance;
82 
84  HashKey key;
85 
88 
91  int rev_refcount;/* 子から親への reference の count */
92 
96  NtesukiRecord(signed short distance,
97  const HashKey& key,
98  const PieceStand& white_stand,
101  {
102  }
103 
105  Player turn() const
106  {
107  return key.turn();
108  }
109 
111  bool isBySimulation() const
112  {
113  return by_simulation;
114  }
115 
120  template<Player P> const PieceStand&
122  {
123  return piece_stand<P>();
124  }
125 
126  const PieceStand&
128  {
129  if (P == BLACK)
130  {
131  return piece_stand<BLACK>();
132  }
133  else
134  {
135  return piece_stand<WHITE>();
136  }
137  }
138 
143  template <Player A>
144  PieceStand
145  calcProofPiecesOr(int pass_left,
146  const NtesukiMove& m);
147 
148  template <Player A>
149  PieceStand
150  calcProofPiecesAnd(int pass_left);
151 
156  template <Player A>
157  void
158  setProofPieces(int pass_left,
159  const NtesukiResult& r,
160  const NtesukiMove& m,
161  const PieceStand* ps);
166  template <osl::Player A>
167  void
168  setDisproofPieces(int pass_left,
169  const NtesukiResult& r,
170  const NtesukiMove& m,
171  const PieceStand* ps);
176  template <Player A> void
177  setResult(int i,
178  const NtesukiResult& r,
179  const NtesukiMove& m,
180  bool bs,
181  const PieceStand* ps = NULL);
182 
186  template <Player A> const NtesukiResult getValue(int i) const;
187  template <Player A> const NtesukiResult getValueWithPath(int i,
188  const PathEncoding path) const;
189  template <Player A> const NtesukiResult getValueOr(int i,
190  const PathEncoding path,
191  IWScheme iwscheme) const;
192  template <Player A> const NtesukiResult getValueAnd(int i,
193  const PathEncoding path,
194  IWScheme iwscheme, PSScheme psscheme) const;
195  const NtesukiResult getValueSlow(const Player attacker, int i) const;
196  const NtesukiResult getValueOfTurn(int i) const;
197  const NtesukiResult valueBeforeFinal() const;
198 
199  /* 勝ちか調べる.
200  * 勝ちだったら pass_left を,
201  * それ以外だったら SIZE を返す.
202  */
203  int isWin(const Player attacker) const
204  {
205  int o = 0;
206  for (; o < (int)SIZE; o++)
207  {
208  if (getValueSlow(attacker, o).isCheckmateSuccess())
209  {
210  break;
211  }
212  }
213  return o;
214  }
215 
216 
220  template <Player A> const NtesukiMove& getBestMove(int i) const;
221  const NtesukiMove& getBestMoveSlow(Player attacker, int i) const;
222 
226  bool isVisited() const { return visited; }
227  bool isFinal() {return final; }
228 
229  void setVisited()
230  {
231  assert (!visited);
232  visited = true;
233  }
234 
236  {
237  assert (visited);
238  visited = false;
239  }
240 
244  template <Player A> bool isByFixed() const;
245  bool isByFixedSlow(Player attacker) const;
246 
250  template <Player A> bool isNtesuki(int pass_left) const;
251  template <Player A> void setNtesuki(int pass_left);
252 
256  template <Player A> bool hasTriedPropagatedOracle(int pass_left) const;
257  template <Player A> void triedPropagatedOracle(int pass_left);
258 
262  template <Player A> PieceStand getPDPieces(int pass_left) const;
263  PieceStand getPDPiecesSlow(Player attacker, int pass_left) const;
264  template <Player A> void setPDPieces(int pass_left, const PieceStand p);
265 
269  bool readInterpose(int pass_left) const
270  {
271  return read_interpose[pass_left];
272  }
273 
274  void setReadInterpose(int pass_left)
275  {
276  read_interpose[pass_left] = true;
277  }
278 
282  bool readCheckDefense(int pass_left) const
283  {
284  return read_check_defense[pass_left];
285  }
286 
287  void setReadCheckDefense(int pass_left)
288  {
289  read_check_defense[pass_left] = true;
290  }
291 
295  bool readNonAttack(int pass_left) const
296  {
297  return read_non_attack[pass_left];
298  }
299 
300  void setReadNonAttack(int pass_left)
301  {
302  read_non_attack[pass_left] = true;
303  }
304 
308  template <Player A> bool
309  useOld(int pass_left) const;
310 
311  template <Player A> void
312  setUseOld(int pass_left,
313  bool value);
314 
318  template <Player A> bool
319  isLoopWithPath(int pass_left,
320  const PathEncoding& path) const;
321 
322  template <Player A> void
323  setLoopWithPath(int pass_left,
324  const PathEncoding& path);
325 
326  template <Player A> bool
327  hasLoop(int pass_left) const
328  {
329  return !loop_path_list<A>()[pass_left].empty();
330  }
331 
335  template <Player P> bool
336  setUpNode();
337 
338  /* 王手のかかっていない局面. */
339  template <Player P> void
340  setUpAttackNode();
341 
342  /* 王手のかかっている局面. */
343  template <Player P> void
345 
346  /* 子ノードからの情報を使って現在の情報を更新する. */
347  void
349  int pass_left);
350 
354  template <Player P> void
356  int pass_left,
357  bool all_moves);
358 
359 
360  bool operator==(const NtesukiRecord& record)
361  {
362  return key == record.key;
363  }
364 
365  /* GC 関係 */
366  unsigned int getChildCount() const
367  {
368  return child_count;
369  }
370 
371  void addChildCount(unsigned int i)
372  {
373  child_count += i;
374  }
375 
376  unsigned int getReadCount() const
377  {
378  return read_count;
379  }
380 
381  unsigned int getWrittenCount() const
382  {
383  return written_count;
384  }
385 
386  /* DAG 対策関係 */
387  private:
388  bool isNewParent(const NtesukiRecord* p) const
389  {
390  for (RecordPList::const_iterator it = parents.begin();
391  it != parents.end(); ++it)
392  {
393  if (*it == p) return false;
394  }
395  return true;
396  }
397 
399  RecordPList& lvisited,
400  RecordPList& rvisited)
401  {
402  if (find_split_right(rhs, lvisited, rvisited))
403  {
404  return;
405  }
406 
407 #if 1
408  if (parents.empty())
409  {
410  return;
411  }
412  /* 最初の一つの親だけ見る */
413  RecordPList::iterator lp = parents.begin();
414  if (std::find(lvisited.begin(), lvisited.end(), *lp)
415  != lvisited.end())
416  {
417  return;
418  }
419  lvisited.push_front(*lp);
420  (*lp)->find_split(rhs, lvisited, rvisited);
421  lvisited.pop_front();
422 #else
423  for (RecordPList::iterator lp = parents.begin();
424  lp != parents.end(); ++lp)
425  {
426  if (std::find(lvisited.begin(), lvisited.end(), *lp)
427  == lvisited.end())
428  {
429  lvisited.push_front(*lp);
430  (*lp)->find_split(rhs, lvisited, rvisited);
431  lvisited.pop_front();
432  }
433  }
434 #endif
435  }
436 
437  /* find_split 一つでやろうとすると, O(n^2) で済むところも O(2^n) かかるので注意 */
439  RecordPList& lvisited,
440  RecordPList& rvisited)
441  {
442  if (this == rhs)
443  {
444  if (!is_split)
445  {
446  ++split_count;
447  is_split = true;
448  }
449  return true;
450  }
451 
452 #if 1
453  if (rhs->parents.empty())
454  {
455  return false;
456  }
457  /* 最初の一つの親だけ見る */
458  RecordPList::iterator rp = rhs->parents.begin();
459  if (std::find(rvisited.begin(), rvisited.end(), *rp)
460  != rvisited.end())
461  {
462  return false;
463  }
464  rvisited.push_front(*rp);
465  bool result = find_split_right(*rp, lvisited, rvisited);
466  rvisited.pop_front();
467  return result;
468 #else
469  bool result = false;
470  for (RecordPList::iterator rp = rhs->parents.begin();
471  rp != rhs->parents.end(); ++rp)
472  {
473  if (std::find(rvisited.begin(), rvisited.end(), *rp)
474  == rvisited.end())
475  {
476  rvisited.push_front(*rp);
477  result |= find_split_right(*rp, lvisited, rvisited);
478  rvisited.pop_front();
479  }
480  }
481  return result;
482 #endif
483  }
484 
486  {
488  parents.push_front(p);
489  p->rev_refcount++;
490  }
491 
492  public:
494  {
495  if (parents.empty())
496  {
497  /* allocate されたばかりなら, parent を add して終了 */
498  addNewParent(p);
499  }
500  else if (isNewParent(p))
501  {
503  if (max_for_split)
504  {
505  /* DAG の分流接点(?)を探す
506  */
507  RecordPList lvisited, rvisited;
508  lvisited.push_front(this);
509  rvisited.push_front(p);
510  find_split(p, lvisited, rvisited);
511  }
512  addNewParent(p);
513  }
514  }
515 
516  private:
517  typedef CArray<NtesukiResult, SIZE> values_t;
518  typedef CArray<NtesukiMove, SIZE> moves_t;
519  typedef CArray<short, SIZE - 1> nodesread_t;
520  typedef CArray<PieceStand, SIZE> pdpieces_t;
521  typedef CArray<bool, SIZE> flags_t;
522  typedef CArray<PathEncodingList, SIZE> pell_t;
523  typedef CArray<Rzone, SIZE> rzones_t;
529  mutable unsigned int child_count, read_count, written_count;
530 
533  bool visited;
537  bool final;
538 
539  public:
540  bool is_split;
542  /* AND節点について,親節点が pass_left = 0 で disproof
543  * された場合,この節点からパスで到達できる節点について,
544  * simulation をする.
545  */
547 
548  /* OR 節点で,rzone を使用した手生成をする */
550 
551  private:
552  flags_t read_interpose;/* 受け方でのみ使われる */
553  flags_t read_check_defense;/* 受け方でのみ使われる */
554  flags_t read_non_attack;/* 攻め方でのみ使われる */
559 
560  NtesukiRecord();
561 
562  template <Player P> bool& by_fixed()
563  {
564  if (P == BLACK)
565  return by_fixed_black;
566  else
567  return by_fixed_white;
568  }
569 
570  template <Player P> const bool& by_fixed() const
571  {
572  if (P == BLACK)
573  return by_fixed_black;
574  else
575  return by_fixed_white;
576  }
577 
578  template <Player P> PieceStand& piece_stand()
579  {
580  if (P == BLACK)
581  return black_stand;
582  else
583  return white_stand;
584  }
585 
586  template <Player P> const PieceStand& piece_stand() const
587  {
588  if (P == BLACK)
589  return black_stand;
590  else
591  return white_stand;
592  }
593 
594  template <Player P> values_t& values()
595  {
596  if (P == BLACK)
597  return values_black;
598  else
599  return values_white;
600  }
601 
602  template <Player P> const values_t& values() const
603  {
604  if (P == BLACK)
605  return values_black;
606  else
607  return values_white;
608  }
609 
610  template <Player P> moves_t& best_move()
611  {
612  if (P == BLACK)
613  return best_move_black;
614  else
615  return best_move_white;
616  }
617 
618  template <Player P> const moves_t& best_move() const
619  {
620  if (P == BLACK)
621  return best_move_black;
622  else
623  return best_move_white;
624  }
625 
626  template <Player P> pdpieces_t& pdpieces()
627  {
628  if (P == BLACK)
629  return pd_pieces_black;
630  else
631  return pd_pieces_white;
632  }
633 
634  template <Player P> const pdpieces_t& pdpieces() const
635  {
636  if (P == BLACK)
637  return pd_pieces_black;
638  else
639  return pd_pieces_white;
640  }
641 
642  template <Player P> flags_t& is_ntesuki()
643  {
644  if (P == BLACK)
645  return is_ntesuki_black;
646  else
647  return is_ntesuki_white;
648  }
649 
650  template <Player P> const flags_t& is_ntesuki() const
651  {
652  if (P == BLACK)
653  return is_ntesuki_black;
654  else
655  return is_ntesuki_white;
656  }
657 
658  template <Player P> flags_t& propagated_oracle()
659  {
660  if (P == BLACK)
662  else
664  }
665 
666  template <Player P> const flags_t propagated_oracle() const
667  {
668  if (P == BLACK)
670  else
672  }
673 
674  template <Player P> flags_t& use_old()
675  {
676  if (P == BLACK)
677  return use_old_black;
678  else
679  return use_old_white;
680  }
681 
682  template <Player P> const flags_t use_old() const
683  {
684  if (P == BLACK)
685  return use_old_black;
686  else
687  return use_old_white;
688  }
689 
690  template <Player P> pell_t& loop_path_list()
691  {
692  if (P == BLACK)
693  return loop_path_list_black;
694  else
695  return loop_path_list_white;
696  }
697 
698  template <Player P> const pell_t& loop_path_list() const
699  {
700  if (P == BLACK)
701  return loop_path_list_black;
702  else
703  return loop_path_list_white;
704  }
705 
706  public:
707  template <osl::Player P> rzones_t& rzone()
708  {
709  if (P == BLACK)
710  return rzone_black;
711  else
712  return rzone_white;
713  }
714  private:
715  template <Player P> void
716  setFinal(int i,
717  const NtesukiResult& r,
718  const NtesukiMove& m,
719  const PieceStand* ps);
720 
724  void lookup_same_board_list();
725 
726  template <Player P>
727  void propagate_proof(int pass_left);
728 
729  template <Player P>
730  void propagate_disproof(int pass_left);
731 
732  public:
733  template <Player P>
734  bool isDominatedByProofPieces(const NtesukiRecord* record,
735  int pass_left) const;
736 
737  template <Player P>
738  bool isDominatedByDisproofPieces(const NtesukiRecord* record,
739  int pass_left) const;
740 
741  template <Player P>
742  bool isBetterFor(NtesukiRecord* record);
743  };
744  std::ostream& operator<<(std::ostream&, const osl::ntesuki::NtesukiRecord&);
745 
746  std::ostream& operator<<(std::ostream&,
748  std::istream& operator>>(std::istream&,
750 
751  std::ostream& operator<<(std::ostream&,
753  std::istream& operator>>(std::istream&,
755 
756  std::ostream& operator<<(std::ostream&,
758  std::istream& operator>>(std::istream&,
760 
762  {
764  public:
766  : record(record)
767  {
768  assert(!record->isVisited());
769  record->setVisited();
770  }
772  {
773  assert(record->isVisited());
774  record->resetVisited();
775  }
776  };
777 
779  {
781  public:
783  : record(record)
784  {
785  assert(record->isVisited());
786  record->resetVisited();
787  }
789  {
790  assert(!record->isVisited());
791  record->setVisited();
792  }
793  };
794  }//ntesuki
795 }//osl
796 
797 #endif /* _NTESUKI_NTESUKI_RECORD_H */
798 // ;;; Local Variables:
799 // ;;; mode:c++
800 // ;;; c-basic-offset:2
801 // ;;; End: