## Programming agents using scripting languages

Java is not the only language one can use to develop applications in MadKit. There are already several scripting languages which may be used to describe agents behavior and GUI components. For the moment four scripting languages are already available: Scheme (using the Kawa engine), Python (using the Jython interpreter), Jess (a rule based language), and BeanShell (a Java interpreter). In the future, more scripting languages will be added to MadKit. Moreover, it is quite straightforward to add a new scripting language to MadKit (see {{adding your own scripting language}}).

## General principles when programming with scripting languages

There are some general principles that work with all scripting languages.

The behavior description of a scripted agent is located in a script file which is loaded and evaluated at launch time. Thus, if you modify the behavior file, when you instantiate and launch a new agent from the same file, then you will get a new behavior. This means that you may develop scripted agents behavior without leaving MadKit. To edit a scripted agent, you have several possibilies (see also the userguide to get more details):

- Use an external editor.

- Use an "Editor agent" to edit the code of the agent.

  Note: On the MadKit desktop, you may invoke this action by selecting the NotePad menuitem on the popup menu associated to a script file in the directory explorer.

- Use jEdit to edit the code of the script file and create agents directly from jEdit. Note: On the MadKit desktop, you may invoke this action by selecting the jEdit menuitem on the popup menu associated to a script file in the directory explorer.

- Use specialized editor agents that may evaluate their content: `JessEditorAgent` {{link}} for the JessLanguage, `SchemeEditorAgent` {{link}} for Scheme, `BeanshellEditorAgent` {{link}} for Beanshell, and `PythonEditorAgent` {{link}} for the Python language. All of these editor has a generic structure of a NotePad agent with the ability to evaluate the content of whole or part of the buffer. On top of it, each editor presents a set of specific features. See the corresponding sections.

For each scripting language there is a special agent called `<language>Agent` where <`language`> is one of the scripting languages. This type of agent inherits from `Agent` and is threaded. When you launch a scripted agent, for instance by double clicking on a script file in the directories explorer of the MadKit desktop, one of these agent is instantiated and the script file is passed as argument.

## Introduction to programming MadKit in Scheme (Kawa)

Scheme agents are instances of the class `SchemeAgent`. Scheme functions have been added to provide bindings with the `Agent` class.

The Kawa Scheme system is the underlying implementation and the bindings are developed with the Scheme/Java interface. The related Kawa documentation (http://www.gnu.org/software/kawa/) is a recommended reading for MadKit/Scheme agent developers.

As with the Java API, an agent developed with the MadKit/Scheme bindings has to define the `activate`, `live` or `end` functions. See examples below.

## API for programming MadKit from Scheme

These functions map to the agent life-cycle and information methods. Arguments are standard scheme type or Java objects.

The variable `self` represents the current agent.

### Organization related primitives

These functions maps the group, role and community management for an agent. Scheme strings are automatically translated to Java strings, so usage is similar.

`(create-group d c g s a), (create-group d g s a)`

  Creates the group `g` in the community `c` if this parameter is present and in `"public"` if not. The group is distributed if the boolean parameter `d` is `#t` and local (i.e. agents are not visible from distant kernels) otherwise. The `s` parameter is used to describe the overall structure of the group, but this feature is not used yet. The `a` parameter is an object which implements an authorization mechanism for agents to get into the group. see section {{section}} for more information on creating groups with authorization elements.

  Example:

      (create-group #t "foo" "myGroup" #!null #!null)

  creates a distributed group `"myGroup"` in the community `"foo"` with no description and no authorization element.

      (create-group #f "myGroup" #!null #!null)

  creates a local group `"myGroup"` in the community `"public"` with no description and no authorization element.

`(request-role c g r m), (request-role g r m)`

  The current agent requests to play the role `r` within the group `g` in the community `c` if this parameter is present and in `"public"` if not. The `m` parameter is a "member card" that the current agent may use to enter the group and obtain this role, which may be null (i.e. #!null in Scheme/Kawa) if the group `g` has no security manager.

  Returns the following values: 1 : operation success; -1 : access denied; -2 : the role is already handled by this agent; -3 : the group does not exist; -4 : the community does not exist.

  Example:

      (request-role "foo" "myGroup" "player" #!null)

  Requests to play the role `"player"` in the group `"myGroup"` with regards to the community `"foo"` with no member card.

`(leave-role c g r), (leave-role g r)`

  Leaves the role `r` which exists in the group `g` of community `c` if the parameter is present, or of community `"public"` if not. If the current agent plays only the role `r` in `g`, then it leaves the group.

`(leave-group c g), (leave-group g)`

  Leaves the group `g` of community `c` if the parameter is present, or of community `"public"` if not.

`(community? c)`

  Returns `#t` if the community `c` exists, i.e. if the kernel (represented by the `SiteAgent`) is present in this community.

`(group? c g), (group? g)`

  Returns `#t` if the group `g` exists in the community `c` if the parameter is present, or exists in the community `"public"` if not. Returns `#f` otherwise.

`(role? c g r), (role? g r)`

  Returns `#t` if the role `r` of the group `` exists in the community `c` if the parameter is present, or exists in the community `"public"` if not. Returns `#f` otherwise.

`(get-my-groups c), (get-my-groups)`

  Returns the list of all groups of which the current agent is a member. Groups are taken from the community `c` if the parameter is present or of the community `"public"` if not.

`(get-existing-groups c), (get-existing-groups)`

  Returns the list of all groups existing in the community `c` if the parameter is present, or existing in the community `"public"` if not.

`(get-my-roles c g), (get-my-roles g)`

  Returns the list of all roles played by the current agent in the group `g`. The group is taken from the community `c` if the parameter is present or of the community `"public"` if not.

`(get-existing-roles c g), (get-existing-roles g)`

  Returns the list of all roles existing in the group `g`. The group is taken from the community `c` if the parameter is present or of the community `"public"` if not. Note: The current agent MUST be a member of the group `g` to get this information

`(get-available-communities)`

  Returns the list of all communities in which the current kernel (through its `SiteAgent`) is present. By default, contains at least one element, the `"public"` community.

`(get-agents-with-role c g r), (get-agents-with-role g r)`

  Returns the list of all agents playing the role `r` in the group `g`. The group is taken from the community `c` if the parameter is present or of the community `"public"` if not. Note: The current agent MUST be a member of the group `g` to get this information

`(get-agent-with-role c g r), (get-agent-with-role g r)`

  Returns one agent taken at random from the list returned by `get-agents-with-role`.

### Communication related primitives

These functions map to the message-related methods of the Agent class. Arguments and return values are Java object references. The developer has to stick with the provided `StringMessage` or `ActMessage` (see below) mappings or develop new bindings for its specific Message class (see Kawa Java/Scheme low-level interface document).

`(messagebox-empty?)`

  Returns `#t` if the message box of the current SchemeAgent is empty and `#f` otherwise.

`(next-message)`

  Returns the next-message in the messagebox or `#!null` if it is empty.

`(wait-next-message)`

  Returns the next-message in the messagebox if there is one or block the thread of the agent until it receives a new message.

`(send-message a m)`

  Sends the message `m` to the agent represented by its agent address `a`.

`(broadcast-message c g r m), (broadcast-message g r m)`

  Sends the message `m` to all agents playing role `r` within group `g` in community `c` (or in community `"public"` if this parameter is not present).

### Agent creation and destruction primitives

`(launch-agent ag name gui)`

  Launches the agent `ag`of name `name`. If the flag `gui` is `#t` then its graphic interface is displayed, otherwise, the agent works without any GUI.

`(make-launch-agent classname name)`

  Creates an agent of class `classname` and of name `name` and launches it.

`(kill-agent ag)`

  Kills the agent referenced by `ag`. This agent must either be the current agent or an agent created by the current agent.

  Note: The `ag` parameter is a reference to an agent and not an `AgentAdress`.

### Miscelleaneous primitives

`(get-address)`

  Returns the AgentAddres of the current agent.

`(get-name)`

  Returns the name of the current agent.

`(set-name name)`

  Sets the name of the current agent to name.

`(pause milli)`

  Stops the thread of the current agent for `milli` milliseconds.

`(println s)`

  Displays the string s in the standard output of the agent.

`(debug s)`

  Displays the string s in the standard output of the agent, if the `debug` flag is on.

`(set-debug b)`

  Sets the `debug` flag to b.

`(get-debug b)`

  Returns the value of the `debug` flag.

### Additional functions

These functions give access to the useful message class `StringClass`.

    (new-string-message m)

    (get-string-message-content m)

The following functions give access to the useful message class `ActMessage`.

    (new-act-message a)

    (get-act-message-action m)

    (get-act-message-content m)

    (set-act-message-content m s)

    (get-act-message-object m)

    (set-act-message-object m o)

    (get-act-message-field m f)

    (set-act-message-field m f o)

The following functions wrap methods of the `Message`class:

    (get-message-sender m)

    (get-message-receiver m)

## Examples

In order to show how to program agents in Scheme, Here is a Hello agent, which has the same behavior as the Hello agent provided in Java. The example is given in the Hello.scm file from the template plugin.

    (define myCommunity "myCommunity")

    (define myGroup "myGroup")

    (define myRole "myRole")

    (define alive #t)

    (define (activate)

      (println "Hello I'm an agent !")

      (let ((r (create-group #t myCommunity myGroup #!null #!null)))

    	  (display "r = ")

    	  (display r)

    	  (if (not (equal? r 1))

    		  (set! alive #f)

    		  (request-role myCommunity myGroup myRole #!null)

    )))

    ;;

    (define (live)

    	(handle-message (wait-next-message))

    )

    (define (handle-message msg)

    	(println (string-append "handling the message " msg))

    	(handle-message (wait-next-message))

    )

    (define (end)

      (println "That's it !!! Bye ")

      (pause 2000)

    )