User:Rednaxela/BotBase
Jump to navigation
Jump to search
This is a class I've been basing all of my recent non-codesize-restricted bots off of.
Note: This is somewhat out-of-date. I plan to update it some time.
Contents
BotBase.java
package ags.muse.base;
import ags.muse.base.actors.*;
import java.awt.Color;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import robocode.BulletHitBulletEvent;
import robocode.BulletHitEvent;
import robocode.BulletMissedEvent;
import robocode.CustomEvent;
import robocode.DeathEvent;
import robocode.Event;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.MessageEvent;
import robocode.RobotDeathEvent;
import robocode.ScannedRobotEvent;
import robocode.SkippedTurnEvent;
import robocode.StatusEvent;
import robocode.WinEvent;
import robocode.TeamRobot;
/**
* @author Alexander Schultz
*/
abstract public class BotBase extends TeamRobot {
private Rules rules;
private GunActor gunActor;
private MovementActor movementActor;
private RadarActor radarActor;
private BroadcastActor broadcastActor;
public Rules getRules() {
return rules;
}
public GunActor getGunActor() {
return gunActor;
}
public MovementActor getMovementActor() {
return movementActor;
}
public RadarActor getRadarActor() {
return radarActor;
}
public BroadcastActor getBroadcastActor() {
return broadcastActor;
}
private final List<Event> events = new ArrayList<Event>();
private List<Event> getEvents() {
List<Event> output = new ArrayList<Event>(events);
events.clear();
return output;
}
public void onCustomEvent(CustomEvent arg0) { events.add(arg0); }
public void onMessageReceived(MessageEvent arg0) { events.add(arg0); }
public void onBulletHit(BulletHitEvent arg0) { events.add(arg0); }
public void onBulletHitBullet(BulletHitBulletEvent arg0) { events.add(arg0); }
public void onBulletMissed(BulletMissedEvent arg0) { events.add(arg0); }
public void onDeath(DeathEvent arg0) { events.add(arg0); }
public void onHitByBullet(HitByBulletEvent arg0) { events.add(arg0); }
public void onHitRobot(HitRobotEvent arg0) { events.add(arg0); }
public void onHitWall(HitWallEvent arg0) { events.add(arg0); }
public void onRobotDeath(RobotDeathEvent arg0) { events.add(arg0); }
public void onScannedRobot(ScannedRobotEvent arg0) { events.add(arg0); }
public void onStatus(StatusEvent arg0) { events.add(arg0); }
public void onWin(WinEvent arg0) { events.add(arg0); }
public void onSkippedTurn(SkippedTurnEvent arg0) {
events.add(arg0);
System.out.println("Warning! Turn skipped!");
}
// Echo broadcast messages back to self
@Override
public void broadcastMessage(java.io.Serializable s) throws java.io.IOException {
super.broadcastMessage(s);
events.add(new MessageEvent(rules.NAME, s));
}
public void setColors(final Color bodyColor, final Color scanColor, final Color gunColor, final Color radarColor) {
if (!running)
throw new UnsupportedOperationException("Bot must be running before colors may be set.");
this.setBodyColor(bodyColor);
this.setScanColor(scanColor);
this.setGunColor(gunColor);
this.setRadarColor(radarColor);
}
abstract public void init();
abstract public void runTick(List<Event> events);
abstract public void _onPaint(Graphics2D g);
private final void preInit() {
// Set turning to be independent
this.setAdjustGunForRobotTurn(true);
this.setAdjustRadarForRobotTurn(true);
this.setAdjustRadarForGunTurn(true);
// Set up rules class
rules = new Rules(this);
// Start up staticsaver
StaticSaver.init(this);
// Set up actors
gunActor = new GunActor(this);
movementActor = new MovementActor(this);
radarActor = new RadarActor(this);
broadcastActor = new BroadcastActor(this);
}
private void ensureVersion() {
if (getTime() < 2) {
boolean gotstatus = false;
for (Event event : events) {
if (event instanceof robocode.StatusEvent)
gotstatus = true;
if (event instanceof robocode.DeathEvent)
gotstatus = true;
if (event instanceof robocode.WinEvent)
gotstatus = true;
}
// If we didn't get a StatusEvent DeathEvent, or WinEvent something is wrong... (i.e. very old robocode version)
if (!gotstatus) {
System.out.println("Got no status event! Dying now! :(");
while (true);
}
}
}
private boolean running = false;
@Override
public void run() {
if (running)
throw new UnsupportedOperationException("Main loop already running!");
running = true;
preInit();
init();
while(true) {
if (events.size() != 0) {
ensureVersion();
runTick(getEvents());
}
execute();
}
}
@Override
public void onPaint(Graphics2D g) {
if (events.size() != 0) {
ensureVersion();
runTick(getEvents());
}
_onPaint(g);
}
}
Rules.java
package ags.muse.base;
import robocode.TeamRobot;
/**
* A consoladated "Rules" class, which includes gun cooling rate, field size,
* teammate listings, and always uses radians.
*
* Essentially stores all battle information that is known from the very start
* of the battle that does not change.
*
* @author Alexander Schultz
*/
public class Rules {
// Redirection to robocode.Rules
public final double ACCELERATION = robocode.Rules.ACCELERATION;
public final double DECELERATION = robocode.Rules.DECELERATION;
public final double GUN_TURN_RATE = robocode.Rules.GUN_TURN_RATE_RADIANS;
public final double MAX_BULLET_POWER = robocode.Rules.MAX_BULLET_POWER;
public final double MAX_TURN_RATE = robocode.Rules.MAX_TURN_RATE_RADIANS;
public final double MAX_VELOCITY = robocode.Rules.MAX_VELOCITY;
public final double MIN_BULLET_POWER = robocode.Rules.MIN_BULLET_POWER;
public final double RADAR_SCAN_RADIUS = robocode.Rules.RADAR_SCAN_RADIUS;
public final double RADAR_TURN_RATE = robocode.Rules.RADAR_TURN_RATE_RADIANS;
public final double ROBOT_HIT_BONUS = robocode.Rules.ROBOT_HIT_BONUS;
public final double ROBOT_HIT_DAMAGE = robocode.Rules.ROBOT_HIT_DAMAGE;
public double getBulletDamage(double bulletPower) { return robocode.Rules.getBulletDamage(bulletPower); }
public double getBulletHitBonus(double bulletPower) { return robocode.Rules.getBulletHitBonus(bulletPower); }
public double getBulletSpeed(double bulletPower) { return robocode.Rules.getBulletSpeed(bulletPower); }
public double getGunHeat(double bulletPower) { return robocode.Rules.getGunHeat(bulletPower); }
public double getTurnRate(double velocity) { return robocode.Rules.getTurnRateRadians(velocity); }
public double getWallHitDamage(double velocity) { return robocode.Rules.getWallHitDamage(velocity); }
// New features
public final double GUN_COOLING_RATE;
public final double BATTLEFIELD_WIDTH;
public final double BATTLEFIELD_HEIGHT;
public final String[] TEAMMATES;
public final int ENEMIES;
public final String NAME;
public Rules(TeamRobot peer) {
GUN_COOLING_RATE = peer.getGunCoolingRate();
BATTLEFIELD_WIDTH = peer.getBattleFieldWidth();
BATTLEFIELD_HEIGHT = peer.getBattleFieldHeight();
if (peer.getTeammates() != null)
TEAMMATES = peer.getTeammates();
else
TEAMMATES = new String[0];
NAME = peer.getName();
ENEMIES = peer.getOthers()-TEAMMATES.length;
}
public boolean isTeammate(String name) {
if (TEAMMATES == null)
return false;
for (String teammate : TEAMMATES) {
if (teammate.equals(name)) return true;
}
return false;
}
public double damageToBulletPower(double energy) {
if (energy/4 <= 1)
return energy/4;
else
return (energy+2)/6;
}
public double getHitRegneration(double bulletPower) {
return 3*bulletPower;
}
}
StaticSaver.java
package ags.muse.base;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import robocode.AdvancedRobot;
import robocode.RobocodeFileOutputStream;
public class StaticSaver {
private static File dataDirectory;
public static void init(AdvancedRobot bot) {
dataDirectory = bot.getDataDirectory();
System.out.println("Bot data directory:");
System.out.print("\t");
System.out.println(dataDirectory.getAbsolutePath());
}
public static RobocodeFileOutputStream getOutputFile(String filename, boolean append) throws IOException {
if (dataDirectory == null)
throw new java.lang.IllegalStateException();
File file = new File(dataDirectory, filename);
RobocodeFileOutputStream fileWriter = new RobocodeFileOutputStream(file.getPath(), append);
return fileWriter;
}
public static FileInputStream getInputFile(String filename) throws IOException {
if (dataDirectory == null)
throw new java.lang.IllegalStateException();
File file = new File(dataDirectory, filename);
return new FileInputStream(file);
}
}
BroadcastActor.java
package ags.muse.base.actors;
import robocode.TeamRobot;
public class BroadcastActor {
private final TeamRobot peer;
public BroadcastActor(TeamRobot peer) {
this.peer = peer;
}
public void broadcastMessage(java.io.Serializable s) {
try {
peer.broadcastMessage(s);
} catch (java.io.IOException e) {
System.out.println("Error during sending team message!");
e.printStackTrace();
}
}
}
GunActor.java
package ags.muse.base.actors;
import robocode.Bullet;
import robocode.TeamRobot;
public class GunActor {
private final TeamRobot peer;
public GunActor(TeamRobot peer) {
this.peer = peer;
}
public Bullet setFire(double arg0) {
return peer.setFireBullet(arg0);
}
public void setTurnGun(double arg0) {
peer.setTurnGunRightRadians(arg0);
}
}
MovementActor.java
package ags.muse.base.actors;
import robocode.TeamRobot;
public class MovementActor {
private final TeamRobot peer;
public MovementActor(TeamRobot peer) {
this.peer = peer;
}
public void setMove(double velocity) {
setMove(velocity, velocity==0 ? 0 : (velocity > 0 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY));
}
public void setMove(double velocity, double dist) {
peer.setMaxVelocity(Math.abs(velocity));
peer.setAhead(dist);
}
public void setTurnBody(double arg0) {
peer.setTurnRightRadians(arg0);
}
}
RadarActor.java
package ags.muse.base.actors;
import robocode.TeamRobot;
public class RadarActor {
private final TeamRobot peer;
public RadarActor(TeamRobot peer) {
this.peer = peer;
}
public void setTurnRadar(double arg0) {
peer.setTurnRadarRightRadians(arg0);
}
}