My Project
move_probability/feature.h
Go to the documentation of this file.
1 /* feature.h
2  */
3 #ifndef OSL_MOVE_PROBABILITY_FEATURE_H
4 #define OSL_MOVE_PROBABILITY_FEATURE_H
5 
8 #include "osl/additionalEffect.h"
10 #include <string>
11 
12 namespace osl
13 {
14  namespace move_probability
15  {
16  class Feature
17  {
18  std::string my_name;
19  int dim;
20  public:
21  Feature(std::string n, size_t d) : my_name(n), dim(d)
22  {
23  assert(dim > 0);
24  }
25  virtual ~Feature();
26  std::string name() const { return my_name; }
27  virtual double match(const StateInfo&, const MoveInfo&, int offset, const double *) const=0;
28  size_t dimension() const { return dim; }
29 
30  static int classifyEffect9(const NumEffectState& state, Player player, Square to)
31  {
32  const int a = std::min(2, state.countEffect(player, to));
33  int d = std::min(2,state.countEffect(alt(player), to));
34  if (a>d)
35  d += AdditionalEffect::hasEffect(state, to, alt(player));
36  return a*3 + d;
37  }
38  };
39 
40  class CheckFeature : public Feature
41  {
42  public:
43  enum { CHECK_CLASS = 4, RELATIVE_Y_CLASS = 3 };
46  {
47  }
48  static int checkIndex(const MoveInfo& move)
49  {
50  if (move.open_check)
51  return 3;
52  return (move.see > 0) ? 0 : ((move.see == 0) ? 1 : 2);
53  }
54  static int sign(const NumEffectState& state, Move move,
55  Player player)
56  {
57  const Square king = state.kingSquare(alt(player));
58  int ry = (move.to().y() - king.y())*osl::sign(player);
59  if (ry == 0) return 0;
60  return ry > 0 ? 1 : -1;
61  }
62  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
63  {
64  if (! move.check && ! move.open_check)
65  return 0;
66  const Player player = move.player;
67  int index = sign(*state.state, move.move, player)+1;
68  index = (index*2 + move.move.isDrop())*PTYPE_SIZE
69  + move.move.ptype();
70  index = index*CHECK_CLASS + checkIndex(move);
71  return w[offset+index];
72  }
73  };
74  class TakeBackFeature : public Feature
75  {
76  public:
77  TakeBackFeature() : Feature("TakeBack", 3)
78  {
79  }
80  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
81  {
82  if (! state.history->hasLastMove()
83  || state.history->lastMove().to() != move.move.to())
84  return 0;
85  int match = 2;
86  if (move.see >= 0) {
87  --match;
88  if (state.history->hasLastMove(2)
89  && state.history->lastMove(2).to() == move.move.to())
90  --match;
91  }
92  return w[offset + match];
93  }
94  };
95  class SeeFeature : public Feature
96  {
97  public:
98  enum { SeeClass = 23, YClass = 3, ProgressClass = 8 };
99  SeeFeature() : Feature("SeeFeature", SeeClass*(3+ProgressClass))
100  {
101  }
102  static int seeIndex(int see)
103  {
104  int index = see / 128;
105  if (see > 0) {
106  index = std::min(10, index);
107  index += 12;
108  } else if (see == 0) {
109  index += 11;
110  } else {
111  index += 10;
112  index = std::max(0, index);
113  }
114  return index;
115  }
116  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
117  {
118  const int see_index = seeIndex(move.see);
119  const Player player = move.player;
120  const Square to = move.move.to();
121  const int promote_index = to.canPromote(player)
122  ? 1 : (to.canPromote(alt(player)) ? 2 : 0);
123  double sum = w[offset+see_index+promote_index*SeeClass];
124  int progress_index = YClass + state.progress8();
125  sum += w[offset+see_index+progress_index*SeeClass];
126  return sum;
127  }
128  };
129 
130  class CapturePtype : public Feature
131  {
132  public:
133  CapturePtype() : Feature("CapturePtype", PTYPE_SIZE*PTYPE_SIZE*2*3)
134  {
135  }
136  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
137  {
138  const Ptype captured = move.move.capturePtype();
139  const Player player = move.player;
140  int index = (move.move.ptype())*PTYPE_SIZE + captured;
141  static_assert(PTYPE_EDGE == 1, "");
142  if (captured != PTYPE_EMPTY
143  && captured == state.threatened[alt(player)].ptype())
144  ++index;
145  if (move.see > 0)
146  index += PTYPE_SIZE*PTYPE_SIZE;
147  if (captured != PTYPE_EMPTY)
148  index += std::min(2, state.state->countPiecesOnStand(player, unpromote(captured)))
149  * (2*PTYPE_SIZE*PTYPE_SIZE);
150  return w[offset+index];
151  }
152  };
153 
154  class ContinueCapture : public Feature
155  {
156  public:
157  ContinueCapture() : Feature("ContinueCapture", 1) {}
158  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
159  {
160  if (move.move.capturePtype() == PTYPE_EMPTY
161  || ! state.history->hasLastMove(2)
162  || state.history->lastMove(2).to() != move.move.from())
163  return 0;
164  return w[offset];
165  }
166  };
167 
169  class DropCaptured : public Feature
170  {
171  public:
172  DropCaptured() : Feature("DropCaptured", PTYPE_SIZE - PTYPE_BASIC_MIN) {}
173  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
174  {
175  if (! move.move.isDrop()
176  || ! state.history->hasLastMove(2)
177  || ! state.history->lastMove(2).isNormal()
178  || state.history->lastMove(2).capturePtype() != move.move.ptype())
179  return 0.0;
180  const size_t index = move.move.ptype() - PTYPE_BASIC_MIN;
181  assert(index < dimension());
182  return w[index + offset];
183  }
184  };
185 
186  class SquareY : public Feature
187  {
188  public:
189  // PTYPE_SIZE, to [1,9], fromto [-3,3], drop|promote, progress8
190  enum {
191  DIM = 9*PTYPE_SIZE*16
192  };
193  SquareY() : Feature("SquareY", DIM)
194  {
195  }
196  static int fromTo(Square to, Square from) // [-3,3]
197  {
198  return std::max(-3, std::min(to.y() - from.y(), 3));
199  }
200  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
201  {
202  const Move move = info.move;
203  const Player P = info.player;
204  const Square to = move.to().squareForBlack(P);
205  size_t index = ((to.y()-1)*PTYPE_SIZE + move.ptype())*16;
206  assert(index+16 <= dimension());
207  const int from_to = move.isDrop() ? 0
208  : fromTo(to, move.from().squareForBlack(P));
209  double sum = w[offset + index + from_to + 3];
210  if (move.isDrop() || move.isPromotion())
211  sum += w[offset + index + 7];
212  sum += w[offset + index + state.progress8()+8];
213  return sum;
214  }
215  };
216 
217  class SquareX : public Feature
218  {
219  public:
220  // PTYPE_SIZE, to [1,5], fromto [-3,3], drop|promote, progress8
221  SquareX() : Feature("SquareX", 5*PTYPE_SIZE*16)
222  {
223  }
224  static int fromTo(Square to, Square from) // [-3,3]
225  {
226  return std::max(-3, std::min(to.x() - from.x(), 3));
227  }
228  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
229  {
230  const Move move = info.move;
231  int to = move.to().x();
232  int from_to = move.isDrop() ? 0 : fromTo(move.to(), move.from());
233  if (to > 5) {
234  to = 10 - to;
235  from_to = -from_to;
236  }
237  size_t index = ((to-1)*PTYPE_SIZE + move.ptype())*16;
238  assert(index+16 <= dimension());
239  double sum = w[offset + index + from_to + 3];
240  if (move.isDrop() || move.isPromotion())
241  sum += w[offset + index + 7];
242  sum += w[offset + index + state.progress8()+8];
243  return sum;
244  }
245  };
246 
247  class KingRelativeY : public Feature
248  {
249  public:
250  // PTYPE_SIZE, to [-8,8], fromto [-3,3], drop|promote, progress8
251  enum { ONE_DIM = 17*PTYPE_SIZE*16 };
252  KingRelativeY() : Feature("KingRelativeY", ONE_DIM*2)
253  {
254  }
255  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
256  {
257  const Move move = info.move;
258  const Player P = info.player;
259  const Ptype ptype = move.ptype();
260 
261  const Square to = move.to().squareForBlack(P);
262  const Square my_king = state.state->kingSquare(P).squareForBlack(P);
263  const Square op_king = state.state->kingSquare(alt(P)).squareForBlack(P);
264  const int from_to = move.isDrop() ? 0
265  : SquareY::fromTo(to, move.from().squareForBlack(P));
266 
267  size_t index = ((to.y()-my_king.y()+8)*PTYPE_SIZE + ptype)*16;
268  assert(index+16 <= ONE_DIM);
269  double sum = w[offset + index + from_to + 3];
270  if (move.isDrop() || move.isPromotion())
271  sum += w[offset + index + 7];
272  sum += w[offset + index + state.progress8()+8];
273 
274  index = ((to.y()-op_king.y()+8)*PTYPE_SIZE + ptype)*16;
275  assert(index+16 <= ONE_DIM);
276  sum += w[offset + ONE_DIM + index + from_to + 3];
277  if (move.isDrop() || move.isPromotion())
278  sum += w[offset + ONE_DIM + index + 7];
279  sum += w[offset + ONE_DIM + index + state.progress8()+8];
280  return sum;
281  }
282  };
283  class KingRelativeX : public Feature
284  {
285  public:
286  // PTYPE_SIZE, to [0,8], fromto [-3,3], drop|promote, progress8
287  enum { ONE_DIM = 9*PTYPE_SIZE*16 };
288  KingRelativeX() : Feature("KingRelativeX", ONE_DIM*2)
289  {
290  }
291  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
292  {
293  const Move move = info.move;
294  const Player P = info.player;
295  const Ptype ptype = move.ptype();
296 
297  const Square to = move.to();
298  const Square my_king = state.state->kingSquare(P);
299  const Square op_king = state.state->kingSquare(alt(P));
300  const int from_to = move.isDrop() ? 0
301  : SquareY::fromTo(to, move.from());
302  int dx = to.x() - my_king.x(), fx = from_to;
303  if (dx < 0) {
304  dx = -dx;
305  fx = -fx;
306  }
307  size_t index = (dx*PTYPE_SIZE + ptype)*16;
308  assert(index+16 <= ONE_DIM);
309  double sum = w[offset + index + fx + 3];
310  if (move.isDrop() || move.isPromotion())
311  sum += w[offset + index + 7];
312  sum += w[offset + index + state.progress8()+8];
313 
314  dx = to.x() - op_king.x(), fx = from_to;
315  if (dx < 0) {
316  dx = -dx;
317  fx = -fx;
318  }
319  index = (dx*PTYPE_SIZE + ptype)*16;
320  assert(index+16 <= ONE_DIM);
321  sum += w[offset + ONE_DIM + index + fx + 3];
322  if (move.isDrop() || move.isPromotion())
323  sum += w[offset + ONE_DIM + index + 7];
324  sum += w[offset + ONE_DIM + index + state.progress8()+8];
325  return sum;
326  }
327  };
328 
329  class FromEffect : public Feature
330  {
331  public:
333  {
334  }
335  double match(const StateInfo& state_info, const MoveInfo& info, int offset, const double *w) const
336  {
337  const Move move = info.move;
338  if (move.isDrop())
339  return 0;
340  const NumEffectState& state = *state_info.state;
341  const Ptype me = move.oldPtype();
342  const Ptype support = state.findCheapAttack(info.player, move.from()).ptype();
343  const Ptype attack = state.findCheapAttack(alt(info.player), move.from()).ptype();
344  const size_t index = (((me * PTYPE_SIZE) + support) * PTYPE_SIZE) + attack;
345  assert(index < dimension());
346  return w[index + offset];
347  }
348  };
349 
350  class ToEffect : public Feature
351  {
352  public:
354  {
355  }
356  static const Piece find(const NumEffectState& state,
357  Square to, const PieceMask& remove,
358  Player player)
359  {
360  assert(to.isOnBoard());
361  PieceMask pieces = state.piecesOnBoard(player)
362  & state.effectSetAt(to);
363  pieces &= ~remove;
364  return state.selectCheapPiece(pieces);
365  }
366  static void supportAttack(const NumEffectState& state,
367  Square to,
368  const PieceMask& my_pin,
369  const PieceMask& op_pin,
370  Player turn,
371  std::pair<Ptype,Ptype>& out)
372  {
373  out.first = find(state, to, my_pin, turn).ptype(); // support
374  out.second = find(state, to, op_pin, alt(turn)).ptype(); // attack
375  }
376  static void supportAttack(const StateInfo& info, Square to, Move move,
377  std::pair<Ptype,Ptype>& out)
378  {
379  const Player turn = info.state->turn();
380  if (move.isDrop())
381  return supportAttack(*(info.state), to, info.pin[turn],
382  info.pin[alt(turn)], turn, out);
383  PieceMask my_pin = info.pin[turn];
384  my_pin.set(info.state->pieceAt(move.from()).number());
385  supportAttack(*(info.state), to, my_pin, info.pin[alt(turn)],
386  turn, out);
387  }
388  static size_t supportAttack(const StateInfo& info, Square to, Move move)
389  {
390  std::pair<Ptype,Ptype> pair;
391  supportAttack(info, to, move, pair);
392  return pair.first * PTYPE_SIZE + pair.second;
393  }
394  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
395  {
396  const Move move = info.move;
397  const Ptype me = move.ptype(), captured = move.capturePtype();
398  const size_t position_index = supportAttack(state, move.to(), move);
399  const size_t index = ((me * PTYPE_SIZE) + captured)
400  * PTYPE_SIZE * PTYPE_SIZE + position_index;
401  assert(index < dimension());
402  return w[index + offset];
403  }
404  };
405 
406  class FromEffectLong : public Feature
407  {
408  public:
409  FromEffectLong() : Feature("FromEffectLong", PTYPE_SIZE*8*8)
410  {
411  }
412  double match(const StateInfo& state_info, const MoveInfo& info, int offset, const double *w) const
413  {
414  const Move move = info.move;
415  if (move.isDrop())
416  return 0;
417  const NumEffectState& state = *state_info.state;
418  const Ptype ptype = move.oldPtype();
419  const CArray<bool,3> me = {{
420  state.longEffectAt<LANCE>(move.from(), info.player).any(),
421  state.longEffectAt<BISHOP>(move.from(), info.player).any(),
422  state.longEffectAt<ROOK>(move.from(), info.player).any(),
423  }};
424  const CArray<bool,3> op = {{
425  state.longEffectAt<LANCE>(move.from(), alt(info.player)).any(),
426  state.longEffectAt<BISHOP>(move.from(), alt(info.player)).any(),
427  state.longEffectAt<ROOK>(move.from(), alt(info.player)).any(),
428  }};
429  size_t index = ptype;
430  for (int i=0; i<3; ++i) {
431  index *= 2; index += me[i];
432  index *= 2; index += op[i];
433  }
434  assert(index < dimension());
435  return w[index + offset];
436  }
437  };
438 
439  class ToEffectLong : public Feature
440  {
441  public:
442  ToEffectLong() : Feature("ToEffectLong", PTYPE_SIZE*8*8)
443  {
444  }
445  double match(const StateInfo& state_info, const MoveInfo& info, int offset, const double *w) const
446  {
447  const Move move = info.move;
448  const NumEffectState& state = *state_info.state;
449  const Ptype ptype = move.oldPtype();
450  NumBitmapEffect effect=state.effectSetAt(move.to());
451  if (! move.isDrop())
452  effect.reset(state.pieceOnBoard(move.from()).number()+8);
453  const CArray<mask_t,3> pieces = {{
454  effect.selectLong<LANCE>() >> 8,
455  effect.selectLong<BISHOP>() >> 8,
456  effect.selectLong<ROOK>() >> 8
457  }};
458  size_t index = ptype;
459  for (int i=0; i<3; ++i) {
460  index *= 2;
461  index += (pieces[i] & state.piecesOnBoard(info.player).getMask(1)).any();
462  index *= 2;
463  index += (pieces[i] & state.piecesOnBoard(alt(info.player)).getMask(1)).any();
464  }
465  assert(index < dimension());
466  return w[index + offset];
467  }
468  };
469 
470  class PatternCommon : public Feature
471  {
472  public:
473  enum {
486  };
487  PatternCommon(const std::string& name, int dim) : Feature(name, dim)
488  {
489  }
490  double addOne(const StateInfo& state, int offset,
491  const double *w, Square position) const
492  {
493  if (! position.isOnBoardRegion() || state.state->pieceAt(position).isEdge()) {
494  size_t basic = ptypeOIndex(PTYPEO_EDGE) *SquareDim;
495  return w[offset + basic];
496  }
497  const StateInfo::pattern_square_t& cache
498  = state.pattern_cache[position.index()];
499  double sum = 0.0;
500  for (size_t i=0; i<cache.size() && cache[i] >= 0; ++i)
501  sum += w[offset + cache[i]];
502  return sum;
503  }
504  static void updateCache(StateInfo& info);
505  private:
506  static void updateCacheOne(Square target, StateInfo& info);
507  };
508 
509  template<bool TestPromotable>
510  class PatternBase : public PatternCommon
511  {
512  int dx, black_dy;
513  public:
514  enum {
515  PromotionSize = TestPromotable ? 3 : 1,
517  };
518  PatternBase(int x, int y)
519  : PatternCommon(name(x,y), DIM), dx(x), black_dy(y)
520  {
521  }
522  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
523  {
524  const Move move = info.move;
525  const Ptype ptype = move.ptype();
526  int basic = ptype*PatternCacheSize;
527  int basic_from = (move.isPromotion() ? PTYPE_EDGE : PTYPE_EMPTY)
529  const Square to = move.to();
530  if (TestPromotable && to.canPromote(info.player))
531  offset += OneDim;
532  else if (TestPromotable && to.canPromote(alt(info.player)))
533  offset += 2*OneDim;
534  int dy = info.player == BLACK ? black_dy : -black_dy;
535  Square target = to + Offset(dx, dy);
536  double sum = 0.0;
537  if (move.from() != target)
538  sum += addOne(state, offset+basic, w, target);
539  else // move from here
540  sum += addOne(state, offset+basic_from, w, target);
541  if (dx == 0)
542  return sum;
543  target = to + Offset(-dx, dy);
544  if (move.from() != target)
545  sum += addOne(state, offset+basic, w, target);
546  else
547  sum += addOne(state, offset+basic_from, w, target);
548  return sum;
549  }
550  static std::string name(int x, int y)
551  {
552  return std::string("Pattern")
553  + (TestPromotable ? "P" : "")
554  + "X" + (char)('2'+x) + "Y"+(char)('2'+y);
555  }
556  };
557 
560 
562  {
563  public:
564  MoveFromOpposingSliders() : Feature("MoveFromOpposingSliders", 36*PTYPE_SIZE)
565  {
566  }
567  static int longPtype(const NumEffectState& state, Square position, Player player)
568  {
569  const int offset = PtypeFuns<LANCE>::indexNum*32;
570  mask_t p = state.longEffectAt<LANCE>(position, player);
571  if (p.any())
572  return state.hasEffectAt(player, state.pieceOf(p.takeOneBit()+offset).square());
573  p = state.longEffectAt<BISHOP>(position, player);
574  if (p.any())
575  return 2 + state.hasEffectAt(player, state.pieceOf(p.takeOneBit()+offset).square());
576  p = state.longEffectAt<ROOK>(position, player);
577  assert(p.any());
578  return 4 + state.hasEffectAt(player, state.pieceOf(p.takeOneBit()+offset).square());
579  }
580  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
581  {
582  const Square from = move.move.from();
583  if (from.isPieceStand()
584  || ! state.pinByOpposingSliders(state.state->pieceOnBoard(from)))
585  return 0.0;
586  const int me = longPtype(*state.state, from, move.player);
587  const int op = longPtype(*state.state, from, alt(move.player));
588  return w[offset + (me*6+op)*PTYPE_SIZE+move.move.ptype()];
589  }
590  };
592  {
593  public:
594  AttackFromOpposingSliders() : Feature("AttackFromOpposingSliders", PTYPE_SIZE*PTYPE_SIZE*2)
595  {
596  }
597  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
598  {
599  const Move move = info.move;
600  const Piece attack = state.state->findCheapAttack(alt(info.player), move.to());
601  if (! state.pinByOpposingSliders(attack))
602  return 0.0;
603  if (state.state->countEffect(alt(info.player), move.to()) == 1)
604  offset += PTYPE_SIZE*PTYPE_SIZE;
605  double sum = w[offset + PTYPE_EMPTY*PTYPE_SIZE+attack.ptype()]
606  + w[offset + move.ptype()*PTYPE_SIZE+PTYPE_EMPTY]
607  + w[offset + move.ptype()*PTYPE_SIZE+attack.ptype()];
608  if (info.see < 0)
609  sum += w[offset + PTYPE_EMPTY*PTYPE_SIZE+PTYPE_EMPTY]*info.see/1024.0;
610  return sum;
611  }
612  };
614  {
615  public:
616  AttackToOpposingSliders() : Feature("AttackToOpposingSliders", PTYPE_SIZE*PTYPE_SIZE*2)
617  {
618  }
619  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
620  {
621  const Move move = info.move;
622  double sum = 0.0;
623  for (Piece piece: state.pin_by_opposing_sliders) {
624  if (! state.state->hasEffectIf(move.ptypeO(), move.to(),
625  piece.square()))
626  continue;
627  int base = (piece.owner() == info.player) ? PTYPE_SIZE*PTYPE_SIZE : 0;
628  sum += w[offset + base + PTYPE_EMPTY*PTYPE_SIZE+piece.ptype()]
629  + w[offset + base + move.ptype()*PTYPE_SIZE+PTYPE_EMPTY]
630  + w[offset + base + move.ptype()*PTYPE_SIZE+piece.ptype()];
631  if (info.see < 0)
632  sum += w[offset + base + PTYPE_EMPTY*PTYPE_SIZE+PTYPE_EMPTY]*info.see/1024.0;
633  }
634  return sum;
635  }
636  };
637  class PawnAttack : public Feature
638  {
639  public:
640  enum {
645  DIM = PawnSize*2
646  };
647  PawnAttack() : Feature("PawnAttack", DIM)
648  {
649  }
650  std::pair<int,int> squareStatus(const NumEffectState& state, Player player, Square to, Square& front) const
651  {
652  int u = 0, uu = 0;
653  const int dy = (player == BLACK) ? -1 : 1;
654  Square position = to + Offset(0, dy);
655  front = position;
656  Piece piece = state.pieceAt(position);
657  if (piece.isPiece())
658  u = piece.ptype() + ((piece.owner() == player) ? PTYPE_SIZE : 0);
659  assert(! piece.isEdge()); // pawn move
660  piece = state.pieceAt(position + Offset(0, dy));
661  if (piece.isPiece())
662  uu = piece.ptype() + ((piece.owner() == player) ? PTYPE_SIZE : 0);
663  return std::make_pair(u, uu);
664  }
665  double matchPtype(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
666  {
667  const Player player = move.player;
668  const Square to = move.move.to();
669 
670  Square front;
671  const std::pair<int,int> u = squareStatus(*state.state, player, to, front);
672 
673  int promotion = 0;
674  if (front.canPromote(player))
675  promotion = 1;
676  else if (front.canPromote(alt(player)))
677  promotion = 2;
678  offset += BasicSize*promotion;
679 
680  bool pawn_drop = move.move.isDrop();
681  const int index0 = (u.first*PTYPE_SIZE*2+u.second)*2 + pawn_drop;
682  double sum = w[offset + index0];
683 
684  const int effect = classifyEffect9(*state.state, player, front);
685  const int index1 = u.first*8 + move.move.to().squareForBlack(player).y()-2;
686  sum += w[offset + index1*9+effect];
687  return sum;
688  }
689  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
690  {
691  if (move.move.ptype() == PAWN)
692  return matchPtype(state, move, offset, w);
693  if (move.move.ptype() == LANCE
694  && state.state->canDropPawnTo(move.player, move.move.to().x()))
695  return matchPtype(state, move, offset+PawnSize, w);
696  return 0.0;
697  }
698  };
699 
700  class BlockLong : public Feature
701  {
702  public:
703  enum {
706  OptionSize = 8, // King8, HasSupport, Promotable, Shadowing,...
709  };
710  BlockLong() : Feature("BlockLong", DIM)
711  {
712  }
713  static int longAttackIndex(osl::PtypeO ptypeo) // [0,7]?
714  {
715  const Ptype ptype = getPtype(ptypeo);
716  int index;
717  if (ptype == LANCE) index = 0;
718  else if (ptype == BISHOP) index = 1;
719  else if (ptype == ROOK) index = 2;
720  else {
721  assert(ptype == PROOK || ptype == PBISHOP);
722  index = 3;
723  }
724  if (getOwner(ptypeo) == WHITE) index += 4;
725  return index;
726  }
727  static double addPiece(const StateInfo& state, Piece piece,
728  Square to, const double *w, int offset)
729  {
730  assert(state.state->hasEffectByPiece(piece, to));
731  const Direction d
732  = Board_Table.getLongDirection<BLACK>(piece.square(), to);
734  cache = state.long_attack_cache[piece.number()][longToShort(d)];
735  double sum = 0.0;
736  for (int index: cache) {
737  assert(index < LongAttackSize);
738  sum += w[index+offset];
739  }
740  return sum;
741  }
742  static int ptypeSupport(Ptype moved, bool has_support)
743  {
744  return (moved*2 + has_support) * LongAttackSize;
745  }
746  static double findAll(const StateInfo& state, Player P,
747  Square target, const double *w, int offset)
748  {
749  mask_t m = state.state->longEffectAt(target, P);
750  double sum = 0.0;
751  while (m.any()) {
752  const Piece piece = state.state->pieceOf
753  (m.takeOneBit() +PtypeFuns<LANCE>::indexNum*32);
754  sum += addPiece(state, piece, target, w, offset);
755  }
756  m = state.state->longEffectAt(target, alt(P));
757  while (m.any()) {
758  const Piece piece = state.state->pieceOf
759  (m.takeOneBit()+PtypeFuns<LANCE>::indexNum*32);
760  sum += addPiece(state, piece, target, w, offset);
761  }
762  return sum;
763  }
764  static double findAll(const StateInfo& state, Move move, const double *w, int offset=0)
765  {
766  const Player P = move.player();
767  Square target = move.to();
768  int a = state.state->countEffect(P, target);
769  offset += ptypeSupport(move.ptype(), a+move.isDrop()>1);
770  return findAll(state, P, target, w, offset);
771  }
772  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
773  {
774  return findAll(state, move.move, w, offset);
775  }
776  static void updateCache(StateInfo&);
777  private:
778  static void makeLongAttackOne(StateInfo& info,
779  Piece piece, Direction d);
780  };
781  class BlockLongFrom : public Feature
782  {
783  public:
784  enum {
786  };
787  BlockLongFrom() : Feature("BlockLongFrom", DIM)
788  {
789  }
790  static double findAll(const StateInfo& state, Move move, const double *w, int offset=0)
791  {
792  const Player P = move.player();
793  Square target = move.from();
794  return BlockLong::findAll(state, P, target, w, offset);
795  }
796  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
797  {
798  if (move.move.isDrop())
799  return 0;
800  return findAll(state, move.move, w, offset);
801  }
802  };
803  class LongRecapture : public Feature
804  {
805  public:
806  enum {
808  };
809  LongRecapture() : Feature("LongRecapture", DIM)
810  {
811  }
812  double match(const StateInfo& info, const MoveInfo& move, int offset, const double *w) const
813  {
814  if (move.see >= 0)
815  return 0.0;
816  const NumEffectState& state = *info.state;
817  const Square to = move.move.to();
818  int a = state.countEffect(move.player, to)+move.move.isDrop()-1;
819  int d = state.countEffect(alt(move.player), to);
820  if (d == 1
821  || (d == 2 && a > 0
822  && state.hasEffectByPiece(state.kingPiece(alt(move.player)), to))) {
823  double sum = w[offset + (PTYPE_EMPTY)*BlockLong::LongAttackSize]
824  *move.see/1024.0;
825  offset += move.move.ptype() * BlockLong::LongAttackSize;
826  const Piece opponent = state.findCheapAttack(alt(move.player), to);
827  sum += BlockLong::findAll(info, move.player, opponent.square(), w, offset);
828  return sum;
829  }
830  return 0.0;
831  }
832  };
833  class AddEffectLong : public Feature
834  {
835  public:
836  enum {
838  };
839  AddEffectLong() : Feature("AddEffectLong", DIM)
840  {
841  }
842  static double addOne(Direction dir, const StateInfo& state, const MoveInfo& move, int offset, const double *w)
843  {
844  Offset diff = Board_Table.getOffset(move.player, dir);
845  Square to = move.move.to() + diff;
846  if (isLong(dir)) {
847  while (state.state->pieceAt(to).isEmpty())
848  to += diff;
849  }
850  if (! state.state->pieceAt(to).isPiece())
851  return 0.0;
852  return BlockLong::findAll(state, move.player, to, w, offset);
853  }
854  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
855  {
856  offset += move.move.ptype()*BlockLong::LongAttackSize;
857  unsigned int directions = Ptype_Table.getMoveMask(move.move.ptype());
858  double sum = 0.0;
859  do {
860  Direction d = (Direction)(misc::BitOp::bsf(directions));
861  directions &= directions-1;
862  sum += addOne(d, state, move, offset, w);
863  } while (directions);
864  return sum;
865  }
866  };
867  class LanceAttack : public Feature
868  {
869  public:
870  enum {
872  DIM = PatternCacheSize*(8+4+4+1)
873  };
874  LanceAttack() : Feature("LanceAttack", DIM)
875  {
876  }
877  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
878  {
879  if (move.move.ptype() != LANCE
880  || (! move.move.isDrop()
881  && move.move.capturePtype() == PTYPE_EMPTY))
882  return 0;
883  const Offset up = Board_Table.getOffset(move.player, U);
884  Square target = move.move.to() + up;
885  while (state.state->pieceAt(target).isEmpty())
886  target += up;
887  if (state.state->pieceAt(target).isOnBoardByOwner(move.player)) {
888  target += up;
889  if (state.state->pieceAt(target).ptype() == LANCE) {
890  while (state.state->pieceAt(target).isEmpty())
891  target += up;
892  }
893  }
894  if (state.state->pieceAt(target).isEdge())
895  target -= up;
896 
897  int y = move.move.to().y(), x = move.move.to().x();
898  if (move.player == WHITE)
899  y = 10-y;
900  y -= 2;
901  int dx1 = abs(state.state->kingSquare(move.player).x()-x);
902  int dx2 = abs(state.state->kingSquare(alt(move.player)).x()-x);
903  dx1 = std::min(dx1, 3);
904  dx2 = std::min(dx2, 3);
905  bool pawn = state.state->canDropPawnTo(alt(move.player), x);
906  assert(! state.state->pieceAt(target).isEdge());
907  const StateInfo::pattern_square_t& cache
908  = state.pattern_cache[target.index()];
909  double sum = 0.0;
910  for (size_t i=0; i<cache.size() && cache[i] >= 0; ++i) {
911  sum += w[offset + y*PatternCacheSize + cache[i]];
912  sum += w[offset + (8+dx1)*PatternCacheSize + cache[i]];
913  sum += w[offset + (12+dx1)*PatternCacheSize + cache[i]];
914  if (! pawn)
915  sum += w[offset + 16*PatternCacheSize + cache[i]];
916  }
917  return sum;
918  }
919  };
920  class BishopAttack : public Feature
921  {
922  public:
923  enum {
925  DIM = PatternCacheSize*2 // square:2
926  };
927  BishopAttack() : Feature("BishopAttack", DIM)
928  {
929  }
930  static double addSquare(Square target,
931  const StateInfo& info,
932  int offset, const double *w)
933  {
934  int type = 0;
935  const StateInfo::pattern_square_t& cache
936  = info.pattern_cache[target.index()];
937  double sum = 0.0;
938  for (size_t i=0; i<cache.size() && cache[i] >= 0; ++i) {
939  sum += w[offset + type + cache[i]];
940  }
941  return sum;
942  }
943  template <Direction D,Ptype Type>
944  static
945  double addOne(const StateInfo& info, Square to,
946  int offset, const double *w)
947  {
948  const NumEffectState& state = *info.state;
950  Square target = to + diff;
951  double sum = 0.0;
952  if (state.pieceAt(target).isEdge())
953  return sum;
954  if (state.pieceAt(target).isPiece()
955  && (state.pieceAt(target).ptype() != Type
956  || state.pieceAt(target).owner() != state.turn())) {
957  ; // almost included in direct pattern
958  } else {
959  while (state.pieceAt(target).isEmpty())
960  target += diff;
961  if (state.pieceAt(target).ptype() == Type
962  && state.pieceAt(target).owner() == state.turn()) {
963  // extend additional effect by the same ptype
964  target += diff;
965  while (state.pieceAt(target).isEmpty())
966  target += diff;
967  }
968  if (state.pieceAt(target).isEdge())
969  target -= diff;
970  sum += addSquare(target, info, offset, w);
971  if (! state.pieceAt(target).isPiece())
972  return sum;
973  }
974  // shadowing
975  target += diff;
976  if (state.pieceAt(target).isEdge())
977  return sum;
978  while (state.pieceAt(target).isEmpty())
979  target += diff;
980  if (state.pieceAt(target).isEdge())
981  target -= diff;
982  sum += addSquare(target, info, offset+PatternCacheSize, w);
983  return sum;
984  }
985  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
986  {
987  if (unpromote(move.move.ptype()) != BISHOP)
988  return 0;
989  double sum = 0.0;
990  sum += addOne<UR,BISHOP>(state, move.move.to(), offset, w);
991  sum += addOne<UL,BISHOP>(state, move.move.to(), offset, w);
992  sum += addOne<DR,BISHOP>(state, move.move.to(), offset, w);
993  sum += addOne<DL,BISHOP>(state, move.move.to(), offset, w);
994  return sum;
995  }
996  };
997  class RookAttack : public Feature
998  {
999  public:
1000  enum {
1002  DIM = DirectionSize*3
1003  };
1004  RookAttack() : Feature("RookAttack", DIM)
1005  {
1006  }
1007  double match(const StateInfo& state, const MoveInfo& move, int offset, const double *w) const
1008  {
1009  if (unpromote(move.move.ptype()) != ROOK)
1010  return 0;
1011  const Square to = move.move.to();
1012  double sum = 0.0;
1013  sum += BishopAttack::addOne<R,ROOK>(state, to, offset, w);
1014  sum += BishopAttack::addOne<L,ROOK>(state, to, offset, w);
1015  const bool pawn_drop = state.state->canDropPawnTo(alt(move.player), to.x());
1016  const int scale = pawn_drop ? 1 : 2;
1017  sum += BishopAttack::addOne<U,ROOK>(state, to, offset+DirectionSize*scale, w);
1018  sum += BishopAttack::addOne<D,ROOK>(state, to, offset+DirectionSize*scale, w);
1019  return sum;
1020  }
1021  };
1022  class BreakThreatmate : public Feature
1023  {
1024  public:
1025  enum {
1034  };
1035  BreakThreatmate() : Feature("BreakThreatmate", DIM)
1036  {
1037  }
1038  static bool isKingMove(Move move)
1039  {
1040  return move.ptype() == KING;
1041  }
1042  static bool isOpeningKingRoad(Move move, Square king)
1043  {
1044  return ! move.isDrop()
1045  && move.from().isNeighboring8(king);
1046  }
1047  static bool isDefendingThreatmate(Move move, Move threatmate,
1048  const NumEffectState& state)
1049  {
1050  if (move.to() == threatmate.to()
1051  || state.hasEffectIf(move.ptypeO(), move.to(),
1052  threatmate.to()))
1053  return true;
1054  if (threatmate.isDrop())
1055  return false;
1056  Offset32 offset32=Offset32(threatmate.from(),move.to());
1057  EffectContent effect=Ptype_Table.getEffect(move.ptypeO(),offset32);
1058  if (! effect.hasEffect())
1059  return false;
1060  if (effect.offset() == threatmate.to()-threatmate.from())
1061  return state.isEmptyBetween(threatmate.from(), move.to());
1062  return false;
1063  }
1064  static bool isDefendingKing8(Move move, Square king,
1065  const NumEffectState& state)
1066  {
1068  (state, move.ptypeO(), move.to(), king))
1069  return true;
1070  mask_t m = state.longEffectAt(move.to(), alt(state.turn()));
1071  while (m.any()) {
1072  const Piece piece = state.pieceOf
1073  (m.takeOneBit() +PtypeFuns<LANCE>::indexNum*32);
1075  (state, piece.ptypeO(), piece.square(), king))
1076  return true;
1077  }
1078  return false;
1079  }
1080  double match(const StateInfo& info, const MoveInfo& move, int offset, const double *w) const
1081  {
1082  if (! info.threatmate_move.isNormal())
1083  return 0;
1084  const NumEffectState& state = *info.state;
1085  const StateInfo::pattern_square_t& cache
1086  = info.pattern_cache[move.move.to().index()];
1087  const int PatternAny = ptypeOIndex(PTYPEO_EDGE)*PatternCommon::SquareDim;
1088  double sum = 0.0;
1089  if (isKingMove(move.move)) {
1090  // king move
1091  sum += w[offset + KingMoveBase + PatternAny];
1092  for (size_t i=0; i<cache.size() && cache[i] >= 0; ++i) {
1093  sum += w[offset + KingMoveBase + cache[i]];
1094  }
1095  } else {
1096  const Square king = state.kingSquare(move.player);
1097  if (isOpeningKingRoad(move.move, king)) {
1098  // open king road
1099  int base = OpenRoadBase + move.move.ptype()*PatternCacheSize;
1100  sum += w[offset + base + PatternAny];
1101  for (size_t i=0; i<cache.size() && cache[i] >= 0; ++i) {
1102  sum += w[offset + base + cache[i]];
1103  }
1104  }
1106  state)) {
1107  // add effect to threatmate-move-at
1108  int base = move.move.ptype()*PatternCacheSize;
1109  sum += w[offset + base + PatternAny];
1110  for (size_t i=0; i<cache.size() && cache[i] >= 0; ++i) {
1111  sum += w[offset + base + cache[i]];
1112  }
1113  } else if (isDefendingKing8(move.move, king, state)) {
1114  // add effect to king8
1115  int base = move.move.ptype()*PatternCacheSize
1116  + AddEffect8Base;
1117  sum += w[offset + base + PatternAny];
1118  for (size_t i=0; i<cache.size() && cache[i] >= 0; ++i) {
1119  sum += w[offset + base + cache[i]];
1120  }
1121  }
1122  const Piece captured = state.pieceOnBoard(move.move.to());
1123  // capture
1124  if (captured.isPiece()) {
1126  (state, captured.ptypeO(), captured.square(), king)) {
1127  sum += w[offset + CaptureBase
1128  + captured.ptype()*PTYPE_SIZE+move.move.ptype()];
1129  sum += w[offset + CaptureBase
1130  + captured.ptype()*PTYPE_SIZE];
1131  }
1132  else {
1133  sum += w[offset + CaptureBase + captured.ptype()*PTYPE_SIZE
1134  + PTYPE_EDGE];
1135  }
1136  }
1137  }
1138  if (sum == 0.0)
1139  sum += w[offset + OtherMoveBase];
1140  return sum;
1141  }
1142  };
1143 
1144  class SendOff : public Feature
1145  {
1146  public:
1147  enum {
1149  };
1150  SendOff() : Feature("SendOff", DIM)
1151  {
1152  }
1153  double match(const StateInfo& info, const MoveInfo& move, int offset, const double *w) const
1154  {
1155  if (! info.sendoffs.isMember(move.move.to()))
1156  return 0;
1157  return w[offset + move.move.ptype()];
1158  }
1159  };
1160 
1161  class LureDefender : public Feature
1162  {
1163  public:
1164  enum {
1167  };
1168  LureDefender() : Feature("LureDefender", DIM)
1169  {
1170  }
1171  static double match(const NumEffectState& state, Move move, int see,
1172  const StateInfo::pinned_gs_t& pinned_list,
1173  int offset, const double *w)
1174  {
1175  const Square to = move.to(), king = state.kingSquare(alt(state.turn()));
1176  const Offset up = Board_Table.getOffset(state.turn(), U);
1177  const int basic_a = move.ptype() * PTYPE_SIZE*PTYPE_SIZE;
1178  double sum = 0.0;
1179  for (PinnedGeneral defense: pinned_list) {
1180  if (to != defense.attack)
1181  continue;
1182  assert(defense.general.owner() != move.player());
1183  assert(defense.covered.owner() != move.player());
1184  if (defense.general.square() == move.to()+up)
1185  offset += ATTACK_DIM;
1186  else if (state.hasEffectIf(move.ptypeO(), move.to(), defense.general.square()))
1187  offset += ATTACK_DIM*2;
1188  int a = basic_a;
1189  if (defense.covered.square().canPromote(state.turn())
1190  && canPromote(move.ptype()))
1191  a = promote(move.ptype()) * PTYPE_SIZE*PTYPE_SIZE;
1192  const int b = defense.general.ptype() * PTYPE_SIZE;
1193  const int c = defense.covered.ptype();
1194  sum += w[offset];
1195  if (see < 0)
1196  sum += w[offset+1] * see/1024.0;
1197  sum += w[offset + a];
1198  sum += w[offset + b];
1199  sum += w[offset + c];
1200  sum += w[offset + a + b];
1201  sum += w[offset + a + c];
1202  sum += w[offset + b + c];
1203  if (defense.covered.square().canPromote(state.turn())) {
1204  sum += w[offset + a + PTYPE_EDGE];
1205  sum += w[offset + b + PTYPE_EDGE];
1206  }
1207  if (defense.covered.square().isNeighboring8(king)) {
1208  sum += w[offset + a + KING];
1209  sum += w[offset + b + KING];
1210  }
1211  sum += w[offset + a + b + c];
1212  break;
1213  }
1214  return sum;
1215  }
1216  double match(const StateInfo& info, const MoveInfo& move, int offset, const double *w) const
1217  {
1218  return match(*info.state, move.move, move.see,
1219  info.exchange_pins[alt(move.player)], offset, w);
1220  }
1221  };
1222 
1224  {
1225  public:
1226  enum {
1228  };
1229  CheckmateIfCapture() : Feature("CheckmateIfCapture", DIM)
1230  {
1231  }
1232  double match(const StateInfo& info, const MoveInfo& move, int offset, const double *w) const
1233  {
1234  if (info.state->inCheck() || move.see > -256)
1235  return 0;
1236  const Square king = info.state->kingSquare(alt(move.player));
1237  if (move.move.capturePtype() != PTYPE_EMPTY
1238  && ! info.state->hasPieceOnStand<GOLD>(move.player)
1239  && ! info.state->hasPieceOnStand<SILVER>(move.player)
1240  && ! info.move_candidate_exists[alt(move.player)])
1241  return 0;
1243  (*info.state, move.move.ptypeO(), move.move.to(), king))
1244  return 0;
1245  if (hasSafeCapture(info.copy, move.move))
1246  return 0;
1247  int ptype_index = move.move.ptype()*PTYPE_SIZE;
1248  int capture_index = move.move.capturePtype();
1249  double sum = 0.0;
1250  sum += w[offset + ptype_index + capture_index];
1251  sum += w[offset + capture_index];
1252  sum += w[offset + ptype_index + PTYPE_EDGE];
1253  sum += w[offset + PTYPE_EDGE];
1254  return sum;
1255  }
1256  static bool hasSafeCapture(NumEffectState& state, Move);
1257  };
1258  class AttackKing8Long : public Feature
1259  {
1260  public:
1261  enum {
1263  };
1264  AttackKing8Long() : Feature("AttackKing8Long", DIM)
1265  {
1266  }
1267  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
1268  {
1269  const Move move = info.move;
1270  double sum = 0.0;
1271  for (Piece piece: state.king8_long_pieces) {
1272  if (! state.state->hasEffectIf(move.ptypeO(), move.to(),
1273  piece.square()))
1274  continue;
1275  sum += w[offset + PTYPE_EMPTY*PTYPE_SIZE+piece.ptype()]
1276  + w[offset + move.ptype()*PTYPE_SIZE+PTYPE_EMPTY]
1277  + w[offset + move.ptype()*PTYPE_SIZE+piece.ptype()];
1278  if (state.pin_by_opposing_sliders.isMember(piece)
1279  && info.see < 0)
1280  sum += w[offset + PTYPE_EMPTY*PTYPE_SIZE+PTYPE_EDGE]*info.see/1024.0;
1281  }
1282  return sum;
1283  }
1284  };
1285  class OpposingPawn : public Feature
1286  {
1287  public:
1288  enum {
1289  DIM = /*king-x*/9 * /* stand-pawn */ 3 * /* others */ 2,
1290  };
1291  OpposingPawn() : Feature("OpposingPawn", DIM)
1292  {
1293  }
1294  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
1295  {
1296  const Move move = info.move;
1297  if (move.ptype() != PAWN)
1298  return 0.0;
1299  const Square front = move.to() + Board_Table.getOffset(info.player, U);
1300  if (state.state->pieceAt(front).ptype() != PAWN)
1301  return 0.0;
1302  int king_x = abs(state.state->kingSquare(alt(info.player)).x() - front.x());
1303  int stand_pawn = state.state->countPiecesOnStand<PAWN>(info.player);
1304  if (move.isDrop())
1305  --stand_pawn;
1306  stand_pawn = std::min(2, stand_pawn);
1307  bool has_other = state.state->hasPieceOnStand<LANCE>(info.player)
1308  || state.state->hasPieceOnStand<KNIGHT>(info.player)
1309  || state.state->hasPieceOnStand<SILVER>(info.player)
1310  || state.state->hasPieceOnStand<GOLD>(info.player)
1311  || state.state->hasPieceOnStand<ROOK>(info.player)
1312  || state.state->hasPieceOnStand<BISHOP>(info.player);
1313  int index = (king_x * 3 + stand_pawn) * 2 + has_other;
1314  return w[offset + index];
1315  }
1316  };
1317 
1319  {
1320  public:
1321  enum {
1322  DIM = /*king-x*/9 * /* stand-pawn */ 3 * /* others */ 2 * /* capturepawn */ 2,
1323  };
1324  DropAfterOpposingPawn() : Feature("DropAfterOpposingPawn", DIM)
1325  {
1326  }
1327  double match(const StateInfo& state, const MoveInfo& info, int offset, const double *w) const
1328  {
1329  const Move move = info.move;
1330  if (move.ptype() != PAWN || ! move.isDrop() || ! state.history->hasLastMove())
1331  return 0.0;
1332  int to_x = move.to().x();
1333  const Move last_move = state.history->lastMove();
1334  if (! last_move.isNormal() || last_move.isDrop()
1335  || last_move.to().x() != to_x
1336  || last_move.from().x() != to_x)
1337  return 0.0;
1338 
1339  const Square front = move.to()+Board_Table.getOffset(info.player, U);
1340  if (! front.canPromote(info.player))
1341  return 0.0;
1342  int king_x = abs(state.state->kingSquare(alt(info.player)).x() - to_x);
1343  int stand_pawn = std::min(2, state.state->countPiecesOnStand<PAWN>(info.player)-1);
1344  bool has_other = state.state->hasPieceOnStand<LANCE>(info.player)
1345  || state.state->hasPieceOnStand<KNIGHT>(info.player)
1346  || state.state->hasPieceOnStand<SILVER>(info.player)
1347  || state.state->hasPieceOnStand<GOLD>(info.player)
1348  || state.state->hasPieceOnStand<ROOK>(info.player)
1349  || state.state->hasPieceOnStand<BISHOP>(info.player);
1350  bool follow_pawn_capture = last_move.capturePtype() == PAWN;
1351  int index = ((king_x * 3 + stand_pawn) * 2 + has_other) * 2 + follow_pawn_capture;
1352  return w[offset + index];
1353  }
1354  };
1355 
1356  class CoverPawn : public Feature
1357  {
1358  public:
1359  enum {
1360  DIM = 9 * 2 * PTYPE_SIZE * PTYPE_SIZE
1361  };
1362  CoverPawn() : Feature("CoverPawn", DIM)
1363  {
1364  }
1365  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1366  {
1367  if (! si.history->hasLastMove() || si.state->inCheck()
1368  || mi.move.isCaptureOrPromotion())
1369  return 0.0;
1370  const Move last_move = si.history->lastMove();
1371  if (last_move.ptype() != PAWN)
1372  return 0.0;
1373  const Offset diff = Board_Table.getOffset(mi.player, U);
1374  const Square front = last_move.to()-diff, front2 = front-diff;
1375  if (si.state->pieceOnBoard(front).ptype() != PAWN // must be turn's pawn
1376  || si.state->pieceAt(front2).isOnBoardByOwner(alt(mi.player)))
1377  return 0.0;
1378  const bool cover = si.state->hasEffectIf
1379  (mi.move.ptypeO(), mi.move.to(), front);
1380  const Ptype moved = cover ? mi.move.ptype() : PTYPE_EDGE,
1381  threatened = si.state->pieceAt(front2).ptype();
1382  const int a = std::min(2,si.state->countEffect(alt(mi.player), front) - 1);
1383  assert(a >= 0);
1384  const int b = std::min(2,si.state->countEffect(mi.player, front));
1385  const int ptype_index = moved*PTYPE_SIZE+threatened;
1386  const bool has_pawn = si.state->hasPieceOnStand(alt(mi.player),PAWN);
1387  const int pawn_index = PTYPE_SIZE*PTYPE_SIZE;
1388  const int effect_index = (a*3+b)*2*PTYPE_SIZE*PTYPE_SIZE
1389  + (has_pawn ? pawn_index : 0);
1390  assert(effect_index >= 0);
1391  return w[offset + threatened]
1392  + w[offset + ptype_index]
1393  + w[offset + effect_index + ptype_index];
1394  }
1395  };
1396  class SacrificeAttack : public Feature
1397  {
1398  public:
1399  enum {
1401  DIM = StandCount * PTYPE_SIZE * 2
1402  };
1403  SacrificeAttack() : Feature("SacrificeAttack", DIM)
1404  {
1405  }
1406  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1407  {
1408  const Square king = si.state->kingSquare(alt(mi.player));
1409  if (mi.see >= 0
1411  (*si.state, mi.move.ptypeO(), mi.move.to(), king)))
1412  return 0.0;
1413  assert(PieceStand::order[6] == PAWN);
1414  int stand = mi.standIndex(*si.state);
1415  int index = (stand * PTYPE_SIZE + mi.move.ptype()) * 2;
1416  double sum = w[offset + index];
1417  if (si.history->hasLastMove(2)) {
1418  Move my_last_move = si.history->lastMove(2);
1419  if (my_last_move.isNormal()
1421  (*si.state, my_last_move.ptypeO(), my_last_move.to(), king))
1422  sum += w[offset + index + 1];
1423  }
1424  return sum;
1425  }
1426  };
1427  class King5x5Ptype : public Feature
1428  {
1429  public:
1430  enum {
1432  DIM = 2 * ONE_DIM,
1433  };
1434  King5x5Ptype() : Feature("King5x5Ptype", DIM)
1435  {
1436  }
1437  static double addOne(Player king, Square center, const StateInfo& si, const MoveInfo& mi, int offset, const double *w)
1438  {
1439  const Square to = mi.move.to();
1440  int dx = center.x() - to.x();
1441  const int dy = center.y() - to.y();
1442  if (abs(dx) >= 3 || abs(dy) >= 3)
1443  return 0.0;
1444  if ((king == BLACK && center.x() > 5)
1445  || (king == WHITE && center.x() >= 5))
1446  dx = -dx;
1447  int sq_index = (dx+2)*5 + dy+2;
1448  bool a = mi.move.isDrop() ? si.state->hasEffectAt(mi.player, to)
1449  : si.state->countEffect(mi.player,to) >= 2;
1450  bool d = si.state->hasEffectAt(alt(mi.player), to);
1451  int index = (sq_index*4 + a*2+d) * PTYPE_SIZE*PTYPE_SIZE
1452  + mi.move.capturePtype()*PTYPE_SIZE + mi.move.ptype();
1453  return w[offset + index];
1454  }
1455  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1456  {
1457  return
1458  addOne(mi.player, si.state->kingSquare(mi.player), si, mi, offset, w)
1459  + addOne(alt(mi.player), si.state->kingSquare(alt(mi.player)), si, mi,
1460  offset+ONE_DIM, w);
1461  }
1462  };
1463  class KingBlockade : public Feature
1464  {
1465  public:
1466  enum {
1470  DIM = 5 * StandCount
1471  };
1472  KingBlockade() : Feature("KingBlockade", DIM)
1473  {
1474  }
1475  static bool blockAll(const King8Info& ki, Square king, Move move,
1476  const NumEffectState& state,
1477  const CArray<Direction,3>& directions)
1478  {
1479  int liberty = 0;
1480  for (Direction d: directions) {
1481  if ((ki.liberty() & (1<<d)) == 0)
1482  continue;
1483  ++liberty;
1484  const Square sq = king + Board_Table.getOffset(alt(state.turn()), d);
1485  if (! state.hasEffectIf(move.ptypeO(), move.to(), sq))
1486  return false;
1487  }
1488  return liberty > 0;
1489  }
1490  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1491  {
1492  const NumEffectState& state = *si.state;
1493  const King8Info ki = si.king8Info(alt(mi.player));
1494  const Square king = state.kingSquare(alt(mi.player));
1495  if (ki.libertyCount() == 0
1497  (state, mi.move.ptypeO(), mi.move.to(), king)))
1498  return 0.0;
1499  int stand = mi.standIndex(state);
1500  offset += stand*5;
1501  double sum = 0.0;
1502  if (ki.libertyCount() == 1) {
1503  const Square sq = king
1506  if (! state.hasEffectIf(mi.move.ptypeO(), mi.move.to(), sq))
1507  return 0.0;
1508  sum += w[offset+BlockLastOne];
1509  // fall through
1510  }
1511  const CArray<Direction,3> front3 = {{ UL, U, UR }};
1512  if (blockAll(ki, king, mi.move, state, front3))
1513  sum += w[offset+BlockFront];
1514  const CArray<Direction,3> left3 = {{ UL, L, DL }};
1515  if (blockAll(ki, king, mi.move, state, left3)) {
1516  const bool wide = (mi.player== WHITE && king.x() < 5)
1517  || (mi.player== BLACK && king.x() > 5);
1518  sum += w[offset+(wide ? BlockSideWide : BlockSideOther)];
1519  }
1520  const CArray<Direction,3> right3 = {{ UR, R, DR }};
1521  if (blockAll(ki, king, mi.move, state, right3)) {
1522  const bool wide = (mi.player== BLACK && king.x() < 5)
1523  || (mi.player== WHITE && king.x() > 5);
1524  sum += w[offset+ (wide ? BlockSideWide : BlockSideOther)];
1525  }
1526  const CArray<Direction,3> back3 = {{ DL, D, DR }};
1527  if (blockAll(ki, king, mi.move, state, back3))
1528  sum += w[offset+BlockBack];
1529  return sum;
1530  }
1531  };
1532  class CoverFork : public Feature
1533  {
1534  public:
1535  enum {
1537  };
1538  CoverFork() : Feature("CoverFork", DIM)
1539  {
1540  }
1541  static bool defending(const NumEffectState& state, Move move, Square target)
1542  {
1543  if (state.countEffect(alt(state.turn()), target) > 1)
1544  return false;
1545  if (state.hasEffectIf(move.ptypeO(), move.to(), target))
1546  return true;
1547  Piece attacking = state.findCheapAttack(alt(state.turn()), target);
1548  Offset o = Board_Table.getShortOffsetNotKnight(Offset32(move.to(), target));
1549  if (o.zero()
1550  || ! Board_Table.isBetween(move.to(), attacking.square(), target))
1551  return false;
1552  return state.countEffect(state.turn(), move.to()) >= (1-move.isDrop());
1553  }
1554  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1555  {
1556  const NumEffectState& state = *si.state;
1557  PieceMask attacked = state.piecesOnBoard(mi.player)
1558  & state.effectedMask(alt(mi.player))
1559  & ~(state.effectedMask(mi.player));
1560  attacked.clearBit<PAWN>();
1561  offset += mi.move.ptype()*PTYPE_SIZE*PTYPE_SIZE;
1562  double sum = 0.0;
1563  while (attacked.any()) {
1564  Piece a = state.pieceOf(attacked.takeOneBit());
1565  if (! defending(state, mi.move, a.square()))
1566  continue;
1567  int index_a = a.ptype()*PTYPE_SIZE;
1568  PieceMask copy = attacked;
1569  while (copy.any()) {
1570  Piece b = state.pieceOf(copy.takeOneBit());
1571  if (! defending(state, mi.move, b.square()))
1572  continue;
1573  sum += w[offset];
1574  sum += w[offset+index_a];
1575  sum += w[offset+b.ptype()];
1576  sum += w[offset+index_a+b.ptype()];
1577  }
1578  }
1579  return sum;
1580  }
1581  };
1583  {
1584  public:
1585  enum {
1587  };
1588  ThreatmateByCapture() : Feature("ThreatmateByCapture", DIM)
1589  {
1590  }
1591  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1592  {
1593  const Move move = mi.move;
1594  const Ptype captured = move.capturePtype();
1595  if (captured == PTYPE_EMPTY
1597  & 1<<(captured-PTYPE_BASIC_MIN)) == 0)
1598  return 0.0;
1599  double sum = 0.0;
1600  sum += w[offset];
1601  if (mi.see < 0)
1602  sum += w[offset+1] * mi.see/1024.0;
1603  sum += w[offset+captured];
1604  sum += w[offset+move.ptype()*PTYPE_SIZE];
1605  sum += w[offset+move.ptype()*PTYPE_SIZE+captured];
1606  return sum;
1607  }
1608  };
1609 
1611  {
1612  public:
1613  enum {
1614  DIM = 2*PTYPE_SIZE * PTYPE_SIZE
1615  };
1616  PromotionBySacrifice() : Feature("PromotionBySacrifice", DIM)
1617  {
1618  }
1619  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1620  {
1621  const Move move = mi.move;
1622  if (mi.see >= 0 || move.isDrop()
1623  || si.state->inCheck()
1624  || si.threatmate_move.isNormal())
1625  return 0.0;
1626  const NumEffectState& state = *si.state;
1627  mask_t m = state.longEffectAt(move.from(), state.turn());
1628  m &= ~mask_t::makeDirect(PtypeFuns<LANCE>::indexMask);
1629  double sum = 0.0;
1630  while (m.any()) {
1631  const Piece piece = state.pieceOf
1632  (m.takeOneBit() +PtypeFuns<LANCE>::indexNum*32);
1633  assert(piece.ptype() != LANCE);
1634  if (piece.isPromoted()
1635  || piece.square().canPromote(mi.player))
1636  continue;
1638  assert(! o.zero());
1639  bool can_promote = false;
1640  Square to = move.from()+o;
1641  if (to == move.to())
1642  continue;
1643  while (state[to].isEmpty()) {
1644  if (to.canPromote(mi.player)
1645  && ! state.hasEffectAt(alt(mi.player), to))
1646  can_promote = true;
1647  to += o;
1648  }
1649  assert(state[to] != piece);
1650  int index = 0;
1651  if (piece.ptype() == ROOK)
1652  index += PTYPE_SIZE*PTYPE_SIZE;
1653  index += move.ptype()*PTYPE_SIZE;
1654  if (to.canPromote(mi.player)
1655  && state[to].isOnBoardByOwner(alt(mi.player))
1656  && ! state.hasEffectAt(alt(mi.player), to)) {
1657  sum += w[offset];
1658  sum += w[offset+1]*mi.see/1024.0;
1659  if (mi.check)
1660  sum += w[offset+2];
1661  if (state.hasEffectAt(alt(mi.player), piece.square())) {
1662  sum += w[offset+3];
1663  if (mi.check)
1664  sum += w[offset+4];
1665  }
1666  if (state.hasEffectIf(piece.ptypeO(), to,
1667  state.kingSquare(alt(mi.player))))
1668  sum += w[offset+5];
1669  sum += w[offset + index + state[to].ptype()];
1670  }
1671  else if (can_promote) {
1672  sum += w[offset];
1673  sum += w[offset+1]*mi.see/1024.0;
1674  if (mi.check)
1675  sum += w[offset+2];
1676  if (state.hasEffectAt(alt(mi.player), piece.square())) {
1677  sum += w[offset+3];
1678  if (mi.check)
1679  sum += w[offset+4];
1680  }
1681  sum += w[offset + index];
1682  }
1683  }
1684  return sum;
1685  }
1686  };
1687 
1688  class EscapeThreatened : public Feature
1689  {
1690  public:
1691  enum {
1692  DIM =(2*PTYPE_SIZE * PTYPE_SIZE) * 3 * PTYPE_SIZE
1693  };
1694  EscapeThreatened() : Feature("EscapeThreatened", DIM)
1695  {
1696  }
1697  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1698  {
1699  const NumEffectState& state = *si.state;
1700  const Move move = mi.move;
1701  const Piece target = si.threatened[mi.player];
1702  if (mi.see > 0 || mi.check || mi.open_check
1703  || ! move.isNormal()
1704  || ! target.isPiece() || state.inCheck()
1705  || si.threatmate_move.isNormal()
1707  (state, move.ptypeO(), move.to(), state.kingSquare(alt(mi.player))))
1708  return 0.0;
1709  const int t0 = target.ptype()*PTYPE_SIZE*2*PTYPE_SIZE*3;
1710  const int t1 = t0 + state.findCheapAttack(alt(mi.player), target.square()).ptype()*2*PTYPE_SIZE*3;
1711  const int t2 = t1 + state.hasEffectAt(mi.player, target.square())*PTYPE_SIZE*3;
1712  double sum = 0.0;
1713  if (! move.isDrop() && state[move.from()] == target) {
1714  sum += w[offset + t0];
1715  sum += w[offset + t1];
1716  sum += w[offset + t2];
1717  return sum;
1718  }
1719  if (state.hasEffectIf(move.ptypeO(), move.to(),
1720  target.square())) {
1721  if (move.isDrop()
1722  || ! state.hasEffectIf(move.oldPtypeO(), move.from(),
1723  target.square())) {
1724  sum += w[offset + t0 + move.ptype()];
1725  sum += w[offset + t1 + move.ptype()];
1726  sum += w[offset + t2 + move.ptype()];
1727  return sum;
1728  }
1729  }
1730  // not related move
1731  offset += PTYPE_SIZE;
1732  if (move.isDrop())
1733  offset += PTYPE_SIZE;
1734  sum += w[offset + t0 + move.ptype()];
1735  sum += w[offset + t1 + move.ptype()];
1736  sum += w[offset + t2 + move.ptype()];
1737  return sum;
1738  }
1739  };
1740  class BookMove : public Feature
1741  {
1742  public:
1743  enum {
1744  DIM = 2
1745  };
1746  BookMove() : Feature("BookMove", DIM)
1747  {
1748  }
1749  double match(const StateInfo& si, const MoveInfo& mi, int offset, const double *w) const
1750  {
1751  if (! si.bookmove[0].isNormal())
1752  return 0.0;
1753  if (mi.move == si.bookmove[0] || mi.move == si.bookmove[1])
1754  return w[offset];
1755  return w[offset+1];
1756  }
1757  };
1758  }
1759 }
1760 #endif /* OSL_MOVE_PROBABILITY_FEATURE_H */
1761 // ;;; Local Variables:
1762 // ;;; mode:c++
1763 // ;;; c-basic-offset:2
1764 // ;;; End:
const Offset getOffset(Direction dir) const
Definition: boardTable.h:47
const Offset getShortOffsetNotKnight(Offset32 offset32) const
Longの利きの可能性のあるoffsetの場合は, 反復に使う offsetを Knight以外のShortの利きのoffsetの場合はそれ自身を返す.
Definition: boardTable.h:119
bool isBetween(Square t, Square p0, Square p1) const
p0, p1の間にtがあるかどうか.
Definition: boardTable.h:172
Direction getLongDirection(Offset32 offset32) const
Definition: boardTable.h:71
static size_t size()
Definition: container.h:76
const Offset offset() const
返り値が0なら長い利きがない, 0以外なら辿るのに必要なoffset (2005/3/25 に仕様変更 - 長い利きだが隣の場合もoffsetを返す)
Definition: effectContent.h:44
bool hasEffect() const
短い利きがあるか,間がemptyなら長い利きがある
Definition: effectContent.h:34
bool isMember(const T &e, const_iterator first, const_iterator last) const
Definition: container.h:257
圧縮していない moveの表現 .
Definition: basic_type.h:1052
PtypeO ptypeO() const
移動後のPtype, i.e., 成る手だった場合成った後
Definition: basic_type.h:1162
bool isPromotion() const
Definition: basic_type.h:1147
Ptype ptype() const
Definition: basic_type.h:1155
Player player() const
Definition: basic_type.h:1195
PtypeO oldPtypeO() const
移動前のPtypeO, i.e., 成る手だった場合成る前
Definition: basic_type.h:1168
bool isDrop() const
Definition: basic_type.h:1150
Ptype capturePtype() const
Definition: basic_type.h:1180
bool isNormal() const
INVALID でも PASS でもない.
Definition: basic_type.h:1088
bool isCaptureOrPromotion() const
Definition: basic_type.h:1149
Ptype oldPtype() const
移動前のPtype, i.e., 成る手だった場合成る前
Definition: basic_type.h:1174
const Square to() const
Definition: basic_type.h:1132
const Square from() const
Definition: basic_type.h:1125
利きを持つ局面
const NumBitmapEffect effectSetAt(Square sq) const
const Piece selectCheapPiece(PieceMask effect) const
利きの中から安そうな駒を選ぶ
const PieceMask effectedMask(Player pl) const
pl からの利きが(1つ以上)ある駒一覧
int countEffect(Player player, Square target) const
利きの数を数える.
bool hasEffectByPiece(Piece attack, Square target) const
駒attack が target に利きを持つか (旧hasEffectToと統合)
const PieceMask & piecesOnBoard(Player p) const
bool hasEffectAt(Square target) const
対象とするマスにあるプレイヤーの利きがあるかどうか.
const Piece findCheapAttack(Player P, Square square) const
bool hasEffectIf(PtypeO ptypeo, Square attacker, Square target) const
attackerにptypeoの駒がいると仮定した場合にtargetに利きがあるかどうか を stateをupdateしないで確かめる.
bool inCheck(Player P) const
Pの玉が王手状態
const mask_t longEffectAt(Square target) const
差が uniqになるような座標の差分.
Definition: offset32.h:17
座標の差分
Definition: basic_type.h:430
bool zero() const
Definition: basic_type.h:502
駒番号のビットセット.
Definition: pieceMask.h:21
const mask_t getMask(int num) const
Definition: pieceMask.h:59
void set(int num)
Definition: pieceMask.h:48
void clearBit()
unpromote(PTYPE) の駒のbit を消す
Definition: pieceMask.h:74
bool any() const
Definition: pieceMask.h:57
void reset(int num)
Definition: pieceMask.h:54
static const CArray< Ptype, 7 > order
持駒の表示で良く使われる順番.
PtypeO ptypeO() const
Definition: basic_type.h:824
Ptype ptype() const
Definition: basic_type.h:821
bool isPromoted() const
promoteした駒かどうかをチェックする
Definition: basic_type.h:898
const Square square() const
Definition: basic_type.h:832
bool isEmpty() const
Definition: basic_type.h:913
bool isEdge() const
Definition: basic_type.h:919
Player owner() const
Definition: basic_type.h:963
bool isPiece() const
Definition: basic_type.h:953
bool isOnBoardByOwner() const
piece がプレイヤーPの持ち物でかつボード上にある駒の場合は true.
Definition: basic_type.h:852
int number() const
Definition: basic_type.h:828
const EffectContent getEffect(PtypeO ptypeo, Square from, Square to) const
fromにいるptypeoがtoに利きを持つか?
Definition: ptypeTable.h:112
int getMoveMask(Ptype ptype) const
Definition: ptypeTable.h:84
const Piece pieceOnBoard(Square sq) const
Definition: simpleState.h:170
bool hasPieceOnStand(Player player, Ptype ptype) const
Definition: simpleState.h:191
const Piece kingPiece() const
Definition: simpleState.h:83
Player turn() const
Definition: simpleState.h:220
bool canDropPawnTo(Player player, int x) const
xの筋に歩を打てる
Definition: simpleState.h:155
const Piece pieceOf(int num) const
Definition: simpleState.h:76
bool isEmptyBetween(Square from, Square to, Offset offset, bool pieceExistsAtTo=false) const
Definition: simpleState.h:267
Square kingSquare() const
Definition: simpleState.h:94
int countPiecesOnStand(Player pl, Ptype ptype) const
持駒の枚数を数える
Definition: simpleState.h:182
const Piece pieceAt(Square sq) const
Definition: simpleState.h:167
unsigned int index() const
Definition: basic_type.h:572
bool isPieceStand() const
Definition: basic_type.h:576
int y() const
将棋としてのY座標を返す.
Definition: basic_type.h:567
bool isNeighboring8(Square to) const
Definition: basic_type.cc:202
bool canPromote() const
Definition: basic_type.h:659
const Square squareForBlack(Player player) const
Definition: basic_type.h:598
bool isOnBoard() const
盤面上を表すかどうかの判定. 1<=x() && x()<=9 && 1<=y() && y()<=9 Squareの内部表現に依存する.
Definition: basic_type.h:583
bool isOnBoardRegion() const
squareがONBOARD_MINとONBOARD_MAXの間にある
Definition: basic_type.h:641
int x() const
将棋としてのX座標を返す.
Definition: basic_type.h:563
unsigned int square
Definition: basic_type.h:533
敵玉の8近傍の状態を表す.
Definition: king8Info.h:29
unsigned int liberty() const
8-15 bit 目を 0-7bitにshiftして返す
Definition: king8Info.h:54
unsigned int libertyCount() const
libertyの数
Definition: king8Info.h:82
bool hasLastMove(size_t last=1) const
Definition: moveStack.h:27
const Move lastMove(size_t last=1) const
Definition: moveStack.h:28
現在の定義 (2005/3/4以降)
const mask_t selectLong() const
static bool hasEffect(const NumEffectState &state, PtypeO ptypeo, Square from, Square target)
ptypeo の駒がfromからtargetの8近傍に直接の利きを持つか
static double addOne(Direction dir, const StateInfo &state, const MoveInfo &move, int offset, const double *w)
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
static double addSquare(Square target, const StateInfo &info, int offset, const double *w)
static double addOne(const StateInfo &info, Square to, int offset, const double *w)
static double findAll(const StateInfo &state, Move move, const double *w, int offset=0)
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
static void makeLongAttackOne(StateInfo &info, Piece piece, Direction d)
Definition: feature_.cc:147
static void updateCache(StateInfo &)
Definition: feature_.cc:113
static double findAll(const StateInfo &state, Move move, const double *w, int offset=0)
static int longAttackIndex(osl::PtypeO ptypeo)
static double findAll(const StateInfo &state, Player P, Square target, const double *w, int offset)
static double addPiece(const StateInfo &state, Piece piece, Square to, const double *w, int offset)
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
static int ptypeSupport(Ptype moved, bool has_support)
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
static bool isDefendingThreatmate(Move move, Move threatmate, const NumEffectState &state)
static bool isOpeningKingRoad(Move move, Square king)
double match(const StateInfo &info, const MoveInfo &move, int offset, const double *w) const
static bool isDefendingKing8(Move move, Square king, const NumEffectState &state)
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
static int sign(const NumEffectState &state, Move move, Player player)
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
static int checkIndex(const MoveInfo &move)
static bool hasSafeCapture(NumEffectState &state, Move)
Definition: feature_.cc:205
double match(const StateInfo &info, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
static bool defending(const NumEffectState &state, Move move, Square target)
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
virtual double match(const StateInfo &, const MoveInfo &, int offset, const double *) const =0
static int classifyEffect9(const NumEffectState &state, Player player, Square to)
double match(const StateInfo &state_info, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state_info, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
static double addOne(Player king, Square center, const StateInfo &si, const MoveInfo &mi, int offset, const double *w)
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
static bool blockAll(const King8Info &ki, Square king, Move move, const NumEffectState &state, const CArray< Direction, 3 > &directions)
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &info, const MoveInfo &move, int offset, const double *w) const
static double match(const NumEffectState &state, Move move, int see, const StateInfo::pinned_gs_t &pinned_list, int offset, const double *w)
double match(const StateInfo &info, const MoveInfo &move, int offset, const double *w) const
static int longPtype(const NumEffectState &state, Square position, Player player)
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
static std::string name(int x, int y)
PatternCommon(const std::string &name, int dim)
static void updateCacheOne(Square target, StateInfo &info)
Definition: feature_.cc:25
double addOne(const StateInfo &state, int offset, const double *w, Square position) const
static void updateCache(StateInfo &info)
Definition: feature_.cc:14
std::pair< int, int > squareStatus(const NumEffectState &state, Player player, Square to, Square &front) const
double matchPtype(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &info, const MoveInfo &move, int offset, const double *w) const
static int fromTo(Square to, Square from)
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
static int fromTo(Square to, Square from)
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
double match(const StateInfo &state, const MoveInfo &move, int offset, const double *w) const
double match(const StateInfo &si, const MoveInfo &mi, int offset, const double *w) const
double match(const StateInfo &state_info, const MoveInfo &info, int offset, const double *w) const
static const Piece find(const NumEffectState &state, Square to, const PieceMask &remove, Player player)
static size_t supportAttack(const StateInfo &info, Square to, Move move)
double match(const StateInfo &state, const MoveInfo &info, int offset, const double *w) const
static void supportAttack(const NumEffectState &state, Square to, const PieceMask &my_pin, const PieceMask &op_pin, Player turn, std::pair< Ptype, Ptype > &out)
static void supportAttack(const StateInfo &info, Square to, Move move, std::pair< Ptype, Ptype > &out)
int max(Player p, int v1, int v2)
Definition: evalTraits.h:84
int min(Player p, int v1, int v2)
Definition: evalTraits.h:92
GeneralMask< mask_int_t > mask_t
Definition: mask.h:351
PatternBase< false > Pattern
PatternBase< true > PatternPromotion
Ptype
駒の種類を4ビットでコード化する
Definition: basic_type.h:84
@ ROOK
Definition: basic_type.h:100
@ BISHOP
Definition: basic_type.h:99
@ PROOK
Definition: basic_type.h:92
@ PAWN
Definition: basic_type.h:95
@ PTYPE_EDGE
Definition: basic_type.h:86
@ KING
Definition: basic_type.h:93
@ KNIGHT
Definition: basic_type.h:97
@ PTYPE_EMPTY
Definition: basic_type.h:85
@ SILVER
Definition: basic_type.h:98
@ PTYPE_BASIC_MIN
Definition: basic_type.h:103
@ GOLD
Definition: basic_type.h:94
@ PBISHOP
Definition: basic_type.h:91
@ LANCE
Definition: basic_type.h:96
const PtypeTable Ptype_Table
Definition: tables.cc:97
const int PTYPE_SIZE
Definition: basic_type.h:107
Ptype getPtype(PtypeO ptypeO)
Definition: basic_type.h:217
const int PTYPEO_SIZE
Definition: basic_type.h:308
bool canPromote(Ptype ptype)
ptypeがpromote可能な型かどうかのチェック promote済みの場合はfalseを返す
Definition: basic_type.h:147
constexpr Direction longToShort(Direction d)
Definition: basic_type.h:380
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に,promote前の型を返す. promoteしていない型の時はそのまま返す
Definition: basic_type.h:157
const BoardTable Board_Table
Definition: tables.cc:95
Player getOwner(PtypeO ptypeO)
Definition: basic_type.h:256
Direction
Definition: basic_type.h:310
@ R
Definition: basic_type.h:317
@ D
Definition: basic_type.h:319
@ UL
Definition: basic_type.h:313
@ DR
Definition: basic_type.h:320
@ U
Definition: basic_type.h:314
@ L
Definition: basic_type.h:316
@ UR
Definition: basic_type.h:315
@ DL
Definition: basic_type.h:318
unsigned int ptypeOIndex(PtypeO ptypeo)
Definition: basic_type.h:205
Offset32Base< 8, 9 > Offset32
Definition: offset32.h:63
constexpr int sign(Player player)
Definition: basic_type.h:23
Player
Definition: basic_type.h:8
@ WHITE
Definition: basic_type.h:10
@ BLACK
Definition: basic_type.h:9
PtypeO
Player + Ptype [-15, 15] PtypeO の O は Owner の O.
Definition: basic_type.h:199
constexpr bool isLong(Direction d)
Definition: basic_type.h:350
constexpr Player alt(Player player)
Definition: basic_type.h:13
Ptype promote(Ptype ptype)
promote可能なptypeに対して,promote後の型を返す promote不可のptypeを与えてはいけない.
Definition: basic_type.h:173
PtypeO captured(PtypeO ptypeO)
unpromoteすると共に,ownerを反転する.
Definition: basic_type.h:264
bool isMember(Square position) const
Definition: square8.h:22
static bool hasEffect(const NumEffectState &, Square target, Player attack)
target に attack の追加利きが一つでもあるか. 相手の影利きが先にある場合は対象としない.
static int bsf(Integer mask)
Definition: mask.h:138
int standIndex(const NumEffectState &state) const
Definition: moveInfo.h:22
CArray< Move, 2 > bookmove
Definition: stateInfo.h:44
CArray< Piece, 2 > threatened
Definition: stateInfo.h:26
unsigned int possible_threatmate_ptype
Definition: stateInfo.h:43
const NumEffectState * state
Definition: stateInfo.h:22
const MoveStack * history
Definition: stateInfo.h:23
CArray< bool, 2 > move_candidate_exists
Definition: stateInfo.h:39
CArray< pinned_gs_t, 2 > exchange_pins
Definition: stateInfo.h:38
bool pinByOpposingSliders(Piece p) const
Definition: stateInfo.h:83
CArray< pattern_square_t, Square::SIZE > pattern_cache
Definition: stateInfo.h:30
King8Info king8Info(Player pl) const
Definition: stateInfo.h:88
CArray< PieceMask, 2 > pin
Definition: stateInfo.h:34
CArray2d< long_attack_t, 40, 8 > long_attack_cache
Definition: stateInfo.h:28