View source for Talk:XanderCat
← Talk:XanderCat
Congrats on breaking the 50% barrier. Seems that you have the planning of your bot on scheme, now it's just the translation into the right code. One small remark: You don't have to have 'zillions of versions' present in the rumble, the details of older versions still are available when not in the participants list anymore. Comparisons between two versions are quite easy to do like [1] . Just click on your bot in the rankings, then the details and a few older versions are shown. Good luck with your further development! --GrubbmGait 08:37, 25 May 2011 (UTC)
- Thanks GrubbmGait, though I'm not sure how much praise I deserve for being officially average. :-P I'm trying out a slightly revised version today, version 2.1. No major component changes, but it modifies the bullet firing parameters, driving parameters, some segmentation parameters, and has improved gun selection. Skotty 20:43, 25 May 2011 (UTC)
Contents
Version 3.1
Interesting results for version 3.1. No real change in rank from 3.0, but using an entirely new drive. I've done away with the borrowed wave surfing drive from BasicGFSurfer and replaced it with a drive of my own design.
Despite the new wave surfing drive (which I will call a Stat Drive) which I crafted almost entirely from scratch, I think it shares a lot in common with other wave surfing drives. It's just naturally where you end up when working out the best way to drive. I really haven't tried to tweak the segmentation yet, so I think it can be further improved with a few parameter changes.
Here is what my new drive does (you will likely see a lot in common with other drive strategies out there):
- Segmentation - Much like other wave surfing drives, my Stat Drive supports segmentation. I can't remember what it is actually segmenting on right now (don't have the code in front of me at the moment). I'll add that detail later. It is very easy to change the segmentation parameters. The Stat Drive relies on a seperate component to determine the segment or combination of segments, and the segmenters can be swapped in and out easily.
- Tracking danger - Each segment has a fixed number of "buckets" or "bins" that represent the danger at a particular "factor", where a factor represents an angular offset of the robot from an original bearing of the bullet wave origin to the robot at the time the bullet was fired. When a particular factor is determined to be more dangerous, a value is added to the corresponding bin or bins around that factor. Initially when I wanted to add danger, I just added to one bin. One thing I did steal from from the BasicGFSurfer wave surfing drive was the manner of adding danger to all the bins, trailing off sharply from the most dangerous bin. I don't know why I didn't think to do this initially. Once my eyes glanced over it, it was obvious it was what I should have been doing from the start.
- Bullet Hits - The most dangerous of events -- actually getting hit by a bullet. When hit by a bullet, the Stat Drive records danger of a certain amount (lets say a value represented by the variable d) to the matching bin of corresponding segment. One tenth that amount (d/10) is currently added to all other segments, though this is just experimental; I may modify or remove that effect as I tune it a bit more.
- Wave Hits - When a wave hits (but not necessarily a bullet hit), the Stat Drive currently records one fifth the amount of danger (d/5) for the matching bin of the corresponding segment. Thea idea being that the opponents gun, likely being a "Guess Factor" gun, might be more likely to aim for that bin next time, so lets try to avoid it. This also probably needs some fine tuning. Part of the same experiment as with bullet hits, adding one tenth of that amount (d/50) is added to all other segments.
- Wall Avoidance - While I wrote it from scratch myself, wall avoidance right now is doing pretty much the exact same thing as the "wall stick" approach. I have some ideas that would be fancier, but the "wall stick" approach works for now.
- Rolling danger - Rolling danger is the idea of removing danger previously added from bullets or waves that are over a certain age. The Stat Drive is not doing this right now, but I'm planning on experimenting with the idea.
- Figuring out where it can get to - One of the first steps to avoiding a bullet wave is determining how far you can go in each orbital direction before the bullet hits. At first I used some crude approaches to this with the Stat Drive, but they just won't cut it if I want to be really competitive. I now have it predict our position into the future, taking pretty much everything into account (turn rates, acceleration/deceleration rates, wall smoothing, etc) to make the prediction as accurate as possible.
- Figuring out where to go - once we know how far we can go, we have to decide where in that range we want to go. I'm experimenting with a few approaches. For now, it looks for the bin with the lowest value and heads there.
- Figuring out how to get there - Once we know where we want to go, we have to figure out how to get there. This seemed simple enough, but one problem I ran into was overshooting the target and being in the wrong place when the bullet arrives. This problem turned out to be significant in my testing. So I had to do additional work to ensure that if I will reach my target before the wave hits, I slow down before getting there so I land right on target. This sounds easier than it actually was to implement.
Where to go from here?
Performance was roughly equal in the rumble to the BasicGFSurfer drive. I need to tweak the segmentation approaches and parameters. I need to tweak the manner of adding danger. And I need to play around with rolling danger to see what effect that has. Once that is done, I don't believe I will make any more changes to the Stat Drive or it's use in XanderCat.
I may employ other drives in combination at some point using a "drive selector", an ability that is built into the Xander framework. For example, I would like to build a drive and gun built specifically for "mirror" bots that mirror their opponents drive; the drive selector would switch to these components whenever a mirror bot is detected.
Outside of drives, my Stat Gun is still a bit crude. I know I can improve there. And then I also have a few other little tricks up my sleeve I would like to try when I have the time.
It's neat to see you taking such a systematic approach with robocode! If I may a few suggestions:
- If I understand correctly, you add d/10 danger to every bin (except the one that hit you) rather than (in addition to?) adding bin-smoothed danger to each bin. I don't think this will help anything. The bin-smoothed danger should be enough.
- Logging hits from every wave, regardless of whether the other robot hit your robot, will give you a flatter movement; however, you may not actually want a flatter movement, even against GF guns. Before wave surfing was invented, I imagine that GF guns didn't roll their averages very much. Because of this, a flat movement will be worse against these guns. Rather than giving the enemy a flat movement to shoot at (which will make their targeting very close to random), you should move to the same GF repeatedly. When they hit you there, you know there is a peak in their stats, so you move somewhere else, and hopefully they keep shooting there for a while, allowing you to dodge bullets. Did I explain that well?
(I had thought of doing something like that but didn't for the reasons described above. It sounds rather similar to YersiniaPestis, but without the adaptive weighting of the flattener.) --AW 19:52, 6 June 2011 (UTC)
Nice job! Implementing Wave Surfing correctly can be a huge undertaking. My first suggestion would be to try just disabling the "every wave" logging of hits. You're right this should make you more unpredictable to learning guns. What most of us have found is that straight dodging from bullet hits actually works better against the vast majority of guns - only against the best guns does a "flattener" (what we call that mode) help. But more importantly, a flattener also destroys your scores against simple targeters.
I see you're getting 80% vs Barracuda and 88% vs HawkOnFire. Those could both be over 99% with no segmentation. My best advice would be to work on distancing, dive protection, and ironing out bugs until you can get that before trying to refine other aspects. Working on other stuff will only make it harder to fix the core stuff, and you may have to re-tune everything anyway once it's fixed. (Just turning off the flattener may go a long way!)
Good luck! --Voidious 20:37, 6 June 2011 (UTC)
- Thanks for all the suggestions. I've been intentionally trying to come up with a lot of the ideas and code myself, as that makes it more rewarding for me. On the down side, this has made it harder to learn all the terminology used by the Robocode community. Not until both of your comments did I know what a "flattener" was, though I had seen the term pop up here and there. I hadn't spent too much time thinking about what the effects of it would be against different opponents, but your comments give me food for thought. I actually have my system set up now to run different configurations of my robot against a test base of robots, so I am now at the point where I can see some real results rather than just trying to deal with the theoretical. I'll try turning off the flattening and see what happens. Skotty 22:18, 6 June 2011 (UTC)
- I assume by "distancing", you mean trying to keep my robot a reasonable distance away from the opponent. I was thinking maybe try to refine my drive path so that it will move slightly away from the waves if the wave origins are too close, and possibly favoring non-smoothing directions when near a wall and the calculated danger in each direction is similar. "Dive protection" as I understand it is not driving towards the enemy excessively; I don't see how this would happen except to a limited degree when wall smoothing, or on startup before bullets start flying (at the moment, when no bullet waves are in action, XanderCat will just move in a straight but wall-smoothed path, causing it to circle around the edges of the field; I should probably change this to make it move into a more desireable position before bullets start flying, rather than relying on chance). Skotty 17:46, 7 June 2011 (UTC)
Version 3.2
Had a bad night of tweaking where everything I did seemed to make my robot worse. I've turned off the flattening but I don't think I have a proper test bed of opponents to determine what kind of effect it might have. It did increase the score on Barracuda and HawkOnFire, but only to the about 90%. I did, however, finish some new anti-mirror components. PolishedRuby 1 is soooo dead. :-D I haven't tested against any other mirror bots yet, but my tests against PolishedRuby put a big smile on my face. As you might guess, when mirroring is detected, I have a drive and gun that work in tandem, where the drive plots a semi-random route in advance that the gun can process to fire on the mirror of the future positions. Awesome. My framework makes it easy to add it on to any existing gun combinations. It's not perfect, but it gets the job done, and might can be improved a bit more. With the mirror components active, my gun hit ratio on PolishedRuby jumped from something very sad up to a wicked 70%.
I've got my score on Barracuda up to the low 90s, and HawkOnFire up to about 98%. I've disabled the flattening, and I've implemented a new drive that takes command on the first few moments of a round to try and obtain better positioning before bullets start flying. Also, my StatDrive will now change it's angle a little to back away from waves when it deems itself too close to them. I also have the anti-mirroring operational. I was going to try and update my StatGun for this version (3.2), but I think I may hold off on that until version 3.3. I want to see what effects the changes so far have made.
Rumble Results
Fascinating results in the rumble. Despite winning fewer rounds than version 3.1, version 3.2 ranks about 30 places higher. Presumably by beating the simpler robots by quite a bit more than previously. Lots of variations in the PBI. I'll have to play around with some of the ones version 3.2 performed poorly against. I'll probably come up with a way to turn the flattening on and off automatically, which I think some of the other robots do. Only other thing I can think of to do for driving is to put some work into not running into the opponent robots, which is something I have ignored previously. AntiMirror components rocked.
Next version I will update the StatDrive. I know of a couple of ways it could be reasonably improved. And after that? Not sure...
My suggestion is that you need to up your score against Barracuda - there are still lots of points to be gained there. Until you are getting 99+% you are losing points due to not getting far enough away. If you watch your battles against Barracuda note every bullet hit and think about what your bot could have done differently to avoid it, be it reversing, being further away, not being against a wall, etc and then code something to get it to (not explicitly, but generally) avoid that situation next time. I'm not sure how your drive system works but in my bots I modify the desired angle towards the orbit centre proportional to the distance from the orbit centre, so as it gets farther away it moves towards the centre, and as it gets closer it moves away. Anyways, some food for thought. --Skilgannon 08:58, 8 June 2011 (UTC)
- Were you looking at version 3.2 or 3.3? Version 3.2 gets about 93% against Barracuda. Yeah, it could be better. Version 3.3 in the rumble only got 80% against Barracuda. I can't explain that. I've run 3.3 myself against Barracuda many times, and it always gets around 93%, same as version 3.2. Ignoring that anomaly, where is that other 7%? It may be from collisions. Right now, XanderCat ignores collisions with the opponent, and can get stuck rammed against them. Also, it may be from getting too close when wall smoothing. I had mentioned the possibility of moving away from the wall in cases where danger each direction is similar in order to not get jammed against the wall as much, but I haven't implemented that idea yet. Skotty 14:21, 8 June 2011 (UTC)
- I'd suggest hunting for bugs really. Even 98% against HawkOnFire, is low enough that I think that notable surfing bugs could be likely, (and having a large hidden influence against other bots). It should be possible to get to 99.9% or so if the surfing algorithm is reasonably precise and the bugs of implementation are worked out. --Rednaxela 14:48, 8 June 2011 (UTC)
- Version 3.4 moves up the ranks, but still gets 98% on HawkOnFire and 95% on Barracuda. I believe this is due to not having any dive protection when wall smoothing (I do employ distancing, if I understand correctly what this is -- attempting to back away some when in too close -- but this doesn't help if you are getting smoothed into a wall). I'm still working on a good solution for dive protection near walls. I tried a few things when developing version 3.4 but haven't come up with something that improves performance yet. Perhaps for the next version. -- Skotty 17:16, 9 June 2011 (UTC)
A quck note for you in relation to ucatcher. That bot is uses bullet shielding. Basically, the better you shoot at it, the better chance it has to deflect your shot. Not too hard to detect when it happens either, just check the bulletHitBullet event and see if it happens a bunch. If so, don't aim for the center of the bot, but an edge of it instead. --Miked0801 23:31, 10 June 2011 (UTC)
Version 3.6
Interesting results in the Rumble. Compare this version to version 3.4, and check out the PBI graph. It seems I inadvertently tuned it against top bots, but somehow lost a bunch of points on the middle of the pack. With a little more analysis and testing, I think I can finally jump up in the ranks again. I suppose there could still be some hidden bugs I need work out, too. The drives on 3.4 and 3.6 are the same but the gun on 3.6 is far more advanced. It should be notably higher in the ranks. Oh well. I guess I have to make version 3.7 before taking a break now. :-)
PBI
Okay, with version 3.8, I am frighteningly close to being able to tie or even beat some of the top and famous robots (note that I haven't been using flattening either), yet I am still way underperforming on the middle of the pack. Crazy! One problem being that apparently my small test bed of robots is not properly representative of the whole. I guess I need to go round up some problem bots for me and figure out what gives. Skotty 23:53, 12 June 2011 (UTC)
- One tip: when trying to improve against certain bots, make sure you run a lot of battles of your previous version against those bots, too. It takes hundreds of battles to get a real accurate result in any pairing, so the rumble result isn't really gospel. You can easily find yourself chasing phantoms (mistaking bad luck for underperforming). --Voidious 00:02, 13 June 2011 (UTC)
- A remark about version 4.0. Your wrapper against bullet shielders does have a very big offset. I use fixed 0.6 distance either way and my bullets are only occasionally intercepted. Your offset of 5 or 10 does influence your performance against the 'pack' to much. There are a lot of bots out there that give you a hard fight although ranked lower, as they do not squeeze every percent out of the minor bots. Compare your stats against a bot on a rank you wish to have, see your strengths and weaknesses compared to it and handle accordingly. --GrubbmGait 22:48, 15 June 2011 (UTC)
- The bullet shielding effect only engages if there are a set number of consecutive bullet-hit-bullets, so I think I'm okay on most of the pack. It would only happen by rare chance against a non-bullet-shielding bot (or so my theory goes). Skotty 23:43, 15 June 2011 (UTC)
From Robin
Holy Disco Batman, I'm stuck in the 70's!
HOT vs RamBots
He's no longer in the rumble, but there's a bot that might make you think twice about using HOT vs RamBots: MaxRisk. =) --Voidious 20:07, 21 June 2011 (UTC)
- Ramming messes with all my hit ratios, which was making the gun selection almost random against them, and occasionally XanderCat would miss a shot against a rammer follwing almost directly behind (probably due to a guess factor shot). This is why I added the extra decision to only use Head-On targeting against rammers (and note, the head-on targeting only takes effect when opponent is within very close range). I'll have to check out the bot you linked to see what it does. At very close range, I don't see how head-on could be a bad choice. At distance while they are closing, yes, head-on might not be best. But at distance, my regular gun selection is active. This makes me think, however, that I could be doing something better when the rammer is at distance, as my regular gun selection, as previously mentioned, is usually messed up by the wild hit ratios that occur when the opponent is constantly ramming.
- I haven't seen MaxRisk in battle for a while. But at the time he was released, Dookious was using HOT as part of his anti-ram mode and MaxRisk crushed him into little pieces. I think the issue is that MaxRisk uses prediction, so he's ramming the spot you're moving towards, not just heading straight at your current position. --Voidious 17:35, 22 June 2011 (UTC)
Rethink / XanderCat 4.8+
I lost some ranks when I refactored the guess factor and wave surfing code in version 4.7, and have yet to get them back. But I'm still convinced the refactor was a good thing.
I've ironed out all the major bugs, and if I watch XanderCat in some battles, I don't see it doing anything obviously wrong. This got me thinking about how I handle segmentation again. I think my philosophy on balancing segments for comparison was wrong in the drive, and am changing it in version 4.8. I also plan on excluding certain segment combinations that when I think about them, just don't make much sense (like using just opponent velocity). I think this should improve performance.
Beyond this, I'm not sure what I would do next to try to improve. I could run zillions of combinations of segments and parameters just to see what seems to work better against a large groups of robots that I think is representative of the whole. Not sure I will go to that extent though. Skotty 01:09, 22 June 2011 (UTC)
I'd definitely say that you still have non-negligible bugs / issues with your surfing. Looking at Barracuda and HawkOnFire again, compared to DrussGT we have 95.82 vs 99.83 and 97.91 vs 99.91. In other words, both are hitting you ~20x as much, totally unrelated to how you log/interpret stats (because they're HOT). Not to be a downer - XanderCat is coming along great and you appear to have a really robust code base. Or if you're burning out on 1v1, how about Melee? It's a much different animal. =) --Voidious 01:28, 22 June 2011 (UTC)
- It appears as though I'm on the right track with version 4.8. Just for you Voidious (grin), in addition to other changes, I configured it to maximize scores against head-on targeters, which raised the Barracuda and HawkOnFire scores to 98.98 and 98.76 respectively (2 battles each so far). To get the rest of the way to DrussGT levels, I will need to tweak my dive protection a little more; it still causes XanderCat to stall near a wall long enough to be hit every once and awhile. I may need to also tweak my "Ideal Position Drive" a bit more too, as it still drives too close to opponents occasionally when trying to reach an ideal position (the Ideal Position Drive drive runs at the start of each round before bullets start flying).
- Nice. =) For better or worse, the RoboRumble greatly rewards bots that can annihilate HOT and other simple targeters, so you might be surprised by how much of a ranking increase you can find by polishing that aspect of your surfing. It's not always the sexiest thing to work on, nor the most fun... But more importantly (to me), it's just a good way to verify that your surfing is working how it should. I can't find a good quote, but both Skilgannon and Axe have commented on the fact that if even a single HOT shot hits you, there's something wrong. --Voidious 17:51, 22 June 2011 (UTC)
- Very true. A wavesurfing bot should be able to dodge all *known* bullets perfectly, and HOT is only known bullets. Unless there is something funky like bullets fired from 20 pixels away, or a gun cooling time of 1 tick, all bullets *should* be avoidable.--Skilgannon 11:54, 23 June 2011 (UTC)
- Nice work, but just as a note, some might think me crazy, but I don't think *any* explicit dive protection is necessary for this sort of thing really. My surfing bots RougeDC and Midboss (same movement code), get 99.5% against HawkOnFire with no explicit dive protection whatsoever (and in certain past versions they did even better IIRC). The thing is, as I see it, dive protection is completely unnecessary if the surfing properly considers how movement changes botwidth. I much prefer it that way as it doesn't require tweaking/tuning to get right. Just my 2 cents on dive protection. --Rednaxela 20:50, 22 June 2011 (UTC)
- Well, I'd still call it "dive protection". =) But yes, I agree that multiplying danger by bot width (or dividing by distance, which I think is still what I do) is about the most elegant solution. And I doubt anyone's calling you crazy. Do any top bots since Phoenix use special cases? I guess I'm not sure about GresSuffurd or WaveSerpent. --Voidious 21:14, 22 June 2011 (UTC)
- Oops, I guess I'm out of touch. Diamond still has special cases, despite taking this approach - it scales the danger more than linearly beyond a certain threshold, as Dookious did. Maybe I'll test removing that, just for the sake of argument. =) I think it will lose points, though. Sure, for one bullet, the danger scales linearly with bot width. But that bot width affects future waves too. I suppose whether this is "explicit dive protection" would be up for debate. --Voidious 21:24, 22 June 2011 (UTC)
- Hmm...considering my own robot width when surfing...why didn't I think of that before? Guess what new feature will be in version 5.0? :-D Skotty 22:44, 22 June 2011 (UTC)
- Rather than multiplying danger by bot width, I prefer integrating over the affected bins, since many bins can be covered at close range... ;) --Rednaxela 22:49, 22 June 2011 (UTC)
- GresSuffurd has 2 lines of code handling both distancing and dive protection. This code hasn't been changed for years. The dive protection just handles the angle, not the danger. My latest effort was to use the summed danger of all covered bins instead of the danger of one bin to decide which direction to go(forward, stop, backward), but this approach let me fall out of the top-10 ;-) Sometimes a simple, proven, not optimal solution works better than a theoretical optimal solution. I do like the idea of letting danger instead of angle decide when to change direction though, and I will continue in this path with the next versions. Welcome to the dark caves of Robocode. --GrubbmGait 23:25, 22 June 2011 (UTC)
- If it's ever pitch black, watch out for GrubbmGait's pet Grue ;) --Rednaxela 00:21, 23 June 2011 (UTC)
- I think the reason these approximations often work better is that we're using a discrete system, and often the optimal assumes continuous. I think the other reason is that the optimal system often gets horrendously complex and bugs creep in, making the simple system actually more accurate. But these are just thoughts =) --Skilgannon 11:54, 23 June 2011 (UTC)
- Well, in this specific case, I would say the "optimal system" doesn't get more complex. I would argue integrating over botwidth is less complex, because:
- It also implicitly does the most important part of what many people use bin smoothing for
- There aren't really any parameters to need to tune
- To be clear, a very very very tiny amount of bin smoothing is still useful, to cause it to get as far as possible from danger, but the integrating over botwidth really does the important part of the smoothing. Actually, I suspect that if people get lower scores with integrating over bins, it's because it overlaps with their existing smoothing which has become far too strong.
- Basically, sometimes the "optimal system" may actually be less complex. It can reduce how many tunable parameters are needed, and also replace multiple system components necessary to fill a purpose. --Rednaxela 13:37, 23 June 2011 (UTC)
- Well, in this specific case, I would say the "optimal system" doesn't get more complex. I would argue integrating over botwidth is less complex, because:
- I also think we tune around a lot of arbitrary stuff in our bots. I remember PEZ and I often lamented how something we'd set intuitively, and "couldn't possibly be optimally tuned!", resisted all attempts to tune it. I imagine that's sometimes the case when an existing simple/approximate approach performs better than the "new hotness totally scientifically accurate" approach. Dark caves indeed. =) --Voidious 14:48, 23 June 2011 (UTC)
- For the record, I don't use binsmoothing, as I don't see the purpose of it. If a safe spot is near danger or far away from danger does not matter, it is still a safe spot. --GrubbmGait 19:16, 23 June 2011 (UTC)
- Oops, I guess I'm out of touch. Diamond still has special cases, despite taking this approach - it scales the danger more than linearly beyond a certain threshold, as Dookious did. Maybe I'll test removing that, just for the sake of argument. =) I think it will lose points, though. Sure, for one bullet, the danger scales linearly with bot width. But that bot width affects future waves too. I suppose whether this is "explicit dive protection" would be up for debate. --Voidious 21:24, 22 June 2011 (UTC)
Case Analysis
Just out of curiousity, does anyone have any insight as to why deo.FlowerBot 1.0 drives so predictably against gh.GresSuffurd? I can't figure it out. FlowerBot just drives around in a big circle when fighting GresSuffurd, while seeming far less predictable against XanderCat 4.8. Maybe it's a distance thing? Looking a little closer, I see that a lot of top robots are only getting about 70% against FlowerBot, so perhaps it's just a lucky tuning on the GresSuffurd matchup (or unlucky, in the case of FlowerBot).
I'm hunting around to find cases where XanderCat performs poorly in cases where top robots perform very well. So far I haven't found a case I can learn anything from. I'll keep looking...
Flowerbot has a bug. This bot is derived from the (original) BasicGFSurfer which had a flaw when bullets had a power of x.x5 It could not match the bullet to a wave due to a bug in the rounding, therefor it did not 'count' the hit as a hit in its surfing. Just try out and always fire 1.95 power bullets at it, you will obliterate it. There are still some more bots using this codebase, so this 'bug-exloiting' could gain some points for you. --GrubbmGait 19:25, 23 June 2011 (UTC)
- Yep. That's it. Skotty 19:35, 23 June 2011 (UTC)
Which Waves to Surf
Anyone tried surfing all enemy waves at the same time? XanderCat currently surfs the next wave to hit, but I've been thinking about trying to surf all enemy waves simultaneously. Not sure if it would be worth trying or not.
Yep, many modern bots do. I surf two waves and weight the dangers accordingly. Doing more or all waves (would be just a variable change) would have almost no effect on behavior, because 3rd wave would be weighted so low, but cost a lot of CPU. --Voidious 19:45, 23 June 2011 (UTC)
In addition to what Voidious says, I'd like to note that going beyond two waves without eating boatloads of CPU could perhaps be done if one tries to be creative. One option is doing something like two and a half waves. What I mean by "half" is for the third wave, taking an approximate measure such as "If waves 1 and 2 are reacted to in this way, what is the lowest danger left for wave 3 that is approximately possibly reachable?". That approach leaves the branching factor of the surfing equal to 2-wave, but allows the 3rd wave to break ties in a meaningful way. Now... I haven't actually tried this, but just a thought about how to go beyond 2 without eating too much cpu. It might help in cases where the reaction to the first two waves would normally leave it particularly trapped... --Rednaxela 21:16, 23 June 2011 (UTC)
- I'm trying out surfing 2 waves at once for version 5.0, but I'm not sure how well it will work. I'm currently weighting the danger of the closer wave at 80%, and the 2nd wave (if there is one) at 20%. This is more a gut feeling for now. I may have to change it later. On a related note, version 5.0 pays more attention to robot width, such as determining when enemy bullet waves hit and when they are fully passed, but I was torn as to when to stop surfing the closest wave. Do I continue to surf it until it is fully passed, or do I stop surfing it right when it hits to try to get an earlier start on the next wave? For now, I'm doing the latter. Skotty 13:15, 24 June 2011 (UTC)
- About weighting between the waves, I believe one popular approach is weighting by (WaveDamage+EnergyGainOpponantWouldGet)/(distanceWaveHasLeftToTravel/WaveSpeed). This approach is nice because it gives a reasonable weighting of waves in "ChaseBullet" scenarios.
- As far when to stop surfing a wave... what I personally do, is surf the wave until it has fully passed, BUT I reduce the danger to 0 for the exact range of angles that would have already hit me (this is all using Precise Intersection to determine what range of angles would hit for each tick). This means that a wave that has almost completely passed me, will still be getting surfed, but care about those few angles that could still possibly hit (meaning, very low weight often). --Rednaxela 16:47, 24 June 2011 (UTC)
- Yeah, (damage / time to impact) is good, maybe squared. I can't remember if XanderCat is reconsidering things each tick (ie, True Surfing) or not, where that formula makes sense. While Rednaxela's setup is by far the sexiest, in a less rocket sciencey system (such as Komarious), I definitely favor surfing the next wave sooner - like once the bullet's effective position* has passed my center. (*Dark caves note: in Robocode physics, a bullet will advance and check for collisions before a bot moves. So for surfing, I add an extra bulletVelocity in cases like this.) --Voidious 17:53, 24 June 2011 (UTC)
- Originally, XanderCat was reconsidering things each tick, but I was running into what I referred to as "flip flopper" problems, where XanderCat would keep changing it's mind, and it seemed to be hurting performance. So I switched it to only decide where to go when a new bullet wave enters or leaves the picture (plus it processes less that way). However, I could see reconsidering every tick as being superior with the kinks worked out, and the "go to" style surfing has problems with dive protection. I therefore just modified my drive again to make the frequency of surfing configurable -- a hybrid approach between "go to" surfing and true surfing -- where I can set the max time to elapse before a reconsideration is performed; if the waves in play haven't changed before the time limit elapses, a reconsideration is executed. This becomes true surfing when you drop the time limit to 1. Not sure what value I will use for 5.1+ yet. Skotty 19:59, 24 June 2011 (UTC)
Rolling Average
I notice you say you are using a very high rolling average in both movement and gun. I have found in DrussGT that the gun should have a very high rolling average, but the movement a very low one to deal with bots that have adaptive targeting. By low I mean less than 5 on very coarsly segmented buffers, and less than 1 on finely segmented buffers. But I suggest you experiment with your own data and figure out what works best for you =) --Skilgannon 10:35, 27 June 2011 (UTC)
#1 Against PolishedRuby
I just checked for fun, and found that XanderCat currently holds the #1 score against PolishedRuby! Only 2 battles in the rumble, and only best by a slim margin, so XanderCat could slip down. But for the moment, I would like to claim my virtual gold medal against mirror bots. :-D —Preceding unsigned comment added by Skotty (talk • contribs)
Well, seems you certainly have a good anti-mirror system in place. I've never gotten around to building one of those... --Rednaxela 06:18, 1 July 2011 (UTC)
End of the Road?
Well...I'm now at a loss as to how to further improve. I have a couple of ideas for gaining a few points here and there, but nothing that would boost me by much. I've played around with a few changes against a small test bed of robots that top bots consistently score about 15 to 20 percent higher than me against, but so far I haven't found a way to improve my score any against them. Ho hum...yeah...no clue. Maybe some more ideas will come to me, but for now, looks like #49 in the rumble is the end of the road for my rank climbing days. Not without picking apart open source top bots, anyways. -- Skotty 02:58, 1 July 2011 (UTC)
- In case anyone cares to comment, I collected a list of problem robots that other top robots consistently score significantly higher than XanderCat on. Maybe there is a connection between some? Hmm...maybe I should look into "flattening" again. Right now I do not use flattening. That could be... if I can just figure out under what circumstances to use it...
- rz.Apollon
- nat.BlackHole
- ary.Help
- Bemo.Sweet30
- kawigi.mini.Coriantumr
- ary.mini.Nimi
- tad.Dalek98
- apv.TheBrainPi
- pez.gloom.GloomyDark
- cx.BlestPain
- tide.pear.Pear
- voidious.mini.Komarious
Hmm... well most of those you list are what I'd consider mid-tier adaptive bots. I would take that to imply that your greatest weakness may be against other adaptive bots. My instinct would be that your gun and/or movement adapts much too slowly against other adaptive bots. Flattening may be useful, but fast-adapting is far far more important. RougeDC and Midboss rank fairly high yet do not use any flattening. I never found it worth the bother
I think this really doesn't have to be the end of the road. I'd highly suggest running your bot's movement/gun against MC2K7 and TC2K7 (Use the fast-learning 35 round variants for both). That should give you an idea of where your bot stands in both movement and gun, against both adaptive and non adaptive opponents. That should show you where to focus I think, and also allow you to track your own improvements with greater precision than the rumble. --Rednaxela 05:55, 1 July 2011 (UTC)
I'm guessing that you need to lower the rolling average on your surfing. Really low, like to around 1. That will speed up your movement adapting to what these bots learn against you. Beyond that, it is all about bughunting, feature adding and tweaking. --Skilgannon 11:37, 1 July 2011 (UTC)
Even without flattener, without rolling average on the movement, without an anti-surfer gun and without bin-smoothing(??), it is possible to reach #10. Choose the attributes of your gun wisely (read: tuned to the opponents movement) and use attributes in your movement that are not common in the 'standard' guns. Be carefull with special cases except when proven that they do not interfere with 'normal' behaviour. If a bot gets 90% where you only get 65%, watch that bot's behaviour in situations where you would be hit. Be aware that 'perfect behaviour' could lead to predictable behaviour. Good luck with your quest for top-25. --GrubbmGait 14:31, 1 July 2011 (UTC)
I agree this doesn't have to be the end of the road. But a break might do you some good. =) Burning yourself out on tweaks is not always the best way to find your next big rating jump. You've done a lot in a short time here!
I don't think you need to peek at any other bots to get to the top. Phoenix and Shadow are proof of that. My own feeling is that in any sufficiently advanced field, you need to understand what everyone's already done before you can really innovate. Calculus didn't spring up out of a void. Dookious climbed to #1 mostly by emulating / perfecting the ideas that were already out there, but then I kept going and Dookious/Phoenix took a huge lead over the rest of the field with some innovations along the way. Skilgannon eventually came along with DrussGT, caught Dookious, and kept on crushing it and took another huge lead - it's only recently that WaveSerpent and Diamond closed that gap a bit. Sure, we both consumed ideas from the community and studied others' code (at least I did), but I still feel we innovated pretty well on top of that. It's hard to say you're copying everyone else when you're way out in front of the pack. =)
Of course there's also value in thinking for yourself. I've been less inclined to study others' code as time goes on. Everyone feels differently about this stuff, so I won't tell you how to go about it - definitely just do what you like! Just felt like sharing my thoughts. And remember there are other territories - MiniBots, Twin Duel, Melee, saying screw it and just becoming a gun nut... Or we could throw around a new rule set again - I would try and participate. Good luck. =) --Voidious 16:00, 1 July 2011 (UTC)
- [View source↑]
- [History↑]
Contents
Thread title | Replies | Last modified |
---|---|---|
Wacky Version Problems with RoboJogger/RoboRunner | 1 | 04:29, 3 April 2017 |
New Garbage Collection Mitigation Strategy | 4 | 15:16, 26 October 2013 |
Garbage Collection and Skipped Turns | 23 | 20:54, 24 October 2013 |
Shielding Success Rates Mystery | 27 | 00:49, 28 February 2013 |
When to shield | 1 | 16:43, 25 February 2013 |
![]() First page |
![]() Previous page |
![]() Next page |
![]() Last page |
Forgot how slow this can go. :-/ I've been trying all day to record some new statistics using the Robocode means for saving file to disk, but I'm getting really bizarre version issues. I've been updating my robot version with each change -- 12.8.1, then 12.8.2, then 12.8.3. Each time I clear robot cache, package the new version, clear the old stats file that was saved from the prior version (as in, physically delete it, so I know the old stats are gone), and then run a new challenge with the new version. However, I keep getting garbage from older versions coming out in the results. Sometimes mixed, like it's randomly running different versions.
I've started trying to record the version information to the stats file each battle. I keep seeing this in the saved information:
Old: xander.cat.XanderCat 12.8.1*; New: xander.cat.XanderCat 12.8.7.
What that means, is it thinks the last battle was run with 12.8.1*, even though the entire challenge was run with 12.8.7. And that may actually be sort of true, because I'm getting some info in the stats file that I removed around version 12.8.4 but it shows up again, like it ran an older version for one or more of the prior battles.
At the moment, I'm totally confused by it. I'm not even sure how to debug it further at the moment.
As sometimes happen, writing about it made me figure it out. What was happening, that I didn't realize, was that the newer version of Robocode has an option to include the data files in the packaged robot, which is checked by default. So it was packaging data from an old version of XanderCat that I had run from Eclipse, which was totally screwing with my robot frameworks attempt to manage the robot data.
If you want to save any persistent data to the data files, make sure you uncheck the option to include data when packaging the robot!
Can't believe how much time I wasted figuring that out today.
I spent some time working on a system to pool frequently used objects in an attempt to mitigate the first round garbage collection problem my robot suffers from. My first attempt had some merit, but the changes involved are a lot more significant than I would like. I'm just not happy with it.
Recently, however, I came up with another idea that may be much simpler and effective. However, I still need to test out the idea. Instead of managing object pools, what if I just dump old objects into a "waste basket" that hangs onto those objects and releases them at a controlled pace -- probably slowly at first and releasing them faster as the rounds progress and the waste basket begins to fill up. Or perhaps empty the waste basket at safe times, like the end of a round or at times when XanderCat has a solid advantage already. This would use more memory overall but may be far simpler and less error prone. I'm going to sideline my prior pooled objects work and try this route for XanderCat 12.7.
Sounds like it has potential, but isn't your primary GC issue at the very beginning of the match? Or did we already conclude that was intractable?
That might work, but I have my doubts. Unless you're calling System.GC() all the time it seems likely that the garbage collector will wait for a bunch to pile up and do it in bursts regardless of how controlled of a pace you release your references at (and calling System.GC() all the time would also likely cause it's own issues). I'd say the real solution needs to involve just plain not using so many tiny objects in the first place.
(It's kind of one of my pet peeves about Java, that the language encourages extensive object use, yet if you use it "too extensively" the code will have performance issues to due excessive allocation/deallocation overhead. In some languages (such as C++) one has the option of combining multiple objects into the same block of allocation, but because all object instances are references in Java there's no such luxury, ironically meaning that high performance java code needs to use simpler/fewer OOP structures than high performance C++ code in order to match the performance)
Also a pet peeve of mine about Robocode at this point. It has a really strict time limit per turn with a programming language that doesn't give you much control at that small of a scope. And even if it did, a rolling average would be soooo much nicer, and skipped turns are such a burden to deal with.
Automated garbage collection is about getting the job done faster/cheaper. Machine code always has more potential for performance than any language and/or paradigm. But in practice, due to overwhelming complexity issues, lower level languages tend to deliver worse software overall.
If you want high performance Java, increase the size of the heap, and/or change the ratio between regions, which solves 99% of garbage collection issues.
We could make it standard in RoboRumble to have a heap optimized for real-time. Using "-Xmn511m -Xmx512m" or "-Xmn1023m -Xmx1024m" in roborumble.bat would do the job very well. Not as fun as programmatic object pooling systems though.
Starting a new thread to discuss my efforts to deal with the skipped turn issue that is apparently related to garbage collection eating up allowed run time. This was previously discussed in thread "Shielding Success Rates Mystery", for anyone who wants to see where it all started.
I purposely did not contribute to the rumble over the last few days after the pairings for XanderCat 12.6 were lost. I originally ran many of the original pairings on my PC that does not have the skipped turns issue. Most of the re-run pairings were likely run by Voidious, whose system does exhibit the skipped turns issue.
The difference between the two is quite significant. With clients that don't exhibit the skipped turns issue, XanderCat achieved an APS of 87.7. With clients that do exhibit the shipped turns issue, XanderCat achieved an APS of 86.5. The difference -- 1.2 APS -- is quite significant. With the current rumble participants, it makes the difference between 5th and 8th place.
Most of the difference is due to the skipped turns causing the bullet shielding system to fail much of the time. But likely the skipped turns in general -- ignoring the bullet shielding -- also contribute a small amount.
I had previously fixed a few performance bottlenecks to make XanderCat run quite a bit faster (v 12.3), with much lower turn time peaks, but this only achieved a marginal improvement. I now need to shift to figuring out how to reduce the amount of garbage my framework apparently creates. This is not a real easy problem to address, because it is a very unique Java problem that rarely ever needs to be addressed in the real world, so there is not a lot of information or research available online to help on this.
I think one thing I can do is to eliminate as many intermediate local variables as I can. For example, variables with only method scope that are used to break something into multiple easier to maintain steps. These extra method scope variables may be contributing to the garbage collection, especially in the first round. Eliminating them may help to fix the problem, but at the expensive of either combining multiple lines together into more complex lines or making the variables have a wider than necessary scope (declaring them as part of the class), thus eating more memory overall but eliminating the possibility of it triggering garbage collection.
I don't know if these steps will help, but I will probably give it a try. I am also not sure if there are other ways to reduce garbage collection, but maybe I will come across some other ideas. I may actually create a second branch in my source tree for this work, something I never thought I would do for Robocode. I want to keep the current version, as I think it will constitute better code and perhaps someday the garbage collection issue will be addressed by changes to Robocode itself; but if my garbage reduction efforts work, for now I will operate off of a garbage reduced branch.
This seems like a really crappy thing to push onto you as a bot author. I do think our time is probably better spent coming up with a proposal to change Robocode itself and submitting that (as idea, design, or code) to Fnl. There could be a very simple and elegant solution that would work, like "allow 10x the CPU constant for the first 100 ticks". (Disabling CPU limits in first 100 ticks seems problematic, since you want to at least interrupt bots that hit infinite loops.) Another idea is having Robocode run its own GC cycle right before the match starts, in case bots are being penalized for GC of the game engine.
I'll try to get to another round of tests and find out how much I need to raise the CPU constant to get normal performance out of XanderCat.
I've had to deal with this quite a bit when writing games in c#. Similar to Java the GC can case obvious stalls. The easiest way is to stop calling the "new" function at run time by using pooling. For instance at the start of a match, or a round create a container object which contains N pooled objects which you know you create often, eg wave objects. At the point you wish to use one, take it from the pool, initialise it, use it, then return it to the pool when finished at any point later on.
Because you have not called new, and then nulled the object, the memory used does not go up, it stays constant, thus no GC is run. It's obviously impractical to pool everything so you just do the worst offenders which are things that you create often and throw away.
That seems like a great approach. And you can even create the pools in a static block, which I'm pretty sure runs before the match starts and won't count against any of your CPU time.
You do not have permission to edit this page, for the following reasons:
You can view and copy the source of this page.
Return to Thread:Talk:XanderCat/Garbage Collection and Skipped Turns/reply (6).
Local variables are stored in the stack and not the heap, so they don't affect garbage collection.
You should look after "new" abuse, like Wolfman said. Although sometimes the instantiation is implicit and simply searching for the "new" keyword doesn't always work.
There are heap profiling tools which locate automatically where too many objects are being instantiated.
Local variables are stored on the stack but any time you use new it will go on the heap afaik:
public void MyFunc(Object a) {
Object b = a; // Variable b is on the stack, pointing at a. b = new Object(); // Memory allocated on heap, referenced by variable b on the stack
}
This is my understanding of it. Please correct me if I am wrong!
This is correct.
My understanding of the snippet above is that you have 3 variables. 2 local in the stack (references "a" and "b") and 1 in the heap (Object instance).
Some variables stay in the stack only, like primitives (double, float, int...).
Where would a primitive array like an int[] end up?
Java treats an array as an object, so on the heap.
However, these days the JVM is more intelligent than you guys are giving it credit for, eg. it has Escape Analysis to determine if objects should be put on the stack if they stay local.
Didn´t know about escape analysis.
What I usually do to take in account all optimizations, even those I don´t know about, is to use profiling tools. Measure what is really happening, instead of looking at the code and guessing.
I've actually been debating writing a Robocode simulator to make robot profiling much easier. What it would do is to pretend to run a robot battle with your robot against either another opponent, or perhaps some imaginary robot, using a combination of mock objects and simulation. It would run without any security at all, no sandbox, nor would their be skipped turns, so you would only want to run it with trusted robots. But it would be much easier to run a profiler against. The simulated battle may not be a perfect simulation, but as long as it's close, it should work and be useful.
When I do profiling in Robocode, I run a battle of a bot against itself. Then I filter the results by package so engine data is filtered out and only data from my bots appear in the profiling report.
Yes. However anything that you are creating during a function and keeping hold of for a few frames and then releasing is going to be allocating on the stack. Stuff like "Wave" objects, "Bullet" objects or whatever else you use in your bot will cause GC stalls if you create lots, use for a while and then null. This is where the pooling comes into force. I would definitely recommend pooling objects such as waves etc if you are having trouble with stalls and then go from there.
-wolfman
See, my bot always had a skipped turns problem, and now you're giving me a possible solution. You're drawing me right back in to wanting to start Robocoding again, dangit! *laughing*
Arrays are objects in java:
public void func() {
int[] myArray; // myArray variable on the stack myArray = new int[5]; // Array object allocated on heap, referenced by myArray variable on the stack
}
Note that member variables of objects are obviously going to take up memory on the heap not the stack - eg if you have 30 primitive member variables (ints, doubles etc) of a class and call new on that class, it will take up more memory allocation than a class that has 1 primitive member variable.
However allocating 30 local primitive variables during a function call allocates those primitive types on the stack alongside you local member reference variables.
While I am not the saddest person here that this has happened to you (as my robot is right above yours in the rankings with only a little APS between it and yours). But I know I would hate it if this happened to me. However I have tried to design things from the ground up in more recent robots to limit object creation and destruction.
At one point I even reused old objects (aforementioned pooling) instead of creating new ones. That didn't make it into the current version however.
I started doing some research on my shielding success rates. I started with a small set including Virus, Seraphim, Hydra, Crusader, and Engineer. I did a first test run of 20 seasons. Shielding success occurred on 20/20, 19/20, 20/20, 20/20, and 13/20 seasons respectively. I know why it's not perfect for Engineer, but the other 4 are the mystery. In the RoboRumble, my success rates on the first 4 are currently 5/8, 5/8, 5/8, and 4/7 respectively.
None of the Rumble losses were run by my machine. But all of them were run using client 1.7.3.0. Losses only occurred when run by Voidious and DivineOmega. I'm guessing there is something common about the machines used by you two that is key. Are you both perhaps running under Linux? Also, what version of Java? I need to replicate one of your machines as closely as possible to explore the problem further.
Maybe their clients are skipping turns. Missed scans hurt bullet shielding a lot.
If they want to check that, they sort-of can. It only reports on the last battle that it happened, but if my robot has any skipped turns, it will write a file xander.cat.XanderCat_SkippedTurns.txt file into it's data directory that has the number of skipped turns printed in it. It's not as useful as it could be since it just reports on the last battle that it happened on, but could be worth a check.
Are the tests you run also using 1.7.3.0? (BTW, I'm doing some major bullet-shielding-suffering at the moment...)
My rumble clients are on a Core i7-3770 running Ubuntu 12.04 (32-bit), and I think OpenJDK 6 (will check when I get home). Now that you mention it, I recall a similarly huge discrepancy for the original BulletCatcher on an old AMD Ubuntu machine I was using as a rumble client (couldn't find the discussion though). I chalked it up to the different JVM or even the CPU and ended up just retiring the machine as a rumble client, since it was a fraction of my overall CPU power.
My first guess is that when two bullets are close enough to parallel, one JVM's Line2D says they intersect and another doesn't. I actually have Ubuntu 32-bit, 64-bit, and Windows 8 64-bit all on that same machine, so I should be able to do some decent tests for you with only the JVM or OS as a variable.
Found the discussion: Archived_talk:User:Voidious_20110909#Wierd_scores
When the opponent is moving, my robot stands perfectly still (it rotates but doesn't move position). Thus, I haven't verified it, but the two bullets should be perfectly parallel, and this is likely handled differently on different JVMs as Voidious was talking about. However, when both robots are standing still, my shielding shot will miss, so my robot will move slightly when firing a shielding shot against a stationary opponent. I haven't had enough time to figure out what causes this, but I wonder if the answer will give any further clues. I did it this way because it worked, but more investigation is required for me to figure out why.
I could play around with moving slightly for every shielding shot (and moving back right after the shot). I tried this briefly, but found standing still to be more reliable on my machine. But maybe I can tweak it to where it works as well as standing still. If I can, I bet it would avoid the problem.
I will likely need a few more days to play around with this further. In the meantime, if Voidious has time to try out the other JDK, that would answer another piece of the puzzle.
Standing still works because the enemy gun rotation happens after the bullet is fired, so they shoot from a position of 1 tick ago but use their aim from 2 ticks ago. So if they are moving their angle to you changes and they don't quite shoot at your centre, meaning that you can get your bullet line to intersect with theirs because your bullet comes from your centre (which they aren't aiming for). This is also why it stops working when they stand still, because their last position relative to you lines up with their current position relative to you so you end up shooting parallel.
I'm trying to figure out why my super-advanced precise circle-line intersection methods are failing so horribly at getting shield hits. I get one every now and again, but nothing like what I should be based on the maths and shield size I'm calculating, and nothing like the 3/4 of bullets that a simple linear projection + bullet power adaptation was getting.
I would recommend against using Seraphim in a test bed. It is a very buggy robot. So much so that I think it sometimes acts differently in a rumble environment then in a test environment.
But also some versions of Seraphim if I recall add a minor variance to its gun heading it detects it is against a bullet shielder. Is the version your using the same as the one in the rumble? (I expect so, but it cannot hurt to ask.)
After some testing, maybe we can come up with a more consistent implementation for checking bullet collisions / line intersections in the Robocode engine. Here's the relevant code snippet: [1] (line 76 calling line 113).
Here's one that gets rid of the division which I expect is what blows up on poorly conditioned problems:
private boolean intersect(Line2D.Double line) { double x1 = line.x1, x2 = line.x2, x3 = boundingLine.x1, x4 = boundingLine.x2; double y1 = line.y1, y2 = line.y2, y3 = boundingLine.y1, y4 = boundingLine.y2; double dx13 = (x1 - x3), dx21 = (x2 - x1), dx43 = (x4 - x3); double dy13 = (y1 - y3), dy21 = (y2 - y1), dy43 = (y4 - y3); double dn = dy43 * dx21 - dx43 * dy21; double dn_sign = Math.signum(dn); double dn_abs = dn*dn_sign; double ua = (dx43 * dy13 - dy43 * dx13) * dn_sign; double ub = (dx21 * dy13 - dy21 * dx13) * dn_sign; return (ua >= 0 && ua <= dn_abs) && (ub >= 0 && ub <= dn_abs); }
It might even be faster, divisions are about the same speed as sqrt.
Given that it is using it's own code to determine intersection rather than a JVM method, I wonder if the discrepancy between systems is actually in the data stored in the line objects.
I thought maybe I could tweak it using a small amount of movement to make it work on all systems, but so far my attempts have degraded shielding performance unacceptably. One bit of good news -- I tested and found out that Robocode security does not prohibit robots from reading System properties, so if I can figure out how to correct (at least partially) for the problem on other OSs or JVMs, I can test for them and just make those changes on the appropriate systems.
When I experimented with bullet shielding, my bot calculated minimum and maximum angles which would hit an incoming bullet, and only shoot if the difference between angles was above a threshold. It was there to work around floating point calculation errors, which translate into "parallel" bullets.
If the difference is below the threshold, then moving sideways helps increase the difference. Near 100% bullet shield against TrackFire. But against moving opponents and/or weak powered bullets, sometimes my bot moved until it crashed on the wall, never finding a good angle to shoot. And this is where my experiments are stuck right now.
Tonight I ran a test on one of my servers in my basement. The OS on it is Fedora 13. I installed Open JDK 6 (command su -c "yum install java-1.6.0-openjdk-devel"). Once installed, it reports itself as:
OpenJDK Runtime Environment (IcedTea6 1.8.8) (fedora-51.1.8.8.fc13-i386) OpenJDK Client VM (build 14.0-b16, mixed mode)
I ran a number of battles and have yet to encounter any shielding failures using XanderCat 12.2. But I need to do a more thorough test to be sure. Tomorrow I will set up RoboJogger and run a bigger series of tests.
Just checked and I'm also on OpenJDK 6:
java version "1.6.0_24" OpenJDK Runtime Environment (IcedTea6 1.11.5) (6b24-1.11.5-0ubuntu1~12.04.1) OpenJDK Server VM (build 20.0-b12, mixed mode)
Sorry I didn't get to any real testing today, but I will tomorrow. Now I'm really curious to see if I see the same in another JVM or in Windows...
In case it's easier just to copy it from here -- here is a challenge file with 3 opponents that XanderCat 12.2 is nearly perfect against on my machine but only maybe 50 percent successful against on machines that exhibit the performance anomaly.
Shielding Vulnerable PERCENT_SCORE 35 Shielding Vulnerable { apv.test.Virus 0.6.1 kc.serpent.Hydra 0.21 trab.Crusader 0.1.7 }
I finally got my precise intersection with bullet shadows working for bullet shielding, so Voidious, if you're going to run some tests to see if bullet collisions work on your machine, give this a try as well: https://dl.dropbox.com/u/4066735/jk.precise.BulletShieldTest_1.0.jar I'm theoretically getting around half a pixel of shield width, so if that doesn't work then there is something seriously wrong.
Hi mate.
I was in the mood to check XanderCat 12.2 on my system and maybe it can help you to detect some uncertainties.
Mac OS X 10.6.8 java version "1.6.0_37" Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-10M3909) Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode) Robocode version: 1.7.4.4 CPU constant: 5426594 nanoseconds
Result vs Virus (png) Last Round Log vs Virus (png) Round start log vs Virus (log)
I started a couple of runs and it looks like almost 50% failed because of massive skipped turns if the round starts. This happens if the client runs on low speed and as well on full speed. If I put the client on debug=on, everything works fine and XanderCat win all rounds like expected. Because of the skipped turns XanderCat misses quite a few bullet catches and decides to move with a different movement - from that point he is almost ever doomed to loose some rounds. I hope it helps a little.
BulletShieldTest 1.0 worked so far very good on my system. He is lost against all 'sloppy' guns (HawkOfFire,SpinBot..) but against well coded targeting he has a quite impressive performance. Of course, he has still some minor flaws but i guess that is not unusual for a test version.
All in all i would say there is no difference in how the JVMs handle intersection but there may be a difference how they handle garbage collection and therefor have a different skipped turn behavior.
Man, I wished I had more time these days :( - take care
Thank you, Wompi. That is very helpful. From the round log, looks like there are occasional skipped turns (most likely due to the wave surfing drive and guess factor guns, but these sit idle when bullet shielding is active, and bullet shielding is much less processing intensive). However, the first round where most things are initialized is the worst.
So it's probable the problem isn't with the JVM doing the shielding calculations but rather how much time each system is allowing and how long it takes my initialization code to run (which I can work on, but it may also be true that different JVMs take different amounts of time for different types of initialization).
Looking at the info provided by the run time loggers, the averages between my system and yours aren't all that different, but the peaks shown on yours are an order of 5x what they are on mine. The radar peaks are even worse, which is weird. A typical greatest peak for my radar on my system is 0.25 trialing down to less than 0.1 by the 3rd peak, whereas on your system they start at 9.9 and are still above 0.8 by the 5th peak. (note: peaks are over the entire however-many round battle, as are the averages)
Both your system and Voidious' system are using the Server VM, and that makes me suspicious. I need to try out a Server VM and see what happens.
It should be noted that if this is the problem for Voidious, DivineOmega, and perhaps others, it is affecting overall performance (in the first round at least) and not just on the bullet shielding. If I can find a way to fix it, overall rumble performance could improve some.
Running some tests now. Starting with 20 seasons, single-threaded on the Ubuntu/OpenDJK setup. 10 seasons in and see it failing a lot vs Virus (~76%), rarely vs Crusader (~90%), and working well vs Hydra (96%). I'll post more details and the full RoboRunner logs when I've got some more data, and try it through the UI to see what I can tell about skipped turns.
If it is a skipped turns issue, I know there is one trick to put heavy initialization stuff in a static block and it won't count against your CPU time. I really hate Robocode's skipped turn setup, though I think limiting the CPU time in general is great. I'm definitely taking a different approach in BerryBots. It's probably too late to completely change it in Robocode, but we could at least look at an average over the last 5 or 100 ticks and penalize based on that instead (which is part of what I'm going to do).
Wow, ok.. So 4 threads was slightly worse overall, but 20 seasons is hardly enough to cover the margin of error. Now testing on Windows, and at 98 overall score after 8+ seasons. This is Oracle Java 7. Also interesting to note that the CPU constant was set to about 5 ms in Windows, vs 7 in Linux. Also this is all on Robocode 1.7.4.0, sorry about that, but I don't think it makes a difference.
Ok, still want to test on Ubuntu 64-bit and with the Oracle JVM on Linux, but here's a bunch of data for now.
config | Virus | Hydra | Crusader | Total |
Linux/OJDK/1 thread | 76.14 +- 8.29 | 95.93 +- 0.37 | 89.26 +- 5.17 | 87.11 +- 2.66 |
Linux/OJDK/4 threads | 81.45 +- 7.6 | 82.77 +- 6.51 | 90.91 +- 5.14 | 85.04 +- 2.92 |
Windows/1 thread | 98.89 +- 0.25 | 96.09 +- 0.33 | 98.67 +- 0.34 | 97.88 +- 0.17 |
Windows/2 threads | 97.18 +- 1.91 | 96.31 +- 0.35 | 98.92 +- 0.3 | 97.47 +- 0.48 |
Windows/3 threads | 95.4 +- 3.19 | 96.39 +- 0.23 | 88.88 +- 5.49 | 93.56 +- 1.55 |
Windows/4 threads | 98.66 +- 0.31 | 92.2 +- 3.5 | 92.42 +- 4.31 | 94.43 +- 1.41 |
It's worth noting that I feel comfortable running my own benchmarks 6-threaded on this machine and I usually run 4 RoboRumble clients at a time.
Thank you, Voidious, for all the data. Don't forget to take a peak at skipped turns under Linux/OJDK. It gets printed to the game log, and you can also check what is printed in the SkippedTurns text file it writes to the data directory.
For now, I'm going with the assumption that I need to target reducing initialization overhead due to skipped turns. Once I have that done, I can prepare another version of XanderCat, which if I'm lucky you will be willing to run through your Linux/OJDK setup again to see how it changes things.
So, upon not getting to the bottom of this, I stopped running my rumble clients. Where are we with the discrepancy in shielding success on different systems? I don't particularly mind keeping my clients off for now, since I'm not submitting bots, but I do have quite a bit of CPU power I'd be happy to contribute.
I also still want to test with the newer XanderCat, Ubuntu 64-bit, and a different JVM on Ubuntu, but that requires Voidious-time and not just CPU-time. :-)
Not much new at this point. I greatly reduced my processing overhead in XanderCat 12.3+ in an attempt to improve on the problem (nearly cut average and peak processing times for targeting and surfing in half; see Version CPU Usage section of my XanderCat page; noting that my CPU constant is around 10ms), but since the problem seems linked to garbage collection, I don't think it will result that much of an improvement (I'm guessing far fewer skipped turns in later rounds but still a bunch in the first round, which will still break shielding). I may be able to reduce the amount of garbage collection by trying to eliminate as many local method-scope variables as I can, but that would be a lot of work for something that will likely make the code less readable and I don't even know for certain if it will help. Thus I haven't tried it yet.
Wompi indicated that using -XX:+UseConcMarkSweepGC to use the concurrent mark and sweep garbage collector eliminated the problem, but I don't think anyone was sure whether it was a good idea or not to use this as a solution. Not sure if it could cause other problems.
For now, I don't mind if you restart your clients. XanderCat 12.5 already has over 10K battles and I don't intend to replace it with a newer version for awhile.
I'm curious, what method are you using to determine that your shielding isn't working? Do you just stop after a certain number of bullet hits/bullet damage?
Mine is a rather complex set of conditions, some that can happen on and off and some that can effectively disable shielding for the rest of the battle.
I'm guessing you are more interested in the conditions that that turn it off for good. That determination takes into account total bullet shielding misses, consecutive bullet shielding misses, average damage taken per shielding shot (presently it assumes all misses will result in damage, but I've been contemplating changing this to only when real damage occurs), overall shielding success ratio (total shielding hits / total shielding shots), and round number (some things more lenient on earlier rounds).
More temporary on and off conditions include stuff like rolling average opponent fire power, opponent distance, round time, whether or not the opponent keeps not firing first, and whether or not a shielding shot was just missed.
If you want to see specifics, you can dig into my code and look at the big nasty condition starting on line 123 of BulletShieldingScenario. It just might be the biggest condition statement I've ever written. I need to do more research to figure out how often any of those conditions are actually triggered to fine tune it all and order the conditions to minimize processing required, but I don't expect a lot changes, other than cleaning up the class so it's not so messy.
![]() First page |
![]() Previous page |
![]() Next page |
![]() Last page |