コード例 #1
0
ファイル: NegamaxPlayer.java プロジェクト: Saucistophe/Thud
  @Override
  public void fight(Individual otherIndividual) {
    NegamaxPlayer otherNegamaxPlayer = (NegamaxPlayer) otherIndividual;

    // Get the test ground.
    Board testBoard = initialTestBoard.cloneBoard();

    // Fight until a side wins, or a max number of turns has elapsed.
    boolean myTurn = true;
    int iteration = 0;
    while (testBoard.numberOf(DWARF) > 0 && testBoard.numberOf(TROLL) > 0 && iteration++ < 1000) {
      if (myTurn) {
        makeBestMove(testBoard);
      } else {
        otherNegamaxPlayer.makeBestMove(testBoard);
      }
      myTurn = !myTurn;
    }

    // Update the fitnesses of the players.
    // Since the dwarves play first, the first player, me, scores the dzqrf side.
    int score = testBoard.numberOf(DWARF) - 4 * testBoard.numberOf(TROLL);
    fitness += score;
    otherNegamaxPlayer.fitness -= score;
  }
コード例 #2
0
ファイル: NegamaxPlayer.java プロジェクト: Saucistophe/Thud
  // TODO depends of the board type.
  @Override
  public int evaluate(Board evaluatedBoard) {
    int result;

    int numberOfDwarves = evaluatedBoard.numberOf(DWARF);
    int numberOfTrolls = evaluatedBoard.numberOf(TROLL);

    // Pure material advantage
    int materialAdvantage =
        dwarfMaterialRatio * numberOfDwarves - trollMaterialRatio * numberOfTrolls;
    result = materialAdvantage;

    // Clustering values;
    int dwarfClusteringValue =
        evaluatedBoard
            .getPiecesStream(DWARF)
            .mapToInt(dwarf -> evaluatedBoard.getNearby(DWARF, dwarf.width, dwarf.height).size())
            .sum();
    int trollClusteringValue =
        evaluatedBoard
            .getPiecesStream(TROLL)
            .mapToInt(troll -> evaluatedBoard.getNearby(TROLL, troll.width, troll.height).size())
            .sum();
    result +=
        dwarfClusteringRatio * dwarfClusteringValue - trollClusteringRatio * trollClusteringValue;

    // Mobility
    int dwarfMobilityValue = 0, trollMobilityValue = 0;

    evaluatedBoard
        .getPiecesStream(DWARF)
        .map(pieceToMove -> evaluatedBoard.validMoves(pieceToMove.width, pieceToMove.height, null))
        .mapToInt(List::size)
        .sum();

    trollMobilityValue =
        evaluatedBoard
            .getPiecesStream(TROLL)
            .map(
                pieceToMove ->
                    evaluatedBoard.validMoves(pieceToMove.width, pieceToMove.height, null))
            .mapToInt(List::size)
            .sum();

    result += dwarfMobilityRatio * dwarfMobilityValue - trollMobilityRatio * trollMobilityValue;

    // If there's no piece left, add a big malus/bonus.
    if (numberOfTrolls == 0) {
      result += absoluteVictoryBonus;
    } else if (numberOfDwarves == 0) {
      result -= absoluteVictoryBonus;
    }

    return evaluatedBoard.dwarvesTurn ? result : -result;
  }
コード例 #3
0
ファイル: NegamaxPlayer.java プロジェクト: Saucistophe/Thud
  /**
   * Alpha-Beta Negamax algorithm. Go check on wikipedia!
   *
   * @param evaluatedBoard The board currently evaluated.
   * @param resultBoard (Optional) The board that will store the result of the best move.
   * @param alpha Alpha parameter, to cut some leaves on the multiverse tree.
   * @param beta Alpha parameter, to cut even more leaves on the multiverse tree.
   * @param depth The current depth of the reflexion.
   * @return The best you can do with the worst the other player can do with the best you can do
   *     with...
   */
  public int negaMax(Board evaluatedBoard, Board resultBoard, int alpha, int beta, int depth) {
    // If it's a leaf, evaluate.
    if (depth == MAX_DEPTH
        || evaluatedBoard.numberOf(DWARF) == 0
        || evaluatedBoard.numberOf(TROLL) == 0) {
      return evaluate(evaluatedBoard);
    }

    List<Board> childrenBoards = evaluatedBoard.childrenBoards();
    /* Map<Board, Integer> boardValues = new HashMap<>();
    for (Board childrenBoard : childrenBoards)
    {
    boardValues.put(childrenBoard, evaluate(childrenBoard));
    }

    // Sort those boards with the evaluation method, to evaluate the most interesting moves.
    Collections.sort(childrenBoards, (board1, board2) -> Integer.compare(boardValues.get(board2), boardValues.get(board1))); */

    // Look for the best value on children boards.
    int boardIndex;
    int bestValue = -INFINITY;
    for (boardIndex = 0; boardIndex < childrenBoards.size(); boardIndex++) {
      // Update the progress callback, if any.
      if (depth == 0 && progressCallback != null) {
        progressCallback.accept(100 * boardIndex / childrenBoards.size());
      }

      Board childBoard = childrenBoards.get(boardIndex);
      // Get the score of the child. The negamax, a specific implementation of the Minimax, requires
      // switching and inverting values here.
      int score = -negaMax(childBoard, null, -beta, -alpha, depth + 1);

      if (score > bestValue) {
        bestValue = score;
        // If we're at depth zero, keep track of the best board.
        if (depth == 0) {
          if (resultBoard != null) {
            resultBoard.set(childBoard);
          }
        }
      }

      // Alpha-beta pruning
      alpha = Math.max(alpha, score);
      if (alpha >= beta) {
        break;
      }
    }

    return bestValue;
  }