public static Move GetBestMove(Board b) { List<Tuple<Board, Move>> possibleNextBoards = new List<Tuple<Board, Move>>(); foreach (Move posMove in b.AllMoves) { possibleNextBoards.Add(new Tuple<Board, Move>(b.MakeMove(posMove.From, posMove.To), posMove)); } List<Tuple<Move, double>> moveScores = new List<Tuple<Move, double>>(); foreach (var posNextBoard in possibleNextBoards) { var bestPossibleBoard = allData.Where(x => x.Item1.WhosMove == posNextBoard.Item1.WhosMove) .OrderBy(x => Similarity.Calculate(x.Item1, posNextBoard.Item1)) .First(); double score = Similarity.Calculate(bestPossibleBoard.Item1, posNextBoard.Item1); moveScores.Add(new Tuple<Move, double>(posNextBoard.Item2, score)); } Move suggestedMove = moveScores.OrderBy(x => x.Item2).First().Item1; return suggestedMove; }
public long GetBoardHash(Board b) { long h = 0; for (int i = 0; i < 64; i++) { if (b.S[i] != null) { int pieceType = (int)b.S[i].PieceType; int pieceColour = (int)b.S[i].Colour; int j = ((pieceType - 1) * 2) + pieceColour; h = h ^ m_Hs[i, j]; } } if (b.WhosMove == Colour.White) h ^= m_Hs[64, 0]; if (b.WhosMove == Colour.Black) h ^= m_Hs[64, 1]; if (b.BlackCanKCastle) h ^= m_Hs[64, 2]; if (b.BlackCanQCastle) h ^= m_Hs[64, 3]; if (b.WhiteCanKCastle) h ^= m_Hs[64, 4]; if (b.WhiteCanQCastle) h ^= m_Hs[64, 5]; return h; }
public Tuple<int, double> GetDepthScoreTuple(Board b) { long hash = GetBoardHash(b); if (m_Zs.ContainsKey(hash)) return m_Zs[hash]; return null; }
private double AlphaBeta(Board b, int depth, double alpha, double beta, int colour, ref Move bestMoveYet) { if (depth == 0) return b.ScoreBoard(); else { if (colour == 1) { for (int i = 0; i < b.AllMovesCount; i++) { Move move = b.AllMoves[i]; double result = AlphaBeta(b.GetBoardAfterMove(move.From, move.To), depth - 1, alpha, beta, -colour, ref bestMoveYet); nodesVisited++; if (result > alpha) { alpha = result; if (depth == MaxAlphaBetaDepth) bestMoveYet = move; } if (beta <= alpha) { betaSkips++; goto skip1; } } skip1: return alpha; } else if (colour == -1) { for (int i = 0; i < b.AllMovesCount; i++) { Move move = b.AllMoves[i]; double result = AlphaBeta(b.GetBoardAfterMove(move.From, move.To), depth - 1, alpha, beta, -colour, ref bestMoveYet); nodesVisited++; if (result < beta) { beta = result; if (depth == MaxAlphaBetaDepth) bestMoveYet = move; //bestMoveYet = move; } if (beta <= alpha) { betaSkips++; goto skip2; } } skip2: return beta; } else throw new ApplicationException(); } throw new ApplicationException(); }
public MainWindow() { InitializeComponent(); CreatePieceBoxes(); board = new Board(); board.SetupStandardBoard(); RenderBoard(board); }
private double Negamax(Board b, int depth, double alpha, double beta, int colour) { Tuple<int, double> tuple = m_Zasher.GetDepthScoreTuple(b); // If the same or better calculation of this state has already been made, use it. if (tuple != null && tuple.Item1 >= depth && depth < MaxNegamaxDepth) { if (depth > 0) hashUsed++; if (depth >= 0) hashUsed++; return colour * tuple.Item2; } if (depth == 0) { double score = b.ScoreBoard(); m_Zasher.SetDepthScoreTuple(b, new Tuple<int, double>(0, score)); hashNotUsed++; return colour * score; } else { for (int i = 0; i < b.AllMovesCount; i++) { Move move = b.AllMoves[i]; Board boardAfterMove = new Board(b); bool moveOk = boardAfterMove.MakeMove(move.From, move.To); if (moveOk) { double score = -Negamax(boardAfterMove, depth - 1, -beta, -alpha, -colour); // Cache this score m_Zasher.AddIfBetter(boardAfterMove, new Tuple<int, double>(depth - 1, colour * score)); nodesVisited++; if (score >= beta) return score; if (score > alpha) { alpha = score; } if (depth == MaxNegamaxDepth) { m_RankedMoves.Add(new Tuple<Move, double>(move, colour * score)); m_Zasher.AddIfBetter(b, new Tuple<int, double>(depth, colour * score)); } } } return alpha; } }
public override Move ComputeBestMove() { for (int i = 0; i < 100; i++) { int r = rand.Next(0, b.AllMovesCount); Move randMove = new Move(b.AllMoves[r].From, b.AllMoves[r].To, -100); Board boardAfterMove = new Board(b); if (boardAfterMove.MakeMove(randMove.From, randMove.To)) return randMove; } throw new ApplicationException("Can't find possible move"); }
public Board(Board currentBoard) { this.BlackCanQCastle = currentBoard.BlackCanQCastle; this.BlackCanKCastle = currentBoard.BlackCanKCastle; this.WhiteCanQCastle = currentBoard.WhiteCanQCastle; this.WhiteCanKCastle = currentBoard.WhiteCanKCastle; this.WhosMove = currentBoard.WhosMove; for (int i = 0; i < 64; i++) { if (currentBoard.S[i] != null) S[i] = new Piece(currentBoard.S[i]); } m_OldBoard = currentBoard; }
internal void AddIfBetter(Board b, Tuple<int, double> tuple) { long hash = GetBoardHash(b); if (m_Zs.ContainsKey(hash)) { // If this position has been calculated to a greater depth, use it instead if (tuple.Item1 > m_Zs[hash].Item1) m_Zs[hash] = tuple; } else { m_Zs[hash] = tuple; } }
public static double Calculate(Board b1, Board b2) { Stats s1 = new Stats(b1); Stats s2 = new Stats(b2); double statSimilarity = GetStatSimilarity(s1, s2); double boardSimilarity = 0; for (int i = 0; i < 63; i++) { if (b1.S[i].Colour == b2.S[i].Colour && b1.S[i].PieceType == b2.S[i].PieceType) boardSimilarity -= PieceValue(b1.S[i].PieceType); } //boardSimilarity = 0; return statSimilarity + boardSimilarity; }
static void Main(string[] args) { string wholeFile = ""; List<Tuple<Board, Move>> allData = new List<Tuple<Board, Move>>(); using(StreamReader fs = new StreamReader(File.OpenRead(".\\Ivanchuk.pgn"))) wholeFile = fs.ReadToEnd(); string[] games = Regex.Split(wholeFile, "\\[Event.*\\]\r\n\r\n"); PgnParser.Parser parser = new PgnParser.Parser(); for (int i = 0; i < 100; i++) { Board board = new Board(); var enu = parser.Parse(games[i]).GetEnumerator(); board.SetupStandardBoard(); while (enu.MoveNext()) { board = board.MakeMove(enu.Current.From, enu.Current.To); allData.Add(new Tuple<Board, Move>(board, enu.Current)); } } Board b = allData[263].Item1; var mostSimilars = allData.Where(x => x.Item1.WhosMove == b.WhosMove). OrderBy(x => Similarity.Calculate(x.Item1, b)).ToList(); Move suggestedMove = new Move(-1, -1); for (int i = 0; i < mostSimilars.Count; i++) { Tuple<Board, Move> tup = mostSimilars[i]; suggestedMove = tup.Item2; if (b.AllMoves.Contains(suggestedMove)) break; } }
static Parser() { string wholeFile = ""; using (StreamReader fs = new StreamReader(File.OpenRead(".\\Ivanchuk.pgn"))) wholeFile = fs.ReadToEnd(); string[] games = Regex.Split(wholeFile, "\\[Event.*\\]\r\n\r\n"); PgnParser.Parser parser = new PgnParser.Parser(); for (int i = 0; i < 100; i++) { Board board = new Board(); var enu = parser.Parse(games[i]).GetEnumerator(); board.SetupStandardBoard(); while (enu.MoveNext()) { allData.Add(new Tuple<Board, Move>(board, enu.Current)); board = board.MakeMove(enu.Current.From, enu.Current.To); } } }
private void HumanMoved() { int oldPos = (int)fromImage.Tag; int destPos = (int)toImage.Tag; try { board = board.MakeMove(oldPos, destPos); Move m = PgnParser.Parser.GetBestMove(board); board = board.MakeMove(m.From, m.To); RenderBoard(board); } catch (ApplicationException e) { MessageBox.Show(e.Message); } fromImage.Opacity = 1f; fromImage = null; toImage.Opacity = 1f; toImage = null; }
private void RenderBoard(Board board) { for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) { Piece piece = board.S[i * 8 + j]; Colour squareColour = i % 2 == j % 2 ? Colour.White : Colour.Black; pieceBoxes[j, i].Source = PieceImages.For(piece.Colour, squareColour, piece.PieceType); } boardCanvas.UpdateLayout(); this.UpdateLayout(); }
private void UpdateUi(Board board) { RenderBoard(board); labelScoreBoard.Content = String.Format("{0:0.00}", computer.Board.ScoreBoard()); //if(!computer.IsThinking) labelComputationTime.Content = String.Format("{0:0.00}s", (float)computer.MsTaken / 1000f); labelWhosTurn.Content = String.Format("Your turn"); }
public void SetDepthScoreTuple(Board b, Tuple<int, double> tuple) { long hash = GetBoardHash(b); m_Zs[hash] = tuple; }
public Stats(Board b) { TotalPossibleMoves = b.AllMoves.Count; for (int i = 0; i < 64; i++) { if(b.S[i].Colour == Colour.White) { switch (b.S[i].PieceType) { case PieceType.Blank: break; case PieceType.Pawn: WPCount++; WPAdvancement += i * i; break; case PieceType.Knight: WNCount++; break; case PieceType.Bishop: WBCount++; WBMobility += b.S[i].ValidMoves.Count; break; case PieceType.Rook: WRCount++; break; case PieceType.Queen: WQCount++; break; } } else if (b.S[i].Colour == Colour.Black) { switch (b.S[i].PieceType) { case PieceType.Blank: break; case PieceType.Pawn: BPCount++; BPAdvancement += (7 - i) * (7 - i); break; case PieceType.Knight: BNCount++; break; case PieceType.Bishop: BBCount++; BBMobility += b.S[i].ValidMoves.Count; break; case PieceType.Rook: BRCount++; break; case PieceType.Queen: BQCount++; break; } } } TotalPieces = WPCount + WNCount + WBCount + WRCount + WQCount + BPCount + BNCount + BBCount + BRCount + BQCount; }
public void MakeMove(int fromPos, int toPos) { if (!Board.MoveIsLegal(fromPos, toPos)) throw new ApplicationException("Move is illegal. Try another"); Board newBoard = new Board(Board); bool isLegal = newBoard.MakeMove(fromPos, toPos); if (isLegal) { m_OldBoards.Push(Board); Board = newBoard; WhosMove = newBoard.WhosMove; } else { throw new ApplicationException("Move is illegal. Try another"); } }
public void BuildInitialBoard() { b = Board.InitialStandardBoard; }
public IEnumerable<Move> Parse(string pgn) { string tmp = RemoveNonsense(pgn); string[] byMoves = SplitIntoMoves(tmp); bool whiteMove = true; Thursday.Board board = new Thursday.Board(); board.SetupStandardBoard(); int curMove = 0; foreach (string move in byMoves) { string[] ms = move.Split(whiteSpaces, StringSplitOptions.RemoveEmptyEntries); if (ms.Length == 0) { // Boring. Just continue } else if (ms.Length == 2) { if (IsEndStatement(ms[0])) goto ended; Move move1 = ParseMove(ms[0], board); board = board.MakeMove(move1.From, move1.To); curMove++; PrintDebug(curMove, board); yield return move1; if (IsEndStatement(ms[1])) goto ended; Move move2 = ParseMove(ms[1], board); board = board.MakeMove(move2.From, move2.To); curMove++; PrintDebug(curMove, board); yield return move2; } else if (ms.Length == 1) { if (IsEndStatement(ms[0])) goto ended; Move move1 = ParseMove(ms[0], board); board = board.MakeMove(move1.From, move1.To); curMove++; PrintDebug(curMove, board); yield return move1; } else if (ms.Length == 3 && IsEndStatement(ms[2])) { Move move1 = ParseMove(ms[0], board); board = board.MakeMove(move1.From, move1.To); curMove++; PrintDebug(curMove, board); yield return move1; Move move2 = ParseMove(ms[1], board); board = board.MakeMove(move2.From, move2.To); curMove++; PrintDebug(curMove, board); yield return move2; goto ended; } else { throw new ApplicationException("Not 0 1 or 2 moves found"); } } ended: ; }
private void RenderBoard(Board board) { for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) { Piece piece; if (m_Flipped) piece = board.S[63 - (i * 8 + j)]; else piece = board.S[i * 8 + j]; Colour squareColour = i % 2 == j % 2 ? Colour.White : Colour.Black; if (piece == null) pieceBoxes[j, i].Source = PieceImages.For(Colour.Blank, squareColour, PieceType.Blank); else pieceBoxes[j, i].Source = PieceImages.For(piece.Colour, squareColour, piece.PieceType); } boardCanvas.UpdateLayout(); this.UpdateLayout(); }