proofNumberTable.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
proofNumberTable.cc
Go to the documentation of this file.
1 /* proofNumberTable.cc
2 */
3 #include "osl/checkmate/proofNumberTable.h"
4 #include "osl/checkmate/immediateCheckmate.h"
5 #include "osl/effect_util/neighboring8Direct.h"
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
70 osl::checkmate::
71 ProofNumberTable::Table::Table()
72 {
73 }
74
75 osl::checkmate::
76 ProofNumberTable::ProofNumberTable()
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
217 int osl::checkmate::
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
226 int osl::checkmate::
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
247 int osl::checkmate::
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
255 int osl::checkmate::
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
313 int osl::checkmate::
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
322 int osl::checkmate::
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
336 const osl::checkmate::ProofDisproof osl::checkmate::
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
349 const osl::checkmate::ProofDisproof osl::checkmate::
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
358 int osl::checkmate::
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