Package cz.cuni.mff.abacs.burglar.logics

Source Code of cz.cuni.mff.abacs.burglar.logics.ExecutingMap

/**
*
*/
package cz.cuni.mff.abacs.burglar.logics;

import aStarLibrary.AStar;
import aStarLibrary.Node;
import cz.cuni.mff.abacs.burglar.logics.objects.BaseInterface;
import cz.cuni.mff.abacs.burglar.logics.objects.Room;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.*;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Inventory;
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.items.Uniform;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.*;
import cz.cuni.mff.abacs.burglar.logics.planning.instructions.Instruction;
import cz.cuni.mff.abacs.burglar.visual.VisualBurglar;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


/**
* A game map that executes instructions on it's agents.
*
* @author abacs
*
*/
public class ExecutingMap extends DataMap implements GameMap {
  // properties:
 
 
  /** List of agents that have no planned action sequence and need to create one. */
  protected List<Agent> _agentsNeedReplan = new LinkedList<Agent>();
 
 
  // -------------------------------------------------------------------------
  // constructors:
 
 
  /**
   *
   *
   * @param nextFreeId
   */
  public ExecutingMap(int nextFreeId, int requiredTrapRoomCount) {
    super(nextFreeId, requiredTrapRoomCount);
  }

 
  // -------------------------------------------------------------------------
 
 
  /**
   * Returns the full list of A* nodes from the layout.
   *
   */
  public List<Node> getNodes() {
    List<Node> nodes = new LinkedList<Node>();
    for(Position pos : this.getPositions()){
      nodes.add(((BasePosition)pos).getNode());
    }
    return nodes;
  }
 
 
  // -------------------------------------------------------------------------
 
 
  /**
   * Creates a guard agent and places him to protect the selected rooms.
   *
   * @param roomIds identifiers of the rooms to protect.
   */
  public void addGuardPatrol(List<Integer> roomIds) {
    Position position = this.getFloorPositions(roomIds.get(0)).get(0);
    Guard guard = new Guard(this.getNextID(), position, roomIds, this);
   
    BeliefBase knowledge = guard.getBeliefBase();
    knowledge.seenFromNear(this.getOperablePositions());
   
    // add the uniform:
    Uniform clothes = new Uniform(this.getNextID(), this);
    guard.addItem(clothes);
    this.addItem(clothes);
   
   
    this.addAgent(guard);
  }
 
 
  // -------------------------------------------------------------------------
 
 
  /**
   * Adds the instructions to the corresponding agents.
   *
   * The instructions are translated to simple instructions if needed.
   *
   * Unchecked function. Agent code must be correct.
   */
  @Override
  public void addInstructions(List<Instruction> instructions) {
    // generate simple instructions if needed:
    List<Instruction> simpleInstructions =
      this.simplifyInstructions(instructions);
   
    // clear the agent instructions that are in the instruction list:
    List<Integer> agents = new LinkedList<Integer>();
    for(Instruction instr : simpleInstructions){
      if(agents.contains(instr._agentId) == false){
        agents.add(instr._agentId);
      }
    }
    for(int agentId : agents)
      this.getAgent(agentId).clearInstructions();
   
   
    // add instructions to their executing agent:
    for(Instruction instr : simpleInstructions){
      assert(this.getAgent(instr._agentId) != null) : "invalid Agent Id in Instruction";
      this.getAgent(instr._agentId).addInstruction(instr);
    }
  }
 
 
  @Override
  public void clearInstructions() {
    for(Agent agent : this.getAgents()){
      agent.clearInstructions();
    }
  }
 
 
  @Override
  public List<Instruction> getAgentInstructions(int agentId) {
    return this.getAgent(agentId).getInstructions();
  }
 

  @Override
  public List<Instruction> getAgentInstructions(Agent agent) {
    return agent.getInstructions();
  }
 
 
  @Override
  public boolean instructionListsMatch(
      List<Instruction> a,
      List<Instruction> b
  ) {
    if(a.size() != b.size()){
      return false;
    }
   
    for(int i = 0; i < a.size(); i++){
      Instruction instrA = a.get(i);
      Instruction instrB = b.get(i);
      if(instrA.matches(instrB) == false)
        return false;
    }
   
    return true;
  }
 
 
  @Override
  public List<Room> instructionsLeadToTraps(List<Instruction> list) {
    List<Room> trapRooms = this.getTrapRooms();
    int burglarId = this.getBurglar().getId();
   
    List<Room> triggeredRooms = new ArrayList<Room>();
   
    for(Instruction instr : list){
      // if the agent is the burglar and the current room contains a trap
      // the room is added to the triggered trap list
      // all room can be only once in the triggered list.
     
      if(instr._agentId != burglarId)
        continue;
     
      Position position = this.getPosition(instr._subjectId);
     
      if(position.isTypeOf(BaseInterface.Type.DOOR)){
        Door door = (Door)position;
        Room rooms[] = door.getRooms();
       
        if(trapRooms.contains(rooms[0]) &&
           triggeredRooms.contains(rooms[0]) == false)
          triggeredRooms.add(rooms[0]);
        if(trapRooms.contains(rooms[1]) &&
           triggeredRooms.contains(rooms[1]) == false)
          triggeredRooms.add(rooms[1]);
      }else{
        Room room = position.getRoom();
        if(trapRooms.contains(room) &&
           triggeredRooms.contains(room) == false)
          triggeredRooms.add(room);
      }
    }
   
    return triggeredRooms;
  }
 
 
  // -------------------------------------------------------------------------
 
 
  /**
   * Executes a single step for each agent.
   */
  @Override
  public void executeStep() {
   
    for(Agent agent : this.getAgents()){
     
      // only active agents should perform actions:
      if(agent.isInState(Agent.State.WELL) == false)
        continue;
     
      // execute the stepp:
      boolean agentResult = this.executeStep(agent);
     
      // if room contains active vender, go to it:
      GoalBase agentGoals = agent.getGoals();
      if(agentGoals.hasVenderToVisit() == false){
        Position vender = this.getActiveVender(agent.getRoomId());
        if(vender != null){
          agentGoals.setVenderIdToVisit(vender.getId());
          agentResult = false;
        }
      }
     
      // if agent has no more instructions,
      // or the instruction failed
      // add the agent to the replanning list.
     
      if(agentResult == false || agent.hasInstructions() == false){
        agent.clearInstructions();
        this._agentsNeedReplan.add(agent);
      }
    }
  }
 
 
  /**
   * Executes the first instruction in the agent's instruction stack.
   *
   * Stunned agents remain immobile.
   *
   * @param agent the agent to act.
   * @return success indicator.
   */
  protected boolean executeStep(Agent agent) {
    // if the agent is a stunned guard, do nothing:
    if(agent.isInState(Agent.State.STUNNED)){
      return true;
    }
   
    return this.execute(agent.popFirstInstruction());
  }
 
 
  /**
   * Executes a single instruction.
   *
   * @param instruction instruction object to execute
   * @return success indicator
   */
  protected boolean execute(Instruction instruction) {
    if(instruction == null)
      return false;
   
    boolean ret = false;
   
    Agent agent = this.getAgent(instruction._agentId);
    assert(agent != null);
   
    switch(instruction._code){
    case MOVE:
      ret = this.move(instruction._agentId, instruction._subjectId);
      break;
    case OPEN:
      ret = this.open(instruction._agentId, instruction._subjectId);
      break;
    case CLOSE:
      ret = this.close(instruction._agentId, instruction._subjectId);
      break;
    case UNLOCK:
      ret = this.unlock(
          instruction._agentId,
          instruction._subjectId,
          instruction._itemId
      );
      break;
    case LOCK:
      ret = this.lock(
          instruction._agentId,
          instruction._subjectId,
          instruction._itemId
      );
      break;
    case PICK_UP:
      ret = this.pickUp(
          instruction._agentId,
          instruction._subjectId,
          instruction._itemId
      );
      break;
    case TAKE_CLOTHES:
      this.takeClothes(
          instruction._agentId,
          instruction._subjectId
      );
      break;
    case USE:
      this.use(instruction._agentId, instruction._subjectId);
      break;
    }
    return ret;
  }
 
 
  /**
   * Agents look around in their room.
   *
   * They may discover new positions or agents in the room.
   * If the positions were already known, it does not change them.
   *
   * @return new information indicator
   */
  @Override
  public boolean lookAround() {
    boolean result = false;
    for(Agent agent : this.getAgents()) {
      boolean agentResult = agent.lookAround();
      result = agentResult || result;
      if(VisualBurglar.FLAG_REPLAN_ON_NEW_KNOWLEDGE && agentResult){
        agent.clearInstructions();
        this._agentsNeedReplan.add(agent);
      }
    }
    return result;
  }
 
  // -------------------------------------------------------------------------
 
 
  /** Returns whether the map has agents that need replanning. */
  @Override
  public boolean needsReplanning() {
    return ! this._agentsNeedReplan.isEmpty();
  }
 
 
  /**
   * Returns the list of agents that require replanning.
   *
   * @return
   */
  @Override
  public List<Agent> getAgentsToReplan() {
    return new ArrayList<Agent>(this._agentsNeedReplan);
  }
 
 
  @Override
  public void clearAgentsToReplan() {
    this._agentsNeedReplan.clear();
  }
 
 
  @Override
  public void addAgentToReplan(Agent agent) {
    this._agentsNeedReplan.add(agent);
  }
 
 
  @Override
  public void removeAgentToReplan(Agent agent) {
    this._agentsNeedReplan.remove(agent);
  }
 
 
  // -------------------------------------------------------------------------
 
 
  @Override
  public List<Position> nodesToPositions(List<Node> nodes) {
    List<Position> positions = new ArrayList<Position>();
    for(Node node : nodes)
      positions.add(this.getPosition(node));
    return positions;
  }
 
 
  // -------------------------------------------------------------------------
 
 
  /**
   * Replaces a complex instruction with simple ones.
   *
   * Used to break apart movement instructions.
   *
   * Destructive operation on the agent parameter.
   * @param testAgent a test copy of the agent that will execute the instructions.
   * @param instruction instruction to process.
   * @return resulted instruction list
   */
  protected List<Instruction> simplifyInstruction(
      Instruction instruction,
      Agent testAgent
  ) {
    List<Instruction> result = new ArrayList<Instruction>();
   
    Instruction simpleInstr;
   
    switch(instruction._code){
      case ENTER_DOOR:
        simpleInstr =
          new Instruction(
              Instruction.code.MOVE,
              instruction._agentId,
              instruction._subjectId
          );
        result.add(simpleInstr);
        testAgent.setPosition(instruction._subjectId);
        break;
       
      case COMPLEX_MOVE:
        Position subjectPos = this.getPosition(instruction._subjectId);
        if(subjectPos == null)
          subjectPos = this.getAgent(instruction._subjectId).getPosition();
        List<Position> path =
            this.getSimplePath(
              testAgent.getPosition(),
              subjectPos
            );
       
        for(Position position : path){
          simpleInstr =
            new Instruction(
                Instruction.code.MOVE,
                instruction._agentId,
                position.getId()
            );
          result.add(simpleInstr);
          testAgent.setPosition(position);
        }
        break;
       
      default:
        result.add(instruction);
    }
   
    return result;
  }
 
 
  /**
   * Replaces complex instructions with simple ones.
   *
   * Instructions have to contain a single agent.
   *
   * @param instructions list of instructions to process.
   * @return resulted instruction list.
   */
  protected List<Instruction> simplifyInstructions(
      List<Instruction> instructions
  ) {
    List<Instruction> result = new ArrayList<Instruction>();
   
    if(instructions.isEmpty())
      return result;
   
    // creates a test copy that will be destroyed later;
    Agent testAgent = this.getAgent(instructions.get(0)._agentId).copy(this);
   
    for(Instruction instr : instructions){
        result.addAll(this.simplifyInstruction(instr, testAgent));
    }
   
    return result;
  }
 
 
  /**
   * Generates a path between two positions.
   *
   * The result does not include the start, neither
   * the end position. It does not calculate with doors, but
   * it does use only walkable positions.
   *
   * @param from starting position
   * @param to movement aim
   * @return list of positions from start to aim in correct order.
   */
  protected List<Position> getSimplePath(Position from, Position to) {
    List<Position> result = new ArrayList<Position>();
   
    if(from.getId() == to.getId())
      return result;
   
    // plan the path:
    AStar aStar = new AStar();
    aStar.nodes.addAll(this.getNodes());
   
    List<Node> nodes =
      aStar.getPath(
          ((BasePosition)from).getNode(),
          ((BasePosition)to).getNode()
      );
   
    // the a* algorithm returns the nodes in oposite order
    // we only need the last stepp if it's not the target position
    for(int index = nodes.size() - 2; index > 0; index--){
      result.add(this.getPosition(nodes.get(index)));
    }
   
    Position lastPosition = this.getPosition(nodes.get(0));
    if(lastPosition.getId() != to.getId()){
      result.add(lastPosition);
    }
   
    return result;
  }
 
  // -------------------------------------------------------------------------
 
 
  @Override
  public boolean isBurglarTrapped() {
    Burglar burglar = this.getBurglar();
   
    // burglar can hide from cameras
    if(burglar.isDisguised() == false){
      for(Position pos : this.getTrapPositions()){
        if(pos.isTypeOf(BaseInterface.Type.CAMERA)){
          Camera camera = (Camera)pos;
          if(
            camera.isActive() &&
            burglar.isInRoom(camera.getRoomId())
          )
            return true;
        }
      }
    }
   
    for(Guard guard : this.getGuards()){
      if(
        guard.isInState(Guard.State.WELL) &&
        guard.getRoomId() == burglar.getRoomId()
      )
        return true;
    }
    return false;
  }
 
 
  // -------------------------------------------------------------------------
  // instructions:
 
 
  /**
   * Executes a directional move instruction.
   *
   * @param agentId acting agent
   * @param direction movement direction
   * @return success of the operation
   */
  public boolean move(int agentId, Direction direction) {
    return this.move(this.getAgent(agentId), direction);
  }
 
 
  /**
   * Executes a directional move instruction.
   *
   * @param agent acting agent
   * @param direction movement direction
   * @return success of the operation
   */
  boolean move(Agent agent, Direction direction) {
    Position aim = this.getNeighbour(agent.getPosition(), direction);
    if(aim == null)
      return false;
    return agent.moveTo(aim);
  }
 
 
  /**
   * Executes a simple move instruction.
   *
   * @param agentId acting agent
   * @param walkableId walkable position to step on
   * @return success of the operation
   */
  boolean move(int agentId, int walkableId) {
    return this.move(this.getAgent(agentId), this.getPosition(walkableId));
  }
 
 
  /**
   * Executes a simple move instruction.
   *
   * @param agent acting agent
   * @param walkable walkable position to step on
   * @return success of the operation
   */
  private boolean move(Agent agent, Position walkable) {
    return agent.moveTo(walkable);
  }
 
 
  /**
   * Executes an open instruction.
   *
   * @param agentId acting agent
   * @param lockableId lockable position to open
   * @return success of the operation
   */
  private boolean open(int agentId, int lockableId) {
    return this.open(
        this.getAgent(agentId),
        (Lockable)this.getPosition(lockableId)
    );
  }
 
 
  /**
   * Executes an open instruction.
   *
   * @param agent acting agent
   * @param lockable lockable position to open
   * @return success of the operation
   */
  private boolean open(Agent agent, Lockable lockable) {
    return agent.open(lockable);
  }
 
 
  /**
   * Executes a close instruction.
   *
   * @param agentId acting agent
   * @param lockableId lockable position to close
   * @return success of the operation
   */
  private boolean close(int agentId, int lockableId) {
    return this.close(
        this.getAgent(agentId),
        (Lockable) this.getPosition(lockableId)
    );
  }
 
 
  /**
   * Executes a close instruction.
   *
   * @param agent acting agent
   * @param lockable lockable position to close
   * @return success of the operation
   */
  private boolean close(Agent agent, Lockable lockable) {
    return agent.close(lockable);
  }
 
 
  /**
   * Executes an unlock instruction.
   *
   * @param agentId acting agent
   * @param lockableId lockable position to unlock
   * @param keyId key to use
   * @return success of the operation
   */
  private boolean unlock(int agentId, int lockableId, int keyId) {
    return this.unlock(
        this.getAgent(agentId),
        (Lockable) this.getPosition(lockableId),
        (Key) this.getItem(keyId)
    );
  }
 
 
  /**
   * Executes an unlock instruction.
   *
   * @param agent acting agent
   * @param lockable lockable position to unlock
   * @param key key to use
   * @return success of the operation
   */
  private boolean unlock(Agent agent, Lockable lockable, Key key) {
    return agent.unlock(lockable, key);
  }
 
 
  /**
   * Executes a lock instruction.
   *
   * @param agentId acting agent
   * @param lockableId lockable position to lock
   * @param keyId key to use
   * @return success of the operation
   */
  private boolean lock(int agentId, int lockableId, int keyId) {
    return this.lock(
        this.getAgent(agentId),
        (Lockable) this.getPosition(lockableId),
        (Key) this.getItem(keyId)
    );
  }
 
 
  /**
   * Executes a lock instruction.
   *
   * @param agent acting agent
   * @param lockable lockable position to lock
   * @param key key to use
   * @return success of the operation
   */
  private boolean lock(Agent agent, Lockable lockable, Key key) {
    return agent.lock(lockable, key);
  }
 
 
  /**
   * Executes a pick up instruction.
   *
   * @param agentId acting agent
   * @param inventoryId from where to pick up the object
   * @param itemId item to pick up
   * @return success of the operation
   */
  private boolean pickUp(int agentId, int inventoryId, int itemId) {
    return this.pickUp(
        this.getAgent(agentId),
        (Inventory) this.getPosition(inventoryId),
        this.getItem(itemId)
    );
  }
 
 
  /**
   * Executes a pick up instruction.
   *
   * @param agent acting agent
   * @param inventory from where to pick up the object
   * @param item item to pick up
   * @return success of the operation
   */
  private boolean pickUp(Agent agent, Inventory inventory, Item item) {
    return agent.pickUp(inventory, item);
  }
 
 
  /**
   * Executes a take clothes instruction.
   *
   * @param agentId acting agent
   * @param subjectAgentId from where to pick up the clothes
   * @return success of the operation
   */
  private boolean takeClothes(int agentId, int subjectAgentId) {
    return this.takeClothes(
        this.getAgent(agentId),
        this.getAgent(subjectAgentId)
    );
  }
 
 
  /**
   * Executes a take clothes instruction.
   *
   * @param agent acting agent
   * @param subjectAgent from where to pick up the clothes
   * @return success of the operation
   */
  private boolean takeClothes(Agent agent, Agent subjectAgent) {
    int id = subjectAgent.getItemIdOfType(BaseInterface.Type.UNIFORM);
   
    Item item;
    if(id != -1)
      item = subjectAgent.removeItem(id);
    else{
      item = new Uniform(this.getNextID(), this);
      this.addItem(item);
    }
    agent.addItem(item);
   
    System.out.println(
      "- " + agent.getId() +
      ": Clothes taken from " + subjectAgent.getId()
    );
    return true;
  }
 
 
  /**
   * Executes a use instruction.
   *
   * @param agentId acting agent
   * @param venderId vender position to use
   * @return success of the operation
   */
  private boolean use(int agentId, int venderId) {
    return this.use(
        this.getAgent(agentId),
        (Vender) this.getPosition(venderId)
    );
  }
 
 
  /**
   * Executes a use instruction.
   *
   * @param agent acting agent
   * @param lockable vender position to use
   * @return success of the operation
   */
  private boolean use(Agent agent, Vender vender) {
    return agent.use(vender);
  }
 
}
TOP

Related Classes of cz.cuni.mff.abacs.burglar.logics.ExecutingMap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.