/**
*
*/
package eas.users.students.christianNagel.coEvolutionChristian;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import eas.math.geometry.Polygon2D;
import eas.math.geometry.Vector2D;
import eas.simulation.Wink;
import eas.simulation.agent.AbstractAgent;
import eas.simulation.agent.Evolvable;
import eas.simulation.agent.GenericActuator;
import eas.simulation.agent.GenericSensor;
import eas.simulation.brain.BrainControlled;
import eas.simulation.spatial.sim2D.standardAgents.AbstractAgent2D;
import eas.simulation.spatial.sim2D.standardAgents.AbstractEvolvableAgent2D;
import eas.simulation.spatial.sim2D.standardEnvironments.AbstractEnvironment2D;
import eas.startSetup.ParCollection;
import eas.users.students.christianNagel.neuroBrain.NeuroBrainChristian;
/**
* @author christiannagel
*/
public class SheepAgent extends AbstractEvolvableAgent2D<CoEvolutionEnv> implements BrainControlled<NeuroBrainChristian<SheepAgent>> {
/**
*
*/
private static final long serialVersionUID = 2383416502756254309L;
private Polygon2D shape;
private double speed;
private long timeOfCreation;
private long lastMutated;
@SuppressWarnings("unused")
private Random random;
private int numberOfDistanceSensors;
private HashSet<Long> lastSheepLifetimes;
private final double MAX_DISTANCE = 500.0;
private final double MAX_ANGLE = 360.0;
public SheepAgent(int id, CoEvolutionEnv env, double sheepSpeed,int numberOfDistanceSensors ,Random random, int timeOfCreation, ParCollection params) {
super(id, env, params);
this.speed=sheepSpeed;
this.timeOfCreation = timeOfCreation;
this.lastMutated = this.timeOfCreation;
this.random = random;
this.numberOfDistanceSensors = numberOfDistanceSensors;
GenericSensor<Double, AbstractEnvironment2D<AbstractAgent2D<?>>, AbstractAgent2D<?>> k;
for (int i =0; i<numberOfDistanceSensors; i++){
this.addSensor(k=new DistanceSensor(i));
k.setEvolvable(true);
}
this.addSensor(k=new GenericSensor<Double, AbstractEnvironment2D<AbstractAgent2D<?>>, AbstractAgent2D<?>>() {
/**
*
*/
private static final long serialVersionUID = -2338175217306583555L;
@Override
public String id() {
return "sensing-wolf-distance";
}
@Override
public Double sense(AbstractEnvironment2D<AbstractAgent2D<?>> env, AbstractAgent2D<?> agent) {
Double result=MAX_DISTANCE;
double currentDistance;
for (AbstractAgent<?> agentX: env.getAgents() ){
if (agentX.id()>=10 && agentX.id()%2==1){ //isWolf
currentDistance = env.getAgentPosition(agent.id()).distance(env.getAgentPosition(agentX.id()));
if (currentDistance < result) {
result = currentDistance;
}
}
}
return result;
}
});
k.setEvolvable(true);
this.addSensor(k=new GenericSensor<Double, AbstractEnvironment2D<AbstractAgent2D<?>>, AbstractAgent2D<?>>() {
/**
*
*/
private static final long serialVersionUID = -6943877925503511262L;
@Override
public String id() {
return "sensing-wolf-direction";
}
@Override
public Double sense(AbstractEnvironment2D<AbstractAgent2D<?>> env, AbstractAgent2D<?> agent) {
Double result = MAX_ANGLE;
AbstractAgent<?> nearestWolfAgent = null;
double distance = MAX_DISTANCE;
double currentDistance;
for (AbstractAgent<?> agentX: env.getAgents() ){
if (agentX.id()>=10 && agentX.id()%2==1){ //isWolf
currentDistance = env.getAgentPosition(agent.id()).distance(env.getAgentPosition(agentX.id()));
if (currentDistance < distance) {
nearestWolfAgent = agentX;
distance = currentDistance;
}
}
}
if(nearestWolfAgent!=null){
Vector2D ownPosition = env.getAgentPosition(agent.id());
Vector2D targetPosition = env.getAgentPosition(nearestWolfAgent.id());
Vector2D direction = new Vector2D(-ownPosition.x+targetPosition.x,-ownPosition.y+targetPosition.y);
double angle = new Vector2D (0,-1).angle(direction)*180/Math.PI;
if (targetPosition.x<ownPosition.x){
result = 180-angle;
}
else{
result = 180+angle;
}
}
return result;
}
});
k.setEvolvable(true);
this.addSensor(k=new GenericSensor<Double, AbstractEnvironment2D<AbstractAgent2D<?>>, AbstractAgent2D<?>>() {
/**
*
*/
private static final long serialVersionUID = -5161883061160341340L;
@Override
public String id() {
return "sensing-sheep-distance";
}
@Override
public Double sense(AbstractEnvironment2D<AbstractAgent2D<?>> env, AbstractAgent2D<?> agent) {
Double result=MAX_DISTANCE;
double currentDistance;
for (AbstractAgent<?> agentX: env.getAgents() ){
if (agentX.id()>=10 && agentX.id()%2==0 && agentX.id()!=agent.id()){ //isSheep
currentDistance = env.getAgentPosition(agent.id()).distance(env.getAgentPosition(agentX.id()));
if (currentDistance < result) {
result = currentDistance;
}
}
}
return result;
}
});
k.setEvolvable(true);
this.addSensor(k=new GenericSensor<Double, AbstractEnvironment2D<AbstractAgent2D<?>>, AbstractAgent2D<?>>() {
/**
*
*/
private static final long serialVersionUID = -9131848570152436642L;
@Override
public String id() {
return "sensing-sheep-direction";
}
@Override
public Double sense(AbstractEnvironment2D<AbstractAgent2D<?>> env, AbstractAgent2D<?> agent) {
Double result= MAX_ANGLE;
AbstractAgent<?> nearestSheepAgent = null;
double distance = MAX_DISTANCE;
double currentDistance;
for (AbstractAgent<?> agentX: env.getAgents() ){
if (agentX.id()>=10 && agentX.id()%2==0 && agentX.id()!=agent.id()){ //isSheep
currentDistance = env.getAgentPosition(agent.id()).distance(env.getAgentPosition(agentX.id()));
if (currentDistance < distance) {
nearestSheepAgent = agentX;
distance = currentDistance;
}
}
}
if (nearestSheepAgent!=null){
Vector2D ownPosition = env.getAgentPosition(agent.id());
Vector2D targetPosition = env.getAgentPosition(nearestSheepAgent.id());
Vector2D direction = new Vector2D(-ownPosition.x+targetPosition.x,-ownPosition.y+targetPosition.y);
double angle = new Vector2D (0,-1).angle(direction)*180/Math.PI;
if (targetPosition.x<ownPosition.x){
result = 180-angle;
}
else{
result = 180+angle;
}
}
return result;
}
});
k.setEvolvable(true);
this.addActuator(new GenericActuator<CoEvolutionEnv, AbstractAgent2D<?>>() {
/**
*
*/
private static final long serialVersionUID = -7306285426125720370L;
@Override
public void actuate(CoEvolutionEnv env, AbstractAgent2D<?> agent) {
if(env.differentialDriveForward(agent.id())){
//no collision
} else{
env.unfallSimulation(env.getAgent(agent.id()),360);
}
}
@Override
public String id() {
return "drive";
}
});
this.shape = new Polygon2D();
this.shape.add(new Vector2D(-.5, -.5));
this.shape.add(new Vector2D(-.5, .5));
this.shape.add(new Vector2D(.5, .5));
this.shape.add(new Vector2D(.5, -.5));
}
class DistanceSensor extends GenericSensor<Double, AbstractEnvironment2D<AbstractAgent2D<?>>, AbstractAgent2D<?>>{
/**
*
*/
private static final long serialVersionUID = -1005277855687110034L;
int sensorNumber;
DistanceSensor(int sensorNumber){
this.sensorNumber=sensorNumber;
}
@Override
public String id() {
return "distance-" + sensorNumber;
}
@Override
public Double sense(AbstractEnvironment2D<AbstractAgent2D<?>> env, AbstractAgent2D<?> agent) {
Vector2D angle0= new Vector2D(env.getNormalizedLOV(agent.id()).x,env.getNormalizedLOV(agent.id()).y);
// Vector2D angle1= new Vector2D(env.getNormalizedLOV(agent.id()).x,env.getNormalizedLOV(agent.id()).y);
// angle1.drehe(Vector2D.NULL_VEKTOR, (sensorNumber)*(360/(double)numberOfDistanceSensors)*Math.PI/180);
// Vector2D angle2= new Vector2D(env.getNormalizedLOV(agent.id()).x,env.getNormalizedLOV(agent.id()).y);
// angle2.drehe(Vector2D.NULL_VEKTOR, (sensorNumber+1)*(360/(double)numberOfDistanceSensors)*Math.PI/180);
// System.out.println("AHHHHHH!");
Vector2D thisAgentsPosition = env.getAgentPosition(agent.id());
double currentDistance;
double distance = MAX_DISTANCE;
AbstractAgent<?> nearestAgent = null;
for(AbstractAgent<?> otherAgent:env.getAgents()){
if(otherAgent!=agent){
Vector2D otherAgentsPosition = env.getAgentPosition(otherAgent.id());
Vector2D angleFromThisToOther = new Vector2D (otherAgentsPosition.x-thisAgentsPosition.x,otherAgentsPosition.y-thisAgentsPosition.y);
double calculatedAngle = angle0.angle(angleFromThisToOther);
double calculatedAngleDEG = calculatedAngle*180/Math.PI;
if (angle0.drehrichtung(angleFromThisToOther)){
calculatedAngleDEG = 360-calculatedAngleDEG;
}
if(calculatedAngleDEG<(sensorNumber+1)*360/numberOfDistanceSensors && calculatedAngleDEG>=sensorNumber*360/numberOfDistanceSensors){
currentDistance = env.getAgentPosition(agent.id()).distance(env.getAgentPosition(otherAgent.id()));
if (currentDistance < distance) {
nearestAgent = otherAgent;
distance = currentDistance;
}
}
}
}
if (nearestAgent==null) {
return MAX_DISTANCE;
}
else{
return env.getAgentPosition(agent.id()).distance(env.getAgentPosition(nearestAgent.id()));
}
}
}
/* NO step()! use decideAndReact() instead!*/
@SuppressWarnings("rawtypes")
@Override
public void step(final Wink simZyk) {
super.step(simZyk);
long currentTime;
if((currentTime=simZyk.getLastTick()) - lastMutated > ((AbstractEnvironment2D) this.getEnvironment()).getParCollection().getParValueLong("brainMutationInterval")){
this.createMutatedOffspring();
lastMutated=currentTime;
}
}
@Override
public Polygon2D getAgentShape() {
return shape;
}
@Override
public double getEvaluation() {
return 0;
}
@Override
public Evolvable<AbstractEvolvableAgent2D<CoEvolutionEnv>> createMutatedOffspring() {
this.getBrainControlledAgent().getBrain().mutate(this.getEnvironment().getSimTime().getCurrentTime());
return this;
}
/**
* @return Returns the speed.
*/
public double getSpeed() {
return speed;
}
/**
* @return Returns the DateOfCreation.
*/
public long getTimeOfCreation() {
return timeOfCreation;
}
/**
* @param dateOfCreation The dateOfCreation to set.
*/
public void setTimeOfCreation(long dateOfCreation) {
this.timeOfCreation = dateOfCreation;
}
public void setSheepLifetime() {
long now = this.getEnvironment().getSimTime().getCurrentTime().getLastTick();
if(lastSheepLifetimes==null){
lastSheepLifetimes = new HashSet<Long>();
}
lastSheepLifetimes.add(now-timeOfCreation);
}
/**
* @return Returns the lastSheepLifetime.
*/
public long getLastSheepLifetime() {
long result;
if(lastSheepLifetimes==null){
result=-1;
}
else{
long sum=0;
for(Long value: lastSheepLifetimes){
sum+=value;
}
result = sum/lastSheepLifetimes.size();
lastSheepLifetimes=null;
}
return result;
}
/**
* @return Returns the currentSheepLifetime.
*/
public long getCurrentSheepLifetime() {
long result;
result = this.getEnvironment().getSimTime().getCurrentTime().getLastTick() - timeOfCreation;
return result;
}
/**
* @return Returns the number of sheep in a certain radius.
*/
@SuppressWarnings("rawtypes")
public int getNumberOfSheepInDistinctRadius() {
double distance = 50;
double currentDistance;
List<AbstractAgent> nearestSheepAgents = new LinkedList<AbstractAgent>();
for (AbstractAgent agentX: this.getEnvironment().getAgents() ){
if (agentX.id()>=10 && agentX.id()%2==0 && agentX.id()!=this.id()){ //isSheep
currentDistance = ((AbstractEnvironment2D) this.getEnvironment()).getAgentPosition(this.id()).distance(((AbstractEnvironment2D) this.getEnvironment()).getAgentPosition(agentX.id()));
if (currentDistance < distance) {
nearestSheepAgents.add(agentX);
}
}
}
return nearestSheepAgents.size();
}
private NeuroBrainChristian<SheepAgent> brain;
@Override
public void implantBrain(NeuroBrainChristian<SheepAgent> setBrain) {
this.brain = setBrain;
}
@Override
public NeuroBrainChristian<SheepAgent> getBrain() {
return this.brain;
}
}