MobilityModule extends Module implements IMobilityModule, IMobilityModuleController { @Override public double costForLevelingToLevel(final LevelType levelType) throws NotAuthenticatedException, NotObservableException { assertObservable(); Tile location = getGameObject().getLocation().get(); double cost = 0; LevelType currentLevel = location.getLevel().getType(); if (levelType == currentLevel) return 0; while (true) { Optional<LevelType> newLevel = currentLevel.up(); if (!newLevel.isPresent()) break; Double currentLevelCost = levelingCost.get( EnumUtils.min( currentLevel, newLevel.get() ) ); if (currentLevelCost == null) return Double.MAX_VALUE; currentLevel = newLevel.get(); cost += currentLevelCost; if (currentLevel == levelType) return cost; } cost = 0; currentLevel = location.getLevel().getType(); while (true) { Optional<LevelType> newLevel = currentLevel.down(); if (!newLevel.isPresent()) break; Double currentLevelCost = levelingCost.get( EnumUtils.min( currentLevel, newLevel.get() ) ); if (currentLevelCost == null) return Double.MAX_VALUE; currentLevel = newLevel.get(); cost += currentLevelCost; if (currentLevel == levelType) return cost; } throw new IllegalArgumentException( "Unsupported level type: " + levelType ); } protected  MobilityModule(final ImmutableResourceCost resourceCost, final int movementSpeed, final Map<LevelType, Double> movementCost,
                             final Map<LevelType, Double> levelingCost); @Override double getRemainingSpeed(); @Override double getMovementSpeed(); @Override double costForMovingInLevel(final LevelType levelType); @Override double costForLevelingToLevel(final LevelType levelType); @Override Leveling leveling(final LevelType levelType); @Override Movement movement(final ITile target); @Override IMobilityModuleController getController(); @Override IMobilityModule getModule();  }
@Test public void testCostForLevelingToLevel() throws Exception { MobilityModule module = MobilityModule.createWithStandardResourceCost() .movementSpeed( 0 ) .movementCost( ImmutableMap.<LevelType, Double>of() ) .levelingCost( ImmutableMap.of( LevelType.GROUND, 1d, LevelType.SKY, 2d ) ); createUnit( testUnitType( "Leveler", module ) ); assertEquals( 0d, module.costForLevelingToLevel( LevelType.GROUND ) ); assertEquals( 1d, module.costForLevelingToLevel( LevelType.SKY ) ); assertEquals( 3d, module.costForLevelingToLevel( LevelType.SPACE ) ); }