private BitBoard ComputeDynamicFencedPawns(Player them) { // reverse order of Down var down = them.IsBlack ? Directions.South : Directions.North; var result = BitBoard.Empty; for (File f = Files.FileA; f < Files.FileNb; ++f) { var sq = NextFenceRankSquare(f, them); var b = sq.ForwardFile(them) & _theirPawns; while (!b.IsEmpty) { sq = BitBoards.PopLsb(ref b) + down; if (_pos.GetPiece(sq) == _ourPawn) { result |= sq; } } } return(result); }
/// <summary> /// Computes the fence ranks /// </summary> private void ComputeFenceRanks() { var covered = _fence; while (covered) { var sq = BitBoards.PopLsb(ref covered); var(r, f) = sq.RankFile; _fenceRank[f.AsInt()] = r; } }
public void BitBoardOrALlTest() { var baseSquares = new Square[] { Squares.a1, Squares.a2, Squares.a3, Squares.a4, Squares.a5, Squares.a6, Squares.a7, Squares.a8 }; var bb = BitBoard.Empty.OrAll(baseSquares); while (!bb.IsEmpty) { var s = BitBoards.PopLsb(ref bb); var valid = Array.BinarySearch(baseSquares, s) > -1; Assert.True(valid); } }
/// <summary> /// Computes whether the current position contains a pawn fence which makes the game a draw. /// </summary> /// <returns>true if the game is a draw position - otherwise false</returns> public bool IsBlocked() { // Quick check if there is only pawns and kings on the board It might be possible to // have a minor piece and exchange it into a passing pawn if (_pos.Board.PieceCount(PieceTypes.AllPieces) > _pos.Board.PieceCount(PieceTypes.Pawn) + 2) { return(false); } var up = _us.PawnPushDistance(); MarkOurPawns(up); MarkTheirPawns(); var isFenceFormed = IsFenceFormed(); if (!isFenceFormed) { return(false); } ComputeFenceRanks(); var ourKsq = _pos.GetKingSquare(_us); var theirKsq = _pos.GetKingSquare(_them); if (ourKsq.Rank.RelativeRank(_us) > _fenceRank[ourKsq.File.AsInt()].RelativeRank(_us)) { return(false); } _dynamicPawns |= ComputeDynamicFencedPawns(_them); while (_dynamicPawns) { var sq = BitBoards.PopLsb(ref _dynamicPawns); var(r, f) = sq.RankFile; var rr = sq.RelativeRank(_us); if (r > _fenceRank[f.AsInt()]) { if ((_theirPawns & sq.PassedPawnFrontAttackSpan(_us)).IsEmpty && (theirKsq.File != f || theirKsq.Rank.RelativeRank(_us) < rr)) { return(false); } } else if (_fence & sq) { if (rr >= Ranks.Rank6) { return(false); } if (_pos.GetPiece(sq + _us.PawnDoublePushDistance()) != _theirPawn) { if (theirKsq.File != f || theirKsq.Rank.RelativeRank(_us) < rr) { return(false); } if (f != Files.FileA && _pos.GetPiece(sq + Directions.West) != _ourPawn || BitBoards.PopCount(_ourPawns & PreviousFile(f)) > 1 || (_fixedPawn & (sq + Directions.West)).IsEmpty || (_fence & (sq + Directions.West)).IsEmpty) { return(false); } if (f != Files.FileH && _pos.GetPiece(sq + Directions.East) != _ourPawn || BitBoards.PopCount(_ourPawns & NextFile(f)) > 1 || (_fixedPawn & (sq + Directions.East)).IsEmpty || (_fence & (sq + Directions.East)).IsEmpty) { return(false); } } if ((sq + _us.PawnDoublePushDistance()).PawnAttack(_us) & _theirPawns) { return(false); } if (BitBoards.PopCount(_ourPawns & f) > 1) { return(false); } } else if (r < _fenceRank[f.AsInt()]) { sq += up; r = sq.Rank; rr = sq.RelativeRank(_us); while ((_fence & Square.Make(r, f)).IsEmpty) { var pawnAttacks = sq.PawnAttack(_us); if (_theirPawns & pawnAttacks) { return(false); } if (_pos.GetPiece(sq) == _ourPawn) { break; } sq += up; r = sq.Rank; } if ((_fence & Square.Make(r, f)).IsEmpty || _pos.IsOccupied(sq)) { continue; } if (rr >= Ranks.Rank6) { return(false); } if ((_theirPawns & (sq + _us.PawnDoublePushDistance())).IsEmpty) { if (theirKsq.File != f || theirKsq.Rank.RelativeRank(_us) < rr) { return(false); } if (f != Files.FileA && _pos.GetPiece(sq + Directions.West) != _ourPawn || BitBoards.PopCount(_ourPawns & (f - 1)) > 1 || (_fixedPawn & Square.Make(r, PreviousFile(f))).IsEmpty || (_fence & Square.Make(r, PreviousFile(f))).IsEmpty) { return(false); } if (f != Files.FileH && _pos.GetPiece(sq + Directions.East) != _ourPawn || BitBoards.PopCount(_ourPawns & (f + 1)) > 1 || (_fixedPawn & Square.Make(r, NextFile(f))).IsEmpty || (_fence & Square.Make(r, NextFile(f))).IsEmpty) { return(false); } } if ((sq + up).PawnAttack(_us) & _theirPawns) { return(false); } } } return(true); }