本文整理汇总了C#中Portfish.Position.piece_on方法的典型用法代码示例。如果您正苦于以下问题:C# Position.piece_on方法的具体用法?C# Position.piece_on怎么用?C# Position.piece_on使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Portfish.Position
的用法示例。
在下文中一共展示了Position.piece_on方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: book_key
// book_key() returns the PolyGlot hash key of the given position
private static UInt64 book_key(Position pos)
{
UInt64 key = 0;
Bitboard b = pos.occupied_squares;
while (b != 0)
{
// Piece offset is at 64 * polyPiece where polyPiece is defined as:
// BP = 0, WP = 1, BN = 2, WN = 3, ... BK = 10, WK = 11
Square s = Utils.pop_1st_bit(ref b);
Piece p = pos.piece_on(s);
int polyPiece = 2 * (Utils.type_of(p) - 1) + (Utils.color_of(p) == ColorC.WHITE ? 1 : 0);
key ^= PolyGlotRandoms[ZobPieceOffset + (64 * polyPiece + s)];
}
b = (ulong)pos.can_castle_CR(CastleRightC.ALL_CASTLES);
while (b != 0)
key ^= PolyGlotRandoms[ZobCastleOffset + Utils.pop_1st_bit(ref b)];
if (pos.st.epSquare != SquareC.SQ_NONE)
key ^= PolyGlotRandoms[ZobEnPassantOffset + Utils.file_of(pos.st.epSquare)];
if (pos.sideToMove == ColorC.WHITE)
key ^= PolyGlotRandoms[ZobTurnOffset + 0];
return key;
}
示例2: move_to_san
/// move_to_san() takes a position and a legal Move as input and returns its
/// short algebraic notation representation.
internal static string move_to_san(Position pos, int m)
{
if (m == MoveC.MOVE_NONE)
{
return "(none)";
}
if (m == MoveC.MOVE_NULL)
{
return "(null)";
}
Debug.Assert(pos.move_is_legal(m));
Bitboard others, b;
Color us = pos.sideToMove;
var san = new StringBuilder();
Square from = from_sq(m);
Square to = to_sq(m);
Piece pc = pos.piece_on(from);
PieceType pt = type_of(pc);
if (type_of_move(m) == MoveTypeC.CASTLING)
{
san.Append(to > from ? "O-O" : "O-O-O");
}
else
{
if (pt != PieceTypeC.PAWN)
{
san.Append(PieceToChar[ColorC.WHITE][pt]); // Upper case
// Disambiguation if we have more then one piece of type 'pt' that can
// reach 'to' with a legal move.
others = b = (pos.attacks_from_PS(pc, to) & pos.pieces_PTC(pt, us)) ^ (ulong)from;
while (others != 0)
{
Move move = make_move(pop_lsb(ref b), to);
if (!pos.pl_move_is_legal(move, pos.pinned_pieces()))
{
others ^= (ulong)from_sq(move);
}
}
if (others != 0)
{
if ((others & file_bb_S(from)) == 0)
{
san.Append(file_to_char(file_of(from)));
}
else if ((others & rank_bb_S(from)) == 0)
{
san.Append(rank_to_char(rank_of(from)));
}
else
{
san.Append(square_to_string(from));
}
}
}
else if (pos.is_capture(m))
{
san.Append(file_to_char(file_of(from)));
}
if (pos.is_capture(m))
{
san.Append('x');
}
san.Append(square_to_string(to));
if (type_of_move(m) == MoveTypeC.PROMOTION)
{
san.Append('=');
san.Append(PieceToChar[ColorC.WHITE][promotion_type(m)]);
}
}
var ci = CheckInfoBroker.GetObject();
ci.CreateCheckInfo(pos);
if (pos.move_gives_check(m, ci))
{
var st = new StateInfo();
pos.do_move(m, st);
var mlist = MListBroker.GetObject();
mlist.pos = 0;
Movegen.generate_legal(pos, mlist.moves, ref mlist.pos);
san.Append(mlist.pos > 0 ? "+" : "#");
MListBroker.Free();
pos.undo_move(m);
}
CheckInfoBroker.Free();
return san.ToString();
}
示例3: evaluate_pawns
/// PawnTable::evaluate_pawns() evaluates each pawn of the given color
internal static Score evaluate_pawns(Color Us, Position pos, Bitboard ourPawns, Bitboard theirPawns, PawnEntry e)
{
Color Them = (Us == ColorC.WHITE ? ColorC.BLACK : ColorC.WHITE);
Bitboard b;
Square s;
File f;
Rank r;
bool passed, isolated, doubled, opposed, chain, backward, candidate;
Score value = ScoreC.SCORE_ZERO;
Square[] pl = pos.pieceList[Us][PieceTypeC.PAWN];
int plPos = 0;
// Loop through all pawns of the current color and score each pawn
while ((s = pl[plPos++]) != SquareC.SQ_NONE)
{
Debug.Assert(pos.piece_on(s) == Utils.make_piece(Us, PieceTypeC.PAWN));
f = (s & 7);
r = (s >> 3);
// This file cannot be half open
if (Us == ColorC.WHITE)
{
e.halfOpenFilesWHITE &= ~(1 << f);
}
else
{
e.halfOpenFilesBLACK &= ~(1 << f);
}
// Our rank plus previous one. Used for chain detection
b = Utils.RankBB[r] | Utils.RankBB[Us == ColorC.WHITE ? r - 1 : r + 1];
// Flag the pawn as passed, isolated, doubled or member of a pawn
// chain (but not the backward one).
chain = (ourPawns & Utils.AdjacentFilesBB[f] & b) != 0;
isolated = (ourPawns & Utils.AdjacentFilesBB[f]) == 0;
doubled = (ourPawns & Utils.ForwardBB[Us][s]) != 0;
opposed = (theirPawns & Utils.ForwardBB[Us][s]) != 0;
passed = (theirPawns & Utils.PassedPawnMask[Us][s]) == 0;
// Test for backward pawn
backward = false;
// If the pawn is passed, isolated, or member of a pawn chain it cannot
// be backward. If there are friendly pawns behind on adjacent files
// or if can capture an enemy pawn it cannot be backward either.
if (!(passed | isolated | chain)
&& (((ourPawns & Utils.AttackSpanMask[Them][s])) == 0)
&& ((((Utils.StepAttacksBB[((Us << 3) | PieceTypeC.PAWN)][s]) & theirPawns)) == 0))
{
// We now know that there are no friendly pawns beside or behind this
// pawn on adjacent files. We now check whether the pawn is
// backward by looking in the forward direction on the adjacent
// files, and seeing whether we meet a friendly or an enemy pawn first.
b = Utils.StepAttacksBB[((Us << 3) | PieceTypeC.PAWN)][s];
// Note that we are sure to find something because pawn is not passed
// nor isolated, so loop is potentially infinite, but it isn't.
while ((b & (ourPawns | theirPawns)) == 0)
{
if (Us == ColorC.WHITE) { b <<= 8; } else { b >>= 8; }
}
// The friendly pawn needs to be at least two ranks closer than the
// enemy pawn in order to help the potentially backward pawn advance.
backward = (((b | (Us == ColorC.WHITE ? b << 8 : b >> 8)) & theirPawns) != 0);
}
Debug.Assert(opposed | passed | (((Utils.AttackSpanMask[Us][s] & theirPawns)) != 0));
// A not passed pawn is a candidate to become passed if it is free to
// advance and if the number of friendly pawns beside or behind this
// pawn on adjacent files is higher or equal than the number of
// enemy pawns in the forward direction on the adjacent files.
candidate = !(opposed | passed | backward | isolated)
&& (b = Utils.AttackSpanMask[Them][s + (Us == ColorC.WHITE ? SquareC.DELTA_N : SquareC.DELTA_S)] & ourPawns) != 0
&& Bitcount.popcount_1s_Max15(b) >= Bitcount.popcount_1s_Max15(Utils.AttackSpanMask[Us][s] & theirPawns);
// Passed pawns will be properly scored in evaluation because we need
// full attack info to evaluate passed pawns. Only the frontmost passed
// pawn on each file is considered a true passed pawn.
if (passed && !doubled)
{
if (Us == ColorC.WHITE)
{
e.passedPawnsWHITE |= Utils.SquareBB[s];
}
else
{
e.passedPawnsBLACK |= Utils.SquareBB[s];
}
}
// Score this pawn
if (isolated)
value -= IsolatedPawnPenalty[opposed ? 1 : 0][f];
//.........这里部分代码省略.........
示例4: connected_threat
// connected_threat() tests whether it is safe to forward prune a move or if
// is somehow connected to the threat move returned by null search.
static bool connected_threat(Position pos, Move m, Move threat)
{
Debug.Assert(Utils.is_ok_M(m));
Debug.Assert(Utils.is_ok_M(threat));
Debug.Assert(!pos.is_capture_or_promotion(m));
Debug.Assert(!pos.is_passed_pawn_push(m));
Square mfrom, mto, tfrom, tto;
mfrom = Utils.from_sq(m);
mto = Utils.to_sq(m);
tfrom = Utils.from_sq(threat);
tto = Utils.to_sq(threat);
// Case 1: Don't prune moves which move the threatened piece
if (mfrom == tto)
return true;
// Case 2: If the threatened piece has value less than or equal to the
// value of the threatening piece, don't prune moves which defend it.
if (pos.is_capture(threat)
&& (Position.PieceValueMidgame[pos.piece_on(tfrom)] >= Position.PieceValueMidgame[pos.piece_on(tto)]
|| Utils.type_of(pos.piece_on(tfrom)) == PieceTypeC.KING)
&& pos.move_attacks_square(m, tto))
return true;
// Case 3: If the moving piece in the threatened move is a slider, don't
// prune safe moves which block its ray.
if (piece_is_slider(pos.piece_on(tfrom))
&& (Utils.bit_is_set(Utils.between_bb(tfrom, tto), mto) != 0)
&& pos.see(m, true) >= 0)
return true;
return false;
}
示例5: search
//.........这里部分代码省略.........
ss[ssPos].killers1 = ss[ssPos].killers0;
ss[ssPos].killers0 = ttMove;
}
MovesSearchedBroker.Free();
return ttValue;
}
// Step 5. Evaluate the position statically and update parent's gain statistics
if (inCheck)
ss[ssPos].eval = ss[ssPos].evalMargin = ValueC.VALUE_NONE;
else if (tteHasValue)
{
Debug.Assert(tte.static_value() != ValueC.VALUE_NONE);
ss[ssPos].eval = tte.static_value();
ss[ssPos].evalMargin = tte.static_value_margin();
refinedValue = refine_eval(tte, ttValue, ss[ssPos].eval);
}
else
{
refinedValue = ss[ssPos].eval = Evaluate.do_evaluate(false, pos, ref ss[ssPos].evalMargin);
TT.store(posKey, ValueC.VALUE_NONE, Bound.BOUND_NONE, DepthC.DEPTH_NONE, MoveC.MOVE_NONE, ss[ssPos].eval, ss[ssPos].evalMargin);
}
// Update gain for the parent non-capture move given the static position
// evaluation before and after the move.
if ((move = ss[ssPos - 1].currentMove) != MoveC.MOVE_NULL
&& ss[ssPos - 1].eval != ValueC.VALUE_NONE
&& ss[ssPos].eval != ValueC.VALUE_NONE
&& (pos.captured_piece_type() == 0)
&& !Utils.is_special(move))
{
Square to = Utils.to_sq(move);
H.update_gain(pos.piece_on(to), to, -ss[ssPos - 1].eval - ss[ssPos].eval);
}
// Step 6. Razoring (is omitted in PV nodes)
if (!PvNode && !inCheck
&& depth < RazorDepth
&& refinedValue + razor_margin(depth) < beta
&& ttMove == MoveC.MOVE_NONE
&& Math.Abs(beta) < ValueC.VALUE_MATE_IN_MAX_PLY
&& !pos.pawn_on_7th(pos.sideToMove))
{
Value rbeta = beta - razor_margin(depth);
Value v = qsearch(NodeTypeC.NonPV, pos, ss, ssPos, rbeta - 1, rbeta, DepthC.DEPTH_ZERO);
if (v < rbeta)
{
// Logically we should return (v + razor_margin(depth)), but
// surprisingly this did slightly weaker in tests.
MovesSearchedBroker.Free();
return v;
}
}
// Step 7. Static null move pruning (is omitted in PV nodes)
// We're betting that the opponent doesn't have a move that will reduce
// the score by more than futility_margin(depth) if we do a null move.
if (!PvNode && !inCheck
&& (ss[ssPos].skipNullMove == 0)
&& depth < RazorDepth
&& Math.Abs(beta) < ValueC.VALUE_MATE_IN_MAX_PLY
&& refinedValue - futility_margin(depth, 0) >= beta
&& (pos.non_pawn_material(pos.sideToMove) != 0))
{
MovesSearchedBroker.Free();
示例6: check_is_dangerous
// check_is_dangerous() tests if a checking move can be pruned in qsearch().
// bestValue is updated only when returning false because in that case move
// will be pruned.
static bool check_is_dangerous(Position pos, Move move, Value futilityBase, Value beta)
{
Bitboard b, occ, oldAtt, newAtt, kingAtt;
Square from, to, ksq;
Piece pc;
Color them;
from = Utils.from_sq(move);
to = Utils.to_sq(move);
them = Utils.flip_C(pos.sideToMove);
ksq = pos.king_square(them);
kingAtt = Position.attacks_from_KING(ksq);
pc = pos.piece_moved(move);
occ = pos.occupied_squares ^ Utils.SquareBB[from] ^ Utils.SquareBB[ksq];
oldAtt = Position.attacks_from(pc, from, occ);
newAtt = Position.attacks_from(pc, to, occ);
// Rule 1. Checks which give opponent's king at most one escape square are dangerous
b = kingAtt & ~pos.pieces_C(them) & ~newAtt & ~(1UL << to);
if ((b & (b - 1)) == 0) // Catches also !b
return true;
// Rule 2. Queen contact check is very dangerous
if (Utils.type_of(pc) == PieceTypeC.QUEEN
&& (Utils.bit_is_set(kingAtt, to) != 0))
return true;
// Rule 3. Creating new double threats with checks
b = pos.pieces_C(them) & newAtt & ~oldAtt & ~(1UL << ksq);
while (b != 0)
{
// Note that here we generate illegal "double move"!
if (futilityBase + Position.PieceValueEndgame[pos.piece_on(Utils.pop_1st_bit(ref b))] >= beta)
return true;
}
return false;
}
示例7: connected_moves
// connected_moves() tests whether two moves are 'connected' in the sense
// that the first move somehow made the second move possible (for instance
// if the moving piece is the same in both moves). The first move is assumed
// to be the move that was made to reach the current position, while the
// second move is assumed to be a move from the current position.
internal static bool connected_moves(Position pos, Move m1, Move m2)
{
Square f1, t1, f2, t2;
Piece p1, p2;
Square ksq;
Debug.Assert(Utils.is_ok_M(m1));
Debug.Assert(Utils.is_ok_M(m2));
// Case 1: The moving piece is the same in both moves
f2 = Utils.from_sq(m2);
t1 = Utils.to_sq(m1);
if (f2 == t1)
return true;
// Case 2: The destination square for m2 was vacated by m1
t2 = Utils.to_sq(m2);
f1 = Utils.from_sq(m1);
if (t2 == f1)
return true;
// Case 3: Moving through the vacated square
p2 = pos.piece_on(f2);
if (piece_is_slider(p2)
&& (Utils.bit_is_set(Utils.between_bb(f2, t2), f1) != 0))
return true;
// Case 4: The destination square for m2 is defended by the moving piece in m1
p1 = pos.piece_on(t1);
if ((Utils.bit_is_set(pos.attacks_from_PS(p1, t1), t2)) != 0)
return true;
// Case 5: Discovered check, checking piece is the piece moved in m1
ksq = pos.king_square(pos.sideToMove);
if (
piece_is_slider(p1)
&&
(Utils.bit_is_set(Utils.between_bb(t1, ksq), f2) != 0)
&&
(Utils.bit_is_set(Position.attacks_from(p1, t1, Utils.xor_bit(pos.occupied_squares, f2)), ksq) != 0)
)
return true;
return false;
}
示例8: generate_quiet_check
internal static void generate_quiet_check(Position pos, MoveStack[] ms, ref int mpos)
{
/// generate<MV_NON_CAPTURE_CHECK> generates all pseudo-legal non-captures and knight
/// underpromotions that give check. Returns a pointer to the end of the move list.
Debug.Assert(!pos.in_check());
var ci = CheckInfoBroker.GetObject();
ci.CreateCheckInfo(pos);
var target = ~pos.occupied_squares;
var dc = ci.dcCandidates;
while (dc != 0)
{
var from = Utils.pop_lsb(ref dc);
var pt = Utils.type_of(pos.piece_on(from));
if (pt == PieceTypeC.PAWN)
{
continue; // Will be generated together with direct checks
}
var b = pos.attacks_from_PTS(pt, from) & ~pos.occupied_squares;
if (pt == PieceTypeC.KING)
{
b &= ~Utils.PseudoAttacks[PieceTypeC.QUEEN][ci.ksq];
}
while (b != 0)
{
ms[mpos++].move = Utils.make_move(from, Utils.pop_lsb(ref b));
}
}
generate_all(GenType.QUIET_CHECKS, pos, ms, ref mpos, pos.sideToMove, target, ci);
CheckInfoBroker.Free();
}
示例9: evaluate_pieces_of_color
//.........这里部分代码省略.........
}
}
score += ((bonus << 16) + bonus); // Utils.make_score(bonus, bonus);
#endregion
}
if ((Piece == PieceTypeC.ROOK || Piece == PieceTypeC.QUEEN) && Utils.relative_rank_CS(Us, s) >= RankC.RANK_5)
{
// Major piece on 7th rank
if (Utils.relative_rank_CS(Us, s) == RankC.RANK_7
&& Utils.relative_rank_CS(Us, pos.king_square(Them)) == RankC.RANK_8)
score += (Piece == PieceTypeC.ROOK ? RookOn7thBonus : QueenOn7thBonus);
// Major piece attacking pawns on the same rank
Bitboard pawns = pos.pieces_PTC(PieceTypeC.PAWN, Them) & Utils.rank_bb_S(s);
if (pawns != 0)
{
score += (Piece == PieceTypeC.ROOK ? RookOnPawnBonus : QueenOnPawnBonus) * Bitcount.popcount_1s_Max15(pawns);
}
}
// Special extra evaluation for bishops
if (pos.chess960 && (Piece == PieceTypeC.BISHOP))
{
// An important Chess960 pattern: A cornered bishop blocked by
// a friendly pawn diagonally in front of it is a very serious
// problem, especially when that pawn is also blocked.
if (s == Utils.relative_square(Us, SquareC.SQ_A1)
|| s == Utils.relative_square(Us, SquareC.SQ_H1))
{
var d = Utils.pawn_push(Us)
+ (Utils.file_of(s) == FileC.FILE_A ? SquareC.DELTA_E : SquareC.DELTA_W);
if (pos.piece_on(s + d) == Utils.make_piece(Us, PieceTypeC.PAWN))
{
if (!pos.is_empty(s + d + Utils.pawn_push(Us)))
{
score -= 2 * TrappedBishopA1H1Penalty;
}
else if (pos.piece_on(s + 2 * d) == Utils.make_piece(Us, PieceTypeC.PAWN))
{
score -= TrappedBishopA1H1Penalty;
}
else
{
score -= TrappedBishopA1H1Penalty / 2;
}
}
}
}
// Special extra evaluation for rooks
if (Piece == PieceTypeC.ROOK)
{
// Open and half-open files
f = (s & 7);
var halfOpenUs = ((Us == ColorC.WHITE)
? (ei.pi.halfOpenFilesWHITE & (1 << f))
: (ei.pi.halfOpenFilesBLACK & (1 << f))) != 0;
if (halfOpenUs)
{
if (((Them == ColorC.WHITE)
? (ei.pi.halfOpenFilesWHITE & (1 << f))
: (ei.pi.halfOpenFilesBLACK & (1 << f))) != 0)
示例10: search
//.........这里部分代码省略.........
{
eval = ss[ssPos].staticEval = Evaluate.do_evaluate(false, pos, ref ss[ssPos].evalMargin);
}
// Can ttValue be used as a better position evaluation?
if (ttValue != ValueC.VALUE_NONE)
{
if ((((tte.type() & Bound.BOUND_LOWER) != 0) && ttValue > eval)
|| (((tte.type() & Bound.BOUND_UPPER) != 0) && ttValue < eval))
{
eval = ttValue;
}
}
}
else
{
eval = ss[ssPos].staticEval = Evaluate.do_evaluate(false, pos, ref ss[ssPos].evalMargin);
TT.store(
posKey,
ValueC.VALUE_NONE,
Bound.BOUND_NONE,
DepthC.DEPTH_NONE,
MoveC.MOVE_NONE,
ss[ssPos].staticEval,
ss[ssPos].evalMargin);
}
// Update gain for the parentSplitPoint non-capture move given the static position
// evaluation before and after the move.
if ((move = ss[ssPos - 1].currentMove) != MoveC.MOVE_NULL && ss[ssPos - 1].staticEval != ValueC.VALUE_NONE
&& ss[ssPos].staticEval != ValueC.VALUE_NONE && (pos.captured_piece_type() == 0) && Utils.type_of_move(move) == MoveTypeC.NORMAL)
{
var to = Utils.to_sq(move);
H.update_gain(pos.piece_on(to), to, -ss[ssPos - 1].staticEval - ss[ssPos].staticEval);
}
// Step 6. Razoring (is omitted in PV nodes)
if (!PvNode && !inCheck && depth < 4 * DepthC.ONE_PLY && eval + razor_margin(depth) < beta
&& ttMove == MoveC.MOVE_NONE && Math.Abs(beta) < ValueC.VALUE_MATE_IN_MAX_PLY
&& !pos.pawn_on_7th(pos.sideToMove))
{
var rbeta = beta - razor_margin(depth);
var v = qsearch(NodeTypeC.NonPV, false, pos, ss, ssPos, rbeta - 1, rbeta, DepthC.DEPTH_ZERO);
if (v < rbeta)
{
// Logically we should return (v + razor_margin(depth)), but
// surprisingly this did slightly weaker in tests.
MovesSearchedBroker.Free();
return v;
}
}
// Step 7. Static null move pruning (is omitted in PV nodes)
// We're betting that the opponent doesn't have a move that will reduce
// the score by more than futility_margin(depth) if we do a null move.
if (!PvNode && !inCheck && (ss[ssPos].skipNullMove == 0) && depth < 4 * DepthC.ONE_PLY
&& Math.Abs(beta) < ValueC.VALUE_MATE_IN_MAX_PLY && eval - FutilityMargins[depth][0] >= beta
&& (pos.non_pawn_material(pos.sideToMove) != 0))
{
MovesSearchedBroker.Free();
return eval - FutilityMargins[depth][0];
}
// Step 8. Null move search with verification search (is omitted in PV nodes)
if (!PvNode && !inCheck && (ss[ssPos].skipNullMove == 0) && depth > DepthC.ONE_PLY && eval >= beta
&& Math.Abs(beta) < ValueC.VALUE_MATE_IN_MAX_PLY && (pos.non_pawn_material(pos.sideToMove) != 0))
示例11: generate_evasion
internal static void generate_evasion(Position pos, MoveStack[] ms, ref int mpos)
{
/// generate<EVASIONS> generates all pseudo-legal check evasions when the side
/// to move is in check. Returns a pointer to the end of the move list.
Debug.Assert(pos.in_check());
ulong b;
int from, checksq;
var checkersCnt = 0;
var us = pos.sideToMove;
var ksq = pos.king_square(us);
ulong sliderAttacks = 0;
var checkers = pos.st.checkersBB;
Debug.Assert(checkers != 0);
// Find squares attacked by slider checkers, we will remove them from the king
// evasions so to skip known illegal moves avoiding useless legality check later.
b = checkers;
do
{
checkersCnt++;
checksq = Utils.pop_lsb(ref b);
Debug.Assert(Utils.color_of(pos.piece_on(checksq)) == Utils.flip_C(us));
switch (Utils.type_of(pos.piece_on(checksq)))
{
case PieceTypeC.BISHOP:
sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.BISHOP][checksq];
break;
case PieceTypeC.ROOK:
sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.ROOK][checksq];
break;
case PieceTypeC.QUEEN:
// If queen and king are far or not on a diagonal line we can safely
// remove all the squares attacked in the other direction becuase are
// not reachable by the king anyway.
if ((Utils.between_bb(ksq, checksq) != 0)
|| ((Utils.bit_is_set(Utils.PseudoAttacks[PieceTypeC.BISHOP][checksq], ksq)) == 0))
{
sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.QUEEN][checksq];
}
// Otherwise we need to use real rook attacks to check if king is safe
// to move in the other direction. For example: king in B2, queen in A1
// a knight in B1, and we can safely move to C1.
else
{
sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.BISHOP][checksq]
| pos.attacks_from_ROOK(checksq);
}
break;
default:
break;
}
}
while (b != 0);
// Generate evasions for king, capture and non capture moves
b = Position.attacks_from_KING(ksq) & ~pos.pieces_C(us) & ~sliderAttacks;
from = ksq;
while (b != 0)
{
ms[mpos++].move = Utils.make_move(from, Utils.pop_lsb(ref b));
}
// Generate evasions for other pieces only if not under a double check
if (checkersCnt > 1)
{
return;
}
// Blocking evasions or captures of the checking piece
var target = Utils.between_bb(checksq, ksq) | checkers;
generate_all(GenType.EVASIONS, pos, ms, ref mpos, us, target, null);
}
示例12: refutes
// refutes() tests whether a 'first' move is able to defend against a 'second'
// opponent's move. In this case will not be pruned. Normally the second move
// is the threat (the best move returned from a null search that fails low).
private static bool refutes(Position pos, int move, int threat)
{
Debug.Assert(Utils.is_ok_M(move));
Debug.Assert(Utils.is_ok_M(threat));
Square mfrom = Utils.from_sq(move);
Square mto = Utils.to_sq(move);
Square tfrom = Utils.from_sq(threat);
Square tto = Utils.to_sq(threat);
// Don't prune moves of the threatened piece
if (mfrom == tto)
{
return true;
}
// If the threatened piece has value less than or equal to the value of the
// threat piece, don't prune moves which defend it.
if (pos.is_capture(threat)
&& (Position.PieceValue[PhaseC.MG][pos.piece_on(tfrom)] >= Position.PieceValue[PhaseC.MG][pos.piece_on(tto)]
|| Utils.type_of(pos.piece_on(tfrom)) == PieceTypeC.KING))
{
// Update occupancy as if the piece and the threat are moving
var occ = Utils.xor_bit(Utils.xor_bit(Utils.xor_bit(pos.occupied_squares, mfrom), mto), tfrom);
Piece piece = pos.piece_on(mfrom);
// The piece moved in 'to' attacks the square 's' ?
if (Utils.bit_is_set(Position.attacks_from(piece, mto, occ), tto) != 0)
{
return true;
}
// Scan for possible X-ray attackers behind the moved piece
var xray = (Utils.rook_attacks_bb(tto, occ)
& pos.pieces(PieceTypeC.ROOK, PieceTypeC.QUEEN, Utils.color_of(piece)))
| (Utils.bishop_attacks_bb(tto, occ)
& pos.pieces(PieceTypeC.BISHOP, PieceTypeC.QUEEN, Utils.color_of(piece)));
// Verify attackers are triggered by our move and not already existing
if ((xray != 0) && ((xray ^ (xray & pos.attacks_from_QUEEN(tto))) != 0))
{
return true;
}
}
// Don't prune safe moves which block the threat path
if ((Utils.bit_is_set(Utils.between_bb(tfrom, tto), mto) != 0) && pos.see(move, true) >= 0)
{
return true;
}
return false;
}
示例13: allows
// allows() tests whether the 'first' move at previous ply somehow makes the
// 'second' move possible, for instance if the moving piece is the same in
// both moves. Normally the second move is the threat (the best move returned
// from a null search that fails low).
internal static bool allows(Position pos, int first, int second)
{
Debug.Assert(Utils.is_ok_M(first));
Debug.Assert(Utils.is_ok_M(second));
Debug.Assert(Utils.color_of(pos.piece_on(Utils.from_sq(second))) == 1 - pos.sideToMove);
Square m1to = Utils.to_sq(first);
Square m1from = Utils.from_sq(first);
Square m2to = Utils.to_sq(second);
Square m2from = Utils.from_sq(second);
// The piece is the same or second's destination was vacated by the first move
if (m1to == m2from || m2to == m1from)
{
return true;
}
// Second one moves through the square vacated by first one
if (Utils.bit_is_set(Utils.between_bb(m2from, m2to), m1from) != 0)
{
return true;
}
// Second's destination is defended by the first move's piece
Bitboard m1att = Position.attacks_from(pos.piece_on(m1to), m1to, pos.occupied_squares ^ (ulong)m2from);
if (Utils.bit_is_set(m1att, m2to) != 0)
{
return true;
}
// Second move gives a discovered check through the first's checking piece
if (Utils.bit_is_set(m1att, pos.king_square(pos.sideToMove)) != 0 &&
Utils.bit_is_set(Utils.between_bb(m1to, pos.king_square(pos.sideToMove)), m2from) != 0) // TODO: removing condition asserts below
{
Debug.Assert(Utils.bit_is_set(Utils.between_bb(m1to, pos.king_square(pos.sideToMove)), m2from) != 0);
return true;
}
return false;
}
示例14: check_is_dangerous
// check_is_dangerous() tests if a checking move can be pruned in qsearch().
// bestValue is updated only when returning false because in that case move
// will be pruned.
private static bool check_is_dangerous(Position pos, int move, int futilityBase, int beta)
{
//ulong b, occ, oldAtt, newAtt, kingAtt;
//int from, to, ksq;
//int pc;
//int them;
//from = Utils.from_sq(move);
//to = Utils.to_sq(move);
//them = Utils.flip_C(pos.sideToMove);
//ksq = pos.king_square(them);
//kingAtt = Position.attacks_from_KING(ksq);
//pc = pos.piece_moved(move);
//occ = pos.occupied_squares ^ Utils.SquareBB[from] ^ Utils.SquareBB[ksq];
//oldAtt = Position.attacks_from(pc, from, occ);
//newAtt = Position.attacks_from(pc, to, occ);
//// Rule 1. Checks which give opponent's king at most one escape square are dangerous
//b = kingAtt & ~pos.pieces_C(them) & ~newAtt & ~(1UL << to);
//if ((b & (b - 1)) == 0) // Catches also !b
Piece pc = pos.piece_moved(move);
Square from = Utils.from_sq(move);
Square to = Utils.to_sq(move);
Color them = pos.sideToMove ^ 1;
Square ksq = pos.king_square(them);
Bitboard enemies = pos.pieces_C(them);
Bitboard kingAtt = Position.attacks_from_KING(ksq);
Bitboard occ = pos.occupied_squares ^ Utils.SquareBB[from] ^ Utils.SquareBB[ksq];
Bitboard oldAtt = Position.attacks_from(pc, from, occ);
Bitboard newAtt = Position.attacks_from(pc, to, occ);
// Checks which give opponent's king at most one escape square are dangerous
if (!Utils.more_than_one(kingAtt & ~(enemies | newAtt | (ulong)to)))
{
return true;
}
// Queen contact check is very dangerous
if (Utils.type_of(pc) == PieceTypeC.QUEEN && (Utils.bit_is_set(kingAtt, to) != 0))
{
return true;
}
// Creating new double threats with checks is dangerous
Bitboard b = (enemies ^ (ulong)ksq) & newAtt & ~oldAtt;
while (b != 0)
{
// Note that here we generate illegal "double move"!
if (futilityBase + Position.PieceValue[PhaseC.EG][pos.piece_on(Utils.pop_lsb(ref b))] >= beta)
{
return true;
}
}
return false;
}
示例15: generate_quiet_check
internal static void generate_quiet_check(Position pos, MoveStack[] ms, ref int mpos)
{
/// generate<MV_NON_CAPTURE_CHECK> generates all pseudo-legal non-captures and knight
/// underpromotions that give check. Returns a pointer to the end of the move list.
Debug.Assert(!pos.in_check());
Color us = pos.sideToMove;
CheckInfo ci = CheckInfoBroker.GetObject();
ci.CreateCheckInfo(pos);
Bitboard dc = ci.dcCandidates;
while (dc != 0)
{
Square from = Utils.pop_1st_bit(ref dc);
PieceType pt = Utils.type_of(pos.piece_on(from));
if (pt == PieceTypeC.PAWN)
continue; // Will be generated together with direct checks
Bitboard b = pos.attacks_from_PTS(pt, from) & ~pos.occupied_squares;
if (pt == PieceTypeC.KING)
b &= ~Utils.PseudoAttacks[PieceTypeC.QUEEN][ci.ksq];
while (b != 0) { ms[mpos++].move = Utils.make_move(from, Utils.pop_1st_bit(ref b)); }
}
generate_pawn_moves(us, MoveType.MV_QUIET_CHECK, pos, ms, ref mpos, ci.dcCandidates, ci.ksq);
generate_direct_checks(PieceTypeC.KNIGHT, pos, ms, ref mpos, us, ci);
generate_direct_checks(PieceTypeC.BISHOP, pos, ms, ref mpos, us, ci);
generate_direct_checks(PieceTypeC.ROOK, pos, ms, ref mpos, us, ci);
generate_direct_checks(PieceTypeC.QUEEN, pos, ms, ref mpos, us, ci);
if (pos.can_castle_C(us) != 0)
{
generate_castle(CastlingSideC.KING_SIDE, true, pos, ms, ref mpos, us);
generate_castle(CastlingSideC.QUEEN_SIDE, true, pos, ms, ref mpos, us);
}
CheckInfoBroker.Free();
}