简体   繁体   中英

Robocode BasicBot Going To The Middle Of The Map... Not

This is one of the classic Robocode practice questions: Going to the middle of the map. I didn't want to move twice (once for x-axis and once for y-axis), but instead get the bearing towards the middle and move in a single motion after setting my robot's bearing.

To my dismay, it seems to be not working. Instead, the behavior I observed from the robots is that they turn 180 degrees and move ahead for the value of 'r', which is the hypotenuse of the "triangle" towards the middle. The distance seems to be getting smaller each loop, so I think that the formula for 'r' is right. My suspicion is towards the methods setWest() and setEast() I wrote. Their purpose is to set the robot parallel to the horizontal facing either East or West. Then I once again rotate the robot towards the middle by using theta (which is the second iffy part) and move it.

The methods implemented in Robocode are pretty self-explanatory, not mine though. Here is the code I've written:

public class MyFirstRobot extends Robot {   
    public void setWest(){  
        // If it's looking NW           
        if(getHeading() > 270 && getHeading() < 0)
            turnLeft(getHeading() - 270);
        // If it's looking SE or SW
        else if(getHeading() >= 90 && getHeading() <= 270)
            turnRight(270 - getHeading());
        // If it's looking NE
        else if(getHeading() >= 0 && getHeading() < 90)
            turnLeft(90 + getHeading());
        // If my coding is undercooked spaghetti
        else {
            System.out.println("Error");
        }   
    }
    
    public void setEast(){  
        // If it's looking NW       
        if(getHeading() > 270 && getHeading() < 0)
            turnRight(450 - getHeading());
        // If it's looking SE or SW
        else if(getHeading() >= 90 && getHeading() <= 270)
            turnLeft(getHeading() - 90);
        // If it's looking NE
        else if(getHeading() >= 0 && getHeading() < 90)
            turnRight(90 - getHeading());
        // If my coding is undercooked spaghetti
        else {
            System.out.println("Error");        
        }
    }
    
    public void run() {
        double x = 0.0;
        double y = 0.0;
        double r = 0.0;     
        double theta = 0.0;
        
        while (true) {
            x = getBattleFieldWidth() / 2.0 - getX();
            y = getBattleFieldHeight() / 2.0 - getY();
            r = Math.sqrt(Math.pow(x,2) + Math.pow(y,2));
            // Find the angle with respect to the horizontal.
            theta = Math.atan((Math.toRadians(y) / Math.toRadians(x)));
        
            /* 
             * Align tank towards the middle
             * depending on the "quadrant" it's in.
             */

            // 1st Quadrant
            if(x < 0 && y < 0){
                setWest();
                turnLeft(theta);
            }
                                    
            // 2nd Quadrant
            else if(x >= 0 && y < 0){
                setEast();
                turnRight(theta);
            }
            
            // 3rd Quadrant
            else if(x >= 0 && y >= 0) {
                setEast();
                turnLeft(theta);
            }
            
            // 4th Quadrant
            else if(x < 0 && y >= 0) {
                setWest();
                turnRight(theta);
            }
            
            // Move to the middle after the final rotation.
            ahead(r);   
        }
    }

Please don't mind the infinite loop, it's just to observe the behavior. run() is the main method of the robot; it is called by default.

I will answer my own question in case someone wonders what the answer is. There were a few fixes:

  1. getHeading() returns a value between 0 <= getHeading() < 360 in degrees. I mistakenly set one of the if conditions to getHeading() < 0 , which isn't possible. I also decided to store the heading in a variable to avoid calling getHeading() multiple times. Here is the fix for that part:

     public void setWest(){ double heading = getHeading(); // If it's looking NW if(heading > 270.0 && heading < 360.0) turnLeft(getHeading() - 270); // If it's looking SE or SW else if(heading >= 90.0 && heading <= 270.0) turnRight(270 - getHeading()); // If it's looking NE else if(heading >= 0.0 && heading < 90.0) turnLeft(90 + getHeading()); // If my coding is god awful else { System.out.println("West | Error"); }

The difference here being 0.0 for the first check being changed to 360.0 0.

  1. Theta was stored in radians instead of degrees. turnLeft() or turnRight() needs a parameter in degrees for it to work properly. Putting in radians won't give you an error. It also won't work as intended. Theta also had to be stored as a positive number, since setWest() and setEast() already accounts for the direction. It was simply fixed by using Math.abs() and Math.toDegrees() . As shown below:

     // Find the abs value of the angle with respect to the horizontal. theta = Math.abs(Math.toDegrees(Math.atan((Math.toRadians(y) / Math.toRadians(x)))));

If you had some lingering questions about it, I hope this helped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM