Talk:Hat League/Message Format

From Robowiki
Jump to navigation Jump to search

Here's my draft suggestion for a common message format. Each line in a message is a different message, prefixed by the message type, followed by comma-seperated-values:

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.
The result of this code is a String array containing the number of elements specified by a parameter. If there are fewer elements in the CSV string, the remaining elements in the array will be null strings. This will not be a problem since we know by the first element what type of message it is, and how many elements we are looking for. -- Martin


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

  • That is also my understanding. -- Martin

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

  • The implementation covers all message types listed at the top of the page (hence the CSV approach), as well as a "CommuniqueNotAvailable" representing something that was unparseable. They are packaged as wiki.team.communication.* -- Martin

I wrote an implementation at User:AaronR/HatLeagueRobot. It is a fairly standard event-delegating framework, but I haven't tested it very much. « AaronR « Talk « 01:23, 15 January 2008 (UTC)

You cannot post new threads to this discussion page because it has been protected from new threads, or you do not currently have permission to edit.

There are no threads on this page yet.