/**
*
*/
package org.timerescue.element.agent;
import java.util.Vector;
import org.timerescue.action.Action;
import org.timerescue.action.ActionFactory;
import org.timerescue.action.DefaultAttackAction;
import org.timerescue.action.ExecutionContext;
import org.timerescue.action.ExecutionContextFactory;
import org.timerescue.action.InvalidContextSource;
import org.timerescue.action.WanderAction;
import org.timerescue.element.Element;
import org.timerescue.enviroment.ActionExecuter;
import org.timerescue.enviroment.Environment;
import org.timerescue.exception.InvalidPropertyException;
import org.timerescue.exception.InvalidSerialException;
import org.timerescue.information.InformationParameters;
import org.timerescue.information.Serializable;
/**
* @author chamanx
* TODO Put it back to abstract and send the non player logic to a new agent
*/
public class Agent extends Element
implements DecisionMaker, DecisionReciever, ActionExecuter{
/*
* Attributes
*/
/**
* Aviable Skills and actions to execute
*/
private Vector<Action> skills;
/**
* Environment information limited to visibility
*/
private Element[] surroundings;
/**
* states, conditions
*/
private StateHolder state_holder;
/**
* properties
*/
private PropertyHolder property_holder;
/**
* Context
*/
private ExecutionContext context;
/**
* Is player controlled by the player?
*/
private boolean player_controlled;
/*
* Methods
*/
//@Inject
/**
* Default Constructor
*/
public Agent() {
// TODO Auto-generated constructor stub
}
/**
* Constructor that ask for the race, skills, default properties
* @param race
* @param skills
* @param default_properties
*/
public Agent(
Race race,
Vector<Action> skills,
Properties default_properties) {
init(race, skills, default_properties);
}
/**
* @return the player_controlled
*/
private boolean isPlayer_controlled() {
return player_controlled;
}
/**
* Initialize the agent attributes
* @param race
* @param skills2
* @param default_properties
*/
private void init(
Race race,
Vector<Action> skills2,
Properties default_properties) {
try {
setSkills(skills);
//It is created in a clean state
setState_holder(new StateHolder());
property_holder = new PropertyHolder();
property_holder.setDefaultProperties(default_properties);
surroundings = null;
setContext(ExecutionContextFactory.getInstance(Agent.class));
// Apply Race's passive Skills
loadRace(race);
} catch (InvalidContextSource e) {
// TODO Log this
}
}
/**
* Load race passive skills
* @param race
*/
protected void loadRace(Race race) {
Action[] skills = race.getPassive_skills();
for (int i = 0; i < skills.length; i++) {
Action skill = skills[i];
executeAction(skill);
}
}
/**
* @return the context
*/
public ExecutionContext getContext() {
return context;
}
/**
* @param context the context to set
*/
private void setContext(ExecutionContext context) {
this.context = context;
}
/**
* An information is received, if it is an action it's executed
* if not it's set as the surroundings attribute
* @param parameters the surroundings to set or the action to
* execute
*/
public void setSorroundings(InformationParameters parameters) {
this.surroundings = readSurroundings(parameters);
}
/**
* @return the Properties contained in the stateHolder
*/
public StateHolder getStateHolder() {
return this.state_holder;
}
/**
* @return the skills
*/
public Vector<Action> getSkills() {
return skills;
}
/**
* @param skills the skills to set
*/
public void setSkills(Vector<Action> skills) {
this.skills = skills;
}
/**
* @return the state_holder
*/
public StateHolder getState_holder() {
return state_holder;
}
/**
* @param state_holder the state_holder to set
*/
public void setState_holder(StateHolder state_holder) {
this.state_holder = state_holder;
}
/**
* @return the property_holder
*/
public PropertyHolder getProperty_holder() {
return property_holder;
}
/**
* @param property_holder the property_holder to set
*/
public void setProperty_holder(PropertyHolder property_holder) {
this.property_holder = property_holder;
}
/*
* Wander method Wraps AI definition methods
*/
public Action decide() {
Action wander_action = null;
//Check if any prolonged states remains
//Tell if agent is been controlled by a player
if(isPlayer_controlled()){
//listen to new events from player
wander_action = decidePlayer();
}else{
//AI wander method decide about the action to take
wander_action = decideNonePlayer();
}
return wander_action;
}
/* (non-Javadoc)
* @see org.timerescue.droid.element.agent.DecisionReciever#wanderPlayer()
*/
@Override
public Action decidePlayer() {
// TODO establish the listener or simply check for new events if applies
return null;
}
//TODO pass all the rules to boolean properties
/* (non-Javadoc)
* @see org.timerescue.droid.element.agent.DecisionMaker#wanderNonePlayer()
*/
@Override
public Action decideNonePlayer() {
Action decision = null;
String aggressiveness = property_holder.getCurrentProperty(
Constants.Property.AGGRESSIVENESS);
//TODO pass this to behaviors
//Getting environment information
//I am already attacking? or am i the target?
if (state_holder.isStateActive(DefaultAttackAction.class)){
DefaultAttackAction attack = (DefaultAttackAction) state_holder.getState(
DefaultAttackAction.class);
Agent target = attack.getTarget();
//Counter attack if it is the target
decision = attack(target);
//If the target couldn't be reached remove states
if(decision.equals(null)){
attack.removeStates();
}
}else{
//Is it aggressive?
if (Boolean.parseBoolean(aggressiveness)){
decision = attack();
}else{
//Wander
decision = ActionFactory.getInstance(WanderAction.class);
}
}
executeAction(decision);
return decision;
}
/**
* Attack : aggressive behavior towards any low life target
* @return
*/
private Action attack() {
// TODO Check on other skills and see how to attack
DefaultAttackAction attack = getAttack();
//Looking for other agents
Element element;
Agent target = null, temp = null;
int target_life, temp_life;
for (int i = 0; i < surroundings.length; i++) {
element = surroundings[i];
if (element instanceof Agent){
//target Found!
temp = (Agent)element;
//Choose target by life
if(target!=null){
target_life = Integer.parseInt(
target.getProperty_holder().getCurrentProperty(
Constants.Property.LIFE));
temp_life = Integer.parseInt(
temp.getProperty_holder().getCurrentProperty(
Constants.Property.LIFE));
if( temp_life < target_life){
target = temp;
}
}else{
target = temp;
}
break;
}
//Other behavior rules
}
return attack(target);
}
/**
* Attack an specific target
* @param target
* @return the attack action
*/
private Action attack(Agent target) {
if(target !=null){
DefaultAttackAction attack = getAttack();
//Add target
attack.setTarget(target);
//Set attacker
attack.setAttacker(this);
return attack;
}
return null;
}
/**
* Return an appropriate attack action to be performed
* @return
*/
private DefaultAttackAction getAttack() {
// TODO Check on other skills and see how to attack
DefaultAttackAction attack =
(DefaultAttackAction) ActionFactory.getInstance(
DefaultAttackAction.class);
return attack;
}
/* (non-Javadoc)
* @see org.timerescue.element.agent.DecisionMaker#readSurroundings(
* org.timerescue.information.InformationParameters)
*/
@Override
public Element[] readSurroundings(InformationParameters information) {
// TODO Auto-generated method stub
//Ask for the list of elements received from the environment
//We assume that all information are Elements
Serializable[] array_surrounds = null;
Element[] elements = new Element[0];
try {
array_surrounds = (Element[])information.getArrayParam(
Environment.Constants.SURROUND_PROPERTY).toArray();
elements = (Element[])array_surrounds;
} catch (InvalidPropertyException e) {
//TODO Ask for new parameters??
//TODO log this
}
return elements;
}
/* (non-Javadoc)
* @see org.timerescue.element.agent.DecisionMaker#executeDecision(
* org.timerescue.action.Action)
*/
@Override
public void executeDecision(Action action) {
// TODO Auto-generated method stub
executeAction(action);
}
@Override
public String toSerial() {
// TODO include local variables
return super.toSerial();
}
@Override
public void fromSerial(String serialized) throws InvalidSerialException {
// TODO include local variables
super.fromSerial(serialized);
}
/* (non-Javadoc)
* @see org.timerescue.enviroment.ActionExecutener#executeAction(org.timerescue.action.Action)
*/
@Override
public void executeAction(Action action) {
//Add states if it's not an instant action
//Execute the action
action.execute(context);
}
/**
* Get current Visibility from the property holder
* @return visibility
*/
public int getVisibility() {
return Integer.parseInt(
property_holder.getCurrentProperty(Constants.Property.VISIBILITY));
}
/**
* Get current Aggressiveness from the property holder
* @return Aggressiveness property
*/
public boolean getAggressiveness() {
return Boolean.parseBoolean(
property_holder.getCurrentProperty(Constants.Property.AGGRESSIVENESS));
}
/**
* Get current Life from the property holder
* @return life
*/
public int getLife() {
return Integer.parseInt(
property_holder.getCurrentProperty(Constants.Property.LIFE));
}
/**
* Get current Strength from the property holder
* @return strength
*/
public int getStrength() {
return Integer.parseInt(
property_holder.getCurrentProperty(Constants.Property.STRENGTH));
}
/**
* Get current Armor from the property holder
* @return armor
*/
public int getArmor() {
return Integer.parseInt(
property_holder.getCurrentProperty(Constants.Property.ARMOR));
}
/**
* Get current Speed from the property holder
* @return speed
*/
public int getSpeed() {
return Integer.parseInt(
property_holder.getCurrentProperty(Constants.Property.SPEED));
}
/**
* Sets current Life from the property holder
*/
public void setLife(int life) {
property_holder.setProperty(Constants.Property.LIFE, String.valueOf(life));
}
/*
* Constants
*/
public static class Constants{
public static class Default{
//public static final short NUMBER_OF_TARGETS = 5;
}
public static class Property{
/**
* Visibility range in distance units
*/
public static final String VISIBILITY = "VISIBILITY";
/**
* Aggressiveness Says if the agent attacks on sight
*/
public static final String AGGRESSIVENESS = "AGGRESSIVENESS";
/**
* LIFE it's the number of points
* that represents being alive if it's > 0 or dead if it's = 0
*/
public static final String LIFE = "LIFE";
/**
* Strength determines physical power of the agent
*/
public static final String STRENGTH = "STRENGTH";
/**
* Defense is the resistance to physical attacks,
* it is determined by the equipment
*/
public static final String ARMOR = "ARMOR";
/**
* Move speed
*/
public static final String SPEED = "SPEED";
}
}
}