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     * A basic Agent, placed randomly inside the Arena and moving randomly (no specific behaviour).
015     * It provides basic functions such as painting the Agent, erasing it,...
016     * @author Benoit
017     * 
018     */
019    public class Agent extends Entity {
020    
021            /**
022             * Angle which determines where the agent is heading
023             */
024            protected double heading;
025    
026            /**
027             * Link to the Arena where the agent is placed.
028             */
029            protected Arena arena;
030    
031            /**
032             * Old coordinates (of the previous position).
033             * Used to avoid the blinking effect while the Agent is moving.
034             * @see #paint(Graphics2D)
035             */
036            protected Point2D oldcoord;
037    
038            /**
039             * Constructs an Agent placed randomly <i>inside</i> the Arena.
040             * @param gen The generator for the random numbers
041             * @param a the Arena where to put the agent
042             * @see Arena#isInside(double, double, double)
043             */
044            public Agent(Random gen, Arena a) {
045                    super();
046                    arena = a;
047                    generator = gen;
048                    size = 20;
049                    boolean isInsideArena;
050                    do {
051                            double x = (double) gen.nextInt(a.getSize()) - a.getShift();
052                            double y = (double) gen.nextInt(a.getSize()) - a.getShift();
053                            coord = new Point2D.Double(x, y);
054                            isInsideArena = a.isInside(x, y, (double) size);
055                    } while (!isInsideArena);
056    
057                    oldcoord = new Point2D.Double(coord.getX(), coord.getY());
058    
059                    heading = 0.0;
060                    color_int = Color.CYAN;
061                    color_ext = Color.GRAY;
062                    paintName = true;
063            }
064    
065            /**
066             * Constructs an Agent placed randomly inside the Arena with the name <code>name</code>.
067             * @param gen
068             * @param a
069             * @param name
070             */
071            public Agent(Random gen, Arena a, String name) {
072                    this(gen, a);
073                    setName(name);
074            }
075    
076            /**
077             * Get the radius of the agent (which is a circle).
078             * @return the radius (size/2)
079             * @see Entity#size
080             */
081    
082            public double getRadius() {
083                    return size / 2;
084            }
085    
086            /**
087             * Remove the drawing of the agent for the old coordinates
088             * and repaint the agent at its new coordinates
089             * (This avoids a blinking effect)
090             * @see Entity#paint()
091             */
092            public void paint(Graphics2D g) {
093    
094                    // clear the previous drawing
095                    clear(g, oldcoord);
096    
097                    super.paint(g);
098    
099                    // to avoid blinking effect
100                    oldcoord = new Point2D.Double(coord.getX(), coord.getY());
101            }
102    
103            /**
104             * Clear the drawing of the agent at the indicated coordinates
105             * (Basically, a white circle is drawn)
106             * @param g Graphics
107             * @param c The coordinates where to clear the drawing of the agent.
108             */
109    
110            public void clear(Graphics2D g, Point2D c) {
111                    g.setColor(Color.WHITE);
112                    int x = (int) (c.getX() - (size / 2));
113                    int y = (int) (c.getY() - (size / 2));
114                    g.fillOval(x - 2, y - 2, size + 5, size + 5);
115            }
116    
117            /**
118             * Clear the drawing of the agent at the <i>current</i> coordinates.
119             * @param g Graphics
120             * @see #clear(Graphics2D, Point2D)
121             */
122            public void clear(Graphics2D g) {
123                    clear(g, coord);
124            }
125    
126            /**
127             * Move the agent randomly.
128             * As an example, here the agent moves randomly 
129             * (on the left or the right  + up or down)
130             */
131            public void move() {
132                    float f = generator.nextFloat();
133                    double newX = coord.getX();
134                    double newY = coord.getY();
135                    if (generator.nextBoolean()) {
136                            newX = newX + 1;
137                    } else {
138                            newX = newX - 1;
139                    }
140                    if (generator.nextBoolean()) {
141                            newY = newY + 1;
142                    } else {
143                            newY = newY - 1;
144                    }
145    
146                    coord.setLocation(newX, newY);
147    
148            }
149    
150            /**
151             * Move the Agent by modifying its coordinates.
152             * @see Entity#move(Arena, Entity[], int, Graphics2D)
153             */
154    
155            public void move(Arena a, Entity[] others, int nbagents, Graphics2D g) {
156                    move();
157            }
158    
159            /**
160             * Returns a pointer to the Arena where the Agent is placed.
161             * @return The arena
162             */
163            public Arena getArena() {
164                    return arena;
165            }
166    
167    
168            /**
169             * By default, an Agent is not dangerous.
170             * Subclasses might be Dangerous and therfore should override this 
171             * function.
172             */
173            public boolean isDangerous() {
174                    return false;
175            }
176            
177            /**
178             * By default, an Agent is a moving entity.
179             * @return true
180             */
181            public boolean isMoving() {
182                    return true;
183            }
184    
185            /**
186             * For compatibility reasons, subclasses might implement an Agent whose
187             * behaviour is described by a ClassifierSet.
188             * @return null for this class (should be overriden by subclasses)
189             * @see AgentClassifier#behaviour
190             * @see ClassifierSet
191             */
192            public ClassifierSet getBehaviour() {
193                    return null;
194            };
195    
196            /**
197             * Get the classifier set representing the behaviour of the Agent.
198             * @param i
199             * @return
200             */
201            public ClassifierSet getBehaviour(int i) {
202                    return getBehaviour();
203            }
204    
205            /**
206             * Return the closest point of the Agent to another Entity
207             * @see Entity#getCoordNearTo(Entity)
208             */
209            public Point2D getCoordNearTo(Entity otherEntity) {
210                    return getCoord();
211            }
212    
213            /**
214             * Creates a String describing the Agent
215             */
216            public String toString() {
217                    String s =
218                                    "Agent "
219                                    + getId()
220                                    + ": [type:"
221                                    + getClass().getName()
222                                    + ", name:"
223                                    + getName()
224                                    + "] x:"
225                                    + getCoord().getX()
226                                    + " y:"
227                                    + getCoord().getY()
228                                    + " size:"
229                                    + getSize();
230                    return s;
231            }
232    
233    }