package com.cookbook.ai;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ai.fsm.DefaultStateMachine;
import com.badlogic.gdx.ai.fsm.State;
import com.badlogic.gdx.ai.fsm.StateMachine;
import com.badlogic.gdx.ai.msg.Telegram;
import com.badlogic.gdx.ai.msg.Telegraph;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.TimeUtils;
public class Caveman implements Telegraph {
private static final String TAG = "Caveman";
private StateMachine<Caveman> fsm;
private float hungry; // [0-100]
private float energy; // [0-100]
private float food; // [20-100] - pending to eat
private boolean threatened;
public enum CavemanState implements State<Caveman> {
GLOBAL_STATE() {
@Override
public void enter(Caveman caveman) {
// TODO Auto-generated method stub
}
@Override
public void update(Caveman caveman) {
// 1 in 1000
if (MathUtils.randomBoolean(0.001f) && !caveman.getFSM().isInState(PEEING)) {
caveman.say("OH! Gotta pee");
caveman.getFSM().changeState(PEEING);
}
}
@Override
public void exit(Caveman caveman) {
// TODO Auto-generated method stub
}
@Override
public boolean onMessage(Caveman entity, Telegram telegram) {
return false;
}
},
PEEING() {
@Override
public void enter(Caveman caveman) {
if(caveman.getFSM().getPreviousState().equals(RUN_TO_HOME))
caveman.say("This hiding place will lose him until I finish");
else if(caveman.getFSM().getPreviousState().equals(SLEEP))
caveman.say("****! not now please...");
else
caveman.say("I really need this");
}
@Override
public void update(Caveman caveman) {
caveman.decreaseEnergy(.005f);
caveman.increaseHungry(.01f);
caveman.getFSM().changeState(caveman.getFSM().getPreviousState());
}
@Override
public void exit(Caveman caveman) {
caveman.say("Nice, now I can carry on...");
}
@Override
public boolean onMessage(Caveman entity, Telegram telegram) {
return false;
}
},
IDLE() {
private double arrivalTime;
@Override
public void enter(Caveman caveman) {
caveman.say("Feeling great at home");
arrivalTime = TimeUtils.millis();
}
@Override
public void update(Caveman caveman) {
caveman.increaseHungry(.05f);
caveman.increaseEnergy(.001f);
// Hungry but strong enough to go hunting
if(caveman.hungry > 20 && caveman.energy > 20) {
caveman.say("I think that I will go hunting");
caveman.getFSM().changeState(HUNTING);
}
// Tired, go to sleep
else if(caveman.energy < 40) {
caveman.say("I'm exhausted");
caveman.getFSM().changeState(SLEEP);
}
// Too long doing nothing? go sleep
else if(TimeUtils.millis()-arrivalTime > 4000) {
caveman.say("Time to sleep");
caveman.getFSM().changeState(SLEEP);
}
}
@Override
public void exit(Caveman caveman) {
caveman.say("Let's move!");
}
@Override
public boolean onMessage(Caveman entity, Telegram telegram) {
return false;
}
},
SLEEP() {
@Override
public void enter(Caveman caveman) {
caveman.say("Good night!");
}
@Override
public void update(Caveman caveman) {
caveman.increaseEnergy(.08f);
caveman.increaseHungry(.01f);
if(caveman.energy==100) {
caveman.say("(yaaaaawn) I'm a new man");
caveman.getFSM().changeState(IDLE);
}
}
@Override
public void exit(Caveman caveman) {
}
@Override
public boolean onMessage(Caveman entity, Telegram telegram) {
return false;
}
},
HUNTING() {
@Override
public void enter(Caveman caveman) {
if(caveman.getFSM().getPreviousState().equals(PEEING))
caveman.say("Where are you my little deer?");
else if(caveman.hungry > 50)
caveman.say("I should take my best spear today");
else
caveman.say("I'm a little fat to go hunting now but I feel like eating a good deer");
}
@Override
public void update(Caveman caveman) {
caveman.increaseHungry(.01f);
caveman.decreaseEnergy(.05f);
// 1 in 250
if (MathUtils.randomBoolean(0.004f)) {
caveman.say("Hey! I got a rabbit, I better go home to cook it");
caveman.food = MathUtils.random(20, 100);
caveman.getFSM().changeState(RUN_TO_HOME);
}
}
@Override
public void exit(Caveman caveman) {
// TODO Auto-generated method stub
}
@Override
public boolean onMessage(Caveman entity, Telegram telegram) {
if (telegram.message == MessageType.GRRRRRRRR) {
entity.threatened = true;
entity.getFSM().changeState(RUN_TO_HOME);
return true;
}
return false;
}
},
RUN_TO_HOME() {
private double beginningTime;
@Override
public void enter(Caveman caveman) {
if(caveman.threatened)
caveman.say("OMG! This dinosaur is gonna eat me!");
else
caveman.say("It's gonna be a long way to home...");
beginningTime = TimeUtils.millis();
}
@Override
public void update(Caveman caveman) {
caveman.increaseHungry(.01f);
caveman.decreaseEnergy(.01f);
if(TimeUtils.millis() - beginningTime > 4000)
if(caveman.threatened) {
caveman.threatened = false;
caveman.getFSM().changeState(IDLE);
}
else
caveman.getFSM().changeState(EAT);
}
@Override
public void exit(Caveman caveman) {
// TODO Auto-generated method stub
caveman.say("I'm almost there...");
}
@Override
public boolean onMessage(Caveman entity, Telegram telegram) {
return false;
}
},
EAT() {
@Override
public void enter(Caveman caveman) {
if(caveman.food > 50)
caveman.say("I will fill up with this meal");
else
caveman.say("It's gonna be a good snack");
}
@Override
public void update(Caveman caveman) {
caveman.decreaseEnergy(.005f);
caveman.say("Yummy yummy!!");
caveman.decreaseHungry(caveman.food);
caveman.food=0;
caveman.getFSM().changeState(IDLE);
}
@Override
public void exit(Caveman caveman) {
caveman.say("It was delicious!");
}
@Override
public boolean onMessage(Caveman entity, Telegram telegram) {
return false;
}
};
}
public Caveman() {
fsm = new DefaultStateMachine<Caveman> (this, CavemanState.IDLE);
hungry = MathUtils.random(0, 100);
energy = MathUtils.random(0, 100);
threatened = false;
fsm.setGlobalState(CavemanState.GLOBAL_STATE);
}
public StateMachine<Caveman> getFSM() {
return fsm;
}
public void update(float delta) {
fsm.update();
}
public void increaseEnergy(float value) {
energy = MathUtils.clamp(energy+value, 0, 100);
}
public void decreaseEnergy(float value) {
energy = MathUtils.clamp(energy-value, 0, 100);
}
public void increaseHungry(float value) {
hungry = MathUtils.clamp(hungry+value, 0, 100);
}
public void decreaseHungry(float value) {
hungry = MathUtils.clamp(hungry-value, 0, 100);
}
private void say(String thought) {
Gdx.app.log(TAG, thought);
}
@Override
public boolean handleMessage(Telegram msg) {
return fsm.handleMessage(msg);
}
}