ntesukiRecord.h Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
3 #include "osl/ntesuki/ntesukiResult.h"
4 #include "osl/ntesuki/ntesukiMove.h"
5 #include "osl/ntesuki/ntesukiMoveList.h"
6 #include "osl/ntesuki/rzone.h"
7 #include "osl/ntesuki/ntesukiExceptions.h"
8 #include "osl/checkmate/checkAssert.h"
9 #include "osl/misc/carray.h"
10 #include "osl/state/hashEffectState.h"
11 #include "osl/container/moveVector.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
24 class NtesukiMoveGenerator;
25 class NtesukiTable;
26
32 class NtesukiRecord
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;
61 static bool use_rzone_move_generation;
62 static bool delay_lame_long;
63 static bool use_9rzone;
64
65 static NumEffectState *state;
66 static NtesukiMoveGenerator *mg;
67 static NtesukiTable *table;
68
69 /* DAG関係の統計情報 */
70 static unsigned int split_count ,
71 confluence_count ;
72
73 /* Visit Lock */
74 class VisitLock;
75 class UnVisitLock;
76
78 PieceStand black_stand, white_stand;
79
81 unsigned short distance;
82
84 HashKey key;
85
87 RecordList *same_board_list;
88
90 RecordPList parents;
91 int rev_refcount;/* 子から親への reference の count */
92
96 NtesukiRecord(signed short distance,
97 const HashKey& key,
98 const PieceStand& white_stand,
99 RecordList* same_board_list);
100 ~NtesukiRecord()
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&
121 getPieceStand() const
122 {
123 return piece_stand<P>();
124 }
125
126 const PieceStand&
127 getPieceStandSlow(Player P) const
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
235 void resetVisited()
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
344 setUpDefenseNode();
345
346 /* 子ノードからの情報を使って現在の情報を更新する. */
347 void
348 updateWithChild(NtesukiRecord* child,
349 int pass_left);
350
354 template <Player P> void
355 generateMoves(NtesukiMoveList& moves,
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
398 void find_split(NtesukiRecord *rhs,
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) かかるので注意 */
438 bool find_split_right(NtesukiRecord *rhs,
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
485 void addNewParent(NtesukiRecord* p)
486 {
487 ntesuki_assert(isNewParent(p));
488 parents.push_front(p);
489 p->rev_refcount++;
490 }
491
492 public:
493 void checkNewParent(NtesukiRecord *p)
494 {
495 if (parents.empty())
496 {
497 /* allocate されたばかりなら， parent を add して終了 */
498 addNewParent(p);
499 }
500 else if (isNewParent(p))
501 {
502 ++confluence_count;
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;
524 values_t values_black, values_white;
525 moves_t best_move_black, best_move_white;
526 pdpieces_t pd_pieces_black, pd_pieces_white;
528 pell_t loop_path_list_black, loop_path_list_white;
529 mutable unsigned int child_count, read_count, written_count;
530
531 NtesukiResult value_before_final;
533 bool visited;
534 bool by_simulation;
535 bool by_fixed_black, by_fixed_white;
536 bool already_set_up;
537 bool final;
538
539 public:
540 bool is_split;
541 bool do_oracle_attack;
542 /* AND節点について，親節点が pass_left = 0 で disproof
543 * された場合，この節点からパスで到達できる節点について，
544 * simulation をする.
545 */
546 bool do_oracle_aunt;
547
548 /* OR 節点で，rzone を使用した手生成をする */
549 bool rzone_move_generation;
550
551 private:
552 flags_t read_interpose;/* 受け方でのみ使われる */
553 flags_t read_check_defense;/* 受け方でのみ使われる */
554 flags_t read_non_attack;/* 攻め方でのみ使われる */
555 flags_t is_ntesuki_black, is_ntesuki_white;
556 flags_t propagated_oracle_black, propagated_oracle_white;
557 flags_t use_old_black, use_old_white;
558 rzones_t rzone_black, rzone_white;
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)
661 return propagated_oracle_black;
662 else
663 return propagated_oracle_white;
664 }
665
666 template <Player P> const flags_t propagated_oracle() const
667 {
668 if (P == BLACK)
669 return propagated_oracle_black;
670 else
671 return propagated_oracle_white;
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&,
747 const osl::ntesuki::NtesukiRecord::IWScheme&);
748 std::istream& operator>>(std::istream&,
749 osl::ntesuki::NtesukiRecord::IWScheme&);
750
751 std::ostream& operator<<(std::ostream&,
752 const osl::ntesuki::NtesukiRecord::PSScheme&);
753 std::istream& operator>>(std::istream&,
754 osl::ntesuki::NtesukiRecord::PSScheme&);
755
756 std::ostream& operator<<(std::ostream&,
757 const osl::ntesuki::NtesukiRecord::ISScheme&);
758 std::istream& operator>>(std::istream&,
759 osl::ntesuki::NtesukiRecord::ISScheme&);
760
761 class NtesukiRecord::VisitLock
762 {
763 NtesukiRecord* record;
764 public:
765 VisitLock(NtesukiRecord* record)
766 : record(record)
767 {
768 assert(!record->isVisited());
769 record->setVisited();
770 }
771 ~VisitLock()
772 {
773 assert(record->isVisited());
774 record->resetVisited();
775 }
776 };
777
778 class NtesukiRecord::UnVisitLock
779 {
780 NtesukiRecord* record;
781 public:
782 UnVisitLock(NtesukiRecord* record)
783 : record(record)
784 {
785 assert(record->isVisited());
786 record->resetVisited();
787 }
788 ~UnVisitLock()
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: