All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ntesukiTable.h
Go to the documentation of this file.
1 #ifndef _PD_NTESUKI_TABLE_H
2 #define _PD_NTESUKI_TABLE_H
5 #include "osl/misc/carray.h"
6 #include "osl/stl/hash_set.h"
7 #include "osl/pathEncoding.h"
8 #include "osl/hash/hashKey.h"
9 #include "osl/stl/hash_map.h"
10 #include "osl/stl/slist.h"
11 #include <boost/scoped_ptr.hpp>
12 #include <stdexcept>
13 
14 namespace osl
15 {
16  namespace stl
17  {
18  template <>
19  struct hash<Square>{
20  unsigned long operator()(const Square& p) const
21  {
22  return p.uintValue();
23  }
24  };
25  }
26 
27  namespace ntesuki
28  {
32  struct TableFull : std::runtime_error
33  {
34  TableFull() : std::runtime_error("table full")
35  {
36  }
37  };
38 
43  struct RootStateNotSet : std::runtime_error
44  {
45  RootStateNotSet () : std::runtime_error("root node not set")
46  {
47  }
48  };
53  {
54  private:
55  typedef hash_map<SignatureKey, NtesukiRecord::RecordList> ntesuki_hash_map;
56 
57  public:
58  class Table : public ntesuki_hash_map
59  {
60  public:
61  unsigned int capacity, default_gc_size;
63  unsigned int numEntry, numCacheHit, gcCount;
65  boost::scoped_ptr<NumEffectState> rootState;
66  static int largeGCCount;
67 
68  Table(unsigned int capacity,
69  unsigned int default_gc_size,
70  bool verbose);
71 
72  ~Table();
73 
81  NtesukiRecord *allocate(const HashKey& key,
82  const PieceStand& white_stand,
83  signed short distance);
84 
91  NtesukiRecord *find(const HashKey& key);
92 
96  void erase(const HashKey key);
97 
101  template <class F> void forEachRecord(F& f);
102  template <class F> void forEachRecordFrom(F&,
103  NumEffectState&,
104  NtesukiRecord *);
105  template <class F> void forEachRecordFromRoot(F& f);
106 
111  void collectGarbage(unsigned int gc_size);
112  };
113 
114 
115  private:
116  boost::scoped_ptr<Table> table;
117  bool verbose;
118 
119  public:
121 
123  {
124  unsigned long operator()(PathEncoding const& pe) const
125  {
126  return pe.getPath();
127  }
128  };
129  typedef hash_set<PathEncoding, HashPathEncoding> PathSet;
130 
131  std::vector<int> depths;
132 
136  NtesukiTable(unsigned int capacity,
137  unsigned int default_gc_size=0,
138  bool verbose=false);
139  ~NtesukiTable();
140 
141  void clear()
142  {
143  table->clear();
144  }
145 
146  Table::const_iterator begin() const
147  {
148  return table->begin();
149  }
150  Table::const_iterator end() const
151  {
152  return table->end();
153  }
154 
160  NtesukiRecord *allocateRoot(const HashKey& key,
161  const PieceStand& white_stand,
162  signed short distance,
163  const NumEffectState* root_state = NULL)
164  {
165  table->root = table->allocate(key, white_stand, distance);
166  if (root_state)
167  {
168  table->rootState.reset(new NumEffectState(*root_state));
169  }
170  return table->root;
171  }
172 
174  const NtesukiMove& move)
175  {
176  /* 毎回 white stand を計算しているのは無駄 */
177  PieceStand white_stand = record->white_stand;
178  const Move m = move.getMove();
179  if (!move.isPass() && m.player())
180  {
181  if (m.isDrop())
182  {
183  white_stand.sub(m.ptype());
184  }
185  else if (m.capturePtype() != PTYPE_EMPTY)
186  {
187  white_stand.add(unpromote(m.capturePtype()));
188  }
189  }
190  unsigned short child_distance = record->distance + 1;
191  NtesukiRecord *child = table->allocate(record->key.newHashWithMove(m),
192  white_stand, child_distance);
193  if (child)
194  {
195  child->distance = std::min(child->distance, child_distance);
196  child->checkNewParent(record);
197  }
198  return child;
199  }
200 
204  NtesukiRecord *find(const HashKey& key)
205  {
206  return table->find(key);
207  }
208 
209  const NtesukiRecord *find(const HashKey& key) const
210  {
211  return table->find(key);
212  }
213 
217  void erase(const HashKey key)
218  {
219  table->erase(key);
220  }
221 
225  void collectGarbage(unsigned int gc_size)
226  {
227  table->collectGarbage(gc_size);
228  }
229 
235  const NtesukiMove& move)
236  {
237  /* テーブルを調べ,あったら move に登録しておく
238  *
239  * (関係ないところから持ってきた move だと
240  * record にない piece を drop する可能性が)
241  */
242  if (move.isNormal() && move.isDrop())
243  {
244  const Ptype drop_type = unpromote(move.getMove().ptype());
245  const PieceStand ps = record->getPieceStandSlow(move.getMove()
246  .player());
247  if (ps.get(drop_type) == 0)
248  {
249  return NULL;
250  }
251  }
252  NtesukiRecord *child = table->find(record->key.newHashWithMove(move.getMove()));
253  if (child)
254  {
255  child->checkNewParent(record);
256  }
257  return child;
258  }
259 
261  const NtesukiMove& move)
262  {
263  /* テーブルを調べ,あったら move に登録しておく
264  *
265  * (関係ないところから持ってきた move だと
266  * record にない piece を drop する可能性が)
267  */
268  if (move.isNormal() && move.isDrop())
269  {
270  const Ptype drop_type = unpromote(move.getMove().ptype());
271  const PieceStand ps = record->getPieceStandSlow(move.getMove()
272  .player());
273  if (ps.get(drop_type) == 0)
274  {
275  return NULL;
276  }
277  }
278  return table->find(record->key.newHashWithMove(move.getMove()));
279  }
280 
284  template <class F> void forEachRecord(F& f)
285  {
286  table->forEachRecord<F>(f);
287  }
288 
292  template <class F> void forEachRecordFromRoot(F& f)
293  {
294  table->forEachRecordFromRoot<F>(f);
295  }
296 
300  unsigned int size() const
301  {
302  return table->numEntry;/* not size() */
303  }
304 
305  unsigned int capacity() const
306  {
307  return table->capacity;
308  }
309 
310  void lockGC()
311  {
312  table->no_gc = true;
313  }
314 
315  void unlockGC()
316  {
317  table->no_gc = false;
318  if (table->gc_request && (table->default_gc_size > 0))
319  {
320  table->collectGarbage(table->default_gc_size);
321  table->gc_request = false;
322  }
323  }
324 
325  bool isVerbose() const;
326  };
327  } //ntesuki
328 }// osl
329 
330 #endif /* _PD_NTESUKI_TABLE_H */
331 // ;;; Local Variables:
332 // ;;; mode:c++
333 // ;;; c-basic-offset:2
334 // ;;; End: