/// <summary> /// minimization process of all possible moves within the /// min level of the minimax tree /// </summary> /// <param name="board"></param> /// <param name="depth"></param> /// <returns></returns> public int min(Board board, int depth, int largest, int lowest) { if (depth == 0 || isEndGameScenario(board)) { this.boardsEvaluated++; return(this.boardEvaluator.evaluate(board, depth)); } int currentLowest = lowest; foreach (Move move in MoveSorter.STANDARD.Sort(board.getCurrentPlayer().getLegalMoves().ToList())) { MoveTransition moveTransition = board.getCurrentPlayer().makeMove(move); if (moveTransition.getMoveStatus().isDone()) { currentLowest = Math.Min(currentLowest, max(moveTransition.getBoard(), calculateQuiescenceDepth(moveTransition.getBoard(), depth), largest, currentLowest)); if (currentLowest <= largest) { this.cutOffsProduced++; break; } } } return(currentLowest); }
public void suggestMove() { this.resetClick(); Move move = this.GameForm.getAI().getMove(this.LogicBoard); MoveTransition trans = this.LogicBoard.CurrentPlayer.makeMove(move); if (trans.getMoveStatus().isDone()) { this.listOfCells[move.getCurrentCoordinate()].BackColor = Color.Cyan; this.listOfCells[move.DesCoordinate].BackColor = Color.Cyan; } }
/// <summary> /// execute the best move based on minimax algorithm /// </summary> /// <param name="board"></param> /// <param name="depth"></param> /// <returns></returns> public Move execute(Board board) { long startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); Move bestMove = MoveFactory.getNullMove(); int largestSeenValue = Int32.MinValue; int lowestSeenValue = Int32.MaxValue; int currentValue; message = String.Concat(board.getCurrentPlayer() + " Thinking with depth = " + searchDepth); int numMoves = board.getCurrentPlayer().getLegalMoves().Count; List <Move> sortedMoves = MoveSorter.EXPENSIVE.Sort(board.getCurrentPlayer().getLegalMoves().ToList()).ToList(); foreach (Move move in sortedMoves) { MoveTransition moveTransition = board.getCurrentPlayer().makeMove(move); this.quiescenceCount = 0; if (moveTransition.getMoveStatus().isDone()) { currentValue = board.getCurrentPlayer().getAlliance().isWhite() ? min(moveTransition.getBoard(), searchDepth - 1, largestSeenValue, lowestSeenValue) : max(moveTransition.getBoard(), searchDepth - 1, largestSeenValue, lowestSeenValue); if (board.getCurrentPlayer().getAlliance().isWhite() && currentValue > largestSeenValue) { largestSeenValue = currentValue; bestMove = move; } else if (board.getCurrentPlayer().getAlliance().isBlack() && currentValue < lowestSeenValue) { lowestSeenValue = currentValue; bestMove = move; if (moveTransition.getBoard().getWhitePlayer().isCheckMate()) { break; } } } } long executionTime = DateTimeOffset.Now.ToUnixTimeMilliseconds() - startTime; return(bestMove); }
/// <summary> /// minimization process of all possible moves within the /// min level of the minimax tree /// </summary> /// <param name="board"></param> /// <param name="depth"></param> /// <returns></returns> public int min(Board board, int depth) { if (depth == 0 || isEndGameScenario(board)) { return(this.boardEvaluator.evaluate(board, depth)); } int lowestSeenValue = Int32.MaxValue; foreach (Move move in board.getCurrentPlayer().getLegalMoves()) { MoveTransition moveTransition = board.getCurrentPlayer().makeMove(move); if (moveTransition.getMoveStatus().isDone()) { int currentValue = max(moveTransition.getBoard(), depth - 1); if (currentValue <= lowestSeenValue) { lowestSeenValue = currentValue; } } } return(lowestSeenValue); }
/// <summary> /// execute the best move based on minimax algorithm /// </summary> /// <param name="board"></param> /// <param name="depth"></param> /// <returns></returns> public Move execute(Board board) { long startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); Move bestMove = MoveFactory.getNullMove(); int largestSeenValue = Int32.MinValue; int lowestSeenValue = Int32.MaxValue; int currentValue; message = String.Concat(board.getCurrentPlayer() + " Thinking with depth = " + searchDepth); int numMoves = board.getCurrentPlayer().getLegalMoves().Count; foreach (Move move in board.getCurrentPlayer().getLegalMoves()) { MoveTransition moveTransition = board.getCurrentPlayer().makeMove(move); if (moveTransition.getMoveStatus().isDone()) { currentValue = board.getCurrentPlayer().getAlliance().isWhite() ? min(moveTransition.getBoard(), searchDepth - 1) : max(moveTransition.getBoard(), searchDepth - 1); if (board.getCurrentPlayer().getAlliance().isWhite() && currentValue >= largestSeenValue) { largestSeenValue = currentValue; bestMove = move; } else if (board.getCurrentPlayer().getAlliance().isBlack()) { lowestSeenValue = currentValue; bestMove = move; } } } long executionTime = DateTimeOffset.Now.ToUnixTimeMilliseconds() - startTime; return(bestMove); }
void CellPanel_Click(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (this.board.SourceCell == null) { this.board.SourceCell = this.board.LogicBoard.getCell(this.cellID); this.board.MovePiece = this.board.SourceCell.getPiece(); //Check if cell contains piece if (this.board.MovePiece == null) { this.board.SourceCell = null; } //Check if player click their alliance pieces else if (this.board.LogicBoard.CurrentPlayer.getAlliance() != this.board.MovePiece.getSide()) { this.board.SourceCell = null; } else { this.hightlight(); this.hightlightLegalMoves(); } } else { this.board.DesCell = this.board.LogicBoard.getCell(this.cellID); Move move = MoveFactory.createMove(this.board.LogicBoard, this.board.SourceCell.getCellCoordinate(), this.board.DesCell.getCellCoordinate()); if (move.isPromote()) { this.choosePiece((PawnPromotionMove)move); } if (move != ChessEngine.Move.NULL_MOVE) { MoveTransition transition = this.board.LogicBoard.CurrentPlayer.makeMove(move); if (transition.getMoveStatus().isDone()) { this.board.executeMove(transition, move); move = this.board.GameForm.getAI().getMove(this.board.LogicBoard); if (move != ChessEngine.Move.NULL_MOVE) { transition = this.board.LogicBoard.CurrentPlayer.makeMove(move); if (transition.getMoveStatus().isDone()) { this.board.executeMove(transition, move); } } } else { //Clear source cell and legal cells that has been click; this.board.resetClick(); } } } } if (e.Button == MouseButtons.Right) { this.board.resetClick(); } }
/// <summary> /// move the selected chess piece /// </summary> /// <param name="tileCoordinate"></param> /// <param name="x"></param> /// <param name="y"></param> private void moveChessPiece(int tileCoordinate, int x, int y) { if (sourceTile == null) { return; } destinationTile = board.getTile(tileCoordinate); Move move = Move.MoveFactory.createMove(board, sourceTile.getTileCoordinate(), destinationTile.getTileCoordinate()); MoveTransition transition = board.getCurrentPlayer().makeMove(move); if (transition.getMoveStatus().isDone()) { board = transition.getBoard(); moveLog.addMove(move); //Add the move to the move log Debug.Log(moveLog.getMoves()[moveLog.getMoves().Count - 1]); Debug.Log(board); ChessPiece opponentPiece; //Check for EnPasssant if (move.isEnPassantMove()) { int attackedPieceCoordinate = move.getAttackedPiece().getPiecePosition(); var pair = GetXAndY(attackedPieceCoordinate); opponentPiece = chessPieces[pair.Key, pair.Value]; } else { opponentPiece = chessPieces[x, y]; } //Destroy the captured piece if (opponentPiece != null) { activeChessPieces.Remove(opponentPiece.gameObject); Destroy(opponentPiece.gameObject); } //Check for pawn promotion if (move.isPawnPromotion()) { //Exchange the pawn piece for a queen piece activeChessPieces.Remove(selectedChessPiece.gameObject); Destroy(selectedChessPiece.gameObject); if (move.getMovedPiece().getPieceAlliance().isWhite()) { //White Queen SpawnChessPiece(7, x, y); selectedChessPiece = chessPieces[x, y]; } else { //Black Queen SpawnChessPiece(1, x, y); selectedChessPiece = chessPieces[x, y]; } } chessPieces[selectedChessPiece.CurrentX, selectedChessPiece.CurrentY] = null; selectedChessPiece.transform.position = GetTileCenter(x, y); selectedChessPiece.SetPosition(x, y); chessPieces[x, y] = selectedChessPiece; //Check for king castle if (move.isCastlingMove()) { //If this is a castling move then move the rook to the destination coordinate as well Move.CastleMove castleMove = (Move.CastleMove)move; int rookSource = castleMove.getCastleRookStart(); int rookDestination = castleMove.getCastleRookDestination(); var rookStart = GetXAndY(rookSource); var rookEnd = GetXAndY(rookDestination); selectedChessPiece = chessPieces[rookStart.Key, rookStart.Value]; chessPieces[selectedChessPiece.CurrentX, selectedChessPiece.CurrentY] = null; selectedChessPiece.transform.position = GetTileCenter(rookEnd.Key, rookEnd.Value); selectedChessPiece.SetPosition(rookEnd.Key, rookEnd.Value); chessPieces[rookEnd.Key, rookEnd.Value] = selectedChessPiece; } if (board.getCurrentPlayer().isCheckMate()) { EndGame(); return; } if (gameSetup.isAIPlayer(getGameBoard().getCurrentPlayer()) && !getGameBoard().getCurrentPlayer().isCheckMate() && !getGameBoard().getCurrentPlayer().isStaleMate()) { aiMove = new Job(board); aiMove.Start(); StartCoroutine(aiCoroutine()); //StartThreadedFunction(() => { AiMove(board); }); //nonThreadAiMove(board); } //moveMadeUpdate(PlayerType.HUMAN); } BoardHighlights.Instance.hideHighlights(); sourceTile = null; destinationTile = null; movedPiece = null; selectedChessPiece = null; }