private void startAIComputing(object sender, DoWorkEventArgs e) { // run ai with its own desk, while computing the desk is modified Desk aiDesk = new Desk(rules.getDeskSize(), rules.getPiecesPerPlayer()); aiDesk.setPlayerPieces(desk.getPlayerFields(GameVar.PLAYER_WHITE), GameVar.PLAYER_WHITE); aiDesk.setPlayerPieces(desk.getPlayerFields(GameVar.PLAYER_BLACK), GameVar.PLAYER_BLACK); aiDesk.setCurrentPlayer(desk.getCurrentPlayer()); aiMove = engine.getBestMove(aiDesk, rules); }
public bool isGameEnd(Desk desk) { int fieldsBlackCnt = desk.getPlayerFields(GameVar.PLAYER_BLACK).Count; int fieldsWhiteCnt = desk.getPlayerFields(GameVar.PLAYER_WHITE).Count; if (fieldsBlackCnt == 0 || fieldsWhiteCnt == 0) { return(true); } if (getPossibleMoves(desk, GameVar.PLAYER_WHITE, true).Count > 0) { return(false); } if (getPossibleMoves(desk, GameVar.PLAYER_BLACK, true).Count > 0) { return(false); } return(true); }
public int getGameEvaluation(Desk desk, short player) { int whitePiecesCnt = desk.getPlayerFields(GameVar.PLAYER_WHITE).Count; int blackPiecesCnt = desk.getPlayerFields(GameVar.PLAYER_BLACK).Count; int piecesDifference = 0, piecesPositionVal = 0, x, y; //white player if (player == GameVar.PLAYER_WHITE) { if (evalPiecePosition) { piecesPositionVal += getPiecesPositionEvaluation(desk.getPlayerFields(GameVar.PLAYER_WHITE)); } if (blackPiecesCnt == 0 && whitePiecesCnt > 0) { return(int.MaxValue); } if (whitePiecesCnt == 0 && blackPiecesCnt > 0) { return(int.MinValue); } piecesDifference = whitePiecesCnt - blackPiecesCnt; } else //black player { if (evalPiecePosition) { piecesPositionVal += getPiecesPositionEvaluation(desk.getPlayerFields(GameVar.PLAYER_BLACK)); } if (whitePiecesCnt == 0 && blackPiecesCnt > 0) { return(int.MaxValue); } if (blackPiecesCnt == 0 && whitePiecesCnt > 0) { return(int.MinValue); } piecesDifference = blackPiecesCnt - whitePiecesCnt; } return(piecesDifference * piecesDifferenceWeight + piecesPositionVal * piecesPositionWeight); }
public ArrayList getPossibleMoves(Desk desk, short currentPlayer, bool firstMoveOnly = false) { int[,] fields = desk.getFields(); int x, y, size = desk.getSize(); ArrayList possibleMoves = new ArrayList(); bool forcedMoves = false; short opositePlayer = getOppositePlayer(currentPlayer); ArrayList playerFields = null; ArrayList playerFieldsCopy = new ArrayList(); //get current player fields if (currentPlayer == GameVar.PLAYER_WHITE) { playerFields = desk.getPlayerFields(GameVar.PLAYER_WHITE); } else if (currentPlayer == GameVar.PLAYER_BLACK) { playerFields = desk.getPlayerFields(GameVar.PLAYER_BLACK); } //make player_fields_copy, because while move inspected player_fields change foreach (var field in playerFields) { playerFieldsCopy.Add(field); } int playerFieldsCnt = playerFieldsCopy.Count; for (int i = 0; i < playerFieldsCnt; i++) //loop player fields { x = (int)(playerFieldsCopy[i] as Array).GetValue(0); y = (int)(playerFieldsCopy[i] as Array).GetValue(1); //get possible jumps ArrayList possible_jumps = getPossibleJumps(desk, x, y, currentPlayer); if (possible_jumps.Count > 0) { if (!forcedMoves) //forced jump found, do not inspect normal moves anymore { possibleMoves.Clear(); forcedMoves = true; } foreach (Move jump in possible_jumps) { addMove(possibleMoves, jump); //add jump move to results } if (firstMoveOnly) { return(possibleMoves); } } if (!forcedMoves) //inspect normal moves only when no forced jump found { int newX = 0; int newY = 0; //loop normal moves directions for (int k = 0; k < directionsNormal[currentPlayer].Length; k++) { if (directionsNormal[currentPlayer][k] == GameVar.DIR_UP) { newX = x; newY = y + 1; } else if (directionsNormal[currentPlayer][k] == GameVar.DIR_UP_LEFT) { newX = x - 1; newY = y + 1; } else if (directionsNormal[currentPlayer][k] == GameVar.DIR_UP_RIGHT) { newX = x + 1; newY = y + 1; } else if (directionsNormal[currentPlayer][k] == GameVar.DIR_DOWN) { newX = x; newY = y - 1; } else if (directionsNormal[currentPlayer][k] == GameVar.DIR_DOWN_LEFT) { newX = x - 1; newY = y - 1; } else if (directionsNormal[currentPlayer][k] == GameVar.DIR_DOWN_RIGHT) { newX = x + 1; newY = y - 1; } if (GameVar.isValidField(newX, newY, deskSize) && fields[newX, newY] == GameVar.FIELD_EMPTY) { addMove(possibleMoves, x, y, newX, newY); //add normal move to results if (firstMoveOnly) { return(possibleMoves); } } } } } return(possibleMoves); }
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); }