All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
stateInfo.cc
Go to the documentation of this file.
1 /* stateInfo.cc
2  */
9 #include "osl/hash/hashKey.h"
10 #include "osl/ptypeTraits.h"
11 #include <iostream>
12 
15 {
16  const osl::Player turn = state->turn();
17  threatmate_move = Move();
18  attack_shadow.fill(false); // need everytime
19  pin[BLACK] = state->pin(BLACK);
20  pin[WHITE] = state->pin(WHITE);
21  move_candidate_exists[BLACK] = king8Info(BLACK).hasMoveCandidate<WHITE>(*state);
22  move_candidate_exists[WHITE] = king8Info(WHITE).hasMoveCandidate<BLACK>(*state);
23 
24  checkmate_defender[BLACK] = findCheckmateDefender(*state, BLACK);
25  checkmate_defender[WHITE] = findCheckmateDefender(*state, WHITE);
26 
27  sendoffs.clear();
28  if (state->hasChangedEffects())
29  changed_effects = state->changedEffects(alt(turn));
30  else
31  changed_effects.invalidate();
32  threatened[turn] = state->inCheck(turn)
33  ? state->kingPiece(turn) : state->findThreatenedPiece(turn);
34  threatened[alt(turn)] = state->findThreatenedPiece(alt(turn));
35 
36  {
37  possible_threatmate_ptype
38  = checkmate::Immediate_Checkmate_Table.dropPtypeMask(king8Info(alt(state->turn())));
39  const Square king = state->kingSquare(alt(state->turn()));
40  const CArray<Direction,2> directions = {{ UUL, UUR }};
41  BOOST_FOREACH(Direction d, directions) {
42  Square knight_attack = king - Board_Table.getOffset(state->turn(), d);
43  if (state->pieceAt(knight_attack).isEmpty()
44  && ! state->hasEffectAt(alt(state->turn()), knight_attack)) {
45  possible_threatmate_ptype |= (1<<(KNIGHT-PTYPE_BASIC_MIN));
46  break;
47  }
48  }
49  for (int p=PTYPE_BASIC_MIN; p<=PTYPE_MAX; ++p) {
50  if (possible_threatmate_ptype & (1<<p))
51  if (state->hasPieceOnStand(state->turn(), static_cast<Ptype>(p)))
52  p &= ~(1<<p);
53  }
54  }
55  bookmove.fill(Move());
56 }
57 
60 {
61  copy.copyFrom(*state);
62  const osl::Player turn = state->turn();
63  const Square king = state->kingSquare(alt(turn));
64  effect_util::SendOffSquare::find(turn, *state, king, sendoffs);
65 
66  updatePinnedGenerals(BLACK);
67  updatePinnedGenerals(WHITE);
68 
69  makePinOfLongPieces();
70  for (int d=SHORT8_DIRECTION_MIN; d<=SHORT8_DIRECTION_MAX; ++d) {
71  Piece p = state->pieceAt(state->kingMobilityAbs(alt(turn), (Direction)d));
72  if (p.isOnBoardByOwner(alt(turn)))
73  king8_long_pieces.push_back(p);
74  }
75  BlockLong::updateCache(*this);
76  if (! history->hasLastMove() || !history->lastMove().isNormal()) {
77  last_move_ptype5 = PTYPE_EMPTY;
78  last_add_effect = PieceMask();
79  } else {
80  last_move_ptype5 = unpromote(history->lastMove().ptype());
81  if (last_move_ptype5 == SILVER)
82  last_move_ptype5 = GOLD;
83  else if (last_move_ptype5 == KNIGHT)
84  last_move_ptype5 = LANCE;
85  else if (isMajor(last_move_ptype5))
86  last_move_ptype5 = KNIGHT;
87  last_add_effect = state->effectedMask(alt(turn))
88  & state->effectedChanged(alt(turn));
89  }
90  PatternCommon::updateCache(*this); // depends on attack_shadow, last_add_effect
91  {
92  MoveVector all;
93  static const BookInMemory& book = BookInMemory::instance();
94  book.find(HashKey(*state), all);
95  for (size_t i=0; i<bookmove.size(); ++i)
96  if (all.size() > i)
97  bookmove[i] = all[i];
98  }
99  dirty = false;
100 }
101 
104 {
105  using namespace osl;
106  if (state->inCheck())
107  return;
108  for (int i=0; i<40; ++i) {
109  const Piece p = state->pieceOf(i);
110  if (!p.isOnBoard() || p.ptype() == KING)
111  continue;
112  CArray<mask_t,2> long_effect = {{
113  state->longEffectAt(p.square(), BLACK),
114  state->longEffectAt(p.square(), WHITE),
115  }};
116  if (long_effect[0].none() || long_effect[1].none()) continue;
117  CArray<Piece,2> attack_piece;
118  {
119  attack_piece[0] = state->findLongAttackAt(p, U);
120  attack_piece[1] = state->findLongAttackAt(p, D);
121  if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
122  && attack_piece[0].owner() != attack_piece[1].owner()) {
123  pin_by_opposing_sliders.push_back(p);
124  continue;
125  }
126  }
127  if ((long_effect[0] & mask_t::makeDirect(PtypeFuns<ROOK>::indexMask)).any()
128  && (long_effect[0] & mask_t::makeDirect(PtypeFuns<ROOK>::indexMask)).any())
129  {
130  attack_piece[0] = state->findLongAttackAt(p, L);
131  attack_piece[1] = state->findLongAttackAt(p, R);
132  if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
133  && attack_piece[0].owner() != attack_piece[1].owner()) {
134  pin_by_opposing_sliders.push_back(p);
135  continue;
136  }
137  }
138  if ((long_effect[0] & mask_t::makeDirect(PtypeFuns<BISHOP>::indexMask)).any()
139  && (long_effect[0] & mask_t::makeDirect(PtypeFuns<BISHOP>::indexMask)).any())
140  {
141  attack_piece[0] = state->findLongAttackAt(p, UL);
142  attack_piece[1] = state->findLongAttackAt(p, DR);
143  if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
144  && attack_piece[0].owner() != attack_piece[1].owner()) {
145  pin_by_opposing_sliders.push_back(p);
146  continue;
147  }
148  attack_piece[0] = state->findLongAttackAt(p, UR);
149  attack_piece[1] = state->findLongAttackAt(p, DL);
150  if (attack_piece[0].isPiece() && attack_piece[1].isPiece()
151  && attack_piece[0].owner() != attack_piece[1].owner()) {
152  pin_by_opposing_sliders.push_back(p);
153  continue;
154  }
155  }
156  }
157 }
158 
159 std::pair<osl::Piece,osl::Square> osl::move_probability::
160 StateInfo::findCheckmateDefender(const NumEffectState& state, Player king)
161 {
162  const King8Info king8info = state.king8Info(king);
163  const unsigned int spaces = king8info.spaces();
164  if (spaces == 0 || (spaces & (spaces-1)))
165  return std::make_pair(Piece::EMPTY(), Square());
166  const Square sq = state.kingSquare(king)
168  assert(state.pieceAt(sq).isEmpty());
169  if (state.countEffect(king, sq) != 2 || ! state.hasEffectAt(alt(king), sq))
170  return std::make_pair(Piece::EMPTY(), Square());
171  unsigned int drop_candidate = king8info.libertyDropMask();
172  drop_candidate &= 0xff00;
173  drop_candidate += spaces;
174  mask_t drop_ptype=mask_t::makeDirect
175  (checkmate::Immediate_Checkmate_Table.dropPtypeMaskOf(drop_candidate));
176  while(drop_ptype.any()){
177  Ptype ptype=static_cast<Ptype>(drop_ptype.takeOneBit()+PTYPE_BASIC_MIN);
178  if (state.hasPieceOnStand(alt(king),ptype))
179  return std::make_pair(state.findCheapAttack(king, sq), sq);
180  }
181  return std::make_pair(Piece::EMPTY(), Square());
182 }
183 
186 {
187  exchange_pins[owner].clear();
188  PieceMask attacked = state->piecesOnBoard(owner)
189  & state->effectedMask(owner) & state->effectedMask(alt(owner));
190  while (attacked.any()) {
191  const Piece p = state->pieceOf(attacked.takeOneBit());
192  const int a = state->countEffect(alt(owner), p.square());
193  const int d = state->countEffect(owner, p.square());
194  if (d != a)
195  continue;
196  const Piece attack_p = state->findCheapAttack(alt(owner), p.square());
197  const Piece support = state->findCheapAttack(owner, p.square());
198  if (support.ptype() == PAWN || support.ptype() == LANCE)
199  continue;
200  unsigned int directions = Ptype_Table.getMoveMask(support.ptype());
201  while (directions) {
202  Direction d = static_cast<Direction>(misc::BitOp::bsf(directions));
203  directions &= directions-1;
204  Square target = support.square() + Board_Table.getOffset(owner, d);
205  if (target == p.square())
206  continue;
207  Piece tp = state->pieceAt(target);
208  if (tp.isEmpty() || tp.isOnBoardByOwner(owner)) {
209  assert(state->hasEffectByPiece(support, target));
210  if (state->countEffect(owner, target)
211  <= state->countEffect(alt(owner), target)+1
212  - state->hasEffectByPiece(attack_p, target)
213  && ! state->hasEffectIf(support.ptypeO(), target, p.square()))
214  exchange_pins[owner].push_back
215  (PinnedGeneral(support, p, target));
216  }
217  }
218  }
219 }
220 
222 StateInfo::findShortThreatmate(const NumEffectState& state, Move last_move)
223 {
224  if (state.inCheck())
225  return Move();
226  NumEffectState copy(state);
227  copy.changeTurn();
228  checkmate::FixedDepthSearcher searcher(copy);
229 
230  Move best_move;
231  const ProofDisproof pdp
232  = searcher.hasCheckmateMoveOfTurn(2, best_move);
233  if (pdp.isCheckmateSuccess())
234  return best_move;
235  if (pdp.isFinal())
236  return Move();
237  if (last_move.isNormal() && Neighboring8Direct::hasEffect
238  (state, last_move.ptypeO(), last_move.to(), state.kingSquare(state.turn()))) {
239  const ProofDisproof pdp4
240  = searcher.hasCheckmateMoveOfTurn(4, best_move);
241  if (pdp4.isCheckmateSuccess())
242  return best_move;
243  if (state.hasPieceOnStand<GOLD>(alt(state.turn()))) {
244  const ProofDisproof pdp6
245  = searcher.hasCheckmateMoveOfTurn(6, best_move);
246  if (pdp6.isCheckmateSuccess())
247  return best_move;
248  }
249  }
250  return Move();
251 }
252 
254 {
255  for (int x=1; x<=9; ++x) {
256  for (int y=1; y<=9; ++y) {
257  const Square position(x,y);
258  if (! (l.pattern_cache[position.index()]
259  == r.pattern_cache[position.index()]))
260  return false;
261  }
262  }
263  return HashKey(*l.state) == HashKey(*r.state)
264  && *l.history == *r.history
267  && l.threatened == r.threatened
269  && l.attack_shadow == r.attack_shadow
270  && l.progress16 == r.progress16
273  && l.pin == r.pin && l.threatmate_move == r.threatmate_move
274  && l.sendoffs == r.sendoffs
275  && l.exchange_pins == r.exchange_pins
278  && HashKey(l.copy) == HashKey(r.copy);
279 }
280 
281 // ;;; Local Variables:
282 // ;;; mode:c++
283 // ;;; c-basic-offset:2
284 // ;;; End: