public static Move[] GetAllMovedByColor(Square[,] Board, CheckerColour color) { List <Move> result = new List <Move>(); for (int x = 0; x < BoardPanel.sizeCheckers; x++) { for (int y = 0; y < BoardPanel.sizeCheckers; y++) { if (Board[y, x].Colour == color) { foreach (Move move in GetOpenSquares(Board, new Point(x, y))) { result.Add(move); } } } } Move[] captured = GetAllMoveCapturedByColor(Board, color); if (captured.Any()) { return(captured); } return(result.ToArray()); }
private void CalculateChildMoves(int recursionLevel, Tree <Move> branch, Move move, Square[,] vBoard) { if (recursionLevel >= AI_MAXPLYLEVEL) { return; } CheckerColour moveColour = vBoard[move.Source.Y, move.Source.X].Colour; //Move the checker vBoard = ExecuteVirtualMove(move, vBoard); //Calculate the other player's moves for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (vBoard[i, j].Colour != moveColour) { foreach (Move otherPlayerMove in Utils.GetOpenSquares(vBoard, new Point(j, i))) { if (vBoard[i, j].Colour != CheckerColour.Empty) { CalculateChildMoves( ++recursionLevel, branch.AddChild(otherPlayerMove), otherPlayerMove, DeepCopy(vBoard)); } } } } } }
private void AdvanceTurn() { _currentTurn = _currentTurn == CheckerColour.Red ? CheckerColour.Black : CheckerColour.Red; // check victory of one side int redCount = 0; int blackCount = 0; for (int i = 0; i < sizeCheckers; i++) { for (int j = 0; j < sizeCheckers; j++) { if (_board[i, j].Colour == CheckerColour.Red) { redCount++; } if (_board[i, j].Colour == CheckerColour.Black) { blackCount++; } } } // If a winner is present if (blackCount == 0 || redCount == 0) { String side = blackCount == 0 ? "rouges" : "noirs"; // display the message and ask the user want to replay if (MessageBox.Show(@"Les " + side + @" ont gagnés voulez-vous rejouer ?", @"Victoire des " + side, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { init_game(); } else { Application.Exit(); } } // Let the AI play if (_ai != null && _ai.Colour == _currentTurn) { Move aiMove = _ai.Process(_board); MoveChecker(aiMove); } if (_ai2 != null && _ai2.Colour == _currentTurn) { Move aiMove = _ai2.Process(_board); MoveChecker(aiMove); } }
private void AdvanceTurn() { if (currentTurn == CheckerColour.Red) { currentTurn = CheckerColour.Black; } else { currentTurn = CheckerColour.Red; } if (AI != null && AI.Colour == currentTurn) { Move aiMove = AI.Process(Board); MoveChecker(aiMove); } }
private static Move[] GetOpenSquares(Square[,] board, Point checker, Move lastMove, List <Point> priorPositions) { if (priorPositions == null) { priorPositions = new List <Point> { checker }; } List <Move> openSquares = new List <Move>(); //Top Left if (board[priorPositions[0].Y, priorPositions[0].X].Colour != CheckerColour.Red || board[priorPositions[0].Y, priorPositions[0].X].King) //Stop regular red pieces from moving backwards { if (IsValidPoint(checker.X - 1, checker.Y - 1)) { if (board[checker.Y - 1, checker.X - 1].Colour == CheckerColour.Empty && lastMove.Destination.X == -1) //Allow immediate empty spaces if it's the first jump { openSquares.Add(new Move(priorPositions[0], checker.X - 1, checker.Y - 1)); } //Check for a capturable piece else if (IsValidPoint(checker.X - 2, checker.Y - 2) && ((checker.X - 2) != lastMove.Destination.X || (checker.Y - 2) != lastMove.Destination.Y) && ((checker.X - 2) != priorPositions[0].X || (checker.Y - 2) != priorPositions[0].Y) && board[checker.Y - 1, checker.X - 1].Colour != board[checker.Y, checker.X].Colour && board[checker.Y - 2, checker.X - 2].Colour == CheckerColour.Empty) { Point newDest = new Point(checker.X - 2, checker.Y - 2); if (!priorPositions.Contains(newDest)) { Move move = new Move(priorPositions[0], newDest); move.Captures.Add(new Point(checker.X - 1, checker.Y - 1)); move.Captures.AddRange(lastMove.Captures); openSquares.Add(move); priorPositions.Add(newDest); //Use recursion to find multiple captures openSquares.AddRange(GetOpenSquares(board, new Point(checker.X - 2, checker.Y - 2), move, priorPositions)); } } } } //Top Right if (board[priorPositions[0].Y, priorPositions[0].X].Colour != CheckerColour.Red || board[priorPositions[0].Y, priorPositions[0].X].King) { if (IsValidPoint(checker.X + 1, checker.Y - 1)) { if (board[checker.Y - 1, checker.X + 1].Colour == CheckerColour.Empty && lastMove.Destination.X == -1) { openSquares.Add(new Move(priorPositions[0], checker.X + 1, checker.Y - 1)); } //Check for a capturable piece else if (IsValidPoint(checker.X + 2, checker.Y - 2) && ((checker.X + 2) != lastMove.Destination.X || (checker.Y - 2) != lastMove.Destination.Y) && ((checker.X + 2) != priorPositions[0].X || (checker.Y - 2) != priorPositions[0].Y) && board[checker.Y - 1, checker.X + 1].Colour != board[checker.Y, checker.X].Colour && board[checker.Y - 2, checker.X + 2].Colour == CheckerColour.Empty) { Point newDest = new Point(checker.X + 2, checker.Y - 2); if (!priorPositions.Contains(new Point(checker.X + 2, checker.Y - 2))) { Move move = new Move(priorPositions[0], newDest); move.Captures.Add(new Point(checker.X + 1, checker.Y - 1)); move.Captures.AddRange(lastMove.Captures); openSquares.Add(move); priorPositions.Add(newDest); //Use recursion to find multiple captures openSquares.AddRange(GetOpenSquares(board, new Point(checker.X + 2, checker.Y - 2), move, priorPositions)); } } } } //Bottom Left if (board[priorPositions[0].Y, priorPositions[0].X].Colour != CheckerColour.Black || board[priorPositions[0].Y, priorPositions[0].X].King) { if (IsValidPoint(checker.X - 1, checker.Y + 1)) { if (board[checker.Y + 1, checker.X - 1].Colour == CheckerColour.Empty && lastMove.Destination.X == -1) { openSquares.Add(new Move(priorPositions[0], checker.X - 1, checker.Y + 1)); } //Check for a capturable piece else if (IsValidPoint(checker.X - 2, checker.Y + 2) && ((checker.X - 2) != lastMove.Destination.X || (checker.Y + 2) != lastMove.Destination.Y) && ((checker.X - 2) != priorPositions[0].X || (checker.Y + 2) != priorPositions[0].Y) && board[checker.Y + 1, checker.X - 1].Colour != board[checker.Y, checker.X].Colour && board[checker.Y + 2, checker.X - 2].Colour == CheckerColour.Empty) { Point newDest = new Point(checker.X - 2, checker.Y + 2); if (!priorPositions.Contains(newDest)) { Move move = new Move(priorPositions[0], newDest); move.Captures.Add(new Point(checker.X - 1, checker.Y + 1)); move.Captures.AddRange(lastMove.Captures); openSquares.Add(move); priorPositions.Add(newDest); //Use recursion to find multiple captures openSquares.AddRange(GetOpenSquares(board, new Point(checker.X - 2, checker.Y + 2), move, priorPositions)); } } } } //Bottom Right if (board[priorPositions[0].Y, priorPositions[0].X].Colour != CheckerColour.Black || board[priorPositions[0].Y, priorPositions[0].X].King) { if (IsValidPoint(checker.X + 1, checker.Y + 1)) { if (board[checker.Y + 1, checker.X + 1].Colour == CheckerColour.Empty && lastMove.Destination.X == -1) { openSquares.Add(new Move(priorPositions[0], checker.X + 1, checker.Y + 1)); } //Check for a capturable piece else if (IsValidPoint(checker.X + 2, checker.Y + 2) && ((checker.X + 2) != lastMove.Destination.X || (checker.Y + 2) != lastMove.Destination.Y) && ((checker.X + 2) != priorPositions[0].X || (checker.Y + 2) != priorPositions[0].Y) && board[checker.Y + 1, checker.X + 1].Colour != board[checker.Y, checker.X].Colour && board[checker.Y + 2, checker.X + 2].Colour == CheckerColour.Empty) { Point newDest = new Point(checker.X + 2, checker.Y + 2); if (!priorPositions.Contains(newDest)) { Move move = new Move(priorPositions[0], newDest); move.Captures.Add(new Point(checker.X + 1, checker.Y + 1)); move.Captures.AddRange(lastMove.Captures); openSquares.Add(move); priorPositions.Add(newDest); //Use recursion to find multiple captures openSquares.AddRange(GetOpenSquares(board, new Point(checker.X + 2, checker.Y + 2), move, priorPositions)); } } } } List <Move> capturesMoves = new List <Move>(); // The color of the player CheckerColour playerColor = board[checker.Y, checker.X].Colour; // The possibility for the king to move int[,] possibility = { { 1, 1 }, { 1, -1 }, { -1, 1 }, { -1, -1 } }; ////King move if ((board[checker.Y, checker.X].King)) { for (int i = 0; i < 4; i++) { int testX = checker.X + possibility[i, 0]; int testY = checker.Y + possibility[i, 1]; List <Move> emptyMove = new List <Move>(); List <Move> capturedMove = new List <Move>(); while (IsValidPoint(testY, testX)) { if (board[testY, testX].Colour == CheckerColour.Empty) { Move move = new Move(new Point(checker.X, checker.Y), new Point(testX, testY)); emptyMove.Add(move); } else { // Position of the king int furtherX = testX + possibility[i, 0]; int furtherY = testY + possibility[i, 1]; // Check if the point to catch is a ennemy // And if it is if (IsValidPoint(furtherX, furtherY) && board[testY, testX].Colour != playerColor && board[furtherY, furtherX].Colour == CheckerColour.Empty) { emptyMove.Clear(); Move move = new Move(new Point(checker.X, checker.Y), new Point(furtherX, furtherY)); move.Captures.Add(new Point(testX, testY)); move.Captures.AddRange(lastMove.Captures); // Add the position openSquares.Add(move); Square[,] copy = board.Clone() as Square[, ]; Square tmp = new Square { Colour = CheckerColour.Empty }; if (copy != null) { copy[checker.Y, checker.X] = tmp; copy[testY, testX] = tmp; copy[furtherY, furtherX] = board[checker.Y, checker.X]; } //Use recursion to find multiple captures capturesMoves.AddRange(GetOpenSquares(board, new Point(furtherX, furtherY), move, priorPositions)); break; } } // Iterate through all the possibility testX += possibility[i, 0]; testY += possibility[i, 1]; } openSquares.AddRange(emptyMove.Any() ? emptyMove : capturedMove); } } // Check Captures foreach (Move move in openSquares) { if (move.Captures.Any()) { capturesMoves.Add(move); } } if (capturesMoves.Any()) { return(capturesMoves.ToArray()); } return(openSquares.ToArray()); }
private int ScoreByChild(Square[,] board, Move move, CheckerColour colour_to_test) { int count = 0; int count_opponent = 0; CheckerColour opponent_color = colour_to_test == CheckerColour.Black ? CheckerColour.Red : CheckerColour.Black; for (int i = 0; i < BoardPanel.sizeCheckers; i++) { for (int j = 0; j < BoardPanel.sizeCheckers; j++) { if (board[j, i].Colour == colour) { count++; } else if (board[j, i].Colour == opponent_color) { count_opponent++; } } } if (count == 0) { return(-999); } if (count_opponent == 0) { return(999); } // Avoid to pass the object by reference Square[,] test_board = DeepCopy(board); // Make the move on the saved board ExecuteVirtualMove(move, test_board); // We get all the possibilities for this state Move[] possibilities = Utils.GetAllMovedByColor(board, colour_to_test); if (possibilities.Count() == 0) { return(0); } int score = ScoreMove(move, board, colour_to_test); // We limit our search at our known states if (memory.ContainsKey(board)) { List <Move> played_moved = memory[board]; // We have not enough information on the state we must try all the possibilites if (played_moved.Count < possibilities.Length) { int indexToGet = played_moved.Any() ? played_moved.Count : 0; played_moved.Add(possibilities[indexToGet]); memory.Remove(board); memory.Add(board, played_moved); Square[,] test_board_bis = DeepCopy(test_board); ExecuteVirtualMove(possibilities[indexToGet], test_board_bis); score += ScoreByChild(test_board, possibilities[indexToGet], opponent_color); } else { foreach (Move test_move in played_moved) { Square[,] test_board_bis = DeepCopy(test_board); ExecuteVirtualMove(test_move, test_board_bis); score += ScoreByChild(test_board, test_move, opponent_color); } } return(score); } else { List <Move> to_play = new List <Move>(); to_play.Add(possibilities[0]); memory.Add(board, to_play); Square[,] test_board_bis = DeepCopy(test_board); ExecuteVirtualMove(possibilities[0], test_board_bis); return(ScoreByChild(test_board, possibilities[0], opponent_color)); } }
private int ScoreMove(Move move, Square[,] board, CheckerColour test_color) { int score = 0; int count_opponent = 0; int count_piece = 0; CheckerColour opponent_color = test_color == CheckerColour.Black ? CheckerColour.Red : CheckerColour.Black; //Offensive traits score += move.Captures.Count * WEIGHT_CAPTUREPIECE; if (move.Captures.Count == 2) { score += WEIGHT_CAPTUREDOUBLE; } if (move.Captures.Count > 2) { score += WEIGHT_CAPTUREMULTI; } //Check King Captures foreach (Point point in move.Captures) { if (board[point.Y, point.X].King) { score += WEIGHT_CAPTUREKING; } } //Check if piece is at risk for (int i = 0; i < BoardPanel.sizeCheckers; i++) { for (int j = 0; j < BoardPanel.sizeCheckers; j++) { if (board[j, i].Colour == test_color) { count_piece++; foreach (Move opponentMove in Utils.GetAllMovedByColor(board, opponent_color)) { if (opponentMove.Captures.Contains(move.Source)) { if (board[move.Source.Y, move.Source.X].King) { score += WEIGHT_KINGATRISK; } else { score += WEIGHT_ATRISK; } } } } if (board[j, i].Colour == opponent_color) { count_opponent++; } } } if (count_opponent == 0) { score += 999; } if (count_piece == 0) { score -= 999; } //Subtract score if we are evaluating an opponent's piece if (board[move.Source.Y, move.Source.X].Colour != test_color) { score *= -1; } Console.WriteLine("Score : " + count_piece + " opponent " + count_opponent); return(score); }