@Override
  public double evaluate(StateObservation oldState, StateObservation newState) {
    List<Observation> movables = StateObservationUtils.getMovablesOfType(newState, itypeOfMovable);
    List<Observation> sinks = StateObservationUtils.getImmovablesOfType(newState, itypeOfSink);

    double dist = calcDistBetweenMovablesAndSinks(movables, sinks, newState.getBlockSize());
    return dist;
  }
  public double[][] generateDistanceMap(StateObservation state) {
    int x = (int) (state.getAvatarPosition().x / state.getBlockSize());
    int y = (int) (state.getAvatarPosition().y / state.getBlockSize());
    int typeId = StateObservationUtils.getAvatarType(state);

    return generateDistanceMap(state, x, y, typeId);
  }
  private double calcDistBetweenMovablesAndSinks(
      List<Observation> movables, List<Observation> sinks, int blocksize) {
    List<Observation> remainingSinks = new LinkedList<>(sinks);
    double totalDist = 0;

    for (Observation movable : movables) {
      if (remainingSinks.isEmpty()) break;

      Observation closestSink =
          StateObservationUtils.selectClosest(remainingSinks, movable.position);
      double distance =
          DistanceUtils.manhattanDistance(closestSink.position, movable.position, blocksize);
      totalDist += distance;

      if (areSinksExclusive) {
        remainingSinks.remove(closestSink);
      }
    }

    return totalDist;
  }