package com.lyndir.omicron.api;
import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.lhunath.opal.system.util.*;
import com.lyndir.omicron.api.util.Maybe;
import com.lyndir.omicron.api.util.PathUtils;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;
public class ExtractorModule extends Module implements IExtractorModule, IExtractorModuleController {
@SuppressWarnings("UnusedDeclaration")
private static final Logger logger = Logger.get( ExtractorModule.class );
private final ResourceType resourceType;
private final int speed;
protected ExtractorModule(final ImmutableResourceCost resourceCost, final ResourceType resourceType, final int speed) {
super( resourceCost );
this.resourceType = resourceType;
this.speed = speed;
}
static Builder0 createWithStandardResourceCost() {
return createWithExtraResourceCost( ResourceCost.immutable() );
}
static Builder0 createWithExtraResourceCost(final ImmutableResourceCost resourceCost) {
return new Builder0( ModuleType.EXTRACTOR.getStandardCost().add( resourceCost ) );
}
@Override
public ResourceType getResourceType() {
assertObservable();
return resourceType;
}
@Override
public int getSpeed() {
assertObservable();
return speed;
}
@Override
protected void onReset() {
}
@Override
protected void onNewTurn() {
// Mine some resources.
Tile location = getGameObject().getLocation().get();
Maybe<Integer> availableResources = location.getResourceQuantity( resourceType );
if (!availableResources.isPresent())
// No resources left to mine.
return;
int newAvailableResources = Math.max( 0, availableResources.get() - speed );
int minedResources = availableResources.get() - newAvailableResources;
if (!availableResources.isPresent())
// No speed left for mining.
return;
// Initialize path finding functions.
PredicateNN<IGameObject> foundFunction = gameObject -> {
for (final ContainerModule containerModule : gameObject.getModules( ModuleType.CONTAINER ))
if (containerModule.getAvailable() > 0)
return true;
return false;
};
NNFunctionNN<PathUtils.Step<IGameObject>, Double> costFunction = gameObjectStep -> 1d;
NNFunctionNN<IGameObject, Stream<? extends IGameObject>> neighboursFunction = neighbour -> //
neighbour.getLocation().get().neighbours().stream() //
.map( new Function<ITile, IGameObject>() {
@Override
public IGameObject apply(final ITile tile) {
return tile.getContents().orNull();
}
} ).filter( gameObject -> gameObject != null );
// Find paths to containers and deposit mined resources.
while (minedResources > 0) {
Optional<PathUtils.Path<IGameObject>> path = PathUtils.find( getGameObject(), foundFunction, costFunction,
Constants.MAX_DISTANCE_TO_CONTAINER, neighboursFunction );
if (!path.isPresent())
// No more containers with available capacity.
break;
for (final ContainerModule containerModule : path.get().getTarget().getModules( ModuleType.CONTAINER ))
minedResources -= containerModule.addStock( minedResources );
}
// If we have minedResources left that we weren't able to stock, put them back in the tile (ie. don't extract them).
newAvailableResources += minedResources;
// Update the amount of resources left in the tile after this turn's extraction.
location.setResourceQuantity( resourceType, newAvailableResources );
logger.trc( "unstocked resources: %d %s, left in tile: %d", minedResources, resourceType, newAvailableResources );
}
@Override
public IExtractorModuleController getController() {
return this;
}
@Override
public IExtractorModule getModule() {
return this;
}
@SuppressWarnings({ "ParameterHidesMemberVariable", "InnerClassFieldHidesOuterClassField" })
static class Builder0 {
private final ImmutableResourceCost resourceCost;
private Builder0(final ImmutableResourceCost resourceCost) {
this.resourceCost = resourceCost;
}
Builder1 resourceType(final ResourceType resourceType) {
return new Builder1( resourceType );
}
class Builder1 {
private final ResourceType resourceType;
private Builder1(final ResourceType resourceType) {
this.resourceType = resourceType;
}
ExtractorModule speed(final int speed) {
return new ExtractorModule( resourceCost, resourceType, speed );
}
}
}
}