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.Font;
010    import java.awt.Graphics2D;
011    import java.awt.geom.Point2D;
012    
013    /**
014     * The Circular Arena
015     * @author Benoit
016     * 
017     */
018    public class Arena extends Entity {
019    
020            private static final int sizeGrad = 10;
021    
022            private Graphics2D graphics;
023            private int shift;
024    
025            public Arena(int s, int sh) {
026                    size = s;
027                    shift = sh;
028                    name = "Arena";
029            }
030            /**
031             * @param g
032             */
033            public void linkGraphics(Graphics2D g) {
034                    graphics = g;
035            }
036    
037            /**
038             * Paints the Arena and the ticks around
039             */
040            public void paint(Graphics2D g) {
041                    g.setColor(Color.BLUE);
042                    int x = (int) (- (size / 2));
043                    int y = (int) (- (size / 2));
044                    g.drawOval(x, y, size, size);
045                    g.setColor(Color.BLACK);
046                    g.drawRect(x, y, size, size);
047                    for (int i = -size / 2; i <= size / 2; i += 3) {
048                            g.drawLine(i, 0, i + 1, 0);
049                            g.drawLine(0, i, 0, i + 1);
050                    }
051    
052                    for (int i = -size / 2; i <= size / 2; i += 100) {
053                            g.drawLine(-size / 2, i, - (size / 2) + sizeGrad, i);
054                            g.drawLine(size / 2 - sizeGrad, i, size / 2, i);
055                            g.drawLine(i, -size / 2, i, -size / 2 + sizeGrad);
056                            g.drawLine(i, size / 2 - sizeGrad, i, size / 2);
057                    }
058            }
059    
060            private void paintTimeSteps(Graphics2D g, int timeSteps) {
061    
062                    int width = 300;
063                    int height = 15;
064                    int x = -size / 2;
065                    int y = size / 2 + height + 20;
066                    g.setColor(Color.WHITE);
067    
068                    g.fillRect(x - 1, y - 15 - height, width, height + 10);
069                    g.setColor(Color.BLACK);
070                    Font current = g.getFont();
071                    g.setFont(new Font("SansSerif", Font.BOLD, 26));
072                    g.drawString("TIME STEPS: " + timeSteps, x, y - 8);
073                    g.setFont(current);
074            }
075            
076            /**
077             * Paint the Arena with the indication of the Time Steps
078             * @param g
079             * @param timeSteps
080             */
081            public void paintWithTimeSteps(Graphics2D g, int timeSteps) {
082                    paint(g);
083                    paintTimeSteps(g, timeSteps);
084            }
085    
086            public double getRadius() {
087                    return size / 2;
088            }
089    
090            public double getRadiusBody() {
091                    return 1;
092            }
093    
094            public int getShift() {
095                    return size / 2 + shift;
096            }
097    
098            /**
099             * Returns true if the circle whose center is the point (x,y) and whose
100             * radius is <code>radiusBody</code> is colliding with the Arena
101             * @param x
102             * @param y
103             * @param radiusBody
104             * @return
105             */
106            public boolean isInside(double x, double y, double radiusBody) {
107                    double dist_from_center = radiusBody + Math.sqrt((x * x) + (y * y));
108                    double r = getRadius();
109                    //System.out.println(x+"-"+y+"-s:"+"-"+dist_from_center+"<"+r);
110                    boolean test = (dist_from_center < getRadius());
111                    return test;
112            }
113    
114            /**
115             * Returns true if Agent a collides with the Arena
116             */
117            public boolean collideWithMe(Agent a) {
118                    double x_ag = (double) a.getCoord().getX();
119                    double y_ag = (double) a.getCoord().getY();
120                    double s_ag = (double) a.getSize();
121    
122                    boolean test =
123                            (s_ag + Math.sqrt((x_ag * x_ag) + (y_ag * y_ag)) < getRadius());
124    
125                    return test;
126            }
127    
128            /**
129             * Calculates the distance between a point and the arena
130             * @param p Point inside the arena
131             * @return the distance between the point and the closest wall
132             */
133            public double distanceTo(Point2D p) {
134                    double distToCentre =
135                            Math.sqrt(p.getX() * p.getX() + p.getY() * p.getY());
136                    return getRadius() - distToCentre;
137            }
138    
139            /**
140             * Gives the closest point of the Wall to a given point
141             * @param p
142             * @param radiusArenaToConsider
143             * @return
144             */
145            public Point2D closestPointTo(Point2D p, double radiusArenaToConsider) {
146                    if (p.getX() == 0) {
147                            if (p.getY() > 0) {
148                                    return new Point2D.Double(0, radiusArenaToConsider);
149                            } else if (p.getY() < 0) {
150                                    return new Point2D.Double(0, -radiusArenaToConsider);
151                            } else {
152                                    return new Point2D.Double(0, -radiusArenaToConsider);
153                            }
154                    } else {
155                            double coeff = p.getY() / p.getX();
156                            double x =
157                                    Math.sqrt(
158                                            radiusArenaToConsider
159                                                    * radiusArenaToConsider
160                                                    / (1 + coeff * coeff));
161                            if (p.getX() < 0) {
162                                    x = -x;
163                            }
164                            double y = coeff * x;
165                            Point2D closest_point = new Point2D.Double(x, y);
166                            return closest_point;
167                    }
168            }
169    
170            /**
171             * Returns the point of the arena which is the closest to p.
172             * If p = 0,0 - no closest point, functions returns the NORTH one (arbitrary)
173             * @param p the point2D
174             * @return closest Point2D of the arena, - NORTH point if no closest
175             */
176    
177            public Point2D closestPointTo(Point2D p) {
178                    return closestPointTo(p, getRadius());
179            }
180    
181            /**
182             * For the arena, the coordinates used to get the vector 
183             * are the coordinates of the closest point of the arena 
184             */
185    
186            public Point2D getCoordNearTo(Entity otherEntity) {
187                    return closestPointTo(otherEntity.getCoord());
188            }
189    
190            /**
191             * By convention, the Arena is dangerous.
192             */
193            public boolean isDangerous() {
194                    return true;
195            }
196            public boolean isMoving() {
197                    return false;
198            }
199            /**
200             * The Arena does not move.
201             * @see Entity#move(Arena,Entity[], int, java.awt.Graphics2D)
202             */
203            public void move(Arena a, Entity[] others, int nbagents, Graphics2D g) {
204            }
205    
206    }