/** * */ package bargainingchips.players; import java.util.concurrent.BlockingQueue; import bargainingchips.Bundle; import bargainingchips.NegotiationContext; import bargainingchips.OutcomeSpace; import bargainingchips.actions.Bid; import bargainingchips.actions.FinalAccept; import bargainingchips.actions.Offer; import bargainingchips.actions.OfferBy; import bargainingchips.actions.OfferType; import bargainingchips.actions.PreAccept; import bargainingchips.outcomes.Outcome; import bargainingchips.players.history.BidEvent; import bargainingchips.players.history.BidEventHistory; import bargainingchips.players.history.BidEventHistoryKeeper; import bargainingchips.utilityfunctions.UtilityFunction; /** * * The bilateral history agent is a model-based agent [1]; that is, it has memory (i.e., the bidding history). * It keeps separate copies of the bids made by itself as well as its opponent. It is designed for Bargaining Chips, * in which, besides its opponent, each such bilateral agent also communicates with its {@link coordinator} agent. * This skeleton memory-based agent adapts some functionalities in both * {@link /NegotiatorGUI/src/main/java/agents/anac/y2011/Nice_Tit_for_Tat/BilateralAgent.java} and * {@link /NegotiatorGUI/src/main/java/bargainingchips/players/TimeDependentNegotiationAgent.java}. * * [1] Stuart Russell and Peter Norvig, Artificial Intelligence: A Modern Approach, Pearson (2020). * * * @author Faria Nassiri-Mofakham * */ public abstract class HistoryAgent extends Agent implements BidEventHistoryKeeper { protected OutcomeSpace outcomeSpace; protected BidEventHistory myHistory; protected BidEventHistory opponentHistory; private Offer lastReceivedOffer = null; public HistoryAgent(String name, UtilityFunction u, NegotiationContext nc, BlockingQueue in, BlockingQueue out, BlockingQueue cin, BlockingQueue cout) { super(name, u, nc, in, out, cin, cout); } @Override protected void receiveOutcome(Outcome outcome) { System.out.println(this + " is done with outcome " + outcome + ". Should clean up now."); } /** * Messaging with the coordinator can happen below */ @Override protected void receiveCoordinationMessage(CoordinationMessage cpoll) { // Update the utility function u = cpoll.getUtilityFunction(); } @Override protected StatusMessage sendStatusMessage() { return null; } @Override protected void receiveOffer(Offer opponentOffer) { lastReceivedOffer = opponentOffer; if (opponentOffer.isBid()) { Bundle b = lastReceivedOffer.getBundle(); double time = getTime(); double myUtility = u.getUtility(b); opponentHistory.add(new BidEvent(b,myUtility,time)); // added the event of opponent's bid in the history } } //** @Override protected Offer sendOffer() { // Nothing received yet if (lastReceivedOffer == null) { Bundle myBid = getNextBid(); remember(new Offer(myBid,OfferType.BID)); return new Bid(myBid); } // Our last bid got accepted. We are also accepting (and we should notify the coordinator). if (lastReceivedOffer.isPreAccept()) return new FinalAccept(lastReceivedOffer); Bundle lastReceivedBid = lastReceivedOffer.getBundle(); // Accept if (isAcceptable(lastReceivedBid)) return new PreAccept(lastReceivedOffer); // Counter offer based actions else { Bundle nextBid = getNextBid(); remember(new Offer(nextBid,OfferType.BID)); return new Bid(nextBid); } } //** /** * Get the next bid we should do */ protected abstract Bundle getNextBid(); //** @Override protected Offer sendOpeningOffer() { return sendOffer(); } public void init() { outcomeSpace = negotiationContext.getOutcomeSpace(); myHistory = new BidEventHistory(); opponentHistory = new BidEventHistory(); } public double getTime() { // time runs from 0.0 to 1.0 int totalrounds = NegotiationContext.DEADLINE; return (double) k / totalrounds; } protected double getUtility(Bundle bid) { double myUtility = 0; try { myUtility = u.getUtility(bid); } catch (Exception e) { e.printStackTrace(); } return myUtility; } /** * Remember our offer, if it was a bid (i.e., of BID type) */ protected void remember(Offer myAction) { if (myAction.isBid()) { Bundle myLastBid = myAction.getBundle(); double time = getTime(); double myUtility = getUtility(myLastBid); BidEvent bidEvent = new BidEvent(myLastBid, myUtility, time); myHistory.add(bidEvent); } } /** * At some point, one of the parties has to accept an offer to end the * negotiation. Use this method to decide whether to accept the last offer * by the opponent. * * @param plannedBid */ public abstract boolean isAcceptable(Bundle plannedBid); public abstract Offer makeAcceptAction(); /** * The opponent has already made a bid. Use this method to make an counter * bid. */ public abstract Bundle chooseCounterBid(); /** * Use this method to make an opening bid. */ public abstract Bundle chooseOpeningBid(); /** * Use this method to make the first counter-bid. */ public abstract Bundle chooseFirstCounterBid(); //protected void prepareOpponentModel() {}; //public Offer chooseOffer() {}; //protected Offer makeAcceptOffer() {}; public Bundle getMyLastBid() { return myHistory.getLastBid(); } public Bundle getMySecondLastBid() { return myHistory.getSecondLastBid(); } public BidEventHistory getOpponentHistory() { return opponentHistory; } public Bundle getOpponentLastBid() { return opponentHistory.getLastBid(); } /** * Returns the current round number, starting at 0. This is equal to the * total number of placed bids. */ public int getRound() { return myHistory.size() + opponentHistory.size(); } protected static void log(String s) { System.out.println(s); } }