quiescenceRecord.h Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
quiescenceRecord.h
Go to the documentation of this file.
1 /* quiescenceRecord.h
2 */
3 #ifndef _QUIESCENCERECORD_H
4 #define _QUIESCENCERECORD_H
5
6 #include "osl/search/dualThreatmateState.h"
7 #include "osl/ptype.h"
8 #include "osl/move.h"
9 #include "osl/container/moveVector.h"
10 #include "osl/stl/vector.h"
11 #include <iosfwd>
12 #ifdef OSL_SMP
13 # include "osl/misc/lightMutex.h"
14 #endif
15
16 namespace osl
17 {
18 namespace search
19 {
20 struct QSearchTraits
21 {
22 enum {
24 MaxDepth = 8,
26 CheckmateSpecialDepth = 127,
28 HistorySpecialDepth = 126,
29 };
30 enum { FirstThreat = 6, SecondThreat = 2 };
31 enum MoveType {
32 UNKNOWN, KING_ESCAPE, CAPTURE, PROMOTE, CHECK,
33 ESCAPE, ATTACK, OTHER,
34 };
35 };
36
40 struct QuiescenceThreat
41 {
42 int value;
43 Move move;
44 explicit QuiescenceThreat(int v=0, Move m=Move::INVALID())
45 : value(v), move(m)
46 {
47 }
48 };
49
50 struct BestMoves : public CArray<Move,4>
51 {
52 BestMoves()
53 {
54 // automaticallyfilled by invalid data by constructor
55 }
56 size_t capacity() const { return size(); }
57 size_t sizeFilled() const
58 {
59 for (size_t i=0; i<capacity(); ++i)
60 if (! operator[](i).isNormal())
61 return i;
62 return capacity();
63 }
64 void add(Move m)
65 {
66 if (! m.isNormal())
67 return;
68 iterator p = std::find(begin(), end(), m);
69 if (p != end()) {
70 std::rotate(begin(), p, p+1);
71 return;
72 }
73 size_t size = sizeFilled();
74 if (size == capacity())
75 operator[](capacity()-1) = m;
76 else
77 operator[](size++) = m;
78 std::rotate(begin(), begin()+(int)size-1, begin()+(int)size);
79 }
80 void clear()
81 {
82 fill(Move());
83 }
84 void addSecondary(const MoveVector& v)
85 {
86 CArray<Move,4> copy = *this;
87 clear();
88 size_t size = 0;
89 if (copy[0].isNormal())
90 operator[](size++) = copy[0];
91 for (size_t i=0; i<v.size() && size<capacity(); ++i) {
92 assert(v[i].isNormal());
93 if (std::find(begin(), begin()+(int)size, v[i]) == begin()+(int)size)
94 operator[](size++) = v[i];
95 }
96 for (size_t i=1; i<copy.size() && copy[i].isNormal() && size<capacity(); ++i)
97 if (std::find(begin(), begin()+(int)size, copy[i]) == begin()+(int)size)
98 operator[](size++) = copy[i];
99 }
100 };
101
105 struct QuiescenceRecordBase
106 {
107 int upper_bound, lower_bound;
108 BestMoves best_moves;
110 QuiescenceThreat threat1, threat2;
111 int static_value;
112 int checkmate_nodes;
113 DualThreatmateState threatmate;
114 int threatmate_nodes;
116 int8_t upper_depth, lower_depth, static_value_depth;
117 public:
122 enum { InitialDepth = -128, };
123 enum StaticValueType { UNKNOWN, UPPER_BOUND, EXACT };
124 protected:
125 QuiescenceRecordBase()
126 : checkmate_nodes(0), threatmate_nodes(0),
127 upper_depth(InitialDepth), lower_depth(InitialDepth),
128 static_value_depth(InitialDepth)
129 {
130 }
131 ~QuiescenceRecordBase() {}
132 };
133 class SimpleHashRecord;
137 class QuiescenceRecord : public QuiescenceRecordBase
138 {
139 public:
140 static const char *toString(StaticValueType);
141 private:
142 #ifdef OSL_SMP
143 typedef osl::misc::LightMutexChar Mutex;
144 mutable Mutex mutex;
145 #endif
146 public:
147 QuiescenceRecord()
148 {
149 }
153 QuiescenceRecord(const QuiescenceRecord& src)
154 : QuiescenceRecordBase(src)
155 {
156 }
157 QuiescenceRecord& operator=(const QuiescenceRecord& src)
158 {
159 if (this == &src)
160 return *this;
161
162 QuiescenceRecordBase::operator=(src);
163 return *this;
164 }
165
166 template <Player Turn>
167 const Square8 sendOffSquare(const NumEffectState& state) const
168 {
169 #ifdef OSL_SMP
170 SCOPED_LOCK_CHAR(lk,mutex);
171 #endif
172 assert(Turn == state.turn());
173 Square8 ret;
174 const Square king_position = state.kingSquare(alt(Turn));
175 if (threatmate.sendoffs == SendOffSquare::invalidData())
176 threatmate.sendoffs = SendOffSquare::find<Turn>(state, king_position, ret);
177 else
178 SendOffSquare::unpack(threatmate.sendoffs, king_position, ret);
179 return ret;
180 }
181 const Square8
182 sendOffSquare(Player turn, const NumEffectState& state) const
183 {
184 if (turn == BLACK)
185 return sendOffSquare<BLACK>(state);
186 else
187 return sendOffSquare<WHITE>(state);
188 }
193 int checkmateNodesLeft(int max)
194 {
195 #ifdef OSL_SMP
196 SCOPED_LOCK_CHAR(lk,mutex);
197 #endif
198 if (max > checkmate_nodes)
199 {
200 const int left = max - checkmate_nodes;
201 checkmate_nodes = max;
202 return left;
203 }
204 return 0;
205 }
210 int threatmateNodesLeft(int max)
211 {
212 #ifdef OSL_SMP
213 SCOPED_LOCK_CHAR(lk,mutex);
214 #endif
215 if (max > threatmate_nodes)
216 {
217 const int left = max - threatmate_nodes;
218 threatmate_nodes = max;
219 return left;
220 }
221 return 0;
222 }
224 int checkmateNodes() const { return checkmate_nodes; }
225 int threatmateNodes() const { return threatmate_nodes; }
226
227 void clear()
228 {
229 #ifdef OSL_SMP
230 SCOPED_LOCK_CHAR(lk,mutex);
231 #endif
232 best_moves.clear();
233 upper_depth = lower_depth = static_value_depth = InitialDepth;
234 }
235 void setStaticValue(StaticValueType type, int value, int depth,
236 const QuiescenceThreat& t1=QuiescenceThreat(),
237 const QuiescenceThreat& t2=QuiescenceThreat())
238 {
239 #ifdef OSL_SMP
240 SCOPED_LOCK_CHAR(lk,mutex);
241 #endif
242 assert((depth <= QSearchTraits::MaxDepth)
243 || (depth == QSearchTraits::CheckmateSpecialDepth));
244 assert(value % 2 == 0);
245 static_value = value;
246 threat1 = t1;
247 threat2 = t2;
248 static_value_depth = depth;
249 threatmate.flags.static_value_type = type;
250 }
251 public:
252 void setLowerBound(int depth, int bound, Move best_move)
253 {
254 #ifdef OSL_SMP
255 SCOPED_LOCK_CHAR(lk,mutex);
256 #endif
257 assert((depth <= QSearchTraits::MaxDepth)
258 || (depth == QSearchTraits::CheckmateSpecialDepth));
259 if (depth >= lower_depth)
260 {
261 best_moves.add(best_move);
262 lower_bound = bound;
263 lower_depth = depth;
264 }
265 }
266 void setUpperBound(int depth, int bound)
267 {
268 #ifdef OSL_SMP
269 SCOPED_LOCK_CHAR(lk,mutex);
270 #endif
271 assert((depth <= QSearchTraits::MaxDepth)
272 || (depth == QSearchTraits::CheckmateSpecialDepth));
273 if (depth >= upper_depth)
274 {
275 upper_bound = bound;
276 upper_depth = depth;
277 }
278 }
279 void setHistoryValue(int value)
280 {
281 lower_bound = upper_bound = value;
282 lower_depth = upper_depth = QSearchTraits::HistorySpecialDepth;
283 }
284 void setHistoryValue(Move best_move, int value)
285 {
286 #ifdef OSL_SMP
287 SCOPED_LOCK_CHAR(lk,mutex);
288 #endif
289 best_moves.add(best_move);
290 setHistoryValue(value);
291 }
292 public:
293 void addKillerMoves(const MoveVector& new_moves)
294 {
295 #ifdef OSL_SMP
296 SCOPED_LOCK_CHAR(lk,mutex);
297 #endif
298 best_moves.addSecondary(new_moves);
299 }
300 StaticValueType staticValueType() const {
301 return static_cast<StaticValueType>(threatmate.flags.static_value_type);
302 }
303 bool hasStaticValue() const { return staticValueType() != UNKNOWN; }
304 bool hasStaticValue(int& value, int& depth, StaticValueType& type) const {
305 type = staticValueType();
306 if (type == UNKNOWN)
307 return false;
308 #ifdef OSL_SMP
309 SCOPED_LOCK_CHAR(lk,mutex);
310 #endif
311 type = staticValueType();
312 value = static_value;
313 depth = static_value_depth;
314 return type != UNKNOWN;
315 }
316 int staticValue() const { assert(hasStaticValue()); return static_value; }
317 int staticValueDepth() const { return static_value_depth; }
318 int upperDepth() const { return upper_depth; }
319 int lowerDepth() const { return lower_depth; }
320 int upperBound() const { return upper_bound; }
321 int lowerBound() const { return lower_bound; }
322 const Move bestMove() const { return best_moves[0]; }
323 int movesEmpty() const { return ! best_moves[1].isNormal(); }
324 int movesSizeLessThan(size_t n) const {
325 return best_moves.capacity() < n || ! best_moves[n-1].isNormal();
326 }
327 int moves_size() const {
328 return std::max(0, (int)best_moves.sizeFilled()-1);
329 }
330 void loadMoves(MoveVector& dst) const{
331 #ifdef OSL_SMP
332 SCOPED_LOCK_CHAR(lk,mutex);
333 #endif
334 dst.clear();
335 for (size_t i=1; i<best_moves.capacity() && best_moves[i].isNormal(); ++i)
336 dst.push_back(best_moves[i]);
337 }
338 void dump(std::ostream&) const;
339 const QuiescenceThreat staticThreat(int index) const
340 {
341 return (index == 0) ? threat1 : threat2;
342 }
343 void updateThreatmate(Player turn, const DualThreatmateState *parent, bool in_check)
344 {
345 #ifdef OSL_SMP
346 SCOPED_LOCK_CHAR(lk,mutex);
347 #endif
348 threatmate.updateInLock(turn, parent, in_check);
349 }
350 friend class SimpleHashRecord;
351 };
352
353 } // namespace search
354 } // namespace osl
355
356 #endif /* _QUIESCENCERECORD_H */
357 // ;;; Local Variables:
358 // ;;; mode:c++
359 // ;;; c-basic-offset:2
360 // ;;; End: