public void FromStringComplexTest() { int count = 100; var rand = new Random(DateTime.Now.Millisecond); while ((count--) > 0) { var board = new BitBoard(); var str = new StringBuilder(64); str.Append('0', 64); var indices = GetRandomBits(rand.Next(64)); foreach (var point in indices) { board.SetBit((Square)(point.Item1 * 8 + point.Item2)); int index = (7 - point.Item1) * 8 + point.Item2; str[index] = '1'; } Assert.AreEqual( board.GetInnerValue(), BitBoardHelper.FromString(str.ToString())); } }
public void Fight(IEnumerable <IEngine> engines, int count = 1) { var i = 0; var sw = Stopwatch.StartNew(); while (i++ < count) { try { engines.PK((e1, e2) => { Console.Title = $"{i} {e1.Name} vs {e2.Name} [{sw.Elapsed}] [{folderName}]"; var board = BitBoard.NewGame(); Fight(e1, e2, board, i); }); Console.WriteLine($"loop {i}"); } catch (Exception ex) { Console.WriteLine($"error:{ex}"); } } sw.Stop(); Console.Title = $"[done!] [{sw.Elapsed}] [{folderName}]"; }
private void AddPawnMoves(ICollection <Move> moves, BitBoard targetSquares, Direction direction, EMoveType type) { if (targetSquares.Empty()) { return; } var piece = EPieceType.Pawn.MakePiece(SideToMove); foreach (var squareTo in targetSquares) { var squareFrom = squareTo - direction; if (squareTo.IsPromotionRank()) { if (Flags.HasFlagFast(Emgf.Queenpromotion)) { AddMove(moves, piece, squareFrom, squareTo, EPieceType.Queen.MakePiece(SideToMove), type | EMoveType.Promotion); } else { for (var promotedPiece = EPieceType.Queen; promotedPiece >= EPieceType.Knight; promotedPiece--) { AddMove(moves, piece, squareFrom, squareTo, promotedPiece.MakePiece(SideToMove), type | EMoveType.Promotion); } } } else { AddMove(moves, piece, squareFrom, squareTo, PieceExtensions.EmptyPiece, type); } } }
public void Fight(IEngine engineA, IEngine engineB, BitBoard board, int index = 0) { var indexText = index.ToString().PadLeft(6, '0'); var targetFile = Path.Combine(fightPath, $"{indexText} {DateTime.Now:yyyy-MM-dd HH-mm} {engineA.Name}-{engineB.Name}.tmp"); FightResult fightResult; using (var cc = ConsoleCopy.Create(targetFile)) { Console.WriteLine("################### Begin #######################"); Console.WriteLine("{0} ({2}) vs {1} ({3})", engineA.Name, engineB.Name, "Black", "White"); fightResult = DoFight(engineA, engineB, board); Console.WriteLine("################### Result #######################"); Console.WriteLine("{0}", fightResult); Console.WriteLine("#################### End #######################"); } var score = fightResult.WinnerName == engineA.Name ? fightResult.Score : -fightResult.Score; var newTargetFile = Path.Combine(fightPath, $"{indexText} {engineA.Name}-{engineB.Name} ({score}) {DateTime.Now:yyyy-MM-dd HH-mm}.txt"); File.Move(targetFile, newTargetFile); }
public void InitialBoardPlacementTest() { var expectedPlaceMent = new Placement( new bool[8, 8] { { false, false, false, false, false, false, false, false }, { false, false, false, false, false, false, false, false, }, { false, false, false, false, false, false, false, false, }, { false, false, false, false, true, false, false, false, }, { false, false, false, true, false, false, false, false, }, { false, false, false, false, false, false, false, false, }, { false, false, false, false, false, false, false, false, }, { false, false, false, false, false, false, false, false, } }, new bool[8, 8] { { false, false, false, false, false, false, false, false }, { false, false, false, false, false, false, false, false, }, { false, false, false, false, false, false, false, false, }, { false, false, false, true, false, false, false, false, }, { false, false, false, false, true, false, false, false, }, { false, false, false, false, false, false, false, false, }, { false, false, false, false, false, false, false, false, }, { false, false, false, false, false, false, false, false, } }); var board = new BitBoard(34628173824, 68853694464); CollectionAssert.AreEqual(expectedPlaceMent.BlackBoard, board.Placement.BlackBoard); CollectionAssert.AreEqual(expectedPlaceMent.WhiteBoard, board.Placement.WhiteBoard); }
public Player() { Board = new BitBoard(); Win = 0; Lost = 0; Draw = 0; }
//private static readonly IEngine deepLearningEngine = new OpeningBookEngine(); public override SearchResult Search(BitBoard board, int depth) { IEngine engine; var empties = board.EmptyPiecesCount(); if (empties.InRange(55, 60)) { engine = openingBookEngine; depth = 8; } else if (empties.InRange(40, 54)) { engine = new MonkeyOpeningEngine(); depth = 8; } else if (empties.InRange(19, 39)) { engine = new MonkeyOpeningEngine(); depth = 8; } else if (empties.InRange(0, 18)) { engine = new MonkeyEndEngine(); depth = empties; } else { throw new Exception($"invalid empties:{empties}"); } engine.UpdateProgress = UpdateProgress; return(engine.Search(board, depth)); }
public static OpeningBookItem Parse(string item) { if (string.IsNullOrEmpty(item)) { return(null); } var sp = item.Split(','); var board = new BitBoard(ulong.Parse(sp[0]), ulong.Parse(sp[1])); var empties = int.Parse(sp[2]); var el = sp[3].Split('/'); var evalList = (from q in el let ms = q.Split(':').Select(int.Parse).ToArray() select new EvalItem { Move = ms[0], Score = ms[1] }).ToList(); return(new OpeningBookItem { Board = board, Empties = empties, EvalList = evalList }); }
// *** OVERRIDES *** // public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { BitBoard pawns = Board.GetPieceTypeBitboard(Game.CurrentSide, PawnType.TypeNumber); while (pawns) { int pawnSquare = pawns.ExtractLSB(); int nextSquare = Board.NextSquare(PredefinedDirections.N + Game.CurrentSide, pawnSquare); if (nextSquare >= 0 && Board[nextSquare] != null && Board[nextSquare].TypeNumber == PawnType.TypeNumber && Board[nextSquare].Player != Game.CurrentSide) { Piece enemyPawn = Board[nextSquare]; // we can only perform the swap if the enemyPawn is not // currently attacking any piece of the current side int attackSquare1 = Board.NextSquare(PredefinedDirections.E, pawnSquare); int attackSquare2 = Board.NextSquare(PredefinedDirections.W, pawnSquare); if ((attackSquare1 < 0 || Board[attackSquare1] == null || Board[attackSquare1].Player != Game.CurrentSide) && (attackSquare2 < 0 || Board[attackSquare2] == null || Board[attackSquare2].Player != Game.CurrentSide)) { // swap move is legal - add it now list.BeginMoveAdd(MoveType.Swap, pawnSquare, nextSquare); Piece myPawn = list.AddPickup(pawnSquare); enemyPawn = list.AddPickup(nextSquare); list.AddDrop(myPawn, nextSquare); list.AddDrop(enemyPawn, pawnSquare); list.EndMoveAdd(25); } } } } }
private SearchResult AnalyzeEndGame(BitBoard board, int turn) { var empties = board.EmptyPiecesCount(); Console.WriteLine($"start to analyze end game. empties:{empties}, color: {turn}"); var sw = Stopwatch.StartNew(); SearchResult sr; if (board.IsGameOver()) { var eval = board.EndDiffCount();; sr = new SearchResult { Score = eval, Message = "game over" }; } else { var endGameEngine = new EdaxEngine(); //new ZebraEngine(); sr = endGameEngine.Search(board, empties); } sw.Stop(); Console.WriteLine($"finish analyzing end game. spent: {sw.Elapsed}"); SaveResult(board, sr); return(sr); }
public void BishopBorderBlocked() { BitBoard border = 0xff818181818181ff; BitBoard borderInner = 0x7e424242427e00; BitBoard corners = 0x8100000000000081; const int expectedCorner = 1; // just a single attack square no matter what const int expectedSide = 2; /* * borderInner (X = set bit) : * * 0 0 0 0 0 0 0 0 * 0 X X X X X X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X X X X X X 0 * 0 0 0 0 0 0 0 0 * */ foreach (var square in border) { var attacks = square.BishopAttacks(borderInner); Assert.False(attacks.Empty()); var expected = corners & square ? expectedCorner : expectedSide; var actual = attacks.Count; Assert.Equal(expected, actual); } }
public void BishopBorderBlocked() { BitBoard border = 0xff818181818181ff; BitBoard borderInner = 0x7e424242427e00; var corners = BitBoards.MakeBitboard(Squares.a1, Squares.a8, Squares.h1, Squares.h8); const int expectedCorner = 1; // just a single attack square no matter what const int expectedSide = 2; /* * borderInner (X = set bit) : * * 0 0 0 0 0 0 0 0 * 0 X X X X X X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X X X X X X 0 * 0 0 0 0 0 0 0 0 * */ foreach (var square in border) { var attacks = square.BishopAttacks(borderInner); attacks.IsEmpty.Should().BeFalse(); var expected = corners & square ? expectedCorner : expectedSide; var actual = attacks.Count; Assert.Equal(expected, actual); } }
public static void Analyze(BitBoard board) { var moves = Rule.FindMoves(board); if (moves.Length > 0) { var bestScore = -64; var bestMove = -1; foreach (var move in moves) { var oppboard = Rule.MoveSwitch(board, move); var own = false; if (!Rule.CanMove(oppboard)) { oppboard = oppboard.Switch(); own = true; } var sr = AnalyzeEndGame(oppboard); var eval = own ? sr.Score : -sr.Score;//opp's score if (eval > bestScore) { bestScore = eval; bestMove = move; } Console.WriteLine($"move:{move} {move.ToNotation()}, score:{eval}, result: {sr}"); } } }
/// <summary> /// Calculate index of pattern (unique id of pattern) /// <para>Trả về index (unique id) của 1 pattern cụ thể (pattern = patternShape & gameBoard)</para> /// </summary> public static int CalculatePatternCode(this PatternShape ps, BitBoard bitBoard) { // ---------- Version của thầy ---------- // var len = ps.ArrayBitCells.Length; // var pattern = new int[len]; // for (var i = 0; i < len; i++) // pattern[i] = bitBoard.GetPieceAt(ps.ArrayBitCells[i]); // // var result = 0; // for (var i = 0; i < len; i++) // result += pattern[len - i - 1] * MathUtils.Power3(i); // ---------- Version của nhóm - ra kết quả giống thầy, nhưng optimized, không cần dùng array ---------- var result = 0; var len = ps.ArrayBitCells.Length; for (var i = 0; i < len; i++) { var cellPos = ps.ArrayBitCells[i]; var cellValue = bitBoard.GetPieceAt(cellPos); result += cellValue * MathUtils.Power3(len - i - 1); } return(result); }
// *** INITIALIZATION *** // #region Initialize public override void Initialize(Game game) { base.Initialize(game); chessGame = (Games.Abstract.GenericChess)game; // determine outpost squares for each player int nSquares = game.Board.NumSquares; outpostSquares = new BitBoard[2] { new BitBoard(nSquares), new BitBoard(nSquares) }; for (int sq = 0; sq < nSquares; sq++) { if (game.Board.InLargeCenter(sq) != 0) { if (game.Board.SquareToLocation(sq).Rank >= game.Board.NumRanks / 2) { outpostSquares[0].SetBit(sq); } if (game.Board.SquareToLocation(sq).Rank <= game.Board.NumRanks / 2) { outpostSquares[1].SetBit(sq); } } } }
public void RookBorderBlocked() { /* * Test purpose : Testing blocked bishop attacks */ BitBoard border = 0xff818181818181ff; BitBoard borderInner = 0x7e424242427e00; BitBoard corners = 0x8100000000000081; const int expectedCorner = 14; const int expectedSide = 8; // 7 to each side and 1 blocked /* * borderInner (X = set bit) : * * 0 0 0 0 0 0 0 0 * 0 X X X X X X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X 0 0 0 0 X 0 * 0 X X X X X X 0 * 0 0 0 0 0 0 0 0 * */ foreach (var square in border) { var attacks = square.GetAttacks(EPieceType.Rook, borderInner); Assert.False(attacks.Empty()); Assert.Equal(corners & square ? expectedCorner : expectedSide, attacks.Count); } }
public static void ValidateDeepLearningResult() { var engine = new MonkeyOthello.Engines.X.EdaxEngine { Timeout = 60, UpdateProgress = (r) => Console.WriteLine(r) }; var file = @"E:\projects\MonkeyOthello\tests\k-dl-32\knowledge\32-2017-03-25-02.k"; var lines = File.ReadAllLines(file); var correct = 0; var i = 0; foreach (var line in lines) { var sp = line.Split(','); var ownp = ulong.Parse(sp[0]); var oppp = ulong.Parse(sp[1]); var eval = int.Parse(sp[2]); var bb = new BitBoard(ownp, oppp); var r = engine.Search(bb, 16); if (eval >= 0 && r.Score >= 0 || eval < 0 && r.Score < 0) { correct++; } if ((i + 1) % 10 == 0) { Console.WriteLine("Correct " + correct + "/" + (i + 1) + ", " + Math.Round(((double)correct / (double)(i + 1) * 100), 2) + "%"); } i++; } }
public static BoardSquare getMagicMoves(BoardSquare position, BoardSquare allPieces, bool isRook) { if (!initialized) { initialize(); initialized = true; } int bitIndex = BitBoard.PositionIndexFromBoardSquare(position); BoardSquare mask, occupancy; int shifts, magicIndex; ulong magicNumber; if (isRook) { mask = occupancyMaskRook[bitIndex]; magicNumber = magicNumberRook[bitIndex]; shifts = magicNumberShiftsRook[bitIndex]; occupancy = allPieces & mask; magicIndex = (int)(((ulong)occupancy * magicNumber) >> shifts); return(magicMovesRook[bitIndex][magicIndex]); } else { mask = occupancyMaskBishop[bitIndex]; magicNumber = magicNumberBishop[bitIndex]; shifts = magicNumberShiftsBishop[bitIndex]; occupancy = allPieces & mask; magicIndex = (int)(((ulong)occupancy * magicNumber) >> shifts); return(magicMovesBishop[bitIndex][magicIndex]); } }
/// <summary> /// Determines which squares forms a fence. First square is always on file A - and will /// perform a depth first verification of its surrounding squares. /// </summary> /// <param name="sq">The square which is currently being looked at</param> /// <returns>true if the square is in the fence</returns> private bool FormsFence(Square sq) { _processed |= sq; // File H is marked as fence if it is reached. if (sq.File == Files.FileH) { _fence |= sq; return(true); } Span <Direction> directions = stackalloc Direction[] { _us.PawnPushDistance(), Directions.East, _them.PawnPushDistance() }; foreach (var direction in directions) { var s = sq + direction; if ((_marked & s).IsEmpty || !(_processed & s).IsEmpty || !FormsFence(s)) { continue; } _fence |= s; return(true); } return(false); }
public override SearchResult Search(BitBoard board, int depth) { var sw = Stopwatch.StartNew(); if (!map.ContainsKey(board)) { throw new KeyNotFoundException(board.ToString()); } var bookItem = map[board]; var bestScore = bookItem.EvalList.Max(c => c.Score); var move = bookItem.EvalList.Where(x => x.Score == bestScore).Select(x => x.Move).First(); //var oppBoard = Rule.MoveSwitch(board, move); sw.Stop(); return(new SearchResult { Move = move, Score = bestScore, Nodes = 1, Process = 1, EvalList = bookItem.EvalList, TimeSpan = sw.Elapsed, }); }
public void PawnPush() { BitBoard fullBoard = 0xffffffffffff00; Player side = 0; var expected = 8; foreach (var square in fullBoard) { var targetPosition = PawnPushDel[side.Side](square.BitBoardSquare()); var toSquare = targetPosition.Lsb(); var distance = toSquare.ToInt() - square.ToInt(); Assert.Equal(expected, distance); } side = ~side; expected = -expected; foreach (var square in fullBoard) { var targetPosition = PawnPushDel[side.Side](square.BitBoardSquare()); var toSquare = targetPosition.Lsb(); var distance = toSquare.ToInt() - square.ToInt(); Assert.Equal(expected, distance); } }
// Copy ctor for a model to a second model public Model(Model copythis) { // Init model as empty this.whites = new List <Piece>(12); this.blacks = new List <Piece>(12); this.board = new BitBoard(); this.WhiteDic = new Dictionary <Vector2Int, Piece>(12); this.BlackDic = new Dictionary <Vector2Int, Piece>(12); // Deep copy each piece foreach (Piece p in copythis.WhiteDic.Values) { this.whites.Add(new Piece(new Vector2Int(p.position.x, p.position.y), p.player)); this.WhiteDic.Add(p.position, new Piece(new Vector2Int(p.position.x, p.position.y), p.player)); } foreach (Piece p in copythis.BlackDic.Values) { this.blacks.Add(new Piece(new Vector2Int(p.position.x, p.position.y), p.player)); this.BlackDic.Add(p.position, new Piece(new Vector2Int(p.position.x, p.position.y), p.player)); } // Copy the board as well this.board = new BitBoard(copythis.board); // Copy the arrays that count the amount of pieces in each col row and diagnoals CopyNumberArrays(copythis); this.WhiteAvg = new Vector2Int(copythis.WhiteAvg.x, copythis.WhiteAvg.y); this.BlackAvg = new Vector2Int(copythis.BlackAvg.x, copythis.BlackAvg.y); this.SumOfDistBlack = copythis.SumOfDistBlack; this.SumOfDistWhite = copythis.SumOfDistWhite; }
public List <MovePerft> Go(BitBoard board, Colour colour, int depth) { var moves = new List <uint>(256); MoveGenerator.Generate(board, colour, moves); var count = 0; var movesView = moves.Select(x => new MoveViewer(x)); var movePerfts = new List <MovePerft>(); foreach (var move in moves) { var moveView = new MoveViewer(move); board.MakeMove(move); var checkers = GetCheckers(board, colour); var nodes = InnerPerft(board, colour.Opposite(), depth - 1); count += nodes; movePerfts.Add(new MovePerft(moveView, nodes)); board.UnMakeMove(move); } return(movePerfts); }
/// <summary> /// Marks the opponent pawn attacks /// </summary> private void MarkTheirPawns() { var(southEast, southWest) = _us.IsWhite ? (Directions.SouthEast, Directions.SouthWest) : (Directions.NorthEast, Directions.NorthWest); _marked |= _theirPawns.Shift(southEast) | _theirPawns.Shift(southWest); }
private static RookBitBoard ComputeBlackRook(RookBitBoard inputRookBB, BitBoard blackPieces, BitBoard allPieces) { RookBitBoard result = new RookBitBoard(ChessPieceColors.Black); result.Bits = Magic.getMagicMoves(inputRookBB.Bits, allPieces.Bits, true); result.Bits &= ~blackPieces.Bits; return(result); }
public int LsbTable(BitBoard bb) { // @ C author Matt Taylor (2003) bb ^= bb - 1; var folded = (uint)(bb.Value ^ (bb.Value >> 32)); return(Lsb64Table[folded * 0x78291ACF >> 26]); }
// Copy ctor public BitBoard(BitBoard b) { this.blacks = b.blacks; this.whites = b.whites; this.board = b.board; this.checkedthis = b.checkedthis; InitDirections(); }
public override SearchResult Search(BitBoard bb, int depth) { var board = V3BoardToV2(bb); var r = Solve(board, 'w'); return(r); }
private static ulong GetLeftRookMask() { var bb = new BitBoard(); bb.SetBit(Square.A1); bb.SetBit(Square.A8); return(bb.GetInnerValue()); }
private IEnumerable <Move> FindOrderedMoves(BitBoard board) { var moves = FindMoves(board); var orderedMoves = moves.OrderBy(m => Rule.DiffMobility(Rule.MoveSwitch(board, m.Index))); return(orderedMoves); }
public static void Analyze(string pattern) { //var pattern = "-X-O------XOXX--OOOXXXX-OOOOXXX-OXXOXXX-O-XX------XX------------O"; var color = 'w'; var board = BitBoard.Parse(pattern, color != 'w'); Analyze(board); }
public void TestAddPositionCoord() { int row = 3; int column = 6; long expectedPos = 0x0000000040000000; BitBoard expected = new BitBoard(expectedPos); BitBoard actual = new BitBoard(); actual.AddPosition(column, row); Assert.AreEqual(expected, actual); }
public void TestContainsPositionCoord() { int row = 3; int column = 6; long expectedPosLong = 0x0000000040000000; BitBoard actual = new BitBoard(); actual.AddPosition(column, row); Assert.IsTrue(actual.Contains(column, row)); Assert.IsTrue(actual.Contains(expectedPosLong)); Assert.IsTrue(actual.Contains(new BoardSquare(column, row))); }
public void TestCtorEmpty() { BitBoard expected = new BitBoard(0); BitBoard actual = new BitBoard(); Assert.AreEqual(expected, actual); }
public void TestCtorPopulated() { BitBoard expected = new BitBoard(1); BitBoard actual = new BitBoard(); Assert.AreNotEqual(expected, actual); }
private static ulong[] GetLowerLongShortMasks() { var leftLongBoard = new BitBoard(); leftLongBoard.SetBit(Square.B1); leftLongBoard.SetBit(Square.C1); leftLongBoard.SetBit(Square.D1); var rightShortBoard = new BitBoard(); rightShortBoard.SetBit(Square.F1); rightShortBoard.SetBit(Square.G1); return new ulong[] {leftLongBoard.GetInnerValue(), rightShortBoard.GetInnerValue()}; }
private static ulong[] GetUpperShortLongMasks() { var leftShortBoard = new BitBoard(); leftShortBoard.SetBit(Square.B8); leftShortBoard.SetBit(Square.C8); var rightLongBoard = new BitBoard(); rightLongBoard.SetBit(Square.E8); rightLongBoard.SetBit(Square.F8); rightLongBoard.SetBit(Square.G8); return new ulong[] {leftShortBoard.GetInnerValue(), rightLongBoard.GetInnerValue()}; }