private void TakeTurn(GameState gameState, bool beginningPlayer) { var board = Board.Parse(gameState.BoardData.ToByteArray(), (int)gameState.BoardWidth, (int)gameState.BoardHeight, beginningPlayer); Console.WriteLine("Opponent played:"); board.Display(); int tilesTotal = board.Width * board.Height; int tilesPlaced = gameState.BoardData.Count(b => b != (byte)'0'); int tilesFree = tilesTotal - tilesPlaced; int depth = 3; /* * int tilesToWin = Math.Min((int)board.Width - maxPlayerScore[0], (int)board.Height - maxPlayerScore[1]); * if(tilesToWin <= 6) * { * depth = 3; * } */ int boardFillAmount = gameState.BoardData.Count(b => b != (byte)'0'); int boardSize = gameState.BoardData.Length; int tilesLeft = boardSize - boardFillAmount; Console.WriteLine("My turn! Calculating..."); Children.Clear(); var root = GameTree(board, null, beginningPlayer, int.MinValue, int.MaxValue, depth, 0, true); Node bestChild = null; if (beginningPlayer) { bestChild = Children.Aggregate((best, cur) => cur.Evaluation > best.Evaluation ? cur : best); } else { bestChild = Children.Aggregate((best, cur) => cur.Evaluation < best.Evaluation ? cur : best); } var end = System.DateTime.Now; Console.WriteLine("Seconds taken for turn: " + Stopwatch.Elapsed.TotalSeconds); var bestMove = new GameTurn() { X1 = bestChild.X1, Y1 = bestChild.Y1, X2 = bestChild.X2, Y2 = bestChild.Y2, }; SubmitTurn(bestMove); Console.WriteLine("Move taken (Eval: " + bestChild.Evaluation + "): "); board.Display(bestMove); Console.WriteLine("---"); }
public void Display(GameTurn myTurn = null) { string firstPlayerMarker = (myToken == 'X' ? green : red) + 'X'; string secondPlayerMarker = (myToken == 'O' ? green : red) + 'O'; var rawToDisplayCharacter = new Dictionary <byte, string>() { { (byte)'0', white + '.' }, { (byte)'1', firstPlayerMarker }, { (byte)'2', secondPlayerMarker } }; StringBuilder sb = new StringBuilder(); for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { if (myTurn != null && (x == myTurn.X1 && y == myTurn.Y1 || x == myTurn.X2 && y == myTurn.Y2)) { sb.Append(yellow + myToken); } else { sb.Append(rawToDisplayCharacter[Data[x, y]]); } } sb.AppendLine(); } sb.Append(white); Console.WriteLine(sb.ToString()); }
public static Board DeepCopyAndAddMove(Board other, GameTurn move, byte b) { var newBoard = DeepCopy(other); newBoard.Data[move.X1, move.Y1] = b; newBoard.Data[move.X2, move.Y2] = b; return(newBoard); }
public Node(int eval, GameTurn move) { Evaluation = eval; if (move == null) { return; } X1 = move.X1; Y1 = move.Y1; X2 = move.X2; Y2 = move.Y2; }
public void SubmitTurn(GameTurn turn) { var cToken = new System.Threading.CancellationToken(); var request = new TurnRequest() { MatchId = matchID, DomGameTurn = turn }; var response = client.SubmitTurn(request, null, null, cToken); if (response.TurnStatus == TurnStatus.InvalidTurn) { Console.WriteLine("Ooops, invalid turn!"); AbortMatch(); } }
public Node GameTree(Board oldBoard, GameTurn move, bool maximizer, int alpha, int beta, int remainingDepth, int depth, bool presort) { Board board; if (move != null) { byte b = maximizer ? (byte)'2' : (byte)'1'; board = Board.DeepCopyAndAddMove(oldBoard, move, b); } else { board = oldBoard; } //board.Display(); //curNode.Board = board; if (GameOver(board)) { if (move == null) { maximizer = !maximizer; } //board.Display(); var eval = (maximizer ? int.MinValue : int.MaxValue) - (maximizer ? (-depth) : (depth)); //Console.WriteLine("^Game Over^ -> " + curNode.Evaluation); return(new Node(eval, move)); } if (remainingDepth == 0) { return(new Node(Heuristic(board, depth), move)); } IEnumerable <GameTurn> possibleMoves; if (presort) { // presort children based on shallow tree Children.Clear(); var tmpRoot = GameTree(oldBoard, move, maximizer, int.MinValue, int.MaxValue, 2, 0, false); possibleMoves = Children.OrderBy(c => c.Evaluation).Select(c => new GameTurn() { X1 = c.X1, X2 = c.X2, Y1 = c.Y1, Y2 = c.Y2 }).ToArray(); if (possibleMoves.Count() < 100) { remainingDepth++; } if (possibleMoves.Count() < 50) { remainingDepth++; } Console.WriteLine("Depth: " + remainingDepth); Children.Clear(); } else { possibleMoves = GetPossibleMoves(board).OrderBy(p => Math.Abs(p.X1 - p.Y1)); } if (!possibleMoves.Any()) { return(new Node(0, move)); } var curNode = new Node(0, move); foreach (var newMove in possibleMoves) { if (Stopwatch.Elapsed.TotalSeconds > 350) { break; } var child = GameTree(board, newMove, !maximizer, alpha, beta, remainingDepth - 1, depth + 1, false); if (depth == 0) { Children.Add(child); } if (maximizer) { alpha = Math.Max(alpha, child.Evaluation); } else { beta = Math.Min(beta, child.Evaluation); } if (beta <= alpha) { curNode.Evaluation = maximizer ? beta : alpha;; return(curNode); } } curNode.Evaluation = maximizer ? alpha : beta; return(curNode); }
public static void ManualPlay(int width, int height, int depth) { var rawBoard = new byte[width * height]; Array.Fill(rawBoard, (byte)'0'); var startingBoard = Board.Parse(rawBoard, width, height, true); var dummyGame = new DominectGame(); dummyGame.InitInternals((int)width, (int)height); string line = ""; do { //System.GC.Collect(); //GC.WaitForPendingFinalizers(); //System.GC.Collect(); line = Console.ReadLine(); if (line.Length == 0) { break; } var coords = line.Split(' '); uint x1 = uint.Parse(coords[0]); uint y1 = uint.Parse(coords[1]); uint x2 = uint.Parse(coords[2]); uint y2 = uint.Parse(coords[3]); startingBoard.Data[x1, y1] = (byte)'1'; startingBoard.Data[x2, y2] = (byte)'1'; var playerMove = new GameTurn { X1 = x1, Y1 = y1, X2 = x2, Y2 = y2 }; dummyGame.Stopwatch.Restart(); dummyGame.Children.Clear(); var start = System.DateTime.Now; var root = dummyGame.GameTree(startingBoard, null, false, int.MinValue, int.MaxValue, depth, 0, true); var end = System.DateTime.Now; Console.WriteLine("Final root value: " + root.Evaluation + " (" + (end - start).TotalSeconds + "s)"); var bestChild = dummyGame.Children.Aggregate((best, cur) => cur.Evaluation < best.Evaluation ? cur : best); var bestMove = new GameTurn() { X1 = bestChild.X1, Y1 = bestChild.Y1, X2 = bestChild.X2, Y2 = bestChild.Y2, }; startingBoard.Data[bestChild.X1, bestChild.Y1] = (byte)'2'; startingBoard.Data[bestChild.X2, bestChild.Y2] = (byte)'2'; //startingBoard.Data[x1, y1] = (byte)'1'; //startingBoard.Data[x2, y2] = (byte)'1'; startingBoard.Display(bestMove); bestChild = null; root = null; } while (line.Length > 0); }