package sos.mas; import jade.content.ContentElement; import jade.content.lang.Codec; import jade.content.lang.sl.SLCodec; import jade.content.onto.Ontology; import jade.core.AID; import jade.core.Agent; import jade.core.behaviours.ParallelBehaviour; import jade.domain.DFService; import jade.domain.FIPAAgentManagement.*; import jade.domain.FIPAException; import jade.domain.FIPANames; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.AchieveREResponder; import jade.proto.SubscriptionInitiator; import sos.mas.ontology.GameOntology; import sos.mas.ontology.Round; import sos.mas.strategies.AbstractStrategyBehaviour; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Iterator; public class PrisonerAgent extends Agent { private Codec codec = new SLCodec(); private Ontology ontology = GameOntology.getInstance(); private AbstractStrategyBehaviour usedStrategy = null; private GameHistory game; private void out(String text, Object... args) { System.out.print("[" + getLocalName() + "] "); System.out.println(String.format(text, args)); } @Override protected void setup() { try { out("Starting"); getContentManager().registerLanguage(codec, FIPANames.ContentLanguage.FIPA_SL0); getContentManager().registerOntology(ontology); game = new GameHistory(getAID(), null, -1); handleArguments(); AID gamemasterAID = getGamemasterService(); ParallelBehaviour behaviour = new ParallelBehaviour(this, ParallelBehaviour.WHEN_ALL); behaviour.addSubBehaviour(createQueryProtocol()); behaviour.addSubBehaviour(createSubscriptionProtocol(gamemasterAID)); addBehaviour(behaviour); } catch (FIPAException e) { e.printStackTrace(); doDelete(); } } private AchieveREResponder createQueryProtocol() { MessageTemplate queryMessageTemplate = MessageTemplate.and( MessageTemplate.MatchProtocol(FIPANames.InteractionProtocol.FIPA_QUERY), MessageTemplate.MatchPerformative(ACLMessage.QUERY_IF)); AchieveREResponder arer = new AchieveREResponder(this, queryMessageTemplate) { @Override protected ACLMessage handleRequest(ACLMessage request) throws NotUnderstoodException, RefuseException { ACLMessage agree = request.createReply(); agree.setPerformative(ACLMessage.AGREE); return agree; } }; arer.registerPrepareResultNotification(usedStrategy); return arer; } private SubscriptionInitiator createSubscriptionProtocol(AID gamemasterAID) { ACLMessage subscribeMsg = new ACLMessage(ACLMessage.SUBSCRIBE); subscribeMsg.addReceiver(gamemasterAID); subscribeMsg.setProtocol(FIPANames.InteractionProtocol.FIPA_SUBSCRIBE); return new SubscriptionInitiator(this, subscribeMsg) { @Override protected void handleRefuse(ACLMessage refuse) { out("%s failed to subscribe", refuse.getSender().getName()); } @Override protected void handleAgree(ACLMessage agree) { out("%s agreed to subscribe", agree.getSender().getName()); super.handleAgree(agree); } @Override protected void handleInform(ACLMessage inform) { out("been informed by %s", inform.getSender().getName()); ContentElement msgContent = null; try { msgContent = getContentManager().extractContent(inform); } catch (Exception e) { e.printStackTrace(); return; } if (!(msgContent instanceof Round)) { out("ERROR: message content not Round"); return; } Round lastRound = (Round) msgContent; game.pushRound(lastRound); } }; } private AID getGamemasterService() throws FIPAException { DFAgentDescription gamemasterServiceTemplate = new DFAgentDescription(); ServiceDescription gamemasterServiceTemplateSD = new ServiceDescription(); gamemasterServiceTemplateSD.setType("prisoners-dilemma-gamemaster"); // TODO refactor into constant gamemasterServiceTemplateSD.addLanguages(FIPANames.ContentLanguage.FIPA_SL0); gamemasterServiceTemplateSD.addOntologies(ontology.getName()); gamemasterServiceTemplate.addServices(gamemasterServiceTemplateSD); SearchConstraints sc = new SearchConstraints(); sc.setMaxResults(1L); DFAgentDescription[] results = DFService.searchUntilFound(this, getDefaultDF(), gamemasterServiceTemplate, sc, 10000L); DFAgentDescription dfd = results[0]; AID gamemasterAID = dfd.getName(); // do we need this? Iterator it = dfd.getAllServices(); while (it.hasNext()) { ServiceDescription sd = (ServiceDescription) it.next(); if (sd.getType().equals("prisoners-dilemma-gamemaster")) out("found the following service: %s by %s", sd.getName(), gamemasterAID.getName()); } return gamemasterAID; } private void handleArguments() { Object[] args = getArguments(); if (args == null || args.length > 2) { out("Need to supply the strategy which the prisoner should use."); doDelete(); } try { Class clazz = Class.forName((String) args[0]); ArrayList<Class> constructorArgumentTypes = new ArrayList<Class>(); Constructor constructor; constructorArgumentTypes.add(Codec.class); constructorArgumentTypes.add(Ontology.class); constructorArgumentTypes.add(GameHistory.class); if (args.length - 1 > 0) for (int i = 1; i < args.length; i++) constructorArgumentTypes.add(String.class); constructor = clazz.getConstructor(constructorArgumentTypes.toArray(new Class[0])); ArrayList<Object> arguments = new ArrayList<Object>(constructorArgumentTypes.size()); arguments.add(codec); arguments.add(ontology); arguments.add(game); for (int i = 1; i < args.length; i++) arguments.add(args[i]); usedStrategy = (AbstractStrategyBehaviour) constructor.newInstance(arguments.toArray()); } catch (Exception e) { e.printStackTrace(); doDelete(); } if (usedStrategy == null) { out("ERROR: invalid strategy parameter supplied"); doDelete(); } out("Using strategy %s", usedStrategy); } @Override protected void takeDown() { out("Stopping"); } }