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 }