Package ise.mace.participants

Source Code of ise.mace.participants.AbstractAgent$InvitationHandler

package ise.mace.participants;

import ise.mace.actions.ApplyToGroup;
import ise.mace.actions.Death;
import ise.mace.actions.Hunt;
import ise.mace.actions.Proposal;
import ise.mace.actions.Proposal.ProposalType;
import ise.mace.actions.Vote;
import ise.mace.agents.PoliticalAgentGroup;
import ise.mace.environment.EnvironmentConnection;
import ise.mace.environment.PublicEnvironmentConnection;
import ise.mace.inputs.ApplicationResponse;
import ise.mace.inputs.ConsumeFood;
import ise.mace.inputs.GroupInvite;
import ise.mace.inputs.HuntOrder;
import ise.mace.inputs.HuntResult;
import ise.mace.inputs.Proposition;
import ise.mace.inputs.VoteResult;
import ise.mace.models.Food;
import ise.mace.models.HuntingTeam;
import ise.mace.tokens.AgentType;
import ise.mace.tokens.RegistrationRequest;
import ise.mace.tokens.RegistrationResponse;
import ise.mace.tokens.TurnType;
import ise.mace.tokens.UnregisterRequest;
import java.util.ArrayList;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.simpleframework.xml.Element;
import presage.EnvironmentConnector;
import presage.Input;
import presage.Participant;
import presage.PlayerDataModel;
import presage.environment.messages.ENVRegistrationResponse;
import presage.util.InputQueue;

/**
* Defines the methods that an Agent may use to interact with the modelling
* system. Some of the interactions with the model are declared as final to
* control the overall interface.
*
* All agents which extend this class should be in the agents package
* @see ise.mace.agents
*/
abstract public class AbstractAgent implements Participant
{
  /**
   * @return the conn
   */
  protected PublicEnvironmentConnection getConn()
  {
    return conn;
  }

  private class ConsumeFoodHandler implements InputHandler
  {
    @Override
    public boolean canHandle(Input input)
    {
      return (input instanceof ConsumeFood);
    }

    @Override
    public void handle(Input input)
    {
      logger.log(Level.FINE, "I, agent {0}, consumed {1} units of food",
              new Object[]
              {
                dm.getName(),
                dm.getFoodConsumedThisTurn()
              });
      dm.foodConsumed(dm.getFoodConsumedThisTurn());
    }
  }

  private class HuntResultHandler implements InputHandler
  {
    @Override
    public boolean canHandle(Input input)
    {
      return (input instanceof HuntResult);
    }

    @Override
    public void handle(Input input)
    {
      final HuntResult in = (HuntResult)input;
      dm.foodAquired(in.getFoodReceived());
      logger.log(Level.FINE, "I, agent {0}, recieved {1} units of food",
              new Object[]
              {
                dm.getName(),
                in.getFoodReceived()
              });

      dm.setCurrentHappiness(updateHappinessAfterHunt(in.getFoodHunted(),
              in.getFoodReceived()));
      dm.setCurrentLoyalty(updateLoyaltyAfterHunt(in.getFoodHunted(),
              in.getFoodReceived()));
      Map<String, Double> t = updateTrustAfterHunt(in.getFoodHunted(),
              in.getFoodReceived());
      if (t == null) return;
      for (String agent : t.keySet())
      {
        dm.setTrust(agent, t.get(agent));
      }
      Map<String, Double> t1 = updateTrustAfterLeadersHunt();
      if (t1 == null) return;
      for (String agent : t1.keySet())
      {
        dm.setTrust(agent, t1.get(agent));
      }
    }
  }

  private class HuntOrderHandler implements InputHandler
  {
    @Override
    public boolean canHandle(Input input)
    {
      return (input instanceof HuntOrder);
    }

    @Override
    public void handle(Input input)
    {
      final HuntOrder in = (HuntOrder)input;
      dm.setHuntingTeam(in.getTeam());
      logger.log(Level.FINE, "I, Agent {0} have been told to hunt with Team {1}",
              new Object[]
              {
                dm.getName(),
                in.getTeam().hashCode()
              });
    }
  }

  private class ApplicationResponseHandler implements InputHandler
  {
    @Override
    public boolean canHandle(Input input)
    {
      return (input instanceof ApplicationResponse);
    }

    @Override
    public void handle(Input input)
    {
      final ApplicationResponse in = (ApplicationResponse)input;
      if (in.wasAccepted())
      {
        dm.setGroup(in.getGroup());
      }
      else
      {
        dm.setGroup(null);
      }

      groupApplicationResponse(in.wasAccepted());
      logger.log(Level.FINE, "I, agent {0} was {1}accepted into group {2}",
              new Object[]
              {
                dm.getName(),
                in.wasAccepted() ? "" : "not ", ec.nameof(in.getGroup())
              });
    }
  }

  private class PropositionHandler implements InputHandler
  {
    @Override
    public boolean canHandle(Input input)
    {
      return (input instanceof ise.mace.inputs.Proposition);
    }

    @Override
    public void handle(Input input)
    {
      final ise.mace.inputs.Proposition in = (ise.mace.inputs.Proposition)input;

      Vote.VoteType v = castVote(in);
      ec.act(new Vote(in, v), getId(), authCode);

      logger.log(Level.FINE, "I, agent {0} voted {1} in {2}'s vote of {3}",
              new Object[]
              {
                dm.getName(),
                v, ec.nameof(in.getProposer()), in.getType()
              });
    }
  }

  private class VoteResultHandler implements InputHandler
  {
    @Override
    public boolean canHandle(Input input)
    {
      return (input instanceof VoteResult);
    }

    @Override
    public void handle(Input input)
    {
      final VoteResult in = (VoteResult)input;
      logger.log(Level.FINE, "I, agent {0} got {1} for my {2} proposal.",
              new Object[]
              {
                dm.getName(),
                in.getVotes(), in.getProposition().getType()
              });
      dm.setCurrentHappiness(updateHappinessAfterVotes(in.getProposition(),
              in.getVotes(), in.getOverallMovement()));
      dm.setCurrentLoyalty(updateLoyaltyAfterVotes(in.getProposition(),
              in.getVotes(), in.getOverallMovement()));
      dm.setSocialBelief(updateSocialBeliefAfterVotes(in.getProposition(),
              in.getVotes(), in.getOverallMovement()));
      dm.setEconomicBelief(updateEconomicBeliefAfterVotes(in.getProposition(),
              in.getVotes(), in.getOverallMovement()));
      Map<String, Double> t = updateTrustAfterVotes(in.getProposition(),
              in.getVotes(), in.getOverallMovement());
      if (t == null) return;
      for (String agent : t.keySet())
      {
        dm.setTrust(agent, t.get(agent));
      }
    }
  }

  private class InvitationHandler implements InputHandler
  {
    @Override
    public boolean canHandle(Input input)
    {
      return (input instanceof GroupInvite);
    }

    @Override
    public void handle(Input input)
    {
      final GroupInvite in = (GroupInvite)input;

      onInvite(in.getGroup());
      logger.log(Level.FINE, "I, agent {0} was inivited to the new {1} group.",
              new Object[]
              {
                dm.getName(),
                ec.nameof(in.getGroup())
              });
    }
  }

  private final static Logger logger = Logger.getLogger("mace.AbstractAgent");
  public final static String leaveGroup = UUID.randomUUID().toString();
  /**
   * The DataModel used by this agent.
   */
  @Element
  private AgentDataModel dm;
  /**
   * The authorisation code for use with sexy things like the environment
   */
  private UUID authCode;
  /**
   * Reference to the environment connector, that allows the agent to interact
   * with the environment
   */
  private PublicEnvironmentConnection conn;
  private EnvironmentConnection ec;
  private EnvironmentConnector tmp_ec;
  private InputQueue msgQ = new InputQueue("inputs");
  private ArrayList<InputHandler> handlers = new ArrayList<InputHandler>();

  /**
   * Serialisation requires a public no-argument constructor to be present.
   * Using a explictly defined deprecated implementation should stop people
   * accidentally calling this function
   * @deprecated Not safe due to serialisation usages
   */
  @Deprecated
  public AbstractAgent()
  {
    super();
  }

  /**
   * Creates a new agent with the two primary properties
   * @param myroles The roles that this agent can perform
   * @param randomseed the random seed for this agent
   * @param initialFood The initial amount of food
   * @param consumption The amount consumed per turn
   */
  public AbstractAgent(String myroles, long randomseed, double initialFood,
          double consumption)
  {
    this(myroles, randomseed, initialFood, consumption, null, 0, 0);
  }

  /**
   * Creates a new agent with the two primary properties
   * @param myroles The roles that this agent can perform
   * @param randomseed the random seed for this agent
   * @param initialFood The initial amount of food
   * @param consumption The amount consumed per turn
   * @param type The logic type of this agent
   * @param socialBelief The social belief of this agent
   * @param economicBelief The economic belief of this agent
   */
  public AbstractAgent(String myroles, long randomseed, double initialFood,
          double consumption, AgentType type,
          double socialBelief, double economicBelief)
  {
    UUID myid = UUID.randomUUID();
    this.dm = new AgentDataModel(myid.toString(), myroles, this.getClass(),
            randomseed, initialFood, consumption, type, socialBelief,
            economicBelief);
  }

  //ADDED The0
  /** ADDED The0
   * Creates a new agent with the two primary properties
   * @param myroles The roles that this agent can perform
   * @param randomseed the random seed for this agent
   * @param initialFood The initial amount of food
   * @param consumption The amount consumed per turn
   * @param type The logic type of this agent
   * @param socialBelief The social belief of this agent
   * @param economicBelief The economic belief of this agent
   */
  public AbstractAgent(String myroles, long randomseed, double initialFood,
          double consumption, AgentType type,
          double socialBelief, double economicBelief, String name)
  {
    UUID myid = UUID.randomUUID();
    this.dm = new AgentDataModel(myid.toString(), myroles, this.getClass(),
            randomseed, initialFood, consumption, type, socialBelief,
            economicBelief, name);
  }

  /**
   * Returns the String representation of the Agent's UUID, which is used to
   * identify the agent in all interactions.
   * @return The String representation of the Agent's unique identifier
   */
  @Override
  public final String getId()
  {
    return dm.getId();
  }

  @Override
  public final ArrayList<String> getRoles()
  {
    return dm.getRoles();
  }

  @Override
  public final void initialise(EnvironmentConnector environmentConnector)
  {
    tmp_ec = environmentConnector;
    dm.initialise(environmentConnector);

    this.handlers.add(new ConsumeFoodHandler());
    this.handlers.add(new HuntResultHandler());
    this.handlers.add(new HuntOrderHandler());
    this.handlers.add(new ApplicationResponseHandler());
    this.handlers.add(new PropositionHandler());
    this.handlers.add(new VoteResultHandler());
    this.handlers.add(new InvitationHandler());
  }

  @Override
  public final void onActivation()
  {
    RegistrationRequest request = new RegistrationRequest(dm.getId(),
            dm.getRoles(), dm.getPublicVersion());
    ENVRegistrationResponse r = tmp_ec.register(request);
    this.authCode = r.getAuthCode();
    this.ec = ((RegistrationResponse)r).getEc();
    conn = PublicEnvironmentConnection.getInstance();
    tmp_ec = null;
    onActivate();
  }

  @Override
  public final void onDeActivation()
  {
    ec.deregister(new UnregisterRequest(dm.getId(), authCode));
  }

  @Override
  public final void execute()
  {
    // Handle Queued Messages
    while (!msgQ.isEmpty())
      handleInput(msgQ.dequeue());
    // Check to see if we died due to a message in the queue
    if (this.dm.getFoodInPossesion() < 0)
    {
      logger.log(Level.FINE, "I, agent, {0}, am starving to death!",
              dm.getName());
      ec.act(new Death(), dm.getId(), authCode);
    }

    TurnType turn = ec.getCurrentTurnType();

    if (TurnType.firstTurn.equals(turn))
    {
      beforeNewRound();
      clearRoundData();
    }

    switch (turn)
    {
      case GroupSelect:
        doGroupSelect();
        break;
      case TeamSelect:
        // This is the group's move
        break;
      case GoHunt:
        doHuntTurn();
        break;
      case HuntResults:
        // This is the group's move
        break;
      case MakeProposals:
        doMakeProposal();
        break;
      case Voting:
        // This is the group's move
        break;
      default:
        throw new IllegalStateException("Turn was not recognised");
    }
  }

  private void handleInput(Input i)
  {
    for (InputHandler inputHandler : handlers)
    {
      if (inputHandler.canHandle(i))
      {
        inputHandler.handle(i);
        return;
      }
    }
    logger.log(Level.SEVERE, "AbstractAgent can not handle inputs of type {0}",
            i.getClass().getCanonicalName());
  }

  private void clearRoundData()
  {
    //ADDED THEO
    for (String dead_a : PoliticalAgentGroup.dead_agents)
    {
      if (this.getId().equals(dead_a))
        ec.act(new Death(), this.getId(), authCode);
    }
    PoliticalAgentGroup.dead_agents.clear();
    //********
    dm.newHistoryEntry();
  }

  private void doGroupSelect()
  {
    String gid = chooseGroup();
    if (gid == null ? true : gid.equals(dm.getGroupId())) return;
    if (gid.equals(leaveGroup))
    {
      ec.act(new ApplyToGroup(gid), getId(), authCode);
      //Bug source
      //this.dm.setGroup(null);
      //Bug source end
      return;
    }
    if (getConn().isGroupId(gid)) ec.act(new ApplyToGroup(gid), getId(),
              authCode);
  }

  private void doHuntTurn()
  {
    Food toHunt = chooseFood();

    if (toHunt == null)
    {
      logger.log(Level.WARNING, "Agent {0} did not pick a food to hunt",
              dm.getName());
    }
    else
    {
      ec.act(new Hunt(toHunt), this.getId(), authCode);
    }
    dm.setLastHunted(toHunt);
  }

  private void doMakeProposal()
  {
    if (dm.getGroupId() == null) return;
    ProposalType t = makeProposal();
    ec.act(new Proposal(t, dm.getGroupId()), getId(), authCode);
  }

  /**
   *
   * @param cycle
   */
  @Override
  public final void setTime(long cycle)
  {
    dm.setTime(cycle);
  }

  /**
   * Makes this agent seek advice from another agent
   * @param agent The agent to seek advice from
   * @return The food they advice you hunt, based on your team etc.
   */
  protected final Food seekAvice(String agent)
  {
    dm.increaseFoodConsumedThisTurn(ec.getFoodConsumedPerAdvice());
    return ec.seekAdvice(getId(), authCode, agent, dm.getHuntingTeam());
  }

  /**
   * Wrapper function for advice giving
   * @param agent The agent who is asking for advice
   * @param agentsTeam The team are part of
   * @return What food you want to tell them to hunt
   */
  public Food advise(String agent, HuntingTeam agentsTeam)
  {
    Food advice = giveAdvice(agent, agentsTeam);
    dm.gaveAdvice(agent, advice);
    return advice;
  }

  /**
   * Returns the DataModel of this object
   * @return The DataModel of this object
   */
  @Override
  public final PlayerDataModel getInternalDataModel()
  {
    return dm.getPublicVersion();
  }

  /**
   * Gets the public data model of this agent
   * @return The public data model of this agent
   */
  public final PublicAgentDataModel getDataModel()
  {
    return dm.getPublicVersion();
  }

  @Override
  public final void enqueueInput(Input input)
  {
    if (input.getClass().equals(Proposition.class))
    {
      handleInput(input);
      return;
    }
    this.msgQ.enqueue(input);
  }

  /**
   *
   * @param input
   */
  @Override
  public final void enqueueInput(ArrayList<Input> input)
  {
    for (Input in : input)
    {
      this.msgQ.enqueue(in);
    }
  }

  @Override
  @SuppressWarnings("NoopMethodInAbstractClass")
  public final void onSimulationComplete()
  {
    // Nothing to see here. Move along, citizen!
  }

  /**
   * Get the next random number in the sequence as a double uniformly
   * distributed between 0 and 1
   * @return Next random number
   */
  protected final double uniformRand()
  {
    return this.dm.random.nextDouble();
  }

  /**
   * Get the next random number in the sequence as a double uniformly
   * distributed between 0 and 1
   * @return Next random number
   */
  protected final long uniformRandLong()
  {
    return this.dm.random.nextLong();
  }

  protected final boolean uniformRandBoolean()
  {
    return this.dm.random.nextBoolean();
  }

  /**
   * Called when the agent has been activated, and when both the {@link
   * PublicAgentDataModel data model} and the {@link PublicEnvironmentConnection
   * environment connection} have been initialised
   * @see #getDataModel()
   * @see #getConn()
   */
  abstract protected void onActivate();

  /**
   * Used to implement any code necessary before all properties of the current
   * round are deleted to make way for a newer, fresher, more flexible
   * round to begin.
   * The reset fields are the last thing we hunted, the last order we received,
   * and the last team we were in. All of these
   */
  abstract protected void beforeNewRound();

  /**
   * Magic heuristic to select which Group the agent wishes to be a part of
   * for the next round. The list of groups can be obtained through the
   * connector {@link #conn this.conn}, as can functions to create a new group.
   * IF the agent wishes to remain in the same group, it can either return the
   * current group id, or null.
   * If the agent wished to leave it's current group, and rejoin the pool of
   * free agents, it should return the constant value at {@link
   * AbstractAgent#leaveGroup}. The value is designed not to collide with any
   * group name.
   * @return The is of the group we should try to join
   */
  abstract protected String chooseGroup();

  /**
   * Called once the environment has issued a response to the application
   * to join a group. Also states whether or not the application has been
   * successful. The group will already be filled into the groupId field of the
   * {@link PublicAgentDataModel data model}, which can be obtained through
   * the {@link #getDataModel() getDataModel()} function
   * @param accepted Whether you were accepted into the group
   */
  abstract protected void groupApplicationResponse(boolean accepted);

  /**
   * Function called to get the Agent to select what kind of food it would like
   * to hunt. It should use all the other information it has received to inform
   * this decision.
   * You can get the types of food from {@link #getConn() this.getConn()},
   * which has various functions related to determining food properties.
   * If the agent is a member of a group, the food they have been ordered to
   * hunt and their current group can be found in the {@link
   * PublicAgentDataModel data model}, which is accessed this {@link
   * #getDataModel() this.getDataModel()}
   * @return The type of food they have decided to hunt
   */
  abstract protected Food chooseFood();

  /**
   * Allows the agent to propose a shift of the group's economic status
   * along the axis. The exact direction and magnitude of the shift
   * depends on how the function is defined.
   * @return The direction and magnitude of the proposed move
   */
  abstract protected ProposalType makeProposal();

  /**
   * Allows the agent to vote on a proposition that has been put before the
   * group
   * @param p The proposition to vote on
   * @return The agent's decision
   */
  abstract protected Vote.VoteType castVote(Proposition p);

  /**
   * Allows other agents to ask this agent what to hunt given their team
   * @param agent The agent who is asking for advice
   * @param agentsTeam The team are part of
   * @return What food you want to tell them to hunt
   */
  abstract protected Food giveAdvice(String agent, HuntingTeam agentsTeam);

  /**
   * Allows the happiness value of the agent to be updated after the completion
   * of the hunt
   * @param foodHunted The amount of food the agent brought back to the group
   * @param foodReceived The amount of food that the agent was allowed to keep
   * @return The new happiness value of the agent, scaled between 0 and 1
   */
  abstract protected double updateHappinessAfterHunt(double foodHunted,
          double foodReceived);

  /**
   * Allows the loyalty value of the agent to be updated after the completion of
   * the hunt
   * @param foodHunted The amount of food the agent brought back to the group
   * @param foodReceived THe amount of food that the agent was allowed to keep
   * @return The new loyalty value of the agent, scaled between 0 and 1
   */
  abstract protected double updateLoyaltyAfterHunt(double foodHunted,
          double foodReceived);

  /**
   * Allows the trust values of the agent to be updated after the completion of
   * the hunt
   * @param foodHunted The amount of food the agent brought back to the group
   * @param foodReceived THe amount of food that the agent was allowed to keep
   * @return A mapping between agent ids, and the new value for their trust
   * rating. Agent ids which are to in the map will not be updated. The trust
   * values should be scaled between 0 and 1.
   */
  abstract protected Map<String, Double> updateTrustAfterHunt(double foodHunted,
          double foodReceived);

  abstract protected Map<String, Double> updateTrustAfterLeadersHunt();

  abstract protected double updateLoyaltyAfterVotes(Proposition proposition,
          int votes, double overallMovement);

  abstract protected double updateHappinessAfterVotes(Proposition proposition,
          int votes, double overallMovement);

  abstract protected double updateSocialBeliefAfterVotes(Proposition proposition,
          int votes, double overallMovement);

  abstract protected double updateEconomicBeliefAfterVotes(
          Proposition proposition, int votes, double overallMovement);

  abstract protected Map<String, Double> updateTrustAfterVotes(
          Proposition proposition, int votes, double overallMovement);

  /**
   * Notifies you when you have been invited to a new group.
   * It is up to agent implementations to supply a place in their own class to
   * store this information. They will be able to join the group when the
   * chooseGroup function is called.
   * @param group The group they've been invited to
   */
  abstract protected void onInvite(String group);
}
TOP

Related Classes of ise.mace.participants.AbstractAgent$InvitationHandler

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.