public void hashDifferentBoards() { var first = BoardFactory.LoadBoardFromFen("rnbqkbnr/pppp1ppp/8/4p3/2B1P3/8/PPPP1PPP/RNBQK1NR b KQkq - 2 2"); var second = BoardFactory.LoadBoardFromFen("rnbqkbnr/pppp1ppp/8/4p3/2B1PP2/8/PPPP2PP/RNBQK1NR b KQkq - 2 2"); Assert.AreNotEqual(HashBoard.hash(first), HashBoard.hash(second)); }
public HashSet <ulong> findTiedBoard(Board board, Stack <Move> history) { Dictionary <ulong, int> occurredPositions = new Dictionary <ulong, int>(); HashSet <ulong> tiedPositions = new HashSet <ulong>(); // take copies so we do not modify the original collection var boardCopy = board.CreateCopy(); Stack <Move> historyCopy = new Stack <Move>(history); var hash = HashBoard.hash(board); while (historyCopy.Count != 0) { if (!occurredPositions.ContainsKey(hash)) { occurredPositions.Add(hash, 0); } // count how many times the position has occured occurredPositions[hash]++; var move = historyCopy.Pop(); boardCopy.UndoMove(move); hash = HashBoard.ApplyMove(board, move, hash); } foreach (var position in occurredPositions) { if (position.Value >= 2) { // when a position occurs 3 times tiedPositions.Add(position.Key); } } return(tiedPositions); }
public void blackAndWhiteDontHashToTheSameValue() { var whiteBoard = BoardFactory.LoadBoardFromFen("r3k2r/8/8/2pP4/8/8/8/R3K2R w KQkq c6 0 2"); var blackBoard = BoardFactory.LoadBoardFromFen("r3k2r/8/8/2pP4/8/8/8/R3K2R b KQkq c6 0 2"); Assert.AreNotEqual(HashBoard.hash(whiteBoard), HashBoard.hash(blackBoard)); }
public void enpassantTargetMakesADifference() { var noEnpassant = BoardFactory.LoadBoardFromFen("rnb1kbnr/1ppp1ppp/p3p3/8/1P1PP2q/5N2/P1P2PPP/RNBQKB1R b KQkq - 1 0"); var enpassant = BoardFactory.LoadBoardFromFen("rnb1kbnr/1ppp1ppp/p3p3/8/1P1PP2q/5N2/P1P2PPP/RNBQKB1R b KQkq b3 1 0"); var enpassantHash = HashBoard.hash(enpassant); Assert.AreNotEqual(HashBoard.hash(noEnpassant), enpassantHash); }
// navnet skifter til noUnionFunction i anden test public void hashFunktion() { ulong combined = 0; var board = ChessGame.StartGame().board; for (int i = 0; i < 1000000; i++) { combined += HashBoard.hash(board); } }
private Board incrementalUpdate(string fen, int fromPosition, int toPosition, Piece promotion = Piece.EMPTY) { var board = BoardFactory.LoadBoardFromFen(fen); var boardHash = HashBoard.hash(board); var move = board.FindMove(fromPosition, toPosition, promotion); var nextBoardHash = HashBoard.ApplyMove(board, move, boardHash); board.Move(move); var expectedHash = HashBoard.hash(board); Assert.AreEqual(expectedHash, nextBoardHash); return(board); }
public void whiteBigPawnMoveBecomesSamePosition() { /* * Starting position (White to play) +---------------+ |r n b q k b n r| 8 |p p p p _ p p p| 7 |_ _ _ _ _ _ _ _| 6 |_ _ _ _ p _ _ _| 5 |_ _ B _ P _ _ _| 4 |_ _ _ _ _ _ _ _| 3 |P P P P _ P P P| 2 |R N B Q K _ N R| 1 +---------------+ * A B C D E F G H * F2 -> F4 +---------------+ |r n b q k b n r| 8 |p p p p _ p p p| 7 |_ _ _ _ _ _ _ _| 6 |_ _ _ _ p _ _ _| 5 |_ _ B _ P P _ _| 4 |_ _ _ _ _ _ _ _| 3 |P P P P _ _ P P| 2 |R N B Q K _ N R| 1 +---------------+ * A B C D E F G H */ var board = BoardFactory.LoadBoardFromFen("rnbqkbnr/pppp1ppp/8/4p3/2B1P3/8/PPPP1PPP/RNBQK1NR w KQkq - 2 2"); var moves = board.GetMoves(); var boardHash = HashBoard.hash(board); var move = moves.FindTargetPosition(BoardStateOffset.F5); var nextBoardHash = HashBoard.ApplyMove(board, move, boardHash); board.Move(move); var expectedHash = HashBoard.hash(board); Assert.AreEqual(expectedHash, nextBoardHash); }
public void canPromote() { /* * Starting position (White to play) +---------------+ |r _ _ _ k _ _ r| 8 |_ _ _ _ _ _ _ _| 7 |_ _ _ _ _ _ _ _| 6 |_ _ p P _ _ _ _| 5 |_ _ _ _ _ _ _ _| 4 |_ _ _ _ _ _ _ _| 3 |_ _ _ _ _ _ _ _| 2 |R _ _ _ K _ _ R| 1 +---------------+ * A B C D E F G H * D5 -> C6 +---------------+ |r _ _ _ k _ _ r| 8 |_ _ _ _ _ _ _ _| 7 |_ _ P _ _ _ _ _| 6 |_ _ _ _ _ _ _ _| 5 |_ _ _ _ _ _ _ _| 4 |_ _ _ _ _ _ _ _| 3 |_ _ _ _ _ _ _ _| 2 |R _ _ _ K _ _ R| 1 +---------------+ * A B C D E F G H */ var board = BoardFactory.LoadBoardFromFen("r3k2r/8/8/2pP4/8/8/8/R3K2R w KQkq c6 0 2"); var moves = board.GetMoves(); var boardHash = HashBoard.hash(board); var move = moves.FindTargetPosition(BoardStateOffset.D5, BoardStateOffset.C6); var nextBoardHash = HashBoard.ApplyMove(board, move, boardHash); board.Move(move); board.UndoMove(move); var previousHash = HashBoard.ApplyMove(board, move, nextBoardHash); Assert.AreEqual(boardHash, previousHash); }
// start by solving your own threads problems // afterwards start solving moves that belong to other that have not been started yet // if there are only started moves left then start working a move that is already beeing worked on (they might have a worse starting minimum score) internal void MinMaxWorker(AITask aiTask) { currentTask = aiTask; Board board = aiTask.board; List <Move> moves = aiTask.moves[aiTask.taskId]; int depth = aiTask.depth; Action <SolvedMove> onMoveComplete = aiTask.onMoveComplete; lock (stateLock) { max = float.MaxValue; min = float.MinValue; alreadySolved.Clear(); begunMoves.Clear(); } bestScore = float.MinValue; boardHash = HashBoard.hash(board); SolvedMove lastSolvedMove = null; // ------------ start working on this threads moves ------------------ foreach (var move in moves) { // check that the other threads have not begun the next move yet if (!alreadySolved.Contains(move) && !begunMoves.Contains(move)) { lastSolvedMove = MinMaxMove(aiTask, move, lastSolvedMove); } } // ------------ start searching for other threads unfinished work -------------- IEnumerable <Move> availableMoves = new List <Move>(); Random random = new Random(); do { availableMoves = aiTask.moves.SelectMany((threadsMoves) => { return(threadsMoves.Where(move => !alreadySolved.Contains(move) && !begunMoves.Contains(move))); }).ToList(); // use random to avoid conflicts var nextMove = availableMoves.RandomElementUsing(random); if (MoveHelper.isValidMove(nextMove)) { lastSolvedMove = MinMaxMove(aiTask, nextMove, lastSolvedMove); } } while (availableMoves.Count() > 0); // ------------ start searching for other threads begun but unfinished work -------------- do { availableMoves = aiTask.moves.SelectMany((threadsMoves) => { return(threadsMoves.Where(move => !alreadySolved.Contains(move))); }).ToList(); // use random to avoid conflicts var nextMove = availableMoves.RandomElementUsing(random); if (MoveHelper.isValidMove(nextMove)) { lastSolvedMove = MinMaxMove(aiTask, nextMove, lastSolvedMove); } } while (availableMoves.Count() > 0); if (lastSolvedMove != null) { aiTask.onMoveComplete(lastSolvedMove); } }
public List <EvaluatedMove> MinMaxList(Board board, int depth, HashSet <ulong> tiedPositions = null, bool maximizing = true, float min = float.MinValue, float max = float.MaxValue) { boardHash = HashBoard.hash(board); if (tiedPositions == null) { tiedPositions = new HashSet <ulong>(); } List <EvaluatedMove> movePoints = new List <EvaluatedMove>(); //var bestMove = MinMaxInternal(board, depth, maximizing, min, max); var bestMove = maximizing ? float.MinValue : float.MaxValue; var moveList = layeredLists[board.VirtualLevel]; moveList.Clear(); var moves = board.GetMoves(moveList); var winner = board.detectWinner(moves); foreach (var move in moves) { byte myTurn = board.IsWhiteTurn; boardHash = HashBoard.ApplyMove(board, move, boardHash); board.Move(move); board.VirtualLevel++; var attacked = board.Attacked(board.GetKingPosition(myTurn), myTurn); if (attacked) { // if the king is under attack after making the move then it is not a valid move, in which case ignore the move board.VirtualLevel--; board.UndoMove(move); boardHash = HashBoard.ApplyMove(board, move, boardHash); continue; } var moveScore = MinMax(board, depth, tiedPositions, !maximizing, min, max); movePoints.Add(new EvaluatedMove() { move = move, score = moveScore, }); board.VirtualLevel--; board.UndoMove(move); boardHash = HashBoard.ApplyMove(board, move, boardHash); if (maximizing) { // optimize for player if (moveScore > bestMove) { bestMove = moveScore; } min = Math.Max(moveScore, min); } else { if (moveScore < bestMove) { bestMove = moveScore; } max = Math.Min(moveScore, max); } } // sort the moves in descending order //movePoints.Sort((a, b) => (a.score < b.score) ? 1 : -1); movePoints = movePoints.OrderBy(move => move.score).Reverse().ToList(); return(movePoints); }
public float MinMax(Board board, int depth, HashSet <ulong> tiedPositions, bool maximizing = true, float min = float.MinValue, float max = float.MaxValue) { // this function boardHash = HashBoard.hash(board); return(MinMaxInteral(board, depth, tiedPositions, maximizing, min, max)); }