BulletShielding is a strategy where your robot shoots down incoming bullets, thereby 'shielding' itself from enemy fire.
How does it work?
The concept is very simple. The idea is to make your bullets collide with the enemy bullets. When the enemy fires a bullet, aim your gun to shoot that bullet down, but only fire bullets with 0.1 power. When intercepting a bullet, both bullets explode; but while the enemy is firing high-powered bullets in an attempt at hitting you, you are firing only 0.1 power bullets. The enemy's energy drains much faster than yours, and eventually the enemy runs out of energy and dies from InactivityTime?. Voila, you win!
How do you intercept a bullet?
To intercept a bullet, you need to know three things: its position, its speed, and its heading.
To find its speed, first find the bullet power by taking the drop in the enemy's energy, then use the power formula to calculate its speed.
To find its heading, simply assume the bullet is going to hit you. This assumption is valid because if the bullet isn't going to hit you, then it doesn't matter if your shield catches it because it will miss you anyway! The algorithm to assume this is explained below.
After finding those, find its position: it's given by the enemy's position at the frame when it was fired, so one turn before you scanned it, and then iterated twice from there (i.e. it moved 2*speed pixels in the direction it's heading).
So now that you know its position, speed and heading, just use a linear lead fire algorithm to intercept it, the same way you would lead-fire an enemy; the only difference is that you are lead-firing a bullet rather than an enemy.
The actual implementation of intercepting the bullet is far more complicated, and is explained below.
How do you calculate the bullet's heading?
To find the bullet's heading, as stated above, you have to assume the bullet is going to hit you. To do this, you're going to have to know your FuturePosition. The simplest way to do this is to move in straight lines; you can then find where the bullet will hit you by using a simple lead-fire algorithm. This is how OddBot? predicts its FuturePosition. The problem with this is that it breaks down when you come up to a wall. You'll end up assuming the enemy's bullets are heading into the wall while you will actually turn around and continue back on your path; from the time when the bullets will be able to hit you after you hit the wall until you actually do hit the wall, the shield will fail, and you will be completely vulnerable to enemy fire.
The most accurate way is to program your movement system to know exactly how it will move for the next few dozen frames, then discover where you can be hit by a specific bullet iteratively. In other words, your movement system should either follow a concrete pattern that it can predict, or schedule its movements early, or use a mixture of these. It should move so that its own movement is 100% predictable.
Before I had formatted my harddrive, SineSweep used a cross between these two methods. Its movement was almost exactly like Wisp; it moved along the walls but rounded the corners, and used antigravity to decide when it would turn around. However, it scheduled when it would turn around beforehand. It would look ahead a few dozen frames, and decide if it should turn around then; if so, it would schedule a reverse at that point. This way it knew exactly when it would turn around. Using its concrete movement pattern and scheduled turns, it could always find out exactly where it would be in however many frames it needed.
Once you've programmed your robot to move predictably, you need to program an algorithm similar to Albert(?)'s FuturePosition, but taking into account your robot's movement decisions at every turn. This means you'll need to advance both you and the enemy bullet one frame, check if theres a collision, ask your movement system how it wants to move, and repeat until the bullet passes you. Log all the places the bullet will collide and take the average.
SineSweep did this using a seperate class which simulated the AdvancedRobot. It had all the setXX calls, and held the robot data. When asking the movement system how it wants to move, it asked it using the simulated AdvancedRobot rather than the robot itself. The movement system could not know the difference between whether or not it was issuing commands for the robot itself or for the iterator system, so the iterator algorithm could always predict where it will be with 100% accuracy.
Anyway, once you end up with a collision average, you'll have the coordinates of where you can be hit by the bullet. Assume the bullet is heading there and do a simple delta arctangent to calculate the heading of the bullet!
Can you explain the complete algorithm for intercepting the bullet?
I sure can.
Okay, explain the complete algorithm for intercepting the bullet.
Okay then. Let me first explain how bullet collisions work.
How do bullet collisions work?
Ah, you're probably wondering how bullet collisions work.
(okay, somebody slap me... *focus, focus!*)
Bullets in Robocode do not occupy any space; they are simply lines. The length of the line is the bullet's speed, and the direction of the line is in the reverse direction of where it's heading; in other words, the line the bullet 'occupies' is that of it's last displacement. Like so:
For bullets to collide, their last displacements must intersect. That's how bullets collide in Robocode.
How do I cause the bullets to collide?
Firstly and most importantly, you need to do ALL of the following calculations (except the power recalculation) one frame ahead of when you are planning to fire. This means that if you plan to fire the following turn, you need to iterate ahead a copy of your robot and a copy of the enemy bullet by one frame, then do the following calculations with that data. That will get your gun ready before it's time to fire it. On the frame when you will fire, redo the following calculations with the real robot and bullet positions; your gun should already be pointing at exactly the angle that the algorithm will give you. If it's not (within about 99.999% certainty), you'll need to start over from the top, iterating the robot and bullet ahead and getting the gun ready for the next turn.
To intercept a bullet, first you start off with a form of linear lead fire, just like you would if you were intercepting an enemy robot moving in a straight line. The difference is that rather than looking for the angle where to aim, you will need the coordinates where the bullets will collide. You can calculate this however you would like; if you are comfortable with traditional lead-fire formulas, you may find it easier to find the angle where you should aim your gun, and then find the linear intercept from there. Either way it's some simple trigonometry to find the coordinates of this point. Use a bullet power of 0.15, because you will need to adjust it later.
Once you've got the coordinates, you will need to adjust them. The idea here is to minimize your chance of missing the enemy bullet by making the displacements of both bullets intersect at their midpoints. The reason for this is that you do not know with absolute certainty the heading of the enemy's bullet. If the calculated intersect is near the edges of the bullet displacements and the actual enemy bullet heading is a bit off, the bullet displacements might not intersect, which means the enemy bullet would be missed and would hit you. To prevent this, you must recalculate your gun heading and bullet power.
Using the intercept coordinates you calculated earlier, slide them along the enemy bullet's trajectory to make them land at exactly the midpoint of a nearby displacement. To do this, use parametric (or vector) equations for your coordinates to calculate a parameter, then subtract 0.5 from your parameter and round it off, then add the 0.5 again and recalculate the coordinates. This should slide the coordinates like so:
Now find the heading to aim your gun to intersect these new coordinates using a simple arctangent. This is the heading to fire your gun.
Lastly, you need to find what bullet power to fire your gun. The original calculations were done for a bullet power of 0.15; you need to adjust the power to make your own bullet's displacement intercept at its midpoint also. You don't actually need to perform this step a frame ahead like the rest of the calculations, because it isn't necessary to know the power beforehand; this step can be performed when you are firing. To do this, divide the distance from your position to the intercept coordinates by the calculated parameter (rounded to nearest 0.5) above. This will give you the speed your bullet will need to travel; simply use the speed formula backwards to find the power you need to fire. Voila!
The bullets should now collide at the midpoints of their last displacemenst. This is the complete algorithm for bullet shielding; the intercept recalculation gives you the most chance to intercept an enemy bullet. With this, you can protect the most of your robot by maximizing the enemy angle you intercept.
Anyway, that's all there is to it. A few suggestions I should make are to keep your robot moving in long straight lines; in general, the greater the angle between the bullets' heading, the more chance they have to collide providing the algorithm is implemented properly. This means that keeping your bot moving in straight lines will make the enemy have to fire far head of you, giving you a greater angle between their bullet heading and your own which gives you the best probability of intercepting it. You are most vulnerable when reversing direction (or returning on your path however you turn around), because the enemy can fire directly at you before you reverse direction, so intercepting this bullet will mean you are firing at it with only a few degrees difference in the angles (almost directly along the same line). The slightest variance in enemy bullet heading will cause your bullet to miss it, and you will be hit by the enemy bullet.
Anyway if I remember more about how this works I'll add it on.
Questions and comments welcome!
Thanx for sharing this Vuen. You inspired me before to try and implement a bullet shield myself, but i couldn't make it work properly. Now i find your workshop really interesting and might try again. -- Vic
Place 2 sample.Fires in a battle. They will both stay still (i think you actually have to comment the onHitByBullet? method to stop them moving, i can't remember) and shoot directly at the center of the enemy. This means the bullets are travelling on the same line (just in opposite directions). Why don't these bullets collide? -- Tango
Before knowing about Vuen's research into this field I thought I got the idea about BulletShielding first and immediately tried two non-moving head-on-targeters. Also immediately, I scrapped all plans of implementing a bullet shielder when even these bullets didn't collide. This is my length way of saying that I am too very curious about the answer to Tango's question. -- PEZ
Bullets are represented as a line which has a length equal to their speed. They colide when they intercept each other. But since both targets are static, and fire at the center of th enemy, both bullets will be paralel, thus never intercepting. In other words, you have to intercept bullets firing them to its side, not front. -- Albert
I have tried this approch myself, inspired by SineWave?, I even did the variable power bit, worked out the nasty tick shift issues the hard way and got it all working, but it did not give a large enough shield at reasonable distances - the problem is that by the time you get enough distance to give a 36 to 50.91 (Sqrt((36^2)*2) wide shield for your bot you can't reliably travel far enough at right angles before hitting a wall, which means less shield width - also lower power bullets from the opponent is an easy way to shrink the size of the shield. It was days of hard work - all to no avail. -- Paul Evans
You also have to successfully predict the angles your opponent fires at. If you can do that then you can simply implement an AG bullet dodger. Edit: Err.. nevermind, I just realize you can force the enemy to fire full lead or shield your future positions. -- Kuuran
That explains why when i place two identical bots that use linear targetting, when they are moving parallel to each other that their bullets always intercept...DragonTamer
Im 'developing' ShootDown?, trying not to be that predictable in movement, but doin as Paul tries: Shielding a position where i will move to. Like an umbrella (hmm, thats a good robot name ... :D). Maybe i'll use Waves for this ... anyone is good with geometry, areas, etc? ;P - Qetu
has anyone tried doing bullet shielding with enemy waves? with heavely segmented enemy wave stats, or some pattern matching thrown in (involving you and their gun), you could pretty accuratly predict where they are going to shoot. and isn't that the hardest thing about bullet shielding?--andrew
I heard about that Vuen did it. I think that Paul too. -- Axe
But donīt know if they succeeded. -- Axe
no. you don't need information about the gun of your opponent. If you have information and you know where your opponent is going to shoot make some AM stuff but don't waste your energy doning BulletShielding. if your opponent uses some kind of random targeting you could think about it, you just want to make sure that there are no bullets in the air facing towards your future position. The problem is as written above by Paul that the area you could make "bullet free" is too small. -- rozu
Like a circus elefant holding a tiny umbrella... :) -- Axe
For me just knowing Paul gave this a really serious try and not getting the goods out of it is enough to disregard the whole idea for competetive uses. =) Until someone proves it's working. Then I'll be as happy to jump on that train as I am with all other trends. --
I don't mind if it is a competitive idea. I want to get it. I'm still developing this! -- Qetu
If you make a 1-on-1 Bullet Sheilder, every time they fire at you, you could move a very small amount in any direction and intercept the bullet! This would only sheild against HOT, but if they don't shoot directly at you, they will miss! --Bayen
You dont need a shielder against HOT... And the problem is(already written somewhere), that your shield is to small to prevent your whole bot. But indeed it would bee funny to beat the sample pots with such an gun (SampleBotChallenge/Targeting or WaveSurfing/BarracudaChallenge). --Krabb
Been a while since ive been on the wiki, being busy with college and all that. Quick mention is to use reverse guessfactoring, similar to wave surfing, but to shoot to protect against one of the spikes. you can prevent being shot at certain spikes in your profile by protecting shots to that guess factor. -- Jokester
If your are using Robocode NG, the Shotgun mod would allow a much larger sheild! --Bayen
I was just reading this, and thought of an idea: Instead of theming Firing/Movement? on bullet collisions like this, why not use this technique to enhance the existing methods of WaveSurfing? Basically, track movement of your own bullets, and check what "umbrellas" exist, and set the danger factor to 0 where it is covered by an "umbrella". A robot using this would be able to take advantage of these zero-danger locations while still using good movement when it can't get to these zero danger locations. You don't even to make the firing algorithm optimized for creating as much BulletShielding as possible, just just look at what lucky BulletShielding happens to exist. Perhaps this could be combined with firing that is designed to create more BulletShielding, but even without that you could use this to make WaveSurfing just a little bit smarter. -- Rednaxela
How about using this in a team setting? Each team member can sit perfectly still in a corner while laying 'cover fire' for its teammates. With enough distance between team members, the heading angles (attacker vs intercepter) would be close to perpendicular, increasing the chance of intercepting the bullets every time (widening the 'umbrellas'). With perfectly stationary bots, predicting the enemy bullet trajectories would be trivial, although you'd have to assume that every enemy bullet was heading towards every one of your team bots, which might be an overwhelming number of bullets to intercept. -- Scarpia
Actually, I have been thinking of trying something like this myself though I haven't gotten around to trying to implement it yet. As far as the issue of needing to assume every bullet is heading to every team bot, I think that would indeed to be an overwhelming number to intercept when the teams are significantly sized (5v5 like standard RoboRumble teams), but it may work somewhat in smaller teams (like 2v2). In 2v2, by using 0.1 power bullets, you could fire pretty fast, but looking at the gunheat calculations it would still be 11 ticks between each time you can fire, when people firing 3.0 power bullets have 16 ticks between each fire, which means that even in a 2v2 setting in which this type of shielding would be most manageable, you still couldn't fire fast enough to be certain you've blocked everything. I think it might be a useful auxiliary strategy however when a team has two members left and the other team only has one left. -- Rednaxela