User talk:Awesomeness

From Robowiki
Revision as of 19:28, 2 May 2009 by Awesomeness (talk | contribs) (UGH)
Jump to navigation Jump to search
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 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)