001 /*
002 * SimuCS - Simulator to use with Classifier Systems
003 * MSc project - Oxford University
004 * by Benoit Isaac - Summer 2005
005 */
006
007 package simuLCS;
008 import java.awt.Graphics2D;
009 import java.awt.geom.Point2D;
010 import java.util.Random;
011
012 /**
013 * Agent moving according to R. Vaughan's mathematical model.
014 * @author Benoit
015 *
016 */
017 public class AgentDuck extends Agent {
018
019 protected double k1 = 3000;
020 protected double k2 = 1000;
021 protected double k3 = 500;
022 protected double k4 = 8000;
023 protected double parameterL = 30;
024
025 protected Vector2D lastMovVector ;
026
027 public AgentDuck(Random gen, Arena a) {
028 super(gen,a);
029 }
030
031 public AgentDuck(Random gen, Arena a, String name)
032 { this(gen,a);
033 lastMovVector = new Vector2D();
034 setName(name);
035 }
036
037 /**
038 * Moves the Agent according to the equation giving the movement vector
039 */
040 public void move(Arena a, Entity[] others, int nbEntities, Graphics2D g)
041 {
042 double newX = coord.getX() ;
043 double newY = coord.getY() ;
044
045 Vector2D sumForces = new Vector2D();
046
047 // Terms (1) and (2) for other ducks, (4) for the sheepdog(s)
048 for(int i=0;i<nbEntities;i++)
049 {
050 Point2D posAgent = others[i].getCoord();
051 if((others[i].getId() != this.getId())) // OTHER agents
052 {
053 Vector2D DA = new Vector2D();
054 // compute unit vector Duck-OtherAgent
055 DA.setUnitVector(getCoord(),posAgent);
056 //System.out.println("DA-"+DA);
057 double distToAgent= this.distanceTo(posAgent);
058 double distToAgentSq = distToAgent * distToAgent ;
059 if (distToAgentSq < 5)
060 {
061 distToAgentSq = 5;
062 }
063
064 if(others[i] instanceof AgentDuck)
065 {
066 // add [k1/(|DDn+L|)²] * unit vector
067 double tmp2 = distToAgent+parameterL ;
068 Vector2D Fattract = new Vector2D(DA);
069 Fattract.multiplyByConstant(k1/(tmp2*tmp2));
070 //Fattract.paint(getCoord(),g,Color.GREEN);
071 //System.out.println("Fattract-"+Fattract);
072 sumForces.add(Fattract);
073
074 // add - [k2/(|DDn|)²] * unit vector
075
076 Vector2D Frepulse = new Vector2D(DA);
077 Frepulse.multiplyByConstant(-k2/distToAgentSq);
078 //Frepulse.paint(getCoord(),g,Color.GREEN);
079 //System.out.println("Frepulse-"+Frepulse);
080 sumForces.add(Frepulse);
081 }
082 else if(others[i] instanceof AgentInteractive)
083 {
084 // add - [k4/(|DR|)²] * unit vector
085 Vector2D FrepSheepdog = new Vector2D(DA);
086 FrepSheepdog.multiplyByConstant(-k4/distToAgentSq);
087 // FrepSheepdog.paint(getCoord(),g,Color.RED);
088 //System.out.println("FrepSheepdog-"+FrepSheepdog);
089 sumForces.add(FrepSheepdog);
090 }
091
092 }
093
094 }
095
096 // repelled by the walls of the arena IF NOT IN THE CENTER
097 Point2D W = arena.closestPointTo(getCoord());
098 if(W.getX() != 0.0 || W.getY() != 0.0) // agent not in the center
099 {
100 Vector2D Fwall = new Vector2D();
101 if(!arena.isInside(getCoord().getX(),getCoord().getY(), 1))
102 { /* agent going out of the arena, the vector should be in the opposite */
103 Fwall.setUnitVector(W,getCoord());
104 }
105 else
106 {
107 Fwall.setUnitVector(getCoord(),W);
108 }
109 double distToWall = arena.distanceTo(getCoord());
110 double k3tmp = k3 ;
111 // if(distToWall < 8)
112 // { k3tmp = 10*k3;
113 // }
114 Fwall.multiplyByConstant(-k3tmp/(distToWall*distToWall));
115 // Fwall.paint(getCoord(),g,Color.BLUE);
116 //System.out.println("Fwall-"+Fwall);
117 sumForces.add(Fwall);
118 }
119
120
121 Vector2D MovVector = new Vector2D(sumForces);
122 Vector2D inertia = new Vector2D(lastMovVector);
123 inertia.multiplyByConstant(0.1);
124 MovVector.add(inertia);
125
126 //MovVector.multiplyByConstant(0.2); // iteration step
127
128 //Saving the new Movement Vector to use it for intertia next time
129 lastMovVector = MovVector ;
130
131 newX = newX + MovVector.getX();
132 newY = newY + MovVector.getY();
133
134 coord.setLocation(newX,newY);
135 }
136
137
138
139
140
141 /**
142 * An agent duck is not dangerous, by convention.
143 */
144 public boolean isDangerous(){
145 return false;
146 }
147
148 }