All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
move_probability/feature.cc
Go to the documentation of this file.
1 /* feature.cc
2  */
5 #include "osl/neighboring8.h"
6 #include <iostream>
7 
10 {
11 }
12 
13 
16 {
17  for (int x=1; x<=9; ++x) {
18  for (int y=1; y<=9; ++y) {
19  const Square position(x,y);
20  updateCacheOne(position, info);
21  }
22  }
23 }
24 
27 {
28  const NumEffectState& state = *info.state;
30  = info.pattern_cache[position.index()];
31  cache.fill(-1);
32  const CArray<Square,2> kings = {{
33  state.kingSquare(BLACK),
34  state.kingSquare(WHITE),
35  }};
36  const Player turn = state.turn();
37  int cur = 0;
38 
39  Piece target = state.pieceAt(position);
40  PtypeO ptypeo = target.ptypeO();
41  if (turn == WHITE)
42  ptypeo = altIfPiece(ptypeo);
43  size_t basic = ptypeOIndex(ptypeo)*SquareDim;
44  std::pair<Ptype,Ptype> pair;
45  ToEffect::supportAttack(state, position,
46  info.pin[turn], info.pin[alt(turn)],
47  turn, pair);
48  int effect9 = classifyEffect9(state, turn, position);
49  cache[cur++] = basic + pair.first;
50  cache[cur++] = basic + AttackBase + pair.second;
51  cache[cur++] = basic + EffectBase + effect9;
52  assert(pair.first != PTYPE_EDGE);
53  assert(pair.second != PTYPE_EDGE);
54  if (isPiece(ptypeo)) {
55  if (info.attack_shadow[target.number()][turn])
56  cache[cur++] = basic + PTYPE_EDGE;
57  if (info.attack_shadow[target.number()][alt(turn)])
58  cache[cur++] = basic + AttackBase + PTYPE_EDGE;
59  }
60  assert(basic + EffectBase + effect9 < PatternCacheSize);
61  int op_king_distance = abs(kings[alt(turn)].x()-position.x())
62  + abs(kings[alt(turn)].y()-position.y());
63  if (op_king_distance == 0) // KING
64  op_king_distance = state.king8Info(alt(turn)).libertyCount();
65  else
66  --op_king_distance;
67  if (op_king_distance < OpKingSize)
68  cache[cur++] = basic + OpKingBase + op_king_distance;
69  int my_king_distance = abs(kings[turn].x()-position.x())
70  + abs(kings[turn].y()-position.y());
71  if (my_king_distance == 0) // KING
72  my_king_distance = state.king8Info(turn).libertyCount();
73  else
74  --my_king_distance;
75  if (my_king_distance < MyKingSize)
76  cache[cur++] = basic + MyKingBase + my_king_distance;
77  // promotion
78  if (position.canPromote(turn))
79  cache[cur++] = basic + PromotionBase;
80  else if (position.canPromote(alt(turn)))
81  cache[cur++] = basic + PromotionBase + 1;
82  if (target.isPiece()) {
83  // pin or open
84  if (state.pinOrOpen(turn).test(target.number()))
85  cache[cur++] = basic + PinOpenBase + (target.owner() == turn);
86  if (state.pinOrOpen(alt(turn)).test(target.number()))
87  cache[cur++] = basic + PinOpenBase + 2 + (target.owner() == alt(turn));
88  // last to
89  if (info.history->hasLastMove()) {
90  if (info.history->lastMove().to() == position)
91  cache[cur++] = basic + LastToBase;
92  for (int i=1; i<4; ++i) {
93  if (! info.history->hasLastMove(i+1))
94  break;
95  if (info.history->lastMove(i+1).to() == position)
96  cache[cur++] = basic + LastToBase + i;
97  }
98  }
99  }
100  // last effect changed
101  if (info.history->hasLastMove()) {
102  if (info.changed_effects.test(position))
103  cache[cur++] = basic + LastEffectChangedBase;
104  if (target.isPiece() && info.last_add_effect.test(target.number())) {
105  int ptype_index = info.last_move_ptype5 - PTYPE_BASIC_MIN + 1;
106  cache[cur++] = basic + LastEffectChangedBase + ptype_index;
107  }
108  }
109 }
110 
111 
112 
115 {
116  const NumEffectState& state = *info.state;
117  for (int i=PtypeTraits<LANCE>::indexMin;
118  i<PtypeTraits<LANCE>::indexLimit; ++i) {
119  const Piece p = state.pieceOf(i);
120  if (! p.isOnBoard() || p.isPromoted())
121  continue;
122  const Direction d = p.owner() == BLACK ? U : D;
123  makeLongAttackOne(info, p, d);
124  }
126  i<PtypeTraits<BISHOP>::indexLimit; ++i) {
127  const Piece p = state.pieceOf(i);
128  if (! p.isOnBoard())
129  continue;
130  makeLongAttackOne(info, p, UL);
131  makeLongAttackOne(info, p, UR);
132  makeLongAttackOne(info, p, DL);
133  makeLongAttackOne(info, p, DR);
134  }
135  for (int i=PtypeTraits<ROOK>::indexMin;
136  i<PtypeTraits<ROOK>::indexLimit; ++i) {
137  const Piece p = state.pieceOf(i);
138  if (! p.isOnBoard())
139  continue;
140  makeLongAttackOne(info, p, L);
141  makeLongAttackOne(info, p, R);
142  makeLongAttackOne(info, p, U);
143  makeLongAttackOne(info, p, D);
144  }
145 }
146 
149  Piece piece, Direction d)
150 {
151  const NumEffectState& state = *info.state;
153  = info.long_attack_cache[piece.number()][d];
154  const Player turn = state.turn();
155  const PtypeO attacking = (turn == BLACK)
156  ? piece.ptypeO() : alt(piece.ptypeO());
157  Square attack_to = state.mobilityOf(d, piece.number());
158  Square attack_to2 = attack_to;
159  assert(! attack_to.isPieceStand());
160  if (attack_to.isEdge())
161  attack_to -= Board_Table.getOffsetForBlack(d);
162  else {
163  const Offset o = Board_Table.getOffsetForBlack(d);
164  attack_to2 += o; // allow edge if neighboring
165  if (state.pieceAt(attack_to2).isEmpty()) {
166  do {
167  attack_to2 += o;
168  } while (state.pieceAt(attack_to2).isEmpty());
169  if (state.pieceAt(attack_to2).isEdge())
170  attack_to2 -= o;
171  }
172  }
173  PtypeO attacked = state.pieceOnBoard(attack_to).ptypeO();
174  if (isPiece(attacked) && turn == WHITE)
175  attacked = alt(attacked);
176  int index = (longAttackIndex(attacking)*PTYPEO_SIZE
177  + ptypeOIndex(attacked))*OptionSize;
178  out.push_back(index);
179  if (Neighboring8::isNeighboring8(attack_to, state.kingSquare(turn)))
180  out.push_back(index + 1); // 1,King8
181  if (! state.hasEffectAt(turn, attack_to))
182  out.push_back(index + 2); // 2,HasSupport;
183  if (attack_to.canPromote(alt(turn)))
184  out.push_back(index + 3); // 3,Promotable;
185  Piece attacked2 = state.pieceAt(attack_to2);
186  if (attacked2.isOnBoardByOwner(turn)) {
187  out.push_back(index + 4); // 4,Shadowing;
188  if (! state.hasEffectAt(turn, attack_to2))
189  out.push_back(index + 5); // 5,
190  if (attack_to2.canPromote(alt(turn)))
191  out.push_back(index + 6); // 6,
192  info.attack_shadow[attacked2.number()][piece.owner()] = true;
193  }
194  if (info.threatmate_move.isNormal()) {
195  Square threat_at = info.threatmate_move.to();
196  if (threat_at == attack_to
197  || (! Board_Table.getShortOffsetNotKnight(Offset32(threat_at, attack_to)).zero()
198  && Board_Table.isBetween(threat_at,
199  piece.square(), attack_to)))
200  out.push_back(index + 7); // 7, threatmate block?
201  }
202 }
203 
204 
206 CheckmateIfCapture::hasSafeCapture(NumEffectState& state, Move move)
207 {
208  return ! checkmate::CheckmateIfCapture::effectiveAttack(state, move, 0);
209 }
210 
211 
212 // ;;; Local Variables:
213 // ;;; mode:c++
214 // ;;; c-basic-offset:2
215 // ;;; End: