本文整理汇总了C#中Portfish.Position.pieces_PTC方法的典型用法代码示例。如果您正苦于以下问题:C# Position.pieces_PTC方法的具体用法?C# Position.pieces_PTC怎么用?C# Position.pieces_PTC使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Portfish.Position
的用法示例。
在下文中一共展示了Position.pieces_PTC方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: probe
/// PawnTable::pawn_info() takes a position object as input, computes
/// a PawnInfo object, and returns a pointer to it. The result is also stored
/// in an hash table, so we don't have to recompute everything when the same
/// pawn structure occurs again.
internal void probe(Position pos, out PawnEntry e)
{
Key key = pos.pawn_key();
e = entries[((UInt32)key) & Constants.PawnTableMask];
// If pi.key matches the position's pawn hash key, it means that we
// have analysed this pawn structure before, and we can simply return
// the information we found the last time instead of recomputing it.
if (e.key == key) return;
// Initialize PawnInfo entry
e.key = key;
e.passedPawnsWHITE = e.passedPawnsBLACK = 0;
e.kingSquaresWHITE = e.kingSquaresBLACK = SquareC.SQ_NONE;
e.halfOpenFilesWHITE = e.halfOpenFilesBLACK = 0xFF;
// Calculate pawn attacks
Bitboard wPawns = pos.pieces_PTC(PieceTypeC.PAWN, ColorC.WHITE);
Bitboard bPawns = pos.pieces_PTC(PieceTypeC.PAWN, ColorC.BLACK);
e.pawnAttacksWHITE = ((wPawns & ~Constants.FileHBB) << 9) | ((wPawns & ~Constants.FileABB) << 7);
e.pawnAttacksBLACK = ((bPawns & ~Constants.FileHBB) >> 7) | ((bPawns & ~Constants.FileABB) >> 9);
// Evaluate pawns for both colors and weight the result
e.value = evaluate_pawns(ColorC.WHITE, pos, wPawns, bPawns, e)
- evaluate_pawns(ColorC.BLACK, pos, bPawns, wPawns, e);
e.value = Utils.apply_weight(e.value, PawnStructureWeight);
return;
}
示例2: probe
/// MaterialTable::material_info() takes a position object as input,
/// computes or looks up a MaterialInfo object, and returns a pointer to it.
/// If the material configuration is not already present in the table, it
/// is stored there, so we don't have to recompute everything when the
/// same material configuration occurs again.
internal void probe(Position pos, out MaterialEntry e)
{
var key = pos.material_key();
e = this.entries[((uint)key) & Constants.MaterialTableMask];
// If mi->key matches the position's material hash key, it means that we
// have analysed this material configuration before, and we can simply
// return the information we found the last time instead of recomputing it.
if (e.key == key)
{
return;
}
// Initialize MaterialInfo entry
var npm = pos.non_pawn_material(ColorC.WHITE) + pos.non_pawn_material(ColorC.BLACK);
e.value = 0;
e.scalingFunctionWHITE = null;
e.scalingFunctionBLACK = null;
e.spaceWeight = 0;
e.key = key;
e.factorWHITE = e.factorBLACK = ScaleFactorC.SCALE_FACTOR_NORMAL;
e.gamePhase = npm >= MidgameLimit
? PhaseC.PHASE_MIDGAME
: npm <= EndgameLimit
? PhaseC.PHASE_ENDGAME
: (((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
// Let's look if we have a specialized evaluation function for this
// particular material configuration. First we look for a fixed
// configuration one, then a generic one if previous search failed.
if ((e.evaluationFunction = Endgame.probeValue(key, out e.evaluationFunctionColor)) != null)
{
return;
}
if (is_KXK(ColorC.WHITE, pos))
{
e.evaluationFunction = Endgame.Endgame_KXK;
e.evaluationFunctionColor = ColorC.WHITE;
return;
}
if (is_KXK(ColorC.BLACK, pos))
{
e.evaluationFunction = Endgame.Endgame_KXK;
e.evaluationFunctionColor = ColorC.BLACK;
return;
}
if ((pos.pieces_PT(PieceTypeC.PAWN) == 0) && (pos.pieces_PT(PieceTypeC.ROOK) == 0)
&& (pos.pieces_PT(PieceTypeC.QUEEN) == 0))
{
// Minor piece endgame with at least one minor piece per side and
// no pawns. Note that the case KmmK is already handled by KXK.
Debug.Assert(
(pos.pieces_PTC(PieceTypeC.KNIGHT, ColorC.WHITE) | pos.pieces_PTC(PieceTypeC.BISHOP, ColorC.WHITE))
!= 0);
Debug.Assert(
(pos.pieces_PTC(PieceTypeC.KNIGHT, ColorC.BLACK) | pos.pieces_PTC(PieceTypeC.BISHOP, ColorC.BLACK))
!= 0);
if (pos.piece_count(ColorC.WHITE, PieceTypeC.BISHOP) + pos.piece_count(ColorC.WHITE, PieceTypeC.KNIGHT)
<= 2
&& pos.piece_count(ColorC.BLACK, PieceTypeC.BISHOP)
+ pos.piece_count(ColorC.BLACK, PieceTypeC.KNIGHT) <= 2)
{
e.evaluationFunction = Endgame.Endgame_KmmKm;
e.evaluationFunctionColor = pos.sideToMove;
return;
}
}
// OK, we didn't find any special evaluation function for the current
// material configuration. Is there a suitable scaling function?
//
// We face problems when there are several conflicting applicable
// scaling functions and we need to decide which one to use.
EndgameScaleFactor sf;
int c;
if ((sf = Endgame.probeScaleFactor(key, out c)) != null)
{
if (c == ColorC.WHITE)
{
e.scalingFunctionWHITE = sf;
}
else
{
e.scalingFunctionBLACK = sf;
}
return;
}
// Generic scaling functions that refer to more then one material
// distribution. Should be probed after the specialized ones.
// Note that these ones don't return after setting the function.
//.........这里部分代码省略.........
示例3: 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();
}
示例4: evaluate_pieces_of_color
// evaluate_pieces_of_color<>() assigns bonuses and penalties to all the
// pieces of a given color.
private static int evaluate_pieces_of_color(int Us, bool Trace, Position pos, EvalInfo ei, ref int mobility)
{
var Them = (Us == ColorC.WHITE ? ColorC.BLACK : ColorC.WHITE);
mobility = ScoreC.SCORE_ZERO;
// Do not include in mobility squares protected by enemy pawns or occupied by our pieces
var mobilityArea = ~(ei.attackedBy[Them][PieceTypeC.PAWN] | pos.byColorBB[Us]);
#region Evaluate pieces
ulong between = 0;
var plPos = 0;
int s, ksq;
int mob;
int f;
int score, scores = ScoreC.SCORE_ZERO;
var attackedByThemKing = ei.attackedBy[Them][PieceTypeC.KING];
var attackedByThemPawn = ei.attackedBy[Them][PieceTypeC.PAWN];
var kingRingThem = ei.kingRing[Them];
for (var Piece = PieceTypeC.KNIGHT; Piece < PieceTypeC.KING; Piece++)
{
score = ScoreC.SCORE_ZERO;
ei.attackedBy[Us][Piece] = 0;
var pl = pos.pieceList[Us][Piece];
plPos = 0;
while ((s = pl[plPos++]) != SquareC.SQ_NONE)
{
// Find attacked squares, including x-ray attacks for bishops and rooks
if (Piece == PieceTypeC.KNIGHT)
{
between = Utils.StepAttacksBB_KNIGHT[s];
}
else if (Piece == PieceTypeC.QUEEN)
{
#if X64
b = Utils.BAttacks[s][(((pos.occupied_squares & Utils.BMasks[s]) * Utils.BMagics[s]) >> Utils.BShifts[s])] | Utils.RAttacks[s][(((pos.occupied_squares & Utils.RMasks[s]) * Utils.RMagics[s]) >> Utils.RShifts[s])];
#else
between = Utils.bishop_attacks_bb(s, pos.occupied_squares)
| Utils.rook_attacks_bb(s, pos.occupied_squares);
#endif
}
else if (Piece == PieceTypeC.BISHOP)
{
#if X64
b = Utils.BAttacks[s][(((
(pos.occupied_squares ^ (pos.byTypeBB[PieceTypeC.QUEEN] & pos.byColorBB[Us]))
& Utils.BMasks[s]) * Utils.BMagics[s]) >> Utils.BShifts[s])];
#else
between = Utils.bishop_attacks_bb(s, pos.occupied_squares ^ pos.pieces_PTC(PieceTypeC.QUEEN, Us));
#endif
}
else if (Piece == PieceTypeC.ROOK)
{
#if X64
b = Utils.RAttacks[s][(((
(pos.occupied_squares ^ ((pos.byTypeBB[PieceTypeC.ROOK] | pos.byTypeBB[PieceTypeC.QUEEN]) & pos.byColorBB[Us]))
& Utils.RMasks[s]) * Utils.RMagics[s]) >> Utils.RShifts[s])];
#else
between = Utils.rook_attacks_bb(
s,
pos.occupied_squares ^ pos.pieces(PieceTypeC.ROOK, PieceTypeC.QUEEN, Us));
#endif
}
// Update attack info
ei.attackedBy[Us][Piece] |= between;
// King attacks
if ((between & kingRingThem) != 0)
{
ei.kingAttackersCount[Us]++;
ei.kingAttackersWeight[Us] += KingAttackWeights[Piece];
var bb = (between & attackedByThemKing); //ei.attackedBy[Them][PieceTypeC.KING]);
if (bb != 0)
{
#if X64
bb -= (bb >> 1) & 0x5555555555555555UL;
bb = ((bb >> 2) & 0x3333333333333333UL) + (bb & 0x3333333333333333UL);
ei.kingAdjacentZoneAttacksCount[Us] += (int)((bb * 0x1111111111111111UL) >> 60);
#else
ei.kingAdjacentZoneAttacksCount[Us] += Bitcount.popcount_1s_Max15(bb);
#endif
}
}
// Mobility
#if X64
Bitboard bmob = b & mobilityArea;
if (Piece != PieceTypeC.QUEEN)
{
bmob -= (bmob >> 1) & 0x5555555555555555UL;
bmob = ((bmob >> 2) & 0x3333333333333333UL) + (bmob & 0x3333333333333333UL);
mob = (int)((bmob * 0x1111111111111111UL) >> 60);
}
else
{
//.........这里部分代码省略.........
示例5: move_to_san
/// move_to_san() takes a position and a move as input, where it is assumed
/// that the move is a legal move for the position. The return value is
/// a string containing the move in short algebraic notation.
internal static string move_to_san(Position pos, Move m)
{
if (m == MoveC.MOVE_NONE)
return "(none)";
if (m == MoveC.MOVE_NULL)
return "(null)";
Debug.Assert(is_ok_M(m));
Bitboard attackers;
bool ambiguousMove, ambiguousFile, ambiguousRank;
Square sq, from = from_sq(m);
Square to = to_sq(m);
PieceType pt = type_of(pos.piece_moved(m));
StringBuilder san = new StringBuilder();
if (is_castle(m))
san.Append((to_sq(m) < from_sq(m) ? "O-O-O" : "O-O"));
else
{
if (pt != PieceTypeC.PAWN)
{
san.Append(piece_type_to_char(pt).ToString());
// Disambiguation if we have more then one piece with destination 'to'
// note that for pawns is not needed because starting file is explicit.
attackers = pos.attackers_to(to) & pos.pieces_PTC(pt, pos.sideToMove);
xor_bit(ref attackers, from);
ambiguousMove = ambiguousFile = ambiguousRank = false;
while (attackers != 0)
{
sq = pop_1st_bit(ref attackers);
// Pinned pieces are not included in the possible sub-set
if (!pos.pl_move_is_legal(make_move(sq, to), pos.pinned_pieces()))
continue;
if (file_of(sq) == file_of(from))
ambiguousFile = true;
if (rank_of(sq) == rank_of(from))
ambiguousRank = true;
ambiguousMove = true;
}
if (ambiguousMove)
{
if (!ambiguousFile)
san.Append(file_to_char(file_of(from)));
else if (!ambiguousRank)
san.Append(rank_to_char(rank_of(from)));
else
san.Append(square_to_string(from));
}
}
if (pos.is_capture(m))
{
if (pt == PieceTypeC.PAWN)
san.Append(file_to_char(file_of(from)));
san.Append('x');
}
san.Append(square_to_string(to));
if (is_promotion(m))
{
san.Append('=');
san.Append(piece_type_to_char(promotion_type(m)));
}
}
CheckInfo ci = CheckInfoBroker.GetObject();
ci.CreateCheckInfo(pos);
if (pos.move_gives_check(m, ci))
{
StateInfo st = new StateInfo();
pos.do_move(m, st);
MList 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();
}
示例6: Endgame_KQKRPs
/// K and queen vs K, rook and one or more pawns. It tests for fortress draws with
/// a rook on the third rank defended by a pawn.
internal static ScaleFactor Endgame_KQKRPs(Color strongerSide, Position pos)
{
Color weakerSide = strongerSide ^ 1;
Debug.Assert(pos.non_pawn_material(strongerSide) == Constants.QueenValueMidgame);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.QUEEN) == 1);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.PAWN) == 0);
Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.ROOK) == 1);
Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.PAWN) >= 1);
Square kingSq = pos.king_square(weakerSide);
if (Utils.relative_rank_CS(weakerSide, kingSq) <= RankC.RANK_2
&& Utils.relative_rank_CS(weakerSide, pos.king_square(strongerSide)) >= RankC.RANK_4
&& ((pos.pieces_PTC(PieceTypeC.ROOK, weakerSide) & Utils.rank_bb_R(Utils.relative_rank_CR(weakerSide, RankC.RANK_3))) != 0)
&& ((pos.pieces_PTC(PieceTypeC.PAWN, weakerSide) & Utils.rank_bb_R(Utils.relative_rank_CR(weakerSide, RankC.RANK_2))) != 0)
&& ((Position.attacks_from_KING(kingSq) & pos.pieces_PTC(PieceTypeC.PAWN, weakerSide)) != 0)
)
{
Square rsq = pos.pieceList[weakerSide][PieceTypeC.ROOK][0];
if ((Position.attacks_from_PAWN(rsq, strongerSide) & pos.pieces_PTC(PieceTypeC.PAWN, weakerSide)) != 0)
return ScaleFactorC.SCALE_FACTOR_DRAW;
}
return ScaleFactorC.SCALE_FACTOR_NONE;
}
示例7: evaluate_unstoppable_pawns
// evaluate_unstoppable_pawns() evaluates the unstoppable passed pawns for both sides, this is quite
// conservative and returns a winning score only when we are very sure that the pawn is winning.
private static int evaluate_unstoppable_pawns(Position pos, EvalInfo ei)
{
ulong b, b2, blockers, supporters, queeningPath, candidates;
int s, blockSq, queeningSquare;
int c, winnerSide, loserSide;
bool pathDefended, opposed;
int pliesToGo = 0, movesToGo, oppMovesToGo = 0, sacptg, blockersCount, minKingDist, kingptg, d;
int pliesToQueenWHITE = 256, pliesToQueenBLACK = 256, pliesToQueenWinner = 256;
// Step 1. Hunt for unstoppable passed pawns. If we find at least one,
// record how many plies are required for promotion.
for (c = ColorC.WHITE; c <= ColorC.BLACK; c++)
{
// Skip if other side has non-pawn pieces
if (pos.non_pawn_material(Utils.flip_C(c)) != 0)
{
continue;
}
b = ei.pi.passed_pawns(c);
while (b != 0)
{
s = Utils.pop_lsb(ref b);
queeningSquare = Utils.relative_square(c, Utils.make_square(Utils.file_of(s), RankC.RANK_8));
queeningPath = Utils.forward_bb(c, s);
// Compute plies to queening and check direct advancement
movesToGo = Utils.rank_distance(s, queeningSquare)
- (Utils.relative_rank_CS(c, s) == RankC.RANK_2 ? 1 : 0);
oppMovesToGo = Utils.square_distance(pos.king_square(Utils.flip_C(c)), queeningSquare)
- ((c != pos.sideToMove) ? 1 : 0);
pathDefended = ((ei.attackedBy[c][0] & queeningPath) == queeningPath);
if (movesToGo >= oppMovesToGo && !pathDefended)
{
continue;
}
// Opponent king cannot block because path is defended and position
// is not in check. So only friendly pieces can be blockers.
Debug.Assert(!pos.in_check());
Debug.Assert((queeningPath & pos.occupied_squares) == (queeningPath & pos.pieces_C(c)));
// Add moves needed to free the path from friendly pieces and retest condition
movesToGo += Bitcount.popcount_1s_Max15(queeningPath & pos.pieces_C(c));
if (movesToGo >= oppMovesToGo && !pathDefended)
{
continue;
}
pliesToGo = 2 * movesToGo - ((c == pos.sideToMove) ? 1 : 0);
if (c == ColorC.WHITE)
{
pliesToQueenWHITE = Math.Min(pliesToQueenWHITE, pliesToGo);
}
else
{
pliesToQueenBLACK = Math.Min(pliesToQueenBLACK, pliesToGo);
}
}
}
// Step 2. If either side cannot promote at least three plies before the other side then situation
// becomes too complex and we give up. Otherwise we determine the possibly "winning side"
if (Math.Abs(pliesToQueenWHITE - pliesToQueenBLACK) < 3)
{
return ScoreC.SCORE_ZERO;
}
winnerSide = (pliesToQueenWHITE < pliesToQueenBLACK ? ColorC.WHITE : ColorC.BLACK);
pliesToQueenWinner = (winnerSide == ColorC.WHITE) ? pliesToQueenWHITE : pliesToQueenBLACK;
loserSide = Utils.flip_C(winnerSide);
// Step 3. Can the losing side possibly create a new passed pawn and thus prevent the loss?
b = candidates = pos.pieces_PTC(PieceTypeC.PAWN, loserSide);
while (b != 0)
{
s = Utils.pop_lsb(ref b);
// Compute plies from queening
queeningSquare = Utils.relative_square(loserSide, Utils.make_square(Utils.file_of(s), RankC.RANK_8));
movesToGo = Utils.rank_distance(s, queeningSquare)
- ((Utils.relative_rank_CS(loserSide, s) == RankC.RANK_2) ? 1 : 0);
pliesToGo = 2 * movesToGo - ((loserSide == pos.sideToMove) ? 1 : 0);
// Check if (without even considering any obstacles) we're too far away or doubled
if ((pliesToQueenWinner + 3 <= pliesToGo)
|| ((Utils.forward_bb(loserSide, s) & pos.pieces_PTC(PieceTypeC.PAWN, loserSide)) != 0))
{
Utils.xor_bit(ref candidates, s);
}
}
// If any candidate is already a passed pawn it _may_ promote in time. We give up.
//.........这里部分代码省略.........
示例8: Endgame_KPsK
/// K and two or more pawns vs K. There is just a single rule here: If all pawns
/// are on the same rook file and are blocked by the defending king, it's a draw.
internal static ScaleFactor Endgame_KPsK(Color strongerSide, Position pos)
{
Color weakerSide = strongerSide ^ 1;
Debug.Assert(pos.non_pawn_material(strongerSide) == ValueC.VALUE_ZERO);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.PAWN) >= 2);
Debug.Assert(pos.non_pawn_material(weakerSide) == ValueC.VALUE_ZERO);
Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.PAWN) == 0);
Square ksq = pos.king_square(weakerSide);
Bitboard pawns = pos.pieces_PTC(PieceTypeC.PAWN, strongerSide);
// Are all pawns on the 'a' file?
if ((pawns & ~Constants.FileABB) == 0)
{
// Does the defending king block the pawns?
if (Utils.square_distance(ksq, Utils.relative_square(strongerSide, SquareC.SQ_A8)) <= 1
|| (Utils.file_of(ksq) == FileC.FILE_A
&& ((Utils.in_front_bb_CS(strongerSide, ksq)) & pawns) == 0))
return ScaleFactorC.SCALE_FACTOR_DRAW;
}
// Are all pawns on the 'h' file?
else if ((pawns & ~Constants.FileHBB) == 0)
{
// Does the defending king block the pawns?
if (Utils.square_distance(ksq, Utils.relative_square(strongerSide, SquareC.SQ_H8)) <= 1
|| (Utils.file_of(ksq) == FileC.FILE_H
&& ((Utils.in_front_bb_CS(strongerSide, ksq)) & pawns) == 0))
return ScaleFactorC.SCALE_FACTOR_DRAW;
}
return ScaleFactorC.SCALE_FACTOR_NONE;
}
示例9: Endgame_KBPsK
/// K, bishop and one or more pawns vs K. It checks for draws with rook pawns and
/// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
/// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
/// will be used.
internal static ScaleFactor Endgame_KBPsK(Color strongerSide, Position pos)
{
Color weakerSide = strongerSide ^ 1;
Debug.Assert(pos.non_pawn_material(strongerSide) == Constants.BishopValueMidgame);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.BISHOP) == 1);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.PAWN) >= 1);
// No Debug.Assertions about the material of weakerSide, because we want draws to
// be detected even when the weaker side has some pawns.
Bitboard pawns = pos.pieces_PTC(PieceTypeC.PAWN, strongerSide);
File pawnFile = Utils.file_of(pos.pieceList[strongerSide][PieceTypeC.PAWN][0]);
// All pawns are on a single rook file ?
if ((pawnFile == FileC.FILE_A || pawnFile == FileC.FILE_H)
&& (((pawns & ~Utils.file_bb_F(pawnFile))) == 0))
{
Square bishopSq = pos.pieceList[strongerSide][PieceTypeC.BISHOP][0];
Square queeningSq = Utils.relative_square(strongerSide, Utils.make_square(pawnFile, RankC.RANK_8));
Square kingSq = pos.king_square(weakerSide);
if (Utils.opposite_colors(queeningSq, bishopSq)
&& Math.Abs(Utils.file_of(kingSq) - pawnFile) <= 1)
{
// The bishop has the wrong color, and the defending king is on the
// file of the pawn(s) or the adjacent file. Find the rank of the
// frontmost pawn.
Rank rank;
if (strongerSide == ColorC.WHITE)
{
for (rank = RankC.RANK_7; (((Utils.rank_bb_R(rank) & pawns)) == 0); rank--) { }
Debug.Assert(rank >= RankC.RANK_2 && rank <= RankC.RANK_7);
}
else
{
for (rank = RankC.RANK_2; (((Utils.rank_bb_R(rank) & pawns)) == 0); rank++) { }
rank = (rank ^ 7); // HACK to get the relative rank
Debug.Assert(rank >= RankC.RANK_2 && rank <= RankC.RANK_7);
}
// If the defending king has distance 1 to the promotion square or
// is placed somewhere in front of the pawn, it's a draw.
if (Utils.square_distance(kingSq, queeningSq) <= 1
|| Utils.relative_rank_CS(strongerSide, kingSq) >= rank)
return ScaleFactorC.SCALE_FACTOR_DRAW;
}
}
return ScaleFactorC.SCALE_FACTOR_NONE;
}
示例10: Endgame_KBPPKB
/// K, bishop and two pawns vs K and bishop. It detects a few basic draws with
/// opposite-colored bishops.
internal static ScaleFactor Endgame_KBPPKB(Color strongerSide, Position pos)
{
Color weakerSide = strongerSide ^ 1;
Debug.Assert(pos.non_pawn_material(strongerSide) == Constants.BishopValueMidgame);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.BISHOP) == 1);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.PAWN) == 2);
Debug.Assert(pos.non_pawn_material(weakerSide) == Constants.BishopValueMidgame);
Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.BISHOP) == 1);
Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.PAWN) == 0);
Square wbsq = pos.pieceList[strongerSide][PieceTypeC.BISHOP][0];
Square bbsq = pos.pieceList[weakerSide][PieceTypeC.BISHOP][0];
if (!Utils.opposite_colors(wbsq, bbsq))
return ScaleFactorC.SCALE_FACTOR_NONE;
Square ksq = pos.king_square(weakerSide);
Square psq1 = pos.pieceList[strongerSide][PieceTypeC.PAWN][0];
Square psq2 = pos.pieceList[strongerSide][PieceTypeC.PAWN][1];
Rank r1 = Utils.rank_of(psq1);
Rank r2 = Utils.rank_of(psq2);
Square blockSq1, blockSq2;
if (Utils.relative_rank_CS(strongerSide, psq1) > Utils.relative_rank_CS(strongerSide, psq2))
{
blockSq1 = psq1 + Utils.pawn_push(strongerSide);
blockSq2 = Utils.make_square(Utils.file_of(psq2), Utils.rank_of(psq1));
}
else
{
blockSq1 = psq2 + Utils.pawn_push(strongerSide);
blockSq2 = Utils.make_square(Utils.file_of(psq1), Utils.rank_of(psq2));
}
switch (Utils.file_distance(psq1, psq2))
{
case 0:
// Both pawns are on the same file. Easy draw if defender firmly controls
// some square in the frontmost pawn's path.
if (Utils.file_of(ksq) == Utils.file_of(blockSq1)
&& Utils.relative_rank_CS(strongerSide, ksq) >= Utils.relative_rank_CS(strongerSide, blockSq1)
&& Utils.opposite_colors(ksq, wbsq))
return ScaleFactorC.SCALE_FACTOR_DRAW;
else
return ScaleFactorC.SCALE_FACTOR_NONE;
case 1:
// Pawns on adjacent files. Draw if defender firmly controls the square
// in front of the frontmost pawn's path, and the square diagonally behind
// this square on the file of the other pawn.
if (ksq == blockSq1
&& Utils.opposite_colors(ksq, wbsq)
&& (bbsq == blockSq2
|| (((pos.attacks_from_BISHOP(blockSq2) & pos.pieces_PTC(PieceTypeC.BISHOP, weakerSide))) != 0)
|| Math.Abs(r1 - r2) >= 2))
return ScaleFactorC.SCALE_FACTOR_DRAW;
else if (ksq == blockSq2
&& Utils.opposite_colors(ksq, wbsq)
&& (bbsq == blockSq1
|| (((pos.attacks_from_BISHOP(blockSq1) & pos.pieces_PTC(PieceTypeC.BISHOP, weakerSide)))) != 0))
return ScaleFactorC.SCALE_FACTOR_DRAW;
else
return ScaleFactorC.SCALE_FACTOR_NONE;
default:
// The pawns are not on the same file or adjacent files. No scaling.
return ScaleFactorC.SCALE_FACTOR_NONE;
}
}
示例11: Endgame_KBPKB
/// K, bishop and a pawn vs K and a bishop. There are two rules: If the defending
/// king is somewhere along the path of the pawn, and the square of the king is
/// not of the same color as the stronger side's bishop, it's a draw. If the two
/// bishops have opposite color, it's almost always a draw.
internal static ScaleFactor Endgame_KBPKB(Color strongerSide, Position pos)
{
Color weakerSide = strongerSide ^ 1;
Debug.Assert(pos.non_pawn_material(strongerSide) == Constants.BishopValueMidgame);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.BISHOP) == 1);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.PAWN) == 1);
Debug.Assert(pos.non_pawn_material(weakerSide) == Constants.BishopValueMidgame);
Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.BISHOP) == 1);
Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.PAWN) == 0);
Square pawnSq = pos.pieceList[strongerSide][PieceTypeC.PAWN][0];
Square strongerBishopSq = pos.pieceList[strongerSide][PieceTypeC.BISHOP][0];
Square weakerBishopSq = pos.pieceList[weakerSide][PieceTypeC.BISHOP][0];
Square weakerKingSq = pos.king_square(weakerSide);
// Case 1: Defending king blocks the pawn, and cannot be driven away
if (Utils.file_of(weakerKingSq) == Utils.file_of(pawnSq)
&& Utils.relative_rank_CS(strongerSide, pawnSq) < Utils.relative_rank_CS(strongerSide, weakerKingSq)
&& (Utils.opposite_colors(weakerKingSq, strongerBishopSq)
|| Utils.relative_rank_CS(strongerSide, weakerKingSq) <= RankC.RANK_6))
return ScaleFactorC.SCALE_FACTOR_DRAW;
// Case 2: Opposite colored bishops
if (Utils.opposite_colors(strongerBishopSq, weakerBishopSq))
{
// We assume that the position is drawn in the following three situations:
//
// a. The pawn is on rank 5 or further back.
// b. The defending king is somewhere in the pawn's path.
// c. The defending bishop attacks some square along the pawn's path,
// and is at least three squares away from the pawn.
//
// These rules are probably not perfect, but in practice they work
// reasonably well.
if (Utils.relative_rank_CS(strongerSide, pawnSq) <= RankC.RANK_5)
return ScaleFactorC.SCALE_FACTOR_DRAW;
else
{
Bitboard path = Utils.forward_bb(strongerSide, pawnSq);
if ((path & pos.pieces_PTC(PieceTypeC.KING, weakerSide)) != 0)
return ScaleFactorC.SCALE_FACTOR_DRAW;
if (((pos.attacks_from_BISHOP(weakerBishopSq) & path) != 0)
&& Utils.square_distance(weakerBishopSq, pawnSq) >= 3)
return ScaleFactorC.SCALE_FACTOR_DRAW;
}
}
return ScaleFactorC.SCALE_FACTOR_NONE;
}
示例12: Endgame_KBPsK
/// K, bishop and one or more pawns vs K. It checks for draws with rook pawns and
/// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
/// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
/// will be used.
internal static int Endgame_KBPsK(int strongerSide, Position pos)
{
var weakerSide = strongerSide ^ 1;
Debug.Assert(pos.non_pawn_material(strongerSide) == Constants.BishopValueMidgame);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.BISHOP) == 1);
Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.PAWN) >= 1);
// No Debug.Assertions about the material of weakerSide, because we want draws to
// be detected even when the weaker side has some pawns.
var pawns = pos.pieces_PTC(PieceTypeC.PAWN, strongerSide);
var pawnFile = Utils.file_of(pos.pieceList[strongerSide][PieceTypeC.PAWN][0]);
// All pawns are on a single rook file ?
if ((pawnFile == FileC.FILE_A || pawnFile == FileC.FILE_H) && (((pawns & ~Utils.file_bb_F(pawnFile))) == 0))
{
var bishopSq = pos.pieceList[strongerSide][PieceTypeC.BISHOP][0];
var queeningSq = Utils.relative_square(strongerSide, Utils.make_square(pawnFile, RankC.RANK_8));
var kingSq = pos.king_square(weakerSide);
if (Utils.opposite_colors(queeningSq, bishopSq) && Math.Abs(Utils.file_of(kingSq) - pawnFile) <= 1)
{
// The bishop has the wrong color, and the defending king is on the
// file of the pawn(s) or the adjacent file. Find the rank of the
// frontmost pawn.
int rank;
if (strongerSide == ColorC.WHITE)
{
for (rank = RankC.RANK_7; (((Utils.rank_bb_R(rank) & pawns)) == 0); rank--)
{
}
Debug.Assert(rank >= RankC.RANK_2 && rank <= RankC.RANK_7);
}
else
{
for (rank = RankC.RANK_2; (((Utils.rank_bb_R(rank) & pawns)) == 0); rank++)
{
}
rank = (rank ^ 7); // HACK to get the relative rank
Debug.Assert(rank >= RankC.RANK_2 && rank <= RankC.RANK_7);
}
// If the defending king has distance 1 to the promotion square or
// is placed somewhere in front of the pawn, it's a draw.
if (Utils.square_distance(kingSq, queeningSq) <= 1
|| Utils.relative_rank_CS(strongerSide, kingSq) >= rank)
{
return ScaleFactorC.SCALE_FACTOR_DRAW;
}
}
}
// All pawns on same B or G file? Then potential draw
if ((pawnFile == FileC.FILE_B || pawnFile == FileC.FILE_G)
&& (pos.pieces_PT(PieceTypeC.PAWN) & ~Utils.file_bb_F(pawnFile)) == 0
&& pos.non_pawn_material(weakerSide) == 0
&& pos.piece_count(weakerSide, PieceTypeC.PAWN) >= 1)
{
// Get weaker pawn closest to opponent's queening square
Bitboard wkPawns = pos.pieces_PTC(PieceTypeC.PAWN, weakerSide);
Square weakerPawnSq = strongerSide == ColorC.WHITE ? Utils.msb(wkPawns) : Utils.lsb(wkPawns);
Square strongerKingSq = pos.king_square(strongerSide);
Square weakerKingSq = pos.king_square(weakerSide);
Square bishopSq = pos.pieceList[strongerSide][PieceTypeC.BISHOP][0];
// Draw if weaker pawn is on rank 7, bishop can't attack the pawn, and
// weaker king can stop opposing opponent's king from penetrating.
if (Utils.relative_rank_CS(strongerSide, weakerPawnSq) == RankC.RANK_7
&& Utils.opposite_colors(bishopSq, weakerPawnSq)
&& Utils.square_distance(weakerPawnSq, weakerKingSq) <= Utils.square_distance(weakerPawnSq, strongerKingSq))
return ScaleFactorC.SCALE_FACTOR_DRAW;
}
return ScaleFactorC.SCALE_FACTOR_NONE;
}