Talk:DemonicRage
Contents
Questions & Comments
Very nice! Seems you've won the race to melee surfing? (EDIT: To melee surfing that collects stats I meant. Since apparently Shadow does do non-learning wave surfing in melee, and while I believe Portia learns a little about enemy targeting it's not technically a wave surfer) I'm a little surprised by DemonicRage still performing behind Glacier though. Perhaps do some 1v1 tests of the surfing to see how well it's working in a more basic situation? --Rednaxela 15:16, 23 April 2010 (UTC)
Thanks, your right... I haven't really tested the 1vrs1. The only difference between the melee and 1vrs1 is seperate Stats, which are both non-Segmented. I haven't tried segmenting yet, but I'm sure the 1vrs1 needs it. -Jlm0924 17:35, 23 April 2010 (UTC)
Version History / Discussion
DRv3.0
- Lately I have completely rebuilt and improved Demonics foundation (still based on Module) I implemented Rednaxela's tree into a bare bones version of D's gun, which I plan to later expand after the new movement is fleshed out. The gun's new PIF I made should be quite quick. I'm not sure how it compares to displacement vectors or if it's type has been done before, but I will post it and D's Radar source code next chance I have.
- I released DR3.0 early. I just got the melee movement working and the gun is untuned. 1vrs1 is temperarily random. I should of disabled some painting and tested for skipping turns, but it seems fine. -Jlm0924 17:11, 20 April 2010 (UTC)
DR3.03 - DR3.05
- despite finding a small bug in DR3.03 1vr1 movement, It's still performing sub par. I will need some time to improve DR's 1vr1 waveSurfing ( i've never spent much time there before.) Till then; I slapped the old random 1vrs1 movement back in to see what happens in the rumble. —Preceding unsigned comment added by Jlm0924 (talk • contribs)
- Well, personally, I'd put one HawkOnFire vs DR3 in 1v1, and attempt to fix the remaining times DR gets hit since HOF is just a "Head-On" targeter. In some tests I saw it dodge well enough that it's clearly surfing, however got hit often enough to indicate the surfing is flawed in some manner or another. --Rednaxela 23:52, 25 April 2010 (UTC)
yeah the bug in 1vrs1 : DR3.03 was accidently not just surfing the closest wave.. (It might have choosen a high risk part of the closest wave if that position was low risk on the waves behind it.) Without that flaw (unsegemented) works great for the first 10 rounds or so. Then the big guns start gaining ground back.. I tried simple segmenting, but it learns too slow to compete with the better Guns. I know nothing about the more advanced wavesurfers.( Whats going on in Druss/Diamond or Glacier?) ..but I'm going to avoid the segment setup, and try surfing with DC. `Jlm0924 06:42, 26 April 2010 (UTC)
Well, Glacier isn't a surfer (in fact, it's 1v1 movement is terrible, just see it's non-melee ranking). Well, how to set up learning for surfing is basically the same as building a gun. I'm sure DC will work better than a single segmentation, though some like Druss have success with overlaying multiple segmentations. One note is usually one segments surfing less heavily due to the reduced amount of data. The other note, is that the particularly good guns start gaining back ground, even with segmented/DC surfing really, and what is usually done to counter this is enable a "flattener" when the enemy hit rate is high enough. The "flattener" basically keeps stats of where you've been, instead of where you've been hit, and you dodge that as well. This works well because it avoids going to the same place twice even if you haven't been hit there yet. Note though, a flattener isn't really necessary. Midboss and RougeDC in 1v1, both lack a "flattener" yet still score high (though not so high against the strong bots due to the lack of such). One thought, is because melee gives much less time to learn than 1v1, perhaps it would make sense switch to pure-flattener against the final remaining bot? I say such because I think chances are the final remaining bot is strong enough that flattener could be best. --Rednaxela 13:33, 26 April 2010 (UTC)
From Portia's stats that was posted sometimes ago (I can't remember where), there is only a few bullets that actually fell into your escape angle and actually hit (the one you can save stats), so your should combine it with your old MR movement to be competitive. My two cents anyway. --Nat Pavasant 14:00, 26 April 2010 (UTC)
- Thx for your wisdom Rednexala. DR has a flattener. But it worked better always off, then alway on :) so I will try enabling it as you suggest. When I get Home, I will release DRv3.06 with (NO-SEG, NO1vr1 bugg, and properly activated flattener) into the (Non-Melee) Rumble for the first time..and go from there. :)-Jlm0924 00:35, 27 April 2010 (UTC)
DR3.06
- VR3.06 released.. ( still no segment, removed small 1vr1 bug and found bigger melee stats bug, played with the flattener (the stats to enable it were swayed by melee/ so I disabled for now) I also removed 2 gun distancing functions (distance and angle) and enabled painting waves. I've come to realise there is alot I can improve still. Currently Dr is selective on which waves it 'sees'. TODO list : allow DR to see more waves and weight them. Precise escape angle. -Jlm0924 00:35, 27 April 2010 (UTC)
DR3.07
- tuned gun, added 1vrs1 flattener(rarely on, if ever) reduced health wieght, and territory wieghts, (which I should look at again for further improvement). fixed bug in bin smoothener and redesigned and tuned. Currently in number 2 spot with 414 battles :) Hope it holds on :) Just in time as I'll be back in school soon.-Jlm0924 19:50, 29 April 2010 (UTC)
- Cool, fingers crossed dude! --Voidious 19:44, 29 April 2010 (UTC)
- I'll cross'em for third :)-Jlm0924 19:50, 29 April 2010 (UTC)
- Very nice! I guess this means I'll need to get working on Glacier... (given how terrible it's movement is in 1v1, perhaps I should just throw a quick random movement in to get an instant boost...) --Rednaxela 21:34, 29 April 2010 (UTC)
- You should .. Your kick-butt gun is probably begging for it :) .. I'm waiting for 3.07 gets 1500 battles or so before releasing 3.08 ;) -Jlm0924 23:52, 29 April 2010 (UTC)
Doh! What happened with 3.09? Hope you keep your old source. =) By the way, did you see this bug we found in the Wave Surfing Tutorial? Discussion of it at Talk:Diamond/Version_History#1.5.5, code change you should make here. --Voidious 03:18, 2 May 2010 (UTC)
Yes I did notice this issue, but don't think I fully caught the bug.... (I was aware DR had this issue and was going to look into it ) I've been using:
- && Math.abs(e.getHitBullet().getVelocity() - ew.velocity ) < 0.007
- Thx for the heads up ! :) I will try the suggested code and see if it helps DR catch the bullet hits it was missing :)
I not sure what happened with 3.09 yet.. I suspect I introduced a new bug which I didn't catch before releasing. I haven't looked into it yet.. but suspected earliar that he was getting kicked out of battles late in the rounds ( but I guess not). No one has seen any errors messages pop up have they?? -Jlm0924 20:24, 2 May 2010 (UTC)
All Versions of DR are now skipping big Time !! -Jlm0924 15:21, 3 May 2010 (UTC) I'm starting to get annoyed! I am using robocode 1.6.1.4 for testing.. In future Version of Robocode I think the time that aloted to bots before they start skipping turns needs to made more consistant.. The results of recalculating the cpu constant are far to great, which don't accomodate a pc's current work load. I am releasing DR 3.1.0 as 3.11 that has been made light years faster.I believe it is one of the fastest DRs made. Though There are still no guarentees it won't skip.. :( -Jlm0924 16:23, 3 May 2010 (UTC) Oh, I also added alittle dynamic anti skip. If it skips a turn, It will started reducing iterations on the gun and movement.. which hopefully reduces performance less than the skipping of turns... -Jlm0924 16:34, 3 May 2010 (UTC)
- I hear you with getting annoyed there. Midboss in 1v1 there is having skipped turn problems itself. About making the time before bots start skipping turns more consistent, it's pretty difficult. See, currently Roboceode uses System.nanotime() to measure how long a robot is taking, which is subject to current load of the machine and such. There are APIs in Java that allow getting the CPU time used by the robot thread instead, however, these have much worse resolution than System.nanotime(). On Windows, those APIs are inaccurate enough that the only way used CPU time could done instead of System.nanotime(), would be if the average time over several turns was used to determine whether to skip or not. It's a bit of dilemma really. --Rednaxela 16:50, 3 May 2010 (UTC)
- From the sounds of it... averaging nano time may help smoothen out spikes in machine load.... not to mention alittle forgiveness for guns targetting every 27th turn or so... -Jlm0924 23:59, 3 May 2010 (UTC)
- Despite this version of DR doing well, I still suspect he is running into a slew of skip turns dew to inconsistency . Out of curiousity; Does robocode recalculate the cpu constant before every battle, or only manually / during install ?? I notice DR vrs Portia are unstable battles, and wonder if it's a skipping turns issue; Or a memory issue. I know DR is a memory hog ( which I will try to address soon.) I suspect Portia is also... (I hope bots don't start fighting for resources) It would be great if Robocode displayed a bots allowable memory and CPU time; the head room remaining... -Jlm0924 00:17, 4 May 2010 (UTC)
- Robocode only recalculates the CPU constant when you tell it to (or edit it in robocode.properties). I agree that taking a wider view of CPU time used would probably be a good thing. DrussGT has similar problems, because its GoTo Surfing does most of its work in one tick, but it doesn't have to do much of anything most ticks. Does DR print when it skips turns? I can check on my currently running MeleeRumble client for you. It's a dual core machine with only one client and nothing else running, so it should be close to "optimal". Oh, and big congrats on the score jump! =) --Voidious 01:03, 4 May 2010 (UTC)
- Thx Void. Yeah DR prints in normal fashion when it skips.. That'd be great if you could check :) I suspect it's only when it fights other resource hungry bots.. I'm guess you added some bells and whistles to your client :) I still need to take some time out and figure out how to run roboResearch.. :)-Jlm0924 01:25, 4 May 2010 (UTC)
- Well, I'm not seeing too many skipped turns from DR here:
- First battle: DR, Diamond, 4x HawkOnFire, 4x Coriantumr. DR skipped 2 turns total, first time in round 21.
- Second battle: DR, Diamond, 4x Coriantumr, 4x Shadow (going for a "more resource hungry" field). DR skipped 2 total again, first time in round 12.
- --Voidious 19:30, 5 May 2010 (UTC)
- Thx Void... 2 turns, is okay I guess..
DR3.12 -DR3.13
Well I was quite pleased on 3.12's performance and ranking jump. (2nd place melee rumble) Though it managed to fair better against all bots.. Diamond still held it's ground in ranking. After some tweaking and mods to enemy threat factors.. DR3.13 lost it's edge to Diamond and over-all ground.-Jlm0924 03:43, 7 May 2010 (UTC)
DR3.12a
I released 3.12a to test a mod to enemy threat. (my testing was hard to tell) It dramatically increases DRs aggressiveness gainining a good amount of bullet damage. Though it gambles it's survival and will likely get into trouble with tough bots. Hope the mod stays, as it adds some character :) ... It did better than expected :) -Jlm0924 20:38, 7 May 2010 (UTC)
- Very impressive gain with 3.12a there! So that was from making it more aggressive to enemies that are deemed not as strong? --Rednaxela 22:49, 7 May 2010 (UTC)
- No ... It's getting closer to enemey(s) not targeting him. For example Dr will consider 2 bots ramming as almost zero risk and at times get within a bots width. The obviously upside is greater bullet damage to unsuspecting enemies. A bigger down side than you might expect is attracting the attention of advanced bots who target all. Another is having your safer corner position taken while swooping in field. Your gangBang turns into a drive-by with no safe place to go :) —Preceding unsigned comment added by Jlm0924 (talk • contribs)
- Ahhh, that technique. In Glacier's danger formula what I do to account for that is factor in the ratio of "closest distance of anything to the enemy, versus, my distance to the enemy" (which is a value from some-small-number up to 1.0). Your approach of reducing that danger to zero is much more aggressive through. Hmm, perhaps I should try something like squaring or cubing that ratio... since that would make it more aggressive while still not reducing danger all the way to zero. Interesting... --Rednaxela 19:40, 8 May 2010 (UTC)
- yep same sort of thing... yea try sqr or cube.. let me know what happens :)-Jlm0924 21:39, 8 May 2010 (UTC)
DR3.14 - DR3.15
I've replaced non-segmented surfing stats with DC-type surfing with mixed results (as always) ... later I'll merge with 2.12a: It may be improving 1vrs1 but hurting melee... -Jlm0924 19:54, 7 May 2010 (UTC)
- That would suggest to me that your DC-type surfing is having problems when the number of data points is too low. That's kind of interesting, because performing well with both high and low numbers of data points is generally a strength of DC-type method. This would suggest to me that either the number of returned data points is too small, or something about the processing after the nearest-neighbor search has issues. Perhaps you are weighting the data based on how close it matches, and that weighting is too harsh? Or perhaps the non-DC type had some kind of smoothing across bins, which is no longer the case? I found back when I was working on RougeDC, that how much one does the equivalent of bin smoothing, has a huge impact in DC-type surfing. --Rednaxela 22:49, 7 May 2010 (UTC)
- as always your on the money... :) It has seperate 1v1 list and seperate melee list (both for DC/NOnSEG) . In melee it can be selective on adding points. When it gets to end game (1vrs1 DC stats) returns about 10-20 data points (in round 15) for Diamond when he is in the ring. Very low.. I going to release v3.15... which for now uses Non-seg until 25 or greater returned data points. There are advantages to non-seg so I can't swicth over sooner.. You made a great point... As I do smoothen out the DC-Wave after creating it; I never thought about playing with the smoothing.. I'll try that , Thx -Jlm0924 00:14, 8 May 2010 (UTC)
- Well, part of my point was that there shouldn't be advantages to non-seg if the DC is set up ideally. If the number of points returned by the DC is at least 25, they're smoothed in the same way the non-seg is, and there is little weighting between them, the result should be *exactly* the same as the non-seg in fact. --Rednaxela 19:40, 8 May 2010 (UTC)
- I hear you.. With my non seq, I account for bullet misses, which decay, and smoothen Stats over time..This naturally weights the waves (showing who more often or more recently hit DR) This isn't inhierent but could be added to DC with weighting. I haven't tried yet. Till then It seems my non-Seg is working better for the first bit , As I rushed to post DR3.15 before taking off last night.. I accidently had DR3.15 surfing DC first; Then switching over to Non-seg. doh! (performance went down instead of up). I have to play with wieghting/decay/smoothing and balance the wave with risk functions that are always present -Jlm0924 00:59, 9 May 2010 (UTC)
- Hmm, there's a lot to consider. First, since 1v1 is such a small part of Melee, it's tough to test surfing changes' effectiveness. Does your surfing use data from Melee in 1v1? I would add some type of attribute to give some strong preference to 1v1 data, like "number of bots alive" (I do this in Diamond's gun). Trying to learn from misses also seems really dangerous. I would test vs HOT bots like HawkOnFire with and without that and see if it's screwing you up.
- It seems very likely to me that there's something different about your smoothing in non-seg vs DC. Are you using VCS in your non-seg? I think Gaussian kernel density is really useful - a lot of DC kernel density stuff will just give a 0 density for anything outside of a bot width, while Gaussian will scale down and never hit zero. So being further away from a dangerous angle is better than being just beyond a bot width of it. Check
Diamond::voidious.move.DiamondWhoosh.getDangerScore
if you want to take a peak. =) Here's a nice list of kernel density estimators for comparison. - Btw, if you want to make each version a sub-heading, you can do it with 3 ='s, like: === DR3.14 - UnReleased ===. Keep up the good work on DR while I chase DrussGT. =)
- --Voidious 21:58, 8 May 2010 (UTC)
- Thx; Yes, Currently the smoothing is different and missed bullets decay the non-Seg stats. -Jlm0924 00:59, 9 May 2010 (UTC)
DR3.16 - current
Source Code
- I left it as is, with code commented out in case someOne wants to play with it..
- Again I have updated the Radar code to be more Inclusive and Robust -Jlm0924 19:19, 30 April 2010 (UTC)
package justin.radar; import justin.Module; import justin.Radar; import justin.Enemy; import robocode.DeathEvent; import robocode.Event; import robocode.HitRobotEvent; import robocode.ScannedRobotEvent; import robocode.RobotDeathEvent; import robocode.WinEvent; import robocode.util.Utils; import java.util.Hashtable; import java.util.Iterator; /** * - An Efficient and Robust RADAR system that I use with Module by jab. * * @author Justin Mallais * */ public class DynamicLocking extends Radar { public DynamicLocking(Module bot) { super(bot); } static final double PI = Math.PI; static double radarDirection = 1; public Enemy lookingFor = new Enemy(); // Note: !! new Enemy must contain a null name !!! // List of enemy names that empties every new round (the boolean is not used) private Hashtable<String, Boolean> knownEnemiesList = new Hashtable<String, Boolean>(); public boolean knownEnemiesListFull = false; public void scan(){ // Only executed once at beginning of new round. if(bot.getRadarTurnRemaining()==0 ){ // initial radar direction is towards the center of Battle field. radarDirection =(Utils.normalRelativeAngle(absbearing(bot.getX(),bot.getY(),bot.getBattleFieldWidth()/2,bot.getBattleFieldHeight()/2) - bot.getRadarHeadingRadians()) > 0 ? 1 : -1); double radarTurn = Double.POSITIVE_INFINITY * radarDirection; bot.setTurnRadarRightRadians(radarTurn);// the scan } } public void listen(Event e){ // These aren't necessary but HitRobot event could help if (e instanceof WinEvent) cleanUpRound(); if (e instanceof DeathEvent) cleanUpRound(); if (e instanceof HitRobotEvent) lookingFor = Module.enemies.get(((HitRobotEvent) e).getName()); // If who we are lookingFor has died if (e instanceof RobotDeathEvent && (( RobotDeathEvent)e).getName()== lookingFor.name){ lookingFor = new Enemy() ; // Note: !! new Enemy must contain a null name !!! } // RADAR SCANNED ROBOT EVENT if (e instanceof ScannedRobotEvent){ // Check we've found all the enemies if(! knownEnemiesListFull){ // Insure Enemy is marked alive; Module.enemies.get(((ScannedRobotEvent) e).getName()).alive = true; knownEnemiesList.put(((ScannedRobotEvent) e).getName(), true); knownEnemiesListFull = (knownEnemiesList.size() >= bot.getOthers())? true : false; //bot.out.println(" found "+knownEnemiesList.size()+" bots, and found all is "+knownEnemiesListFull); if( !knownEnemiesListFull ) return; } // We've found all the robots, now we can choose who to lookFor next if(lookingFor.name == null) lookingFor = Module.enemies.get( ((ScannedRobotEvent)e).getName() ); if( ((ScannedRobotEvent)e).getName() == lookingFor.name) { Iterator<Enemy> iterator= Module.enemies.values().iterator(); double bestScore=Double.POSITIVE_INFINITY; while (iterator.hasNext()){ Enemy tank= iterator.next(); if(tank.alive){ double time = tank.scanTime; double sweepSize = (Math.abs(Utils.normalRelativeAngle(tank.absBearingRadians - bot.getRadarHeadingRadians())) /PI); //1 needs the scan // NOTE: The commented out options below are for reference. (may be broken) // prioritise based on distance /* int distance = (int)Math.round((Math.min(1000,tank.distance)/1000*3)); // 1 needs the scan distance = ( distance ==3 && bot.getOthers()>4 ) ? 10 : 0; // farthest bots not a concern int priority = 0; if( (tank.name==bot.enemy.name || tank.name == bot.myClosestBot.name || bot.myLocation.distance(tank.location)<tank.cbD || bot.getOthers()<4)){ priority = -5; } */ double score = time - sweepSize;// + distance + priority; // scan target before he fires /* double ang = lookingFor.absBearing + (lookingFor.deltaAbsBearing); double turnsB4ScanBot = Utils.normalRelativeAngle(Math.abs( (bot.getRadarHeadingRadians()-ang) ))/.785; double sS = bot.getTime()-lookingFor.timeScanned; if(enemy.name == lookingFor.name && (bot.getGunHeat()/bot.getGunCoolingRate())-turnsB4ScanBot < 2 && sS > 1)score=score-25; */ // scan Target before we fire at him /* if (tank.name==bot.enemy.name && ticksUntilGunCool() < bot.enemy.timeSinceLastScan +2 ) { score = score - 10; // score is based on time } */ if(score < bestScore){ bestScore = score; lookingFor = tank; } } } // New scan double angle = lookingFor.absBearingRadians-(lookingFor.deltaAbsBearingRadians*2); // + lookingFor.deltaBearing;// should be much more accurate to use below radarDirection =(int) Math.signum(Utils.normalRelativeAngle(angle - bot.getRadarHeadingRadians())); double turnsTillScanBot = Utils.normalRelativeAngle(Math.abs( (bot.getRadarHeadingRadians()-angle) ))/.7; double radarTurn = Double.POSITIVE_INFINITY * radarDirection; // When to enable Radar Lock if(lookingFor.deltaScanTime < 1.1 && turnsTillScanBot < 1){ // A small Offset is needed. //A few different types are here for bling bling :) double offset =0; // = radarsMaxEscapeAngle(lookingFor.distance,sinceScanned) * radarDirection; // a small offset based on escape angle offset = offset + ( Math.abs(lookingFor.deltaAbsBearingRadians * 3 ) ); // greater offset for lateral speed offset = offset + (20* (lookingFor.deltaScanTime)) / (lookingFor.distance); // greater offset for smaller distance offset = offset * radarDirection; radarTurn =(Utils.normalRelativeAngle(angle - bot.getRadarHeadingRadians()+offset)); } bot.setTurnRadarRightRadians(radarTurn);// set scan } } } // Fail Safe public void cleanUpRound() { knownEnemiesList = null; // fail safe knownEnemiesListFull = false; // fail safe Iterator<Enemy> iterator= Module.enemies.values().iterator(); while (iterator.hasNext()){ Enemy him= iterator.next(); if(him.alive){ // clean Ups' } else him.alive = true; // fail safe } } /* // PAINT LookingFor public void onPaint(Graphics2D g){ if(lookingFor!=null&&lookingFor.location !=null){ g.setColor(new Color(0, 0, 255, 70)); g.fillRect((int)lookingFor.location.x-25,(int)lookingFor.location.y-25,50,50); } } */ // Utils //gets the absolute bearing between to x,y coordinates (not sure of Author) public double absbearing( double x1,double y1, double x2,double y2 ){ double xo = x2-x1; double yo = y2-y1; double h = getRange( x1,y1, x2,y2 ); if( xo > 0 && yo > 0 ){ return Math.asin( xo / h ); } if( xo > 0 && yo < 0 ){ return Math.PI - Math.asin( xo / h );} if( xo < 0 && yo < 0 ){ return Math.PI + Math.asin( -xo / h );} if( xo < 0 && yo > 0 ){ return 2.0*Math.PI - Math.asin( -xo / h );} return 0; } public double getRange( double x1,double y1, double x2,double y2 ){ double xo = x2-x1; double yo = y2-y1; double h = Math.sqrt( xo*xo + yo*yo ); return h; } /* protected long ticksUntilGunCool() { return Math.round(Math.ceil(bot.getGunHeat() / bot.getGunCoolingRate())); } public static double radarsMaxEscapeAngle(double distance, double sinceScanned) { return Math.asin( 8/ (distance-(8*sinceScanned))) * sinceScanned ;// } */ }
- Note: HistoryLog is a linked list; Enemy is normal scan Data.
- I also cleaned up PIF with comments -Jlm0924 19:16, 28 April 2010 (UTC)
//Play It Forward // author : Justin Mallais public Angle getGunAngle(HistoryLog similar, Enemy e ,double bulletSpeed, long time, double weight){// GunData predictedInfo, Enemy e) { //bot.out.println(" predLocation test "); final HistoryLog similarInfo = similar; final HistoryLog currInfo = e.last; HistoryLog endInfo = similarInfo; double bulletTime; long timeDelta = (time - currInfo.scanTime); double predDist = 0, predAng; // My 'current' position transposed on to the 'similar' battlefield Point2D.Double myRelativePosition = project(similarInfo.location, Utils.normalRelativeAngle(currInfo.absBearingRadians + PI-currInfo.headingRadians+similarInfo.headingRadians), currInfo.distance); while (endInfo.next != null && endInfo.round == similarInfo.round && endInfo.scanTime >= similarInfo.scanTime ) { endInfo = endInfo.next; bulletTime = (myRelativePosition.distance(endInfo.location) / bulletSpeed) +1; if (Math.abs(endInfo.scanTime - similarInfo.scanTime - timeDelta - bulletTime) <= 1) break; } if ( endInfo.next == null || endInfo.round != similarInfo.round )return null; // Enemies offset angle travelled predAng = Utils.normalRelativeAngle(DRUtils.absoluteBearing(similarInfo.location, endInfo.location) - similarInfo.headingRadians ); // Enemies distance travelled predDist = similarInfo.location.distance(endInfo.location); // Enemies future location on 'Current' battleField Point2D.Double predLocation = project(currInfo.location,Utils.normalRelativeAngle(predAng+currInfo.headingRadians),predDist); if(!Module.bf.contains(predLocation)) return null; // My absolute angle to his future position predAng = DRUtils.absoluteBearing(bot.myData.location, predLocation); // My absolute angle to his future position predDist = bot.myData.location.distance( predLocation); // returns Angle : ("predicted angle", "tolerance", and weight)) Angle angle = new Angle( predAng, Math.atan(18 / predDist), 0, weight ); return angle; }