private void performMove(Move move, bool newMovePath = true, bool refreshDesk = true, bool autorunAI = true) { if (newMovePath) { // in case some undo moves were made, clear this history int movesUndoneCnt = movesUndone.Count; while (movesUndoneCnt > 0) { gameMovesHistory.Items.RemoveAt(0); movesUndoneCnt--; } movesUndone.Clear(); } movesDone.Add(move); boardMakeMove(move); desk.makeMove(move); if (refreshDesk) { tableDesk.Refresh(); } incrementGameSteps(); updatePlayerPiecesCnt(rules.getOppositePlayer(desk.getCurrentPlayer())); if (newMovePath) { addGameHistoryMove(move); } if (rules.isGameEnd(desk)) { gameFinished(); return; } desk.setCurrentPlayer(rules.getNextPlayer(desk)); setActivePlayer(desk.getCurrentPlayer(), autorunAI, refreshDesk); }
public Move getBestMove(Desk desk, GameRules rules) { movesInspected = 0; int topMoveScore = int.MinValue; int currentScore = 0; short currentPlayer = desk.getCurrentPlayer(); short oppositePlayer = rules.getOppositePlayer(currentPlayer); bool maximizingPlayer = false; ArrayList topMoves = new ArrayList(); //check game end - both players have some fields and at least one can move if (rules.isGameEnd(desk)) { return(null); } ArrayList possiblePlayerMoves = rules.getPossibleMoves(desk, currentPlayer); if (possiblePlayerMoves.Count == 0) //no possible moves for current player, switch to another player { possiblePlayerMoves = rules.getPossibleMoves(desk, oppositePlayer); oppositePlayer = currentPlayer; maximizingPlayer = !maximizingPlayer; } //loop possible moves foreach (Move move in possiblePlayerMoves) { //try the move and run minimax desk.makeMove(move); currentScore = minimax(desk, rules, depthMax, oppositePlayer, maximizingPlayer); desk.undoMove(move); if (currentScore > topMoveScore) //new top move found { topMoveScore = currentScore; topMoves.Clear(); topMoves.Add(move); } else if (currentScore == topMoveScore) //more moves with same value found { topMoves.Add(move); } } if (!randomMoveSelection) { return((Move)topMoves[0]); } //pick randomly one of the top moves Random r = new Random(); return((Move)topMoves[r.Next(0, topMoves.Count)]); }
public ArrayList getPossibleJumps(Desk desk, int x, int y, short currentPlayer) { ArrayList possibleJumps = new ArrayList(); ArrayList jumpsFound = new ArrayList(); Move newMove; int[,] fields = desk.getFields(); int xIncrement = 0; int yIncrement = 0; int[] targetCoords; short opposite_player = getOppositePlayer(currentPlayer); //loop all possible diretions for jump for (int i = 0; i < directionsJump.Length; i++) { if (directionsJump[i] == GameVar.DIR_UP_LEFT) { xIncrement = -1; yIncrement = 1; } else if (directionsJump[i] == GameVar.DIR_UP) { xIncrement = 0; yIncrement = 1; } else if (directionsJump[i] == GameVar.DIR_UP_RIGHT) { xIncrement = 1; yIncrement = 1; } else if (directionsJump[i] == GameVar.DIR_RIGHT) { xIncrement = 1; yIncrement = 0; } else if (directionsJump[i] == GameVar.DIR_LEFT) { xIncrement = -1; yIncrement = 0; } else if (directionsJump[i] == GameVar.DIR_DOWN_LEFT) { xIncrement = -1; yIncrement = -1; } else if (directionsJump[i] == GameVar.DIR_DOWN) { xIncrement = 0; yIncrement = -1; } else if (directionsJump[i] == GameVar.DIR_DOWN_RIGHT) { xIncrement = 1; yIncrement = -1; } //get target coords of possible jump targetCoords = canJump(fields, x, y, xIncrement, yIncrement, currentPlayer); if (targetCoords == null) //no jump possible { continue; } int targetCoordsX = targetCoords[0]; int targetCoordsY = targetCoords[1]; //create new (master) move, make it on desk and inspect again from new position - in case multiple jump newMove = new Move(x, y, targetCoordsX, targetCoordsY); newMove.addRemoveField(targetCoordsX - xIncrement, targetCoordsY - yIncrement); desk.makeMove(newMove); jumpsFound = getPossibleJumps(desk, targetCoordsX, targetCoordsY, currentPlayer); desk.undoMove(newMove); //multiple jump found if (jumpsFound.Count > 0) { foreach (Move jump in jumpsFound) //loop multiple jump fractals, add for master jump { jump.addOverField(jump.getFrom()[0], jump.getFrom()[1]); jump.addRemoveField(jump.getFrom()[0] - xIncrement, jump.getFrom()[1] - yIncrement); jump.setFrom(x, y); possibleJumps.Add(jump); } } else { possibleJumps.Add(newMove); //no (more) multijumps, add master jump to results } } return(possibleJumps); }
private int minimax(Desk desk, GameRules rules, int depth, short currentPlayer, bool maximizingPlayer) { movesInspected++; short oppositePlayer = rules.getOppositePlayer(currentPlayer); if (rules.isGameEnd(desk)) //check game end - both players have some fields and at least one can move { short nextPlayer = rules.getNextPlayer(desk); if (desk.getPlayerFields(GameVar.PLAYER_WHITE).Count != 0 && desk.getPlayerFields(GameVar.PLAYER_BLACK).Count != 0 && nextPlayer == -1) { return(0); //draw, neither of players can move } if (maximizingPlayer) { return(int.MinValue + depthMax - depth); } return(int.MaxValue - depthMax + depth); } if (depth == 0) //check depth level, return eval of current position { if (maximizingPlayer) { return(-rules.getGameEvaluation(desk, oppositePlayer)); } return(rules.getGameEvaluation(desk, oppositePlayer)); } //get new possible moves, make the moves and call recursively minmax ArrayList possibleMoves = rules.getPossibleMoves(desk, currentPlayer); int bestVal = 0; int currentVal = 0; //current player has no possible moves, play "nothing" and call minimax if (possibleMoves.Count == 0) { if (maximizingPlayer) { bestVal = int.MinValue; currentVal = minimax(desk, rules, depth, oppositePlayer, false); bestVal = Math.Max(bestVal, currentVal); } else { bestVal = int.MaxValue; currentVal = minimax(desk, rules, depth, oppositePlayer, true); bestVal = Math.Min(bestVal, currentVal); } return(bestVal); } if (maximizingPlayer) //current player's best move, looking for the highest rating move { bestVal = int.MinValue; foreach (Move move in possibleMoves) { desk.makeMove(move); currentVal = minimax(desk, rules, depth - 1, oppositePlayer, false); desk.undoMove(move); bestVal = Math.Max(bestVal, currentVal); } } else //opposite player's best move - the worst move for current player, looking for the lowest rating move { bestVal = int.MaxValue; foreach (Move move in possibleMoves) { desk.makeMove(move); currentVal = minimax(desk, rules, depth - 1, oppositePlayer, true); desk.undoMove(move); bestVal = Math.Min(bestVal, currentVal); } } return(bestVal); }