0

I wrote a relatively simple AdvancedRobot that turns its radar around and records all enemies with their velocities. Eventually, I noticed that the robot misses in cases where it's not supposed to miss. I copied the code from Robocode/Graphical Debugging wiki and tested that. Here is the code (Wiki is currently down):

// The coordinates of the last scanned robot
int scannedX = Integer.MIN_VALUE;
int scannedY = Integer.MIN_VALUE;

// Called when we have scanned a robot
public void onScannedRobot(ScannedRobotEvent e) {
    // Calculate the angle to the scanned robot
    double angle = Math.toRadians((getHeading() + e.getBearing()) % 360);

    // Calculate the coordinates of the robot
    scannedX = (int)(getX() + Math.sin(angle) * e.getDistance());
    scannedY = (int)(getY() + Math.cos(angle) * e.getDistance());
}

And the event handler:

// Paint a transparent square on top of the last scanned robot
public void onPaint(Graphics2D g) {
    // Set the paint color to a red half transparent color
    g.setColor(new Color(0xff, 0x00, 0x00, 0x80));

    // Draw a line from our robot to the scanned robot
    g.drawLine(scannedX, scannedY, (int)getX(), (int)getY());

    // Draw a filled square on top of the scanned robot that covers it
    g.fillRect(scannedX - 20, scannedY - 20, 40, 40);
}

The "filled square" is definitely NOT on top of the robot. A couple of screenshots are shown below. It looks like the precision depends on the distance, but I'm not sure. Is this expected, or am I doing something wrong?

Shot 1 Shot 2

user1334767
  • 587
  • 4
  • 17

2 Answers2

1

One reason this may happen is that delivery of the onScannedRobot event is delayed until higher priority events have finished processing. In particular, if a higher priority event handler executes a command to rotate the body, that command will execute before onScannedRobot is called, causing time to advance, robots to move, and your robot's heading to be altered.

Since deferred event delivery causes a variety of problems, I recommend to never execute commands in event handlers. Instead, event handlers should simply inspect, think about, and store information in fields for the main loop to react to. This enables the main loop to look at all available information before committing to a course of action, and to intelligently select which action is most appropriate given the totality of information received. For instance, it could look at a robot hit event on the front combined with a radar detection of an opponent approaching from the rear, and decide that a sideways evasion is more promising than the usual evasion to the rear ...

meriton
  • 68,356
  • 14
  • 108
  • 175
  • What is the main loop? I noticed that `run()` does not get executed at all in the `AdvancedRobot`. I changed my robot's color in `run()` and it had no effect. That's why I'm treating `onStatus()` as my "main loop". My other event handlers do what you just said -- "inspect, think about, and store information". – user1334767 Apr 07 '20 at 00:34
  • The main loop is in `run()`, which does get executed for me. – meriton Apr 07 '20 at 01:10
0

I think I know what the issue is. It does not seem to be documented; if I am wrong, please post a link. ScannedRobotEvent reports bearing relative to previous heading of the robot, i.e., its heading when the last StatusEvent hit. Taking this into account greatly improved my bot's accuracy.

user1334767
  • 587
  • 4
  • 17
  • 1
    It's been ages since I coded for robocode, but I don't recall having to do that. I just checked the code of my old robots, and none of them compensate for body turns, and hit (stationary) targets just fine even if my robot is rotating and driving. Are you sure you're not delaying event delivery by executing a synchronous command that takes multiple turns? – meriton Apr 05 '20 at 04:24
  • 1
    In particular, check that no event handler with a [higher priority](https://robocode.sourceforge.io/docs/robocode/robocode/AdvancedRobot.html#setEventPriority-java.lang.String-int-) has executed a turn command. – meriton Apr 05 '20 at 05:08
  • Thank you. Yes. I am executing all my logic, often including a turn command, in `onStatus` which is probably higher priority than `onScannedRobot`. I did not realize that execution/calculation is started as soon as the `execute()` is called; I thought that all events of this cycle are done while nothing is moving. – user1334767 Apr 05 '20 at 13:54