[Home]GamePhysics/BotSpeed

Robo Home | GamePhysics | Changes | Preferences | AllPages

Robocode's method for determining the speed of your bot is based on the distance you desire to travel (indicated via the setAhead method). It has a few caveats that are worth noting, as listed below. The code Robocode uses (as of version 1.6.1.1) is posted after the three caveats listed below.

Caveat 1

The equation Robocode uses to determine your bot's speed, (int) Math.sqrt(4 * distanceRemaining + 1) - 1), will pick the wrong value when distanceRemaining is between [3.75, 4). It will pick 3, leaving your bot with [.75-1) pixels left to travel. The slowest it can go at that point, however, is 1, so it will necessarily overshoot your desired distance. Without intervention, robocode will just stop your bot at that overshot location.

Your bot will reach this situation when you call setAhead([3.75, 4)) explicitly, or when Robocode slows your bot down to it. Those cases are for [7.75, 8), [8.75, 9), [13.75, 14) plus any distance a multiple of 8, and [14.75, 15) plus any distance a multiple of 8. The same holds for the negative direction.

For example, if your bot's speed is 8 and you call setAhead(22.8), it's speed / distanceRemaining per tick after that will be:

  1. 8 / 14.8
  2. 6 / 8.8
  3. 5 / 3.8
  4. 3 / .8
  5. 1 / -.2 (but robocode just sets distanceRemaining to 0 at this point)

Caveat 2

When your bot has less than 2 pixels to travel Robocode uses a special case. One might expect that if your bot can slow down / speed up to travel exactly that distance, it will. However, that is not the case when your bot's current speed is greater than 2. In that case Robocode falls back to the equation mentioned above. For distances remaining in the range (1, 2) the equation prescribes a speed of 1, which results in your bot taking one tick longer than necessary to travel your desired distance.

Your bot will reach this situation when its speed is greater than 2 and you call setAhead((1, 2)) yourself, or when Robocode slows your bot down to it. Those cases are for (4, 5), (8, 8.75), and (14, 14.75) plus multiples of 8. The same holds for the negative direction.

For example, if your bot's speed is 8 and you call setAhead(22.5), it's speed / distanceRemaining per tick after that will be:

  1. 8 / 14.5
  2. 6 / 8.5
  3. 4 / 4.5
  4. 3 / 1.5
  5. 1 / .5 (when it could be just 1.5/0)
  6. .5 / 0

Caveat 3

If you will be slowing down to get to the next tick, and you set your maxVelocity to a value between your current speed and the one to which you would otherwise be slowing down, you will travel at that max velocity instead.

For example, if your bot's speed is 8 and you call setAhead(-200) your bot would normally travel at speed 6 next tick. However, if you also call setMaxVelocity(7), you will instead travel at speed 7 next tick.

The Code

This is what Robocode does to determine the speed your bot will travel next tick.
	private void updateMovement() {
		if (distanceRemaining == 0 && velocity == 0) {
			return;
		}

		lastX = x;
		lastY = y;

		if (!slowingDown) {
			// Set moveDir and slow down for move(0)
			if (moveDirection == 0) {
				// On move(0), we're always slowing down.
				slowingDown = true;

				// Pretend we were moving in the direction we're heading,
				if (velocity > 0) {
					moveDirection = 1;
				} else if (velocity < 0) {
					moveDirection = -1;
				} else {
					moveDirection = 0;
				}
			}
		}

		double desiredDistanceRemaining = distanceRemaining;

		if (slowingDown) {
			if (moveDirection == 1 && distanceRemaining < 0) {
				desiredDistanceRemaining = 0;
			} else if (moveDirection == -1 && distanceRemaining > 0) {
				desiredDistanceRemaining = 0;
			}
		}
		double slowDownVelocity = (int) ((sqrt(4 * abs(desiredDistanceRemaining) + 1) - 1));

		if (moveDirection == -1) {
			slowDownVelocity = -slowDownVelocity;
		}

		if (!slowingDown) {
			// Calculate acceleration
			if (moveDirection == 1) {
				// Brake or accelerate
				if (velocity < 0) {
					acceleration = Rules.DECELERATION;
				} else {
					acceleration = Rules.ACCELERATION;
				}

				if (velocity + acceleration > slowDownVelocity) {
					slowingDown = true;
				}
			} else if (moveDirection == -1) {
				if (velocity > 0) {
					acceleration = -Rules.DECELERATION;
				} else {
					acceleration = -Rules.ACCELERATION;
				}

				if (velocity + acceleration < slowDownVelocity) {
					slowingDown = true;
				}
			}
		}

		if (slowingDown) {
			// note:  if slowing down, velocity and distanceremaining have same sign
			if (distanceRemaining != 0 && abs(velocity) <= Rules.DECELERATION
					&& abs(distanceRemaining) <= Rules.DECELERATION) {
				slowDownVelocity = distanceRemaining;
			}

			double perfectAccel = slowDownVelocity - velocity;

			if (perfectAccel > Rules.DECELERATION) {
				perfectAccel = Rules.DECELERATION;
			} else if (perfectAccel < -Rules.DECELERATION) {
				perfectAccel = -Rules.DECELERATION;
			}

			acceleration = perfectAccel;
		}

		// Calculate velocity
		if (velocity > maxVelocity || velocity < -maxVelocity) {
			acceleration = 0;
		}

		velocity += acceleration;
		if (velocity > maxVelocity) {
			velocity -= min(Rules.DECELERATION, velocity - maxVelocity);
		}
		if (velocity < -maxVelocity) {
			velocity += min(Rules.DECELERATION, -velocity - maxVelocity);
		}

		double dx = velocity * sin(heading);
		double dy = velocity * cos(heading);

		x += dx;
		y += dy;

		boolean updateBounds = false;

		if (dx != 0 || dy != 0) {
			updateBounds = true;
		}

		if (slowingDown && velocity == 0) {
			distanceRemaining = 0;
			moveDirection = 0;
			slowingDown = false;
			acceleration = 0;
		}

		if (updateBounds) {
			updateBoundingBox();
		}

		distanceRemaining -= velocity;
	}


I have overcome all but a few cases of these sub-optimal behaviors, but it has been a real pain to discover them and make workarounds. Can I open up a discussion about getting them changed in Robocode's game engine, or is that just too radical of an idea? I don't know if there are any bots that rely on these quirks, but if not, it may be worthwhile to save future robocoders the pain I have gone through. -- Simonton

This is nice, just the kind of optimal movement im looking for in yoda. Mined if i use it, to your credit of course Simonton -- Gorded

I'll chime in with my opinion on this: I have no issue with fixing these things. I doubt there will be a large impact in practice, but where there is an impact I would expect a positive impact because to my knowledge everyone had assumed things worked 'intuitively', because I've never heard anyone else bring up this issue. -- Rednaxela

Any change in the "physics" code will impact negatively bots that use precise prediction and/or are tweaked to preform best in a world with these quirks. Future robocoders would of course welcome these changes, but I think it is a bit of a radical change. -- ABC

Well, do you know of any bots that do consider these unusual quirks in precise prediction? I don't know of any, and if there indeed aren't any, resolving these quirks wouldn't negatively impact them. As far as bots that are just manually tweaked, I really don't think these quirks are big enough to really change the balance measurably. In Simonton's bug report for this however, Fnl did say he'd make a prototype with these tweaks resolved. I believe it would be worthwhile to test a fair number of pairings with that, with focus on precise predictors like most surfers, and on some highly tweaked bots like Raiko. I do strongly suspect there will be no measurable impact on existing bots, but it testing of course would be important. -- Rednaxela

Lots of surfers use a copy the internal robocode code to simulate future positions, if you change that code those bots will lose precision. That loss will be measurable, imo. -- ABC

I haven't looked over this particular issue in-depth enough to say if I think it will affect bots' predictions, but I'm definitely against changing anything in the current Robocode physics engine. We've already changed a lot, and more than I probably would have, with fixing tweaks on bullet collisions and adding new API calls (which greatly affects competitiveness of legacy CodeSize-restricted bots). I don't mean to sound negative, that's just how I feel about it. My take on it is that I think this kind of enhancement should be poured into Robocode 2. -- Voidious

I understand that game physics are a sacred thing. Like Voidious, I would not have supported a change in the bullet collision code if asked, and we saw it made a very large difference in the scores of bots that used the extra information gained by them vs. those that did not. However, in this case I would support the change, since I believe it's the way the physics engine was probably intended (or if not, should have been), I doubt it would make much difference to legacy bots, and the benefits of intuitive-izing the physics for future robocoders could be substantial. (Now that our 1v1 king is a goto surfer, I expect more coders to take up that style.) As for those space-saving API methods ... are any of those new in the last year? Because if so I'll be taking advantage of them! :) -- Simonton

I would think that, if we are building a new set of rumble stats, it would be interesting to compare a version with a 'fixed' physics engine and the regular engine. Perhaps just do a test with a relatively small number of bots, but be sure to include several of each type of surfing. The thing is, all WaveSurfing bots were designed with the physics *as we intend to change them to* in mind, *not as they actually are*. For most TrueSurfers? it won't make any difference, because they all call setAhead(Infinity). It's when you are trying to accurately predict deceleration of setAhead(<20) that things start getting fuzzy. AFAIK no bots implement any way to get around the caveats listed above, instead assuming that the engine will make the smartest choice for them. Unfortunately this is not true. OTOH Simonton, if you've figured out a 'smart goto' method that fools the bot engine into doing the right thing, I'd be very grateful if you shared it =) -- Skilgannon

Guys, I have now implemented the [code] provided by Simonton on SF in a special version of Robocode 1.7, that is version 1.7.0.10 Alpha, which you can download from [here]. I can't see a big impact, but perhaps you guys can? If it has no real impact, I suggest that we incorporate Simontons fix into Robocode (later), as his code is correct according to Robocode's own rules, and because the code is simpler and easier to understand. --Fnl

IMO the fix has to be incorporate 'couse will be easier implement precise prediction (time ago i've was getting crasy to understand why mine version wasn't working), and obiusly robocode's engine has to be perfect ^^ --Darkstorm?


Robo Home | GamePhysics | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited February 24, 2009 14:23 EST by 85-18-37-71.ip.fastwebnet.it (diff)
Search: