My Project
checkmateIfCapture.cc
Go to the documentation of this file.
1 /* checkmateIfCapture.cc
2  */
8 
10 {
12  int depth;
13  bool result;
14  void operator()(Square last_to)
15  {
16  result = cannotCapture(*state, last_to, depth);
17  }
18 };
19 
22 {
23  using namespace move_classifier;
24  // depth 0 専用の枝刈
25  const Player attacker = state.turn();
26  const Player defender = alt(attacker);
27  const Square king = state.kingSquare(defender);
28  PieceMask pieces = state.effectSetAt(move.to())
29  & state.piecesOnBoard(defender);
30  if (pieces.none())
31  return false;
32  if (move.to().isNeighboring8(king))
33  return true;
34  const Piece captured = state.pieceOnBoard(move.to());
35  if (move.isCapture()) {
36  if (Neighboring8Direct::hasEffect(state, captured.ptypeO(),
37  move.to(), king))
38  return true;
39  }
40  if (! move.isDrop()
41  && (state.longEffectAt(move.from(), attacker).any() // todo: refinement 開き王手pinとか8近傍くらい?
42  || (move.from().isNeighboring8(king)
43  && state.hasEffectAt(attacker, move.from()))))
44  return true;
45 
46  const King8Info info = state.king8Info(defender);
47  const CArray<Square,2> knight_position = {{
48  Board_Table.nextSquare(defender, king, UUR),
49  Board_Table.nextSquare(defender, king, UUL)
50  }};
51  if (state.inCheck()
52  && (info.dropCandidate() || info.moveCandidate2()
53  || /* only when has knight or knight effect */info.liberty() == 0))
54  return true;
55  if (move.isCapture()) {
56  if (info.dropCandidate())
57  return true;
58  if (info.liberty() == 0) {
59  for (int i=0; i<2; ++i) {
60  const Square kp = knight_position[i];
61  const Piece kpp = state.pieceAt(kp);
62  if (kpp.isEdge() || state.hasEffectNotBy(defender, captured, kp))
63  continue;
64  if (kpp.isEmpty()
65  && unpromote(move.capturePtype()) == KNIGHT)
66  return true;
67  if (state.hasEffectByPiece(captured, kp)
68  && (unpromote(move.capturePtype()) == KNIGHT
69  || state.hasPieceOnStand<KNIGHT>(attacker)
70  || state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp)))
71  return true;
72  }
73  }
74  } else if (info.liberty() == 0 && state.hasPieceOnStand<KNIGHT>(attacker)) {
75  for (int i=0; i<2; ++i) {
76  const Square kp = knight_position[i];
77  const Piece kpp = state.pieceAt(kp);
78  if (! kpp.isOnBoardByOwner(defender))
79  continue;
80  if (state.hasEffectByPiece(kpp, move.to()))
81  return true;
82  }
83  }
84  // テストでは出てこないが焦点もあるか?
85  while (pieces.any())
86  {
87  const Piece p=state.pieceOf(pieces.takeOneBit());
88  if (Neighboring8Direct::hasEffectOrAdditional(state, p.ptypeO(), p.square(), king)
89  || p.square().isNeighboring8(king))
90  continue; // i.e., need analyses
91  if (state.longEffectAt(p.square(), attacker).any()) // todo: refinement
92  continue;
93  if (info.liberty() == 0) {
94  int i=0;
95  for (; i<2; ++i) {
96  const Square kp = knight_position[i];
97  const Piece kpp = state.pieceAt(kp);
98  if (kpp.isEdge() || state.hasEffectNotBy(defender, p, kp))
99  continue;
100  if (p.square() == kp
101  && state.hasPieceOnStand<KNIGHT>(attacker))
102  break;
103  if (state.countEffect(defender, kp) == 1)
104  if ((kpp.canMoveOn(attacker)
105  && state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp))
106  || (kpp.isEmpty()
107  && state.hasPieceOnStand<KNIGHT>(attacker)))
108  break;
109  }
110  if (i<2)
111  continue;
112  }
113  // now we have safe takeback
114  return false;
115  }
116  return true;
117 }
118 
121 {
122  assert(move.player() == state.turn());
123  CallDefense defense = { &state, depth, false };
124  state.makeUnmakeMove(move, defense);
125 #ifdef OSL_DEBUG
126  if (defense.result && ! effectiveAttackCandidate0(state, move))
127  std::cerr << state << move << "\n", assert(0);
128 #endif
129  return defense.result;
130 }
131 
134  Square last_to, int depth)
135 {
136  if (state.inCheck(alt(state.turn())))
137  return false; // 前の手が自殺
138 
139  using namespace move_generator;
140  using namespace move_action;
141  MoveVector moves; // may contain unsafe move
142  GenerateCapture::generate(state, last_to, moves);
143 
144  if (moves.empty())
145  return false;
146 
147  FixedDepthSearcher searcher(state);
148  const Square king = state.kingSquare(state.turn());
149  for (MoveVector::const_iterator p=moves.begin(); p!=moves.end(); ++p)
150  {
151  if (state.inCheck()) {
152  if (state.countEffect(alt(state.turn()), king) > 1
153  || ! state.hasEffectByPiece(state.pieceOnBoard(last_to), king))
154  if (p->ptype() != KING)
155  continue;
156  }
157  const bool checkmate
158  = searcher.hasEscapeByMoveOfTurn(*p, depth).isCheckmateSuccess();
159  if (! checkmate)
160  return false;
161  }
162 
163  return true;
164 }
165 
166 /* ------------------------------------------------------------------------- */
167 // ;;; Local Variables:
168 // ;;; mode:c++
169 // ;;; c-basic-offset:2
170 // ;;; End:
const Square nextSquare(Player P, Square pos, Direction dr) const
next position from pos for player P.
Definition: boardTable.h:61
圧縮していない moveの表現 .
Definition: basic_type.h:1052
Player player() const
Definition: basic_type.h:1195
bool isDrop() const
Definition: basic_type.h:1150
Ptype capturePtype() const
Definition: basic_type.h:1180
bool isCapture() const
Definition: basic_type.h:1148
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 checkmate::King8Info king8Info(Player king) const
bool hasEffectNotBy(Player player, Piece piece, Square target) const
対象とするマスにあるプレイヤーの(ただしある駒以外)利きがあるかどうか.
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
対象とするマスにあるプレイヤーの利きがあるかどうか.
bool inCheck(Player P) const
Pの玉が王手状態
const mask_t longEffectAt(Square target) const
void makeUnmakeMove(Move move, Function &f)
bool hasEffectByPtypeStrict(Player attack, Square target) const
target に ptype の利きがあるか? 成不成を区別
駒番号のビットセット.
Definition: pieceMask.h:21
bool any() const
Definition: pieceMask.h:57
PtypeO ptypeO() const
Definition: basic_type.h:824
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
bool canMoveOn() const
Player Pの駒が,thisの上に移動できるか? PIECE_EMPTY 0x00008000 BLACK_PIECE 0x000XxxYY X>=2, YY>0 PIECE_EDGE 0xfff1...
Definition: basic_type.h:980
bool isOnBoardByOwner() const
piece がプレイヤーPの持ち物でかつボード上にある駒の場合は true.
Definition: basic_type.h:852
const Piece pieceOnBoard(Square sq) const
Definition: simpleState.h:170
bool hasPieceOnStand(Player player, Ptype ptype) const
Definition: simpleState.h:191
Player turn() const
Definition: simpleState.h:220
const Piece pieceOf(int num) const
Definition: simpleState.h:76
Square kingSquare() const
Definition: simpleState.h:94
const Piece pieceAt(Square sq) const
Definition: simpleState.h:167
bool isNeighboring8(Square to) const
Definition: basic_type.cc:202
深さ固定で,その深さまで depth first searchで読む詰将棋.
const ProofDisproof hasEscapeByMoveOfTurn(Move next_move, int depth)
敵玉の8近傍の状態を表す.
Definition: king8Info.h:29
unsigned int liberty() const
8-15 bit 目を 0-7bitにshiftして返す
Definition: king8Info.h:54
unsigned int moveCandidate2() const
24-31 bit 目を 0-7bitにshiftして返す
Definition: king8Info.h:69
unsigned int dropCandidate() const
0-7 bit 目を返す
Definition: king8Info.h:49
@ KING
Definition: basic_type.h:93
@ KNIGHT
Definition: basic_type.h:97
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に,promote前の型を返す. promoteしていない型の時はそのまま返す
Definition: basic_type.h:157
const BoardTable Board_Table
Definition: tables.cc:95
@ UUR
Definition: basic_type.h:323
@ UUL
Definition: basic_type.h:322
Player
Definition: basic_type.h:8
constexpr Player alt(Player player)
Definition: basic_type.h:13
PtypeO captured(PtypeO ptypeO)
unpromoteすると共に,ownerを反転する.
Definition: basic_type.h:264
static bool cannotCapture(NumEffectState &state, Square last_to, int depth)
手番の側がSquare の駒を取っても詰みがないか.
static bool effectiveAttackCandidate0(const NumEffectState &state, Move move)
depth==0でeffectiveAttackになる可能性がなければfalse
static bool effectiveAttack(NumEffectState &state, Move move, int depth)
move を指した後,alt(move.player())が取ると詰みかどうか.