All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
checkmateIfCapture.cc
Go to the documentation of this file.
1 /* checkmateIfCapture.cc
2  */
10 #include "osl/move_action/store.h"
13 #include "osl/neighboring8.h"
14 
16 {
17  NumEffectState *state;
18  int depth;
19  bool result;
20  void operator()(Square last_to)
21  {
22  result = cannotCapture(*state, last_to, depth);
23  }
24 };
25 
27 CheckmateIfCapture::effectiveAttackCandidate0(const NumEffectState& state, Move move)
28 {
29  using namespace move_classifier;
30  // depth 0 専用の枝刈
31  const Player attacker = state.turn();
32  const Player defender = alt(attacker);
33  const Square king = state.kingSquare(defender);
34  PieceMask pieces = state.effectSetAt(move.to())
35  & state.piecesOnBoard(defender);
36  if (pieces.none())
37  return false;
38  if (Neighboring8::isNeighboring8(move.to(), king))
39  return true;
40  const Piece captured = state.pieceOnBoard(move.to());
41  if (move.isCapture()) {
42  if (Neighboring8Direct::hasEffect(state, captured.ptypeO(),
43  move.to(), king))
44  return true;
45  }
46  if (! move.isDrop()
47  && (state.longEffectAt(move.from(), attacker).any() // todo: refinement 開き王手pinとか8近傍くらい?
48  || (Neighboring8::isNeighboring8(move.from(), king)
49  && state.hasEffectAt(attacker, move.from()))))
50  return true;
51 
52  const King8Info info = state.king8Info(defender);
53  const CArray<Square,2> knight_position = {{
54  Board_Table.nextSquare(defender, king, UUR),
55  Board_Table.nextSquare(defender, king, UUL)
56  }};
57  if (state.inCheck()
58  && (info.dropCandidate() || info.moveCandidate2()
59  || /* only when has knight or knight effect */info.liberty() == 0))
60  return true;
61  if (move.isCapture()) {
62  if (info.dropCandidate())
63  return true;
64  if (info.liberty() == 0) {
65  for (int i=0; i<2; ++i) {
66  const Square kp = knight_position[i];
67  const Piece kpp = state.pieceAt(kp);
68  if (kpp.isEdge() || state.hasEffectNotBy(defender, captured, kp))
69  continue;
70  if (kpp.isEmpty()
71  && unpromote(move.capturePtype()) == KNIGHT)
72  return true;
73  if (state.hasEffectByPiece(captured, kp)
74  && (unpromote(move.capturePtype()) == KNIGHT
75  || state.hasPieceOnStand<KNIGHT>(attacker)
76  || state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp)))
77  return true;
78  }
79  }
80  } else if (info.liberty() == 0 && state.hasPieceOnStand<KNIGHT>(attacker)) {
81  for (int i=0; i<2; ++i) {
82  const Square kp = knight_position[i];
83  const Piece kpp = state.pieceAt(kp);
84  if (! kpp.isOnBoardByOwner(defender))
85  continue;
86  if (state.hasEffectByPiece(kpp, move.to()))
87  return true;
88  }
89  }
90  // テストでは出てこないが焦点もあるか?
91  while (pieces.any())
92  {
93  const Piece p=state.pieceOf(pieces.takeOneBit());
94  if (Neighboring8Direct::hasEffectOrAdditional(state, p.ptypeO(), p.square(), king)
95  || Neighboring8::isNeighboring8(p.square(), king))
96  continue; // i.e., need analyses
97  if (state.longEffectAt(p.square(), attacker).any()) // todo: refinement
98  continue;
99  if (info.liberty() == 0) {
100  int i=0;
101  for (; i<2; ++i) {
102  const Square kp = knight_position[i];
103  const Piece kpp = state.pieceAt(kp);
104  if (kpp.isEdge() || state.hasEffectNotBy(defender, p, kp))
105  continue;
106  if (p.square() == kp
107  && state.hasPieceOnStand<KNIGHT>(attacker))
108  break;
109  if (state.countEffect(defender, kp) == 1)
110  if ((kpp.canMoveOn(attacker)
111  && state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp))
112  || (kpp.isEmpty()
113  && state.hasPieceOnStand<KNIGHT>(attacker)))
114  break;
115  }
116  if (i<2)
117  continue;
118  }
119  // now we have safe takeback
120  return false;
121  }
122  return true;
123 }
124 
125 bool osl::checkmate::
126 CheckmateIfCapture::effectiveAttack(NumEffectState& state, Move move, int depth)
127 {
128  assert(move.player() == state.turn());
129  CallDefense defense = { &state, depth, false };
130  state.makeUnmakeMove(move, defense);
131 #ifdef OSL_DEBUG
132  if (defense.result && ! effectiveAttackCandidate0(state, move))
133  std::cerr << state << move << "\n", assert(0);
134 #endif
135  return defense.result;
136 }
137 
138 bool osl::checkmate::
139 CheckmateIfCapture::cannotCapture(NumEffectState& state,
140  Square last_to, int depth)
141 {
142  if (state.inCheck(alt(state.turn())))
143  return false; // 前の手が自殺
144 
145  using namespace move_generator;
146  using namespace move_action;
147  MoveVector moves; // may contain unsafe move
148  GenerateCapture::generate(state, last_to, moves);
149 
150  if (moves.empty())
151  return false;
152 
153  FixedDepthSearcher searcher(state);
154  const Square king = state.kingSquare(state.turn());
155  for (MoveVector::const_iterator p=moves.begin(); p!=moves.end(); ++p)
156  {
157  if (state.inCheck()) {
158  if (state.countEffect(alt(state.turn()), king) > 1
159  || ! state.hasEffectByPiece(state.pieceOnBoard(last_to), king))
160  if (p->ptype() != KING)
161  continue;
162  }
163  const bool checkmate
164  = searcher.hasEscapeByMoveOfTurn(*p, depth).isCheckmateSuccess();
165  if (! checkmate)
166  return false;
167  }
168 
169  return true;
170 }
171 
172 /* ------------------------------------------------------------------------- */
173 // ;;; Local Variables:
174 // ;;; mode:c++
175 // ;;; c-basic-offset:2
176 // ;;; End: