void MovePicker::score() { static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); for (auto& m : *this) if (Type == CAPTURES) { #ifdef ATOMIC if (pos.is_atomic()) m.value = pos.see<ATOMIC_VARIANT>(m); else #endif #ifdef RACE if (pos.is_race()) m.value = PieceValue[pos.variant()][MG][pos.piece_on(to_sq(m))] - Value(200 * relative_rank(BLACK, to_sq(m))) + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))] / 8; else #endif m.value = PieceValue[pos.variant()][MG][pos.piece_on(to_sq(m))] + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))] / 8; } else if (Type == QUIETS) { m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]; #ifdef ANTI if (pos.is_anti() && pos.attackers_to(to_sq(m), pos.pieces() ^ from_sq(m)) & pos.pieces(~pos.side_to_move())) { m.value += (1 << 28); if (!(pos.attackers_to(from_sq(m)) & pos.pieces(~pos.side_to_move()))) m.value += (1 << 27); } #endif } else // Type == EVASIONS { if (pos.capture(m)) m.value = PieceValue[pos.variant()][MG][pos.piece_on(to_sq(m))] - Value(type_of(pos.moved_piece(m))); else m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] - (1 << 28); } }
bool move_is_check(const Position& pos, Move move) { Color us = pos.side_to_move(); Square from = from_sq(move); Square to = to_sq(move); Square ksq = pos.king_square(~us); PieceType pfr = type_of(pos.piece_on(from)); PieceType pto = type_of(pos.piece_on(to)); Bitboard pawns = pos.pieces(us, PAWN); Bitboard knights = pos.pieces(us, KNIGHT); Bitboard cannons = pos.pieces(us, CANNON); Bitboard rooks = pos.pieces(us, ROOK); Bitboard occ = pos.pieces(); Bitboard occl90 = pos.piecesl90(); occ ^= from; occl90 ^= square_rotate_l90_bb(from); if (pto == NO_PIECE_TYPE) { occ ^= to; occl90 ^= square_rotate_l90_bb(to); } switch (pfr) { case ROOK: rooks ^= from; rooks ^= to; break; case CANNON: cannons ^= from; cannons ^= to; break; case KNIGHT: knights ^= from; knights ^= to; break; case PAWN: pawns ^= from; pawns ^= to; break; default:break; } if((PseudoAttacks[ROOK][ksq]& cannons) &&(cannon_control_bb(ksq, occ,occl90) & cannons)) return true; if((PseudoAttacks[ROOK][ksq]& rooks) && (rook_attacks_bb(ksq,occ,occl90)& rooks) ) return true; if( knight_attackers_to_bb(ksq, knights, occ) ) return true; if( pos.attacks_from_pawn_nomask(ksq, ~us) & pawns ) return true; return false; }
MoveStack* generate<LEGAL>(const Position& pos, MoveStack* mlist) { MoveStack *end, *cur = mlist; Bitboard pinned = pos.pinned_pieces(); Square ksq = pos.king_square(pos.side_to_move()); end = pos.checkers() ? generate<EVASIONS>(pos, mlist) : generate<NON_EVASIONS>(pos, mlist); while (cur != end) if ( (pinned || from_sq(cur->move) == ksq || type_of(cur->move) == ENPASSANT) && !pos.pl_move_is_legal(cur->move, pinned)) cur->move = (--end)->move; else cur++; return end; }
ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) { Bitboard pinned = pos.pinned_pieces(pos.side_to_move()); Square ksq = pos.square<KING>(pos.side_to_move()); ExtMove* cur = moveList; moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList) : generate<NON_EVASIONS>(pos, moveList); while (cur != moveList) if ( (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT) && !pos.legal(*cur, pinned)) *cur = (--moveList)->move; else ++cur; return moveList; }
// A PolyGlot book move is encoded as follows: // // bit 0- 5: destination square (from 0 to 63) // bit 6-11: origin square (from 0 to 63) // bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4) // // Castling moves follow "king captures rook" representation. So in case book // move is a promotion we have to convert to our representation, in all the // other cases we can directly compare with a Move after having masked out // the special Move's flags (bit 14-15) that are not supported by PolyGlot. // // SF: // bit 0- 5: destination square (from 0 to 63) // bit 6-11: origin square (from 0 to 63) // bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2) // bit 14-15: special move flag: promotion (1), en passant (2), castling (3) static Move pg_move_to_sf_move(const Pos *pos, uint16_t pg_move) { Move move = (Move)pg_move; int pt = (move >> 12) & 7; if (pt) return make_promotion(from_sq(move), to_sq(move), pt + 1); // Add 'special move' flags and verify it is legal ExtMove *m = (pos->st-1)->endMoves; ExtMove *end = generate_legal(pos, m); for (; m < end; m++) if (move == (m->move & (~(3 << 14)))) // Compare with MoveType (bit 14-15) masked out return m->move; return 0; }
bool move_is_legal(const Position& pos, Move move) { Move m = move; assert(is_ok(m)); Color us = pos.side_to_move(); Square from = from_sq(m); Square to = to_sq(m); assert(color_of(pos.piece_moved(m)) == us); assert(pos.piece_on(pos.king_square(us)) == make_piece(us, KING)); PieceType pfr = type_of(pos.piece_on(from)); PieceType pto= type_of(pos.piece_on(to)); Bitboard pawns = pos.pieces(~us, PAWN); Bitboard knights = pos.pieces(~us, KNIGHT); Bitboard cannons = pos.pieces(~us, CANNON); Bitboard rooks = pos.pieces(~us, ROOK); Bitboard occ = pos.pieces(); Bitboard occl90 = pos.piecesl90(); occl90 ^= square_rotate_l90_bb(from); occ ^= from; if(pto == NO_PIECE_TYPE) { occl90 ^= square_rotate_l90_bb(to); occ ^= to; } Square ksq = pos.king_square(us); if(ksq == from) ksq = to; if (pto != NO_PIECE_TYPE) { switch(pto) { case PAWN: pawns ^= to; break; case KNIGHT: knights ^= to; break; case ROOK: rooks ^= to; break; case CANNON: cannons ^= to; break; } } if((PseudoAttacks[ROOK][ksq]& cannons) &&(cannon_control_bb(ksq, occ,occl90) & cannons)) return false; if((PseudoAttacks[ROOK][ksq]& rooks) && (rook_attacks_bb(ksq,occ,occl90)& rooks) ) return false; if( knight_attackers_to_bb(ksq, knights, occ) ) return false; if( pos.attacks_from_pawn_nomask(ksq, us) & pawns ) return false; if((PseudoAttacks[ROOK][ksq]& pos.king_square(~us)) && (rook_attacks_bb(ksq,occ,occl90)& pos.king_square(~us))) return false;//╤таЁ return true; }
// 利きのある場所への取れない近接王手からの3手詰め Move Position::weak_mate_n_ply(int ply) const { // 1手詰めであるならこれを返す Move m = mate1ply(); if (m) return m; // 詰まない if (ply <= 1) return MOVE_NONE; Color us = side_to_move(); Color them = ~us; Bitboard around8 = kingEffect(king_square(them)); // const剥がし Position* This = ((Position*)this); StateInfo si; StateInfo si2; // 近接王手で味方の利きがあり、敵の利きのない場所を探す。 for (auto m : MoveList<CHECKS>(*this)) { // 近接王手で、この指し手による駒の移動先に敵の駒がない。 Square to = to_sq(m); if ((around8 & to) #ifndef LONG_EFFECT_LIBRARY // toに利きがあるかどうか。mが移動の指し手の場合、mの元の利きを取り除く必要がある。 && (is_drop(m) ? effected_to(us, to) : (attackers_to(us, to, pieces() ^ from_sq(m)) ^ from_sq(m))) // 敵玉の利きは必ずtoにあるのでそれを除いた利きがあるかどうか。 && (attackers_to(them,to,pieces()) ^ king_square(them)) #else && (is_drop(m) ? effected_to(us, to) : board_effect[us].effect(to) >= 2 || (long_effect.directions_of(us, from_sq(m)) & Effect8::directions_of(from_sq(m), to)) != 0) // 敵玉の利きがあるので2つ以上なければそれで良い。 && (board_effect[them].effect(to) <= 1) #endif ) { if (!legal(m)) continue; ASSERT_LV3(gives_check(m)); This->do_move(m,si,true); ASSERT_LV3(in_check()); // この局面ですべてのevasionを試す for (auto m2 : MoveList<EVASIONS>(*this)) { if (!legal(m2)) continue; // この指し手で逆王手になるなら、不詰めとして扱う if (gives_check(m2)) goto NEXT_CHECK; This->do_move(m2, si2, false); ASSERT_LV3(!in_check()); if (!weak_mate_n_ply(ply-2)) { // 詰んでないので、m2で詰みを逃れている。 This->undo_move(m2); goto NEXT_CHECK; } This->undo_move(m2); } // すべて詰んだ This->undo_move(m); // mによって3手で詰む。 return m; NEXT_CHECK:; This->undo_move(m); } } return MOVE_NONE; }