[Home]Minimize the line count

Robo Home | Changes | Preferences | AllPages

Difference (from prior major revision) (no other diffs)

Changed: 3c3,4
I thought I would add some tips for those people trying to write SonnetBots for the Robocode Little League. This will allow your robot to get pretty big without to many semicolons. Since I like text that lines up I'm going to use the pre tag here.
I thought I would add some tips for those people trying to write SonnetBots for the Robocode Little League. This will allow your robot to get pretty big without to many semicolons. Since I like text that lines up I'm going to use the pre tag here. Since I went and wrote a 12meg SonnetBot that used only 6 lines and implemented anti-gravity and a
guess factor gun I think i'm qualified to lecture here (I was the one who actually tried to understand flood sonnet!). In case you folks are wondering why I din't enter it in the leage it's because it's still a work in progress and still gets it's but kicked by some of the simpler bots out there. :(

Added: 5a7,10

RULE #0 !!!!! K.I.S.S. (Keep it simple stupid)
Start small. Work a piece at a time and get it running.


Changed: 101,102c106,109
Determine what their arguments are before hand.

Determine what their arguments are before hand in global variables so you can see the results
from methods like onScannedRobot()

Information you need to know

Changed: 121c128,151
</pre>
Rule #6 Use print statements to debug your conditions soe you know whats going on. I consider these freebe's
because although you use a semi-colon they aren't integral to the workings of your final product and
can be removed later. However they are key to development. Usually you are only conserned with the
failure result so something like this would be appropriate.

--- before ---
absbearing = new Double(e.getBearingRadians?() + getHeadingRadians());
turn = new Double(Math.PI/2 + e.getBearingRadians?());

--- after ---
if ( ( (absbearing = new Double( e.getBearingRadians?() + getHeadingRadians())) == null)
|| ( (turn = new Double( Math.PI/2 + e.getBearingRadians?())) == null)
)
{ out.println("Error in onScannedRobot() : Failed to set absbearing our our proper turn");
} else
{ out.println("absbearing = " + absbearing.toString()); // toString is not required
out.println("turn = " + turn); // compiler assumes it's called for Objects.
}

By doing this especially for our larger conditions we know what went wrong in each condition.
Preferable we would like to keep our conditions as small as possible because in this example we
still don't know what part of the condition failed. However in order to make our code more readable
it's reasonable to assume statements like the above are NOT going to fail and can all be written in
one big long condition. Use shortcut operators frequently to increase performance and find errors quicker

Minimizing the line count (For Sonnet-Bots

I thought I would add some tips for those people trying to write SonnetBots for the Robocode Little League. This will allow your robot to get pretty big without to many semicolons. Since I like text that lines up I'm going to use the pre tag here. Since I went and wrote a 12meg SonnetBot that used only 6 lines and implemented anti-gravity and a guess factor gun I think i'm qualified to lecture here (I was the one who actually tried to understand flood sonnet!). In case you folks are wondering why I din't enter it in the leage it's because it's still a work in progress and still gets it's but kicked by some of the simpler bots out there. :(

<pre>

   RULE #0  !!!!! K.I.S.S.  (Keep it simple stupid)
            Start small. Work a piece at a time and get it running.

   Rule #1: Learn to comment well. I say this because It's going to be your comments that tell you
            where everything is in the code and what everything is going to do. Since you are going to end
            up having a lot of brackets I find it particularly useful to indent each new set of semi-colons unless
            its a simple easy to read condition.

            --- before ---
            ((x>0) && (x<width) && (y>0) && (y<height)) ? "yes" : "no"

            --- after ---
            (   (   x        // (double) - x coordinate
                >   0        // Test if right of west wall (x=0)
                )            
            &&  (   x        // (double) - x coordinate
                <   width    // Test if left of east wall (x=width)
                )
            &&  (   y        // (double) - y coordinate
                >   0        // Test if north of south wall (y=0)
                )
            &&  (   y        // (double) - y coordinate
                <   height   // Test if couth of north wall (y=height)
                )
            )
            ?   "yes"        // The point is in the battlefield
            :   "no"         // The point is not in the battle field

            While this might make your code look more cryptic it make it far easier to understand the mechanics
            of a condition that has many nested brackets. The same method can be applied to functions. It
            helps when ALL THE BRACKETS AND OPERATOR ARE ALIGNED ON THE SAME INDENTATION DEPTH. 
            It also allows you to comment beside each argument so you know what they do.          

   Rule #2: Get comfortable with casting because you're going to be doing a lot of it.
            Every variable you can imagine can be implemented using an object. Java supplies numerous
            wrapper classes for the common primitives. int becomes Integer, double becomes Double.
            If you use these wrapper classes ALL YOUR VARIABLES CAN BE WRITTEN ON ONE LINE.

            --- before ---
            int       i, j;
            double    x, y;
            HashTable? h = new HashTable?();

            --- after ---
            Object
               i = new Integer(),
               j = new Integer(),
               x = new Double(),
               y = new Double(),
               h = new HashTable?();

            Now in order to access their actual values you will need to cast them into their wrapper values
            and use the methods they contain.

            --- before ---
            if (i < j)
                  return i;
            else  return j;

            --- after ---
            if (   ((Integer) i).intValue()
               <   ((Integer) j).intValue()
               )
            {  return ((Integer) i).intValue();     
            } else
            {  return ((Integer) j).intValue();
            }

            The above condition could have eliminated 2 semicolons by using the ? condition

            --- better ---
            return (   ((Integer) i).intValue() < ((Integer) j).intValue() )   // condition
                   ?   ((Integer) i).intValue()                                // true return value
                   :   ((Integer) j).intValue();                               // false return value

   Rule #3: Think of your program as one big condition. EVERY STATEMENT CAN BE WRITTEN AS A CONDITION THAT HAS
            A BOOLEAN RETURN VALUE. This will allow you to eliminate almost ALL of your semi-colons right here.

            --- before ---
            A = B;

            --- after ---
            if ((A = B) != null)
            { // The assignment succeeded in this case.
            } else
            { // The assignment failed in this case because the object was null
            } 

   Rule #5: EACH FUNCTION YOU WRITE COSTS AT LEAST ONE SEMICOLON. Each time you write a function with a return
            statement it costs one semi-colon. But you can use a function that has a return condition for free by
            testing and assignment with it's return value in a condition. Writing a void function can be free because
            you avoid the return statement, but you will need that semi-colon when you call it. Since NO FUNCTION
            IS A NECESSITY, you can cut down on your line count by simply not writing them.

            Unfortunatly the key methods in robocode that do what you want them to do are "void" methods
            that do require a semi-colon. Since you have to use them, only call them once in the main method.
            Determine what their arguments are before hand in global variables so you can see the results
            from methods like onScannedRobot()

               Information you need to know
               a) Amount to turn the radar.     (Double)
               b) Amount to turn the gun.       (Double)
               c) Amount to turn the robot.     (Double)
               d) Amount to move back and forth (Double)
               e) Fired power we wish to shoot. (Double)

            Because the run method has the lowest priority it will be the last function executed. In the 
            end this is all we need to know so lets try to ensure we only leave one line for each required 
            method. The last one can be put into a condition if you use the alternate setFireBullet()

            --- code ---
            // I used 11 for the or symbol because it causes a line break in html. (grr..)
            while( setFireBullet( power ) != null 11 true)  
            {   setTurnRadarRightRadians( rturn );
                setTurnGunRightRadians?( gturn );
                setTurnRightRadians?( turn );
                setAhead( moveDist );
            }
   Rule #6  Use print statements to debug your conditions soe you know whats going on. I consider these freebe's
            because although you use a semi-colon they aren't integral to the workings of your final product and
            can be removed later. However they are key to development. Usually you are only conserned with the
            failure result so something like this would be appropriate.

            --- before ---
            absbearing = new Double(e.getBearingRadians?() + getHeadingRadians());
            turn       = new Double(Math.PI/2 + e.getBearingRadians?());

            --- after ---
            if (   (   (absbearing = new Double( e.getBearingRadians?() + getHeadingRadians()))   == null)
               ||  (   (turn = new Double( Math.PI/2 + e.getBearingRadians?()))                   == null)
               )
            {  out.println("Error in onScannedRobot() : Failed to set absbearing our our proper turn");
            } else
            {  out.println("absbearing = " + absbearing.toString());   // toString is not required
               out.println("turn       = " + turn);                    // compiler assumes it's called for Objects.
            }

            By doing this especially for our larger conditions we know what went wrong in each condition.
            Preferable we would like to keep our conditions as small as possible because in this example we
            still don't know what part of the condition failed. However in order to make our code more readable
            it's reasonable to assume statements like the above are NOT going to fail and can all be written in
            one big long condition. Use shortcut operators frequently to increase performance and find errors quicker

Robo Home | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited June 23, 2004 2:16 EST by ABC (diff)
Search: