/**
*
*/
package cz.cuni.mff.abacs.burglar.logics.objects.agents;
import cz.cuni.mff.abacs.burglar.logics.DataMap;
import cz.cuni.mff.abacs.burglar.logics.objects.BaseInterface;
import cz.cuni.mff.abacs.burglar.logics.objects.BaseObject;
import cz.cuni.mff.abacs.burglar.logics.objects.Room;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Inventory;
import cz.cuni.mff.abacs.burglar.logics.objects.items.InventoryImpl;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Item;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Key;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.*;
import cz.cuni.mff.abacs.burglar.logics.planning.instructions.Instruction;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* Simple agent with the common features of all instantiated agent classes.
*
* <ul>
* <li>can move on walkable positions</li>
* <li>can pick up items</li>
* <li>can put down items</li>
* <li>can contain items</li>
* <li>can lock/unlock doors, boxes</li>
* <li>can activate/deactivate positions</li>
* </ul>
*
* @author abacs
*/
public abstract class BaseAgent extends BaseObject implements Inventory, Agent {
// -------------------------------------------------------------------------
/** The walkable position where the agent is standing.
*
* -1 means not set.
* Changeable property. */
private int _positionId = -1;
/**
* -1 means not set.
* Changeable property. */
private int _roomId = -1;
/** The state of the agent (WELL or STUNNED). */
private State _state = State.WELL;
/**
* Items are immutable.
* Changeable property. */
private final InventoryImpl _inventory =
new InventoryImpl();
/** Instruction cue to execute.
*
* Instructions are immutable.
* Changeable property. */
protected final List<Instruction> _instructions =
new ArrayList<Instruction>();
/**
* The beliefs of the agent.
*
* Changeable property. */
protected final BeliefBase _knowledge = new BeliefBase();
/**
* The goal set of the agent.
*/
protected GoalBase _goals = null;
// -------------------------------------------------------------------------
// constructors:
/**
*
*
* @param id
* @param type
* @param position
* @param goals
* @param referenceMap
*/
protected BaseAgent(
int id,
BaseObject.Type type,
Position position,
GoalBase goals,
DataMap referenceMap
) {
super(id, type, referenceMap);
this._positionId = position.getId();
// set the room if possible:
if(position.getRoom() != null)
this._roomId = position.getRoom().getId();
this._goals = goals;
}
/**
* Goals are not yet copied, it should be done in descendants.
*
* @param original
* @param referenceMap
*/
protected BaseAgent(BaseAgent original, DataMap referenceMap) {
super(original.getId(), original.getType(), referenceMap);
this._positionId = original._positionId;
this._roomId = original._roomId;
this._state = original._state;
this._inventory.copyChangeables(original._inventory);
this._instructions.clear();
for(Instruction instr : original._instructions)
this._instructions.add(instr);
this._knowledge.copyChangeables(original._knowledge);
}
// -------------------------------------------------------------------------
@Override
public Position getPosition() {
return this._referenceMap.getPosition(this._positionId);
}
@Override
public int getPositionId() {
return this._positionId;
}
@Override
public void setPosition(int walkableId) {
this._positionId = walkableId;
}
@Override
public void setPosition(Position walkable) {
this.setPosition(walkable.getId());
}
// -------------------------------------------------------------------------
// Inventory related:
@Override
public void addItem(Item item) {
this._inventory.addItem(item);
}
@Override
public void addItems(List<Item> items) {
this._inventory.addItems(items);
}
@Override
public Item removeItem(int id) {
return this._inventory.removeItem(id);
}
@Override
public boolean hasItem(int id) {
return this._inventory.hasItem(id);
}
@Override
public boolean hasItemOfType(BaseInterface.Type type) {
return this._inventory.hasItemOfType(type);
}
@Override
public int getItemIdOfType(Type type) {
return this._inventory.getItemIdOfType(type);
}
@Override
public List<Item> getItems() {
return this._inventory.getItems();
}
// -------------------------------------------------------------------------
@Override
public boolean isInState(State state) {
return this._state == state;
}
@Override
public Guard.State getState() {
return this._state;
}
@Override
public void daze() {
this._state = Guard.State.STUNNED;
}
// -------------------------------------------------------------------------
// Agent interface:
@Override
public boolean moveTo(Position walkable) {
if(walkable.isNeighbouring((BasePosition)this.getPosition()) == false){
System.out.println(
"- " + this.getId() +
": Failed to move - " + walkable.getId() +
" is too far"
);
return false;
}
if(walkable.isTypeOf(BaseObject.Type.DOOR)){
Door door = (Door)walkable;
if(door.isClosed()){
System.out.println(
"- " + this.getId() +
": Failed to move - " + walkable.getId() +
" is closed"
);
this.examine(walkable);
return false;
}
System.out.println(
"- " + this.getId() +
": Moved from " + this._positionId +
" to " + walkable.getId()
);
this._positionId = walkable.getId();
return true;
}
if(walkable.isTypeOf(BaseObject.Type.FLOOR)){
System.out.print(
"- " + this.getId() +
": Moved from " + this._positionId +
" to " + walkable.getId()
);
if(this.getPosition().isTypeOf(BaseObject.Type.DOOR)){
// went into another room:
int oldRoomId = this.getRoomId();
this._roomId = walkable.getRoomId();
// look around in the new room:
this.lookAround();
System.out.println(
" (Room changed from " + oldRoomId +
" to " + this.getRoomId() + ')'
);
}else{
System.out.println();
}
this._positionId = walkable.getId();
return true;
}
System.out.println(
"- " + this.getId() +
": Failed to move to " + walkable.getId() +
", invalid destination type"
);
return false;
}
@Override
public boolean open(Lockable lockable) {
boolean result = lockable.open();
this.examine((Position)lockable);
if(result){
System.out.println(
"- " + this.getId() +
": Opened " + ((Position)lockable).getId()
);
}else{
System.out.println(
"- " + this.getId() +
": Failed to open - " + ((Position)lockable).getId() +
" is locked"
);
}
return result;
}
@Override
public boolean close(Lockable lockable) {
boolean result = lockable.close();
this.examine((Position)lockable);
System.out.println(
"- " + this.getId() +
": Closed " + ((Position)lockable).getId()
);
return result;
}
@Override
public boolean unlock(Lockable lockable, Key key) {
boolean result = lockable.unlock(key.getId());
this.examine((Position)lockable);
if(result){
System.out.println(
"- " + this.getId() +
": Unlocked " + ((Position)lockable).getId() +
" with " + key.getId()
);
}else{
System.out.println(
"- " + this.getId() +
": Failed to unlock " + ((Position)lockable).getId() +
" with " + key.getId()
);
}
return result;
}
@Override
public boolean lock(Lockable lockable, Key key) {
boolean result = lockable.lock(key.getId());
this.examine((Position)lockable);
if(result){
System.out.println(
"- " + this.getId() +
": Locked " + ((Position)lockable).getId() +
" with " + key.getId()
);
}else{
System.out.println(
"- " + this.getId() +
": Failed to lock " + ((Position)lockable).getId() +
" with " + key.getId()
);
}
return result;
}
@Override
public boolean pickUp(Inventory inventory, Item item) {
Item result = inventory.removeItem(item.getId());
if(result != null)
this.addItem(item);
this.examine((Position)inventory);
this._knowledge.forgetItemPosition(item);
if(result != null){
System.out.println(
"- " + this.getId() +
": Picked up from " + ((Position)inventory).getId() +
" item " + item.getId()
);
}else{
System.out.println(
"- " + this.getId() +
": Failed to pick up from " + ((Position)inventory).getId() +
" item " + item.getId()
);
}
return result != null;
}
@Override
public boolean use(Vender vender) {
vender.deactivate();
this.examine(vender);
this.getGoals().removeVenderToVisit();
System.out.println(
"- " + this.getId() +
": Used " + vender.getId()
);
return true;
}
// -------------------------------------------------------------------------
@Override
public Room getRoom() {
return this._referenceMap.getRoom(this._roomId);
}
@Override
public int getRoomId() {
return this._roomId;
}
@Override
public boolean isInRoom(Room room) {
return this.isInRoom(room.getId());
}
@Override
public boolean isInRoom(int roomId) {
if(this._roomId == roomId)
return true;
return this.getPosition().isInRoom(roomId);
}
// -------------------------------------------------------------------------
// instructions:
@Override
public void addInstruction(Instruction instruction) {
this._instructions.add(instruction);
}
@Override
public void addInstructions(List<Instruction> instructions) {
this._instructions.addAll(instructions);
}
@Override
public void clearInstructions() {
this._instructions.clear();
}
@Override
public List<Instruction> getInstructions() {
return new ArrayList<Instruction>(this._instructions);
}
@Override
public boolean hasInstructions() {
return ! this._instructions.isEmpty();
}
@Override
public Instruction popFirstInstruction() {
if(this._instructions.isEmpty())
return null;
return this._instructions.remove(0);
}
// -------------------------------------------------------------------------
/**
* Returns the rooms that the agent plans to visit.
*
* @return list of rooms to visit
*/
public List<Integer> getPlannedRoomIds() {
List<Integer> rooms = new LinkedList<Integer>();
int currentRoomId = -1;
Position subject;
for(Instruction instr : this._instructions){
subject = this._referenceMap.getPosition(instr._subjectId);
if(subject.getRoomId() != currentRoomId){
currentRoomId = subject.getRoomId();
rooms.add(currentRoomId);
}
}
return rooms;
}
// -------------------------------------------------------------------------
@Override
public boolean lookAround() {
boolean result = false;
for(Agent agent : this.getRoom().getAgents()){
// doesn't check self
if(agent.getId() == this.getId())
continue;
boolean agentResult = this._knowledge.seenFromFar(agent);
result = agentResult || result;
}
result =
this._knowledge.seenFromFar(this.getRoom().getOperablePositions()) ||
result;
return result;
}
/**
* Closely examines a selected position.
*/
public void examine(Position pos) {
this._knowledge.seenFromNear(pos);
}
@Override
public BeliefBase getBeliefBase() {
return this._knowledge;
}
@Override
public GoalBase getGoals() {
return this._goals;
}
@Override
public Agent examinedFromFar() {
return this.copy(null);
}
@Override
public boolean matchesFromFar(Agent agent) {
BaseAgent other = (BaseAgent) agent;
return this.getId() == other.getId() &&
//this._inventory.matchesFromFar(other._inventory) &&
this.getRoomId() == other.getRoomId() &&
this._state == other._state;
}
// -------------------------------------------------------------------------
/**
* Replicates the changeable details of the selected agent.
*/
protected void copyChangeables(BaseAgent original) {
this._positionId = original._positionId;
this._roomId = original._roomId;
this._state = original._state;
this._inventory.copyChangeables(original._inventory);
this._instructions.clear();
for(Instruction instr : original._instructions)
this._instructions.add(instr);
this._knowledge.copyChangeables(original._knowledge);
this._goals.copyChangeables(original._goals);
}
}