//Find the best move to do and execute it on the board public void DoComputerTurn() { //Find the list of the best moves to do (1 per unit). List <Move> moves = ComputerPlayer.BestMoves(); foreach (Move m in moves) { //Ignore duplicate movement moves if (m is MovementMove) { MovementMove mm = m as MovementMove; if (tiles[mm.x, mm.y].unitOn != null) { continue; } } //Execute every move m.Execute(false); } playerTurn = true; turnButton.texture = Assets.myTurn; Console.WriteLine("Computer turn ended, player map control: " + DepthSearch.CalculateMapControl(tiles)); }
/// <summary> /// Find the best move for a unit to execute on a board, using Depth first search, forcasting a few moves ahead. /// </summary> /// <param name="u">The unit to move</param> /// <param name="board">The board for the unit to move on</param> /// <param name="level">The amount of levels the algorithm still needs to go through</param> /// <returns>The best move for unit u and the amount of map control this move will yield eventually (using DFS)</returns> public static Tuple<Move,int> GetBestMoveMin(Unit u, Tile[,] board, int level) { Tile[,] clone; int minControl = 1000; Move best = null; //Get all moves possible and check each one foreach (Move m in u.GetMoves(board)) { //Clone the boarad clone = CopyBoard(board); //Find the cloned unit Unit cloneUnit = clone[u.TileX, u.TileY].UnitsOn[0]; //Check that the move can actually be executed. If it can, execute it on the clone. if (cloneUnit.type.GetMaxMoves() < m.CostBoard(clone)) continue; m.Execute(false, clone); int control; //If this is the final search level, find the map control of the current state. if (level == 1) control = CalculateMapControl(clone); //Otherwise, get the best move after this one and the control will be the result from there. else control = GetBestMoveMin(cloneUnit, clone, level - 1).Control(); //If the control of this move is better than the best one found so far, switch them. if (control < minControl) { minControl = control; best = m; } //If the current move is equal control-wise to the best so far, prioritize attack moves, or movement moves to places //Closer to the enemy base. else if (control == minControl) { if (m is AttackMove) { minControl = control; best = m; } else if (best is MovementMove && m is MovementMove) { MovementMove bb = best as MovementMove; MovementMove mm = m as MovementMove; if (mm.x + mm.y < bb.x + bb.y) { minControl = control; best = m; } } } } //Return the best move found and the control it yields. return new Tuple<Move, int>(best, minControl); }
/// <summary> /// Create a button for a movement move. /// </summary> /// <param name="move">The movement move to create a button to trigger.</param> private void GenerateMovementButton(MovementMove move) { //The location for drawing the button. int xPixels = move.x * Tile.TILE_WIDTH + Game.instance.xScroll; int yPixels = move.y * Tile.TILE_HEIGHT + Game.instance.yScroll; //Only create the button if there are enough moves left for making the move. if (CanMove(move.cost)) { Button select = new Button(new Rectangle(xPixels, yPixels, Tile.TILE_WIDTH, Tile.TILE_HEIGHT), Assets.greenHighlight); select.RightClick += () => { move.Execute(true); SubtractMove(move.cost); foreach (Button b in movementButtons) { b.Delete(); } }; Game.instance.selectionButtons.Add(select); movementButtons.Add(select); } }
public override ReadOnlyCollection <Move> GetCandidateMoves(BoardState board, ChessPiece piece) { List <Move> CandidateMoves = new List <Move>(); if (!piece.HasMoved) { int RookRow = piece.Row + YRookSearch * RookSearchRange; int RookColumn = piece.Column + XRookSearch * RookSearchRange; if (board.ValidTile(RookRow, RookColumn)) { Tile RookTile = board[RookRow, RookColumn]; if (!RookTile.IsVacant) { if (RookTile.Piece is Rook) { if (!RookTile.Piece.HasMoved) { bool ValidPieceConditions = true; for (int i = 1; i < RookSearchRange; i++) { int SearchedRow = piece.Row + i * YRookSearch; int SearchedColumn = piece.Column + i * XRookSearch; if (board.ValidTile(SearchedRow, SearchedColumn)) { Tile intermediateTile = board[SearchedRow, SearchedColumn]; if (!intermediateTile.IsVacant) { ValidPieceConditions = false; break; } } else { ValidPieceConditions = false; break; } } if (ValidPieceConditions) { if (board.ValidTile(RookRow + YRookMove, RookColumn + XRookMove)) { Tile NewRookTile = board[RookRow + YRookMove, RookColumn + XRookMove]; MovementMove RookMove = new MovementMove(RookTile, NewRookTile); ReadOnlyCollection <Tile> CandidateTiles = GetCandidateTiles(board, piece); foreach (Tile CandidateTile in CandidateTiles) { MovementMove PieceMove = new MovementMove(board[piece.Row, piece.Column], CandidateTile); Move CastleMove = new CastleMove(PieceMove, RookMove); CandidateMoves.Add(CastleMove); } } } //targetting movement squares/in check foreach (Tile tile in board.Tiles) { if (!tile.IsVacant) { if (tile.Piece.Alliance != piece.Alliance) { //NOT DONE } } } } } } } } return(CandidateMoves.AsReadOnly()); }