Robocode

Aprendendo a guerrear em java
PET Teleinformática @ 2015
http://www.peteti.ufc.br
Agenda
- zz
Indo além de simples robôs
- Robôs basicos
public class Freyja extends Robot {- Robôs avançados
public class Freyja extends AdvancedRobot {Indo além de simples robôs

Realizando Ações Simultâneas
- AdvancedRobot
- Possibilidade de realizar ações em cada turno
- Blocking Methods não nos dá o poder de controlar
- Turno no robocode é chamado de pulso
- Note que AdvancedRobot é na verdade uma subclasse de Robot
Realizando Ações Simultâneas
- E como controlamos o robô durante um pulso?
- Primeiro, devemos realizar que todos os métodos utilizados até agora são Blocking Methods
- Agora, como Freyja é uma subclasse de AdvancedRobot
nós podemos utilizar os novos tipos de métodos, os
Non-Blocking
Realizando Ações Simultâneas

Realizando Ações Simultâneas
public class Freyja extends AdvancedRobot {
...
public void run() {
...
setTurnRight(fullTurn);
setAhead(veryFar);
setTurnGunLeft(fullTurn);
}Realizando Ações Simultâneas
- Non-Blocking Methods não retornam o poder para o Robocode
- Necessidade de um blocking-method ou execute()
Realizando Ações Simultâneas
public class Freyja extends AdvancedRobot {
...
public void run() {
...
setTurnRight(fullTurn);
setAhead(veryFar);
setTurnGunLeft(fullTurn);
execute()
}Realizando Ações Simultâneas
public class Freyja extends AdvancedRobot {
...
public void run() {
...
while(true) {
waitFor(new TurnCompleteCondition(this));
toggleDirection();
}
}Realizando Ações Simultâneas
public class Freyja extends AdvancedRobot {
private void toggleDirection() {
if (clockwise) {
setTurnLeft(fullTurn);
setBack(veryFar);
setTurnGunRight(fullTurn);
} else {
setTurnRight(fullTurn);
setAhead(veryFar);
setTurnGunLeft(fullTurn);
}
clockwise = ! clockwise;
}Eventos Customizados
- Observações:
- heading : ângulo absoluto com 0º apontado para cima 0 <= heading <= 360
- bearing: ângulo relativo à algum objeto que o robô está observando ~ -180 <= bearing <= 180
- Todas as coordenadas são expressas em (x,y)
- Todas as coordenadas são positivas
- A origem (0,0) é no canto inferior esquerdo
- X é positivo para direita
- Y é positivo para cima
Eventos Customizados
- Exemplo:
public void onHitByBullet (HitByBulletEvent e) {
turnLeft(90 - e.getBearing());
}- Acesso à documentação:
- Help -> Robocode API
Eventos Customizados
- Eventos conhecidos:
- onBulletHit()
- onBulletHitBullet()
- onBulletMissed()
- onDeath()
- onHitByBullet()
- onHitWall()
- onRobotDeath()
- onScannedRobot()
- onWin()
Eventos Customizados
- centerRobot()
public void onHitWall(HitWallEvent ev) {
centerRobot();
}
private void centerRobot() {
double width, height, x, y;
height= this.getBattleFieldHeight();
width = this.getBattleFieldWidth();
y = this.getY();
x = this.getX();
if (x > width/2)
turnRight(threeQuarterTurn - getHeading());
else
turnRight(quarterTurn - getHeading());
ahead(Math.abs(width/2 - x));
if (y < height/2)
turnLeft(getHeading());
else
turnRight(halfTurn - getHeading());
ahead(Math.abs(height/2 - y));
}Localização do Alvo
- Os três principais novos recursos providos por AdvancedRobot são:
- Carregar múltiplos movimentos simultaneamente
- Decidir a ação do robô ou estratégia em tempo real
- Definir e lidar com eventos customizados
Interfaces e Classes Internas
Localização do Alvo
Interfaces e Classes Internas
public class DuckSeekerBot extends AdvancedRobot implements DuckConstants
{
boolean targetLocked = false;
Target curTarget = null;
public void run() {
setColors(Color.red,Color.green,Color.red);
setTurnRadarRight(oneRev);
while(true) {
if (curTarget != null) {
if (curTarget.isAlive() && curTarget.isLocked()) {
fire(2);
}
}
execute();
}
}Localização do Alvo
Interfaces e Classes Internas
class Target {
...
public Target(String inname, boolean inalive, boolean inlocked) {
...
}
public boolean isAlive() {
...
}
public boolean isLocked() {
...
}
...
}Localização do Alvo
Interfaces e Classes Internas
stop();
turnRight(evt.getBearing());
if (evt.getDistance() > safeDistance)
ahead(evt.getDistance() - safeDistance);
if(curTarget != null) {
if (curTarget.getName().equals(evt.getName()))
return;
}
curTarget = new Target(evt.getName(), true, true);Localização do Alvo
Interfaces e Classes Internas
class Target {
private String name = null;
private boolean locked = false;
private boolean alive = false;
public Target(String inname, boolean inalive, boolean inlocked) {
setName(inname);
setAlive(inalive);
setLocked(inlocked);
}
public boolean isAlive() {
return alive;
}
public boolean isLocked() {
return locked;
}
public void setAlive( boolean inalive) {
alive = inalive;
}
public void setLocked( boolean inlocked) {
locked = inlocked;
}
public String getName() {
return name;
}
public void setName(String inName) {
name = inName;
}
}
}Robôs Já Conhecidos
Crazy
public class Crazy extends AdvancedRobot {
boolean movingForward;
public void run() {
// Set colors
setBodyColor(new Color(0, 200, 0));
setGunColor(new Color(0, 150, 50));
setRadarColor(new Color(0, 100, 100));
setBulletColor(new Color(255, 255, 100));
setScanColor(new Color(255, 200, 200));
// Loop forever
while (true) {
// Tell the game we will want to move ahead 40000 -- some large number
setAhead(40000);
movingForward = true;
// Tell the game we will want to turn right 90
setTurnRight(90);
waitFor(new TurnCompleteCondition(this));
// Note: We are still moving ahead now, but the turn is complete.
// Now we'll turn the other way...
setTurnLeft(180);
// ... and wait for the turn to finish ...
waitFor(new TurnCompleteCondition(this));
// ... then the other way ...
setTurnRight(180);
// .. and wait for that turn to finish.
waitFor(new TurnCompleteCondition(this));
// then back to the top to do it all again
}
}Robôs Já Conhecidos
Crazy
public void onHitWall(HitWallEvent e) {
// Bounce off!
reverseDirection();
}
/**
* reverseDirection: Switch from ahead to back & vice versa
*/
public void reverseDirection() {
if (movingForward) {
setBack(40000);
movingForward = false;
} else {
setAhead(40000);
movingForward = true;
}
}
public void onScannedRobot(ScannedRobotEvent e) {
fire(1);
}
public void onHitRobot(HitRobotEvent e) {
// If we're moving the other robot, reverse!
if (e.isMyFault()) {
reverseDirection();
}
}
}
Robôs Já Conhecidos
Walls
public class Walls extends Robot {
boolean peek; // Don't turn if there's a robot there
double moveAmount; // How much to move
/**
* run: Move around the walls
*/
public void run() {
...
Robôs Já Conhecidos
Walls
public void run() {
// Set colors
setBodyColor(Color.black);
setGunColor(Color.black);
setRadarColor(Color.orange);
setBulletColor(Color.cyan);
setScanColor(Color.cyan);
// Initialize moveAmount to the maximum possible for this battlefield.
moveAmount = Math.max(getBattleFieldWidth(), getBattleFieldHeight());
// Initialize peek to false
peek = false;
// turnLeft to face a wall.
// getHeading() % 90 means the remainder of
// getHeading() divided by 90.
turnLeft(getHeading() % 90);
ahead(moveAmount);
// Turn the gun to turn right 90 degrees.
peek = true;
turnGunRight(90);
turnRight(90);
while (true) {
// Look before we turn when ahead() completes.
peek = true;
// Move up the wall
ahead(moveAmount);
// Don't look now
peek = false;
// Turn to the next wall
turnRight(90);
}
}Robôs Já Conhecidos
Walls
public void onHitRobot(HitRobotEvent e) {
// If he's in front of us, set back up a bit.
if (e.getBearing() > -90 && e.getBearing() < 90) {
back(100);
} // else he's in back of us, so set ahead a bit.
else {
ahead(100);
}
}
public void onScannedRobot(ScannedRobotEvent e) {
fire(2);
// Note that scan is called automatically when the robot is moving.
// By calling it manually here, we make sure we generate another scan event if there's a robot on the next
// wall, so that we do not start moving up it until it's gone.
if (peek) {
scan();
}
}
}
Robôs Já Conhecidos
Tracker
public class Tracker extends Robot {
int count = 0; // Keeps track of how long we've
// been searching for our target
double gunTurnAmt; // How much to turn our gun when searching
String trackName; // Name of the robot we're currently tracking
public void run() {
...Robôs Já Conhecidos
Tracker
public void run() {
// Set colors
setBodyColor(new Color(128, 128, 50));
setGunColor(new Color(50, 50, 20));
setRadarColor(new Color(200, 200, 70));
setScanColor(Color.white);
setBulletColor(Color.blue);
// Prepare gun
trackName = null; // Initialize to not tracking anyone
setAdjustGunForRobotTurn(true); // Keep the gun still when we turn
gunTurnAmt = 10; // Initialize gunTurn to 10
// Loop forever
while (true) {
// turn the Gun (looks for enemy)
turnGunRight(gunTurnAmt);
// Keep track of how long we've been looking
count++;
// If we've haven't seen our target for 2 turns, look left
if (count > 2) {
gunTurnAmt = -10;
}
// If we still haven't seen our target for 5 turns, look right
if (count > 5) {
gunTurnAmt = 10;
}
// If we *still* haven't seen our target after 10 turns, find another target
if (count > 11) {
trackName = null;
}
}
}
Robôs Já Conhecidos
Tracker
public void onScannedRobot(ScannedRobotEvent e) {
// If we have a target, and this isn't it, return immediately
// so we can get more ScannedRobotEvents.
if (trackName != null && !e.getName().equals(trackName)) {
return;
}
// If we don't have a target, well, now we do!
if (trackName == null) {
trackName = e.getName();
out.println("Tracking " + trackName);
}
// This is our target. Reset count (see the run method)
count = 0;
// If our target is too far away, turn and move toward it.
if (e.getDistance() > 150) {
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
turnGunRight(gunTurnAmt); // Try changing these to setTurnGunRight,
turnRight(e.getBearing()); // and see how much Tracker improves...
// (you'll have to make Tracker an AdvancedRobot)
ahead(e.getDistance() - 140);
return;
}
// Our target is close.
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
turnGunRight(gunTurnAmt);
fire(3);
// Our target is too close! Back up.
if (e.getDistance() < 100) {
if (e.getBearing() > -90 && e.getBearing() <= 90) {
back(40);
} else {
ahead(40);
}
}
scan();
}
Robôs Já Conhecidos
Tracker
public void onHitRobot(HitRobotEvent e) {
// Only print if he's not already our target.
if (trackName != null && !trackName.equals(e.getName())) {
out.println("Tracking " + e.getName() + " due to collision");
}
// Set the target
trackName = e.getName();
// Back up a bit.
// Note: We won't get scan events while we're doing this!
// An AdvancedRobot might use setBack(); execute();
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
turnGunRight(gunTurnAmt);
fire(3);
back(50);
}Robôs Já Conhecidos
Corners
public class Corners extends Robot {
int others; // Number of other robots in the game
static int corner = 0; // Which corner we are currently using
// static so that it keeps it between rounds.
boolean stopWhenSeeRobot = false; // See goCorner()
public void run() {
// Save # of other bots
others = getOthers();
// Move to a corner
goCorner();
// Initialize gun turn speed to 3
int gunIncrement = 3;
// Spin gun back and forth
while (true) {
for (int i = 0; i < 30; i++) {
turnGunLeft(gunIncrement);
}
gunIncrement *= -1;
}
}
Robôs Já Conhecidos
Corners
/**
* goCorner: A very inefficient way to get to a corner. Can you do better?
*/
public void goCorner() {
// We don't want to stop when we're just turning...
stopWhenSeeRobot = false;
// turn to face the wall to the "right" of our desired corner.
turnRight(normalRelativeAngleDegrees(corner - getHeading()));
// Ok, now we don't want to crash into any robot in our way...
stopWhenSeeRobot = true;
// Move to that wall
ahead(5000);
// Turn to face the corner
turnLeft(90);
// Move to the corner
ahead(5000);
// Turn gun to starting point
turnGunLeft(90);
}Robôs Já Conhecidos
Corners
public void onScannedRobot(ScannedRobotEvent e) {
// Should we stop, or just fire?
if (stopWhenSeeRobot) {
// Stop everything! You can safely call stop multiple times.
stop();
// Call our custom firing method
smartFire(e.getDistance());
// Look for another robot.
// NOTE: If you call scan() inside onScannedRobot, and it sees a robot,
// the game will interrupt the event handler and start it over
scan();
// We won't get here if we saw another robot.
// Okay, we didn't see another robot... start moving or turning again.
resume();
} else {
smartFire(e.getDistance());
}
}
/**
* smartFire: Custom fire method that determines firepower based on distance.
*
* @param robotDistance the distance to the robot to fire at
*/
public void smartFire(double robotDistance) {
if (robotDistance > 200 || getEnergy() < 15) {
fire(1);
} else if (robotDistance > 50) {
fire(2);
} else {
fire(3);
}
}
}Robocode @ 2015 (#001)
By Alexandre Barroso
Robocode @ 2015 (#001)
[AVANÇADO] --
- 712