All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
proofNumberTable.cc
Go to the documentation of this file.
1 /* proofNumberTable.cc
2  */
6 #include "osl/boardTable.h"
7 #include "osl/ptypeTable.h"
8 
9 namespace osl
10 {
11  namespace
12  {
13  using namespace osl::checkmate;
17  const checkmate::ProofNumberTable::Liberty
18  effectiveCheckShort(Ptype ptype,Direction dir,unsigned int mask)
19  {
20  assert(isShort(dir));
21  // 王は8近傍に移動できない
22  if (ptype==KING)
23  return ProofNumberTable::Liberty(0,false);
24  // ptypeがdir方向に利きを持たない場合も空王手の場合があるので作成
25  const bool has_effect
26  = (Ptype_Table.getMoveMask(ptype)
27  & (dirToMask(dir) | dirToMask(shortToLong(dir))));
28  int dx=Board_Table.getDxForBlack(dir);
29  int dy=Board_Table.getDyForBlack(dir);
30  int count = 0;
31  for (int l=0;l<8;l++) {
32  if ((mask&(1<<l))==0)
33  continue;
34  Direction dir1=static_cast<Direction>(l);
35  int dx1=Board_Table.getDxForBlack(dir1);
36  int dy1=Board_Table.getDyForBlack(dir1);
37  Offset32 o32(dx-dx1,dy-dy1);
38  if ((dx != dx1 || dy != dy1)
39  && !Ptype_Table.getEffect(newPtypeO(BLACK,ptype),o32).hasEffect())
40  ++count;
41  }
42  return ProofNumberTable::Liberty(std::max(count,1), has_effect);
43  }
44  const checkmate::ProofNumberTable::Liberty
45  effectiveCheckLong(Ptype ptype,Direction dir,unsigned int mask)
46  {
47  assert(isLong(dir));
48  // ptypeがdir方向に利きを持たなくても2マス離れた空王手で8近傍に
49  // 利きが増える場合があるので作成
50  const bool has_effect
51  = (Ptype_Table.getMoveMask(ptype) & dirToMask(dir));
52  int dx=Board_Table.getDxForBlack(dir)*2; // 1マス遠くから
53  int dy=Board_Table.getDyForBlack(dir)*2;
54  int count = 0;
55  for (int l=0;l<8;l++) {
56  if ((mask&(1<<l))==0)
57  continue;
58  Direction dir1=static_cast<Direction>(l);
59  int dx1=Board_Table.getDxForBlack(dir1);
60  int dy1=Board_Table.getDyForBlack(dir1);
61  Offset32 o32(dx-dx1,dy-dy1);
62  if (!Ptype_Table.getEffect(newPtypeO(BLACK,ptype),o32).hasEffect())
63  ++count;
64  }
65  return ProofNumberTable::Liberty(std::max(count,1), has_effect);
66  }
67  }
68 }
69 
72 {
73 }
74 
77  : table(new Table())
78 {
79  // liberties
80  for (int i=0; i<0x100; i++) {
81  for (int k=PTYPE_PIECE_MIN; k<=PTYPE_MAX; k++) {
82  const Ptype ptype=static_cast<Ptype>(k);
83  assert(isPiece(ptype));
84  for (int j=0; j<8; j++) {
85  Direction dir=static_cast<Direction>(j);
86  const Liberty e = effectiveCheckShort(ptype,dir,i);
87  table->liberties[i][k][j] = e;
88  }
89  int longs = 0;
90  for (int j=LONG_DIRECTION_MIN; j<=LONG_DIRECTION_MAX; ++j,++longs) {
91  Direction dir=static_cast<Direction>(j);
92  const Liberty e = effectiveCheckLong(ptype,dir,i);
93  table->liberties[i][k][j] = e;
94  }
95  assert(longs == 8);
96  }
97  }
98  // drop_liberty
99  table->drop_liberty.fill(0);
100  for(int i=0;i<0x10000;i++){
101  const unsigned int liberty = (i>>8)&0xff;
102  const int liberty_count = misc::BitOp::countBit(liberty);
103  if (liberty_count <= 2)
104  continue; // low enough
105 
106  for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
107  int minimum_liberty = liberty_count;
108  Ptype ptype=static_cast<Ptype>(k);
109  if (ptype == KING)
110  continue;
111  for (int j=0;j<8;j++) {
112  // 有効王手でない
113  if ((i&(0x1<<j))==0)
114  continue;
115  if ((i&(0x100<<j))!=0)
116  continue;
117  const Direction dir=static_cast<Direction>(j);
118  // ptypeがdir方向に利きを持つか
119  const bool has_effect
120  = (Ptype_Table.getMoveMask(ptype)
121  & (dirToMask(dir) | dirToMask(shortToLong(dir))));
122  if (! has_effect)
123  continue;
124  const int e = table->liberties[liberty][k][j].liberty;
125  assert(e);
126  minimum_liberty = std::min(minimum_liberty, e);
127  }
128  for (int l=minimum_liberty; l<liberty_count; ++l)
129  {
130  table->drop_liberty[i][l] |= (1<<(ptype-GOLD));
131  }
132  }
133  }
134  // pmajor_liberty
135  table->pmajor_liberty.fill(8);
136  for (int l=0; l<0x100; l++) { // liberty
137  for (int m=0; m<0x100; m++) { // move_mask
138  if (l & m)
139  continue;
140  int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
141  if (min_liberty > 1)
142  {
143  for (int j=0; j<8; j++) {
144  if ((m&(0x1<<j))==0)
145  continue;
146  const int pr = table->liberties[l][PROOK][j].liberty;
147  const int pb = table->liberties[l][PBISHOP][j].liberty;
148  min_liberty = std::min(min_liberty, std::min(pr,pb));
149  assert(min_liberty);
150  }
151  }
152  table->pmajor_liberty[l][m] = min_liberty;
153  }
154  }
155  // promote_liberty
156  table->promote_liberty.fill(8);
157  for (int l=0; l<0x100; l++) { // liberty
158  for (int m=0; m<0x100; m++) { // move_mask
159  if (l & m)
160  continue;
161  int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
162  if (min_liberty > 1)
163  {
164  for (int j=0; j<8; j++) {
165  if ((m&(0x1<<j))==0)
166  continue;
167  for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
168  Ptype ptype=static_cast<Ptype>(k);
169  if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
170  continue;
171  Liberty e = table->liberties[l][k][j];
172  if (! e.has_effect)
173  continue;
174  assert(e.liberty);
175  min_liberty = std::min(min_liberty, (int)e.liberty);
176  assert(min_liberty);
177  }
178  }
179  }
180  table->promote_liberty[l][m] = min_liberty;
181  }
182  }
183  // other_move_liberty
184  table->other_move_liberty.fill(8);
185  for (int l=0; l<0x100; l++) { // liberty
186  for (int m=0; m<0x100; m++) { // move_mask
187  if (l & m)
188  continue;
189  int min_liberty = std::max(2,misc::BitOp::countBit(l))-1;
190  if (min_liberty > 1)
191  {
192  for (int j=0; j<8; j++) {
193  if ((m&(0x1<<j))==0)
194  continue;
195  for (int k=PTYPE_BASIC_MIN;k<=PTYPE_MAX;k++) {
196  Ptype ptype=static_cast<Ptype>(k);
197  if (ptype == KING || ptype == PROOK || ptype == PBISHOP)
198  continue;
199  if (j == U
200  && (ptype == GOLD || ptype == PPAWN || ptype == PLANCE
201  || ptype == PKNIGHT || ptype == PSILVER))
202  continue;
203  Liberty e = table->liberties[l][k][j];
204  if (! e.has_effect)
205  continue;
206  assert(e.liberty);
207  min_liberty = std::min(min_liberty, (int)e.liberty);
208  assert(min_liberty);
209  }
210  }
211  }
212  table->other_move_liberty[l][m] = min_liberty;
213  }
214  }
215 }
216 
218 ProofNumberTable::countLiberty(const NumEffectState& state, Move move) const
219 {
220  const Player attack = move.player();
221  const Square king = state.kingSquare(alt(attack));
222  const King8Info info(state.Iking8Info(alt(attack)));
223  return countLiberty(state, info.libertyCount(), move, king, info);
224 }
225 
227 ProofNumberTable::libertyAfterAllDrop(const NumEffectState& state, Player attack,
228  King8Info info) const
229 {
230  assert(state.turn() == attack);
231  int result = info.libertyCount()-1;
232  if (result < 2)
233  return 1;
234  const unsigned int ld_mask = info.libertyDropMask();
235  uint8_t ptype_mask = 0;
236  for (int p=GOLD; p<=ROOK; ++p)
237  ptype_mask |= state.hasPieceOnStand(attack, static_cast<Ptype>(p)) << (p-GOLD);
238  for (;
239  result > 1
240  && (ptype_mask & table->drop_liberty[ld_mask][result-1]);
241  --result)
242  {
243  }
244  return result;
245 }
246 
248 ProofNumberTable::libertyAfterAllDrop(const NumEffectState& state) const
249 {
250  const Player attack = state.turn();
251  const King8Info info(state.Iking8Info(alt(attack)));
252  return libertyAfterAllDrop(state, attack, info);
253 }
254 
256 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state,
257  Player attack,
258  King8Info info, Square king) const
259 {
260  bool has_pmajor = false;
261  {
262  for (int i = PtypeTraits<BISHOP>::indexMin;
263  i < PtypeTraits<ROOK>::indexLimit; i++)
264  {
265  // move maskを見て8マス調べる方が良いか?
266  const Piece p = state.pieceOf(i);
267  assert(isMajor(p.ptype()));
268  if (! p.isOnBoardByOwner(attack))
269  continue;
270  if (king.squareForBlack(attack).y() > 3 // 1段おまけ
271  && ! isPromoted(p.ptype()))
272  {
273  if (! p.square().canPromote(attack))
274  continue;
275  }
276  if (Neighboring8Direct::hasEffect(state, p.ptypeO(), p.square(),
277  king))
278  {
279  // 本当はそこにbitが立っているかを判定したい.
280  has_pmajor = true;
281  break;
282  }
283  }
284  }
285  int moveCandidate;
286  if(attack==BLACK)
287  moveCandidate = info.moveCandidateMask<BLACK>(state);
288  else
289  moveCandidate = info.moveCandidateMask<WHITE>(state);
290  if (has_pmajor)
291  {
292  int result = table->pmajor_liberty[info.liberty()][moveCandidate];
293  assert(result);
294  return result;
295  }
296  bool promoted_area = king.squareForBlack(attack).y() < 3;
297  if (! promoted_area)
298  {
299  const Square u = king + Board_Table.getOffset(alt(attack), U);
300  promoted_area = state.hasEffectByPtype<GOLD>(attack, u);
301  }
302  if (promoted_area)
303  {
304  int result = table->promote_liberty[info.liberty()][moveCandidate];
305  assert(result);
306  return result;
307  }
308  int result = table->other_move_liberty[info.liberty()][moveCandidate];
309  assert(result);
310  return result;
311 }
312 
314 ProofNumberTable::libertyAfterAllMove(const NumEffectState& state) const
315 {
316  const Player attack = state.turn();
317  const Square king = state.kingSquare(alt(attack));
318  const King8Info info(state.Iking8Info(alt(attack)));
319  return libertyAfterAllMove(state, attack, info, king);
320 }
321 
323 ProofNumberTable::disproofAfterAllCheck(const NumEffectState& state,
324  Player attack,
325  King8Info info) const
326 {
327  int num_checks;
328  num_checks=info.countMoveCandidate(attack,state);
329  int drop_scale = state.hasPieceOnStand<GOLD>(attack)
330  + state.hasPieceOnStand<SILVER>(attack);
331  if (drop_scale)
332  num_checks += misc::BitOp::countBit(info.dropCandidate()) * drop_scale;
333  return std::max(1, num_checks);
334 }
335 
337 ProofNumberTable::attackEstimation(const NumEffectState& state,
338  Player attack,
339  King8Info info, Square king) const
340 {
341  int p = libertyAfterAllDrop(state, attack, info);
342  if (p >= 2)
343  {
344  p = std::min(p, libertyAfterAllMove(state, attack, info, king));
345  }
346  return ProofDisproof(p, disproofAfterAllCheck(state, attack, info));
347 }
348 
350 ProofNumberTable::attackEstimation(const NumEffectState& state) const
351 {
352  const Player attack = state.turn();
353  const Square king = state.kingSquare(alt(attack));
354  const King8Info info(state.Iking8Info(alt(attack)));
355  return attackEstimation(state, attack, info, king);
356 }
357 
359  ProofNumberTable::libertyAfterAllCheck(const NumEffectState& state) const
360 {
361  return attackEstimation(state).proof();
362 }
363 
364 /* ------------------------------------------------------------------------- */
365 // ;;; Local Variables:
366 // ;;; mode:c++
367 // ;;; c-basic-offset:2
368 // ;;; End:
369 
370