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.Color;
009    import java.awt.Graphics2D;
010    import java.awt.geom.Point2D;
011    import java.util.Random;
012    
013    /**
014     * Agent having a behaviour described as a set of rules (classifiers).
015     * @author Benoit
016     * 
017     */
018    public class AgentClassifier extends Agent {
019            
020            
021            /**
022             * The template used by the Agent for its behaviour
023             */
024            protected Template template;
025    
026            /**
027             * Indicates whether or not a Visibility Circle should be used
028             */
029            protected boolean isDetectionLimited = false;
030            
031            /**
032             * Size of the visibility circle
033             */
034            protected double DETECTION_DISTANCE = 150;
035    
036            /**
037             * Last movement vector (for the computation of the inertia
038             */
039            protected Vector2D lastMovVector;
040    
041            /**
042             * The behaviour of the Agent
043             */
044            protected ClassifierSet behaviour;
045    
046            /**
047             * Creates an AgentClassifier randmoly placed inside the Arena
048             * @param gen
049             * @param a
050             * @param name
051             */
052            public AgentClassifier(Random gen, Arena a, String name) {
053                    super(gen, a);
054                    lastMovVector = new Vector2D();
055                    setName(name);
056            }
057    
058    
059            /**
060             * Calculates the New Movement Vector according to the <code>behaviourToConsider</code>.
061             * This corresponds to the procedure "Guess New Position"
062             * @param behaviourToConsider
063             * @param arena
064             * @param others
065             * @param nbEntities
066             * @param g
067             * @param actionSetToReturn
068             * @return
069             */
070            public Vector2D getNewMovVectorAccordingTo(
071                    ClassifierSet behaviourToConsider,
072                    Arena arena,
073                    Entity[] others,
074                    int nbEntities,
075                    Graphics2D g,
076                    ClassifierSet actionSetToReturn) {
077    
078                    Vector2D sumForces = new Vector2D();
079                    Vector2D currentVector;
080    
081                    /* Putting all the entities together: adding the arena */
082                    Entity[] en = new Entity[nbEntities + 1];
083                    for (int i = 0; i < nbEntities; i++) {
084                            en[i] = others[i];
085                    }
086                    en[nbEntities] = arena;
087    
088                    /* Adding the response to the other entities*/
089                    for (int i = 0; i < nbEntities + 1; i++) {
090                            Entity current = en[i];
091                            Vector2D action = new Vector2D();
092                            if (current.getId() != this.getId()
093                                    && this.canDetect(current)) // OTHER agents
094                                    {
095                                    /* get the definition of this agent */
096                                    String s = getTemplate().testCondition(current);
097                                    /* find the classifiers satisfied */
098                                    ClassifierSet matchSet = behaviourToConsider.getMatchSet(s);
099                                    if (Config.PRINT_MODE > 7) {
100                                            System.out.flush();
101                                            System.out.println(
102                                                    "-- Size MatchSet for "
103                                                            + s
104                                                            + " :"
105                                                            + matchSet.getSize());
106                                            System.out.flush();
107                                    }
108    
109                                    /* from these, do a selection according to the template */
110                                    ClassifierSet actionSet = matchSet.getActionSet();
111                                    /* calculate the vector generated by the action parts of
112                                     * the classifiers selected
113                                     */
114                                    if (Config.PRINT_MODE > 7) {
115                                            System.out.flush();
116                                            System.out.println(
117                                                    "-- Action Set for:"
118                                                            + s
119                                                            + " : size "
120                                                            + actionSet.getSize());
121                                            System.out.println(actionSet.toString());
122                                            System.out.flush();
123                                    }
124                                    Classifier[] actionSetArray = actionSet.getClassifiers();
125                                    currentVector =
126                                            getTemplate().getVectorFromActions(
127                                                    actionSetArray,
128                                                    this,
129                                                    current);
130                                    if (Config.PRINT_MODE > 8)
131                                            System.out.println(
132                                                    "Reaction to:" + current + " - " + currentVector);
133                                    action.add(currentVector);
134                                    // adding the activated classifiers to the action Set
135                                    if(actionSetToReturn != null)
136                                            actionSetToReturn.addClassifierSet(actionSet);
137                            }
138                            sumForces.add(action);
139                    }
140    
141                    //              TODO limitate the speed
142    
143                    //TODO apply the momentum to represent the inertia
144                    Vector2D movVector = new Vector2D(sumForces);
145                    Vector2D inertia = new Vector2D(lastMovVector);
146                    inertia.multiplyByConstant(0.1);
147                    movVector.add(inertia);
148    
149                    //MovVector.multiplyByConstant(0.2); // iteration step
150    
151                    //Saving the new Movement Vector to use it for intertia next time
152                    // MovVector.paint(getCoord(),g,Color.BLACK);
153                    //System.out.println("FINAL-"+MovVector);
154                    return movVector;
155    
156            }
157            
158    
159            /**
160             * Move the agent according to its behaviour and the others entities around.
161             */
162            public void move(
163                    Arena arena,
164                    Entity[] others,
165                    int nbEntities,
166                    Graphics2D g) {
167                    double newX = coord.getX();
168                    double newY = coord.getY();
169    
170                    Vector2D newMovVector =
171                            getNewMovVectorAccordingTo(
172                                    behaviour,
173                                    arena,
174                                    others,
175                                    nbEntities,
176                                    g,
177                                    null);
178    
179    //              newMovVector = Vector2D.getCorrectedVector(newMovVector,arena,this,g);
180                    
181                    lastMovVector = newMovVector;
182                    
183    
184                    newX = newX + newMovVector.getX();
185                    newY = newY + newMovVector.getY();
186    
187                    coord.setLocation(newX, newY);
188            }
189    
190            /**
191             * Indicates if an Entity can be detected (inside the Visibility Circle).
192             * @param e the Entity to detect
193             * @return always true without a Visibility Circle; with a VC, true if e can be detected.
194             */
195            public boolean canDetect(Entity e) {
196                    boolean result;
197                    if (isDetectionLimited) {
198                            // is the other agent visible ? (not too far)
199                            result =
200                                    (this.distanceTo(e.getCoordNearTo(this)) < DETECTION_DISTANCE);
201                            
202                    } else {
203                            // always visible
204                            result = true;
205                    }
206    
207                    return result;
208            }
209    
210            /**
211             * Draw the Circle around the Agent
212             * @param g
213             * @param coord
214             * @param c
215             */
216            protected void drawVisibilityCircle(Graphics2D g, Point2D coord, Color c) {
217                    g.setColor(c);
218                    int x = (int) (coord.getX() - (DETECTION_DISTANCE));
219                    int y = (int) (coord.getY() - (DETECTION_DISTANCE));
220                    g.drawOval(
221                            x,
222                            y,
223                            (int) DETECTION_DISTANCE * 2,
224                            (int) DETECTION_DISTANCE * 2);
225            }
226    
227            /**
228             * Paint the Agent Classifier + its circle if it has one.
229             */
230            public void paint(Graphics2D g) {
231    
232                    // erase and draw the new visibility circle
233                    if (isDetectionLimited) {
234                            drawVisibilityCircle(g, oldcoord, Color.WHITE);
235                            drawVisibilityCircle(g, coord, color_ext);
236                    }
237                    // draw the agent
238                    super.paint(g);
239            }
240    
241            
242            public ClassifierSet getBehaviour() {
243                    return behaviour;
244            }
245    
246            
247            public Vector2D getLastMovVector() {
248                    return lastMovVector;
249            }
250    
251            
252            public Template getTemplate() {
253                    return template;
254            }
255    
256            
257            public void setBehaviour(ClassifierSet behaviour) {
258                    this.behaviour = behaviour;
259            }
260    
261            
262            public void setLastMovVector(Vector2D lastMovVector) {
263                    this.lastMovVector = lastMovVector;
264            }
265    
266            
267            public void setTemplate(Template template) {
268                    this.template = template;
269            }
270    
271            
272            public boolean isDetectionLimited() {
273                    return isDetectionLimited;
274            }
275    
276            
277            public void setDetectionLimited(boolean b) {
278                    isDetectionLimited = b;
279            }
280    
281    }