天天看點

Anti- Gravity Robocode反重力移動政策分析

轉自: http://www.ibm.com/developerworks/java/library/j-antigrav/

    class Enemy

    {

        String name;

        public double bearing, heading, speed, x, y, distance, changehead;

        public long ctime; //game time that the scan was produced

        public bool live; //is the enemy alive?

        public PointF guessPosition(long when)

        {

            double diff = when - ctime;

            double newY = y + Math.Cos(heading) * speed * diff;

            double newX = x + Math.Sin(heading) * speed * diff;

            return new PointF((float)newX, (float)newY);

        }

    }

    public class Anti_Gravity : AdvancedRobot

    {

        Dictionary<string, Enemy> enemyList = new Dictionary<string, Enemy>();

        Enemy target;

        private const double PI = Math.PI;

        private int direction = 1;  // direction we are heading. 1 = forward, -1 = back.

        private double firePower;   // the pow of the shot we will battle.

        private double midPointStrength = 0;    // The strength of the gravity point in the middle of field.

        private int midPointCount = 0;              // Number of turns since that strenght was changed.

        public override void Run()

        {

            target.Distance = 100000;

            this.IsAdjustGunForRobotTurn = true;

            this.IsAdjustRadarForGunTurn = true;

            TurnRadarRightRadians(2 * Math.PI);

            while (true)

            {

                antiGravMove(); // Move

                doFirePower();  // Set fire power to the pot

                doScanner();    // Scan the robot.

                doGun();        

                Fire(firePower);

                Execute();

            }

        }

        public void antiGravMove()

        {

            double xforce = 0;

            double yforce = 0;

            double force;

            double ang;

            GravPoint p;

            Enemy en;

            Enumeration e = targets.elements();

            //cycle through all the enemies.  If they are alive, they are repulsive.  Calculate the force on us

            while (e.hasMoreElements())

            {

                en = (Enemy)e.nextElement();

                if (en.live)

                {

                    p = new GravPoint(en.x, en.y, -1000);

                    force = p.power / Math.pow(getRange(getX(), getY(), p.x, p.y), 2);

                    //Find the bearing from the point to us

                    ang = normaliseBearing(Math.PI / 2 - Math.atan2(getY() - p.y, getX() - p.x));

                    //Add the components of this force to the total force in their respective directions

                    xforce += Math.sin(ang) * force;

                    yforce += Math.cos(ang) * force;

                }

            }

            midpointcount++;

            if (midpointcount > 5)

            {

                midpointcount = 0;

                midpointstrength = (Math.random() * 2000) - 1000;

            }

            p = new GravPoint(getBattleFieldWidth() / 2, getBattleFieldHeight() / 2, midpointstrength);

            force = p.power / Math.pow(getRange(getX(), getY(), p.x, p.y), 1.5);

            ang = normaliseBearing(Math.PI / 2 - Math.atan2(getY() - p.y, getX() - p.x));

            xforce += Math.sin(ang) * force;

            yforce += Math.cos(ang) * force;

            xforce += 5000 / Math.pow(getRange(getX(), getY(), getBattleFieldWidth(), getY()), 3);

            xforce -= 5000 / Math.pow(getRange(getX(), getY(), 0, getY()), 3);

            yforce += 5000 / Math.pow(getRange(getX(), getY(), getX(), getBattleFieldHeight()), 3);

            yforce -= 5000 / Math.pow(getRange(getX(), getY(), getX(), 0), 3);

            //Move in the direction of our resolved force.

            goTo(getX() - xforce, getY() - yforce);

        }

        public void doFirePower()

        {

            firePower = 400 / target.Distance;

            if (firePower > 3)

            {

                firePower = 3;

            }

        }

        public void doScanner()

        {

            SetTurnRadarLeftRadians(2 * Math.PI);

        }

        public void doGun()

        {

            //long time = getTime() + (int)Math.round((getRange(getX(), getY(), target.x, target.y) / (20 - (3 * firePower))));

            //Point2D.Double p = target.guessPosition(time);

            offsets the gun by the angle to the next shot based on linear targeting provided by the enemy class

            //double gunOffset = getGunHeadingRadians() - (Math.PI / 2 - Math.atan2(p.y - getY(), p.x - getX()));

            //setTurnGunLeftRadians(normaliseBearing(gunOffset));

        }

        public int turnTo(double angle)

        {

            double ang;

            int dir;

            ang = normaliseBearing(getHeading() - angle);

            if (ang > 90)

            {

                ang -= 180;

                dir = -1;

            }

            else if (ang < -90)

            {

                ang += 180;

                dir = -1;

            }

            else

            {

                dir = 1;

            }

            setTurnLeft(ang);

            return dir;

        }

        public void goTo(double x, double y)

        {

            double dist = 20;

            double angle = Utils.ToDegrees(absbearing(X, Y, x, y));

            //double angle = Math.toDegrees(absbearing(getX(), getY(), x, y));

            double r = turnTo(angle);

            SetAhead(dist * r);

        }

        //if a bearing is not within the -pi to pi range, alters it to provide the shortest angle

        public double normaliseBearing(double ang)

        {

            if (ang > PI)

                ang -= 2 * PI;

            if (ang < -PI)

                ang += 2 * PI;

            return ang;

        }

        //if a heading is not within the 0 to 2pi range, alters it to provide the shortest angle

        double normaliseHeading(double ang)

        {

            if (ang > 2 * PI)

                ang -= 2 * PI;

            if (ang < 0)

                ang += 2 * PI;

            return ang;

        }

        //returns the distance between two x,y coordinates

        public double getRange(double x1, double y1, double x2, double y2)

        {

            double xo = x2 - x1;

            double yo = y2 - y1;

            double h = Math.Sqrt(xo * xo + yo * yo);

            return h;

        }

        //gets the absolute bearing between to x,y coordinates

        public double absbearing(double x1, double y1, double x2, double y2)

        {

            double xo = x2 - x1;

            double yo = y2 - y1;

            double h = getRange(x1, y1, x2, y2);

            if (xo > 0 && yo > 0)

            {

                return Math.Asin(xo / h);

            }

            if (xo > 0 && yo < 0)

            {

                return Math.PI - Math.Asin(xo / h);

            }

            if (xo < 0 && yo < 0)

            {

                return Math.PI + Math.Asin(-xo / h);

            }

            if (xo < 0 && yo > 0)

            {

                return 2.0 * Math.PI - Math.Asin(-xo / h);

            }

            return 0;

        }

        public void onScannedRobot(ScannedRobotEvent e)

        {

            Enemy en;

            if (targets.containsKey(e.getName()))

            {

                en = (Enemy)targets.get(e.getName());

            }

            else

            {

                en = new Enemy();

                targets.put(e.getName(), en);

            }

            //the next line gets the absolute bearing to the point where the bot is

            double absbearing_rad = (getHeadingRadians() + e.getBearingRadians()) % (2 * PI);

            //this section sets all the information about our target

            en.name = e.getName();

            double h = normaliseBearing(e.getHeadingRadians() - en.heading);

            h = h / (getTime() - en.ctime);

            en.changehead = h;

            en.x = getX() + Math.sin(absbearing_rad) * e.getDistance(); //works out the x coordinate of where the target is

            en.y = getY() + Math.cos(absbearing_rad) * e.getDistance(); //works out the y coordinate of where the target is

            en.bearing = e.getBearingRadians();

            en.heading = e.getHeadingRadians();

            en.ctime = getTime(); //game time at which this scan was produced

            en.speed = e.getVelocity();

            en.distance = e.getDistance();

            en.live = true;

            if ((en.distance < target.distance) || (target.live == false))

            {

                target = en;

            }

        }

    }

}