*** A format war?! Really? Well I personally like frameworks to mimic the style of the jdk (I take alot of wisdom from the well formatted java.util section). But thats me. If I was to make a format I would probably base it off the normal robocode api and just add some basics, such as "onTeammateDeath?" and (getLastTeammateX?, getLastTeammateY?) or getLastTeammateLocation?. Basically only based off the message system, and override the setFire, fire and such options to send messages based on those. I basically apt for a bearly know its there approach. However I am strange. --Chase-san |
PD,time,x,y,h,v,e // personal data ES,time,x,y,h,v,e,name // enemy scan BO,time,x,y,h,v // bullet (origin) EW,time,x,y,v // enemy wave origin MR,name // my radar target MB,name // my bullet target TR,name // suggested radar target TB,name // suggested bullet target NA,message // custom message-- Martin
I like the messages you have laid out there. So were you thinking of just sending strings for each thing? Alternatively, we could create a base class for everyone to extend, with (Serializable) classes for each message type, and methods for sending the messages that are customizable (i.e., not personal data or enemy scan); then create the onMessageReceived method that passes off the message types to handler methods, which you'd override like with the built in event methods. I hope I'm making sense... No other message types come to mind that you don't already have listed, but I'll rack my brain a bit. -- Voidious
In my second attempt at making a team robot, I had a serializable structure that had some doubles in it, but when I tried to send it to the message broadcaster it choked. I ended up having to break the same data into a comma delimeted string manually and reinterpreting it on the other end. If there is some magic thing I overlooked then it would certainly be easier to send it as a structure. Otherwise we / I can provide a complete class to compose and translate messages. I do mostly batch processing lately so I've got routines for doing the CSV stuff already. -- Martin
Sending serializable structures (with doubles) worked in my last 5 team attempts :) --Krabb
Just FYI, I found that internal classes wouldn't serialize even if they extended Serializable. The moment I made the class external, problem solved. -- Skilgannon
public static String[] parseCSV( String line, int count ) { final char delimeter = ','; final char textWrapper = '\"'; return parseDelimetedValues( line, count, delimeter, textWrapper ); } private static String[] parseDelimetedValues( String delimetedValues, int count, final char delimeter, final char textWrapper ) { String value[] = new String[ count ]; int startIndex = 0; int endIndex = 0; try { for( int i = 0; ( ( i < count ) && ( endIndex != -1 ) && startIndex < delimetedValues.length( ) ); i++ ) { if( delimetedValues.charAt( startIndex ) == textWrapper ) { startIndex++; endIndex = delimetedValues.indexOf( textWrapper, startIndex ); value[ i ] = delimetedValues.substring( startIndex, endIndex ); startIndex = delimetedValues.indexOf( delimeter, endIndex ) + 1; } else { endIndex = delimetedValues.indexOf( delimeter, startIndex ); if( endIndex == -1 ) { value[ i ] = delimetedValues.substring( startIndex ); } else { value[ i ] = delimetedValues.substring( startIndex, endIndex ); startIndex = endIndex + 1; } } } } catch( Exception ex ) { ExceptionHandler.getInstance().log( ex ); ExceptionHandler.getInstance().log( "line: " + delimetedValues ); } return value; }Above is some code I've written for a batch processing application. I am sure it could stand some optimization. The ExceptionHandler class is just a log file recorder. You could also use this to process tab delimeted (not shown) or some other delimeter. Writing out comma separated values is much simpler, so I didn't bother writing any example code.
Possible beginning of a "base class":
import robocode.*; import robocode.Bullet; import java.io.*; // // "Base Class" to share information, every bot must extend "CustomTeamRobot" // and call the setCustomTeamRobot(this) function // public class CustomTeamRobot extends TeamRobot { CustomTeamRobot robot; public void setCustomTeamRobot(CustomTeamRobot robot) { this.robot=robot; } public Bullet setFireBullet(double p) { Bullet b = super.setFireBullet(p); if(b==null) return b; MessageBullet mb = new MessageBullet(b, p, this); if(getTeammates()!=null) { try{ broadcastMessage(mb);} catch(IOException ex){ System.out.println(ex);} } return b; } public final void onMessageReceived(MessageEvent ev){ if(ev.getMessage().getClass()==MessageBullet.class) { robot.newTeamBullet(new TeamBullet((MessageBullet)ev.getMessage(),this)); } } public void newTeamBullet(Bullet b){ } } //class to send Bullet data class MessageBullet implements Serializable { double heading; double power; double velocity; double x_start,y_start; long time_start; public MessageBullet(Bullet b, double power, CustomTeamRobot robot) { heading=robot.getGunHeadingRadians(); this.power=power; velocity=20-3*power; x_start=robot.getX(); y_start=robot.getY(); time_start=robot.getTime(); } public double getHeading(){ return heading;} } // simulates a real robocode "Bullet" class TeamBullet extends Bullet { CustomTeamRobot robot; MessageBullet mb; public TeamBullet(MessageBullet mb, CustomTeamRobot robot) { super(null); this.robot=robot; this.mb=mb; } public double getY() { return mb.y_start+Math.cos(mb.heading)*mb.velocity*(robot.getTime()-mb.time_start); } public double getX() { return mb.x_start+Math.sin(mb.heading)*mb.velocity*(robot.getTime()-mb.time_start); } } //============================================================================================= ///////////////// //Test Robot: ///////////////// import java.awt.*; import java.util.*; import robocode.Bullet; public class TeamTestBot extends CustomTeamRobot { ArrayList<Bullet> bullets = new ArrayList<Bullet>(); public void run() { setCustomTeamRobot(this); setTurnRadarRightRadians(Double.POSITIVE_INFINITY); setTurnLeft(Double.POSITIVE_INFINITY); setAhead(Double.POSITIVE_INFINITY); while(true) { Bullet b = setFireBullet(3); if(b!=null) bullets.add(b); System.out.println("size: "+bullets.size()); execute(); } } public void newTeamBullet(Bullet b){ bullets.add(b); } public void onPaint(java.awt.Graphics2D g) { g.setColor(Color.RED); for(int i=0; i<bullets.size(); i++) g.fillOval((int)bullets.get(i).getX()-2, (int)bullets.get(i).getY()-2, 5, 5); } }
This could be the beginning of a "base class" for all competitors, we could implement the same for ScannedRobotEvents and Bullet Missed(/Hit)Events. With this kind of implementation the bots don't have to differentiate between their own or mate bullets and events, but it might be a bit slow :/ Suggestions? --Krabb
Would the 2000 byte limit still apply? Cause this code doesn't exactly look optimized for size... ---David Alves
I was under the impression there would be no CodeSize limit for this... ? -- Voidious
I'm mentioning this prematurely, as I don't have the JavaDoc written and am not really competent at packaging JAR files (which seems odd since I've done Java since 2000), but I've written a set of classes to support team communication. They don't do automatic serialization, but rather read and write comma-separated value Strings. I'm open to do some beta testing with anyone interested in making the Hat Tourney a reality. -- Martin
(discussion migrated to new wiki)
I'm running into some issues with packaging the JAR file. All of my traditional tank code is packaged under pedersen.*, but the new communication code is packaged as wiki.team.communication.*. I launched Robocode from within Eclipse and started getting errors about one of the communication class files being duplicated. Doing a clean and rebuild did not change this. I started a new project and moved the communication package to it, linking robocode.jar (for MessageEvent?). I packaged the contents as a JAR file under F:\robocode\libs\communication.jar, linked to it from my main tank project, and added the jar to the VM arguments for launching Robocode within Eclipse. Launching Robocode within Eclipse again I got NoClassDefFound? errors for the communication classes. Anyone know what I am doing wrong? -- Martin