Menu

#368 Issues with sentries

1.9.1.0
closed
1
2015-01-23
2014-02-23
No

I found some bugs concerning the sentries:

1) text field in UI is set to wrong value after entering an invalid value (e.g. 20)
NewBattleRulesTab.java, function "getSentryBorderSizeTextField":
replace
sentryBorderSizeTextField.setText("" + battleProperties.getInactivityTime());
with
sentryBorderSizeTextField.setText("" + battleProperties.getSentryBorderSize());

2) BattleManager ignores custom sentryBorderSize
BattleManager.java, function "startNewBattle(BattleSpecification spec, ...)":
replace
battleProperties.setHideEnemyNames(spec.getHideEnemyNames());
battleProperties.setSelectedRobots(spec.getRobots());
with
battleProperties.setHideEnemyNames(spec.getHideEnemyNames());
battleProperties.setSentryBorderSize(spec.getSentryBorderSize());
battleProperties.setSelectedRobots(spec.getRobots());

3) bad code for placement of sentry robots
- constants instead of real sentryBorderSize
- unequal distribution on battlefields with high aspect ratio: robots appear mostly on the short sides of a 400x5000 battlefield
- no real random distribution (high random values for x have higher chance to lead to a placement on a horizontal border, ...)
- wrong variable in lines with modulo operator
- wrong check for inside/outside sentryBorder (wrong limits and using *Width-Variables on y-Values)

I therefore suggest replacing the code

        if (!valid) {
            final Random random = RandomFactory.getRandom();

            double maxWidth = battleRules.getBattlefieldWidth() - RobotPeer.WIDTH;
            double maxHeight = battleRules.getBattlefieldHeight() - RobotPeer.HEIGHT;

            double halfRobotWidth = RobotPeer.WIDTH / 2;
            double halfRobotHeight = RobotPeer.HEIGHT / 2;

            int minBorderWidth = Math.max(RobotPeer.WIDTH, (100 - RobotPeer.WIDTH)); // FIXME: Replace 100 with constant
            int minBorderHeight = Math.max(RobotPeer.HEIGHT, (100 - RobotPeer.HEIGHT)); // FIXME: Replace 100 with constant

            for (int j = 0; j < 1000; j++) {
                double rndX = random.nextDouble();
                double rndY = random.nextDouble();

                x = halfRobotWidth;
                y = halfRobotHeight;

                if (isSentryRobot()) {
                    if (rndX / battleRules.getBattlefieldWidth() > rndY / battleRules.getBattlefieldHeight()) {
                        x = halfRobotWidth + rndX * maxWidth;
                        y = halfRobotHeight
                                + ((rndY * 2 * minBorderHeight - minBorderHeight) + battleRules.getBattlefieldHeight())
                                        % maxHeight;
                    } else {
                        x = halfRobotWidth
                                + ((rndX * 2 * minBorderWidth - minBorderWidth) + battleRules.getBattlefieldWidth())
                                        % maxWidth;
                        y = halfRobotHeight + rndY * maxHeight;
                    }
                    // Make sure that the border sentry robot is not placed outside the border sentry robot border
                    if (x > minBorderWidth && x < (battleRules.getBattlefieldWidth() - minBorderWidth)
                            && y > minBorderWidth && y < (battleRules.getBattlefieldHeight() - minBorderWidth)) {
                        continue; // loop again to find better location
                    }
                } else {
                    x = RobotPeer.WIDTH + rndX * (battleRules.getBattlefieldWidth() - 2 * RobotPeer.WIDTH);
                    y = RobotPeer.HEIGHT + rndY * (battleRules.getBattlefieldHeight() - 2 * RobotPeer.HEIGHT);
                }

                bodyHeading = 2 * Math.PI * random.nextDouble();
                gunHeading = radarHeading = bodyHeading;
                updateBoundingBox();

                if (validSpot(robots)) {
                    break;
                }
            }
        }

with

        if (!valid) {
            final Random random = RandomFactory.getRandom();

            double maxWidth = battleRules.getBattlefieldWidth() - RobotPeer.WIDTH;
            double maxHeight = battleRules.getBattlefieldHeight() - RobotPeer.HEIGHT;

            double halfRobotWidth = RobotPeer.WIDTH / 2;
            double halfRobotHeight = RobotPeer.HEIGHT / 2;

            int sentryBorderMoveWidth = battle.getBattleRules().getSentryBorderSize() - RobotPeer.WIDTH;
            int sentryBorderMoveHeight = battle.getBattleRules().getSentryBorderSize() - RobotPeer.HEIGHT;

            for (int j = 0; j < 1000; j++) {
                double rndX = random.nextDouble();
                double rndY = random.nextDouble();

                if (isSentryRobot()) {
                    boolean placeOnHorizontalBar = random.nextDouble() <= ( (double)battleRules.getBattlefieldWidth() / (battleRules.getBattlefieldWidth() + battleRules.getBattlefieldHeight()) );

                    if(placeOnHorizontalBar) {
                        x = halfRobotWidth + rndX * maxWidth;
                        y = halfRobotHeight + (sentryBorderMoveHeight*(rndY * 2.0 - 1.0) + maxHeight) % maxHeight;
                    }
                    else {
                        y = halfRobotHeight + rndY * maxHeight;
                        x = halfRobotWidth + (sentryBorderMoveWidth*(rndX * 2.0 - 1.0) + maxWidth) % maxWidth;
                    }
                } else {
                    x = RobotPeer.WIDTH + rndX * (battleRules.getBattlefieldWidth() - 2 * RobotPeer.WIDTH);
                    y = RobotPeer.HEIGHT + rndY * (battleRules.getBattlefieldHeight() - 2 * RobotPeer.HEIGHT);
                }

                bodyHeading = 2 * Math.PI * random.nextDouble();
                gunHeading = radarHeading = bodyHeading;
                updateBoundingBox();

                if (validSpot(robots)) {
                    break;
                }
            }
        }

4) a proper check for sentryBorderSize is missing
Now there is just a check in the user interface (>= 50), but this does not work if the battle is started calling the RobocodeEngine directly with BattleSpecification. A check similar to the one for the minimum battlefieldSize would be great.

5) general ideas for the sentries
- an API-function to get the number of sentries, similar to getOthers()
- bullets of sentries should destroy themselves as soon as they leave the border area (like crashing a virtual wall) in order not to influence the game (hit normal robots' bullets)
- the initial positions for normal robots could be set to lie not on the sentry borders (in a bad case a robot could be catched within a corner blocked by two sentries on each side)

Discussion

  • Flemming N. Larsen

    Thanks for having put a great effort into the new Sentry robot.
    You have very sharp eyes. I will need to examine all points in detail. You are definitely right in most cases. :-)

    Regarding point 5) general ideas for the sentries... bullets of sentries should destroy themselves as soon as they leave the border area ...
    Well, it was made this way on purpose, as a robot at one side on the border should be able to hit a robot hiding on a border on the other side, which means that the bullet must be able to pass through the battle area. But, when it hits a robot the robot should take no damage. But you are right that the bullet should not interfere with the battle "in between" by stopping other bullets. :-)
    You are right about the rest, of course.

    In general, I like all your good observations, and I will fix as many as possible - if not all - for the coming version of Robocode.

     
  • Flemming N. Larsen

    • labels: --> BorderSentryRobot, border, sentry
     
  • Flemming N. Larsen

    Fixed and implemented in version 1.9.1.0

     
  • Flemming N. Larsen

    • status: open --> closed
    • Group: 1.9.0.0 --> 1.9.1.0
     

Log in to post a comment.