/*******************************************************************************
* 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.EMovableAction;
import jsettlers.common.position.MutablePoint2D;
import jsettlers.common.position.ShortPoint2D;
import jsettlers.common.utils.mutables.MutableDouble;
import jsettlers.logic.movable.Movable;
import jsettlers.logic.movable.MovableStrategy;
/**
*
* @author Andreas Eberle
*
*/
public final class GeologistStrategy extends MovableStrategy {
private static final long serialVersionUID = 1L;
private static final float ACTION1_DURATION = 1.4f;
private static final float ACTION2_DURATION = 1.5f;
private EGeologistState state = EGeologistState.JOBLESS;
private ShortPoint2D centerPos;
public GeologistStrategy(Movable movable) {
super(movable);
}
@Override
protected void action() {
switch (state) {
case JOBLESS:
return;
case GOING_TO_POS: {
ShortPoint2D pos = movable.getPos();
if (centerPos == null) {
this.centerPos = pos;
}
super.getGrid().setMarked(pos, false); // unmark the pos for the following check
if (canWorkOnPos(pos)) {
super.getGrid().setMarked(pos, true);
super.playAction(EMovableAction.ACTION1, ACTION1_DURATION);
state = EGeologistState.PLAYING_ACTION_1;
} else {
findWorkablePosition();
}
}
break;
case PLAYING_ACTION_1:
super.playAction(EMovableAction.ACTION2, ACTION2_DURATION);
state = EGeologistState.PLAYING_ACTION_2;
break;
case PLAYING_ACTION_2: {
ShortPoint2D pos = movable.getPos();
super.getGrid().setMarked(pos, false);
if (canWorkOnPos(pos)) {
executeAction(pos);
}
findWorkablePosition();
}
break;
}
}
private void findWorkablePosition() {
ShortPoint2D closeWorkablePos = getCloseWorkablePos();
if (closeWorkablePos != null && super.goToPos(closeWorkablePos)) {
super.getGrid().setMarked(closeWorkablePos, true);
this.state = EGeologistState.GOING_TO_POS;
return;
}
centerPos = null;
ShortPoint2D pos = movable.getPos();
if (super.preSearchPath(true, pos.x, pos.y, (short) 30, ESearchType.RESOURCE_SIGNABLE)) {
super.followPresearchedPath();
this.state = EGeologistState.GOING_TO_POS;
return;
}
this.state = EGeologistState.JOBLESS;
}
private ShortPoint2D getCloseWorkablePos() {
MutablePoint2D bestNeighbourPos = new MutablePoint2D(-1, -1);
MutableDouble bestNeighbourDistance = new MutableDouble(Double.MAX_VALUE); // distance from start point
HexGridArea.streamBorder(movable.getPos(), 2).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.value) {
bestNeighbourDistance.value = distance;
bestNeighbourPos.x = x;
bestNeighbourPos.y = y;
}
});
if (bestNeighbourDistance.value != Double.MAX_VALUE) {
return bestNeighbourPos.createShortPoint2D();
} else {
return null;
}
}
private void executeAction(ShortPoint2D pos) {
super.getGrid().executeSearchType(movable, pos, ESearchType.RESOURCE_SIGNABLE);
}
private boolean canWorkOnPos(ShortPoint2D pos) {
return super.fitsSearchType(pos, ESearchType.RESOURCE_SIGNABLE);
}
private boolean canWorkOnPos(int x, int y) {
return super.fitsSearchType(x, y, ESearchType.RESOURCE_SIGNABLE);
}
@Override
protected boolean canBeControlledByPlayer() {
return true;
}
@Override
protected void moveToPathSet(ShortPoint2D oldPosition, ShortPoint2D oldTargetPos, ShortPoint2D targetPos) {
this.state = EGeologistState.GOING_TO_POS;
centerPos = null;
super.getGrid().setMarked(oldPosition, false);
if (oldTargetPos != null) {
super.getGrid().setMarked(oldTargetPos, false);
}
}
@Override
protected void stopOrStartWorking(boolean stop) {
if (stop) {
state = EGeologistState.JOBLESS;
} else {
state = EGeologistState.GOING_TO_POS;
}
}
@Override
protected void strategyKilledEvent(ShortPoint2D pathTarget) {
if (pathTarget != null) {
super.getGrid().setMarked(pathTarget, false);
} else {
super.getGrid().setMarked(movable.getPos(), false);
}
}
@Override
protected void pathAborted(ShortPoint2D pathTarget) {
state = EGeologistState.JOBLESS;
}
private static enum EGeologistState {
JOBLESS,
GOING_TO_POS,
PLAYING_ACTION_1,
PLAYING_ACTION_2
}
}