double deltaBearing(double distance) { return Math.atan2(distance, shootingDistance()); }It's supposed to help me figure out the gunners deltabearing for an object traveling "distance" length in a right angle from a point at the shootingDistance(). I use it for several things, one is to extend the blind-mans-stick from my robot to smooth walls. But sometimes my robot behaves funny. It seems it is on closer ranges. Then it rams its opponent. I suspect the function above. Anyone have a clue?
-- PEZ
Check your shootingDistance function maybe? This part looks ok to me. --David Alves
Thanks! That was the problem. shootingDistance() was just that. I want to use the current enemy distance of course. Removed both those function from my Wave class and now things work much better. -- PEZ
sorry PEZ, not here to help (as if i could). question of my own:
how do you get the onBulletHit? event to coincide with an enemy wave hitting? right now, when an enemy wave is 20-3*ewave.bulletPower away from me, i make it the passingWave. then when a bullethitevent shows up, i use passingWave to calculate the guess factor of the hit bullet. But i seem to be having some errors with this method. Any suggestions? --andrew
Are you setting the centre of the wave as the enemies position the tick before you detected the EnergyDrop, and the time of firing 2 ticks before when you detected it? -- Tango
Use RobocodeGLV014 to line them up properly. You'll need to offset the wave to account for the fact that 1) you didn't detect the energy drop until 1 turn after the enemy fired and 2) the enemy's bullet started moving the turn before that. --David Alves
Andrew, i strongly suggest you to start graphing your waves with RoboCodeGL?. I was a newbie with GL stuff till i start developing my WaveSurfing, and now looking back, i see that it would be at least 3 times harder to do and debug all without the graphing aid. The instalation and configuration is a little confuse, but i can assure you that it will pay back your efforts. -- Axe
robocode gl sounds so imensly complicated to install though.--andrew
Yeah I agree. I only started with RCGL some few days ago when I tired of not "seeing" what was going on in my code. I got RCGL running in a jiffy and it only took me some hour or so to start graphing my waves.
I suggest you don't use the event mechanism for EnemyWaves. Even though potentially more precise the whole business of keeping track on execution order gets tricky. It has bitten me lots of times. Instead put the EnemyWaves in a List and iterate over that list to advance them and check status. And when you get hit iterate over the list and find a wave that has passing over you by checking if it is withing -18 to +18 from the distance your bot from the gunning location. Also check that the fire power matches the e.getPower() value. But don't use == for this beacause some rounding issues or whatever makes that fail. Instead check if the bullet power of the wave and the bullet that hit you are within a margin of, say +/- 0.1.
PS. Nano made the install of RCGL 'much simpler. Check it out on the RobocodeGLV014 page.
-- PEZ
I just added EnemyWaves to my dev bot (took about 10 mins), and they lined up perfectly. I like my strategy of just letting everyone else work out how to do it, and then copying. Makes life much easier! Tomorrow I will actually do something with the waves, they currently feed into a dummy array, and I'm not even using onBulletHit? (I know they line up because of the GL, and I'm assuming they will still line up when I collect the events). -- Tango
just to clarify, when i detect that the enemies energy level drops w/in range of bullet, and i create an enemy wave for that ; should i put the starting distance at 2*20-3*deltaenergy? i used to put it at 0.--[andrew
Correct. And thats 2*bulletspeed from the centre of the enemy *last* tick. -- Tango
This should be one of the things you can read about on the EnemyWave page. Maybe that page needs a summary... -- PEZ
Yes, that's what you should do. Never worked for me, though... -- Jamougha
Well, and you probably don't have the waves lined up all that precisely either. But you do use the last ticks enemy location and that's what is important if you just use strategy for determining which bullet hit you that doesn't assume perfectly lined up waves. -- PEZ
When you edit a page, there's a box at the bottom that says Summary. Just enter the description in there. --David Alves
double goalDirection =enemyAbsoluteBearing-(Math.PI/2+(e.getDistance()>=600?-0:0.4 ))*direction; while (!fieldRectangle.contains(getX()+Math.sin(goalDirection)*120,getY()+Math.cos(goalDirection)*120)){ goalDirection += direction*.1; } goalDirection = robocode.util.Utils.normalRelativeAngle(goalDirection-getHeadingRadians()); setAhead(100*direction); setTurnRightRadians(Math.tan(goalDirection));
--andrew
Does fieldRectangle include a buffer? If not, it will need one. The other problem I can think of is how much time you are giving for the bot to turn, they don't have much of a turning circle. -- Tango
fieldRecangle is this:
static final RoundRectangle2D fieldRectangle= new RoundRectangle2D.Double(19.0,19.0,762.0,562.0,114.59,114.59);
what exactly do you mean by too much time to turn? i think somthing is wrong in the actual code, because i used to have somthing else with the same numbers, and that worked.
--andrew
That buffer should work, but you should really use the getBattleFieldHeight?() and getBattleFieldWidth?() methods, so it works on any battlefield. What I meant about turning is this: Imagine the bot is heading straight at a wall, at full speed. You code will tell it to turn to avoid crashing, and as it works sometimes, I would guess the code does that correctly, however if the bot is too close to the wall when the code tells it to start turning, it may not have turned enough to avoid the collision. The turning rate is something like 0.75*velocity degrees a tick, IIRC. -- Tango
the reason i have it as a final is because this is for a nano bot (Acero). i understand what you're saying now. should i change it to predict farther than 120 ahead to fix it? my old wall smoothing used the same numbers and didn't have this problem. any suggestions? --andrew
Having it as final shouldn't make any difference, as the battlefield doesn't change during a battle. Make it predict further might help, I don't know. The only way to tell is to try it. Good luck! -- Tango
Are you using this code in your onScannedRobot method? And if so, are you constantly scanning? If not, you might not be starting the wall-smoothing early enough (remember that you can move forward 64 pixels between scans quite easily, and then you're turning too late). -- Kawigi
that's not the problem. i'm pretty sure it has somthing to do w/ i'm doing setahead(-100) sometimes instead of setback
my working code was like this:
/*if (Math.abs(turn) > Math.PI/2){// turn = robocode.util.Utils.normalRelativeAngle(turn + Math.PI);// setTurnRightRadians(turn);// setBack(100);// } else{// setTurnRightRadians(turn);// setAhead(100);// } */
The problem could be that the turn in `Math.abs(turn) > Math.PI/2` isn`t normalized. Normalize it or use `Math.cos(turn) < 0` instead. -- rozu
that code is the working code. it works. i am trying to find a way to make this working code smaller in codesize for a nanobot. --andrew
Ah ok, my fault. You could try the Raiko version, if your code is called every tick and you don't need to turn so accurately:
setAhead(100 * Math.cos(turn)); setTurnRightRadians(Math.tan(turn));an exact version of your code would be:
int dir=1; if(Math.cos(turn) < 0){ turn += Math.PI; dir = -1; } setAhead(dir*100); setTurnRightRadians(robocode.util.Utils.normalRelativeAngle(turn));-- rozu
i'll try that. i got it down to : (and it works fine now)
while (!new Rectangle2D.Double(19.0,19.0,762.0,562.0).contains(getX()+Math.sin(goalDirection)*120,getY()+Math.cos(goalDirection)*120)){ goalDirection = goalDirection+direction*.1; } goalDirection = robocode.util.Utils.normalRelativeAngle(goalDirection-getHeadingRadians()); setTurnRightRadians(Math.tan(goalDirection)); setAhead(100*(Math.abs(goalDirection) > Math.PI/2 ?-1:1));if anyone knows how to make it smaller,please tell me. --andrew
how about this:
while (!new Rectangle2D.Double(19.0,19.0,762.0,562.0).contains(getX() + Math.sin(goalDirection += direction*.1)*120, getY() + Math.cos(goalDirection)*120)) setTurnRightRadians(Math.tan(goalDirection -= getHeadingRadians())); setAhead(100*(Math.cos(goalDirection) < 0 ? -1 : 1)); // or setAhead(100*Math.cos(goalDirection));
thanks,i'll try that out after i see how acero does in rumble
Hey PEZ I was wondering if you could give me some help ? If you have the time could you help me understand this bit of code ? maybe break it up into smaller bits ?? And if you could tell me what each bit is doing....... Hope you can help, I'm just geting into robocode, I've made a few bots but now I'm looking into better targeting "(Math.toDegrees( Math.asin(e.getVelocity() / 14 * Math.sin(e.getHeadingRadians() - enemyBearing) ) + enemyBearing ) - getGunHeading()) % 360)"-- PEZ
I am not that good at trigonometry but lets try:
e.getHeadingRadians() the direction the enemy is moving (0 is straight up) enemyBearing (probably) the angle at which the enemy is currently, seen from your point (0 is straight up) getGunHeading?() the direction your gun is pointing at the moment e.getVelocity() the current speed of the enemy 14 bulletspeed with bulletpower = 2.0 (replace it with (20 - 3 * bulletpower) )
A = (e.getHeadingRadians() - enemyBearing) the direction the enemy is moving with regard to your position Math.sin(A) the movement part perpendicular (at 90 degrees) to you B = e.getVelocity() / 14 * Math.sin(A) the relative speed of the enenemy perpendicular to you in respect to your bulletspeed (in this case 14) Math.asin(B) the relative angle the enemy will travel C = Math.asin(B) + enemyBearing the absolute angle the enemy will be when the bullet should hit
Math.toDegrees(C) - getGunHeading?() the angle your gun has to turn to hopefully intercept the enemy
I think the %360 can be replaced by enclosing the whole lot in a Utils.normalRelativeAngle( ... )
Hopefully the explanation above is good enough. Short said it is sort of a linear gun which expects the enemy to orbit your position while staying at a fixed distance. Hey, I can use this gun myself ! --GrubbmGait
Bloody great stuff man! You are a true robowiki community member. There's a lot of honour in that. To stay competetive minded and still sharing isn't for all. -- PEZ
Thanks --GrubbmGait your explanation really help.
Irish
Elsewhere on this site you can find examples on how to use the Radar. -- StefW
[Edit conflict]Most of your questions are answered on the GamePhysics page (re-arranged your question Wiki-style).
Thanks for the info!
I'd like to discuss the "implicit execute()" some more though. The AdvancedRobot API follows the normal pattern for an "event queue" design (normal for a live GUI), so I was very surprised the first time something ran without my calling execute(). It seems like a bug to me. It's hard to get upset about it if it's happening as a side effect of the event handlers though - running application logic in an event handler is always a bit sensitive to secondary effects. OTOH I think it would be a big problem if execute() is called for me when I use a state machine design (only set state variables in the event handlers, run all action commands in the mainline). Does anyone have any experience with bots using lightweight event handlers which also exhibit this "implicit execute()" behavior? -- ycn228
Are you sure you are not using any of the non setXXX calls that causes an execute? turnRadar, turnGun, ahead etc? I've had that happen to me by accident, they are so similar, Last time it was the radar I think :-). Yes I always just record stuff in the event handlers and execute any actions from the main run loop (delegating to different managers). It has the additional benefit of separating the logic from the data collection of course. I'll publish a small framework for it later on, something like the snippet bot tutorial shows but a lot separated and extensible. --Pulsar
Thanks Pulsar - that was the problem. The bot I originally used as a template does use a "non-set" call in its main action loop. It does:
turnRadarRightRadians?(Double.POSITIVE_INFINITY);then some setXXX calls are triggered from onScannedRobot(). I haven't had time to test this out yet, but I guess my new theory is that the "implied execute()" problem is an illusion :-) I'm really looking forward to your lightweight framework. I looked for something like that (perhaps in all the wrong places) but finished up with nanobot-style bots - very cleverly coded but not ideal as a learning platform. -- ycn228
If your running winXP, just open task Manager (ctrl+alt+del) and switch to the performance tab. Look at the "Physical Memory (K)" The difference in "Available" will be the ammount for memory your bot uses before and after being loaded. I fyour running Linux, open a terminal and run "top" --UnderDark
Thank you, but I will try that. But I was thinking more of a java functionality if there was any. -- Florent
You may be able to piece together the memory picture from methods in java.lang.Runtime. e.g. Runtime.getRuntime().freeMemory() -- Martin
Thanks I'll have a look at the javadoc for Runtime. -- Florent
+ Semantic Error: The type of this expression, "double", is not an integral typei tried to make an event so that it would turn around if it got within 10 of a wall. when i debugged it i got this error message for getX() and for (getBattleFieldWidth??()-10)
I suggest a common routine for this such as public static boolean inRange( double min, double val, double min ) { return (( min <= val ) && ( val <= max )); } which in your example you could call as inRange( 10.0, getX(), getBattleFieldWidth?() - 10.0 ) -- Martin
thanks
package js; import robocode.*; //import java.awt.Color;
/**
* Firstgood - a robot by (your name here) */public class Firstgood extends AdvancedRobot {
/** * run: Firstgood's default behavior */ public void run() { // After trying out your robot, try uncommenting the import at the top, // and the next line: //setColors(Color.red,Color.blue,Color.green); // Replace the next 4 lines with any behavior you would like int tracking = 0; setTurnRadarLeft(Double.POSITIVE_INFINITY); }
/** * onScannedRobot: What to do when you see another robot */ public void onScannedRobot(ScannedRobotEvent e) { turnGunRight?(getRadarHeading?()-getGunHeading?()); fire(1); setTurnRadarLeft(getRadarTurnRemaining?()); if(e.getBearing() < 180) { turnRight(e.getBearing()-90); } else { turnRight(e.getBearing()+90); } }
/** * onHitByBullet?: What to do when you're hit by a bullet */ public void onHitByBullet?(HitByBulletEvent? e) { turnLeft(90 - e.getBearing()); } public void onHitRobot?(HitRobotEvent? e) { turnRight(180); setAhead(100000); setTurnGunLeft?(100000); } public void onHitWall?(HitWallEvent? e) { turnRight(180); setAhead(Double.POSITIVE_INFINITY); setTurnGunLeft?(Double.POSITIVE_INFINITY); }
public boolean inRange( double min, double val, double max ) { return (( min <= val ) && ( val <= max )); }}
if you test it, after a while it stops scanning robots. is there any way to stop that?
I suspect it is a reault of calling 'setTurnRadarRight' instead of 'turnRadarRight?', since the latter is a blocking call and won't return control to the run() method until it is done (which shouldn't happen). If run() exits, your robot is done. I suggest sticking with all non-blocking calls, and calling execute() to commit all of them at once. I don't feel like getting into the argument of where to place your code right now, so I'll leave that to the philosophers. -- Martin
i accidentally removed the code to make it go forward while i was testing to see what was wrong. in this form it wont stop scanning them. when it hits into the walls several times though in its normal form, it stops. would that explain anything?
It generally is a bad idea to use blocking calls (turnxxx, ahead etc) in an AdvancedRobot mixed with non-blocking calls (setxxx). All events have a certain priority. A hitwall-event has a high priority, meaning that if you stay in that event (by calling a turnRight) all other events are not handled until the commands are completed. Put in some 'out.println("I am here and do this");' stuff and watch the output of the console. The console can be opened during or after a battle by clicking on the name of the bot in the upper right corner. An other remark: it is better that your run-routine contains a loop, it will end automatically when your robot wins or dies. -- GrubbmGait
my radar continues turning and so does the body but the gun will not turn towards a scanned robot
about the wall avoidance event, should it be inside "run" or outside?
Most people put almost all the logic in the onScannedRobot. However, it is possible to just collect data in the onScannedRobot event and do all the robot movement and firing in the run loop. I would say to put the wall avoidance event with the movement, so if you move in the run loop, put it there. -- Kinsen
This has been bothering me for abit now, does anyone know how i might refer to a derived class from an abtract super class like so
abtract class A { public abstract B get(); }
class B { public B get() { return this; } }
thanks -- Gorded
You dont. Especially as there is no need to, you can just return an object of type A and cast it back to type B, if you need it. -- Ebo
Doing it that way would bring up all whole bunch of unchecked casts warning, isn't there any way of doing this with generics -- Gorded
Ah ha it took little bit of hair becuase of the container class this is used in but its sloved with
abstract classA<Type extend A> { public abstract Type get(); }
class B extends A<B> { public B get() { return this; } }
all in a days works -- Gorded
I was hoping one of you clever guys could help me with getting a random number. I was hoping to get a random number between 0 and PI, that is expodentially more likely to be zero than PI. I believe I could use the formula : Math.pow(random()* math.squareRoot(PI),2)); //
My dilemna is being able to change the square root to match the exponent ..eg: if the 2 was changed to 1.4 -Justin thx guys
You could do it with the formula Math.pow(random() * Math.pow(PI, 1 / n), n)) where n is the exponent you want to use. Raising a number to the 1/n power is the same as taking the nth root of that number. -- Kev
Thx Kev :) that's exactley what I was looking for!! Thanks Kev - Justin