@Override
  public BattleResult resolveBattle(Piece attacker, Piece defender) {
    if (defender.getType().equals(PieceType.FLAG)) {
      state.setWinner(attacker.getColor());
      return BattleResult.VICTORY;
    }
    if (attacker.getType().equals(PieceType.MINER) && defender.getType().equals(PieceType.BOMB)) {
      return BattleResult.VICTORY;
    }
    if (attacker.getType().equals(PieceType.SPY) && defender.getType().equals(PieceType.MARSHAL)) {
      return BattleResult.VICTORY;
    }

    if (attacker.getType().getRank() < defender.getType().getRank()) {
      return BattleResult.VICTORY;
    }
    if (attacker.getType().getRank() == defender.getType().getRank()) {
      return BattleResult.DRAW;
    }
    return BattleResult.DEFEAT;
  }
  @Override
  public Piece makeMove(Position source, Position destination) throws StrategyException {
    if (source.equals(destination)) {
      throw new StrategyException("destination must be different from source");
    }
    if (source.isDiagonal(destination)) {
      throw new StrategyException("Pieces cannot move diagonally");
    }
    if (!state.getBoard().isOccupied(source)) {
      throw new StrategyException("source must be occupied by a piece");
    }
    if (state.isOver()) {
      throw new StrategyException("Game is already over");
    }

    // change turn/dont double move
    if (state.getBoard().getPieceAt(source).getColor() != state.getTurn()) {
      throw new StrategyException("not your turn");
    }

    if (state.getTurn() == PlayerColor.RED) {
      state.setTurn(PlayerColor.BLUE);
    } else {
      state.setTurn(PlayerColor.RED);
    }

    final Piece sourcePiece = state.getBoard().getPieceAt(source);
    final Piece destinationPiece = state.getBoard().getPieceAt(destination);

    final int distance = state.getBoard().getDistance(source, destination);
    final int range = sourcePiece.getType().getRange();
    if (range >= 0 && distance > range) {
      throw new StrategyException("Cannot move piece farther than its range");
    }

    if (sourcePiece.getColor().equals(destinationPiece.getColor())) {
      throw new StrategyException("Cannot move onto a friendly piece");
    }

    if (!state.getBoard().isPathValid(source, destination)) {
      throw new StrategyException("Cannot move through occupied spaces or water");
    }

    BattleResult result = BattleResult.VICTORY;
    if (state.getBoard().isOccupied(destination)) {
      result = resolveBattle(sourcePiece, destinationPiece);
    }

    switch (result) {
      case VICTORY:
        state.getBoard().putPieceAt(destination, sourcePiece);
        state.getBoard().putPieceAt(source, Piece.NULL_PIECE);
        break;
      case DRAW:
        state.getBoard().putPieceAt(destination, Piece.NULL_PIECE);
        // fallthrough
      case DEFEAT:
        state.getBoard().putPieceAt(source, Piece.NULL_PIECE);
        break;
    }
    // if moves>10 end game
    state.setNumMoves(state.getNumMoves() + 1);
    if (state.getNumMoves() >= 10) {
      state.setWinner(PlayerColor.BLUE);
    }
    return state.getBoard().getPieceAt(destination);
  }