All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
historyToTable.cc
Go to the documentation of this file.
1 /* historyToTable.cc
2  */
12 #include "osl/record/csa.h"
13 #include <boost/foreach.hpp>
14 #include <iostream>
15 
18 
20 HistoryToTable::adjustDominance(const HashKey& key,
22  int black_win, int white_win,
23  const Move& good_move)
24 {
25  const PieceStand black_stand = key.pieceStand();
26  const Player turn = key.turn();
27  BOOST_FOREACH(Ptype ptype, PieceStand::order)
28  {
29  if (black_stand.get(ptype))
30  {
31  // white win dominance
32  PieceStand new_stand = black_stand;
33  new_stand.sub(ptype);
34  HashKey new_key = key;
35  new_key.setPieceStand(new_stand);
36  SimpleHashRecord *record = table.allocate(new_key, LIMIT);
37  if (record)
38  {
39  const Move record_move = (turn == WHITE) ? good_move : Move::INVALID();
40  record->setAbsoluteValue(record_move, white_win, LIMIT);
41  record->qrecord.setHistoryValue(record_move, white_win);
42  }
43  }
44  if (black_stand.canAdd(ptype))
45  {
46  // black win dominance
47  // TODO:
48  // - 加える持駒があるかどうかのチェックは本当は盤面を見る必要がある
49  // - good_move がvalid であることの assert を入れる
50  PieceStand new_stand = black_stand;
51  new_stand.add(ptype);
52  HashKey new_key = key;
53  new_key.setPieceStand(new_stand);
54  SimpleHashRecord *record = table.allocate(new_key, LIMIT);
55  if (record)
56  {
57  const Move record_move = (turn == BLACK) ? good_move : Move::INVALID();
58  record->setAbsoluteValue(record_move, black_win, LIMIT);
59  record->qrecord.setHistoryValue(record_move, black_win);
60  }
61  }
62  }
63 }
64 
66 HistoryToTable::adjustTable(const GameState& state, SimpleHashTable& table,
67  int black_win, int draw, int white_win)
68 {
69  const RepetitionCounter& counter = state.counter();
70  // 優越関係より千日手が優先
71  // 千日手は新しい局面優先
72  HashKeyStack history = state.hashHistory(); // copy
73  MoveStack move_history = state.moveHistory();
74  move_history.push(Move::INVALID());
75  assert(move_history.size() == history.size());
76 
77  HashKeyStack reverse_history;
78  while (! history.empty())
79  {
80  const HashKey key = history.top();
81  history.pop();
82  assert(move_history.hasLastMove());
83  const Move last_move = move_history.lastMove();
84  move_history.pop();
85 
86  if (key != HashKey(state.state())) // keep current state clean
87  reverse_history.push(key);
88 
89  // set dominance
90  adjustDominance(key, table, black_win, white_win, last_move);
91  }
92 
93  while (! reverse_history.empty())
94  {
95  // set repetition
96  const HashKey key = reverse_history.top();
97  reverse_history.pop();
98 
99  SimpleHashRecord *record = table.allocate(key, LIMIT);
100  const std::pair<Sennichite,int> result = counter.distanceToSennichite(key);
101  if (result.first.isDraw())
102  {
103  record->setAbsoluteValue(Move::INVALID(), draw*result.second, LIMIT);
104  record->qrecord.setHistoryValue(draw*result.second);
105  }
106  else
107  {
108  assert(result.first.hasWinner());
109  const int value = (result.first.winner() == BLACK) ? black_win : white_win;
110  record->setAbsoluteValue(Move::INVALID(), value, LIMIT);
111  record->qrecord.setHistoryValue(value);
112  }
113  }
114 }
115 
117 HistoryToTable::setPV(const PVHistory& pv_history, const GameState& gstate, search::SimpleHashTable& table)
118 {
119  const Player Turn = gstate.state().turn();
120  NumEffectState state(gstate.getInitialState());
121  MoveStack history = gstate.moveHistory();
122  HashKey key(state);
123  for (int i=history.size(); i>0; --i) {
124  const Move m = history.lastMove(i);
125  if (! m.isNormal() || ! state.isValidMove(m)) {
126  std::cerr << "setPV failed " << i << " " << m << "\n" << state;
127 #ifndef NDEBUG
128  for (int j=history.size(); j>0; --j)
129  std::cerr << history.lastMove(j) << " ";
130  std::cerr << std::endl;
131 #endif
132  return;
133  }
134  const MoveWithComment& pv = pv_history[(history.size()-i) % pv_history.size()];
135  if (pv.root == key && state.turn() == Turn && !pv.moves.empty()) {
136  if (table.isVerbose()) {
137  std::cerr << "setPV " << record::csa::show(m) << " ";
138  BOOST_FOREACH(Move p, pv.moves)
139  std::cerr << record::csa::show(p);
140  std::cerr << "\n";
141  }
142  if (! pv.move.isNormal() || ! state.isValidMove(pv.move))
143  {
144  std::cerr << "setPV failed (corrupt pv) " << pv.move << "\n";
145  }
146  else
147  {
148  NumEffectState state_copy = state;
149  state_copy.makeMove(pv.move);
150  HashKey cur = key.newHashWithMove(pv.move);
151  BOOST_FOREACH(Move move, pv.moves) {
152  SimpleHashRecord *record = table.allocate(cur, 1000);
153  if (record) {
154  if (move == Move::PASS(state_copy.turn()) // pass is allowed here
155  || state_copy.isValidMove(move)) {
156  record->setBestMove(move);
157  }
158  else {
159  std::cerr << "setPV failed (corrupt pv) " << i << " " << move << "\n";
160  break;
161  }
162  }
163  state_copy.makeMove(move);
164  cur = cur.newHashWithMove(move);
165  }
166  }
167  }
168  key = key.newHashWithMove(m);
169  state.makeMove(m);
170  }
171 }
172 
173 /* ------------------------------------------------------------------------- */
174 // ;;; Local Variables:
175 // ;;; mode:c++
176 // ;;; c-basic-offset:2
177 // ;;; End: