|
From: <jom...@us...> - 2008-05-31 11:11:34
|
Revision: 1319
http://jason.svn.sourceforge.net/jason/?rev=1319&view=rev
Author: jomifred
Date: 2008-05-31 04:11:27 -0700 (Sat, 31 May 2008)
Log Message:
-----------
add gui examples
add food-simulation example
Modified Paths:
--------------
trunk/release-notes.txt
Added Paths:
-----------
trunk/demos/gui/
trunk/demos/gui/gui1/
trunk/demos/gui/gui1/gui/
trunk/demos/gui/gui1/gui/yes_no.java
trunk/demos/gui/gui1/gui1.mas2j
trunk/demos/gui/gui1/sample.asl
trunk/demos/gui/gui2/
trunk/demos/gui/gui2/gui/
trunk/demos/gui/gui2/gui/create.java
trunk/demos/gui/gui2/gui2.mas2j
trunk/demos/gui/gui2/sample.asl
trunk/demos/gui/readme.txt
trunk/examples/food-simulation/
trunk/examples/food-simulation/FoodSimulation.mas2j
trunk/examples/food-simulation/lib/
trunk/examples/food-simulation/lib/jcommon-1.0.12.jar
trunk/examples/food-simulation/lib/jfreechart-1.0.8a.jar
trunk/examples/food-simulation/src/
trunk/examples/food-simulation/src/asl/
trunk/examples/food-simulation/src/asl/blind.asl
trunk/examples/food-simulation/src/asl/normative.asl
trunk/examples/food-simulation/src/asl/reputation.asl
trunk/examples/food-simulation/src/asl/strategic.asl
trunk/examples/food-simulation/src/java/
trunk/examples/food-simulation/src/java/FoodEnvironment.java
trunk/examples/food-simulation/src/java/FoodModel.java
trunk/examples/food-simulation/src/java/FoodView.java
trunk/examples/food-simulation/src/java/bb/
trunk/examples/food-simulation/src/java/bb/list.java
trunk/examples/food-simulation/src/java/math/
trunk/examples/food-simulation/src/java/math/distance.java
trunk/src/jason/asSemantics/SuspendInternalAction.java
Removed Paths:
-------------
trunk/src/jason/asSemantics/SynchronousInternalAction.java
Added: trunk/demos/gui/gui1/gui/yes_no.java
===================================================================
--- trunk/demos/gui/gui1/gui/yes_no.java (rev 0)
+++ trunk/demos/gui/gui1/gui/yes_no.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,49 @@
+package gui;
+
+import jason.asSemantics.*;
+import jason.asSyntax.*;
+import java.util.logging.*;
+
+import javax.swing.JOptionPane;
+
+public class yes_no extends SuspendInternalAction {
+
+ private Logger logger = Logger.getLogger("gui."+yes_no.class.getName());
+
+ @Override
+ public Object execute(final TransitionSystem ts, Unifier un, final Term[] args) throws Exception {
+ try {
+ // suspend the intention (max 5 seconds)
+ final String key = suspend(ts, "gui", 5000);
+
+ // to not block the agent thread,
+ // create a new thread that show the GUI and resume the intention latter
+ new Thread() {
+ public void run() {
+ int answer = JOptionPane.showConfirmDialog(null, args[0].toString());
+ // resume the intention with success
+ if (answer == JOptionPane.YES_OPTION)
+ yes_no.this.resume(ts, key);
+ else
+ fail(ts, key);
+ }
+ }.start();
+
+ return true;
+ } catch (Exception e) {
+ logger.warning("Error in internal action 'gui.yes_no'! "+e);
+ }
+ return false;
+ }
+
+ /** called back when some intention should be resumed/failed by timeout */
+ @Override
+ public void timeout(TransitionSystem ts, String intentionKey) {
+ // this method have to decide what to do with actions finished by timeout
+ // 1: resume
+ //resume(ts,intentionKey);
+
+ // 2: fail
+ fail(ts, intentionKey);
+ }
+}
Property changes on: trunk/demos/gui/gui1/gui/yes_no.java
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/demos/gui/gui1/gui1.mas2j
===================================================================
--- trunk/demos/gui/gui1/gui1.mas2j (rev 0)
+++ trunk/demos/gui/gui1/gui1.mas2j 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,15 @@
+/* Jason Project
+
+ Simple exaple of GUI: and internal action is used to ask something for the user
+
+*/
+
+MAS gui1 {
+
+ infrastructure: Centralised
+
+ agents:
+ sample;
+
+}
+
Added: trunk/demos/gui/gui1/sample.asl
===================================================================
--- trunk/demos/gui/gui1/sample.asl (rev 0)
+++ trunk/demos/gui/gui1/sample.asl 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,19 @@
+/* Initial goals */
+
+!start.
+!print.
+
+/* Plans */
+
+
+// the internal action gui.yes_no succeed if the user click Yes and fails otherwise
+//
+// note that this IA blocks only the intention using it (the !start) and not all the
+// intentions (the agent continues to print "." while the interface is being shown
+
++!start <- gui.yes_no("Is it Ok?"); .print(ok).
+-!start <- .print(nok).
+
++!print <- .wait(500); .print("."); !!print.
+
+
Added: trunk/demos/gui/gui2/gui/create.java
===================================================================
--- trunk/demos/gui/gui2/gui/create.java (rev 0)
+++ trunk/demos/gui/gui2/gui/create.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,63 @@
+package gui;
+
+import jason.asSemantics.DefaultInternalAction;
+import jason.asSemantics.TransitionSystem;
+import jason.asSemantics.Unifier;
+import jason.asSyntax.Literal;
+import jason.asSyntax.StringTerm;
+import jason.asSyntax.Term;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JLabel;
+
+/** internal action that creates a simple GUI with two buttons that trigger AS plans */
+public class create extends DefaultInternalAction {
+
+ int runCount = 0;
+
+ @Override
+ public Object execute(final TransitionSystem ts, Unifier un, Term[] args) throws Exception {
+
+ // get the window title
+ String title = ((StringTerm)args[0]).getString();
+
+ // create the windows
+ final JButton run = new JButton("run");
+ final JButton stop = new JButton("stop");
+ stop.setEnabled(false);
+ JPanel buttons = new JPanel();
+ buttons.add(new JLabel("Use the following buttons to control the agent intentions: "));
+ buttons.add(run);
+ buttons.add(stop);
+
+ JFrame frame = new JFrame(title);
+ frame.getContentPane().add(buttons);
+ frame.pack();
+ frame.setVisible(true);
+
+ // add the event listeners
+ run.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ // creates a new event +!run so that the agent can react to the button
+ runCount++;
+ ts.getC().addAchvGoal(Literal.parseLiteral("run("+runCount+")"), null);
+ stop.setEnabled(true);
+ run.setEnabled(false);
+ }
+ });
+ stop.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ ts.getC().addAchvGoal(Literal.parseLiteral("stop("+runCount+")"), null);
+ stop.setEnabled(false);
+ run.setEnabled(true);
+ }
+ });
+
+ return true;
+ }
+}
Added: trunk/demos/gui/gui2/gui2.mas2j
===================================================================
--- trunk/demos/gui/gui2/gui2.mas2j (rev 0)
+++ trunk/demos/gui/gui2/gui2.mas2j 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,16 @@
+/*
+ Jason Project
+
+ Example of GUI that create events the agent can react to.
+
+ -- created on May 30, 2008
+*/
+
+
+
+MAS gui2 {
+ infrastructure: Centralised
+
+ agents:
+ sample;
+}
\ No newline at end of file
Added: trunk/demos/gui/gui2/sample.asl
===================================================================
--- trunk/demos/gui/gui2/sample.asl (rev 0)
+++ trunk/demos/gui/gui2/sample.asl 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,15 @@
+
+/* Initial goals */
+
+!start.
+
+/* Plans */
+
++!start <- gui.create("Example GUI").
+
+// the event !run is created by the GUI
++!run(X) <- .print("running ",X,"...."); .wait(100); !!run(X).
+
+
+// the event !stop is created by the GUI
++!stop(X) <- .drop_desire(run(X)).
Added: trunk/demos/gui/readme.txt
===================================================================
--- trunk/demos/gui/readme.txt (rev 0)
+++ trunk/demos/gui/readme.txt 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,18 @@
+There are many ways of creating GUI for Jason agents.
+All of them relies on Java.
+
+This directory contains the following examples:
+
+gui1: uses and internal action to ask something to the user
+
+gui2: creates a window with buttons that, when pressed,
+ produce events the agent can react to.
+
+
+Some examples of Jason also use GUI:
+
+auction: uses a customised agent architecture that provides special
+ actions to show information in a GUI
+
+domestic-robot, iterated-prisoners-dilemma, and many others: the GUI
+ is implemented and maintained by the environment.
\ No newline at end of file
Added: trunk/examples/food-simulation/FoodSimulation.mas2j
===================================================================
--- trunk/examples/food-simulation/FoodSimulation.mas2j (rev 0)
+++ trunk/examples/food-simulation/FoodSimulation.mas2j 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,66 @@
+/*
+ Jason Project
+
+ -- create on December 20, 2007
+
+ -- Food Simulation --
+
+ based on the description available at
+ http://jasss.soc.surrey.ac.uk/1/3/3.html
+
+*/
+
+/*
+
+The environment implementation provides the following perception and actions
+
+Percepts:
+. step(X): the step X has started.
+
+. food(X,Y,P,O): food perception
+ X is the column
+ Y is the line
+ P can be
+ my_pos if the food is the same location as the agent
+ see if the food is in the agent's territory
+ smell if the food is two steps away from the agent
+ O is the agent allocated to the food, -1 if none
+
+. pos(AgId,X,Y): agent position
+ AgId the agent's identification in the environment
+
+. agent(AgId, X, Y, S, A): perception of other agents in the agent's territory
+ AgId is the identification of the other agent
+ S is its strength
+ A is its action (moving or eating)
+
+. strength(S): the strength of the agent
+
+. attacked(AgId,Name): the agent is beign attacked by AgId
+
+
+
+Actions:
+. eat
+. move(X,Y)
+. attack(X,Y)
+. random_move
+. pause
+
+*/
+
+
+MAS normative_simulation {
+ // the class that implements the environment is FoodEnvironment
+ // parameters are: grid size, number of agents, number of food units
+ environment: FoodEnvironment(10,50,25)
+
+ agents:
+ //blind [verbose=0] #50;
+ strategic [verbose=0] #25;
+ //normative [verbose=0] #25;
+ //normativerule [verbose=0] #50;
+ reputation [verbose=0] #25;
+
+ aslSourcePath: "src/asl";
+}
\ No newline at end of file
Property changes on: trunk/examples/food-simulation/FoodSimulation.mas2j
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/lib/jcommon-1.0.12.jar
===================================================================
(Binary files differ)
Property changes on: trunk/examples/food-simulation/lib/jcommon-1.0.12.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/examples/food-simulation/lib/jfreechart-1.0.8a.jar
===================================================================
(Binary files differ)
Property changes on: trunk/examples/food-simulation/lib/jfreechart-1.0.8a.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/examples/food-simulation/src/asl/blind.asl
===================================================================
--- trunk/examples/food-simulation/src/asl/blind.asl (rev 0)
+++ trunk/examples/food-simulation/src/asl/blind.asl 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,14 @@
+// rule 1: food in my position
++step(_) : food(X,Y,my_pos,_) <- eat.
+
+// rule 2: food I see
++step(_) : food(X,Y,see,_) & not agent(_,X,Y,_,_) <- move(X,Y).
+
+// rule 3: food I see
++step(_) : food(X,Y,see,_) & agent(_,X,Y,_,eating) <- attack(X,Y).
+
+// rule 4: food I smell
++step(_) : food(X,Y,smell,_) <- move(X,Y).
+
+// rule 5
++step(_) <- random_move.
Property changes on: trunk/examples/food-simulation/src/asl/blind.asl
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/src/asl/normative.asl
===================================================================
--- trunk/examples/food-simulation/src/asl/normative.asl (rev 0)
+++ trunk/examples/food-simulation/src/asl/normative.asl 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,16 @@
+
+// food in my position
++step(_) : food(X,Y,my_pos,A) & (pos(A,_,_) | A == -1) <- eat.
+
+// food I see
++step(_) : food(X,Y,see,Me) & pos(Me,_,_) & not agent(_,X,Y,_,_) <- move(X,Y).
++step(_) : food(X,Y,see,-1) & not agent(_,X,Y,_,_) <- move(X,Y).
++step(_) : food(X,Y,see,OAg) & agent(AgId,X,Y,_,eating) &
+ AgId \== OAg & OAg \== -1
+ <- attack(X,Y).
+
+// food I smell
++step(_) : food(X,Y,smell,Me) & pos(Me,_,_) <- move(X,Y).
++step(_) : food(X,Y,smell,-1) <- move(X,Y).
+
++step(_) <- random_move.
Property changes on: trunk/examples/food-simulation/src/asl/normative.asl
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/src/asl/reputation.asl
===================================================================
--- trunk/examples/food-simulation/src/asl/reputation.asl (rev 0)
+++ trunk/examples/food-simulation/src/asl/reputation.asl 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,26 @@
+
+// food in my position
++step(_) : food(_,_,my_pos,A) & (pos(A,_,_) | A == -1 | cheater(A)) <- eat.
+
+// food I see
++step(_) : food(X,Y,see,Me) & pos(Me,_,_) & not agent(_,X,Y,_,_) <- move(X,Y).
++step(_) : food(X,Y,see,-1) & not agent(_,X,Y,_,_) <- move(X,Y).
++step(_) : food(X,Y,see,_) & agent(AgId,X,Y,S,eating) &
+ cheater(AgId) &
+ strength(MS) & MS > S
+ <- attack(X,Y).
+
+
+// food I smell
++step(_) : food(X,Y,smell,Me) & pos(Me,_,_) <- move(X,Y).
++step(_) : food(X,Y,smell,-1) <- move(X,Y).
+
++step(_) <- random_move.
+
+
+// reputation model
+
++attacked(A,_) <- +cheater(A); .broadcast(tell, cheater(A)).
+
+//+new_cheater(A,N) <- +cheater(A)[name(N)]; -new_cheater(A,N)[source(_)].
+
Property changes on: trunk/examples/food-simulation/src/asl/reputation.asl
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/src/asl/strategic.asl
===================================================================
--- trunk/examples/food-simulation/src/asl/strategic.asl (rev 0)
+++ trunk/examples/food-simulation/src/asl/strategic.asl 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,13 @@
+
+// food in my position
++step(_) : food(X,Y,my_pos,_) <- eat.
+
+// food I see
++step(_) : food(X,Y,see,_) & not agent(_,X,Y,_,_) <- move(X,Y).
++step(_) : food(X,Y,see,_) & agent(_,X,Y,S,eating) & strength(MS) & MS > S <- attack(X,Y).
+
+// food I smell
++step(_) : food(X,Y,smell,_) <- move(X,Y).
+
+// nothing else
++step(_) <- random_move.
Property changes on: trunk/examples/food-simulation/src/asl/strategic.asl
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/src/java/FoodEnvironment.java
===================================================================
--- trunk/examples/food-simulation/src/java/FoodEnvironment.java (rev 0)
+++ trunk/examples/food-simulation/src/java/FoodEnvironment.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,247 @@
+// Environment code for project game-of-life.mas2j
+
+import jason.asSyntax.Atom;
+import jason.asSyntax.Literal;
+import jason.asSyntax.NumberTerm;
+import jason.asSyntax.NumberTermImpl;
+import jason.asSyntax.Structure;
+import jason.environment.SteppedEnvironment;
+import jason.environment.grid.Location;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+public class FoodEnvironment extends SteppedEnvironment {
+
+ private Logger logger = Logger.getLogger("game-of-life.mas2j."+FoodEnvironment.class.getName());
+
+ private FoodModel model;
+ private FoodView view;
+
+ private Literal lstep; // current step
+ private Atom aMyPos = new Atom("my_pos");
+ private Atom aSee = new Atom("see");
+ private Atom aSmell = new Atom("smell");
+
+ Map<String,Integer> ag2id = new HashMap<String,Integer>();
+ Map<Integer,String> id2ag = new HashMap<Integer,String>();
+
+ /** Called before the MAS execution with the args informed in .mas2j */
+ @Override
+ public void init(String[] args) {
+ super.init(new String[] { "1000" } ); // set step timeout
+ setOverActionsPolicy(OverActionsPolicy.ignoreSecond);
+
+ model = new FoodModel(Integer.parseInt(args[0]), Integer.parseInt(args[1]), Integer.parseInt(args[2]));
+ view = new FoodView(model, this);
+ model.setView(view);
+ }
+
+ @Override
+ public List<Literal> getPercepts(String agName) {
+ // if the agent is not in the map, add it and update its perception
+ if (ag2id.get(agName) == null) {
+ updateAgPercept(addAg2IdMap(agName));
+ }
+ return super.getPercepts(agName);
+ }
+
+ private static int lastUsedId = -1;
+ private synchronized int addAg2IdMap(String agName) {
+ lastUsedId++;
+ ag2id.put(agName,lastUsedId);
+ id2ag.put(lastUsedId, agName);
+ return lastUsedId;
+ }
+
+ @Override
+ public boolean executeAction(String agName, Structure action) {
+ String actId = action.getFunctor();
+ if (actId.equals("pause"))
+ return true;
+
+ int agId = ag2id.get(agName);
+ try {
+ if (actId.equals("eat")) {
+ model.eat(agId);
+ } else if (actId.equals("move")) {
+ int x = (int)(((NumberTerm)(action.getTerm(0))).solve());
+ int y = (int)(((NumberTerm)(action.getTerm(1))).solve());
+ model.move(agId, x, y);
+ } else if (actId.equals("attack")) {
+ int x = (int)(((NumberTerm)(action.getTerm(0))).solve());
+ int y = (int)(((NumberTerm)(action.getTerm(1))).solve());
+ model.attack(agId, x, y);
+ } else if (actId.equals("random_move")) {
+ model.randomMove(agId);
+ } else {
+ logger.warning("Unknown action: "+action);
+ }
+ } catch (Exception e) {}
+ return true;
+ }
+
+ @Override
+ protected int requiredStepsForAction(String agName, Structure action) {
+ if (action.getFunctor().equals("eat")) {
+ return 3; // eat takes 2 steps
+ }
+ return super.requiredStepsForAction(agName, action);
+ }
+
+ @Override
+ protected void stepStarted(int step) {
+ //logger.info("start step "+step);
+ lstep = new Literal("step");
+ lstep.addTerm(new NumberTermImpl(step+1));
+ }
+
+ long sum = 0;
+ List<Double> strategicValues = new ArrayList<Double>();
+ List<Double> reputationValues = new ArrayList<Double>();
+
+
+ @Override
+ protected void stepFinished(int step, long time, boolean timeout) {
+ if (step % 100 == 0) {
+ long mean = (step > 0 ? sum / step : 0);
+ logger.info(String.format("step %10d finished in %3d ms. Str/Var/Att %7.0f %7.0f %7d", step, mean, +model.getStrengthMean(),model.getVarianceOfStrength(),model.getAttackCounter() ));
+ //logger.info(String.format(" Strategic Str/Var/Att %7.0f", getStrength("strategic") ));
+ //logger.info(String.format(" Normative Str/Var/Att %7.0f", getStrength("normative") ));
+ //logger.info(String.format(" Reputation Str/Var/Att %7.0f", getStrength("reputation") ));
+
+ if (view != null) {
+ view.addSerie("strategic", getData(strategicValues));
+ view.addSerie("reputation", getData(reputationValues));
+ }
+ }
+ sum += time;
+ strategicValues.add(getStrength("strategic"));
+ reputationValues.add(getStrength("reputation"));
+ }
+
+
+ double getStrength(String typeOfAg) {
+ double sum = 0;
+ double q = 0;
+ for (int i=0; i<getNbAgs(); i++) {
+ if (id2ag.get(i).startsWith(typeOfAg)) {
+ sum += model.getAgStrength(i);
+ q++;
+ }
+ }
+ if (q > 0)
+ return sum / q;
+ else
+ return 0;
+ }
+
+ private double[][] getData(List<Double> values) {
+ double[][] r = new double[2][values.size()];
+ int i = 0;
+ for (double v: values) {
+ r[0][i] = i;
+ r[1][i] = v;
+ i++;
+ }
+ return r;
+ }
+
+ @Override
+ protected void updateAgsPercept() {
+ for (int i = 0; i < model.getNbOfAgs(); i++) {
+ updateAgPercept(i);
+ }
+ }
+
+ void updateAgPercept(int ag) {
+ //if (ag < 0 || ag >= model.getNbOfAgs()) return;
+ String name = id2ag.get(ag);
+ if (name != null) {
+ updateAgPercept(name, ag);
+ } else {
+ logger.warning("Can not give perception to "+ag+" bacause it is no registered!");
+ }
+ }
+
+ void updateAgPercept(String agName, int ag) {
+ clearPercepts(agName);
+
+ Location l = model.getAgPos(ag);
+ Literal lpos = new Literal("pos");
+ lpos.addTerm(new NumberTermImpl(ag));
+ lpos.addTerm(new NumberTermImpl(l.x));
+ lpos.addTerm(new NumberTermImpl(l.y));
+ addPercept(agName, lpos);
+
+ Literal lstrength = new Literal("strength");
+ lstrength.addTerm(new NumberTermImpl(model.getAgStrength(ag)));
+ addPercept(agName, lstrength);
+
+ testAg(agName, l.x - 1, l.y);
+ testAg(agName, l.x + 1, l.y);
+ testAg(agName, l.x, l.y + 1);
+ testAg(agName, l.x, l.y - 1);
+
+ testFood(agName, ag, aMyPos, l.x, l.y);
+ testFood(agName, ag, aSee, l.x - 1, l.y);
+ testFood(agName, ag, aSee, l.x + 1, l.y);
+ testFood(agName, ag, aSee, l.x, l.y + 1);
+ testFood(agName, ag, aSee, l.x, l.y - 1);
+
+ testFood(agName, ag, aSmell, l.x, l.y - 2);
+ testFood(agName, ag, aSmell, l.x, l.y + 2);
+ testFood(agName, ag, aSmell, l.x+1, l.y - 1);
+ testFood(agName, ag, aSmell, l.x+1, l.y + 1);
+ testFood(agName, ag, aSmell, l.x+2, l.y);
+ testFood(agName, ag, aSmell, l.x-2, l.y);
+ testFood(agName, ag, aSmell, l.x-1, l.y - 1);
+ testFood(agName, ag, aSmell, l.x-1, l.y + 1);
+
+ addPercept(agName, lstep);
+
+ int a = model.isAttacked(ag);
+ if (a >= 0) {
+ addPercept(agName, Literal.parseLiteral("attacked("+a+","+id2ag.get(a)+")"));
+ }
+ }
+
+ void testFood(String agName, int ag, Atom where, int x, int y) {
+ if (model.hasObject(FoodModel.FOOD, x, y)) {
+ Literal f = new Literal("food");
+ f.addTerm(new NumberTermImpl(x));
+ f.addTerm(new NumberTermImpl(y));
+ f.addTerm(where);
+ f.addTerm(new NumberTermImpl(model.getFoodOwner(x, y)));
+ addPercept(agName, f);
+ }
+ }
+
+ private static Atom aEating = new Atom("eating");
+ private static Atom aMoving = new Atom("moving");
+ void testAg(String agName, int x, int y) {
+ int other = model.getAgAtPos(x, y);
+ if (other >= 0) {
+ Literal f = new Literal("agent"); // seeing
+ f.addTerm(new NumberTermImpl(other));
+ f.addTerm(new NumberTermImpl(x));
+ f.addTerm(new NumberTermImpl(y));
+ f.addTerm(new NumberTermImpl(model.getAgStrength(other)));
+
+ if (isEating(agName)) {
+ f.addTerm(aEating);
+ } else {
+ f.addTerm(aMoving);
+ }
+ addPercept(agName, f);
+ }
+ }
+
+ private boolean isEating(String agName) {
+ Structure actInSchedule = getActionInSchedule(agName);
+ return actInSchedule != null && actInSchedule.getFunctor().equals("eat");
+ }
+}
Property changes on: trunk/examples/food-simulation/src/java/FoodEnvironment.java
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/src/java/FoodModel.java
===================================================================
--- trunk/examples/food-simulation/src/java/FoodModel.java (rev 0)
+++ trunk/examples/food-simulation/src/java/FoodModel.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,203 @@
+import jason.environment.grid.GridWorldModel;
+import jason.environment.grid.Location;
+
+/** class that implements the Model of the Food application */
+public class FoodModel extends GridWorldModel {
+
+ public static final int FOOD = 16; // represent a cell with food
+
+ public static final int INITIAL_STR = 40;
+ public static final int FOOD_NUTRITIVE_VALUE = 20;
+ public static final int MOVING_COST = 1;
+ public static final int ATTACK_COST = 4;
+
+ //private Logger logger = Logger.getLogger(FoodModel.class.getName());
+
+ int[] strengths;
+ int[] attacked;
+ int[][] owner; // the owner (agent id) of each food
+ private int attackCount = 0;
+
+ public FoodModel(int size, int ags, int foods) {
+ super(size, size, ags);
+
+ strengths = new int[ags];
+ attacked = new int[ags];
+ owner = new int[size][size];
+
+ // create agents
+ for (int i=0; i<ags; i++) {
+ setAgPos(i, getFreePos());
+ strengths[i] = INITIAL_STR;
+ }
+
+ // set attackers
+ clearAttackers();
+
+ // create food
+ for (int i=0; i<foods; i++) {
+ add(FOOD, getFreePos(FOOD));
+ }
+ setFoodOwners();
+ }
+
+ protected void clearAttackers() {
+ for (int i=0; i<attacked.length; i++) {
+ attacked[i] = -1;
+ }
+ }
+
+ protected void setFoodOwners() {
+ for (int x=0; x<getWidth(); x++) {
+ for (int y=0; y<getHeight(); y++) {
+ setFoodOwner(x, y);
+ }
+ }
+ }
+
+ private void setFoodOwner(int x, int y) {
+ if (hasObject(FOOD, x, y)) {
+ // find an agent around
+ int ag;
+ // food pos
+ ag = getAgAtPos(x, y); if (ag >= 0) { owner[x][y] = ag; return; }
+ // up
+ ag = getAgAtPos(x, y-1); if (ag >= 0) { owner[x][y] = ag; return; }
+ // down
+ ag = getAgAtPos(x, y+1); if (ag >= 0) { owner[x][y] = ag; return; }
+ // left
+ ag = getAgAtPos(x-1, y); if (ag >= 0) { owner[x][y] = ag; return; }
+ // right
+ ag = getAgAtPos(x+1, y); if (ag >= 0) { owner[x][y] = ag; return; }
+ }
+ owner[x][y] = -1;
+ }
+
+ public int getFoodOwner(int x, int y) {
+ return owner[x][y];
+ }
+
+ public boolean eat(int ag) {
+ Location l = getAgPos(ag);
+ return eat(ag, l.x, l.y);
+ }
+
+ private boolean eat(int ag, int x, int y) {
+ if (hasObject(FOOD, x, y)) {
+ remove(FOOD, x, y);
+ owner[x][y] = -1;
+ strengths[ag] += FOOD_NUTRITIVE_VALUE;
+ Location l = getFreePos(FOOD);
+ add(FOOD, l);
+ setFoodOwner(l.x, l.y);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean move(int ag, int x, int y) {
+ //if (strengths[ag] < MOVING_COST)
+ // return false;
+
+ Location l = getAgPos(ag);
+ strengths[ag] -= MOVING_COST;
+
+ // should go right
+ if (l.x < x && isFree(l.x+1,l.y)) {
+ setAgPos(ag, l.x+1, l.y);
+ return true;
+ }
+ // should go left
+ if (l.x > x && isFree(l.x-1,l.y)) {
+ setAgPos(ag, l.x-1, l.y);
+ return true;
+ }
+ // should go up
+ if (l.y > y && isFree(l.x,l.y-1)) {
+ setAgPos(ag, l.x, l.y-1);
+ return true;
+ }
+ // should go down
+ if (l.y < y && isFree(l.x,l.y+1)) {
+ setAgPos(ag, l.x, l.y+1);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean randomMove(int ag) {
+ Location l = getAgPos(ag);
+ Location nl = null;
+ for (int i=0; i<4; i++) {
+ switch (random.nextInt(4)) {
+ case 0: nl = new Location(l.x+1, l.y); break;
+ case 1: nl = new Location(l.x-1, l.y); break;
+ case 2: nl = new Location(l.x, l.y+1); break;
+ case 3: nl = new Location(l.x, l.y-1); break;
+ }
+ if (isFree(nl) && isFree(FOOD, nl)) {
+ return move(ag,nl.x,nl.y);
+ }
+ }
+ return false;
+ }
+
+ public boolean attack(int ag, int x, int y) {
+ //if (strengths[ag] < ATTACK_COST)
+ // return false;
+
+ strengths[ag] -= ATTACK_COST;
+
+ int other = getAgAtPos(x, y);
+ if (other < 0)
+ return false;
+
+ attackCount++;
+ if (strengths[ag] > strengths[other]) {
+ strengths[other] -= ATTACK_COST;
+ attacked[other] = ag;
+
+ Location agl = getAgPos(ag);
+
+ // move food of position
+ if (isFree(FOOD, agl) && hasObject(FOOD, x, y)) {
+ remove(FOOD, x, y);
+ owner[x][y] = -1;
+ add(FOOD, agl);
+ return true;
+ }
+ //eat(ag, x, y);
+ }
+ return false;
+ }
+
+ public int isAttacked(int ag) {
+ return attacked[ag];
+ }
+
+ public int getAgStrength(int ag) {
+ return strengths[ag];
+ }
+
+ public double getStrengthMean() {
+ double sum = 0;
+ for (int i=0; i<strengths.length; i++) {
+ sum += strengths[i];
+ }
+ return sum / strengths.length;
+ }
+
+ public double getVarianceOfStrength() {
+ double mean = getStrengthMean();
+ double sum = 0;
+ for (int i=0; i<strengths.length; i++) {
+ sum = sum + Math.pow((double)strengths[i] - mean, 2);
+ }
+ return Math.sqrt(sum / strengths.length);
+ }
+
+ public int getAttackCounter() {
+ return attackCount;
+ }
+
+}
Property changes on: trunk/examples/food-simulation/src/java/FoodModel.java
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/src/java/FoodView.java
===================================================================
--- trunk/examples/food-simulation/src/java/FoodView.java (rev 0)
+++ trunk/examples/food-simulation/src/java/FoodView.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,84 @@
+import jason.environment.grid.GridWorldView;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.event.*;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartFrame;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.xy.DefaultXYDataset;
+
+
+/** class that implements the View of the Game of Life application */
+public class FoodView extends GridWorldView {
+
+ private static final long serialVersionUID = 1L;
+
+ FoodModel hmodel;
+
+ DefaultXYDataset dataset = new DefaultXYDataset();
+
+ public FoodView(FoodModel model, final FoodEnvironment env) {
+ super(model, "Normative Simulation", 500);
+ hmodel = model;
+ setVisible(true);
+ repaint();
+
+ getCanvas().addMouseListener(new MouseListener() {
+ public void mouseClicked(MouseEvent e) {
+ int col = e.getX() / cellSizeW;
+ int lin = e.getY() / cellSizeH;
+ if (col >= 0 && lin >= 0 && col < getModel().getWidth() && lin < getModel().getHeight()) {
+ hmodel.add(FoodModel.FOOD, col, lin);
+ //env.updateNeighbors(hmodel.getAgId(col,lin));
+ update(col, lin);
+ }
+ }
+ public void mouseExited(MouseEvent e) {}
+ public void mouseEntered(MouseEvent e) {}
+ public void mousePressed(MouseEvent e) {}
+ public void mouseReleased(MouseEvent e) {}
+ });
+
+ JFreeChart xyc = ChartFactory.createXYLineChart(
+ "Agents' strength",
+ "step",
+ "strength",
+ dataset, // dataset,
+ PlotOrientation.VERTICAL, // orientation,
+ true, // legend,
+ true, // tooltips,
+ true); //urls
+ ChartFrame frame = new ChartFrame("Normative Simulation: Agents' Strength", xyc);
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ public void addSerie(String key, double[][] values) {
+ dataset.addSeries(key, values);
+ }
+
+ @Override
+ public void drawAgent(Graphics g, int x, int y, Color c, int id) {
+ g.setColor(Color.GRAY);
+ g.fillRect(x * cellSizeW + 1, y * cellSizeH+1, cellSizeW-1, cellSizeH-1);
+ if (hmodel.hasObject(FoodModel.FOOD, x, y)) {
+ drawFood(g, x, y);
+ }
+ }
+
+ @Override
+ public void draw(Graphics g, int x, int y, int object) {
+ if (object == FoodModel.FOOD && !hmodel.hasObject(FoodModel.AGENT, x, y)) {
+ drawFood(g, x, y);
+ }
+ }
+
+ public void drawFood(Graphics g, int x, int y) {
+ g.setColor(Color.YELLOW);
+ g.fillRect(x * cellSizeW + 15, y * cellSizeH+15, cellSizeW-30, cellSizeH-30);
+ }
+
+}
Property changes on: trunk/examples/food-simulation/src/java/FoodView.java
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/examples/food-simulation/src/java/bb/list.java
===================================================================
--- trunk/examples/food-simulation/src/java/bb/list.java (rev 0)
+++ trunk/examples/food-simulation/src/java/bb/list.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,28 @@
+// Internal action code for project FoodSimulation
+
+package bb;
+
+import jason.asSemantics.*;
+import jason.asSyntax.*;
+import java.util.logging.*;
+
+/** list all BB */
+public class list extends DefaultInternalAction {
+
+ private Logger logger = Logger.getLogger("FoodSimulation."+list.class.getName());
+
+ @Override
+ public Object execute(TransitionSystem ts, Unifier un, Term[] args) throws Exception {
+ try {
+ String s = " .";
+ for (Literal l: ts.getAg().getBB()) {
+ s += l + " ";
+ }
+ logger.info(s);
+ return true;
+ } catch (Exception e) {
+ logger.warning("Error in internal action 'bb.list'! "+e);
+ }
+ return false;
+ }
+}
Added: trunk/examples/food-simulation/src/java/math/distance.java
===================================================================
--- trunk/examples/food-simulation/src/java/math/distance.java (rev 0)
+++ trunk/examples/food-simulation/src/java/math/distance.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,28 @@
+// Internal action code for project FoodSimulation
+
+package math;
+
+import jason.asSemantics.DefaultArithFunction;
+import jason.asSemantics.TransitionSystem;
+import jason.asSyntax.NumberTerm;
+import jason.asSyntax.Term;
+
+import java.util.logging.Logger;
+
+/** function that computes the distance between two number */
+public class distance extends DefaultArithFunction {
+
+ private Logger logger = Logger.getLogger("FoodSimulation."+distance.class.getName());
+
+ @Override
+ public double evaluate(TransitionSystem ts, Term[] args) throws Exception {
+ try {
+ int n1 = (int)((NumberTerm)args[0]).solve();
+ int n2 = (int)((NumberTerm)args[1]).solve();
+ return Math.abs(n1 - n2);
+ } catch (Exception e) {
+ logger.warning("Error in function 'math.distance'! "+e);
+ }
+ return 0;
+ }
+}
Modified: trunk/release-notes.txt
===================================================================
--- trunk/release-notes.txt 2008-05-31 10:47:10 UTC (rev 1318)
+++ trunk/release-notes.txt 2008-05-31 11:11:27 UTC (rev 1319)
@@ -3,8 +3,51 @@
-------------
New features
-. internal actions to control execution: .if, .while and .for
+. (experimental) control of the execution in plan's body with if, while
+ and for.
+ if ( <expression> ) {
+ <plan_body1>
+ [ } else { <plan_body2> }
+ };
+
+ if <expression> is true, <plan_body1> is executed; otherwise,
+ <plan_body2> is executed.
+
+ e.g.: if (vl(X) & X > 10) {
+ .print("value > 10")
+ }
+
+
+ while ( <expression> ) {
+ <plan_body>
+ };
+
+ while <expression> is true, the <plan_body> is executed.
+
+ e.g.: while (vl(X) & X > 10) {
+ -+vl(X+1);
+ }
+
+ for ( <expression> ) {
+ <plan_body>
+ };
+
+ for all unifications of <expression> the <plan_body> is executed.
+
+ e.g.: for ( vl(X) ) {
+ .print(X);
+ };
+ for ( .member(X,[a,b,c]) ) {
+ .print(X);
+ };
+
+
+New examples and demos:
+. demos/gui: two simple example of how to make a GUI for agents
+. example/food-simulation: implementation of the scenario of simulation
+ presented in http://jasss.soc.surrey.ac.uk/1/3/3.html
+
Bugs fixed:
. BUF add annotation "source(percept)" in the perception deletion event
. drop_desire does not remove desires in Circumstance.Event correctly
Copied: trunk/src/jason/asSemantics/SuspendInternalAction.java (from rev 1318, trunk/src/jason/asSemantics/SynchronousInternalAction.java)
===================================================================
--- trunk/src/jason/asSemantics/SuspendInternalAction.java (rev 0)
+++ trunk/src/jason/asSemantics/SuspendInternalAction.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -0,0 +1,98 @@
+package jason.asSemantics;
+
+import jason.asSemantics.Circumstance;
+import jason.asSemantics.Intention;
+import jason.asSemantics.InternalAction;
+import jason.asSemantics.TransitionSystem;
+import jason.asSyntax.InternalActionLiteral;
+import jason.asSyntax.PlanBody;
+import jason.asSyntax.PlanBodyImpl;
+import jason.asSyntax.PlanBody.BodyType;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+
+ This class can be used in place of DefaultInternalAction to create IA that
+ suspend/resume the intention.
+
+ Example: a plan should to ask something to an user and wait until he/she answer some.
+ If DefaultInternalAction is used for that, all the agent thread is suspended until
+ the answer. With SuspendInternalAction, only the intention using the IA is
+ suspended. See demos/gui/gui1.
+
+ @author jomi
+*/
+public abstract class SuspendInternalAction implements InternalAction {
+
+ protected ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+ private static int actcount = 0;
+
+ public boolean canBeUsedInContext() {
+ return false;
+ }
+
+ public boolean suspendIntention() {
+ return true;
+ }
+
+ /**
+ * Suspend the current intention, put it in the PendingIntention (PI) structure and assigns it to a key.
+ *
+ * @param basekey the base key to form final key used to get the intention back from PI (e.g. "moise", "cartago", ...)
+ * @param timeout the max time the intention will be in PI, the value 0 means until "resume"
+ * @return the final key used to store the intention in PI
+ */
+ public String suspend(final TransitionSystem ts, String basekey, int timeout) {
+ final String key = basekey + "/" + (actcount++);
+ final Circumstance C = ts.getC();
+ Intention i = C.getSelectedIntention();
+ i.setSuspended(true);
+ C.getPendingIntentions().put(key, i);
+
+ if (timeout > 0) {
+ // schedule a future test of the end of the action
+ scheduler.schedule( new Runnable() {
+ public void run() {
+ // finish the IA by timeout
+ if (C.getPendingIntentions().get(key) != null) { // test if the intention is still there
+ timeout(ts,key);
+ }
+ }
+ }, timeout, TimeUnit.MILLISECONDS);
+ }
+ return key;
+ }
+
+ /** called back when some intention should be resumed/failed by timeout */
+ abstract public void timeout(TransitionSystem ts, String intentionKey);
+
+ /** resume the intention identified by intentionKey */
+ public void resume(TransitionSystem ts, String intentionKey) {
+ resume(ts, intentionKey, false);
+ }
+
+ /** fails the intention identified by intentionKey */
+ public void fail(TransitionSystem ts, String intentionKey) {
+ resume(ts, intentionKey, true);
+ }
+
+ synchronized private void resume(TransitionSystem ts, String intentionKey, boolean abort) {
+ Circumstance C = ts.getC();
+ Intention pi = C.getPendingIntentions().remove(intentionKey);
+ if (pi != null) {
+ pi.setSuspended(false);
+ C.addIntention(pi); // add it back in I
+ pi.peek().removeCurrentStep(); // remove the internal action that put the intention in suspend
+
+ if (abort) {
+ // fail the IA
+ PlanBody pbody = pi.peek().getPlan().getBody();
+ pbody.add(0, new PlanBodyImpl(BodyType.internalAction, new InternalActionLiteral(".fail")));
+ }
+ ts.getUserAgArch().getArchInfraTier().wake();
+ }
+ }
+}
Deleted: trunk/src/jason/asSemantics/SynchronousInternalAction.java
===================================================================
--- trunk/src/jason/asSemantics/SynchronousInternalAction.java 2008-05-31 10:47:10 UTC (rev 1318)
+++ trunk/src/jason/asSemantics/SynchronousInternalAction.java 2008-05-31 11:11:27 UTC (rev 1319)
@@ -1,99 +0,0 @@
-package jason.asSemantics;
-
-import jason.asSemantics.Circumstance;
-import jason.asSemantics.Intention;
-import jason.asSemantics.InternalAction;
-import jason.asSemantics.TransitionSystem;
-import jason.asSyntax.InternalActionLiteral;
-import jason.asSyntax.PlanBody;
-import jason.asSyntax.PlanBodyImpl;
-import jason.asSyntax.PlanBody.BodyType;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
-
- This class can be used in place of DefaultInternalAction to create synchronous IA.
-
- A sync. IA is one that suspend the intention that uses it until some event.
-
- Example: a plan should to ask something to an user and wait until he/she answer some.
- If DefaultInternalAction is used for that, all the agent thread is suspended until
- the answer. With SynchronousInternalAction, only the intention using the IA is
- suspended. See demos/gui/gui1.
-
- @author jomi
-*/
-public abstract class SynchronousInternalAction implements InternalAction {
-
- protected ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
- private static int actcount = 0;
-
- public boolean canBeUsedInContext() {
- return false;
- }
-
- public boolean suspendIntention() {
- return true;
- }
-
- /**
- * Suspend the current intention, put it in the PendingIntention (PI) structure and assigns it to a key.
- *
- * @param basekey the base key to form final key used to get the intention back from PI (e.g. "moise", "cartago", ...)
- * @param timeout the max time the intention will be in PI, the value 0 means until "resume"
- * @return the final key used to store the intention in PI
- */
- public String suspend(final TransitionSystem ts, String basekey, int timeout) {
- final String key = basekey + "/" + (actcount++);
- final Circumstance C = ts.getC();
- Intention i = C.getSelectedIntention();
- i.setSuspended(true);
- C.getPendingIntentions().put(key, i);
-
- if (timeout > 0) {
- // schedule a future test of the end of the action
- scheduler.schedule( new Runnable() {
- public void run() {
- // finish the IA by timeout
- if (C.getPendingIntentions().get(key) != null) { // test if the intention is still there
- timeout(ts,key);
- }
- }
- }, timeout, TimeUnit.MILLISECONDS);
- }
- return key;
- }
-
- /** called back when some intention should be resumed/failed by timeout */
- abstract public void timeout(TransitionSystem ts, String intentionKey);
-
- /** resume the intention identified by intentionKey */
- public void resume(TransitionSystem ts, String intentionKey) {
- resume(ts, intentionKey, false);
- }
-
- /** fails the intention identified by intentionKey */
- public void fail(TransitionSystem ts, String intentionKey) {
- resume(ts, intentionKey, true);
- }
-
- synchronized private void resume(TransitionSystem ts, String intentionKey, boolean abort) {
- Circumstance C = ts.getC();
- Intention pi = C.getPendingIntentions().remove(intentionKey);
- if (pi != null) {
- pi.setSuspended(false);
- C.addIntention(pi); // add it back in I
- pi.peek().removeCurrentStep(); // remove the internal action that put the intention in suspend
-
- if (abort) {
- // fail the IA
- PlanBody pbody = pi.peek().getPlan().getBody();
- pbody.add(0, new PlanBodyImpl(BodyType.internalAction, new InternalActionLiteral(".fail")));
- }
- ts.getUserAgArch().getArchInfraTier().wake();
- }
- }
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|