package rts.units;
import rts.PhysicalGameState;
/**
* \brief This is an action that a unit can take
* @author Jeff Bernard
*
*/
public class UnitAction {
public static final int NONE = 0;
public static final int MOVE = 1; /**< action type */
public static final int ATTACK = 2; /**< action type */
public static final int HARVEST = 3; /**< action type */
public static final int RETURN = 4; /**< action type */
public static final int BUILD = 5; /**< action type */
public static final int UPGRADE = 6;
public static final int ATTACK_KILL = 7;
public static final int DEFAULT_COOLDOWN = 2; /**< the default time for an action */
private long timestamp; /**< when this action was issued */
private int type; /**< what type of move this is */
private long unitID; /**< the id of the unit this is for */
private int targetX; /**< where this action culminates */
private int targetY; /**< where this action culminates */
private int build; /**< what to build */
private int cooldown; /**< how long this action has before it goes */
private boolean is_ready; /**< whether or not this action is ready to execute */
private boolean isValidated; /**< whether or not this action has been validated as legal */
/**
* Constructs a new unit action
* @param unit the unit this action is for
* @param action_type what type of action this
* @param target_x x target coordinate
* @param target_y y target coordinate
* @param production (only for action_type == BUILD) what to build
*/
public UnitAction(Unit unit, int action_type, int target_x, int target_y, int production) {
this(unit.getID(), action_type, target_x, target_y, production);
}
private UnitAction(long id, int action_type, int target_x, int target_y, int production) {
unitID = id;
type = action_type;
targetX = target_x;
targetY = target_y;
build = production;
isValidated = false;
is_ready = false;
}
public UnitAction(UnitStats unit, int action_type, int target_x, int target_y, int production) {
unitID = unit.id;
type = action_type;
targetX = target_x;
targetY = target_y;
build = production;
isValidated = false;
is_ready = false;
}
/**
* Gets type
* @return
*/
public int getType() {
return type;
}
/**
* Gets target x
* @return
*/
public int getTargetX() {
return targetX;
}
/**
* Gets target y
* @return
*/
public int getTargetY() {
return targetY;
}
/**
* Gets build
* @return
*/
public int getBuild() {
return build;
}
/**
* Returns the timestamp for this action
* @return timestamp
*/
public long getTimestamp() {
return timestamp;
}
/**
* Sets the timestamp to now
*/
public void setTimestamp() {
timestamp = System.currentTimeMillis();
}
/**
* Returns the unit ID
* @return
*/
public long getUnitID() {
return unitID;
}
/**
* Returns whether or not this action is ready to execute
* @return
*/
public boolean ready() {
boolean ret = is_ready;
is_ready = false;
return ret;
}
public boolean cooldown() {
return(--cooldown<=0);
}
/**
* Validates this action as legal or not
* @param unit the unit who is doing this action
* @param pgs the game state
* @return
*/
public boolean validate(UnitStats unit, PhysicalGameState pgs) {
if (isValidated) {
return true;
}
is_ready = true;
if (unit.id == unitID) {
cooldown = DEFAULT_COOLDOWN;
switch (type) {
case MOVE:
cooldown = unit.definition.move_speed;
isValidated = true;
break;
case ATTACK:
cooldown = unit.definition.attack_speed;
isValidated = true;
break;
case HARVEST:
cooldown = pgs.harvestTime(targetX, targetY);
isValidated = true;
break;
case RETURN:
isValidated = true;
break;
case BUILD:
cooldown = pgs.buildTime(unit.player, !unit.definition.is_building, build);
isValidated = true;
break;
case UPGRADE:
cooldown = pgs.upgradeTime(unit.player, build);
isValidated = true;
break;
}
}
return isValidated;
}
/**
* Executes this action
* @param unit the unit this action is for
* @param pgs the phsyical game state
* @return whether or not this action succeeded
*/
public boolean execute(UnitStats unit, PhysicalGameState pgs) {
// obviously, but no harm checking for the umpteenth time
if (unit.id == unitID) {
boolean result = false;
switch (type) {
case MOVE:
result = pgs.moveUnit(unit, targetX, targetY);
break;
case ATTACK:
result = pgs.attackUnit(unit, targetX, targetY);
break;
case HARVEST:
result = pgs.harvestUnit(unit, targetX, targetY);
break;
case RETURN:
result = pgs.returnUnitHarvest(unit, targetX, targetY);
break;
case BUILD:
result = pgs.buildUnit(unit, targetX, targetY, build);
if (!result) {
//pgs.restoreResources(unit.player, !unit.definition.is_building, build);
}
break;
case UPGRADE:
result = pgs.upgradeUnits(unit.player, build);
break;
}
//if (!result) { System.out.println(targetX+"x"+targetY);System.exit(-1);}
unit.last_action_success = result;
// if (!result) {
// System.out.println(unit.definition.label+"("+unit.id+") failed to execute action of type: "+type);
// }
return result;
}
return false;
}
/**
* Compares two actions to see if they are equal
* @param other the other action to compare with
* @return true or false
*/
public boolean equals(UnitAction other) {
return(unitID == other.unitID && type == other.type && targetX == other.targetX && targetY == other.targetY && build == other.build);
}
public UnitAction copy() {
return new UnitAction(unitID, type, targetX, targetY, build);
}
public String toString() {
return type+" => "+targetX+"x"+targetY+" ("+build+")";
}
}