Talk:DrussGT
Just going through the algorithm, and I realised that there's a bug in my precise prediction: I'm using the bullet-hit-time of the 'target' point, not the point that I actually reach. This is left over from the days when the only thing my precise prediction checked was whether I could reach the target point. Now, for regular, constant distance surfing this is fine. But the moment I start changing distance my predictions can get a couple ticks off... Basically the less lateral velocity component I have, the more inaccurate my prediction gets. Which is bad against, say, RamBots, and in corner situations. I may have to rethink this algorithm... I've already tested doing an iterative search but it gets way too slow, way too quickly. --Skilgannon 10:47, 27 January 2009 (UTC)
Hi, I just want to know. You had once tell me that DrussGT doesn't call Math.random() in real battle, but it does in development process. Is the random call in development process use to generated all those 100 buffers' slices? Thanks » Nat | Talk » 06:02, 21 February 2009 (UTC)
Again, I'll rework DrussGT and see how it will act if it had 73,728 buffers. (The maximum buffer without duplicated buffer :)) » Nat | Talk » 06:05, 21 February 2009 (UTC)
- My robocode crash after intialize that bot with 73728 buffers! I think it too much :) » Nat | Talk » 07:18, 21 February 2009 (UTC)
Yes, it uses random() to decide which buffers to use, and which slices for those buffers (ie fine, regular, coarse). Unfortunately I couldn't do every possible buffer, due to memory constraints. So I use random() and make a set of buffers that hopefully covers all the segments fairly evenly. Also, if I used every possible combination I would probably run into problems with execution time while extracting buffers to use and smoothing new hits into the buffers. --Skilgannon 22:45, 21 February 2009 (UTC)
One more question: Does it do hit surfing? I go trough your code to understand the flattener (it easier to understand than Dookious one because my robot base on basic surfer, too.) I've recognize that you only do logHit() on hit and do logFlattener on every waves. Does hit surfer competitive? Or I miss something in your code? Thanks. » Nat | Talk » 02:21, 22 February 2009 (UTC)
Yes, hit surfing is the primary way of surfing. The flattener is only enabled against top guns. The reason for this is that if we are flattening the whole time, we can never learn where they are shooting, and dodge those areas. For example, against linear targeting, hit surfing can learn to dodge it perfectly, whereas flattener-only will still get hit. The same is also true against GF bots because they will learn that you move in certain ways, but the moment you get hit by them, you know how they think you move, so you can move differently. By rolling your surfing stats quickly you can stay ahead of their stats and actually do better than just creating a flat profile. Only against fast adapting guns is it necessary to enable the flattener. --Skilgannon 19:49, 22 February 2009 (UTC)
Question: Why you always use Float in DrussGT? Is it faster than Double? » Nat | Talk » 13:51, 6 March 2009 (UTC)
Yes, a float is significantly faster than double for multiplication/addition, which is what I use the most. It is slower for trig due to having to caste into a double, but with the new FastTrig class I can change that. It also uses half the memory. If I tried using doubles DrussGT would skip quite a few turns, and might also skip turns on initialisation due to allocating twice the memory. --Skilgannon 22:14, 6 March 2009 (UTC)
Well, I just decided to add "float" functionality to my FastTrig class. Iterestingly, despite the bulk of the calculation involved being multiplication/addition to get the index it isn't actually significantly different than the plain double version of FastTrig:
FastTrig init time: 0.00703 seconds Wrost error: 0.000436324725 FastTrig time: 0.520 seconds Math time: 8.811 seconds Wrost float error: 0.000465920262 FastTrig float time: 0.510 seconds
The difference is slim enough that I don't think it's worth keeping two different versions. I'm just not sure which version to keep. But indeed, floats are nice for speed/memory and I'm already using them in a componant of my upcoming bot other than the FastTrig --Rednaxela 23:03, 6 March 2009 (UTC)
I don't think floats are faster than doubles at operation time, if I remember correctly calculations are done in higher precision registers anyway. The main time difference comes from the memory bus, a float(32-bits) can be read and written on a single memory access, while doubles(64-bit) are not. Some 64-bit architectures can move the whole 64 bit at once and have no real performance hit, while some use only 48 bit transfers, in those cases there is still a small difference. It's been a long time since I have read any of this, but I think that is the reason. --zyx 06:07, 7 March 2009 (UTC)
I'd say it really depends. For some applications before I've noticed as much as a 10% to 20% difference using floats, even with not being on a 64-bit architecture at all. Though for FastTrig float doesn't give a significant performance benefit. The reduced memory usage though, is of course undenyable. --Rednaxela 06:20, 7 March 2009 (UTC)
Well, the memory is of course half of it when using floats :). That can also affect on performance from the cache fetching point of view, and honestly most people doesn't need the extra precision that comes from using doubles. What I mean is that there isn't any real time performance difference that should people use float over double, if it is memory you need to optimize, float is the way. Otherwise I think people should use which ever he/she feels comfortable with. I use double when is a fresh new application just because doubles can represent all 32-bit integers exactly. And when I'm working with an API(like Robocode) I use the same as the API, that ensures that I will consistently behave the same as the API. I wouldn't consider it PrecisePrediction if it uses floats, because there will be differences when Robocode handles the same situations with doubles, I'd think of it as an approximation to it. When working on something as non-deterministic as a Robocode, maybe it's not even good to have more bits, but I'm a precision freak :/, that's why currently I'm using 628318 divisions on FastTrig --zyx 19:04, 8 March 2009 (UTC)
- Good point about the cache fetching. Also, as a precision freak, I take it you don't like VCS much ;P --Rednaxela 19:18, 8 March 2009 (UTC)
- Hehehe yes, I had been looking forward to making a DC bot for a long time, but I admit that VCS is a very good technique and certainly was easier to learn the heavy stuff of GF and WS using simple VCS. -- zyx
- Zyx, are you precision freak? I think not. I use 7,200,000 divisions on FastTrig in my Pallas! Take about 1 secs to load =) Also define this in it's FastMath class:
public static final double PI = public static final double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986...D; // actually it over 2,000 precision!
- :-D So who is real precision freak? I felt more comfortable with Digital (one mistake mean corrupted data), not analog (can have some disort). I always add the asin() to my nano linear targeting. If you are precision freak like me, you should use Anti-Alias VCS from Rednaxela. » Nat | Talk » 06:01, 9 March 2009 (UTC)
- Sheesh, that would take 27.5MB of memory on FastTrig alone, that's outright wasteful. Actually, my anti-aliased VCS, while far lower data distortion than conventional VCS isn't as low-distortion as log-based techniques like DC are. If you made a spectrum where one side was fast/distorted and the other was slow/accurate, then Anti-aliased would fit somewhere in the middle, with DC towards slow/accurate, and Conventional VCS (single buffer) towards fast/distorted. So really, no, anti-aliased VCS isn't for a real precision freak even if it's more precise than other VCS. --Rednaxela 07:11, 9 March 2009 (UTC)
- Well about the number of divisions, you are winning :p, I may push it higher but I haven't seen any real reason to do so yet. As for PI I use the Java Math.PI, but honestly I don't even know how precise it is (I don't really know Java), I just believe it is ok. But instead of your PI constant I would use:
- :-D So who is real precision freak? I felt more comfortable with Digital (one mistake mean corrupted data), not analog (can have some disort). I always add the asin() to my nano linear targeting. If you are precision freak like me, you should use Anti-Alias VCS from Rednaxela. » Nat | Talk » 06:01, 9 March 2009 (UTC)
public static final double PI = Math.acos(-1);
- You can't get better than that, it will be as accurate as your compiler (or JVM in this case) can be :-). About the anti-aliased VCS maybe I will add it to Newton someday, but in the mean time my time will be spent on DC. -- zyx
- Doesn't it
Math.acos(0)*2
? Anyway, Math.PI has 20 precision. Mine have 2,000 precision. 100 times! But java double can't handler it =). I think java trig function depend on OS, so predefine it is good ideas. I'm now planning to preloaded 720,000,000 divisions into FastTrig, then my robot jar will count as 300MB. Wait! just kidding! I am not that crazy... Note to your bot, don't stick with Newton and that DC (I can't remember it), create a new robot, base on old bot if necessary. » Nat | Talk » 13:54, 9 March 2009 (UTC)
- Doesn't it
- You can't get better than that, it will be as accurate as your compiler (or JVM in this case) can be :-). About the anti-aliased VCS maybe I will add it to Newton someday, but in the mean time my time will be spent on DC. -- zyx
I would like to point out that your surfing can only be as accurate as the enemy gun. Thus, if the enemy has a very low number of bins (for eg. I have seen 25), keeping PI to 2000 places will make very little difference. On the other hand, this gives me an idea: if you could figure out the granularity of the enemy's shots, and find that it is quite high, there could be 'safe spots' at long distances where the enemy doesn't fire, ie. between bins. In this situation having that precision may help.
To get back to the original point, the reason I switched DrussGT to floats (after going through my private release notes) is that, during testing, it would often crash due to an exception of some sort. Robocode doesn't (or didn't) release the memory from all those buffers when I restarted the match, so I would often have to restart Robocode every 30 minutes or so from running out of memory. By changing to floats it doubled the time between each restart of Robocode. Also, with the number of buffers I'm keeping, and thus the sheer number of floating point multiplication that gets done every tick, having floats instead of doubles means that much less memory is moved around, accessed or modified. For example, if, in the same tick I both get hit by a bullet and sense a bullet being fired, without flatter, just from the VCS I'm doing around 75000 float operations, over 14000 of which are writes to an array. Added to this I still have to do several hundred precise predictions, and it's easy to see how DrussGT could start skipping turns, even if everything just took a *little* bit longer. --Skilgannon 18:48, 9 March 2009 (UTC)
- What you say about safe spots between bins sounds like a good exploit point for some guns, and seems doable without any rocket science theory. --zyx 02:35, 10 March 2009 (UTC)
- Hey, doesn't System.gc() you called handle that? » Nat | Talk » 12:07, 10 March 2009 (UTC)
- Not if the bot crashes before I can call it. To prevent skipped turns I always call it at the end of the round, or in the onDeath handler. So if my bot crashed, it would never get called. Besides, my (crashed) bot was still holding a reference to the buffers, so they wouldn't get cleaned up anyways. --Skilgannon 19:53, 10 March 2009 (UTC)
Hey Skilgannon, I think if you re-structured your source code, you will easier integrated another thing and I'll easier understand your code :-) I always imagine DrussGT as clean as Dookious before I read DrussGT code and I disappointed. If you can clean your code, that would be best thing ever. » Nat | Talk » 00:36, 20 March 2009 (UTC)
Quote"Pleeaase don't just take my bot, tweak it and release it under another name. Rather tell me about the changes, and I'll give you credit.": I've improved DrussGT 1.3.3 Virtual Gun Rating a bit, here. It base on Dookious VGun. I think it perform better, at least against Shadow. » Nat | Talk » 02:52, 20 March 2009 (UTC)
Cool! Nobody's ever really contributed to my code before, so I'm not sure how to go about this. I've read through your changes, they were mainly rolling averages instead of a straight sum for the VG score, and modifying the values that different guns get chosen at, right? While I very much appreciate your effort, I'd actually like to re-code it in a way that makes more sense to me. So I'll give you credit in the /Version History of my next version. I actually had some other ideas on how to ensure that the AS gun doesn't get chosen against bots that don't surf, and it was those I was referring to. I'm not sure how much adding rolling averages to a VG will help, since, unlike GrubbmGrb my guns all learn and adapt. But perhaps they do. What I would be worried about is one gun getting a lucky streak and then me using a gun that is actually weaker. But your rolling averages are quite deep, so I don't think that will really happen. Also, about that cleanup, there is very little that I still want to add to DrussGT, most would be bugfixing. It was never designed to be something that is easy to read, as long as I can understand it, and I can =) --Skilgannon 05:42, 20 March 2009 (UTC)
Right, 2500 is a depth which Dookious use. Also, the 0.22 and 0.26 is from Dookious, too. I don't know about hitting the surfer much, but I think if you lower your vgun rolling averaged depth, you will do better against surfer. Shadow usually hit much by your AS gun in first 3 rounds, then the PM gun, then the DC gun in the rest. I don't know about random-movement, but by lowering my vgun rolling depth to 3 in BlackHole, I got more score from surfer... About code cleaning, actually I understand them but I lazy to scroll up and down to find method :-) Which editor do you use? I think it is not Eclipse because the messy indentation and it is not Robocode's editor since Robocode's show that a large part of DrussGT.java is a comment! (it doesn't understand // */
) By the way, the another minor changes that I want you to keep is just to draw current gun and flattener status, as it very helpful not to watch the console while watching robot fighting. » Nat | Talk » 08:11, 20 March 2009 (UTC)
Hey, one more! Please update this robot page! It is getting outdated. AntiSurfer gun is already there but it still in "What's the next for this robot" section. » Nat | Talk » 11:51, 20 March 2009 (UTC)
Against random movement (which makes up the majority of the rumble) having a lower rolling depth for your VG will not help, because their movement doesn't change, so one gun (probably DC) will be strongest. For an editor I am using jGrasp - it is lightweight and runs in Java, which makes it easy for me to use on Linux, as well as keep running while also having a browser and robocode open. It indents things very nicely, it's just that eclipse has different indentation rules. Try opening with Wordpad or another text editor, it looks fine =) --Skilgannon 17:17, 20 March 2009 (UTC)
Hey, I look trough your new code (1.3.4) and realize this thing:
if (robot.getRoundNum() < 1 || (DCHits > 0.25*bp && DCHits > PMHits*0.98) || (DCHits*bp > 0.16 && DCHits >= Math.max(PMHits*0.95,ASHits*0.9)) || DCHits >= Math.max(PMHits, ASHits)){
should this be
if (robot.getRoundNum() < 1 || (DCHits > 0.25*bp && DCHits > PMHits*0.98) || (DCHits > 0.16*bp && DCHits >= Math.max(PMHits*0.95,ASHits*0.9)) || DCHits >= Math.max(PMHits, ASHits)){
? If you multiply DCHits with bulletPassed, which both integer, you will get something really large that always over 0.16. » Nat | Talk » 00:18, 24 March 2009 (UTC)
Wow. Yes, that could be a problem =) Programming in the evening, after a day at university which followed a night with minimal sleep, doesn't seem the best idea =) It looks like 1.3.4 lost quite a bit of score against weaker bots (as expected) - I'll release 1.3.5 right away. --Skilgannon 11:56, 24 March 2009 (UTC)
Hmm. It seems there is a problem somewhere. I wish I could do diffs against old versions so I could see where problems are. I'll probably end up reverting back to 1.3.3 and re-applying the changes I made :-/ I guess I should let them at least stabilise first though... --Skilgannon 20:42, 24 March 2009 (UTC)
Hmm? Diffs against old versions shouldn't be hard considering the source code is in the jar file, at least with a *nix system. --Rednaxela 20:50, 24 March 2009 (UTC)
- [View source↑]
- [History↑]
You cannot post new threads to this discussion page because it has been protected from new threads, or you do not currently have permission to edit.
Contents
Thread title | Replies | Last modified |
---|---|---|
Precise Max Escape Angle bug | 0 | 02:14, 22 June 2019 |
Throws exception when MC flag is on | 0 | 04:34, 3 February 2018 |
timeSinceDirChange bug | 2 | 11:10, 31 October 2017 |
close race at #1 | 2 | 15:56, 18 July 2012 |
genetic tunings | 3 | 01:43, 4 December 2011 |
Head-to-head | 17 | 07:14, 19 October 2011 |
exception in 2.2.0 | 1 | 07:04, 22 September 2011 |
Once I noticed DrussGT is orbiting predicted location, I turned on the MC flag to better see the movement ;)
However, in onPaint,
if (!shieldEnabled)gun.onPaint(g);
gun is null when MC is on, while shieldEnabled is false, so it throws NPE.
changing this line to
if (!shieldEnabled && !MC)gun.onPaint(g);
will fix that ;)
Btw, what's the biggest impact on movement between orbiting predicted pos and last seen pos/wave pos do you think?
Hey, I was trying to plug Druss' gun into Knight (to do some experiments using my MEA/preciseIntersection/features calculations to see if they break your gun) and I noticed something interesting in the code.
I looked throughout the wiki and found nothing about it being a known bug (and probably performance enchancing?), so I'll put it here anyway.
In the onScannedRobot() method, you override the "lastDirection" variable with the new direction value before updating "timeSinceDirChange". This causes this variable to be incremented at every scan, as you increment it if(lastDirection == direction). So, the normalized version 1/(1+2x) goes quickly towards zero during the round, which is probably almost the same as having a very low weight for this feature.
Not sure when you introduced this, but maybe it is worth fixing it in the future for a possible programmatic tuning round.
That certainly isn't intended behaviour, and might also explain why I was never able to get much benefit from this attribute. Thanks!
I find it pretty cool that Diamond and DrussGT are so close right now, it's sometimes coming down to the head-to-head score to determine who's ahead. =) (Though I don't find it as cool that it's always DrussGT...)
Yeah, I'm racking my brains for anything which might give me a little edge and have come to the conclusion that my regular, slow, plodding idea/implement/test/release schedule is still the best plan.
And I'm not sure what is giving me these surprisingly high scores against Diamond. Of course, what I gain there I lose in comparison against deo.FlowerBot. How on earth are you managing to dodge a pattern matcher so well?
I similarly kind of took my foot off the gas and decided to just continue my usual development routine. I figure it's going to take more than a minor lead to break away from DrussGT and actually claim the throne. Right now I'm obsessed with matching or beating 1.7.53 by tuning my hit percentage thresholds (flattener, decaying surf stats), because I refuse to rollback to a stupider way of normalizing hit rates. =)
Diamond scores about 44% vs DrussGT over a lot of battles. I haven't focused on it much lately, but I have in the past and just had no idea what to do to improve. Not sure about FlowerBot... I don't think I've ever watched a battle against him. =)
I'm curious about your genetic optimization stuff. This is using genetic algorithms to tune attribute weights with pre-gathered data using your WaveSim-like system? Or is there any GA stuff happening mid-battle? I've generally believed WaveSim wouldn't work against surfers, but at one point I convinced myself I might as well try. I gathered a bunch of data, only to find that HOT outperformed my guns against it, which convinced me it was probably useless. Have you run real battles to check that the improvements correlate, or are you just dropping them in the rumble?
Well, on Talk:DrussGT/Version_History#Anti-Diamond_tuning_.3D.29_404 already stated it was fixed pre-gathered data.
My suspicion is that while HOT performs better than actual guns in such tests, WaveSim-type tests could still be useful(but non-optimal) against surfers in restricted domains (i.e. changing the relative weights in segmentation). For instance... I suspect it may be less useful for changing relatively "dynamic" things like VG rolling weight paramters, than just how segmentation works.
I would say that if HOT is outperforming your guns in classifying/regressing the wave values it probably means that your gun isn't shooting towards GF0 often enough, making the surfers move towards GF0 too often. I haven't actually tested to see if HOT is outperforming my guns, but just changing the weights in my gun can improve my hitrate by ~8% (difference between worst (random) weights and best (final) weights).
I've thought maybe my process should involve recording WaveSim data, doing genetic tuning, recording new WaveSim data with the new tuning, and repeating until it converges. I think this would do quite a good job of having the same effect as genetic tuning directly against a surfer, but much faster.
Well, I'm not sure it means that... I'm not sure how you'd even code a gun to shoot at GF=0 more often (besides stupid ways =P). Regardless, it makes it pretty clear that what works in WaveSim is not what works in real battles, since HOT would perform dismally in real battles vs surfers.
The reason I thought WaveSim might still work against surfers is that even though your WaveSim targeting decisions are based off of a different movement profile than they would be in a real battle, the characteristics of the real vs simulated movement profiles may not be different enough to matter. You're still making each firing decision off the same data set. So maybe I will give it a shot. (Hopefully I didn't delete all that data...) I also love your idea about tuning/re-gathering data.
DrussGT 2.4.5 certainly far outperforms 2.4.4 against Diamond, so that's something. Then again, I've done so much anti-DrussGT tuning recently that it's possible just about any change you made would have improved your score against Diamond. =)
I've been focusing a lot on beating DrussGT and Shadow lately and just wanted to give you props on how incredibly strong DrussGT is. Nothing I do to movement or gun seems to have any positive effect, like there's just some magical element I am unaware of. I tested with my flattener or Anti-Surfer gun hard-coded on, and those too had almost no effect - the flattener helped slightly, giving me my best score of 46.6% over 55 battles, up from the usual 45-46 range. Definitely need to put my Thinking Cap on over here. =)
Haha, thanks. I'm putting in work on my side as well, I'm experimenting with using DC for movement. My best version loses around 0.4% on the MC2K7 vs 2.2.0, mostly against the top bots, so I haven't released anything yet as I don't want to lose my new PL crown =)
Oh, neat! DC surfing requires some serious thought after years of doing things in VCS ways. I'm still working some fairly basic things out, after all this time. It gets you to really analyze how/why aspects of your VCS setup worked. Actually, I think I had an important realization just last night...
0.4% doesn't sound like much. :-P But then I don't think MC2K7 is a particularly robust way to measure a drastic movement change, either.
Interesting, no matter what I tried I couldn't get it better than my 3rd try (the -0.4% one). I guess I'll have to stick with my VCS for now... it's just that DC would be much more suitable for an idea I had...
Sounds familiar. =) You sure you ran enough seasons? Sometimes I convince myself I ran enough and then waste lots of cycles trying to match what was actually just a lucky score...
100 seasons, which should be plenty... minor tuning changes score slightly less but in the same region. Maybe I'll try identical code and see what happens...
My intuition is that so long as the magnitude that dimensions are weighted with is similar, the most likely sources of loss/differences between VCS and KNN would be:
- Non-linear spacing of segments in the VCS. In order to achieve maximally similar results between methods, you need to preform transforms on the dimensions to approximate the result of any non-linear spacing of segments in the VCS.
- Insufficient number of KNN data points used when the data is dense (late in battle). How many data points should be used should probably be larger as the data becomes denser. The density of points returned should probably affect how many points are used.
Have you looked into these factors Skilgannon?
I'm going to try the non-linear thing just now - good call as I had forgotten about this despite spending quite a while tuning it in my gun.
I'm currently weighting based on distance to the location point as a function of the average distance of the closest 3 points - it works quite well but I wouldn't be surprised if there were improvements which could be made.
While I think those points are valid, I somewhat disagree with their importance.
- I've experimented with different scaling of attribute differences, but never to any major success, in gun or movement. I'm currently not doing this anywhere in Diamond.
- If the data is dense anywhere in the graph of your movement data, it probably means you're getting hit a lot by a learning gun, at which point a much bigger issue is modeling data decay intelligently. Experience has shown that in VCS, stat buffers of varying depths with a generally low rolling average works well. There's no direct way to translate that to a DC setup.
Personally, I'd say that intelligently modeling data decay in DC surf stats is probably the biggest hurdle in converting from VCS. It's actually one of the main things I'm still tinkering with. I'm pretty happy with the setup I've arrived at in Diamond, but I think there's still a lot of room for improvement. I'd be happy to go into more detail about that if anyone's interested.
Here are my thoughts on those aspects.
The approach to data decay I took in RougeDC was to have an "index" dimension which continually counted up. This is kind of mean/nasty to the kd-tree performance, but as far as KNN search I think it's a very natural way to model decay.
Regarding varied depths, I'm pretty sure the depth of VCS segmentation is extremely analogous to the number of KNN points used and how they are weighted. The way to match that aspect of VCS systems is to mix the result of varied numbers of points in varied weightings. Since processing the same points multiple times is redundant it simplifies to the following: The way to get the same effect as varied depth VCS, is to work on how your weighting of KNN points rolls off, and use plenty of KNN points so it rolls off properly before the limit on number of points is reached.
I don't know if you were referring to this Voidious, but with regards to having many stat buffers as some like DrussGT do, my experience is you get the same effect by performing antialiasing and interpolation. This implies to me that the primary cause of "many stat buffers" being effective for traditional VCS is that it acts as a sort of accidental stochastic antialiasing. A KNN approach implicitly needs no antialiasing/interpolation, so that aspect of VCS setups does not need to be arranged.
(We might just move this thread to Talk:Wave Surfing at some point...)
Well, I agree that much of the value of multiple VCS buffers is covered inherently by a DC system: smoothing of the data and scaling to different amounts of data (eg, no need for a quick-learning unsegmented buffer in DC). So while my best VCS gun has a few stat buffers (and your best does anti-aliasing / interpolation), my best DC gun has only one tree. But while I wouldn't expect to have 100 trees in a DC movement, I do have more than one and I think there's value in it.
As far as data decay in a DC system, I think the progression from simplistic to sophisticated goes something like this:
- Weighting by age. This is not without merit, but is pretty crude. An old piece of data may still be the most recent for that situation.
- Capping number of data points, deleting old ones. Also pretty crude, but effective if it's very important to emphasize recent data. I still do this in parts of Diamond.
- Within the set of nearest points, sort chronologically and weight by rank. This is about as close as you can get to how rolling average works in a VCS segment. I weight data by 1 / (base ^ sort position). So with a base of 2, they're weighted 1, .5, .25, ... . A base of 2.4 is about equivalent to a rolling average of 0.7.
- Use multiple, exponentially increasing values of k (say 1/4/15/50), with each set of data weighted by chronological order. This emulates having stat buffers of increasing segmentation depths, each with a rolling average. The deepest set of segmentation is akin to taking a low k nearest neighbors search, while an unsegmented buffer would use the max value of k.
Lastly, this is just a hunch, but I think another value of combining many different views of your data is that you achieve a safe pseudo-randomness. That is, simply surfing one set of data will make you move more predictably than the sum of a diverse set of viewpoints - at least with a True Surfing algorithm. But surfing that sum of viewpoints is still going to err on the side of dodging bullets accurately, in contrast to a truly random movement.
I need to figure out a way to phase out old scans - however all my experience with using time weightings in DC have been utter failures. I just tried another right now (a counter that counts every tick of the match) and it didn't help either, although maybe I need to weight it lower than I have right now.
I'm thinking maybe using a limited number of points in the tree, and removing the closest when the limit is reached. Then when I need neighbours for creating a buffer I weight the hits by the time they were logged. This should approximate the way VCS does things.
I don't like the idea of 'doing it the way VCS does it', even if it works, because we don't exactly know why VCS works so well that way either.
Perhaps, for a simple quick method take a sqrt(tree_size) cluster and just use the most recent point. Who knows...
I totally agree that emulating VCS is not the ultimate goal, but it does seem like a good starting point. For instance, I think weighting similar situations by chronological rank instead of raw age is a good insight that I wouldn't have noticed if not for considering how things work in VCS.
Oh, I did try phasing out nearest point instead of oldest point for a while. I thought that was such a great idea (I recall it came out of a discussion between us), so I tried hard to tweak it into submission, but I never got any improved performance out of it.
I'm not sure about that, I think raw age might be better for trying to emulate enemy guns. They log hits all the time, not just when a bullet hits, so if there is a bit gap between two bullet hits the last hit may be getting weighted proportionally much higher than it should be. This is something I think VCS does wrong, which can be addressed in DC, if only I could get the scores back up to where they were =)
But it's also the case that a piece of data that's 100x older but 10x closer to the current situation (wrt the rest of the attributes) may be a better estimate of where the enemy is firing in that situation. The ratio of those values is going to depend on how granular the enemy's gun is. So I think considering the situations sorted by time at a bunch of different granularities is a pretty good bet, and I think it's similar to what our VCS systems do with great success.
You have got me thinking again about super-lightweight flatteners against weaker learning guns though. =) It does bother me that they're learning all the time and I'm not!
Btw, I'm up to 49.3% vs DrussGT 2.2.2 now with Diamond 1.6.15 (over 1000 battles). I got up to like 49.7%, but only with some changes that killed my scores too much vs Shadow and Tomcat. I decided to stop spinning my wheels for now and move on to more general improvements. =)
Heh, I was getting worried so came out with some changes which may just help in the AS department. My strongest PL version is probably 2.3.7, although I need to figure out what is loosing me my 0.1APS since 2.2.2... I'm happy to improve my PL but not at the expense of my APS =)
Been running a lot of tests vs DrussGT 2.2.0 lately and I just noticed an exception I've hit twice along the way (in the data dir). Probably over a few thousand battles or so.
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) at jk.mega.dGun.DrussGunDC.onScannedRobot(DrussGunDC.java:254) at jk.mega.DrussGT.onScannedRobot(DrussGT.java:266) at robocode.ScannedRobotEvent.dispatch(ScannedRobotEvent.java:297) at robocode.Event$HiddenEventHelper.dispatch(Event.java:244) at net.sf.robocode.security.HiddenAccess.dispatch(HiddenAccess.java:194) at net.sf.robocode.host.events.EventManager.dispatch(EventManager.java:487) at net.sf.robocode.host.events.EventManager.processEvents(EventManager.java:460) at net.sf.robocode.host.proxies.BasicRobotProxy.executeImpl(BasicRobotProxy.java:413) at net.sf.robocode.host.proxies.BasicRobotProxy.execute(BasicRobotProxy.java:123) at robocode.AdvancedRobot.execute(AdvancedRobot.java:565) at jk.mega.DrussGT.run(DrussGT.java:156) at net.sf.robocode.host.proxies.HostingRobotProxy.run(HostingRobotProxy.java:220) at java.lang.Thread.run(Thread.java:680)