All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
openMidEndingEval.h
Go to the documentation of this file.
1 /* openMidEndingEval.h
2  */
3 
4 #ifndef EVAL_ML_OPENMIDENDINGEVAL_H
5 #define EVAL_ML_OPENMIDENDINGEVAL_H
6 
7 #include "osl/eval/ml/weights.h"
10 #include "osl/eval/evalTraits.h"
11 #include "osl/eval/pieceEval.h"
14 #include "osl/progress/effect5x3.h"
17 #include "osl/misc/align16New.h"
18 #include "osl/oslConfig.h"
19 #include <cstring>
20 
21 #define USE_TEST_PROGRESS
22 // NewProgressが学習可能な場合に定義 (現在はosl側に変更はないので常に定義)
23 #define LEARN_TEST_PROGRESS
24 
25 namespace osl
26 {
27  namespace eval
28  {
29  namespace ml
30  {
31  using namespace osl::progress::ml;
33  {
34  public:
36  };
37 
39  {
41  {
103  STAGE_FEATURE_LIMIT
104  };
106  {
108  BISHOP_EXCHANGE_SILVER_KING, // recalculated_value
110  KING25_EFFECT_ATTACK, // end recalculated_value
113  PROGRESS_INDEPENDENT_FEATURE_LIMIT
114  };
115  int value;
116  int progress;
117  CArray<int, PROGRESS_INDEPENDENT_FEATURE_LIMIT> progress_independent_values;
118  CArray<MultiInt, STAGE_FEATURE_LIMIT> stage_values;
119 
120  static const char *name(ProgressIndependentFeature);
121  static const char *name(StageFeature);
122  };
123 
125 #if OSL_WORDSIZE == 32
126  : public misc::Align16New
127 #endif
128  {
129  private:
130  enum { INVALID=EvalTraits<BLACK>::MAX_VALUE+1 };
131  enum {
133  ProgressIndependentValueLimit = 4000
134  };
135  enum LoadStatus { Zero=0, Loaded, Random };
136  static volatile LoadStatus initialized_flag;
138 #ifdef USE_TEST_PROGRESS
140 #else
141  typedef osl::progress::Effect5x3 progress_t;
142 #endif
143  progress_t progress;
144  MultiIntPair kingx_blocked, king25_effect_each;
145  MultiIntPair king25_both_side,king_rook_bishop;
146  MultiIntPair piece_stand_turn, non_pawn_attacked,
147  non_pawn_attacked_ptype, piece_fork_turn;
148  MultiInt ptypey, ptypex, king_table_value;
149  MultiInt piece_stand_value, recalculated_stage_value, pawn_advance;
150  MultiInt rook_mobility, bishop_mobility, lance_mobility;
151  MultiInt knight_advance, pawn_drop, promoted_minor_piece, rook_pawn,
152  rook_effect, bishop_effect, bishop_head, nosupport, ptype_yy, king3pieces;
154  MultiInt piece_stand_combination, piece_stand_y, knight_check,
155  knight_head, pawn_ptypeo, ptype_count_value, lance_effect_piece,
156  ptype_y_pawn_y, bishop_and_king, rook_silver_knight, bishop_silver_knight;
157  CArray<BoardMask, 2> knight_fork_squares;
158  CArray<PieceMask, 2> effect25; // index: owner of king
159  CArray<PieceMask, 2> effect25_supported; // index: owner of king
160  CArray<PieceMask, 2> effected_mask;
161  CArray<PieceMask, 2> effected_mask_for_attacked;
162  CArray<PieceMask, 40> attacked_mask;
163  CArray<int, 5> black_vertical, white_vertical,
164  black_king_vertical, white_king_vertical;
165  // flat
166  CArray<int,2> piece_pair_king_value;
167  CArray<int, 2> non_pawn_stand_count;
168  CArray2d<int, 2, 3> gs_near_king_count;
169  CArray2d<int, 2, PTYPE_SIZE> ptype_count, ptype_board_count;
170  CArray<std::pair<Square,int>, 2> knight_drop, silver_drop, bishop_drop, rook_drop;
171  CArray2d<int, 2, 9> pawns;
172  int progress_independent_value, // should be renamed to piece
173  recalculated_value, piece_pair_value;
175  int black_major_count, black_gold_count;
176  int black_attack_effect, black_attack_piece,
177  white_attack_effect, white_attack_piece,
178  black_attack_supported_piece, white_attack_supported_piece;
179  int black_defense_effect, black_defense_piece,
180  white_defense_effect, white_defense_piece;
181  mutable int cache;
183  unsigned int ptypeo_mask;
184  CArray<bool, 2> can_check; // king is defense
186  static const int ROUND_UP = 2;
187  static int roundUp(int v)
188  {
189  return v & (~(ROUND_UP-1));
190  }
191  void updateGoldSilverNearKing(const NumEffectState &state)
192  {
193  const CArray<Square,2> kings = {{
194  state.kingSquare(BLACK),
195  state.kingSquare(WHITE),
196  }};
197  gs_near_king_count.fill(0);
198  for (int i = PtypeTraits<GOLD>::indexMin;
199  i < PtypeTraits<GOLD>::indexLimit; ++i)
200  {
201  const Piece p = state.pieceOf(i);
202  if (p.isOnBoard())
203  {
204  const Square pos = p.square();
205  const int y_diff = std::abs(pos.y() - kings[p.owner()].y());
206  const int x_diff = std::abs(pos.x() - kings[p.owner()].x());
207  if (y_diff <= 2 && x_diff <= 3)
208  {
209  ++gs_near_king_count[p.owner()][std::max(x_diff, y_diff) - 1];
210  }
211  }
212  }
213  for (int i = PtypeTraits<SILVER>::indexMin;
214  i < PtypeTraits<SILVER>::indexLimit; ++i)
215  {
216  const Piece p = state.pieceOf(i);
217  if (p.isOnBoard())
218  {
219  const Square pos = p.square();
220  const int y_diff = std::abs(pos.y() - kings[p.owner()].y());
221  const int x_diff = std::abs(pos.x() - kings[p.owner()].x());
222  if (y_diff <= 2 && x_diff <= 3)
223  {
224  ++gs_near_king_count[p.owner()][std::max(x_diff, y_diff) - 1];
225  }
226  }
227  }
228  }
229  public:
230  explicit OpenMidEndingEval
231  (const NumEffectState &state=NumEffectState(),
232  bool limit_progress_independent_value=! OslConfig::hasByoyomi());
234  {
235  if (this != &src)
236  memcpy(this, &src, sizeof(OpenMidEndingEval));
237  return *this;
238  }
239  void changeTurn() { }
240  static bool initialized()
241  {
242  return initialized_flag;
243  }
244  static bool setUp(const char *filename);
245  static bool setUp();
246  static std::string defaultFilename();
248  {
249  return progress_independent_value + recalculated_value + piece_pair_value
250  + piece_pair_king_value[BLACK] + piece_pair_king_value[WHITE];
251  }
252  void debug() const;
254  {
255  return king_table_value + piece_stand_value +
256  king25_effect_each[BLACK] + king25_effect_each[WHITE] +
257  ptypex + ptypey + rook_mobility + bishop_mobility + lance_mobility +
258  rook_effect + bishop_effect +
259  piece_stand_combination + piece_stand_turn[turn] +
260  rook_pawn + pawn_drop + piece_stand_y + knight_check +
261  pawn_advance + pawn_ptypeo + promoted_minor_piece +
262  nosupport +
263  non_pawn_attacked[turn] + non_pawn_attacked_ptype[turn] +
264  ptype_yy + king3pieces + bishop_head + knight_head
265  + rook_promote_defense +
266  ptype_count_value + lance_effect_piece + ptype_y_pawn_y +
267  bishop_and_king + piece_fork_turn[turn] + rook_silver_knight + bishop_silver_knight +
268  recalculated_stage_value;
269  }
270  int openingValue() const
271  {
272  return stageValue()[0];
273  }
274  int midgameValue() const
275  {
276  return stageValue()[1];
277  }
278  int midgame2Value() const
279  {
280  return stageValue()[2];
281  }
282  int endgameValue() const
283  {
284  return stageValue()[EndgameIndex];
285  }
286  void invalidateCache() { cache=INVALID; }
287  static int progressIndependentValueAdjusted(int value, int progress,
288  int progress_max)
289  {
290  if (value > ProgressIndependentValueLimit) {
291  int diff = value - ProgressIndependentValueLimit;
292  value = ProgressIndependentValueLimit
293  + diff * progress/progress_max;
294  }
295  else if (value < -ProgressIndependentValueLimit) {
296  int diff = value + ProgressIndependentValueLimit;
297  value = -ProgressIndependentValueLimit
298  + diff * progress/progress_max;
299  }
300  return value;
301  }
303  {
304  const int progress_max = NewProgress::maxProgress(), c = progress_max/2;
305  const int progress = this->progress.progress();
306  int progress_independent = use_progress_independent_value_limit
307  ? progressIndependentValueAdjusted
308  (progressIndependentValue(), progress, progress_max)
309  : progressIndependentValue();
310  int sum = progress_independent * progress_max;
311  if (progress < c)
312  {
313  sum += openingValue() * 2*(c - progress);
314  sum += midgameValue() * 2*progress;
315  }
316  else
317  {
318  sum += midgameValue() * 2*(progress_max - progress);
319  sum += endgameValue() * 2*(progress - c);
320  }
321  return sum;
322  }
323 #ifdef EVAL_QUAD
324  int composeOpenMid2Endgame() const
325  {
326  const int progress_max = NewProgress::maxProgress();
327  const int progress = this->progress.progress();
328  const int c0 = progress_max/3, c1 = c0*2;
329 #ifndef NDEBUG
330  const int w2 = progress_max - c1;
331 #endif
332  assert(c0 == w2);
333  int progress_independent = use_progress_independent_value_limit
334  ? progressIndependentValueAdjusted
335  (progressIndependentValue(), progress, progress_max)
336  : progressIndependentValue();
337  int sum = progress_independent * c0;
338  const MultiInt stage_sum = stageValue();
339  if (progress < c0)
340  {
341  sum += stage_sum[0] * (c0 - progress);
342  sum += stage_sum[1] * progress;
343  }
344  else if (progress < c1)
345  {
346  sum += stage_sum[1] * (c1 - progress);
347  sum += stage_sum[2] * (progress-c0);
348  }
349  else
350  {
351  sum += stage_sum[2] * (progress_max - progress);
352  sum += stage_sum[3] * (progress - c1);
353  }
354  return sum;
355  }
356 #endif
357  int value() const
358  {
359  if (cache==INVALID)
360  {
361 #ifdef USE_TEST_PROGRESS
362 # ifdef EVAL_QUAD
363  cache = roundUp(composeOpenMid2Endgame());
364 # else
365  cache = roundUp(composeOpenMidEndgame());
366 # endif
367 #else
368 # ifdef EVAL_QUAD
369 # error "not supported"
370 # else
371  cache = roundUp(progressIndependentValue() * 16 +
372  openingValue() * (16 - progress.progress16().value()) +
373  endgameValue() * progress.progress16().value());
374 # endif
375 #endif
376  }
377  return cache;
378  }
379  const Move suggestMove(const NumEffectState& state) const
380  {
381  assert(turn == state.turn());
382  Move suggest;
383  int best_value = 0;
384  if (! rook_drop[turn].first.isPieceStand()) {
385  assert(state.hasPieceOnStand(turn, ROOK));
386  suggest = Move(rook_drop[turn].first, ROOK, turn);
387  best_value = rook_drop[turn].second;
388  }
389  assert(best_value >= 0);
390  if (bishop_drop[turn].second > best_value) {
391  assert(! bishop_drop[turn].first.isPieceStand());
392  assert(state.hasPieceOnStand(turn, BISHOP));
393  suggest = Move(bishop_drop[turn].first, BISHOP, turn);
394  best_value = bishop_drop[turn].second;
395  }
396  if (silver_drop[turn].second > best_value) {
397  assert(! silver_drop[turn].first.isPieceStand());
398  assert(state.hasPieceOnStand(turn, SILVER));
399  suggest = Move(silver_drop[turn].first, SILVER, turn);
400  best_value = silver_drop[turn].second;
401  }
402  if (knight_drop[turn].second > best_value
403  && state.hasPieceOnStand(turn, KNIGHT)) {
404  assert(! knight_drop[turn].first.isPieceStand());
405  suggest = Move(knight_drop[turn].first, KNIGHT, turn);
406  best_value = knight_drop[turn].second;
407  }
408  return suggest;
409  }
410  int expect(const NumEffectState &state, Move move) const;
411  template<Player P>
412  void updateSub(const NumEffectState &new_state, Move last_move);
413  void update(const NumEffectState &new_state, Move last_move);
414  const Progress32 progress32() const
415  {
416  return Progress32(progress.progress16(BLACK).value()
417  + progress.progress16(WHITE).value());
418  }
419  const Progress16 progress16() const { return progress.progress16(); }
420  int progressValue() const { return progress.progress(); }
421  int progressMax() const { return progress.maxProgress(); }
422  public:
423  static int infty()
424  {
425 #ifdef USE_TEST_PROGRESS
426 # ifdef EVAL_QUAD
427  assert(NewProgress::maxProgress() % 3 == 0);
428  return 57984 * (NewProgress::maxProgress()/3);
429 # else
430  return 57984 * NewProgress::maxProgress();
431 # endif
432 #else
433  return 57984 * 16;
434 #endif
435  }
436  static int captureValue(PtypeO ptypeO) {
437  assert(isValidPtypeO(ptypeO));
438  return roundUp((-PieceEval::value(ptypeO) +
439  PieceEval::value(captured(ptypeO))) * seeScale());
440  }
441  static int seeScale() {
442 #ifdef USE_TEST_PROGRESS
443 # ifdef EVAL_QUAD
444  assert(NewProgress::maxProgress() % 3 == 0);
445  return (NewProgress::maxProgress()/3);
446 # else
447  return NewProgress::maxProgress();
448 # endif
449 #else
450  return 16;
451 #endif
452  }
453 
454  OpenMidEndingEvalDebugInfo debugInfo(const NumEffectState &state);
455  static void setRandom();
456  static void resetWeights(const int *w, size_t length);
459  return use_progress_independent_value_limit;
460  }
461  private:
462  template <class Reader>
463  static void doResetWeights(Reader& reader);
464  };
465  }
466  using ml::OpenMidEndingEval;
467  }
468  using eval::OpenMidEndingEval;
469 }
470 
471 #endif // EVAL_ML_OPENMIDENDINGEVAL_H
472 // ;;; Local Variables:
473 // ;;; mode:c++
474 // ;;; c-basic-offset:2
475 // ;;; coding:utf-8
476 // ;;; End: