Being simple doesn't mean being not advanced. Being simple means the reason why it works is simple. In this page, I will describe certain techniques I used that made SimpleBot simply works.
SimpleBot is using only one gun, which is a traditional kNN gun with gaussian kernel density. The attributes I use are BulletFlightTime, LateralVelocity, Acceleration, ForwardPreciseMEA, ReversePreciseMEA, TimeSinceDeceleration, and CurrentGuessFactor. Those attributes are the most useful attributes I've found in the past years, and they are also used by a lot of bots, etc. DrussGT, Gaff. Credit will give to Skilgannon in his great DrussGT/Understanding DrussGT, where I first see those attributes a few years ago.
In kernel density (which affects the performance a lot) I use max overlay area, say, I extend every recorded GuessFactor to a GuessFactor range, based on bot width at current distance, then see where they overlap the most. This is different from DrussGT, as I don't record precise bot width at wave intersection (being imprecise may decrease performance, but it's simple ;)). I use these approach as it's faster than iterating through every pair of two GuessFactors. And it's closer to robocode physics as well.
To eliminate the effect of irrelevant situations, I use gaussian distribution as weights and give the most weights to those within the average distance of the cluster. Cluster size is simply sqrt(totalSize), as this will make my gun a statistical gun when there's not so much data (when I don't know its movement well), and a pattern matcher when there's enough data. Using gaussian distribution greatly helps these process as well, as the average distance would be great when there's not so much precise match, whereas the average distance will be tiny when the situation is already faced a lot of time.
Currently I don't use any manual decay, as with so many attributes, it's already hard for a new situation to be the same as an old situation (and newer situations are easier to match newer situations, if its movement is adaptive), which works like some hash algorithm.
SimpleBot's movement is simple — it selects a few GuessFactors and try to avoid them. One is the most recent hit, the others are from trees, where one tree gives one GuessFactor.
- On choosing what to dodge
Currently SimpleBot is using two trees in its movement, one is called SimpleTreeView, another is called NormalTreeView. SimpleTreeView uses three attributes, BulletFlightTime, LateralVelocity and TimeSinceDeceleration, whereas NormalTreeView is using BulletFlightTime, LateralVelocity, Acceleration, ForwardPreciseMaxEscapeAngle and ReversePreciseMaxEscapeAngle.
In movement it's very different from guns. In gun you know a lot about enemy movement, and all you need to do is to select one firing angle. But in movement, you know only your own movement, and their bullets that hit you (or hit your bullets).
Since you know only a little, if you are using a lot of attributes, the result may be very close to random, as those irrelevant attributes would take control. Instead, you may want to break attributes to some combinations, and combine the result later.
Currently SimpleBot is not weighting the attributes, and it simply selects best match in each tree. Those selected GuessFactors are not weighted as well. I tried using the same kernel density strategy with gun but it doesn't work as expected at all.
Meanwhile SimpleBot doesn't have a flattener. I've tried a flattener that's always on, but removed it later, as the improvement is as remarkable as the decrease ;)
- Surfing Algorithm
SimpleBot uses a fairly simple true surfing algorithm to dodge bullets. Unlike most bots, the danger is calculated as 1 / (1 + abs(diff)), which decreases slowly. I tried something different but nothing else works.
SimpleBot currently surfs two waves at the same time, weighting two waves on the damage they may deal (considering only bullet power).
- Tracking enemy firing angles
What's really special of SimpleBot is its fire tracking algorithm. Unlike most bots, which tries to match bullet hits with existing waves they dodge, SimpleBot's fire tracking system is completely separate. This system is originally designed in a Melee bot to precisely track enemy firing angles in melee. Instead of trying simulating exact game physics at fire time, I save everything I have until new information come. Say, I save all possible fire positions the enemy used to be, and every possible scans he might have. When hit by a bullet, I brute force through the history to find one exact match (or it will try to find the best match), which works pretty well in melee.
Even if SimpleBot is a pure 1v1 bot, an algorithm works well in melee must work well in 1v1, as in 1v1 you have even more information. Therefore I brought the idea to SimpleBot, and made the possibly most accurate 1v1 fire tracking system (and the simplest as well).
- Detect enemy fire
As my tracking system is completely separate, I won't need to consider the negative effect of changes in fire detection system on tracking system, which simplified the design a lot as well. Basically enemy fire is detected whenever there is a energy drop — but it's also important you remove the effect of bullet hits, which happens frequently. I also try to simulate enemy gun heat to prevent false positive waves from firing when enemy hits wall or energy drain happens.
- Fallback movement
One thing that is special in SimpleBot is its fallback movement — it is fairly simple while very effective against rammers. Unlike most state-of-the-art surfers, SimpleBot yet doesn't use gun heat waves. Instead, when there is no waves in air, every tick, it surfs a dummy HOT bullet that is fired from the same tick, and deletes that dummy bullet immediately. In this way, I'm able to reuse the danger evaluation of WaveSurfing to push me to a good position constantly. It works surprisingly well against Rammers, as a rammer just feels like some HOT bullet that fires at you constantly. As a side effect, this algorithm also maximizes MaxEscapeAngle, which is good against both real bullets and rammers. This may be one on the most effect fallback movement against everything, especially rammers, and it's simple!