/***************************************************************************** * * Controleur: * ----------- * This class defines the Controleur agent, the agent facilitator for the * economic competition of the course IFT6802 - Systemes et Architecture * du Commerce electronique. * * Version 1.1 - 16 avril 2004 * Authors: Jean Vaucher * * 16 avril: - On elimine les messages orphelins * - Recode le redemarrage d'un agent en mettant a jour sa Cle * * 13 avril: - Bug trouvee par Bui corrigee * 12 avril: - Attribue les points comme specifie * - Elimine des Behaviours Contract Net qui trainent * Version 0.6: Corrige l'info expediee dans STATE pour que les # associes aus * colis soient #Proprietaire et non #contrat * Version 0.5: verifie et gere les transactions * Departement d'Informatique et de Recherche Operationnelle (DIRO). * Universite de Montreal. * * *******************************************************************************/ import jade.content.*; import jade.content.onto.*; import jade.content.onto.basic.*; import jade.content.lang.*; import jade.content.lang.sl.*; import jade.core.*; import jade.core.behaviours.*; import jade.gui.*; import jade.domain.*; import jade.domain.FIPAAgentManagement.*; import jade.domain.JADEAgentManagement.*; import jade.proto.ContractNetInitiator; import jade.wrapper.AgentContainer; import jade.wrapper.AgentController; import jade.lang.acl.*; import java.util.*; import java.awt.Rectangle; import java.awt.Point; //========================= External class ================================= public class Controleur extends JVGuiAgent implements Constants6802 // ---------------------------------------------------------------- { private int NJOURS = 7; private int NHEURES = 600; final String VERSION = "Controleur v1.1" ; transient protected TableauControle myGui; // The gui private int command = START; private ArrayList livreurs = new ArrayList(); private Set afficheurs ; List cn1 = new ArrayList(), cn2 = new ArrayList(); Robot findRobot( AID id) { for (Iterator it = livreurs.iterator(); it.hasNext();) { Robot r = (Robot) it.next(); if (r.aid.equals(id) ) return r; } return null; } Robot findRobot( String id ) { for (Iterator it = livreurs.iterator(); it.hasNext();) { Robot r = (Robot) it.next(); if (r.nom.equals(id) ) return r; } return null; } Set props = new HashSet(); int nColis = 0, maxColis = 20, TA = 10; int MaxN [] = {2,3,4,5,6,7,8}; int tick = 500; // Intervalle entre coups en msec int jour = 0; int heure= 0; TickerBehaviour tickB; Behaviour sellB, reqB; //========================= Set up this agent ================================ protected void setup() { // ------------------------ initialisation(); // Set up the gui myGui = new TableauControle(this, livreurs); myGui.setVisible(true); // Register in the DF ServiceDescription sd = new ServiceDescription(); sd.setType( CONTROLEUR ); sd.setName( VERSION ); sd.setOwnership("Prof6802"); register( sd ); //--> Subscribe with DF to receive notification every time an agent registers DFAgentDescription dfd = new DFAgentDescription(); sd = new ServiceDescription(); sd.setType(LIVREUR); dfd.addServices(sd); SearchConstraints sc = new SearchConstraints(); sc.setMaxResults(new Long(1)); sendMessage(DFService.createSubscriptionMessage(this, getDefaultDF(), dfd, sc)); sd.setType(AFFICHEUR); sendMessage(DFService.createSubscriptionMessage(this, getDefaultDF(), dfd, sc)); // ------------ ces 2 behaviours seront actifs en permanence --------------------- addBehaviour( new CyclicBehaviour( this ) { int n=0; public void action() { ACLMessage msg= receive(MessageTemplate.MatchPerformative( ACLMessage.CFP )); if (msg!=null) { Robot r = findRobot( msg.getSender()); if (r!=null) r.cfps++; } block(); } }); addBehaviour( new GCAgent( this, 5000)); addBehaviour( new CyclicBehaviour( this ) { public void action() { ACLMessage msg= receive(MessageTemplate.and (MessageTemplate.MatchSender( getAMS() ), MessageTemplate.MatchPerformative( ACLMessage.FAILURE ) )); if (msg!=null) { String body = msg.getContent(); int p1 = body.indexOf("MTS-error"); String s1 = body.substring(p1); p1 = s1.indexOf(":name"); int p2 = s1.indexOf("@"); s1 = s1.substring(p1+6, p2); System.out.println( "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ERREUR: /" + s1 + "/ inconnu de AMS" ); Robot r = findRobot( s1 ) ; if ( r != null ) r.up=false; else System.out.println( " Unknown Agent"); } block(); } }); addBehaviour(new RegistrationNotification(this)); addBehaviour(new TransactionChecker(this)); afficheurs = searchDF( AFFICHEUR ); } void initialisation() { // Initialisation d'une zone d'exclusion autour des destinations // ou les nouvelles piecesne doivent pas etre placee; makeXZ(1,1) ; makeXZ(1,XY_LIM-1) ; makeXZ(XY_LIM-1,1) ; makeXZ(XY_LIM-1,XY_LIM-1) ; penaltyZone.add( new Point(1,1) ) ; penaltyZone.add( new Point(1,XY_LIM) ) ; penaltyZone.add( new Point(XY_LIM,1) ) ; penaltyZone.add( new Point(XY_LIM,XY_LIM) ) ; // shuffling # colis for (int i=0; i< MaxN.length; i++) { int j = rnd.nextInt(MaxN.length); int tmp = MaxN[j]; MaxN[j] = MaxN[i]; MaxN[i] = tmp; } } void Start() { // -------------- Start a new day of competition println("----------------------- Debut de journee --------------------"); jour ++; heure = 0; tick = getVitesse( myGui. getVitesse() ); if (jour==1 && myGui.test.isSelected()) { NJOURS = 3; NHEURES = 200; } flushMessages(); grille = new Piece [XY_LIM+2] [XY_LIM+2]; Piece mur = new Mur(); for (int i=0; i= moy ) r.points ++; } ArrayList a = sort( livreurs ); trace(3,"" ); trace(3,"----------- Resultats - Jour " + jour + " ------"); for (Iterator it = a.iterator(); it.hasNext();) { Robot r = (Robot) it.next(); trace(3, r.nom + " : $" + r.argent ); if (ss.length()>0) ss += ","; ss += r.nom + "/" + r.argent ; } ACLMessage msg = newMsg( ACLMessage.INFORM, "STOP=" + ss); sendToLivreurs( msg); if (jour == NJOURS) { jour ++; ss = ""; trace(3,"" ); trace(3,"----------- Fin de competition ------------ " ); a = sort2( livreurs ); int max_profit = ((Robot)a.get(0)). cumul_argent; int point = 10; for (Iterator it = a.iterator(); it.hasNext();) { Robot r = (Robot) it.next(); int score_relatif = 10*r.cumul_argent/max_profit; r.points += Math.max( point, score_relatif); if (ss.length() > 0) ss += ","; ss += r.nom + "/" + r.cumul_argent + "/" + r.points; trace(3, r.nom + " : $" + r.cumul_argent + ", " + r.points + " points."); point --; } msg = newMsg( ACLMessage.INFORM, "FIN=" + ss); sendToLivreurs( msg); alertGui("Fin de Competition") ; } else addBehaviour ( new WakerBehaviour( this, 10000 ) { protected void handleElapsedTimeout() { alertGui("Depart") ; Start(); } }); updateGui(); } //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // BEHAVIOURS //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // =========================================================================== // =========================================================================== class RegistrationNotification extends CyclicBehaviour // =========================================================================== // =========================================================================== { RegistrationNotification(Agent a) { super(a); } public void action() { ACLMessage msg = receive( MessageTemplate.MatchSender(getDefaultDF()) ); if (msg != null) try { DFAgentDescription[] dfds = DFService.decodeNotification(msg.getContent()); for (int i = 0; i < dfds.length; ++i) { DFAgentDescription dfd = dfds[i]; AID agent = dfd.getName(); trace( agent.getLocalName() + " registered in DF"); String key = "", type = "", owner = ""; Iterator it = dfd.getAllServices(); while (it.hasNext()) { ServiceDescription sd = (ServiceDescription) it.next(); String s1 = sd.getType(); trace( " Type: " + s1); if (s1.equals( AFFICHEUR)) { type = AFFICHEUR; } else if (s1.equals( LIVREUR )) { type = LIVREUR; owner = sd.getOwnership(); } else if (s1.equals( "publicKey" )) { key = sd.getName(); // System.out.println( " Key: " + key); } } if (type.equals( LIVREUR ) ) { if ( owner != null) { alertGui( "Enregistrement: " + agent.getLocalName() ) ; Robot r = addLivreur( agent, owner, key ); String s = "ID="+r.id+","+ r.position.x+","+ r.position.y +","+ NJOURS +","+ NHEURES ; ACLMessage reply = newMsg( ACLMessage.INFORM, s, agent); send( reply ); updateGui(); } } else if (type.equals( AFFICHEUR )) afficheurs.add( agent ); } } catch (Exception ex) { ex.printStackTrace(); } else block(); } } Robot addLivreur( AID id, String owner, String key ) { if (owner.charAt(0) == '"') owner = owner.substring(1, owner.length()-1); Robot r = findRobot (id ); if (r == null) { r = new Robot( id, id.getLocalName(), owner, key); livreurs.add( r ); } else r.restart( key ); if (! props.contains( r )) { props.add( id ); } return r; } // =========================================================================== // =========================================================================== // CONTRACT - NET // =========================================================================== // =========================================================================== class SellingBehaviour extends WakerBehaviour { Colis colis; int j = jour; int n; public SellingBehaviour ( Agent a, long msec ) { super(a, msec ); } protected void handleElapsedTimeout() { if (heure < (NHEURES-4000/tick) && j == jour) addBehaviour( new SellingBehaviour(myAgent, 10+rnd.nextInt(tick*TA)) ); if ( nColis > maxColis ) return; colis = new Colis(); nColis ++; ACLMessage msg = new ACLMessage(ACLMessage.CFP); msg.setProtocol(FIPANames.InteractionProtocol.FIPA_CONTRACT_NET); for (Iterator it = livreurs.iterator(); it.hasNext();) { Robot r = (Robot) it.next(); if (r.up) { msg.addReceiver( r.aid ); n++; } } // We want to receive a reply in 4 secs msg.setReplyByDate(new Date(System.currentTimeMillis() + 4000)); msg.setContent( "CONTRACT="+ colis.id); // System.out.println(" --- " + (System.currentTimeMillis()-t0)/1000 + ": " + id + // " new CNet" ); Behaviour b; addBehaviour(b=new ContractNetInitiator(myAgent, msg) { protected void handleAllResponses(Vector responses, Vector acceptances) { int bestProposal = 0; AID bestProposer = null; ACLMessage accept = null; if (responses.size() != n ) alertGui( responses.size() + "/" + n + " agents ne repondent PLUS" ); Enumeration e = responses.elements(); while (e.hasMoreElements()) { ACLMessage msg = (ACLMessage) e.nextElement(); if (msg.getPerformative() == ACLMessage.PROPOSE) { ACLMessage reply = msg.createReply(); reply.setPerformative(ACLMessage.REJECT_PROPOSAL); acceptances.addElement(reply); int proposal = Integer.parseInt(msg.getContent()); Robot r = findRobot( msg.getSender() ); if (proposal > bestProposal && r.argent >= proposal) { bestProposal = proposal; bestProposer = msg.getSender(); accept = reply; } } } colis.place(); // Accept the proposal of the best proposer if (accept != null && heure0) data.append( "," ); data.append( p.dispString()); } for (Iterator it = livreurs.iterator(); it.hasNext();) { Robot r = (Robot) it.next(); for (int i = 0; i < r.load.size(); i++) data.append(",B-" + r.id + "-" + r.posString() + "-" + i); } // trace("State: " + data); msg = newMsg(ACLMessage.INFORM, "STATE=" + data.toString()); for (Iterator it = afficheurs.iterator(); it.hasNext();) { AID aid = (AID)it.next(); msg.addReceiver(aid); } // System.out.println(" ** Display data : " + data); send(msg); if (heure>=NHEURES) { alertGui( "Fin de la journee" ); endDay(); myAgent.removeBehaviour( this ); } } } // =========================================================================== // =========================================================================== // TransactionChecker // =========================================================================== // =========================================================================== class TransactionChecker extends CyclicBehaviour // -------------------------------------------------------- { TransactionChecker(Agent a) { super(a); } MessageTemplate mt = MessageTemplate.and( MessageTemplate.MatchProtocol( PROTOCOLE ), MessageTemplate.MatchPerformative( ACLMessage.ACCEPT_PROPOSAL )); public void action() { ACLMessage msg = receive( mt ); if (msg != null) { String erreurs = ""; String body = msg.getContent(); String atr [] = body.split("/"); String info = atr[0], sigPart = atr[1]; int contratID, px, py, dx, dy, prix, hlim; contratID=px=py=dx=dy=prix=hlim=0; Colis c = null; // Checking signatures atr = info.split(","); String sig [] = sigPart.split(","); Robot acheteur = findRobot( atr[0] ); Robot vendeur = findRobot( atr[1] ); if ( vendeur == null ) erreurs += ",7"; if ( acheteur == null ) erreurs += ",8"; try { contratID = Integer.parseInt( atr[2] ); px = Integer.parseInt( atr[3] ); py = Integer.parseInt( atr[4] ); dx = Integer.parseInt( atr[5] ); dy = Integer.parseInt( atr[6] ); prix = Integer.parseInt( atr[7] ); hlim = Integer.parseInt( atr[8] ); if (! Crypto.checkSignature( sig[0], info, acheteur.key) ) erreurs += ",5"; if (! Crypto.checkSignature( sig[1], info, vendeur.key) ) erreurs += ",6"; } catch (Exception e) { erreurs += ",0"; } if ( contratID == 0 ) erreurs += ",9"; else if ( vendeur != null) { c = findColis( vendeur.contrats.iterator(), contratID ); if ( c == null || vendeur.load.contains(c) ) erreurs += ",2"; else if ( px != c.position.x || py != c.position.y || dx != c.dest.x || dy != c.dest.y ) erreurs += ",4"; } if ( heure > hlim ) erreurs += ",3"; if ( acheteur != null && acheteur.argent < prix ) erreurs += ",1"; // -------------- verification terminee -------------------------- if ( erreurs == "" ) { c.owner = acheteur.id; vendeur.contrats.remove ( c ); acheteur.contrats.add ( c ); vendeur.argent += prix; acheteur.argent -= prix; alertGui("VENTE: " + atr[1] + " -> " + atr[0] + " $" + prix ); ACLMessage reply = msg.createReply(); reply.setPerformative( ACLMessage.CONFIRM ); reply.clearAllReceiver(); reply.addReceiver(acheteur.aid); reply.setContent(contratID + "," + c.value + "," + acheteur.argent); send( reply ); reply = msg.createReply(); reply.setPerformative( ACLMessage.CONFIRM ); reply.clearAllReceiver(); reply.addReceiver(vendeur.aid); reply.setContent(contratID + "," + vendeur.argent); send( reply ); } else // Problemes { trace(3, "Checking: " + body); trace(3," ERR: " + erreurs.substring(1,erreurs.length())); ACLMessage reply = msg.createReply(); reply.setPerformative( ACLMessage.FAILURE ); reply.setContent(atr[0]+ "," + atr[1] + erreurs); reply.clearAllReceiver(); sendToLivreurs( reply ); } } block(); } } //---------------------------- TransactionChecker -------------------- // ========================================================================== // Methodes utilitaires // ========================================================================== void register( ServiceDescription sd) // ----------------------------------------- { DFAgentDescription dfd = new DFAgentDescription(); dfd.setName(getAID()); try { DFAgentDescription list[] = DFService.search( this, dfd ); if ( list.length>0 ) DFService.deregister(this); dfd.addServices(sd); ServiceDescription sd2 = new ServiceDescription(); sd2.setType( LIVREUR ); sd2.setName( "Hari" ); dfd.addServices(sd2); ServiceDescription crypto = new ServiceDescription(); crypto.setType( "publicKey" ); crypto.setName( "K" + keys.getPublicKey() ); dfd.addServices(crypto); DFService.register(this, dfd); trace("Registration: OK"); } catch (FIPAException e) { trace( "DF registration failed: " + e.getMessage()); doDelete(); } } void sendToLivreurs( ACLMessage msg ) // -------------------------------------- { Iterator it; for (it = livreurs.iterator(); it.hasNext();) { Robot r = (Robot)it.next(); if (r.up) { msg.addReceiver( r.aid ); } } sendMessage(msg); } /* void sendTo( ACLMessage msg, Collection AidSet ) // ------------------------------------------------ { Iterator it; for (it = AidSet.iterator(); it.hasNext();) { AID aid = (AID)it.next(); msg.addReceiver(aid); } sendMessage(msg); } ---------------------------------------------------------- */ void flushMessages() // -------------------- { ACLMessage msg = receive(); if (msg == null ) return; trace("Flushing messages"); while (msg != null) { trace(3," " + Msg2String( msg )); msg = receive(); } } void outSet( Set set ) // -------------------- { int len = set.size(); Iterator it = set.iterator(); String s = "["; for (int i=0; i0) data.append( "," ); data.append( p == null ? " " : p.shortString() ); } return data.toString(); } void doMove() // ------------------------------------------------------------------- { if (penaltyZone.contains( position )) blockN++; else blockN = 0; if (blockN>4) { grille[position.x][position.y]= null; position = placer(this); alertGui("AMENDE pour blockage ($10): " + nom); argent -= 10; blockN = 0; return; } if (dir == 8) return; int dir2 = dir; dir = 8; Point d2 = nextPoint( position, dir2 ); Piece voisin = grille[d2.x][d2.y]; if (voisin==null) { grille[position.x][position.y]= null; grille[d2.x][d2.y]= this; position = d2; } else if ( voisin instanceof Mur || voisin instanceof Robot) { } else if ( voisin instanceof Colis && load.size() < MAX_LOAD ) { Colis c = (Colis) voisin; if ( c.owner == 0) { c.owner = id; ACLMessage msg = newMsg( ACLMessage.ACCEPT_PROPOSAL, c.getContrat(), aid); msg.setProtocol("Pickup"); send(msg); } if ( c.owner == id ) { // contrats.remove( c ); load.add( c ); props.remove( c ); grille[position.x][position.y]= null; grille[d2.x][d2.y]= this; position = d2; } } } }//end Robot // Tris en ordre descendant ArrayList sort( ArrayList l ) { ArrayList a = (ArrayList)l.clone(); Collections.sort( a, new Comparator() { public int compare(Object o1, Object o2) { Robot r1 = (Robot) o1, r2 = (Robot) o2; return r2.argent - r1.argent; } public boolean equals(Object o1, Object o2) { Robot r1 = (Robot) o1, r2 = (Robot) o2; return r1.argent == r2.argent; } }); return a; } ArrayList sort2( ArrayList l ) { ArrayList a = (ArrayList)l.clone(); Collections.sort( a, new Comparator() { public int compare(Object o1, Object o2) { Robot r1 = (Robot) o1, r2 = (Robot) o2; return r2.cumul_argent - r1.cumul_argent; } public boolean equals(Object o1, Object o2) { Robot r1 = (Robot) o1, r2 = (Robot) o2; return r1.cumul_argent == r2.cumul_argent; } }); return a; } // ---------------------------------------------------------------------- class Colis extends Piece // ---------------------------------------------------------------------- { int value = rnd.nextInt(20)+10; int owner = 0; Point dest; Rectangle zone; public Colis() { c = 'C'; id = ++contractNum; switch (rnd.nextInt(4)) { case 0: dest = new Point(1,1); break; case 1: dest = new Point(1,XY_LIM); break; case 2: dest = new Point(XY_LIM,1); break; case 3: dest = new Point(XY_LIM,XY_LIM); } } public Colis( Contrat c) { id = c.id; owner = c.owner; value = c.value; position = c.pos; dest = c.dest; } void place() { int dx = XY_LIM/2 ; int x0 = (dest.x==1 ? 1 : XY_LIM-dx); int y0 = (dest.y==1 ? 1 : XY_LIM-dx); int x, y; Point pt = null; do { x = x0+rnd.nextInt(dx); y = y0+rnd.nextInt(dx); pt = new Point(x,y); } while ( grille[x][y] != null || forbiddenZone.contains( pt )); grille[x][y] = this; props.add( this ); position = pt; int d = distance( position, dest ); value = 10 + d + rnd.nextInt( d ) ; } String dispString() { return c+"-"+owner+"-"+position.x+"-"+position.y; } String shortString() { return c+"-"+owner ; } String msg() { return id + ","+ position.x + ","+ position.y + ","+ dest.x + ","+ dest.y + ","+ value ; } public String toString(){ return "Colis: " + id + "/" + owner + ",["+ dest.x + "-"+ dest.y + "] $"+ value ; } Contrat getContrat() { return new Contrat(id,owner,value,position, dest); } } Colis findColis( Iterator it, int id ) { while (it.hasNext() ) { Colis c = (Colis) it.next(); if (c.id == id ) return c; } return null; } class Mur extends Piece { public Mur() { c = 'X'; } String shortString() { return ""+c ; } } // =========================================================================== // Following methods handle interactions with the gui // =========================================================================== void updateGui() { myGui.dataModel.fireTableDataChanged(); } void updateData(int row, int col) {} void alertGui(String response) { // -------------------------------- Process the response of the server // to the gui for display myGui.alertResponse(response); } void resetStatusGui() { // ----------------------- Reset the status of the gui myGui.resetStatus(); } protected void onGuiEvent(GuiEvent ev) { // ---------------------------------------- Receive user command via the gui command = ev.getType(); if (command == START) { jour = 0; heure = 0; Start(); } else if (command == TRACE) { niveau_trace = Integer.parseInt( (String) ev.getParameter(0)) ; } else if (command == VITESSE) { tick = getVitesse( (String) ev.getParameter(0) ); if (tickB!=null) tickB.reset( tick ); } else if (command == QUIT) { myGui.alertResponse("Bye!"); doDelete(); System.exit(0); } } int getVitesse(String s) { int tick = 500; try { int vit = Integer.parseInt( s ) ; if (vit == 0) tick = 1000; else if (vit == 1) tick = 500; else if (vit == 2) tick = 350; else if (vit == 3) tick = 200; else tick = 100; } catch (Exception e){} return tick; } // ========================================================================== // ========================================================================== // Deplacement des Robots // ========================================================================== // ========================================================================== private Piece [] [] grille = new Piece [XY_LIM+2] [XY_LIM+2] ; Set forbiddenZone = new HashSet(); Set penaltyZone = new HashSet(); void makeXZ(int x, int y) { for (int i = 0; i< 2; i++) for (int j = 0; j< 2; j++) forbiddenZone . add( new Point(x+i, y+j) ); } Point placer( Piece p ) // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< { int x, y; Point pt = null; do { x = 1+rnd.nextInt(XY_LIM); y = 1+rnd.nextInt(XY_LIM); pt = new Point(x,y); } while ( grille[x][y] != null || forbiddenZone.contains( pt )); grille[x][y] = p; props.add( p ); return pt; } Point nextPoint( Point p, int dir) { int x=p.x, y = p.y; int x2=x, y2=y; switch (dir) { case 0: x2=x-1; y2=y-1; break; case 1: x2=x ; y2=y-1; break; case 2: x2=x+1; y2=y-1; break; case 3: x2=x+1; y2=y; break; case 4: x2=x+1; y2=y+1; break; case 5: x2=x ; y2=y+1; break; case 6: x2=x-1; y2=y+1; break; case 7: x2=x-1; y2=y ; break; } return new Point(x2,y2); } static int inDir(Point p2, Point p1, int dir) { int dx = p2.x-p1.x; int dy = p1.y-p2.y; switch (dir) { case 0: return dy-dx; case 1: return dy; case 2: return dx+dy; case 3: return dx; case 4: return dx-dy; case 5: return -dy; case 6: return -dx-dy; case 7: return -dx; } return 0; } int distance( Point p1, Point p2 ) { return Math.max( Math.abs(p1.x-p2.x), Math.abs(p1.y-p2.y)); } static int newX ( int x, int dir ) { switch (dir) { case 0: case 6: case 7: return x-1; case 2: case 3: case 4: return x+1; } return x; } static int newY ( int y, int dir ) { switch (dir) { case 0: case 1: case 2: return y-1; case 4: case 5: case 6: return y+1; } return y; } // ----- clean-up agent which takes old messages out of the queue class GCAgent extends TickerBehaviour { Set seen = new HashSet(), old = new HashSet(); GCAgent( Agent a, long dt) { super(a,dt); } protected void onTick() { ACLMessage msg = myAgent.receive(); while (msg != null) { if (! old.contains(msg)) seen.add( msg); else { System.out.println("==== Flushing message:"); dumpMessage( msg ); if (msg.getPerformative() == ACLMessage.PROPOSE ) { ACLMessage reply = msg.createReply(); reply.setPerformative(ACLMessage.REJECT_PROPOSAL); send(reply); } } msg = myAgent.receive(); } for( Iterator it = seen.iterator(); it.hasNext(); ) myAgent.putBack( (ACLMessage) it.next() ); old.clear(); Set tmp = old; old = seen; seen = tmp; } } // ---------- Message print-out -------------------------------------- static long t0 = System.currentTimeMillis(); void dumpMessage( ACLMessage msg ) { System.out.print( "t=" + (System.currentTimeMillis()-t0)/1000F + " in " + getLocalName() + ": " + ACLMessage.getPerformative(msg.getPerformative() )); System.out.print( " from: " + (msg.getSender()==null ? "null" : msg.getSender().getLocalName()) + " --> to: "); for ( Iterator it = msg.getAllReceiver(); it.hasNext();) System.out.print( ((AID) it.next()).getLocalName() + ", "); System.out.println( " cid: " + msg.getConversationId()); String s1 = msg.getContent(); if (s1.length() > 40) s1 = s1.substring(0,40) + ".... "; System.out.println( " content: " + s1); } }//end class Controleur