Anti- Gravity Robocode反重力移动策略分析


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


    class Enemy
    {
        /*
         * ok, we should really be using accessors and mutators here,
         * (i.e getName() and setName()) but life's too short.
         */
        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;
                }
            }


            /**The next section adds a middle point with a random (positive or negative) strength.
            The strength changes every 5 turns, and goes between -1000 and 1000.  This gives a better
            overall movement.**/
            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;


            /**The following four lines add wall avoidance.  They will only affect us if the bot is close 
            to the walls due to the force from the walls decreasing at a power 3.**/
            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);
        }


         /**Move the gun to the predicted next bearing of the enemy**/
        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));
        }


        /**Turns the shortest angle possible to come to a heading, then returns the direction the
the bot needs to move in.**/
        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;
        }


        /**Move towards an x and y coordinate**/
        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;
            }
        }

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值