Robo Home | Changes | Preferences | AllPages

I made this grapher today because I was tired of plugging the same code into different bots and commenting and uncommenting the same giant block of code over and over again. If you have RobocodeGLV014 (which you should!), this class will draw all of your stats for you in the background as you watch your bot fight, no matter how many segments you have, nor whether you store your stats as ints, floats, or doubles. All you have to do is have the following code in your run() method:
 statGrapher = new StatGrapher();
 statGrapher.setFrame(0, 0, getBattleFieldWidth?(), getBattleFieldHeight?());
And then the following in your onScannedRobot event:
 statGrapher.selectSegment(new int[] {a, b, c, d});
Where a, b, c, and d are the indices for your segments that would normally select your current stats array, like "yourStatsArray?[a][b][c][d]". If you don't have any segments, there is no need to call selectSegment(). It will work without it. If you do call it and you have no segments, you must pass either null or an empty int array. You may display multiple graphs as well, if you like, and put them wherever you want on the background.

I hope someone finds this useful! If you have any feature requests, just let me know.

package wiki.graphing;

import robocode.robocodeGL.LineGL;
import robocode.robocodeGL.system.GLRenderer;
import java.awt.Color;
import java.lang.reflect.*;

public class StatGrapher {
	private LineGL[] graph;
	private Object stats;
	private Object selected;
	private double x, y, width, height;
	private double lineWidth = 2;
	private Color color = Color.GREEN;
	public void setFrame(double x, double y, double width, double height) {
		setX(x); setY(y); setWidth(width); setHeight(height);
	public void setX(double x) { this.x = x; }
	public void setY(double y) { this.y = y; }
	public void setWidth(double width) { this.width = width; }
	public void setHeight(double height) { this.height = height; }
	public void setStats(Object stats) { this.stats = this.selected = stats; }
	public void setColor(Color color) { this.color = color; }
	public void selectSegment(int[] indices) {
		Object temp = stats;

		for (int i = 0; indices != null && i < indices.length; i++)
			temp = Array.get(temp, indices[i]);

		selected = temp;
	public void draw() {
		double highestValue = 1;
		graph = new LineGL[Array.getLength(selected) - 1];
		for (int i = 0; i < Array.getLength(selected); i++)
			if (Array.getDouble(selected, i) > highestValue)
				highestValue = Array.getDouble(selected, i);
		for (int i = 0; i < graph.length; i++) {
			graph[i] = new LineGL();
			graph[i].setLine(x + width * i / graph.length, y + height * Array.getDouble(selected, i) / highestValue,
			 x + width * (i + 1) / graph.length, y + height * Array.getDouble(selected, i + 1) / highestValue);
	public void remove() {
		if (graph != null) {
			for (int i = 0; i < graph.length; i++) {
				if (graph[i] != null)


Wow, great tool... thanks nano! --David Alves

Totally AWESOME tool!!! Thanks nano! -- PEZ

No problem! :) -- nano

I added the following constructor:
	public StatGrapher(Color color) {
	    this.color = color;
Convenient when you want to paint several graphs. Also, the way I do waves makes statGrapher truly easy to use. Like so:
import wiki.graphing.*;

public class Pugilist extends AdvancedRobot {
    StatGrapher ewGrapher = new StatGrapher(Color.GREEN);
    public void run() {
	ewGrapher.setFrame(0, 0, getBattleFieldWidth(), getBattleFieldHeight());
    public void onScannedRobot(ScannedRobotEvent e) {
	EnemyWave ew = new EnemyWave();
	ew.visits = moveFactors[distanceIndex = (int)(enemyDistance / (MAX_DISTANCE / DISTANCE_INDEXES))]
	    [(int)(enemyFirePower / 0.65)];
Where "visits" is my int[] visit counts array held by my Wave instances. Anyone try doing this with totally unsegmented EnemyWaves and watch the graph move! It's a learning experience.

-- PEZ

Robo Home | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited September 27, 2004 19:57 EST by Ph (diff)