Help:Help/Code Shrinking

From Robowiki
< Help:Help
Revision as of 16:52, 1 May 2009 by Miked0801 (talk | contribs) (Randm linear Nano gun.)
Jump to navigation Jump to search

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)




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)