Last active
June 18, 2017 17:57
-
-
Save npruehs/e663c7be3efa27e93a8b557172475154 to your computer and use it in GitHub Desktop.
Animal AI that tries to stay alive and healthy.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class NicksBrain extends Brain | |
{ | |
// How far we're looking around for things like plants. | |
// Higher view range means better awareness of the environment, but also higher energy cost. | |
// Note that this is still capped by maxViewRange of the creature. | |
private static final int VIEW_RANGE = 2; | |
// Energy level that is considered healthy. | |
// If we're falling below this threshold, we'll run away and look for food. | |
private static final float HEALTHY_ENERGY_LEVEL = 0.8f; | |
// Die to roll, in order to move in random directions. | |
private java.util.Random random; | |
public void init() { | |
// Load image. | |
this.creature.setCreatureImage("kangaroo.png"); | |
// Setup die. | |
this.random = new java.util.Random(); | |
} | |
public String getName() { | |
return "Nick"; | |
} | |
public void think() { | |
// Check current energy level. | |
int currentEnergy = this.creature.getEnergy(); | |
int maxEnergy = this.creature.getMaxEnergy(); | |
float energyLevel = (float)currentEnergy / maxEnergy; | |
// Examine environment. | |
Thing[] nearbyThings = this.creature.lookAround(VIEW_RANGE); | |
// Are we healty enough? | |
if (energyLevel > HEALTHY_ENERGY_LEVEL) { | |
// Yes. If there's a bear nearby and alive, attack it. | |
for (int i = 0; i < nearbyThings.length; ++i) { | |
Thing t = nearbyThings[i]; | |
if (this.canAttack(t)) { | |
this.creature.attack(t); | |
this.creature.say("Attacked bear!"); | |
return; | |
} | |
} | |
} | |
// If we're unhealthy, or no bear is nearby, look for food. | |
for (int i = 0; i < nearbyThings.length; ++i) { | |
Thing t = nearbyThings[i]; | |
if (this.canEat(t)) { | |
// If we're at a plant, eat it. | |
this.creature.eat(); | |
this.creature.say("Ate plant."); | |
return; | |
} | |
} | |
for (int i = 0; i < nearbyThings.length; ++i) { | |
Thing t = nearbyThings[i]; | |
if (t.getType() == Thing.PLANT) { | |
// Move towards plant. | |
this.moveTowards(t); | |
this.creature.say("Moved towards nearby plant."); | |
return; | |
} | |
} | |
// There's no plant in sight, just move somewhere. | |
// Make a list of all nearby destinations. | |
java.util.ArrayList<Point> possibleDestinations = new java.util.ArrayList<Point>(); | |
possibleDestinations.add(new Point(this.creature.getX() + 1, this.creature.getY())); | |
possibleDestinations.add(new Point(this.creature.getX() - 1, this.creature.getY())); | |
possibleDestinations.add(new Point(this.creature.getX(), this.creature.getY() + 1)); | |
possibleDestinations.add(new Point(this.creature.getX(), this.creature.getY() - 1)); | |
// Try each possible destination, one after another, in random order. | |
while (possibleDestinations.size() > 0) { | |
int randomDestinationIndex = random.nextInt(possibleDestinations.size()); | |
Point randomDestination = possibleDestinations.get(randomDestinationIndex); | |
if (this.canMoveTowards(randomDestination.x, randomDestination.y, nearbyThings)) { | |
this.moveTowards(randomDestination.x, randomDestination.y); | |
this.creature.say("Moved in random direction."); | |
return; | |
} | |
possibleDestinations.remove(randomDestinationIndex); | |
} | |
// We're stuck. Pass the turn. | |
this.creature.say("Can't move anywhere!"); | |
} | |
private boolean canEat(Thing t) { | |
return t.getType() == Thing.PLANT && getDistanceTo(t) == 0; | |
} | |
private boolean canAttack(Thing t) { | |
return t.getType() == Thing.BEAR && t.getEnergy() > 0 && getDistanceTo(t) == 1; | |
} | |
private int getDistanceTo(Thing t) { | |
return getDistanceTo(t.getX(), t.getY()); | |
} | |
private int getDistanceTo(int otherX, int otherY) { | |
int thisX = this.creature.getX(); | |
int thisY = this.creature.getY(); | |
return Math.abs(thisX - otherX) + Math.abs(thisY - otherY); | |
} | |
private void moveTowards(Thing t) { | |
moveTowards(t.getX(), t.getY()); | |
} | |
private void moveTowards(int destinationX, int destinationY) { | |
int currentX = this.creature.getX(); | |
int currentY = this.creature.getY(); | |
if (currentX < destinationX) { | |
this.creature.move(EAST); | |
} else if (currentX > destinationX) { | |
this.creature.move(WEST); | |
} else if (currentY < destinationY) { | |
this.creature.move(SOUTH); | |
} else if (currentY > destinationY) { | |
this.creature.move(NORTH); | |
} | |
} | |
private boolean canMoveTowards(int destinationX, int destinationY, Thing[] knownThings) { | |
// Check if we know any thing that might be blocking our way. | |
for (int i = 0; i < knownThings.length; ++i) { | |
Thing t = knownThings[i]; | |
if (t.getX() == destinationX && t.getY() == destinationY && t.getType() != Thing.PLANT) { | |
// There's a thing at the destination, and it's not a plant. Won't move there. | |
return false; | |
} | |
} | |
return true; | |
} | |
private class Point | |
{ | |
public int x; | |
public int y; | |
public Point(int x, int y) { | |
this.x = x; | |
this.y = y; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment