Piloter le tank
Voici quelques exemples de code pour le tank...
« Hello World »
Quand on apprend un nouveau langage le premier programme que l'on fait est souvent appelé « hello world » car il vise simplement à afficher le message « hello world » à l'écran. Nous voulons piloter un tank donc on ne fera aucun affichage mais nous allons commencer par un programme tout aussi simple : avancer.
|
; ceci est un programme super simple
move
|
Voilà comment vous devez modifier le fichier pour que le programme soit intégré au reste du code.

Notez l'utilisation du caractère « ; » permet d'écrire des commentaires : des lignes qui ne seront pas interprétées par Netlogo, mais qui permettent de faire des remarques pour vous faciliter la compréhension du code.
Allez dans l'onglet « interface » et cliquez sur le bouton « go », pour voir votre programme s'executer...
Résultat : on voit que tous les robots avancent, et restent vite bloqués par des obstacles, c'est normal, notre programme est vraiment trop simple, nous allons le faire évoluer....
Cliquez à nouveau sur « go » pour arrêter le programme, puis sur l'onglet procédure pour retourner au code pour aller le modifier.
|
move ; avancer
right 2 ; tourner à droite de 2°
|
Ce nouveau code demande au robot de tourner légèrement sur sa droite après avoir avancé. Résultat le robot tourne en rond. Changez l'argument ( c'est à dire l'angle) de l'instruction right pour voir ce que cela donne...
Éviter les obstacles n'est pas une tâche simple et pour ne pas rester bloqué, je propose une solution radicale : Tirer pour ouvrir la voie...
Hum c'est la catastrophe.... corrigeons le programme pour qu'il ne tire qu'un missile à chaque fois
fired est une variable de votre tank et indique le nombre de missiles « en vol ». L'instruction if
permet de conditionner le tir au fait qu'aucun autre tir (de votre tank) n'est actuellement en cours.
Notez que l'instruction move est exécutée à chaque fois, seul l'instruction fire est conditionnée au test. Vous pouvez, si vous en avez besoin, mettre plusieurs instructions conditionnées par un if :
|
if fired = 0 [ right 20 fire] ; si un tir n'a pas été effectué récemment, alors tourner de 20° et tirer
move
|
Je vous conseille plutôt de le présenter comme ceci :
|
if fired = 0 [
right 20
fire
]
move
|
On a alors un programme plus lisible.
Note importante : faîtes attention aux espaces entre les instructions, il faut absolument que toutes les instructions soient séparées par un espace, sinon l'interpréteur du langage Netlogo a du mal à comprendre le programme. Dans l'exemple précédent, le simple oubli d'un espace autour du symbole « = » rend le programme incompréhensible par Netlogo, et amène alors à un message d'erreur.
(voir l'exemple ci-dessous)

En cas d'erreur
Si le programme s'exécute sur votre ordinateur,en cas d'erreur, le programme sera stoppé et un message d'erreur s'affichera (comme au dessus). En cas d'erreur sur un code envoyé sur le serveur du concours, votre robot ne fera rien (et si c'est le missile, il ira tout droit) et affichera un mot "erreur" à la place du robot ou du missile faisant l'erreur....

il y a en fait 3 robots sur cette image, celui du milieu est en erreur (et donc immobile et sans défense...).
Cherchons des étoiles...
L'objectif est de collecter des étoiles … Utilisons l'instruction face qui permet d'orienter notre tank vers un autre agent.
Notez l'utilisation de l'instruction one-of qui permet de sélectionner (aléatoirement) un seul agent d'un groupe. Si on n'avait pas utilisé one-of , l'instruction face aurait eu comme paramètre stars qui désigne toutes les étoiles, ce qui n'a pas de sens : on ne peut pas se tourner vers plusieurs objectifs à la fois, il faut en choisir un...
Résultat, ça marche très mal : à chaque instant, le tank hésite entre plusieurs étoiles (l'instruction one-of ne choisit pas toujours la même étoile.)....
Solution : rechercher l'étoile la plus proche:
|
face min-one-of stars [distance myself]
move
|
Notez l'utilisation de l'instruction min-one-of, grâce à cet instruction l'agent est sélectionné sur un critère calculé (et non plus aléatoire). Le critère est donnée entre [ ] , c'est le calcul de distance entre votre (« myself ») robot et toutes les étoiles. L'étoile sélectionnée par l'instruction min-one-of, est donc la plus proche de votre robot.
Attention si il n'y a aucune étoile cela amènera à une erreur car l'instruction min-one-of aura pour résultat « nobody », et l'instruction « face nobody » n'a pas de sens....
En cas d'erreur de ce type, le déroulement de la partie est interrompu. Dans la version locale du jeu (celle que vous utilisez), cela vous permettra de comprendre l'erreur et de la corriger. Dans la version du jeu utilisé pour le concours, il est prévu simplement ne rien faire, ainsi cette erreur n'interrompra pas l'exécution de votre code, mais dans le cas ou il n'y a aucune étoile, votre robot ne fera rien, et sera donc à la merci des autres candidats...
Pour l'écrire parfaitement cela s'écrit alors :
|
let s min-one-of stars [distance myself]
if s != nobody [face s]
move
|
Notez l'utilisation d'une variable, s qui représente l'étoile sélectionnée comme la plus proche. L'instruction let déclare une variable et set permet d'en changer sa valeur.
Voici un exemple plus simple d'utilisation de variable :
let x 0 ; x est maintenant déclaré et a la valeur 0
set x 1 ; x a maintenant la valeur 1
Notez aussi l'utilisation du symbole « != » dans le test, il signifie « n'est pas égal ».
À l'attaque
Un bon moyen d'être bien classé est de prendre les étoiles des autres candidats (celles qu'ils ont déjà collectées). Pour cela il suffit de leur tirer dessus, une fois leur jauge d'énergie à 0, ils relâcherons toutes leur étoiles...
Comme dans un des exemples précédents, l'instruction one-of sélectionne un robot au hasard à chaque exécution du code, or il ne choisit pas toujours le même...
De plus notre robot est dans la liste des robots, ainsi il risque de se sélectionner lui-même en tant qu'ennemi potentiel... Il faut donc ajouter un « filtre » permettant de s'exclure de la sélection, il s'agit de l'instruction other.
|
face one-of other robots
fire
|
Le résultat n'est pas beaucoup mieux. Il faut utiliser un critère de sélection pour choisir sur quel tank nous allons tirer.
|
let r min-one-of other robots [distance myself]
if r != nobody [face r]
fire
|
C'est mieux mais les tirs sont trop rapprochés, utilisons le morceau de code (vu précédemment) permettant de ne tirer qu'un missile à la fois.
|
let r min-one-of other robots [distance myself]
if r != nobody [face r]
if fired = 0 [fire]
|
Note : vous pouvez avoir jusqu'à 3 missiles en vol simultanément. Au delà, la fonction fire ne fait rien.
Pour obtenir une bonne stratégie, il faudra habilement mixer les codes et stratégies de recherche d'étoiles, d'attaque, ainsi que de défense...
Défense
Si votre tank ne bouge pas, il recharge son énergie, ce qui le rend plus résistant aux explosions....
Mais aussi plus facile à viser vu qu'il n'avance pas...
Une autre solution possible est la riposte : tirer s'il y a un missile dans un rayon donné.
|
let m one-of missiles in-radius 5 ; soit m un missile dans un rayon de 5
if m != nobody and fired = 0 [ ; si il y a un missile et qu'on a pas déjà tiré
face m ; on se met face au missile
fire ; et on tire.
]
|
Essayez ce code en jouant avec le tank que vous pouvez piloter à la souris. Tirez sur un des tanks (normalement ils sont immobiles), vous allez voir comment ils « ripostent » pour stopper votre missile.
Notez l'utilisation d 'opérateur logique comme and , vous disposez bien sûr aussi de l'opérateur or (pour réaliser le « ou logique »).
Vous avez pu remarquer que certaines ripostes sont peu précises, l'orientation prise au moment du lancement du missile n'était pas la bonne car la cible est en mouvement. C'est pour cela que les missiles peuvent être dirigés en vol... Les missiles se pilotent exactement comme les tanks au détail près qu'ils avancent tout le temps, vous ne pouvez donc donner que la direction.
Avant de passer au pilotage des missiles, voici un exemple d'instruction très utile ifelse, cela permet de définir un bloc de code à exécuter si le test est vrai et un autre si le test est faux.
|
let m one-of missiles in-radius 5 ; soit m un missile dans un rayon de 5
ifelse m != nobody and fired = 0 [ ; si il y a un missile et qu'on a pas déjà tiré
face m ; on se met face au missile
fire ; et on tire...
]
[ ; si il n'y a pas de danger, cherchons des étoiles
let s min-one-of stars [distance myself]
if s != nobody [face s]
move
]
|
Dans cet exemple le premier bloc de code est le même que l'exemple précédent, il s'agit d'une procédure de défense. Dans le deuxième bloc , qui ne sera exécuté que si le test est faux, on décide de chercher des étoiles car aucun danger ne menace notre robot.
La suite :
Programmer les missiles
Stratégies...