package com.lyndir.omicron.api; import com.google.common.collect.*; import com.lyndir.lhunath.opal.math.Side; import com.lyndir.lhunath.opal.math.Vec2; import com.lyndir.lhunath.opal.system.error.AlreadyCheckedException; import com.lyndir.omicron.api.util.Maybe; import com.lyndir.omicron.api.util.Maybool; import java.util.Optional; /** * <i>10 07, 2012</i> * * @author lhunath */ public interface ITile extends GameObservable { /** * @return The object currently on this tile, if one. */ Maybe<? extends IGameObject> getContents(); /** * @return The position of a tile within its level among the other tiles. */ Vec2 getPosition(); /** * @return The level that hosts this tile. */ ILevel getLevel(); /** * @param resourceType The resource tile to query availability for. * * @return The amount of resources still available on this tile of the given resource type. */ default Maybe<Integer> getResourceQuantity(final ResourceType resourceType) { return getQuantitiesByResourceType().get( resourceType ); } /** * @return The quantities of the remaining resources available on this tile mapped by their resource type. */ ImmutableMap<ResourceType, Maybe<Integer>> getQuantitiesByResourceType(); /** * @param side The side of this tile to find the neighbour tile at. * * @return Find the tile in this tile's level adjacent to this tile on the given side. */ default Optional<? extends ITile> neighbour(final Side side) { return getLevel().getTile( getPosition().translate( side.getDelta() ) ); } /** * @return Find all the tiles adjacent to this tile. */ default ImmutableCollection<? extends ITile> neighbours() { ImmutableList.Builder<ITile> neighbours = ImmutableList.builder(); for (final Side side : Side.values()) { Optional<? extends ITile> neighbour = neighbour( side ); if (neighbour.isPresent()) neighbours.add( neighbour.get() ); } return neighbours.build(); } /** * @param distance The maximum distance from this tile of the neighbouring tiles to return. * * @return Find all the tiles near this tile at a maximum given distance. */ default ImmutableCollection<? extends ITile> neighbours(final int distance) { ImmutableList.Builder<ITile> neighbours = ImmutableList.builder(); // FIXME: Not correct. for (int dx = -distance; dx <= distance; ++dx) for (int dy = Math.max( -distance, -dx - distance ); dy <= Math.min( distance, -dx + distance ); ++dy) neighbours.add( getLevel().getTile( getPosition().translate( dx, dy ) ).get() ); return neighbours.build(); } /** * @param target The game object to check the tile for. * * @return Determine whether the given game object is on this tile. */ @SuppressWarnings("NonBooleanMethodNameMayNotStartWithQuestion") default Maybool contains(final IGameObject target) { Maybe<? extends IGameObject> contents = getContents(); switch (contents.presence()) { case EMPTY: return Maybool.no(); case UNKNOWN: return Maybool.unknown(); case PRESENT: return Maybool.from( contents.get().equals( target ) ); } throw new AlreadyCheckedException(); } /** * @return true if this tile is visible to the current player and has no contents. */ @SuppressWarnings("NonBooleanMethodNameMayNotStartWithQuestion") default Maybool isAccessible() { Maybe<? extends IGameObject> contents = getContents(); switch (contents.presence()) { case EMPTY: return Maybool.yes(); case UNKNOWN: return Maybool.unknown(); case PRESENT: return Maybool.no(); } throw new AlreadyCheckedException(); } }