User talk:Cbrowne

From Robowiki
Jump to navigation Jump to search


Thread titleRepliesLast modified
another "does it make sense to...?" question619:39, 12 October 2011
Is this a sensible way to do it?918:57, 11 October 2011

another "does it make sense to...?" question

I've currently got the bot tracking nicely, and have worked out how to collect and store as much data as I can get from the scanner (x,y,heading,velocity,energy). I know I can also get distance, but if I've understood Pattern Matching correctly I have no real need to store the distance to the bot at the time of scanning.

Anyway, does it make sense to do this for my fire power?

onBulletHit(BulletHitEvent e) {
onBulletMissed(BulletMissedEvent e) {

My motivation is that the bot should conserve energy if it keeps missing, but ramp up the firepower as it scores consecutive hits. Increase and Decrease functions can be pretty much anything (I've currently got them behaving linearly, but there's probably a more optimal equation for the increase/decrease functions).

I think this function is moderately better than simply firing 3.0 all the time, but I haven't looked into the alternatives used by other bots. I'm probably doing a lot of wheel reinvention, but hopefully that's to be expected from a newbie bot author, heh. *wipes sweat from brow*

Cbrowne23:28, 11 October 2011

Yes, it does make sense, although mostly it is dependent on hitrate instead of hit/miss. The are some more things to keep in mind regarding bulletpower. First of all, heavier bullets travel slower. Next to that, you do not want to disable yourself, you'll be a Sitting Duck with 0.0 energy. You can choose your bulletpower depending on distance, when you are close, fire full power as the chance of hitting is bigger. There has been grown a consensus to have the default bulletpower somewhere between 1.7 and 2.4, mostly due to a (theoretical) discussion years ago (somewhere on the old wiki). This number would be an optimum to minimize the energyloss while still be able to punch hard enough. The best way is to pick an opponent and try different (extreme?) powerschemes, so you can see what is happening and come up with something you like. And it gives much more satisfaction that you create by yourself even out of ideas of others, than just to copy some things from others you don't understand.

GrubbmGait00:33, 12 October 2011

That makes some sense to me, too, though I'd also advise experimenting with different schemes to find out what works best.

I think everyone has to find their own balance of reinventing wheels and learning from other bots and the wiki. There are lots of trade-offs either way. But yes, certainly some of that is expected. =)

Voidious02:37, 12 October 2011

Yes, my current calculations for targeting messed up a bit so I discovered on my own that heavier bullets travel slower. They're still messed up, but that was just one facet of their messing up that is now (hopefully) less messed up.

If the consensus is to always fire between 1.7 and 2.4, might it be sensible to "cap" my firepower within those numbers? And instead fire less often if I keep missing past 1.7 (I was planning on implementing a "fire less often" extension anyway, since I'm firing a heck of a lot of shots with minimum power at the moment, mostly because my implementation of pattern matching is both incomplete and horribly broken).

I'm still not 100% sure how you get disabled. Is it purely from trying to do too much in a single turn, or are there other things that cause it?

Cbrowne15:50, 12 October 2011

Particularly when low on energy, firing very low power bullets makes sense because they're faster (easier to hit with) and give you more chances to land some shots and stage a comeback. The opponent could be firing higher power bullets, miss a few shots, and you're right back in it. So I wouldn't completely restrict myself from going below 1.7, but that sounds like a reasonable setup until you get low on energy.

Voidious16:26, 12 October 2011

Oh, and you can disable yourself by firing yourself down to 0 energy, or by taking a ridiculously long time on a turn. If it's the latter, it should say something in the console about stopping your bot for not doing anything in a "reasonable amount of time".

Voidious16:28, 12 October 2011

Yeah, I've had a few disables from infinite loops before, but I didn't realise you also got disabled if you fired down to 0 energy. although that makes sense, since if it didn't disable you at that point you could either commit suicide or fire bullets for free.

I'm currently working on a deltas-based GF system, where I store the "deltas" of previous guesses and attempt to smooth the deltas to be as close to each other as possible (I don't much care if they're close to zero yet, but ultimately if I can determine with some degree of accuracy that the deltas are always offset by a constant or linear amount from zero, I can adjust the function using that offset, so I just want to get the delta function as close to flat as I can, currently). This should give me a fairly accurate gun, unless I'm very much mistaken? The only "magic" being the smoothing function, which would attempt to compensate for over/under guesses by increasing or decreasing the guess offset from the enemy's current position. Taking into account things like bullet velocity (which is a non-linear function, thanks to my "firepower" calculations, eugh) and distance from self to guess to then compute an optimal firing angle.

Thing is, with this system I'm not sure which is a better delta to use. You get more information from a delta that is the distance between your guess and the robot's actual position on that turn (provided you can get both pieces of information, and heaven help us if we can't) but a delta between the gun angle you used and the gun angle you -should've- used might provide more information to the next step (trying to get that delta as low as possible).

Of course, all of this could be surplus to requirement, but any help would be appreciated.

Cbrowne19:39, 12 October 2011

Is this a sensible way to do it?

My AdvancedRobot, Thor, is currently using a static boolean "scanning" to determine whether to turn the radar or not.

This should provide a degree of locking by setting "scanning" to false when we scan a robot, setting it to "true" after we execute, and turning if it's true.

I know it's a naive approach and doesn't lock very well, but it doesn't appear to lock -at all- currently.

Is it my methodology that's flawed, or should I hunt for a bug in the code? (No point debugging if I'm going about it the wrong way from the start).

Cbrowne15:20, 11 October 2011

I think the way most of us do it is to simply scan towards the last known location of the enemy every single tick, making sure we overshoot by a little bit in case they move. I've never put too much effort into radar myself (at least 1v1 radar), because extremely simple solutions tend to work perfectly...

Skilgannon15:47, 11 October 2011

You need to turn it every tick, it's just a question of clockwise or counter-clockwise. The area covered by the sweep of the radar from last tick to this tick is the area that is scanned. So once you scan, you want to reverse the direction you turn the radar, not stop turning it.

Edit: Also, there's an option in Robocode to display the radar arcs, which would help you see exactly what's going on.

Voidious15:59, 11 October 2011

Ah, so I need to refactor "scanning" to function more as a "turn radar left" boolean (if true, turn radar left, if false turn right) and then just toggle it when I find a robot, would that work?

Cbrowne16:02, 11 October 2011

Yep, that would work fine. That kind of scan type is known as an 'Infinity lock' - there's more on it here: One_on_One_Radar. That kind of radar algorithm will skip scans occasionally, so there are a few others on that page which are usually used on bots that aren't in severely limited codesize tournaments. Personally, I recommend the 'turn multiplier lock', it works perfectly and is quick and easy to implement.

Skilgannon17:01, 11 October 2011
Edited by another user.
Last edit: 17:57, 11 October 2011

Wow, that one is excellent. I'm not quite grokking it yet, but experiments have shown that it performs much smoother than my previous implementation.

Now to get the gun to point in the right direction.

I've implemented a function, "turnGunTo" which (in theory) turns the gun to a given (absolute) heading. I'm struggling to get it to work, though, as the gun just appears to spin continuously. Here's my function:

	public void turnGunTo(double newHeading) {
		double oldHeading = getGunHeadingRadians(); 
		// use of normalRelativeAngle means we don't have to decide left or right

And, for reference, the calculateTurnAmount() function:

	public double calculateTurnAmount(double newHeading,double oldHeading) {
		// turn amount is a segment of a full circle, calculated by (circle - leftAngle) + rightAngle;
		return (FULL_CIRCLE - Math.max(newHeading, oldHeading)) + Math.min(newHeading, oldHeading);

What am I doing wrong? Also, is the method abstraction superfluous? It seems so, but in some ways it makes it a little bit more semantically-obvious what I'm trying to achieve.

Cbrowne17:55, 11 October 2011

I think rather just go with this:

	public void turnGunTo(double newHeading) {
		double oldHeading = getGunHeadingRadians(); 
		// use of normalRelativeAngle means we don't have to decide left or right

You can even move the getGunHeadingRadians() into the brackets if you want, and get rid of oldHeading, although that might be going a bit far =). Utils.normalRelativeAngle() will automatically clean up the full circle/double circle/no circle thing for you.

It might be setTurnGunRight though... you'll have to check.

Skilgannon18:01, 11 October 2011

Well the reason I was using oldHeading was because it was originally passed into turnGunTo, but since it's called turnGunTo, and therefore only ever applies to the Gun, I realised I could [read: should] get the value inside the function itself.

Shouldn't it be setTurnGunLeftRadians() (or setTurnGunRightRadians())?

I'm still working on checking which one I want, and what value I want to pass into it (currently calling it with:

turnGunTo(Utils.normalRelativeAngle(getGunHeadingRadians() - e.getBearingRadians())); 

inside my onScannedRobot() function)

You're being uncharacteristically helpful for a random stranger on the internet. Am I supposed to give you cookies or something? :)

Cbrowne18:18, 11 October 2011

Ah yes, it should be radians.

I suggest you read up on e.getBearingRadians() - I think it returns something relative to what your getHeadingRadians() returns. So the absolute bearing from you to your enemy would be getHeadingRadians() + e.getBearingRadians(), which (I think) is what you need to call your turnGunTo function with.

And you don't need to give me a cookie, just work on your bot and provide some more competition =) I might also be procrastinating for my final B.Eng. thesis - it's due in 2 weeks ;-)

Skilgannon18:38, 11 October 2011

Of course, it's me rather stupidly thinking I should compare it to getGunHeadingRadians() instead of getHeadingRadians() - the signing I already worked out was the wrong way around, but thank you for pointing that out too.

I don't know about providing any competition, but I'll give it the best shot I can! If I can ever grok Wave Surfing...

Cbrowne18:57, 11 October 2011