Difference between revisions of "User talk:Awesomeness"

From Robowiki
Jump to navigation Jump to search
(UGH)
m (Help... ='()
Line 86: Line 86:
  
  
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.
+
UGH!  I worked so hard on this and look what it does!  Enable the debug graphics to see where it thinks the bullets are...  Theres no point in working on antigrav movement until I fix this.
 
Program:
 
Program:
 
<pre>package awesomeness;
 
<pre>package awesomeness;
Line 298: Line 298:
 
</pre>
 
</pre>
  
[[User:Awesomeness|Awesomeness]] 17:28, 2 May 2009 (UTC)
+
=( [[User:Awesomeness|Awesomeness]] 17:28, 2 May 2009 (UTC)

Revision as of 20:05, 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)
Oh, you're right. Awesomeness 14:27, 2 May 2009 (UTC)
One suggestion. Don't use bullets.remove(bullet);, use bullets.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 see 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)