/*******************************************************************************
* Copyright (c) 2015 - 2017
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*******************************************************************************/
package jsettlers.logic.movable.strategies.specialists;
import jsettlers.common.map.shapes.HexGridArea;
import jsettlers.common.material.ESearchType;
import jsettlers.common.movable.EDirection;
import jsettlers.common.movable.EMovableAction;
import jsettlers.common.position.ShortPoint2D;
import jsettlers.logic.movable.EGoInDirectionMode;
import jsettlers.logic.movable.Movable;
import jsettlers.logic.movable.MovableStrategy;
/**
*
* @author Andreas Eberle
*
*/
public final class PioneerStrategy extends MovableStrategy {
private static final long serialVersionUID = 1L;
private static final float ACTION1_DURATION = 1.2f;
private EPioneerState state = EPioneerState.JOBLESS;
private ShortPoint2D centerPos;
public PioneerStrategy(Movable movable) {
super(movable);
}
@Override
protected void action() {
switch (state) {
case JOBLESS:
return;
case GOING_TO_POS:
if (centerPos == null) {
this.centerPos = movable.getPos();
}
if (canWorkOnPos(movable.getPos())) {
super.playAction(EMovableAction.ACTION1, ACTION1_DURATION);
state = EPioneerState.WORKING_ON_POS;
} else {
findWorkablePosition();
}
break;
case WORKING_ON_POS:
if (canWorkOnPos(movable.getPos())) {
executeAction(movable.getPos());
}
findWorkablePosition();
break;
}
}
private void findWorkablePosition() {
EDirection closeForeignTileDir = getCloseForeignTile();
if (closeForeignTileDir != null && super.goInDirection(closeForeignTileDir, EGoInDirectionMode.GO_IF_ALLOWED_AND_FREE)) {
this.state = EPioneerState.GOING_TO_POS;
return;
}
centerPos = null;
ShortPoint2D pos = movable.getPos();
if (super.preSearchPath(true, pos.x, pos.y, (short) 30, ESearchType.UNENFORCED_FOREIGN_GROUND)) {
super.followPresearchedPath();
this.state = EPioneerState.GOING_TO_POS;
} else {
this.state = EPioneerState.JOBLESS;
}
}
private EDirection getCloseForeignTile() {
EDirection[] bestNeighbourDir = new EDirection[1];
double[] bestNeighbourDistance = new double[] { Double.MAX_VALUE }; // distance from start point
ShortPoint2D position = movable.getPos();
HexGridArea.stream(position.x, position.y, 1, 6)
.filter((x, y) -> super.isValidPosition(x, y) && canWorkOnPos(x, y))
.forEach((x, y) -> {
double distance = ShortPoint2D.getOnGridDist(x - centerPos.x, y - centerPos.y);
if (distance < bestNeighbourDistance[0]) {
bestNeighbourDistance[0] = distance;
bestNeighbourDir[0] = EDirection.getApproxDirection(position.x, position.y, x, y);
}
});
return bestNeighbourDir[0];
}
private void executeAction(ShortPoint2D pos) {
super.getGrid().changePlayerAt(pos, movable.getPlayer());
}
private boolean canWorkOnPos(int x, int y) {
return super.fitsSearchType(x, y, ESearchType.UNENFORCED_FOREIGN_GROUND);
}
private boolean canWorkOnPos(ShortPoint2D pos) {
return super.fitsSearchType(pos, ESearchType.UNENFORCED_FOREIGN_GROUND);
}
@Override
protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos) {
this.state = EPioneerState.GOING_TO_POS;
centerPos = null;
}
@Override
protected boolean canBeControlledByPlayer() {
return true;
}
@Override
protected void stopOrStartWorking(boolean stop) {
if (stop) {
state = EPioneerState.JOBLESS;
} else {
state = EPioneerState.GOING_TO_POS;
}
}
@Override
protected void pathAborted(ShortPoint2D pathTarget) {
state = EPioneerState.JOBLESS;
}
/**
* Internal state of a {@link PioneerStrategy}.
*
* @author Andreas Eberle
*
*/
private static enum EPioneerState {
JOBLESS,
GOING_TO_POS,
WORKING_ON_POS
}
}