This law represent an improvement of the basic ping-pong law that maintains its fundamental behavior. A few features are added in this law:
pingTo term in the control
state is removed and the source is informed. Another improvement
reffers to the fact that the source of a message is informed whenever
there is an attempt to send a message invalid under this policy. The
policy also features the behavior of an agent that runs disconnected
from its controller.
The Prolog version of this law follows:
law(pingpongplus,language(prolog)).
/* the pingPong basic protocol*/
sent(X,ping(M),Y) :- not(pingTo(Y)@CS), do(add(pingTo(Y))),do(forward).
arrived(X,ping(M),Y) :- do(add(pingFrom(X))), do(deliver).
sent(X,pong(M),Y) :- pingFrom(Y)@CS, do(remove(pingFrom(Y))),do(forward).
arrived(X,pong(M),Y) :- do(remove(pingTo(X))), do(deliver).
sent(Self,getCS,Z) :- do(discloseCS(all)).
/*disconnection and reconnection */
disconnected :- do(imposeObligation(toQuit,10, min)).
reconnected :- do(repealObligation(toQuit)).
obligationDue(toQuit) :- do(quit).
/*automatic state monitoring */
sent(S,display(DT),Z) :- do(imposeObligation(display,DT,sec)), do(add(obTime(DT))),
do(show(possibleEvent(all), cs(all))).
obligationDue(display) :- obTime(DT)@CS, do(imposeObligation(display,DT,sec)),
do(show(possibleEvent(all), cs(all))).
sent(S,stopDisplay,Z) :- obTime(T)@CS, do(remove(obTime(T))),
do(repealObligation(display)).
/*exception handling*/
exception(forward(Self,ping(M),[Y,L]),D) :- do(remove(pingTo(Y))),
do(deliver(Self,exc(ping(M)),Y)).
exception(E,D) :- do(deliver(Self,exception(E,D),Self)).
/*sentinel rule*/
sent(X,N,Y) :- do(deliver(Self,messageIgnored,Self)).
This is the Java version of the law:
public class Pingpongplus extends Law {
public void sent(String source, String message, String dest) {
String pingToY = "pingTo(" + dest + ")";
String pingFromY = "pingFrom(" + dest + ")";
if (message.startsWith("ping(") && !CS.has(pingToY)) {
doAdd(pingToY);
doForward();
return;
}
if (message.startsWith("pong(") && CS.has(pingFromY)) {
doRemove(pingFromY);
doForward();
return;
}
if (message.equals("getCS")) {
doDiscloseAllCS();
return;
}
if (message.startsWith("display(")) {
int dt = Integer.parseInt(getContentFromMessage(message));
doImposeObligation("display", dt, "sec");
doAdd("obTime(" + dt + ")");
doShowEvents("all", "all");
return;
}
if (message.equals("stopDisplay")) {
Term timeTerm = CS.findT("obTime(%A)");
doRemove(timeTerm);
doRepealObligation("display");
return;
}
doDeliver(Self, "messageIgnored", Self);
}
public void arrived(String source, String message, String dest) {
if (message.startsWith("ping(")) {
doAdd("pingFrom(" + source + ")");
doDeliver();
}
if (message.startsWith("pong(")) {
doRemove("pingTo(" + source + ")");
doDeliver();
}
}
public void disconnected() {
doImposeObligation("toQuit", 10, "min");
}
public void reconnected() {
doRepealObligation("toQuit");
}
public void obligationDue(Term obligationTerm) {
if (obligationTerm.toString().equals("toQuit")) doQuit();
if (obligationTerm.toString().equals("display")) {
int dt = CS.fetchInt("obTime");
doImposeObligation("display", dt, "sec");
doShowEvents("all", "all");
}
}
public void exception(Message m, String diagnostic) {
if ((m.type == Const.FWD) && m.source.equals(Self) && m.s_payload.startsWith("ping")) {
doRemove("pingTo(" + m.dest + ")");
doDeliver("law", "exc(" + m.s_payload + ")", Self);
return;
}
doDeliver("law", "exception(type(" + m.type + "),source(" + m.source + "),payload(" + m.s_payload
+ "),dest(" + m.dest + "),diagnostic(" + diagnostic + "))", Self);
}
/*This is a helper method to retrieve the only argument of a regular expression*/
public String getContentFromMessage(String anyMessage) {
int index = anyMessage.indexOf("(");
if (index == -1) return "";
else return anyMessage.substring(index+1, anyMessage.length()-1);
}
}
The basic behavior of this law can be observed by following the same scenario outlined in the ping-pong law example. In order to observe the behavior augmented by the new additions to the law note the following:
messageIgnored answer to it.
getCS to anybody, and check the
control state in the main communication window; in this case, the
message is captured and handled directly by the controller.
display(t), where t
can be any positive integer, the control state and the repertoire
will be displayed automatically every t seconds. The control state is
displayed in the web-based agent text area called CS. Also, the
repertoire text area displays all the possible messages the agent can
send (feature available in the prolog version of the law). This way, one
can observe the state of the agent during the interaction.
stopDisplay message.