| # Principe, programmation et règles du jeu de Warbot J. Ferber - version 2.1 |
--- | --- | ---

#

Règles du jeu | Forum | Download | Tutoriel

## Principe

WarBot est un environnement de simulation de comportement de robots se déplaçant et agissant dans un environnement simulé comme le montre la figure ci-desssous.

Deux équipes comprenant chacune n robots s'affrontent. Ces robots sont divisés en plusieurs catégories : pour l'instant il n'existe que trois types de robots: les robots lanceurs de missiles, les robots eplorateurs et les bases.

Le but des équipes est de détruire les bases du camp adverse avant que l'autre ne le fasse...

Pour cela toutes les stratégies sont possibles !

Le joueur doit définir une équipe, c'est-à-dire définir le comportement de ses robots, sachant que le nombre de robots et leur répartition dans les catégories (lanceurs de missiles, explorateurs et base) sont les mêmes pour tous.

Une fois cette équipe définie et les positions initiales précisées, deux équipes s'affrontent sans intervention humaine. Que le meilleur gagne...

## Les entités de WarBot

Il existe globalement deux grandes catégories d'entités dans Warbot: les robots et les "objets du monde" qui ne sont pas des robots.

#### Les robots

Un robot dans WarBot se compose de deux parties : le corps et la tête.

- Le corps définit l'ensemble des caractéristiques " physiques " du robot : ses possibilités d'actions, ses armes, son énergie initiale, sa perception, etc...
- La tête décrit l'ensemble des comportements du robots, en termes de perception, connaissance, communication avec autrui et prise de décision. (ce sont les systèmes conatifs, représentationnels et communicationnels dans [Fer 95]). C'est cette tête des robots qu'il faut très précisément décrire !!

WarBot fonctionne sur la plate-forme MadKit. Il est donc possible d'utiliser tous les outils de cette plateforme pour surveiller l'évolution des robots.

Dans la version actuelle, il existe exactement trois types de corps de robots:

##### Les robots explorateurs (warbot.kernel.Explorer)

Ce sont les robots qui se déplacent le plus rapidement de tous, mais en revanche, ils ne disposent d'aucune arme. D'autre part, ils disposent d'une distance de perception plus grande que les lanceurs de missile. Comme tous les robots mobiles, les explorateurs peuvent prendre de la nourriture dans leur "sac" et le déposer près de la base. Ils peuvent aussi manger la nourriture. Dans ce cas, l'énergie de la nourriture vient s'ajouter à leur propre énergie.

Voici leurs valeurs initiales (attention la vitesse mesure en fait la "lenteur" des agents. Plus un agent est rapide, plus sa vitesse est faible. Les agents les plus rapides ont une valeur de vitesse de 1):

- Radius (taille): 12
- Energy: 1000
- DetectionRange: 130
- Speed: 2

##### Les robots lanceurs de missiles (warbot.kernel.RocketLauncher)

Ces robots sont assez lents, mais disposent d'une bonne quantité d'énergie et surtout sont capables de lancer des rockets. Ils comportent 300 rockets (ce qui est assez importants) et peuvent aussi construire de nouvelles rockets en transformant leur énergie en rockets. Ils peuvent aussi transporter et consommer de la nourriture.

- Radius (taille): 12
- Energy: 4000
- DetectionRange: 80
- Speed: 8
- RocketNumber: 300

##### Les bases (warbot.kernel.Home)

Les bases sont aussi des robots, mais des robots immobiles. Elles disposent d'une grande énergie initiale, d'une grande capacité de perception et de toutes les caractéristiques de communication des autres robots. De plus, elles peuvent transformer de la nourriture en nouveaux robots, et ainsi régénérer une armée.

- Radius (taille): 20
- Energy: 12000
- DetectionRange: 200
- Speed: 0

#### Les autres entités de Warbot

Il existe un ensemble d'entités qui ne sont pas des robots dans warbot. Ce sont les obstacles (murs et arbres), la nourriture et les missiles (rockettes).

##### Les obstacles

Les obstacles servent à délimiter le terrain, et aussi à offrir des protections. Les obstacles peuvent être détruits par des missiles. Iil n'est pas possible de bouger ou de construire des obstacles (pour l'instant).

##### La nourriture

La nourriture, visualisée sous la forme de "hamburgers", peut être utilisée par les robots de deux manière différente. Ils peuvent soit la consommer pour eux-mêmes et augmenter leurs points de vie, soit la rapporter à la base. Dans ce cas, si cette nourriture est consommée par la base, elle est transformée en "points de ressources" afin de créer de nouveaux robots.

##### Les missiles

Les missiles (rockettes) sont des entités mobiles qui explosent et enlèvent des points de vie lorsqu'elles rencontrent une entité du monde. Attention: les missile ne peuvent pas détruire celui qui vient d'envoyer le missile, mais ils peuvent (et cela arrive assez souvent) endommager ou détruire des robots de la même équipe s'il viennent à entrer en contact avec ces robots. Cela fait partie des comportements des robots de faire attention à leurs propres rockettes.

## La programmation des robots

Les cerveaux des robots sont des agents madkit qui contrôlent le comportement des "corps" des robots. On peut programmer les cerveaux en Warbot dans deux langages: Java et Python. Très bientôt il sera aussi possible de les programmer en Jess (un langage à base de règles) et en WTE, un petit langage de règles (pas très puissant, mais bien adapté à des enfants..)

Python est un langage fonctionnel et objet qui manipule de manière très élégante des structures de données telles que les listes et les dictionnaires. De plus la version de Python utilisée, jython disponible sur le site www.jython.org, permet d'utiliser toutes les classes Java (la documentation de Python se trouve sur le site)

Jess un système à base de règles qui fonctionne selon le modèle des "moteurs d'inférence": un ensemble de règle s'appliquent sur une base de faits jusqu'à ce que la base soit saturée, c'est à dire que le moteur ne puisse plus déduire de nouveaux faits. Jess, qui est un moteur d'inférence fonctionnant essentiellement en chaînage avant, implémente l'algorithme de Rete. C'est un descendand de OPS5 et CLIPS. Il est très pratique pour décrire des comportements d'agents évolués, en associant un comportement élémentaire à une règle. Il est possible aussi d'ajouter des fonctions et ainsi d'étendre les capacités du langage. Jess est très bien interfacé à Java. Toutes les classes de Java sont directement accessibles depuis Jess. Toutes les informations concernant Jess sont sur le site http://herzberg.ca.sandia.gov/jess/.

Si vous désirez d'autres langages de programmation, faites votre demande sur le forum de Warbot: (il faut que ce langage soit exécutable sur une machine virtuelle Java. Le site http://www.robert-tolksdorf.de/vmlanguages.html et d'autre part que ce langage ait une licence relativement "open" ou tout du moins gratuite pour des raisons non commerciales).

La classe `madkit.kernel.Brain` constitue le lieu de relation entre les programmes comportementaux des têtes et les comportements effectifs réalisés par le corps. Elle contient tout ce qu'un cerveau peut effectuer et notamment toutes les actions qu'il peut demander à un corps.

Par la suite d'autres langages de scripting seront disponibles: Scheme (version Kawa), Forth (Fidji), BeanShell (un interpréteur Java), JavaScript, etc...

ATTENTION: dans la version actuelle, les agents Jess ne fonctionnent pas!!

#### Les actions des corps

Voici quelques unes des actions et fonctions primitives que l'on peut utiliser pour programmer des cerveaux. Toutes ces fonctions se présentent comme des méthodes "public" de la classe `warbot.kernel.Brain`:

Fonctions d'accès aux attributs internes du robot

- int getEnergy() : retourne l'énergie courante d'un robot. Lorsque cette énergie est égale à zéro, le robot meurt...
- int getMaximumEnergy(): retourne l'énergie maximum qu'un robot peut normalement posséder
- double getHeading(): retourne la direction (en degrés) que le robot prend.
- String getTeam(): retourne la chaîne de caractère décrivant l'équipe du robot.
- public int getResourceLevel() : retourne la quantité de ressource dont dispose un agent. Seules les bases sont capables de conserver des ressources. Ces ressources pourront ensuite être transformées en création de robots par les bases elles-mêmes.

Actions de déplacement

- void setHeading(double dir) : définit la direction à prendre (en degrés). Les directions sont données dans le sens classique en navigation (sens des aiguilles d'une montre, inverse du sens trigonométrique). Le 0 se situe vers la droite.
- void move() : avance dans la direction courante. On ne peut avancer que d'une fois par unité de temps, à la vitesse du robot.
- boolean isMoving(): indique si l'agent s'est déplacé lors de l'action précédente. Permet de savoir si un agent est bloqué par un obstacle.
- double towards(double a, double b) : retourne la direction qu'il faut prendre pour aller dans la direction où se trouve le point de coordonnées a et b. Les valeurs de ces coordonnées sont relatives au robot.
- double distanceTo(Percept p) : retourne la distance,
- void randomHeading() : pointe dans une direction aléatoire.
- public int getCoveredDistance(): retourne la distance parcourue pendant la dernière unité de temps.

Actions de détection

- Percept[] getPercepts() : retourne l'ensemble des percepts issus des entités qui se trouvent dans la portée de détection du robot.
- boolean getShot(): indique si l'agent vient d'être touché par une rocket.
- int getCoveredDistance(): donne la distance parcourue lors du dernier trajet.

##### Actions de communication

Toutes les communications entre agents (donc entre 'Brains') s'effectuent à l'aide de messages de type "WarbotMessage" dont le contenu est une chaînes de caractères: il est donc impossible de transférer une référence vers un objet à l'aide d'un message.

- WarbotMessage readMessage() : retourne le premier message de la boîte aux lettres si la boite aux messages n'est pas vide et l'enlève de la boîte aux lettres. Retourne null si la boîte est vide.
- boolean isMessageBoxEmpty(): indique si la boîte de message est vide.
- int getMessageBoxNumber(): retourne le nombre de messages dans la boîte aux lettres.
- void send(AgentAdress agent, String act): envoie un message de performatif `act` à l'agent `agent` (qui est généralement un Brain).
- void send(AgentAdress agent, String act, String arg): envoie un message de performatif `act` et d'argument `arg` à l'agent `agent` (qui est généralement un Brain).
- void send(AgentAdress agent, String act, String arg1, String arg2): envoie un message de performatif `act` et d'argument `arg1` et `arg2` à l'agent `agent` (qui est généralement un Brain).
- void send(AgentAdress agent, String act, String[] cont): envoie un message de performatif `act` et et de tableau d'argument `cont` à l'agent `agent` (qui est généralement un Brain).
- void broadcast(String group, String role, String act): envoie un message de performatif `act` à tous les agents jouant le rôle `role` dans le groupe `group`.
- void broadcast(String group, String role, String act, String arg): envoie un message de performatif `act` et l'argument `arg` à tous les agents jouant le rôle `role` dans le groupe `group`.
- void broadcast(String group, String role, String act, String arg1, String arg2): envoie un message de performatif `act` et l'argument `arg1` et `arg2` à tous les agents jouant le rôle `role` dans le groupe `group`.
- void broadcast(String group, String role, String act, String[] cont): envoie un message de performatif `act` et de tableau d'argument `cont` à tous les agents jouant le rôle `role` dans le groupe `group`.

Les WarbotMessage comprennent un "acte de langage" dénommé par 'act' et un contenu, dénommé par 'content'. Le contenu est donné sous la forme d'un tableau de chaîne de caractères. Des fonctions simplifiées permettent d'accéder directement au premier et au second élément de ce contenu (méthodes `getArg1()` et `getArg2()`).

De plus, tous les WarbotMessage contiennent ,en coordonnées relatives par rapport au receveur, la position en x et en y de l'émetteur du message. Il donc possible d'aller vers l'émetteur sans que l'on sache effectivement où il se trouve en coordonnées absolues. Il est possible d'obtenir les informations correspondant à un WarbotMessage de la manière suivante:

- AgentAdress getSender():
- String getAct():
- String getArg1():
- String getArg2():
- String getArgN(int i):
- String[] getContent():
- int getNumberArgs():
- double getFromX()
- double getFromY()

Attention: un 'Brain' ne peut pas envoyer et recevoir d'autres messages que des WarbotMessage. Même les mécanismes d'envoi de messages traditionnels (sendMessage, broadcastMessage, etc..) ont été réécrits pour ne pas permettre de manipuler d'autres types de messages.

##### Actions de manipulation d'objets

- boolean eat(Food e) : tente de manger l'entité e (si elle est comestible, sinon il ne se passe rien). Retourne le succès de l'action.
- boolean take(Percept e) : tente de prendre une entité courante. Retourne le succès de l'action. Pour l'instant, on ne peut prendre que de la nourriture (percept Food qui représente un Hamburger). Quand un robot prend quelque chose, cela disparait de l'environnement.
- boolean drop(int i) : dépose la ième entité disponible dans le sac du robot. Lorsqu'un robot dépose quelque chose, cela réapparait dans l'environnement à l'endroit où se trouve le robot.
- void dropAll(): dépose tout ce que l'agent possède dans son sac.
- Percept[] inMyBag(): retourne l'ensemble des objets que le robot possède sous la forme d'un ensemble de percepts. Evidemment, les informations de position ne sont pas très pertinentes :-)
- boolean isMyBagFull() : indique si le sac est plein.
- boolean isMyBagEmpty(): indique si le sac est vide.
- int nbOfObjectsInMyBag() : retourne le nombre d'objets que le robot porte dans son sac.
- int bagCapacity(): retourne le nombre maximum d'objets qu'un agent peut contenir dans son sac.
- public Percept[] getBagPercepts() : retourne l'ensemble des objets qu'un robot possède sous la forme d'un tableau de percepts. Un cerveau n'a jamais accès à l'objet directement, mais seulement à son percept.
- public void createAgent(String str) : crée un agent à partir du nom qu'il possède dans le formalisme associé (voir {{ref}} pour une explication de la manière dont on peut créer de nouveaux robots dynamiquement). Seules les bases peuvent utiliser cette commande.

##### Actions de commandes des armes (uniquement valables pour les RocketLauncher)

- void launchRocket(double dir) : tire une rockette dans la direction indiquée. Attention, on ne peut tirer qu'une seule rocket toutes les 3 unités de temps seulement. Il faut un peu de temps pour recharger ;-)
- int getRocketNumber(): retourne le nombre de rockettes dont dispose le robot
- void buildRocket(): crée une rockette.

##### Actions d'interface avec l'utilisateur

Il est possible d'afficher une information à l'écran sous la forme d'une bulle. Cette bulle permet de visualiser des messages de 26 caractères au plus (ce n'est pas très grand, mais bon...).

- void showUserMessage(boolean b) : Indique si l'on veut afficher l'information utilisateur à l'écran sous la forme d'une bulle.
- void setUserMessage(String s): Affiche le message contenu dans la chaîne s à l'écran. Si le message est trop long, il est tronqué. Une chaîne vide (si s == null ou None en Python) n'affiche aucune bulle.

#### La perception

Les Robots de Warbot récupèrent leur perception par la primitive Percept[] getPercepts() qui retourne un tableau comprenant toutes les perceptions du robot qui sont perceptibles par lui c'est-à-dire qui se trouve dans son rayon de perception.

Un percept est une représentation individuelle de l'objet perçu. Cela signifie que toutes les informations qui se trouvent dans le percept ne sont pas seulement relatives à la chose perçues, mais elles prennent en compte aussi le percevant et la relation qui les unit. Par exemple, un percept comprend une distance et une direction qui sont données relativement au robot percevant.

Voici les différentes méthodes associées à un percept:

- public String getPerceptType() : retourne le type de l'objet perçu sous la forme d'une chaîne de caractère (voir la table des correspondances entre type de percept et classe java).
- public double getDistance() : retourne la distance qui sépare le robot percevant de l'objet perçu
- public double getX(), getY() : retourne les coordonnées relatives en x et y de l'objet perçu. C'est le robot percevant qui est pris comme origine de ces coordonnées (il est le centre de sa perception).
- public int getRadius() : retourne le rayon, c'est à dire la taille, de l'objet perçu
- public int getEnergy() : retourne l'énergie de l'entité perçue.
- public String getTeam() : retourne l'équipe de l'entité perçue. N'a de valeur que pour les robots.

Voici un petit exemple de l'utilisation de percepts. Si l'on voit de la nourriture alors on fait quelque chose, sinon si on voit un explorateur qui est d'une autre équipe que la nôtre, alors on fait autre chose, etc..

    	Percept[] percepts = getPercets();
    	for (int i=0;i<percepts.size();i++){
    		Percept p = percepts[i];
    		if (p.getPerceptType().equals("Food"))
    			// faire quelque chose
    		else if (p.getPerceptType().equals("Explorer") &&
    				 !p.getTeam().equals("MyTeam"))
    			// faire autre chose
    	}

Note: A chaque unité de temps, l'ensemble des percepts est mémorisé. De ce fait, on peut appeler la méthode getPercept autant de fois qu'on le désire sans que les calculs soient pénalisés.

##### La table des percepts

Voici les correspondances entre les types de percepts tels qu'ils sont retournés par la méthode getPerceptType(), la classe Java correspondante et leur nom usuel.

Type de percept | Classe Java | Remarques
--- | --- | ---
Home | warbot.kernel.Home | Base
RocketLauncher | warbot.kernel.RocketLauncher | Lanceur de missile
Explorer | warbot.kernel.Explorer | Explorateur
Rocket | warbot.kernel.Rocket | Missile
Obstacle | warbot.kernel.Wall et warbot.kernel.PalmTree | Obstacle
Food | warbot.kernel.Hamburger | Nourriture

#### Quelques exemples

- Voici un exemple élémentaire de " cerveau" de robot écrit en Java. Ce robot présente un comportement de "fourmi" (très simplifié): il cherche de la nourriture qu'il mange s'il en trouve, et il rebondit sur les obstacles. C'est le comportement des explorateurs "vert" de l'équipe Dumb.
- Voici un exemple de lanceur de missiles un peu bête écrit en Java. Il tire sur tous les ennemis sans trop réfléchir. C'est le comportements des lanceurs de missile "vert" de l'équipe Dumb.
- Un autre exemple de lanceur de missiles à peine plus intelligent. En plus il essaye aussi d'aller défendre les explorateurs en perdition et fonce sur les bases ennemies lorsqu'il reçoit leur position. A chaque fois il remet en question ses décisions, ce qui lui donne un comportement un peu véléitaire. C'est le comportements des lanceurs de missile "rouge" de l'équipe Dumb.
- Un exemple d'explorateur écrit en Python qui cherche les bases ennemies et prévient tous les lanceurs de missiles de sont groupe de la position de la base s'il la trouve. S'il détecte de la nourriture, il la prend et la rapporte à la base. C'est le comportements des explorateurs "rouge" de l'équipe Dumb.
- Un exemple de base très simple écrite en Python. C'est le comportements des bases "rouge" de l'équipe Dumb.

On pourra noter d'une part la simplicité des comportements, et d'autre part que les comportements collectifs sont très réduits (voire inexistant) dans ces exemples. A vous de jouer...

#### Autre documentation

Les cerveaux des robots sont des AbstractAgent au sens de MadKit. ils disposent ainsi de toutes les fonctionnalités des agents MadKit!! (création de groupes, demande d'adhésion à un groupe en jouant un rôle, récupération de tous les agents jouant un certain rôle dans un certain groupe, etc..). Pour plus d'information sur la manière de programmer en MadKit. Lire la documentation de MadKit concernant la programmation des agents.

La Javadoc du dossier WarBot donne toutes les API des classes utilisées par Warbot.

Le tutoriel de Warbot présentant la manière de réaliser ses premiers pas en Warbot.

## Règles

##### Généralités

Warbot est un projet dédié à l'étude des coordinations entre agents et notamment des procédés de coopération/compétition.

De ce fait, tous les procédés tendant à utiliser des failles de la plate-forme pour gagner sont considérées être des "tricheries" "et sont donc interdites.

Il est interdit de faire des sous-classes de corps (de body...). On a uniquement le droit de programmer des "cerveaux" d'agents (brains) soit en sous-classant la classe Brain soit en utilisant les langages de Scripts.

##### Paramètres généraux

Il existe un certain nombre de paramètres associés aux corps des robots. Ces paramètres doivent être conservés en l'état et ne doivent pas être modifiés directement par un programme. En particulier les paramètres suivants ne doivent en aucun cas être modifiés:

- Energie: Interdit de modifier directement l'énergie des robots. L'énergie des robots ne peut provenir que de leur énergie initiale, de la nourriture qu'ils absorbent. Cette énergie est diminuée uniquement lorsqu'il reçoit un missile.
- Vitesse maximale: interdit de modifier la vitesse maximale des robots. Mais il est par contre possible de réduire la vitesse des robots et donc de faire varier cette vitesse de 0 à la vitesse Maximale.
- Rayon de détection: le rayon de détection des robots est fixe et ne peut être modifié.
- La puissance des missile est fixe.

##### Communications

Les robots ne doivent communiquer que par l'intermédiaire de messages de type WarbotMessage et éventuellement de traces laissées au sol (dans de futures versions). Tout autre mécanisme de communication: tubes (pipes), sockets, fichiers, objets partagés, etc.. sont considérés comme de la tricherie.

##### Partage et références

Fondamentalement les agents sont supposées être distincts les uns des autres. Il ne peuvent pas partager d'informations. De ce fait il est interdit pour un agent (un corps ou une tête) d'avoir une référence directe vers un autre agent ou d'avoir une référence vers un objet partagé avec un autre agent. Normalement tout est fait pour empêcher cela, mais on connaît deux ou trois trucs qu'il serait possible de faire, et cela est interdit.

Il est interdit de créer d'autres agents que les robots, sauf si ces agents ne servent qu'à "réfléchir" et font donc partie des cerveaux des robots.

Il est interdit de créer d'autres agents que des robots qui permettraient à des robots de communiquer par des messages autre que des WarbotMessage.

##### L'unité de temps

Warbot fonctionne par un scheduler qui passe en revue tous les robots. L'unité de temps est donc le temps que l'on attribue à un robot pendant un tour. Attention: tous les robots n'ont pas accès au même nombre d'unités de temps. Chaque corps impose sa manière de gérer le temps. {{à finir et à approfondir}}

D'une manière générale, un robot peut:

- Réfléchir autant qu'il le désire (évidemment, cela peut bloquer le jeu, mais on demande tout de même aux joueurs de laisser les autres jouer...)
- Envoyer et lire autant de messages qu'il le désire.

En revanche un robot est limité par l'ensemble des actions physiques qu'il peut accomplir:

- il ne peut faire qu'une seule action par unité de temps: on appelle action soit un déplacement (commande move) soit une consommation (commande eat), soit une prise d'objet (commande take), soit une dépose d'objet (commande drop), soit un tir de rocket (launchRocket) soit une création de rocket (buildRocket).
- il ne peut tirer qu'un missile une fois toutes les 3 unités de temps.

Il est interdit de bloquer le fonctionnement des autres robots en faisant une boucle infinie.

# Bibliographie

[Fer 95] J. Ferber, les systèmes multi-agents, InterEditions, 1995.

©2001-2005 MadKit Team