Help:Help/Code Shrinking

From Robowiki
< Help:Help
Revision as of 01:46, 21 January 2010 by Rednaxela (talk | contribs) (Quick note)
Jump to navigation Jump to search

Again, I need help... Sorry, I can't seem to make anything smaller, ever... >.<

  • sniff* Elite has grown up so fast... It still sucks.
package awesomeness;

import robocode.*;
import robocode.util.*;
import java.util.Random;
import java.awt.Color;

/**
 * PwnBot - a robot by Awesomeness
 */
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;  //Enemy energy from the last turn
	static double changeInEnergy;  //Enemy bullet detection
	static int movementDirection = 50;  //Positive or negative, determines the direction I (usually) go
	static int alternate;  //Part of my weird moving system
	static Random generator = new Random(); //This makes random numbers
	
	/**
	 * run: PwnBot's default behavior
	 */
	public void run() {
		
		// body = black, gun = white, radar = red
		//setColors(Color.black, Color.gray, Color.orange);
		//setBulletColor(Color.yellow);
		
		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//////////////////////
		
		//If there's a change in energy, it probably fired

		
		if ((changeInEnergy = previousEnergy - (previousEnergy = e.getEnergy())) > 0d && changeInEnergy<=4) {
			i();
			alternate ++;
			if (alternate > generator.nextInt(5)) {
				i();
				alternate = 0;
			}
		}
		System.out.println(e.getDistance());
		
							
		// Stay at right angles to the opponent	
		//setTurnRight(e.getBearing()+90d);
		setTurnRightRadians(Math.cos(absoluteBearing+(1/e.getDistance())*movementDirection)); // Simonton-ish way. one byte smaller	
	
		
		//setMaxVelocity(8);
		
		setAhead(movementDirection*(Math.random()-0.2)*5);
		 
		previousEnergy = e.getEnergy();
		
		////////////////////Movement Code//////////////////////
		///////////////////////////////////////////////////////
		
		///////////////////////////////////////////////////////
		///////////////////////Gun Code////////////////////////
		
		//Pretty simple...  Just linear
		setTurnGunRightRadians(Utils.normalRelativeAngle((absoluteBearing += getHeadingRadians()) - 
    		getGunHeadingRadians() + (e.getVelocity() * Math.sin(e.getHeadingRadians() - 
    		absoluteBearing) / 13.2)));

		
		///////////////////////////////////////////////////////////
		// Edit:  I'm probably not going to put the SPM in       //
		// If I can't find the space.  I'm not going to even try //
		// customizing it to suit my bot until then, because the //
		// modified version will be inevitably larger... =(      //
		///////////////////////////////////////////////////////////
		
		//Thanks to FunkyChicken for the basis of my new gun code!
		
		//rounding to be more accurate in projection!
		/*pattern.insert(0, (char)(Math.round(Math.sin(e.getHeadingRadians() -
			(absoluteBearing = absoluteBearing + 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 = e.getDistance();
		searchlength =  index - (int)((dist)/(20-(power = 2)*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
		{
			absoluteBearing += Math.asin(((byte)pattern.charAt(index--))/dist);
		}
		while (index >= Math.max(0, searchlength));
		
		setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians()));*/
		setFire(2);


		
		///////////////////////Gun Code////////////////////////
		///////////////////////////////////////////////////////
		
		
		
		///////////////////////////////////////////////////////
		/////////////////////Radar Code////////////////////////
			
		setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
		
		
		/////////////////////Radar Code////////////////////////
		///////////////////////////////////////////////////////	
		
	
		
	}

	public void onHitWall(HitWallEvent e) {
		i();
	}
	
	public void i() {
		movementDirection = -movementDirection;
	}
}

I'm sure you can get at least 50 bits out of this... It's 234 right now. If it gets small enough, I might be able to fit a modified pattern matcher in. Ugh, I feel like I'm just 'the annoying guy who needs help all the time' on this wiki sometimes... Awesomeness 23:57, 20 January 2010 (UTC)

I'll look into trimming it more in a moment, but right now that compiles as 224 codesize for me, not 234. --Rednaxela 00:46, 21 January 2010 (UTC)


Anyone can help me shrink the code here by 10 bytes? It is currently 759 and I have really no ideas how to shrink it more. » Nat | Talk » 05:12, 21 June 2009 (UTC)

Not mind, I manage to shrink it to 745 bytes now.

Annoying... I've made an Über-Nano bot that gets 99% against N, but I'm stuck at 283 bytes... Awesomeness 01:29, 30 April 2009 (UTC)

Post the source. I'm a past master at reducing codesize on bots. Hell, I wrote the original articles over at the repository and codesize tricks that spurred the nanobot explosion. I'd love some new blood in the nano area while I grit my teeth over Infinity/Dustbunny and how to make them just 1% better :) --Miked0801 03:56, 30 April 2009 (UTC)
Okay.
package awesomeness;

import robocode.*;
import robocode.util.*;
import java.util.Random;
import static robocode.util.Utils.normalRelativeAngleDegrees;
//import java.awt.Color;

/**
 * Elite - a robot by Awesomeness
 */
public class Elite extends AdvancedRobot {
	
	int previousEnergy = 100;
	int count;
	int countAdd;// The amount to add to the count
	byte movementDirection = 1;
	byte alternate;
	Random generator = new Random(); //This makes random numbers
	
	/**
	 * run: Elite's default behavior
	 */
	public void run() {
		
		setAdjustRadarForGunTurn(true);
		setAdjustGunForRobotTurn(true);
		
		
		// After trying out your robot, try uncommenting the import at the top,
		// and the next line:
		//setColors(Color.red,Color.blue,Color.green);
		while(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 = getHeadingRadians() + e.getBearingRadians();
		
		///////////////////////////////////////////////////////
		////////////////////Movement Code//////////////////////
		
		//If there's a change in energy, it probably fired
		int changeInEnergy = previousEnergy- (int) e.getEnergy();
		
		if (changeInEnergy>0 && changeInEnergy<=4) {
			alternate();
		}
		
							
		// Stay at right angles to the opponent	
		setTurnRight(e.getBearing()+90/*-5*movementDirection*/);	
		
		countAdd += (generator.nextInt(2)*2-1) * 3;
	
		count += countAdd;
		
		setMaxVelocity(8);
		
		
		setAhead(50*movementDirection);
		
		// Track the energy level
		previousEnergy = (int) e.getEnergy();
		
		////////////////////Movement Code//////////////////////
		///////////////////////////////////////////////////////
		
		///////////////////////////////////////////////////////
		///////////////////////Gun Code////////////////////////
		
		//Pretty simple...
		setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing - 
    		getGunHeadingRadians() + (e.getVelocity() * Math.sin(e.getHeadingRadians() - 
    		absoluteBearing) / 13.2)));
		if (getGunHeat() == 0) { // Only try to fire if we can-
			setFire(2.0); // otherwise we do much worse
		}
		
		///////////////////////Gun Code////////////////////////
		///////////////////////////////////////////////////////
		
		
		
		///////////////////////////////////////////////////////
		/////////////////////Radar Code////////////////////////
			
		setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
		
		
		/////////////////////Radar Code////////////////////////
		///////////////////////////////////////////////////////	
		
		
		
	}
	public void onHitWall(HitWallEvent e) {
		i();
	}
	
	public void i() {
		setMaxVelocity(1);
		movementDirection = (byte) -movementDirection;
	}
	public void alternate() {
		i();//Length: 276
		alternate = (byte) -alternate;
		if (alternate == 1) {
			i();
		}
	}
}

Edit: WAIT A SEC! I FORGOT TO DELETE PART OF MY OLD COUNTING CODE! What if I delete it? I hope it'll be enough! Awesomeness 11:33, 30 April 2009 (UTC) Okay, changed the code. 278 bytes.... lol Awesomeness 11:44, 30 April 2009 (UTC)

What's count and countAdd use for? Here is my version that do exactly same as your. except that it 233 bytes (with javac)

package awesomeness;

import robocode.*;
import robocode.util.*;
import java.util.Random;
import static robocode.util.Utils.normalRelativeAngleDegrees;
//import java.awt.Color;

/**
 * Elite - a robot by Awesomeness
 */
public class Elite extends AdvancedRobot {
	
	static double previousEnergy = 100;
	static int count;
	static int countAdd;// The amount to add to the count
	static int movementDirection = 50;
	static int alternate;
	static Random generator = new Random(); //This makes random numbers
	
	/**
	 * run: Elite's default behavior
	 */
	public void run() {
		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//////////////////////
		
		//If there's a change in energy, it probably fired
		double changeInEnergy = previousEnergy - e.getEnergy();
		
		if (changeInEnergy>0d && changeInEnergy<=4d) {
			i();
			alternate = -alternate;
			if (alternate == 1) {
				i();
			}
		}
		
							
		// Stay at right angles to the opponent	
		//setTurnRight(e.getBearing()+90d);
		setTurnRightRadians(Math.cos(absoluteBearing)); // Simonton-ish way. one byte smaller	
	
		count += (countAdd += (generator.nextInt(2)*2-1) * 3);
		
		setMaxVelocity(8);
		
		setAhead(movementDirection);
		
		// Track the energy level
		previousEnergy = e.getEnergy();
		
		////////////////////Movement Code//////////////////////
		///////////////////////////////////////////////////////
		
		///////////////////////////////////////////////////////
		///////////////////////Gun Code////////////////////////
		
		//Pretty simple...
		setTurnGunRightRadians(Utils.normalRelativeAngle((absoluteBearing += getHeadingRadians()) - 
    		getGunHeadingRadians() + (e.getVelocity() * Math.sin(e.getHeadingRadians() - 
    		absoluteBearing) / 13.2)));
		if (getGunHeat() == 0d) { // Only try to fire if we can-
			setFire(2d); // otherwise we do much worse
		}
		
		///////////////////////Gun Code////////////////////////
		///////////////////////////////////////////////////////
		
		
		
		///////////////////////////////////////////////////////
		/////////////////////Radar Code////////////////////////
			
		setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
		
		
		/////////////////////Radar Code////////////////////////
		///////////////////////////////////////////////////////	
		
		
		
	}
	public void onHitWall(HitWallEvent e) {
		i();
	}
	
	public void i() {
		setMaxVelocity(1);
		movementDirection = -movementDirection;
	}
}

» Nat | Talk » 16:54, 30 April 2009 (UTC)

I took a quick stab at this. Note that static variables take up less room than instance variables, for whatever reason. But Nat, he wants previousEnergy set to 100 at start of each round, and count and countAdd set to 0, so switching those to static would require setting the value in run() -- not sure which is smaller. I think movementDirection and alternate keeping their values from previous round should not be a performance hit, and will save codesize.

package awesomeness;

import robocode.*;
import robocode.util.*;
import java.util.Random;
import static robocode.util.Utils.normalRelativeAngleDegrees;
//import java.awt.Color;

/**
 * Elite - a robot by Awesomeness
 */
public class Elite extends AdvancedRobot {

    int previousEnergy = 100;
    static byte movementDirection = 1;
    static byte alternate;
    static Random generator = new Random(); //This makes random numbers

    /**
     * run: Elite's default behavior
     */
    public void run() {

        setAdjustRadarForGunTurn(true);
        setAdjustGunForRobotTurn(true);


        // After trying out your robot, try uncommenting the import at the top,
        // and the next line:
        //setColors(Color.red,Color.blue,Color.green);
        while(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;

        ///////////////////////////////////////////////////////
        ////////////////////Movement Code//////////////////////

        //If there's a change in energy, it probably fired
        int changeInEnergy;

        // Voidious: ugly as it is, I *think* this will execute in right order
        if ((changeInEnergy = previousEnergy - (previousEnergy = (int) e.getEnergy()))>0 &&
            changeInEnergy<=4) {
            i();//Length: 276
            alternate = (byte) -alternate;
            if (alternate == 1) {
                i();
            }
        }


        // Stay at right angles to the opponent
        setTurnRight(e.getBearing()+90/*-5*movementDirection*/);

        setMaxVelocity(8);

        setAhead(50*movementDirection);

        ////////////////////Movement Code//////////////////////
        ///////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////
        ///////////////////////Gun Code////////////////////////

        //Pretty simple...
        setTurnGunRightRadians(Utils.normalRelativeAngle(
            (absoluteBearing = getHeadingRadians() + e.getBearingRadians()) -
            getGunHeadingRadians() + (e.getVelocity() * Math.sin(e.getHeadingRadians() -
            absoluteBearing) / 13.2)));
//        if (getGunHeat() == 0) { // Only try to fire if we can-
            setFire(2.0); // otherwise we do much worse
                          // Voidious: what side effect to setFire if you can't?
                          //           I didn't think there was any.
//        }

        ///////////////////////Gun Code////////////////////////
        ///////////////////////////////////////////////////////



        ///////////////////////////////////////////////////////
        /////////////////////Radar Code////////////////////////

        setTurnRadarLeftRadians(getRadarTurnRemainingRadians());


        /////////////////////Radar Code////////////////////////
        ///////////////////////////////////////////////////////



    }
    public void onHitWall(HitWallEvent e) {
        i();
    }

    public void i() {
        setMaxVelocity(1);
        movementDirection = (byte) -movementDirection;
    }

    // Voidious is "*= -1" smaller than "var = (byte)-var"? seems like it
    // would be (both in i() and alternate(), which was moved)
}

I haven't compiled that, but I think everything there is basic and will work. There's surely more that can be done, but I hit most of the obvious stuff. Good luck. =) --Voidious 16:22, 30 April 2009 (UTC)

Er, yeah, sorry, that count stuff is definitely not doing anything, and should save you more than 5 bytes. (Updated my code there.) You can also compile with Jikes if you use an older version of robocode.jar, that might save some bytes too. --Voidious 16:31, 30 April 2009 (UTC)

No, the var = -var is the smallest. I see no point to use byte when the memory isn't in issue. The integer should take smaller codesize since it need not to be promoted to each operation. And by assign the 50 to movementDirection instead of multiply by 50 should saves around 1 or 2 bytes (or 3? I not sure) And what is alternate necessary? It always be zero... Anyway, Here my new code. Got rid off the count thing and using the energy system Voidious posted, this version cost 202 bytes with javac and 205 with Jikes (!!): » Nat | Talk » 16:54, 30 April 2009 (UTC)

package awesomeness;

import robocode.*;
import robocode.util.*;
import java.util.Random;
//import static robocode.util.Utils.normalRelativeAngleDegrees;
//import java.awt.Color;

/**
 * Elite - a robot by Awesomeness
 */
public class Elite extends AdvancedRobot {
	
	double previousEnergy = 100d;
	//int count;
	//int countAdd;// The amount to add to the count
	static int movementDirection = 50;
	static int alternate;
	//static Random generator = new Random(); //This makes random numbers
	
	/**
	 * run: Elite's default behavior
	 */
	public void run() {
		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//////////////////////
		
		//If there's a change in energy, it probably fired
		double changeInEnergy;
		
		if ((changeInEnergy = previousEnergy - (previousEnergy = e.getEnergy())) > 0d && changeInEnergy<=4) {
			i();
			alternate = -alternate;
			if (alternate == 1) {
				i();
			}
		}
		
							
		// Stay at right angles to the opponent	
		//setTurnRight(e.getBearing()+90d);
		setTurnRightRadians(Math.cos(absoluteBearing)); // Simonton-ish way. one byte smaller	
	
		//count += (countAdd += (generator.nextInt(2)*2-1) * 3);
		
		//setMaxVelocity(8);
		
		setAhead(movementDirection);
		
		// Track the energy level
		previousEnergy = e.getEnergy();
		
		////////////////////Movement Code//////////////////////
		///////////////////////////////////////////////////////
		
		///////////////////////////////////////////////////////
		///////////////////////Gun Code////////////////////////
		
		//Pretty simple...
		setTurnGunRightRadians(Utils.normalRelativeAngle((absoluteBearing += getHeadingRadians()) - 
    		getGunHeadingRadians() + (e.getVelocity() * Math.sin(e.getHeadingRadians() - 
    		absoluteBearing) / 13.2)));
		if (getGunHeat() == 0d) { // Only try to fire if we can-
			setFire(2d); // otherwise we do much worse
		}
		
		///////////////////////Gun Code////////////////////////
		///////////////////////////////////////////////////////
		
		
		
		///////////////////////////////////////////////////////
		/////////////////////Radar Code////////////////////////
			
		setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
		
		
		/////////////////////Radar Code////////////////////////
		///////////////////////////////////////////////////////	
		
		
		
	}
	public void onHitWall(HitWallEvent e) {
		i();
	}
	
	public void i() {
		//setMaxVelocity(1);
		movementDirection = -movementDirection;
	}
}
Just found out that setMaxVelocity isn't need since it will get override, so now 190 bytes (javac) » Nat | Talk » 16:58, 30 April 2009 (UTC)

Some improvements, codesize down to 173 (comments removed):

package awesomeness;
import robocode.*;
import robocode.util.*;

public class Elite extends AdvancedRobot {
	
	double previousEnergy = 100d;
	static int movementDirection;
	static int alternate;

	public void run() {
		movementDirection = 50;
		setAdjustGunForRobotTurn(true);
		turnRadarRightRadians(Double.POSITIVE_INFINITY);
	}

	public void onScannedRobot(ScannedRobotEvent e) {
		
		double absoluteBearing = e.getBearingRadians();
		
		double changeInEnergy;
		
		if ((changeInEnergy = previousEnergy - (previousEnergy = e.getEnergy())) > 0d && changeInEnergy<=4) {			
			if ((alternate = -alternate) != 1) {
				movementDirection = -movementDirection;
			}
		}
		
		setTurnRightRadians(Math.cos(absoluteBearing)); // Simonton-ish way. one byte smaller	
		
		setAhead(movementDirection);
		
		setTurnGunRightRadians(Utils.normalRelativeAngle((absoluteBearing += getHeadingRadians()) - 
    		getGunHeadingRadians() + (e.getVelocity() * Math.sin(e.getHeadingRadians() - 
    		absoluteBearing) / 13.2)));
		if (getGunHeat() == 0d) {
			setFire(2d);
		}
		setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
	}
	public void onHitWall(HitWallEvent e) {
		movementDirection = -movementDirection;
	}
}

Basically:

  • it takes 1 less byte to initialize static variables in run() than when it is declared.
  • if enemy fired, i() is possibly twice, so removed 1 possible call by changing the if to if ((alternate = -alternate) != 1) and removing the call above it
  • previousEnergy = e.getEnergy() was done twice...
  • finally, after all this it's less expensive to just inline i()

But 1 question: since alternate is never initialized, won't it always be zero? --Starrynte 00:37, 5 May 2009 (UTC)



What's the best targeting system equal or less than 83 bytes long? Awesomeness 21:59, 30 April 2009 (UTC)

What kind of bot are you building? For very short range to around 200 and very long range (600+), an Infinity type gun works great. If that's too big, just standard linear aim is fine for short range. But, it all depends on what type of bots you are going up against. A bullet dodger would crush Infinity and a good stop and go would also confuse it. Heck head on firing works fine in melee beyond around 200. It even will occasionally hit dodgers and the like.

For the more advanced bots, random linear is probably your best bet. --Miked0801 22:37, 30 April 2009 (UTC)

I'm not sure but I think circular targeting can fit in. But random is better, PM is the best for nanobot. » Nat | Talk » 08:11, 1 May 2009 (UTC)

PM will not fit in my Nano, I'm sure of it. I don't know how to implement random linear. You're right, circular targeting might fit in, but I'm sure it'd be a stretch. PS: I've tweaked my code, and now its movement fools PMers and linear targeting! =) PPS: All of the different small versions of elite are making the page huge. Should we take them down?

A random, linear aim gun - assumes firepower 3 shots always. Change the /11 to fix that. Will not fire behind the targeted bot, change the random() to 1 - 1.5*random() to fix that. Yanked from Infinity w/o the decrease lead with distance code.

setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians() + 
				Math.random() * 
				Math.asin(e.getVelocity() / 11) * Math.sin(e.getHeadingRadians() - absoluteBearing) ));

--Miked0801 15:52, 1 May 2009 (UTC)

Actually, there is no need for asin. The disorted between them isn't really matter. And, no, you should not take them down. If you finsih asking help, letting me know and this page will be archived instead. » Nat | Talk » 16:39, 1 May 2009 (UTC)

Yes, FunkyChicken's PM gun on my bot easily beats many minis and ties with even a few megas, but it's 370 bytes. Awesomeness 23:34, 1 May 2009 (UTC)

I don't get it... Most guns I borrow from sample code always aim 90 degrees away from where I want it to aim. About half of the time I can fix it, (I had to fix it for myself in FunkyChicken's gun) but the other half I can't. The random linear code is in the second group.

  • Remember that zero degrees is up (North) in robocode and the direction is clockwise, not as math at school. --GrubbmGait 01:47, 2 May 2009 (UTC)