All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
minorPiece.h
Go to the documentation of this file.
1 /* testEval.h
2  */
3 
4 #ifndef EVAL_ML_MINORPIECE_H
5 #define EVAL_ML_MINORPIECE_H
6 
7 #include "osl/eval/ml/midgame.h"
8 #include "osl/eval/ml/weights.h"
10 #include "osl/misc/carray.h"
14 
15 namespace osl
16 {
17  namespace eval
18  {
19  namespace ml
20  {
21  class PawnDrop
22  {
23  public:
24  enum { ONE_DIM = 9, DIM = ONE_DIM * 2};
25  static void setUp(const Weights &weights,int stage);
26  };
27 
28  class PawnDropY
29  {
30  public:
31  enum { ONE_DIM = 81, DIM = ONE_DIM * 2};
32  static void setUp(const Weights &weights,int stage);
33  };
34 
36  {
37  friend class PawnDrop;
38  friend class PawnDropY;
39  friend class PawnDropX;
40  friend class PawnDropPawnStand;
41  friend class PawnDropPawnStandX;
42  friend class PawnDropPawnStandY;
43  friend class PawnDropNonDrop;
44  friend class PawnStateKingRelative;
45  private:
47  static CArray<MultiInt, 9> attack_table, defense_table;
48  static CArray<MultiInt, 81> attack_y_table, defense_y_table;
49  static CArray<MultiInt, 90> x_table;
50  static CArray<MultiInt, 18> stand_table;
51  static CArray<MultiInt, 90> x_stand_table;
52  static CArray<MultiInt, 162> y_stand_table;
53  static CArray<MultiInt, 10> drop_non_drop_table;
54  static CArray<MultiInt, 36> state_king_relative_table;
55  template <Player Owner>
56  static int indexY(const Piece king, int x)
57  {
58  assert(Owner == king.owner());
59  const int king_y = (Owner == BLACK ?
60  king.square().y() : 10 - king.square().y());
61  return std::abs(x - king.square().x()) * 9 + king_y - 1;
62  }
63  static int index(const Square king, int x)
64  {
65  return std::abs(x - king.x());
66  }
67  template <bool Attack>
68  static int indexX(const Piece king, int x)
69  {
70  const int king_x = king.square().x();
71  const int target_x = (king_x > 5 ? 10 - king_x : king_x);
72  if (king_x >= 6 || (king.owner() == WHITE && king_x == 5))
73  x = 10 - x;
74  return (x - 1) * 5 + target_x - 1 + (Attack ? 0 : 45);
75  }
76  public:
77  static MultiInt value(
78  int attack_index, int defense_index,
79  int attack_index_y, int defense_index_y,
80  int attack_index_x, int defense_index_x)
81  {
82  return (attack_table[attack_index] +
83  defense_table[defense_index] +
84  attack_y_table[attack_index_y] +
85  defense_y_table[defense_index_y] +
86  x_table[attack_index_x] +
87  x_table[defense_index_x]);
88  }
90  int attack_index, int defense_index,
91  int attack_index_y, int defense_index_y,
92  int attack_index_x, int defense_index_x)
93  {
94  return (stand_table[attack_index] +
95  stand_table[defense_index + 9] +
96  y_stand_table[attack_index_y] +
97  y_stand_table[defense_index_y + 81] +
98  x_stand_table[attack_index_x] +
99  x_stand_table[defense_index_x]);
100  }
101  static MultiInt eval(const NumEffectState &state);
102  template<Player P>
103  static MultiInt evalWithUpdate(const NumEffectState &state,
104  Move moved,
105  MultiInt &last_value)
106  {
108  Ptype captured = moved.capturePtype();
109  if (moved.ptype() == KING ||
110  (moved.isDrop() && moved.ptype() == PAWN &&
111  !state.hasPieceOnStand<PAWN>(P)) ||
112  (captured != PTYPE_EMPTY &&
113  unpromote(captured) == PAWN &&
114  state.countPiecesOnStand<PAWN>(P) == 1))
115  {
116  return eval(state);
117  }
118 
119  MultiInt result(last_value);
120  const CArray<Square, 2> king_bw = {{ state.kingSquare<BLACK>(), state.kingSquare<WHITE>() }};
121  const CArray<Square, 2> kings = {{ king_bw[playerToIndex(P)], king_bw[playerToIndex(alt(P))] }};
122  const CArray<Piece, 2> king_piece = {{ state.kingPiece(P),
123  state.kingPiece(alt(P)) }};
124  if (moved.oldPtype() == PAWN)
125  {
126  if (moved.isDrop())
127  {
128  const int attack_index = index(kings[1], moved.to().x());
129  const int defense_index = index(kings[0], moved.to().x());
130  const int attack_index_x =
131  indexX<true>(king_piece[1], moved.to().x());
132  const int defense_index_x =
133  indexX<false>(king_piece[0], moved.to().x());
134 
135  const int attack_index_y = indexY<altP>(king_piece[1], moved.to().x());
136  const int defense_index_y = indexY<P>(king_piece[0], moved.to().x());
137  const int index_x = (moved.to().x() > 5 ? 10 -
138  moved.to().x() : moved.to().x());
139  if (state.isPawnMaskSet<altP>(moved.to().x()))
140  {
141  if (P == BLACK)
142  {
143  result -= drop_non_drop_table[index_x - 1 + 5];
144  result += drop_non_drop_table[index_x - 1];
145  result -=
146  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
147  OPP_ON_BOARD * 9];
148  result +=
149  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
150  SELF_ON_BOARD * 9];
151  }
152  else
153  {
154  result -= drop_non_drop_table[index_x - 1];
155  result += drop_non_drop_table[index_x - 1 + 5];
156  result -=
157  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
158  SELF_ON_BOARD * 9];
159  result +=
160  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
161  OPP_ON_BOARD * 9];
162  }
163  result +=
164  state_king_relative_table[std::abs(king_bw[BLACK].x() -
165  moved.to().x()) +
166  BOTH_ON_BOARD * 9];
167  result -=
168  state_king_relative_table[std::abs(king_bw[WHITE].x() -
169  moved.to().x()) +
170  BOTH_ON_BOARD * 9];
171  }
172  else
173  {
174  result -=
175  state_king_relative_table[std::abs(king_bw[BLACK].x() -
176  moved.to().x()) +
177  BOTH_ON_STAND * 9];
178  result +=
179  state_king_relative_table[std::abs(king_bw[WHITE].x() -
180  moved.to().x()) +
181  BOTH_ON_STAND * 9];
182  if (P == BLACK)
183  {
184  result += drop_non_drop_table[index_x - 1];
185  result -= drop_non_drop_table[index_x - 1 + 5];
186  result +=
187  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
188  SELF_ON_BOARD * 9];
189  result -=
190  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
191  OPP_ON_BOARD * 9];
192  }
193  else
194  {
195  result += drop_non_drop_table[index_x - 1 + 5];
196  result -= drop_non_drop_table[index_x - 1];
197  result +=
198  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
199  OPP_ON_BOARD * 9];
200  result -=
201  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
202  SELF_ON_BOARD * 9];
203  }
204  }
205  if (P == BLACK)
206  {
207  result -= value(attack_index, defense_index, attack_index_y,
208  defense_index_y, attack_index_x, defense_index_x);
209  if (state.hasPieceOnStand<PAWN>(P))
210  {
211  result -= standValue(attack_index, defense_index, attack_index_y,
212  defense_index_y, attack_index_x, defense_index_x);
213  }
214  }
215  else
216  {
217  result += value(attack_index, defense_index, attack_index_y,
218  defense_index_y, attack_index_x, defense_index_x);
219  if (state.hasPieceOnStand<PAWN>(P))
220  {
221  result += standValue(attack_index, defense_index, attack_index_y,
222  defense_index_y, attack_index_x, defense_index_x);
223  }
224  }
225  }
226  if (moved.isPromotion())
227  {
228  const int attack_index = index(kings[1], moved.to().x());
229  const int defense_index = index(kings[0], moved.to().x());
230  const int attack_index_x =
231  indexX<true>(king_piece[1], moved.to().x());
232  const int defense_index_x =
233  indexX<false>(king_piece[0], moved.to().x());
234  const int attack_index_y = indexY<altP>(king_piece[1], moved.to().x());
235  const int defense_index_y = indexY<P>(king_piece[0], moved.to().x());
236  if (P == BLACK)
237  {
238  result += value(attack_index, defense_index, attack_index_y,
239  defense_index_y, attack_index_x, defense_index_x);
240  if (state.hasPieceOnStand<PAWN>(P))
241  {
242  result += standValue(attack_index, defense_index, attack_index_y,
243  defense_index_y, attack_index_x, defense_index_x);
244  }
245  }
246  else
247  {
248  result -= value(attack_index, defense_index, attack_index_y,
249  defense_index_y, attack_index_x, defense_index_x);
250  if (state.hasPieceOnStand<PAWN>(P))
251  {
252  result -= standValue(attack_index, defense_index, attack_index_y,
253  defense_index_y, attack_index_x, defense_index_x);
254  }
255  }
256  const int index_x = (moved.to().x() > 5 ? 10 -
257  moved.to().x() : moved.to().x());
258  if (state.isPawnMaskSet<altP>(moved.to().x()))
259  {
260  result -=
261  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
262  BOTH_ON_BOARD * 9];
263  result +=
264  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
265  BOTH_ON_BOARD * 9];
266  if (P == BLACK)
267  {
268  result += drop_non_drop_table[index_x - 1 + 5];
269  result -= drop_non_drop_table[index_x - 1];
270  result +=
271  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
272  OPP_ON_BOARD * 9];
273  result -=
274  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
275  SELF_ON_BOARD * 9];
276  }
277  else
278  {
279  result += drop_non_drop_table[index_x - 1];
280  result -= drop_non_drop_table[index_x - 1 + 5];
281  result +=
282  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
283  SELF_ON_BOARD * 9];
284  result -=
285  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
286  OPP_ON_BOARD * 9];
287  }
288  }
289  else
290  {
291  result +=
292  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
293  BOTH_ON_STAND * 9];
294  result -=
295  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
296  BOTH_ON_STAND * 9];
297  if (captured == PAWN)
298  {
299  result -=
300  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
301  BOTH_ON_BOARD * 9];
302  result +=
303  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
304  BOTH_ON_BOARD * 9];
305  }
306  else
307  {
308  if (P == BLACK)
309  {
310  result -= drop_non_drop_table[index_x - 1];
311  result += drop_non_drop_table[index_x - 1 + 5];
312  result -=
313  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
314  SELF_ON_BOARD * 9];
315  result +=
316  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
317  OPP_ON_BOARD * 9];
318  }
319  else
320  {
321  result -= drop_non_drop_table[index_x - 1 + 5];
322  result += drop_non_drop_table[index_x - 1];
323  result -=
324  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
325  OPP_ON_BOARD * 9];
326  result +=
327  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
328  SELF_ON_BOARD * 9];
329  }
330  }
331  }
332  }
333  }
334 
335  if (captured == PAWN)
336  {
337  const int attack_index = index(kings[0], moved.to().x());
338  const int defense_index = index(kings[1], moved.to().x());
339  const int attack_index_x =
340  indexX<true>(king_piece[0], moved.to().x());
341  const int defense_index_x =
342  indexX<false>(king_piece[1], moved.to().x());
343  const int attack_index_y = indexY<P>(king_piece[0], moved.to().x());
344  const int defense_index_y = indexY<altP>(king_piece[1], moved.to().x());
345  if (P == BLACK)
346  {
347  result -= value(attack_index, defense_index, attack_index_y,
348  defense_index_y, attack_index_x, defense_index_x);
349  if (state.hasPieceOnStand<PAWN>(alt(P)))
350  {
351  result -= standValue(attack_index, defense_index, attack_index_y,
352  defense_index_y, attack_index_x, defense_index_x);
353  }
354  }
355  else
356  {
357  result += value(attack_index, defense_index, attack_index_y,
358  defense_index_y, attack_index_x, defense_index_x);
359  if (state.hasPieceOnStand<PAWN>(alt(moved.player())))
360  {
361  result += standValue(attack_index, defense_index, attack_index_y,
362  defense_index_y, attack_index_x, defense_index_x);
363  }
364  }
365  if (!(moved.ptype() == PPAWN && moved.isPromotion())) // promote is already handled above
366  {
367  const int index_x =
368  (moved.to().x() > 5 ? 10 - moved.to().x() : moved.to().x());
369  if (state.isPawnMaskSet<P>(moved.to().x()))
370  {
371  result -=
372  state_king_relative_table[std::abs(king_bw[BLACK].x() -
373  moved.to().x()) +
374  BOTH_ON_BOARD * 9];
375  result +=
376  state_king_relative_table[std::abs(king_bw[WHITE].x() -
377  moved.to().x()) +
378  BOTH_ON_BOARD * 9];
379  if (P == BLACK)
380  {
381  result += drop_non_drop_table[index_x - 1];
382  result -= drop_non_drop_table[index_x - 1 + 5];
383  result +=
384  state_king_relative_table[std::abs(king_bw[BLACK].x() -
385  moved.to().x()) +
386  SELF_ON_BOARD * 9];
387  result -=
388  state_king_relative_table[std::abs(king_bw[WHITE].x() -
389  moved.to().x()) +
390  OPP_ON_BOARD * 9];
391  }
392  else
393  {
394  result += drop_non_drop_table[index_x - 1 + 5];
395  result -= drop_non_drop_table[index_x - 1];
396  result +=
397  state_king_relative_table[std::abs(king_bw[BLACK].x() -
398  moved.to().x()) +
399  OPP_ON_BOARD * 9];
400  result -=
401  state_king_relative_table[std::abs(king_bw[WHITE].x() -
402  moved.to().x()) +
403  SELF_ON_BOARD * 9];
404  }
405  }
406  else
407  {
408  if (P == BLACK)
409  {
410  result -= drop_non_drop_table[index_x - 1 + 5];
411  result += drop_non_drop_table[index_x - 1];
412  result -=
413  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
414  OPP_ON_BOARD * 9];
415  result +=
416  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
417  SELF_ON_BOARD * 9];
418  }
419  else
420  {
421  result -= drop_non_drop_table[index_x - 1];
422  result += drop_non_drop_table[index_x - 1 + 5];
423  result -=
424  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
425  SELF_ON_BOARD * 9];
426  result +=
427  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
428  OPP_ON_BOARD * 9];
429  }
430  result +=
431  state_king_relative_table[std::abs(king_bw[BLACK].x() - moved.to().x()) +
432  BOTH_ON_STAND * 9];
433  result -=
434  state_king_relative_table[std::abs(king_bw[WHITE].x() - moved.to().x()) +
435  BOTH_ON_STAND * 9];
436  }
437  }
438  }
439  return result;
440  }
441  };
442 
443  class PawnDropX
444  {
445  public:
446  enum { ONE_DIM = 90, DIM = ONE_DIM * EvalStages };
447  static void setUp(const Weights &weights);
448  };
449 
451  {
452  public:
453  enum { ONE_DIM = 18, DIM = ONE_DIM * EvalStages };
454  static void setUp(const Weights &weights);
455  };
457  {
458  public:
459  enum { ONE_DIM = 90, DIM = ONE_DIM * EvalStages };
460  static void setUp(const Weights &weights);
461  };
463  {
464  public:
465  enum { ONE_DIM = 162, DIM = ONE_DIM * EvalStages };
466  static void setUp(const Weights &weights);
467  };
468 
470  {
471  public:
472  enum { ONE_DIM = 10, DIM = ONE_DIM * EvalStages };
473  static void setUp(const Weights &weights);
474  };
475 
477  {
478  public:
479  enum { ONE_DIM = 36, DIM = ONE_DIM * EvalStages };
480  static void setUp(const Weights &weights);
481  };
482 
484  {
485  public:
486  enum { DIM = 1 };
487  private:
488  static MultiInt weight;
489  public:
490  static void setUp(const Weights &weights,int stage);
491  static MultiInt eval(const NumEffectState &state, int black_pawn_count)
492  {
493  if (black_pawn_count > 9 && !state.hasPieceOnStand<PAWN>(WHITE))
494  return -weight;
495  else if (black_pawn_count < 9 && !state.hasPieceOnStand<PAWN>(BLACK))
496  return weight;
497 
498  return MultiInt();
499  }
500  };
501 
503  {
504  static int index(Player P, Square pos)
505  {
506  return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
507  }
508  static bool cantAdvance(const NumEffectState &state, const Piece pawn)
509  {
510  return cantAdvance(state, pawn.ptypeO(), pawn.square());
511  }
512  static bool cantAdvance(const NumEffectState &state,
513  const PtypeO ptypeO, const Square position)
514  {
515  assert(getPtype(ptypeO) == PAWN);
516  return state.pieceAt(Board_Table.nextSquare(getOwner(ptypeO),
517  position,
518  U)).isOnBoardByOwner(getOwner(ptypeO));
519  }
520  };
522  {
523  template <osl::Player P>
524  static void adjust(int index, MultiInt& values);
525  template<Player P>
526  static void evalWithUpdateBang(const NumEffectState &state, Move moved,
527  MultiInt& last_value);
528  };
529 
531  {
532  public:
533  enum { DIM = 9 };
534  private:
535  static CArray<MultiInt, 9> table;
536  friend struct PawnAdvanceAll;
537  public:
538  static void setUp(const Weights &weights,int stage);
539  static MultiInt eval(const NumEffectState &state);
540  };
541 
543  {
544  public:
545  static MultiInt eval(const NumEffectState &state);
546  protected:
547  template <Player P>
548  static int indexRetreat(Square pos)
549  {
550  return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
551  }
552  template<Player P>
553  static bool canRetreat(const NumEffectState &state,
554  const Piece silver);
555  template <Player P>
556  static MultiInt evalOne(const NumEffectState &state,
557  const Piece silver,
558  const CArray<Square, 2> &kings)
559  {
561  if (!canRetreat<P>(state,silver))
562  {
563  result += retreat_table[indexRetreat<P>(silver.square())];
564  }
565  const Square up =
567  if (up.isOnBoard())
568  {
569  const Piece up_piece = state.pieceAt(up);
570  if (up_piece.isEmpty() &&
571  (state.hasEffectByPtype<PAWN>(alt(P), up) ||
572  !state.isPawnMaskSet<PlayerTraits<P>::opponent>(silver.square().x())))
573  {
574  const int x_diff =
575  std::abs(kings[P].x() - silver.square().x());
576  const int y_diff = (P == BLACK ?
577  silver.square().y() - kings[P].y() :
578  kings[P].y() - silver.square().y());
579  result += head_table[x_diff + 9 * (y_diff + 8)];
580  }
581  }
582  return result;
583  }
584  static CArray<MultiInt, 153> head_table;
585  static CArray<MultiInt, 9> retreat_table;
586  };
587 
589  {
590  public:
591  enum { ONE_DIM = 153, DIM = ONE_DIM * EvalStages };
592  static void setUp(const Weights &weights);
593  };
594 
596  {
597  public:
598  enum { DIM = 9 };
599  static void setUp(const Weights &weights,int stage);
600  };
601 
603  {
604  public:
605  static MultiInt eval(const NumEffectState &state);
606  protected:
607  template <Player P>
608  static int indexRetreat(Square pos)
609  {
610  return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
611  }
612  static int indexSideX(Square pos)
613  {
614  return (pos.x() > 5 ? 9 - pos.x() : pos.x() - 1);
615  }
616  template <Player P>
617  static int indexSideY(Square pos)
618  {
619  return (P == BLACK ? (pos.y() - 1) : (9 - pos.y())) + 5;
620  }
621  template<Player P>
622  static bool canRetreat(const NumEffectState &state,
623  const Piece gold);
624  template<Player P>
625  static bool canMoveToSide(const NumEffectState &state,
626  const Piece gold)
627  {
630  // check effect is from lesser pieces?
631  if ((!r.isOnBoard() ||
632  state.pieceAt(r).isOnBoardByOwner(gold.owner()) ||
633  state.hasEffectAt(alt(gold.owner()), r)) &&
634  (!l.isOnBoard() ||
635  state.pieceAt(l).isOnBoardByOwner(gold.owner()) ||
636  state.hasEffectAt(alt(gold.owner()), l)))
637  {
638  return false;
639  }
640  return true;
641  }
642  template <Player P>
643  static MultiInt evalOne(const NumEffectState &state,
644  const Piece gold,
645  const CArray<Square, 2> &kings)
646  {
647  assert(P==gold.owner());
649  if (!canRetreat<P>(state, gold))
650  {
651  result += retreat_table[indexRetreat<P>(gold.square())];
652  }
653  if (!canMoveToSide<P>(state, gold))
654  {
655  result += side_table[indexSideX(gold.square())] +
656  side_table[indexSideY<P>(gold.square())];
657  }
658  const Square uur = gold.square().neighbor<P,UUR>();
659  const Square uul = gold.square().neighbor<P,UUL>();
660  if ((state.pieceAt(uul).isEmpty() && !state.hasEffectAt(P, uul))
661  || (state.pieceAt(uur).isEmpty() && !state.hasEffectAt(P, uur)))
662  {
663  assert(state.kingSquare(gold.owner()) == kings[gold.owner()]);
664  const Square king = kings[P];
665  const int x_diff = std::abs(king.x() - gold.square().x());
666  const int y_diff = (P == BLACK ?
667  gold.square().y() - king.y() :
668  king.y() - gold.square().y());
669  result += knight_table[x_diff + 9 * (y_diff + 8)];
670  }
671  return result;
672  }
673  static CArray<MultiInt, 153> knight_table;
674  static CArray<MultiInt, 9> retreat_table;
675  static CArray<MultiInt, 14> side_table;
676  };
677 
679  {
680  public:
681  enum { ONE_DIM = 153, DIM = ONE_DIM * EvalStages };
682  static void setUp(const Weights &weights);
683  };
684 
685  class GoldRetreat : public GoldFeatures
686  {
687  public:
688  enum { DIM = 9 };
689  static void setUp(const Weights &weights,int stage);
690  };
691 
692  class GoldSideMove : public GoldFeatures
693  {
694  public:
695  enum { ONE_DIM = 14, DIM = ONE_DIM * EvalStages };
696  static void setUp(const Weights &weights);
697  };
698 
700  {
701  public:
702  enum { DIM = 9 };
703  private:
704  static CArray<MultiInt, 9> table;
705  static int index(Player P, Square pos)
706  {
707  return (P == BLACK ? (pos.y() - 1) : (9 - pos.y()));
708  }
709  template<Player P>
710  static bool cantAdvance(const NumEffectState &state,
711  const Piece knight);
712  public:
713  static void setUp(const Weights &weights,int stage);
714  static MultiInt eval(const NumEffectState &state);
715  };
716 
717  class AllGold
718  {
719  public:
720  enum { DIM = 1 };
721  static void setUp(const Weights &weights,int stage);
722  static MultiInt eval(int black_major_count)
723  {
724  if (black_major_count == 4)
725  return weight;
726  else if (black_major_count == 0)
727  return -weight;
728 
729  return MultiInt();
730  }
731  private:
732  static MultiInt weight;
733  };
734 
735  class PtypeY
736  {
737  public:
738  enum { DIM = PTYPE_SIZE * 9 };
739  static void setUp(const Weights &weights,int stage);
740  static MultiInt eval(const NumEffectState &state);
741  template<Player P>
742  static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
743  MultiInt const& last_value);
744  private:
745  static CArray<MultiInt, 144> table;
746  static int index(const Piece piece)
747  {
748  return index(piece.owner(), piece.ptype(), piece.square());
749  }
750  static int index(const Player player, const Ptype ptype, const Square pos)
751  {
752  const int y = (player == BLACK ? pos.y() : 10 - pos.y()) - 1;
753  return ptype * 9 + y;
754  }
755  };
756 
757  class PtypeX
758  {
759  public:
760  enum { DIM = PTYPE_SIZE * 5 };
761  static void setUp(const Weights &weights,int stage);
762  static MultiInt eval(const NumEffectState &state);
763  template<Player P>
764  static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
765  MultiInt const& last_value);
766  private:
767  static CArray<MultiInt, 80> table;
768  static int index(const Piece piece)
769  {
770  return index(piece.owner(), piece.ptype(), piece.square());
771  }
772  static int index(const Player, const Ptype ptype, const Square pos)
773  {
774  const int x = (pos.x() > 5 ? 10 - pos.x() : pos.x()) - 1;
775  return ptype * 5 + x;
776  }
777  };
778 
780  {
781  friend class KnightCheckY;
782  public:
783  enum { DIM = 1 };
784  static void setUp(const Weights &weights,int stage);
785  static MultiInt eval(const NumEffectState &state);
786  template <Player Defense>
787  static bool canCheck(const NumEffectState &state)
788  {
789  const Square king = state.kingSquare<Defense>();
790  const Player offense = PlayerTraits<Defense>::opponent;
791  const Square ul =
793  const Square ur =
795  if (ul.isOnBoard())
796  {
797  const Piece p = state.pieceAt(ul);
798  if (!state.hasEffectAt<Defense>(ul) &&
799  ((p.isEmpty() && state.hasPieceOnStand<KNIGHT>(offense)) ||
800  (!p.isOnBoardByOwner<offense>() &&
801  state.hasEffectByPtypeStrict<KNIGHT>(offense, ul))))
802  return true;
803  }
804  if (ur.isOnBoard())
805  {
806  const Piece p = state.pieceAt(ur);
807  if (!state.hasEffectAt<Defense>(ur) &&
808  ((p.isEmpty() && state.hasPieceOnStand<KNIGHT>(offense)) ||
809  (!p.isOnBoardByOwner<offense>() &&
810  state.hasEffectByPtypeStrict<KNIGHT>(offense, ur))))
811  return true;
812  }
813  return false;
814  }
815  static MultiInt value(int index_y) { return weight + y_table[index_y]; }
816  private:
817  static MultiInt weight;
818  template <Player King>
819  static int indexY(int y)
820  {
821  return (King == BLACK ? y - 1 : 9 - y) ;
822  }
823  static CArray<MultiInt, 9> y_table;
824  };
825 
827  {
828  public:
829  enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages };
830  static void setUp(const Weights &weights);
831  };
832 
834  {
836  public:
837  enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages};
838  static void setUp(const Weights &weights);
839  static MultiInt eval(const NumEffectState &state);
840  private:
841  static CArray<MultiInt, 9> table;
842  static CArray<MultiInt, 144> opp_table;
843  };
844 
846  {
847  public:
848  enum { ONE_DIM = 9 * 16, DIM = ONE_DIM * EvalStages};
849  static void setUp(const Weights &weights);
850  private:
851  };
852 
854  {
855  friend class PawnPtypeOPtypeOY;
856  public:
857  enum { ONE_DIM = 1024, DIM = ONE_DIM * EvalStages };
858  static void setUp(const Weights &weights);
859  static MultiInt eval(const NumEffectState &state);
860  template<Player P>
861  static MultiInt evalWithUpdate(const NumEffectState &state,
862  Move moved,
863  const CArray2d<int, 2, 9> &pawns,
864  const MultiInt &last_value);
865  private:
866  static int index(Player P, PtypeO up, PtypeO up_up)
867  {
868  if (P == WHITE)
869  {
870  up = altIfPiece(up);
871  up_up = altIfPiece(up_up);
872  }
873  return (up - PTYPEO_MIN) * 32 + (up_up - PTYPEO_MIN);
874  }
875  static int indexY(Player P, PtypeO up, PtypeO up_up, int y)
876  {
877  const int y_index = (P == BLACK ? y - 1 : 9 - y);
878  return index(P, up, up_up) + 1024 * y_index;
879  }
880  static CArray<MultiInt, 1024> table;
881  static CArray<MultiInt, 9216> y_table;
882  };
883 
885  {
886  friend class PromotedMinorPiecesY;
887  public:
888  enum { ONE_DIM = 9, DIM = ONE_DIM * EvalStages };
889  static void setUp(const Weights &weights);
890  static MultiInt eval(const NumEffectState &state);
891  static MultiInt evalWithUpdate(
892  const NumEffectState &state,
893  Move moved,
894  const MultiInt &last_values);
895  template <int Sign>
896  static void adjust(int index, int index_attack, int index_defense,
897  MultiInt &result);
898  private:
899  template <Player P>
900  static void evalOne(const NumEffectState &state,
901  const PieceMask promoted,
902  MultiInt &result);
903  template <bool attack, Player owner>
904  static int indexY(const Square king, int x_diff)
905  {
906  const int y = (owner == BLACK ? king.y() : 10 - king.y());
907  return x_diff + (y - 1) * 9 + (attack ? 0 : 81);
908  }
909  static CArray<MultiInt, 9> table;
910  static CArray<MultiInt, 162> y_table;
911  };
913  {
915  public:
916  enum { ONE_DIM = 64, DIM = ONE_DIM * EvalStages };
917  static void setUp(const Weights &weights);
918  static void eval(const NumEffectState &state, MultiIntPair& out);
919  template<Player P>
920  static void evalWithUpdateBang(
921  const NumEffectState &state,
922  Move moved,
923  const CArray<PieceMask, 2> &effected_mask,
924  MultiIntPair &last_value_and_out);
925  template <int Sign>
926  static void adjust(int black_turn_king_attack,
927  int black_turn_king_defense,
928  int white_turn_king_attack,
929  int white_turn_king_defense,
931  private:
932  static int index(bool same_turn, bool has_support, Ptype ptype)
933  {
934  return ptype + (same_turn ? 0 : PTYPE_SIZE) +
935  (has_support ? 0 : PTYPE_SIZE * 2);
936  }
937  template <bool Attack>
938  static int indexK(Square king, bool same_turn, bool has_support,
939  Square position, Player owner, Ptype ptype)
940  {
941  const int x_diff = std::abs(position.x() - king.x());
942  const int y_diff = (owner == BLACK ?
943  position.y() - king.y() :
944  king.y() - position.y());
945  return ((ptype + (same_turn ? 0 : PTYPE_SIZE) +
946  (has_support ? 0 : PTYPE_SIZE * 2)) * 9 + x_diff) * 17 +
947  y_diff + 8 + (Attack ? 0 : 9792);
948  }
949  template <bool Attack>
950  static int indexK(Square king, bool same_turn, bool has_support,
951  Piece piece)
952  {
953  return indexK<Attack>(king, same_turn, has_support,
954  piece.square(), piece.owner(),
955  piece.ptype());
956  }
957 
958  template <Player Attacked>
959  static void updateEffectChanged(
960  const NumEffectState &state,
961  const CArray<PieceMask, 2> &effected_mask,
962  const CArray<PieceMask, 2> &new_mask,
963  int moved_piece_number,
965  {
966  CArray<Square, 2> kings = {{ state.kingSquare<BLACK>(),
967  state.kingSquare<WHITE>() }};
968  // old without, new with
969  PieceMask black_old = (~effected_mask[alt(Attacked)]) & new_mask[alt(Attacked)] & state.piecesOnBoard(Attacked);
970  black_old.reset(moved_piece_number);
971  while (black_old.any())
972  {
973  const Piece piece = state.pieceOf(black_old.takeOneBit());
974  const bool has_support =
975  new_mask[Attacked].test(piece.number());
976  const int index_king_black_turn_attack =
977  indexK<true>(kings[alt(Attacked)], Attacked == BLACK, has_support, piece);
978  const int index_king_white_turn_attack =
979  indexK<true>(kings[alt(Attacked)], Attacked == WHITE, has_support, piece);
980  const int index_king_black_turn_defense =
981  indexK<false>(kings[Attacked], Attacked == BLACK, has_support, piece);
982  const int index_king_white_turn_defense =
983  indexK<false>(kings[Attacked], Attacked == WHITE, has_support, piece);
984  adjust<Attacked == BLACK ? 1 : -1>(
985  index_king_black_turn_attack, index_king_black_turn_defense,
986  index_king_white_turn_attack, index_king_white_turn_defense,
987  result);
988  }
989 
990  // old with, new without
991  PieceMask black_new = effected_mask[alt(Attacked)] & (~new_mask[alt(Attacked)]) & state.piecesOnBoard(Attacked);
992  black_new.reset(moved_piece_number);
993  while (black_new.any())
994  {
995  const Piece piece = state.pieceOf(black_new.takeOneBit());
996  const bool has_support =
997  effected_mask[Attacked].test(piece.number());
998  const int index_king_black_turn_attack =
999  indexK<true>(kings[alt(Attacked)], Attacked == BLACK, has_support, piece);
1000  const int index_king_white_turn_attack =
1001  indexK<true>(kings[alt(Attacked)], Attacked == WHITE, has_support, piece);
1002  const int index_king_black_turn_defense =
1003  indexK<false>(kings[Attacked], Attacked == BLACK, has_support, piece);
1004  const int index_king_white_turn_defense =
1005  indexK<false>(kings[Attacked], Attacked == WHITE, has_support, piece);
1006  adjust<Attacked == BLACK ? -1 : 1>(
1007  index_king_black_turn_attack, index_king_black_turn_defense,
1008  index_king_white_turn_attack, index_king_white_turn_defense,
1009  result);
1010  }
1011  // old with, new with, self with, self without
1012  PieceMask black_self_old = effected_mask[alt(Attacked)] & new_mask[alt(Attacked)] &
1013  effected_mask[Attacked] & (~new_mask[Attacked]) & state.piecesOnBoard(Attacked);
1014  black_self_old.reset(moved_piece_number);
1015  while (black_self_old.any())
1016  {
1017  const Piece piece = state.pieceOf(black_self_old.takeOneBit());
1018  const int index_king_black_turn_attack =
1019  indexK<true>(kings[alt(Attacked)], Attacked == BLACK, false, piece);
1020  const int index_king_white_turn_attack =
1021  indexK<true>(kings[alt(Attacked)], Attacked == WHITE, false, piece);
1022  const int index_king_black_turn_defense =
1023  indexK<false>(kings[Attacked], Attacked == BLACK, false, piece);
1024  const int index_king_white_turn_defense =
1025  indexK<false>(kings[Attacked], Attacked == WHITE, false, piece);
1026  const int index_king_black_turn_attack_old =
1027  indexK<true>(kings[alt(Attacked)], Attacked == BLACK, true, piece);
1028  const int index_king_white_turn_attack_old =
1029  indexK<true>(kings[alt(Attacked)], Attacked == WHITE, true, piece);
1030  const int index_king_black_turn_defense_old =
1031  indexK<false>(kings[Attacked], Attacked == BLACK, true, piece);
1032  const int index_king_white_turn_defense_old =
1033  indexK<false>(kings[Attacked], Attacked == WHITE, true, piece);
1034  adjust<Attacked == BLACK ? -1 : 1>(
1035  index_king_black_turn_attack_old, index_king_black_turn_defense_old,
1036  index_king_white_turn_attack_old, index_king_white_turn_defense_old,
1037  result);
1038  adjust<Attacked == BLACK ? 1 : -1>(
1039  index_king_black_turn_attack, index_king_black_turn_defense,
1040  index_king_white_turn_attack, index_king_white_turn_defense,
1041  result);
1042  }
1043  // old with, new with, self without, self with
1044  PieceMask black_self_new = effected_mask[alt(Attacked)] & new_mask[alt(Attacked)] &
1045  (~effected_mask[Attacked]) & new_mask[Attacked] & state.piecesOnBoard(Attacked);
1046  black_self_new.reset(moved_piece_number);
1047  while (black_self_new.any())
1048  {
1049  const Piece piece = state.pieceOf(black_self_new.takeOneBit());
1050  const int index_king_black_turn_attack =
1051  indexK<true>(kings[alt(Attacked)], Attacked == BLACK, true, piece);
1052  const int index_king_white_turn_attack =
1053  indexK<true>(kings[alt(Attacked)], Attacked == WHITE, true, piece);
1054  const int index_king_black_turn_defense =
1055  indexK<false>(kings[Attacked], Attacked == BLACK, true, piece);
1056  const int index_king_white_turn_defense =
1057  indexK<false>(kings[Attacked], Attacked == WHITE, true, piece);
1058  const int index_king_black_turn_attack_old =
1059  indexK<true>(kings[alt(Attacked)], Attacked == BLACK, false, piece);
1060  const int index_king_white_turn_attack_old =
1061  indexK<true>(kings[alt(Attacked)], Attacked == WHITE, false, piece);
1062  const int index_king_black_turn_defense_old =
1063  indexK<false>(kings[Attacked], Attacked == BLACK, false, piece);
1064  const int index_king_white_turn_defense_old =
1065  indexK<false>(kings[Attacked], Attacked == WHITE, false, piece);
1066 
1067  adjust<Attacked == BLACK ? -1 : 1>(
1068  index_king_black_turn_attack_old, index_king_black_turn_defense_old,
1069  index_king_white_turn_attack_old, index_king_white_turn_defense_old,
1070  result);
1071  adjust<Attacked == BLACK ? 1 : -1>(
1072  index_king_black_turn_attack, index_king_black_turn_defense,
1073  index_king_white_turn_attack, index_king_white_turn_defense,
1074  result);
1075  }
1076  }
1077  static CArray<MultiInt, 64> table;
1078  static CArray<MultiInt, 19584> king_table;
1079  };
1080 
1082  {
1083  public:
1084  enum { ONE_DIM = 19584, DIM = ONE_DIM * EvalStages};
1085  static void setUp(const Weights &weights);
1086  };
1087 
1089  {
1090  public:
1091  enum { ONE_DIM = 162, DIM = ONE_DIM * EvalStages };
1092  static void setUp(const Weights &weights);
1093  };
1094 
1096  {
1097  public:
1098  enum { ONE_DIM = 9216, DIM = ONE_DIM * EvalStages };
1099  static void setUp(const Weights &weights);
1100  };
1101 
1103  {
1104  public:
1105  enum { ONE_DIM = 1024, DIM = ONE_DIM * EvalStages};
1106  static void setUp(const Weights &weights);
1107  static void eval(const NumEffectState &state,
1108  CArray<PieceMask, 40> &attacked_mask,
1109  MultiIntPair& out);
1110  template<Player P>
1111  static void evalWithUpdateBang(
1112  const NumEffectState &state,
1113  Move moved,
1114  const CArray<PieceMask, 2> &effected_mask,
1115  CArray<PieceMask, 40> &attacked_mask,
1116  MultiIntPair &last_value_and_out);
1117  private:
1118  static int index(bool same_turn, bool has_support, Ptype ptype,
1119  Ptype attack_ptype)
1120  {
1121  return (ptype + (same_turn ? 0 : PTYPE_SIZE) +
1122  (has_support ? 0 : PTYPE_SIZE * 2)) * 16 + attack_ptype;
1123  }
1124  template <int Sign>
1125  static void adjust(int black, int white, MultiIntPair &result)
1126  {
1127  if(Sign>0){
1128  result[BLACK] += table[black];
1129  result[WHITE] += table[white];
1130  }
1131  else{
1132  result[BLACK] -= table[black];
1133  result[WHITE] -= table[white];
1134  }
1135  }
1136  template <bool Plus>
1137  static void evalOnePiece(const Player player,
1138  const Ptype ptype,
1139  const Ptype attack_ptype,
1140  bool with_support,
1142  {
1143  const int index_black_turn = index(BLACK == player, with_support,
1144  ptype, attack_ptype);
1145  const int index_white_turn = index(WHITE == player, with_support,
1146  ptype, attack_ptype);
1147  if (Plus)
1148  adjust<1>(index_black_turn, index_white_turn, result);
1149  else
1150  adjust<-1>(index_black_turn, index_white_turn, result);
1151  }
1152  template <Player P>
1153  static void updateChanged(const NumEffectState &state,
1154  const Piece p,
1155  Move moved,
1156  int captured_number,
1157  const CArray<PieceMask, 2> &effected_mask,
1158  const CArray<PieceMask, 2> &new_mask,
1159  CArray<PieceMask, 40> &attacked_mask,
1161  {
1162  // old without, new with
1163  PieceMask old = (~effected_mask[alt(P)]) & new_mask[alt(P)] & state.piecesOnBoard(P);
1164  old.reset(p.number());
1165  while (old.any())
1166  {
1167  const Piece piece = state.pieceOf(old.takeOneBit());
1168  const bool has_support =
1169  new_mask[P].test(piece.number());
1170  PieceMask attacking =
1171  state.effectSetAt(piece.square()) &
1172  state.piecesOnBoard(alt(P));
1173  attacked_mask[piece.number()] = attacking;
1174  while (attacking.any())
1175  {
1176  const Piece attack = state.pieceOf(attacking.takeOneBit());
1177  evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
1178  has_support, result);
1179  }
1180  }
1181  // old with, new without
1182  PieceMask new_without = effected_mask[alt(P)] & (~new_mask[alt(P)]) & state.piecesOnBoard(P);
1183  new_without.reset(p.number());
1184  while (new_without.any())
1185  {
1186  const Piece piece = state.pieceOf(new_without.takeOneBit());
1187  const bool has_support =
1188  effected_mask[P].test(piece.number());
1189  PieceMask attacking = attacked_mask[piece.number()];
1190  if (moved.isPromotion() && attacking.test(p.number()))
1191  {
1192  evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
1193  has_support, result);
1194  attacking.reset(p.number());
1195  }
1196  if (captured_number != -1 && attacking.test(captured_number))
1197  {
1198  evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
1199  has_support, result);
1200  attacking.reset(captured_number);
1201  }
1202  while (attacking.any())
1203  {
1204  const Piece attack = state.pieceOf(attacking.takeOneBit());
1205  evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
1206  has_support, result);
1207  }
1208  }
1209  // old with, new with, self with, self without
1210  PieceMask self_old = effected_mask[alt(P)] &
1211  new_mask[alt(P)] &
1212  effected_mask[P] & (~new_mask[P]) & state.piecesOnBoard(P);
1213  self_old.reset(p.number());
1214  while (self_old.any())
1215  {
1216  const Piece piece = state.pieceOf(self_old.takeOneBit());
1217  PieceMask old_attacking = attacked_mask[piece.number()];
1218  if (moved.isPromotion() && old_attacking.test(p.number()))
1219  {
1220  evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
1221  true, result);
1222  old_attacking.reset(p.number());
1223  }
1224  if (captured_number != -1 && old_attacking.test(captured_number))
1225  {
1226  evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
1227  true, result);
1228  old_attacking.reset(captured_number);
1229  }
1230  while (old_attacking.any())
1231  {
1232  const Piece attack = state.pieceOf(old_attacking.takeOneBit());
1233  evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
1234  true, result);
1235  }
1236  PieceMask new_attacking = state.effectSetAt(piece.square())
1237  & state.piecesOnBoard(alt(P));
1238  attacked_mask[piece.number()] = new_attacking;
1239  while (new_attacking.any())
1240  {
1241  const Piece attack = state.pieceOf(new_attacking.takeOneBit());
1242  evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
1243  false, result);
1244  }
1245  }
1246  // old with, new with, self without, self with
1247  PieceMask self_new_with = effected_mask[alt(P)] &
1248  new_mask[alt(P)] &
1249  (~effected_mask[P]) & new_mask[P] & state.piecesOnBoard(P);
1250  self_new_with.reset(p.number());
1251  while (self_new_with.any())
1252  {
1253  const Piece piece = state.pieceOf(self_new_with.takeOneBit());
1254  PieceMask old_attacking = attacked_mask[piece.number()];
1255  if (moved.isPromotion() && old_attacking.test(p.number()))
1256  {
1257  evalOnePiece<P != BLACK>(P, piece.ptype(), moved.oldPtype(),
1258  false, result);
1259  old_attacking.reset(p.number());
1260  }
1261  if (captured_number != -1 && old_attacking.test(captured_number))
1262  {
1263  evalOnePiece<P != BLACK>(P, piece.ptype(), moved.capturePtype(),
1264  false, result);
1265  old_attacking.reset(captured_number);
1266  }
1267  while (old_attacking.any())
1268  {
1269  const Piece attack = state.pieceOf(old_attacking.takeOneBit());
1270  evalOnePiece<P != BLACK>(P, piece.ptype(), attack.ptype(),
1271  false, result);
1272  }
1273  PieceMask new_attacking = state.effectSetAt(piece.square())
1274  & state.piecesOnBoard(alt(P));
1275  attacked_mask[piece.number()] = new_attacking;
1276  while (new_attacking.any())
1277  {
1278  const Piece attack = state.pieceOf(new_attacking.takeOneBit());
1279  evalOnePiece<P == BLACK>(P, piece.ptype(), attack.ptype(),
1280  true, result);
1281  }
1282  }
1283  // old with, new with, support unchanged, attack changed
1284  PieceMask effected = effected_mask[P];
1285  effected ^= new_mask[P];
1286  effected = ~effected;
1287  PieceMask attack_changed = effected_mask[alt(P)] &
1288  new_mask[alt(P)] &
1289  effected & state.piecesOnBoard(P) &
1290  state.effectedChanged(alt(P));
1291  attack_changed.reset(p.number());
1292  while (attack_changed.any())
1293  {
1294  const Piece attacked = state.pieceOf(attack_changed.takeOneBit());
1295  PieceMask attack_old_mask = attacked_mask[attacked.number()];
1296  PieceMask attack_new_mask = state.effectSetAt(attacked.square()) & state.piecesOnBoard(alt(P));
1297  if (captured_number != -1 &&
1298  attack_old_mask.test(captured_number))
1299  {
1300  evalOnePiece<P != BLACK>(P, attacked.ptype(),
1301  moved.capturePtype(),
1302  new_mask[P].test(attacked.number()),
1303  result);
1304  attack_old_mask.reset(captured_number);
1305  }
1306  if (moved.isPromotion() &&
1307  attack_old_mask.test(p.number()))
1308  {
1309  evalOnePiece<P != BLACK>(P, attacked.ptype(),
1310  moved.oldPtype(),
1311  new_mask[P].test(attacked.number()),
1312  result);
1313  attack_old_mask.reset(p.number());
1314  }
1315  if (moved.isPromotion() &&
1316  attack_new_mask.test(p.number()))
1317  {
1318  evalOnePiece<P == BLACK>(P, attacked.ptype(),
1319  moved.ptype(),
1320  new_mask[P].test(attacked.number()),
1321  result);
1322  attack_new_mask.reset(p.number());
1323  }
1324  PieceMask gone = attack_old_mask & (~attack_new_mask);
1325  while (gone.any())
1326  {
1327  const Piece attacking = state.pieceOf(gone.takeOneBit());
1328  evalOnePiece<P != BLACK>(P, attacked.ptype(),
1329  attacking.ptype(),
1330  effected_mask[P].test(attacked.number()),
1331  result);
1332  }
1333  PieceMask added = (~attack_old_mask) & attack_new_mask;
1334  while (added.any())
1335  {
1336  const Piece attacking = state.pieceOf(added.takeOneBit());
1337  evalOnePiece<P == BLACK>(P, attacked.ptype(),
1338  attacking.ptype(),
1339  new_mask[P].test(attacked.number()),
1340  result);
1341  }
1342 
1343  attacked_mask[attacked.number()] = state.effectSetAt(attacked.square()) & state.piecesOnBoard(alt(P));
1344  }
1345  }
1346 
1347  static CArray<MultiInt, 1024> table;
1348  };
1349 
1351  {
1352  public:
1353  enum {
1356  };
1357  static void setUp(const Weights &weights);
1358  template <Player Owner>
1359  static MultiInt evalOne(const NumEffectState &state);
1360  static MultiInt eval(const NumEffectState &state);
1361  static int index1(const NumEffectState &state, Piece piece)
1362  {
1363  const Ptype attack_ptype
1364  = state.findCheapAttack(alt(piece.owner()), piece.square()).ptype();
1365  const bool has_support = state.hasEffectAt(piece.owner(),
1366  piece.square());
1367  return (piece.ptype() +
1368  (has_support ? 0 : PTYPE_SIZE)) * PTYPE_SIZE + attack_ptype;
1369  }
1370  static int index2(int i0, int i1)
1371  {
1372  return i0 * PTYPE_SIZE * 2 * PTYPE_SIZE + i1;
1373  }
1374  static CArray<MultiInt, ONE_DIM> table;
1375  };
1376 
1378  {
1379  friend class PtypeCountXY;
1380  friend class PtypeCountXYAttack;
1381  public:
1382  enum { ONE_DIM = 160, DIM = ONE_DIM * EvalStages };
1383  static void setUp(const Weights &weights);
1384  template<osl::Player P,osl::Ptype T>
1385  static MultiInt evalPlayerPtype(const CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
1386  const CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
1387  const osl::CArray<int,2> &kings_x,
1388  const osl::CArray<int,2> &kings_y);
1389  static void eval(const NumEffectState &state,
1390  const CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
1391  const CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
1392  MultiInt &out);
1393  template<Player P>
1394  static void evalWithUpdateBang(
1395  const NumEffectState &state,
1396  Move last_move,
1397  CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
1398  CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
1399  MultiInt &last_value_and_out,unsigned int &ptypeo_mask);
1400  private:
1401  static int indexCount(Ptype ptype, int count)
1402  {
1403  return Ptype_Table.getIndexMin(unpromote(ptype)) +
1404  (isPromoted(ptype) ? 40 : 0) +
1405  count - 1;
1406  }
1407  static int indexBoardCount(Ptype ptype, int count)
1408  {
1409  return Ptype_Table.getIndexMin(unpromote(ptype)) +
1410  (isPromoted(ptype) ? 40 : 0) + 80 +
1411  count - 1;
1412  }
1413  static int indexCountX(Ptype ptype, int count, int x)
1414  {
1415  return x - 1 + 5 *
1416  (Ptype_Table.getIndexMin(unpromote(ptype)) +
1417  (isPromoted(ptype) ? 40 : 0) +
1418  count - 1);
1419  }
1420  static int indexCountY(Ptype ptype, int count, int y)
1421  {
1422  return y - 1 + 9 *
1423  (Ptype_Table.getIndexMin(unpromote(ptype)) +
1424  (isPromoted(ptype) ? 40 : 0) +
1425  count - 1) + 800;
1426  }
1427  static int indexBoardCountX(Ptype ptype, int count, int x)
1428  {
1429  return x - 1 + 5 *
1430  (Ptype_Table.getIndexMin(unpromote(ptype)) +
1431  (isPromoted(ptype) ? 40 : 0) +
1432  count - 1) + 400;
1433  }
1434  static int indexBoardCountY(Ptype ptype, int count, int y)
1435  {
1436  return y - 1 + 9 *
1437  (Ptype_Table.getIndexMin(unpromote(ptype)) +
1438  (isPromoted(ptype) ? 40 : 0) +
1439  count - 1) + 720 + 800;
1440  }
1441  template<Ptype T>
1442  static int indexCount(int count)
1443  {
1444  return PtypeTraits<T>::indexMin+ (isPromoted(T) ? 40 : 0) +
1445  count - 1;
1446  }
1447  template<Ptype T>
1448  static int indexBoardCount(int count)
1449  {
1450  return PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0)+ 80 +
1451  count - 1;
1452  }
1453  template<Ptype T>
1454  static int indexCountX(int count, int x)
1455  {
1456  return x - 1 + 5 *
1457  (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
1458  count - 1);
1459  }
1460  template<Ptype T>
1461  static int indexCountY(int count, int y)
1462  {
1463  return y - 1 + 9 *
1464  (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
1465  count - 1) + 800;
1466  }
1467  template<Ptype T>
1468  static int indexBoardCountX(int count, int x)
1469  {
1470  return x - 1 + 5 *
1471  (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
1472  count - 1) + 400;
1473  }
1474  template<Ptype T>
1475  static int indexBoardCountY(int count, int y)
1476  {
1477  return y - 1 + 9 *
1478  (PtypeTraits<T>::indexMin+(isPromoted(T) ? 40 : 0) +
1479  count - 1) + 720 + 800;
1480  }
1481  static MultiInt valueAll(Ptype ptype, int count, int my_king_x, int my_king_y, int op_king_x, int op_king_y)
1482  {
1483  assert(count>0);
1484  return
1485  xy_table_diff[indexCountX(ptype, count, my_king_x)]+
1486  xy_table_diff[indexCountY(ptype, count, my_king_y)]+
1487  xy_attack_table_diff[indexCountX(ptype,count, op_king_x)]+
1488  xy_attack_table_diff[indexCountY(ptype, count, op_king_y)];
1489  }
1490  static MultiInt valueBoardAll(Ptype ptype, int count, int my_king_x, int my_king_y, int op_king_x, int op_king_y)
1491  {
1492  assert(count>0);
1493  return
1494  xy_table_diff[indexBoardCountX(ptype, count, my_king_x)]+
1495  xy_table_diff[indexBoardCountY(ptype, count, my_king_y)]+
1496  xy_attack_table_diff[indexBoardCountX(ptype,count, op_king_x)]+
1497  xy_attack_table_diff[indexBoardCountY(ptype, count, op_king_y)];
1498  }
1499  static CArray<MultiInt, 160> table;
1500  static CArray<MultiInt, 2240> xy_table;
1501  static CArray<MultiInt, 2240> xy_attack_table;
1502  static CArray<MultiInt, 2240> xy_table_diff;
1503  static CArray<MultiInt, 2240> xy_attack_table_diff;
1504  };
1505 
1507  {
1508  public:
1509  enum { ONE_DIM = 2240, DIM = ONE_DIM * EvalStages };
1510  static void setUp(const Weights &weights);
1511  };
1513  {
1514  public:
1515  enum { ONE_DIM = 2240, DIM = ONE_DIM * EvalStages };
1516  static void setUp(const Weights &weights);
1517  };
1518 
1520  {
1521  public:
1522  enum { ONE_DIM = 9792, DIM = ONE_DIM * EvalStages };
1523  static void setUp(const Weights &weights);
1524  static MultiInt eval(const NumEffectState &state);
1525  private:
1526  static int index(Player p, Square pos, Square king,
1527  PtypeO ptypeO, bool attack)
1528  {
1529  const int y_diff = (p == BLACK ? king.y() - pos.y() : pos.y() - king.y());
1530  const int x_diff = std::abs(king.x() - pos.x());
1531  if (p == WHITE)
1532  {
1533  ptypeO = alt(ptypeO);
1534  }
1535  return y_diff + 8 + x_diff * 17 + (ptypeO - PTYPEO_MIN) * 17 * 9 +
1536  (attack ? 0 : 4896);
1537  }
1538  static CArray<MultiInt, 9792> table;
1539  };
1540 
1542  {
1543  public:
1544  enum { ONE_DIM = 1440, DIM = ONE_DIM * EvalStages };
1545  static MultiInt eval(const NumEffectState &state,
1546  const CArray2d<int, 2, 9> &pawns);
1547  template<Player P>
1548  static void evalWithUpdateBang(const NumEffectState &state,
1549  Move moved,
1550  const CArray2d<int, 2, 9> &pawns,
1551  MultiInt& last_value);
1552  static void setUp(const Weights &weights);
1553  private:
1554  static int index(Player player, Ptype ptype, int y, int pawn_y)
1555  {
1556  if (player == WHITE)
1557  {
1558  y = 10 - y;
1559  pawn_y = (10 - pawn_y) % 10;
1560  }
1561  return pawn_y + 10 * (y - 1 + 9 * ptype);
1562  }
1563  static CArray<MultiInt, 1440> table;
1564  };
1565 
1567  {
1569  public:
1570  enum { ONE_DIM = 1215, DIM = ONE_DIM * EvalStages };
1571  static void setUp(const Weights &weights);
1572  static MultiInt eval(const NumEffectState &state,
1573  const CArray2d<int, 2, 3> &gs_count);
1574  private:
1575  template <Player Defense>
1576  static int index(const Square king, int distance0, int count)
1577  {
1578  int king_x = (king.x() > 5 ? 10 - king.x() : king.x());
1579  int king_y = (Defense == WHITE ? 10 - king.y() : king.y());
1580  return king_x - 1 + 5 * (king_y - 1+ 9 * (distance0 + 3 * count));
1581  }
1582  template <Player P>
1583  static MultiInt evalOne(const NumEffectState &state,
1584  const CArray2d<int, 2, 3> &gs_count);
1585  template <Player Defense>
1586  static int indexCombination(const Square king, int count0,
1587  int count1, int count2)
1588  {
1589  int king_x = (king.x() > 5 ? 10 - king.x() : king.x());
1590  int king_y = (Defense == WHITE ? 10 - king.y() : king.y());
1591  return king_x + 5 * (king_y + 9 * (std::min(5,count0) + 6 *
1592  (std::min(5,count1) + 6 * std::min(5,count2))));
1593  }
1594  static CArray<MultiInt, 1215> table;
1595  static CArray<MultiInt, 9720> combination_table;
1596  };
1597 
1599  {
1600  public:
1601  enum { ONE_DIM = 9720, DIM = ONE_DIM * EvalStages };
1602  static void setUp(const Weights &weights);
1603  private:
1604  };
1605 
1607  {
1608  public:
1609  enum { ONE_DIM = 8192, DIM = ONE_DIM * EvalStages };
1610  static void setUp(const Weights &weights);
1611  static MultiInt eval(unsigned int ptypeo_mask);
1612  private:
1613  template <Player P>
1614  static MultiInt evalOne(unsigned int ptypeo_mask)
1615  {
1616  int index = 0;
1617  if (P==BLACK) index=((ptypeo_mask>>19)&0x1fc0)|((ptypeo_mask>>18)&0x3f);
1618  else index=((ptypeo_mask>>3)&0x1fc0)|((ptypeo_mask>>2)&0x3f);
1619  if (P == BLACK)
1620  return table[index];
1621  else
1622  return -table[index];
1623  }
1624  static CArray<MultiInt, 8192> table;
1625  };
1627  {
1628  static std::pair<int,int> matchRook(const NumEffectState& state, Piece rook,
1629  const CArray<bool,2>& has_silver,
1630  Square& silver_drop);
1631  static std::pair<int,int> matchGold(const NumEffectState& state, Piece gold,
1632  const CArray<bool,2>& has_silver,
1633  Square& silver_drop);
1634  public:
1635  enum { ONE_DIM = 5*2, DIM = ONE_DIM * EvalStages };
1636  static void setUp(const Weights &weights);
1637  static MultiIntPair eval(const NumEffectState& state,
1638  CArray<std::pair<Square,int>,2>& silver_drop);
1639  static CArray<MultiInt, ONE_DIM> table;
1640  };
1642  {
1643  public:
1644  enum {
1647  };
1648  static const Square isBishopForkSquare(const NumEffectState& state, Player defense, const Square a, const Square b, bool maybe_empty=false);
1649  static const Square isRookForkSquare(const NumEffectState& state, Player defense, const Square a, const Square b);
1650  static int bishopIndex(Ptype a, Ptype b) { return a * PTYPE_SIZE + b; }
1651  static int rookIndex(Ptype a, Ptype b) { return bishopIndex(a,b) + DROP_DIM; }
1652  static void setUp(const Weights &weights);
1653  template <Player Defense>
1654  static MultiIntPair evalOne(const NumEffectState& state, const PieceVector& target,
1655  std::pair<Square,int>& bishop_drop,
1656  std::pair<Square,int>& rook_drop);
1657  static MultiIntPair eval(const NumEffectState& state,
1658  CArray<std::pair<Square,int>,2>& bishop_drop,
1659  CArray<std::pair<Square,int>,2>& rook_drop);
1660  static CArray<MultiInt, ONE_DIM> table;
1661  private:
1662  static const Square findDropInLine
1663  (const NumEffectState& state, Player defense,
1664  const Square a, const Square b, Piece king);
1665  static bool testCenter(const NumEffectState& state, Player defense,
1666  const Square a, const Square b, Piece king,
1667  Square center, bool maybe_empty=false);
1668  };
1669 
1671  {
1672  public:
1673  enum {
1675  DIM = ONE_DIM * EvalStages
1676  };
1677  static void setUp(const Weights &weights);
1678  template <Player Defense>
1679  static MultiIntPair evalOne(const NumEffectState& state,
1680  bool has_knight,
1681  BoardMask& knight_fork_squares,
1682  std::pair<Square,int>& knight_drop);
1683  static MultiIntPair eval(const NumEffectState& state,
1684  CArray<BoardMask,2>& knight_fork_squares,
1685  CArray<std::pair<Square,int>,2>& knight_drop);
1686  template <Player P>
1687  static MultiIntPair evalWithUpdate(const NumEffectState& state,
1688  Move moved,
1689  CArray<BoardMask,2>& knight_fork_squares,
1690  CArray<std::pair<Square,int>,2>& knight_drop);
1691  static CArray<MultiInt, ONE_DIM> table;
1692 
1693  static bool isForkSquare(const NumEffectState& state, Player defense,
1694  int y, int x0, int x1);
1695  static int index(Ptype a, Ptype b)
1696  {
1697  return a * PTYPE_SIZE + b;
1698  }
1699  static bool isTarget(Ptype ptype)
1700  {
1701  ptype = unpromote(ptype);
1702  return ptype != PAWN && ptype != LANCE && ptype != KNIGHT;
1703  }
1704  private:
1705  template <Player P, Player Defense>
1706  static void updateSquares
1707  (const NumEffectState& state, Move moved,
1708  BoardMask& knight_fork_squares);
1709  template <osl::Player Defense>
1710  static MultiIntPair accumulate
1711  (const NumEffectState& state,
1712  bool has_knight, const BoardMask& knight_fork_squares,
1713  std::pair<Square,int>& knight_drop);
1714  };
1715 
1717  {
1718  public:
1719  enum { ONE_DIM = 1, DIM = ONE_DIM*EvalStages };
1720  static void setUp(const Weights &weights);
1721  static MultiInt eval(const NumEffectState &state);
1722  private:
1723  static CArray<MultiInt, ONE_DIM> table;
1724  };
1725 
1727  {
1728  public:
1730  static void setUp(const Weights &weights);
1731  static MultiInt eval(const NumEffectState &state);
1732  template<Player P>
1733  static MultiInt evalOne(const NumEffectState &state, int rank);
1734  template<Player P>
1735  static MultiInt evalWithUpdate(const NumEffectState &, Move moved,
1736  MultiInt const& last_value);
1737 
1738  static CArray<MultiInt, ONE_DIM> table;
1739  };
1740  }
1741  }
1742 }
1743 
1744 #endif // EVAL_ML_MINORPIECE_H
1745 // ;;; Local Variables:
1746 // ;;; mode:c++
1747 // ;;; c-basic-offset:2
1748 // ;;; End: