Difference between revisions of "User talk:Awesomeness"
Awesomeness (talk | contribs) (Anti-Gravity) |
Awesomeness (talk | contribs) (UGH) |
||
Line 84: | Line 84: | ||
:Thanks! This fits exactly what I was planning to do! [[User:Awesomeness|Awesomeness]] 16:44, 2 May 2009 (UTC) | :Thanks! This fits exactly what I was planning to do! [[User:Awesomeness|Awesomeness]] 16:44, 2 May 2009 (UTC) | ||
:However anti-gravity confuses me greatly... [[User:Awesomeness|Awesomeness]] 17:11, 2 May 2009 (UTC) | :However anti-gravity confuses me greatly... [[User:Awesomeness|Awesomeness]] 17:11, 2 May 2009 (UTC) | ||
+ | |||
+ | |||
+ | UGH! I worked so hard on this and look what it does! Enable the debug graphics to where it thinks the bullets are... Theres no point in working on antigrav movement until I fix this. | ||
+ | Program: | ||
+ | <pre>package awesomeness; | ||
+ | import robocode.*; | ||
+ | import robocode.util.*; | ||
+ | import java.util.Random; | ||
+ | import java.util.ArrayList; | ||
+ | import java.awt.*; | ||
+ | |||
+ | /** | ||
+ | * PwnBot - a robot by (your name here) | ||
+ | */ | ||
+ | public class PwnBot extends AdvancedRobot { | ||
+ | |||
+ | static StringBuffer pattern = new StringBuffer("" + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)-8 + (char)-7 + (char)-6 + (char)-5 + (char)-4 + (char)-3 + (char)-2 + (char)-1 + (char)1 + (char)2 + (char)3 + (char)4 + (char)5 + (char)6 + (char)7 + (char)8); | ||
+ | |||
+ | static double previousEnergy = 100d; | ||
+ | static double changeInEnergy; | ||
+ | //static double totalBulletDist; | ||
+ | //double[] bulletDists; | ||
+ | |||
+ | |||
+ | static int movementDirection = 50; | ||
+ | static long lastTime; //The last time known, used to track bullets | ||
+ | |||
+ | static Random generator = new Random(); //This makes random numbers | ||
+ | ArrayList<VirtualBullet> bullets = new ArrayList<VirtualBullet>(); | ||
+ | static VirtualBullet newBullet, bullet; | ||
+ | |||
+ | public void run() { | ||
+ | lastTime = 0; | ||
+ | setAdjustGunForRobotTurn(true); | ||
+ | turnRadarRightRadians(Double.POSITIVE_INFINITY); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * onScannedRobot: What to do when you see another robot | ||
+ | */ | ||
+ | public void onScannedRobot(ScannedRobotEvent e) { | ||
+ | |||
+ | //The absolute bearing, this is used a lot | ||
+ | double absoluteBearing = e.getBearingRadians(); | ||
+ | |||
+ | /////////////////////////////////////////////////////// | ||
+ | ////////////////////Movement Code////////////////////// | ||
+ | |||
+ | /////////////////////Bullet Code/////////////////////// | ||
+ | |||
+ | //If there's a change in energy, it probably fired | ||
+ | |||
+ | if ((changeInEnergy = previousEnergy - (previousEnergy = e.getEnergy())) > 0d && changeInEnergy<=3) { | ||
+ | |||
+ | newBullet = new VirtualBullet(getX() + Math.sin(absoluteBearing) * e.getDistance(), getY() + Math.cos(absoluteBearing) * e.getDistance(), 20 - 3 * changeInEnergy, Utils.normalRelativeAngle(absoluteBearing + Math.PI + Math.asin((Math.sin(e.getBearingRadians()) * getVelocity())/(20 - 3 * changeInEnergy)))); | ||
+ | bullets.add(newBullet); | ||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | for (int i = 0; i < bullets.size(); i++) { | ||
+ | bullet = bullets.get(i); | ||
+ | bullet.tick(getTime() - lastTime); | ||
+ | bullets.set(i, bullet); | ||
+ | |||
+ | if (bullets.get(i).checkHitWall()) { | ||
+ | // I think this will work | ||
+ | // bullets.remove(i--); | ||
+ | // but usually I do | ||
+ | bullets.remove(i); | ||
+ | i--; | ||
+ | } | ||
+ | |||
+ | //bulletDists[i] = bullets.get(i).getDistance(getX(), getY()); | ||
+ | //totalBulletDist += bullets.get(i).getDistance(getX(), getY()); | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////End Bullet Code///////////////////// | ||
+ | |||
+ | |||
+ | //Stay at almost right angles | ||
+ | setTurnRightRadians(Math.cos(absoluteBearing+(-0.003*movementDirection))); | ||
+ | |||
+ | setAhead(movementDirection); | ||
+ | |||
+ | |||
+ | |||
+ | ////////////////////Movement Code////////////////////// | ||
+ | /////////////////////////////////////////////////////// | ||
+ | |||
+ | /////////////////////////////////////////////////////// | ||
+ | ///////////////////////Gun Code//////////////////////// | ||
+ | |||
+ | double absbearing; | ||
+ | absbearing = (e.getBearingRadians()-Math.PI/2)+1.57079633; | ||
+ | //rounding to be more accurate in projection! | ||
+ | pattern.insert(0, (char)(Math.round(Math.sin(e.getHeadingRadians() - (absbearing = absbearing + getHeadingRadians()))*e.getVelocity()))); | ||
+ | |||
+ | int index=0, searchlength = 30; | ||
+ | //lol, if I ever make a haiku pattern-matcher, this will be in it: | ||
+ | while ((index = pattern.toString().indexOf(pattern.substring(0, searchlength--), 1)) < 0); | ||
+ | |||
+ | //searchlength will now become the index of the StringBuffer that I will project back to (back because my pattern | ||
+ | //is stored backward). | ||
+ | double power; | ||
+ | double dist; | ||
+ | searchlength = index - (int)((dist = e.getDistance())/(20-(power = Math.min(3, Math.min(getEnergy(), e.getEnergy())/4))*3)); | ||
+ | |||
+ | //just add the offset to the bearing instead of making a new variable! | ||
+ | //The fact that this actually reconstructs future movement (like a normal pattern-matcher does) probably makes this | ||
+ | //just about the most accurate current nano pattern-matcher (except possibly Kakuru's, since it uses doubles instead of | ||
+ | //characters). The nice thing about it is that it correctly projects patterns even if I'm at a different distance than | ||
+ | //when I collected the pattern. | ||
+ | do | ||
+ | { | ||
+ | absbearing += Math.asin(((byte)pattern.charAt(index--))/dist); | ||
+ | } | ||
+ | while (index >= Math.max(0, searchlength)); | ||
+ | |||
+ | setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absbearing - getGunHeadingRadians())); | ||
+ | setFire(power); | ||
+ | |||
+ | |||
+ | ///////////////////////Gun Code//////////////////////// | ||
+ | /////////////////////////////////////////////////////// | ||
+ | |||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////// | ||
+ | /////////////////////Radar Code//////////////////////// | ||
+ | |||
+ | |||
+ | setTurnRadarLeftRadians(getRadarTurnRemainingRadians()); | ||
+ | |||
+ | |||
+ | /////////////////////Radar Code//////////////////////// | ||
+ | /////////////////////////////////////////////////////// | ||
+ | |||
+ | |||
+ | lastTime = getTime(); | ||
+ | |||
+ | } | ||
+ | |||
+ | public void onHitWall(HitWallEvent e) { | ||
+ | i(); | ||
+ | } | ||
+ | |||
+ | public void i() { | ||
+ | movementDirection = -movementDirection; | ||
+ | } | ||
+ | |||
+ | // Paint a transparent square on top of the last scanned robot | ||
+ | public void onPaint(Graphics2D g) { | ||
+ | // Set the paint color to a red half transparent color | ||
+ | g.setColor(new Color(0xff, 0x00, 0x00, 0x80)); | ||
+ | |||
+ | for (int i = 0; i < bullets.size(); i++) { | ||
+ | bullet = bullets.get(i); | ||
+ | |||
+ | // Draw a filled square on top of the scanned robot that covers it | ||
+ | g.fillRect( (int) bullet.getX() - 5, (int) bullet.getY() - 5, 10, 10); | ||
+ | |||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | public class VirtualBullet { //A class to simulate bullets. | ||
+ | |||
+ | double x, y, speed, angle; | ||
+ | |||
+ | |||
+ | VirtualBullet(double startX, double startY, double velocity, double trajectory) { | ||
+ | x = startX; | ||
+ | y = startY; | ||
+ | speed = velocity; | ||
+ | angle = trajectory; | ||
+ | } | ||
+ | |||
+ | public void tick(long ticks) { //Moves the bullet the amount it would | ||
+ | while(ticks > 0) { | ||
+ | x += Math.cos(angle)*speed; | ||
+ | y += Math.sin(angle)*speed; | ||
+ | ticks --; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public double getX() { | ||
+ | return x; | ||
+ | } | ||
+ | |||
+ | public double getY() { | ||
+ | return y; | ||
+ | } | ||
+ | |||
+ | public double getDistance(double botX, double botY) { | ||
+ | return Math.sqrt(Math.pow(botX-x, 2)+Math.pow(botY-y, 2)); | ||
+ | } | ||
+ | |||
+ | |||
+ | public boolean checkHitWall() { | ||
+ | if (x < 0 || y < 0 || x > getBattleFieldWidth() || y > getBattleFieldHeight()) { | ||
+ | return true; | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | [[User:Awesomeness|Awesomeness]] 17:28, 2 May 2009 (UTC) |
Revision as of 18:28, 2 May 2009
- Archived talks:
- Archived Talk 20090502
Okay, I need to make a list of bullets. I have made a bullet class and everything, but I need a special list that will let me access all of the bullets in a while/for loop and be able to add and remove them at any time and never mess up. If I did this in a normal array I could do a for loop and access using an increasing number, but I wouldn't know when to stop. In a while loop, if I used while(bulletsArray[x] != null) and then increment x, after I remove my first bullet that say, hit a wall, it will stop there. I need help!
- Thanks,
- Awesomeness 14:02, 2 May 2009 (UTC)
I think this will do:
ArrayList<Bullet> bullets = new ArrayList<Bullet>(); for (int i = 0; i < bullets.size(); i++) { Bullet bullet = bullets.get(i); if (bullet.needRemove()) { // I think this will work // bullets.remove(i--); // but usually I do bullets.remove(bullet); i--; } }
Here I assume that you use ArrayList to store you bullets and your bullet's classname is Bullet. If you use a plain array to keep the bullets, consider change to ArrayList. It is more flexible. » Nat | Talk » 14:09, 2 May 2009 (UTC)
- Oh my gosh! You're right! ArrayList is way more flexible! I looked at the documentation; you don't even have to increment or decrement anything! The function remove() shifts the other elements to the left already! Thanks! Awesomeness 14:14, 2 May 2009 (UTC)
- Be sure don't use for-each style (
for(Bullet bullet : bullets)
or you will get ConcurentModificationException when you remove element (this is per java spec, but I still use the for-each style and didn't get this exception actually). And when you scroll through the array like one I mentioned, be sure you do i--, or you will just skip one element. » Nat | Talk » 14:19, 2 May 2009 (UTC)
- Be sure don't use for-each style (
- Oh, you're right. Awesomeness 14:27, 2 May 2009 (UTC)
- One suggestion. Don't use
bullets.remove(bullet);
, usebullets.remove(i);
instead because removing by index is far faster than removing by content. Well, with the size the list is in robocode it probably doesn't matter a ton, but removal of list by content, when you already have the index on hand, seems terribly wasteful to me. --Rednaxela 14:45, 2 May 2009 (UTC)
- I changed that myself already. =D lol Awesomeness 14:56, 2 May 2009 (UTC)
I've grown very fond of iterators for Lists, this would be my implementation:
ArrayList<Bullet> bullets = new ArrayList<Bullet>(); Iterator<Bullet> i = bullets.iterator(); while (i.hasNext()) { Bullet bullet = i.next(); if (bullet.needRemove()) { i.remove(); } }
--Skilgannon 15:00, 2 May 2009 (UTC)
- Ahhh... I never knew that iterator has remove method so I always using ArrayLisy.get(i) to prevent ConcurentModificationException. Thanks you very much. » Nat | Talk » 15:06, 2 May 2009 (UTC)
How do you find the x and y of a robot you've scanned? I see no ScannedRobotEvent.getX()
or getY()
method. Awesomeness 15:19, 2 May 2009 (UTC)
Trig Trig Trig...
double absBearing = e.getBearingRadians() + getHeadingRadians(); double x = getX() + Math.sin(absBearing) * e.getDistance(); double y = getY() + Math.cos(absBearing) * e.getDistance();
That's all. » Nat | Talk » 15:21, 2 May 2009 (UTC)
Here's a method I use in my utils class (I first saw it in a PEZ bot):
public static Point2D.Double project(Point2D.Double sourceLocation, double angle, double length) { return new Point2D.Double(sourceLocation.x + Math.sin(angle) * length, sourceLocation.y + Math.cos(angle) * length); } // You'd pass it something like: // myLocation = new Point2D.Double(getX(), getY()); // enemyLocation = MyUtils.project(myLocation, absBearing, e.getDistance());
--Voidious 16:15, 2 May 2009 (UTC)
Lastly, I need a way to "dodge" these simulated bullets and to figure out what angle the oppenent bot would be shooting from if it used linear targeting against me. I don't know how to do either of these. Awesomeness 16:31, 2 May 2009 (UTC)
To dodge, use Anti-Gravity Movement, to assume linear firing, use this code:
angle = Utils.normalRelativeAngle(absBearing + Math.PI + Math.asin((Math.sin(e.getBearingRadians()) * getVelocity())/(20 - 3 * BULLET_POWER)));
replace BULLET_POWER to which you get from energy drop. This prediction use non-iterative no-wall-stopping linear targeting. » Nat | Talk » 16:35, 2 May 2009 (UTC)
- Thanks! This fits exactly what I was planning to do! Awesomeness 16:44, 2 May 2009 (UTC)
- However anti-gravity confuses me greatly... Awesomeness 17:11, 2 May 2009 (UTC)
UGH! I worked so hard on this and look what it does! Enable the debug graphics to where it thinks the bullets are... Theres no point in working on antigrav movement until I fix this.
Program:
package awesomeness; import robocode.*; import robocode.util.*; import java.util.Random; import java.util.ArrayList; import java.awt.*; /** * PwnBot - a robot by (your name here) */ public class PwnBot extends AdvancedRobot { static StringBuffer pattern = new StringBuffer("" + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)0 + (char)-8 + (char)-7 + (char)-6 + (char)-5 + (char)-4 + (char)-3 + (char)-2 + (char)-1 + (char)1 + (char)2 + (char)3 + (char)4 + (char)5 + (char)6 + (char)7 + (char)8); static double previousEnergy = 100d; static double changeInEnergy; //static double totalBulletDist; //double[] bulletDists; static int movementDirection = 50; static long lastTime; //The last time known, used to track bullets static Random generator = new Random(); //This makes random numbers ArrayList<VirtualBullet> bullets = new ArrayList<VirtualBullet>(); static VirtualBullet newBullet, bullet; public void run() { lastTime = 0; setAdjustGunForRobotTurn(true); turnRadarRightRadians(Double.POSITIVE_INFINITY); } /** * onScannedRobot: What to do when you see another robot */ public void onScannedRobot(ScannedRobotEvent e) { //The absolute bearing, this is used a lot double absoluteBearing = e.getBearingRadians(); /////////////////////////////////////////////////////// ////////////////////Movement Code////////////////////// /////////////////////Bullet Code/////////////////////// //If there's a change in energy, it probably fired if ((changeInEnergy = previousEnergy - (previousEnergy = e.getEnergy())) > 0d && changeInEnergy<=3) { newBullet = new VirtualBullet(getX() + Math.sin(absoluteBearing) * e.getDistance(), getY() + Math.cos(absoluteBearing) * e.getDistance(), 20 - 3 * changeInEnergy, Utils.normalRelativeAngle(absoluteBearing + Math.PI + Math.asin((Math.sin(e.getBearingRadians()) * getVelocity())/(20 - 3 * changeInEnergy)))); bullets.add(newBullet); } for (int i = 0; i < bullets.size(); i++) { bullet = bullets.get(i); bullet.tick(getTime() - lastTime); bullets.set(i, bullet); if (bullets.get(i).checkHitWall()) { // I think this will work // bullets.remove(i--); // but usually I do bullets.remove(i); i--; } //bulletDists[i] = bullets.get(i).getDistance(getX(), getY()); //totalBulletDist += bullets.get(i).getDistance(getX(), getY()); } ///////////////////End Bullet Code///////////////////// //Stay at almost right angles setTurnRightRadians(Math.cos(absoluteBearing+(-0.003*movementDirection))); setAhead(movementDirection); ////////////////////Movement Code////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// ///////////////////////Gun Code//////////////////////// double absbearing; absbearing = (e.getBearingRadians()-Math.PI/2)+1.57079633; //rounding to be more accurate in projection! pattern.insert(0, (char)(Math.round(Math.sin(e.getHeadingRadians() - (absbearing = absbearing + getHeadingRadians()))*e.getVelocity()))); int index=0, searchlength = 30; //lol, if I ever make a haiku pattern-matcher, this will be in it: while ((index = pattern.toString().indexOf(pattern.substring(0, searchlength--), 1)) < 0); //searchlength will now become the index of the StringBuffer that I will project back to (back because my pattern //is stored backward). double power; double dist; searchlength = index - (int)((dist = e.getDistance())/(20-(power = Math.min(3, Math.min(getEnergy(), e.getEnergy())/4))*3)); //just add the offset to the bearing instead of making a new variable! //The fact that this actually reconstructs future movement (like a normal pattern-matcher does) probably makes this //just about the most accurate current nano pattern-matcher (except possibly Kakuru's, since it uses doubles instead of //characters). The nice thing about it is that it correctly projects patterns even if I'm at a different distance than //when I collected the pattern. do { absbearing += Math.asin(((byte)pattern.charAt(index--))/dist); } while (index >= Math.max(0, searchlength)); setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absbearing - getGunHeadingRadians())); setFire(power); ///////////////////////Gun Code//////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////Radar Code//////////////////////// setTurnRadarLeftRadians(getRadarTurnRemainingRadians()); /////////////////////Radar Code//////////////////////// /////////////////////////////////////////////////////// lastTime = getTime(); } public void onHitWall(HitWallEvent e) { i(); } public void i() { movementDirection = -movementDirection; } // Paint a transparent square on top of the last scanned robot public void onPaint(Graphics2D g) { // Set the paint color to a red half transparent color g.setColor(new Color(0xff, 0x00, 0x00, 0x80)); for (int i = 0; i < bullets.size(); i++) { bullet = bullets.get(i); // Draw a filled square on top of the scanned robot that covers it g.fillRect( (int) bullet.getX() - 5, (int) bullet.getY() - 5, 10, 10); } } public class VirtualBullet { //A class to simulate bullets. double x, y, speed, angle; VirtualBullet(double startX, double startY, double velocity, double trajectory) { x = startX; y = startY; speed = velocity; angle = trajectory; } public void tick(long ticks) { //Moves the bullet the amount it would while(ticks > 0) { x += Math.cos(angle)*speed; y += Math.sin(angle)*speed; ticks --; } } public double getX() { return x; } public double getY() { return y; } public double getDistance(double botX, double botY) { return Math.sqrt(Math.pow(botX-x, 2)+Math.pow(botY-y, 2)); } public boolean checkHitWall() { if (x < 0 || y < 0 || x > getBattleFieldWidth() || y > getBattleFieldHeight()) { return true; } return false; } } }
Awesomeness 17:28, 2 May 2009 (UTC)