Tutoriel LeekScript : Les Conditions

De Leek Wars Wiki
Aller à : navigation, rechercher

Bien ! Il est temps d'ajouter des conditions à vos programmes !

Pour l'instant, votre code fait toujours la même chose. Les conditions vont remédier à cela.

Les conditions sont la première "structure de contrôle" dont nous allons parler. Celles-ci permettent de rendre votre code plus flexible, de faire en sorte qu’il s’adapte au contexte.

Pour l’instant, vous avez vu que votre code s'exécute de façon linéaire, une instruction après l’autre. Maintenant, nous allons voir comment exécuter ou non du code selon une condition.


Opérateurs de comparaison

Mais avant d’en venir aux conditions, il faut d’abord revenir sur les opérateurs. Nous avons surtout parlé des opérateurs permettant d’effectuer des calculs, et pour s’attaquer aux conditions, il va falloir voir ceux qui permettent de faire des comparaisons.

Ces opérateurs sont un peu différents de ceux que nous avons déjà vu. Par exemple, vous avez vu qu’en LeekScript, l’expression "4 + 6" donne pour résultat 10. Le résultat est un entier, un nombre. C’est une expression mathématique exprimant un calcul.

Les opérateurs de comparaison vont permettre d’écrire des expressions mathématiques qui exprimeront une relation. Si nous écrivons l’expression "2 < 6". Vous comprenez que "2 est inférieur à 6". Il y a une relation d'ordre entre 2 et 6. Eh bien, l’ordinateur aussi comprend cela. Mais comment doit-il interpréter le résultat de cette expression ? Déduire un nombre de cette expression n’aurait pas beaucoup de sens.

Et c’est là qu’interviennent les booléens, ces petites bêtes dont nous avons déjà parlé. Souvenez-vous, les booléens peuvent avoir deux états, soit vrai, soit faux.

C’est la même chose avec ces expressions relationnelles, elles sont vraies, ou elles sont fausses. Ainsi, l’expression "2 < 6" est vraie, vous serez d’accord pour dire que 2 est plus petit que 6, j’espère. Donc cette expression a pour résultat true, la valeur vraie d’un booléen. Par contre, l’expression "4 < 1" est fausse, et aura donc false pour résultat.


Opérateur d’égalité

Vous aurez souvent besoin de savoir si une valeur est égale ou non à une autre. Par exemple pour savoir si la distance avec votre adversaire est égale à une certaine valeur.

L’opérateur d’égalité a pour symbole "===", 3 symboles "=" à la suite, ni plus, ni moins. Ainsi vous pouvez écrire :

var celluleEnnemi = getCell(getNearestEnemy());
var distDe5 = getCellDistance(getCell(), celluleEnnemi) === 5;
debug(distDe5);

Ici, "getCellDistance(getCell(), celluleEnnemi)" donne la distance entre votre poireau et l’ennemi le plus proche. Si cette distance est exactement de 5 cellules, alors le résultat sera true, sinon le résultat sera false. Ce résultat sera assigné à la variable "distDe5".

Essayez ce code avec une distance de 1 par exemple : lorsque votre adversaire est collé à vous, le code affiche "true" au lieu de "false".


Attention, il ne faut pas confondre l'opérateur d'affectation "=" et celui de comparaison "===". En mathématique, on utilise un seul signe égal pour symboliser l'égalité, mais pas en LeekScript. Faites donc bien attention à utiliser "===" dans vos conditions.

Opérateur d’inégalité

Il existe aussi un symbole pour l’inégalité, il s’agit de "!==". Un point d’exclamation suivi de 2 "=". Ce symbole fait exactement l’inverse de "===". Il renvoie true lorsque les deux valeurs sont différentes, et false lorsqu'elles sont identiques.

Essayez ceci :

var celluleEnnemi = getCell(getNearestEnemy());
var aDistance = getCellDistance(getCell(), celluleEnnemi) !== 1;
debug(aDistance);

Ce code affiche "true" lorsque votre adversaire est à distance, et "false" lorsqu'il est collé à vous.

Opérateurs relationnels stricts

Les opérateurs relationnels sont "<" et ">", c’est-à-dire "Inférieur strictement" et "Supérieur strictement". (Si besoin, la touche pour ces symboles se trouve à gauche du "W", l’un se fait avec la touche MAJ enfoncée, l’autre sans)

Bref, ces opérateurs permettent de tester la relation d'ordre entre deux éléments. Par exemple :

var resultat = a < b;

Si la valeur de "a" est inférieure strictement à celle de "b", le résultat sera true, qui sera assigné à la variable "resultat". Si c’est l’inverse, ce sera false.

Même chose, mais à l’inverse pour :

var resultat = a > b;

Si la valeur de "a" est supérieure strictement à celle de "b", le résultat sera true, qui sera assigné à la variable "resultat". Si c’est l’inverse, ce sera false.

On parle bien ici de relations "strictes". Si a et b ont la même valeur, le résultat sera false; puisque aucune n’est plus petite ou grande que l’autre.


Opérateurs relationnels mixtes

Et maintenant, la version non stricte des opérateurs relationnels.

Ainsi, pour l’opérateur supérieur ou égal, il suffit de mixer les opérateurs d’égalité et de relation. On obtient l’opérateur ">=" ! Le symbole de supériorité suivi du symbole d’égalité.

Par exemple :

var resultat = a >= b;

Si la valeur de "a" est supérieure ou égale à celle de "b", le résultat sera true, qui sera assigné à la variable "resultat". Si c’est l’inverse, donc inférieure strictement, le résultat sera false.

Et pour traduire "Inférieur ou égal", l’opérateur est donc "<=".

Par exemple :

var resultat = a <= b;

Si la valeur de "a" est "inférieure ou égale à celle de "b", le résultat sera true, qui sera assigné à la variable "resultat". Si c’est l’inverse, donc supérieure strictement, le résultat sera false.

Opérateurs logiques

Quand il n’y en a plus, il y en a encore ! Mais rassurez-vous, on aperçoit le bout du tunnel. Les opérateurs précédents comparaient des nombres, ceux que nous allons voir permettent de comparer des booléens. Il s’agit des opérateurs AND, OR, et NOT.


AND

En Français, c’est un "ET logique". Il y a deux façons de l’écrire en LeekScript, soit en écrivant "and", soit en utilisant le symbole "&&" (deux "&", le symbole de la touche 1).

Regardez ce code :

var A = true;
var B = false;
debug(A && B); // Affiche : false
debug(A and B); // Affiche : false

Le résultat d'un ET logique sera true à l'unique condition que les deux valeurs valent true.

Ainsi, on obtient :

A B A && B
false false -> false
false true -> false
true false -> false
true true -> true

Avec ce code, vous pouvez tester les quatre couples de valeur :

debug("false AND false : " + false && false);  // Affiche : false
debug("false AND true : " + false && true);    // Affiche : false
debug("true AND false : " + true && false);    // Affiche : false
debug("true AND true : " + true && true);      // Affiche : true

OR

En Français, c’est un "OU logique". Il y a deux façons de l’écrire en LeekScript, soit en écrivant "or", soit en utilisant le symbole "||" (deux "|", le symbole de la touche 6, en utilisant ALT GR).

Retestons avec le code précédent :

var A = true;
var B = false;
debug(A || B); // Affiche : true
debug(A or B); // Affiche : true

Cette fois, le résultat est true ! Le résultat d'un OU logique sera true si au moins une des deux valeurs vaut true.

Ainsi, on a :

A B A || B
false false -> false
false true -> true
true false -> true
true true -> true

A nouveau, si vous voulez tester :

debug("false OR false : " + false || false);  // Affiche : false
debug("false OR true : " + false || true);    // Affiche : true
debug("true OR false : " + true || false);    // Affiche : true
debug("true OR true : " + true || true);      // Affiche : true

NOT

En Français, c’est un "NON logique". Il y a deux façons de l’écrire en LeekScript, soit en écrivant "not", soit en utilisant le symbole "!" (C’est un bête point d’exclamation).

Contrairement aux précédents qui comparaient deux valeurs, celui-ci ne s’applique que sur une seule. Il permet d’inverser un booléen.

Testons le :

var A = true;
var B = false;
debug(!A); // Affiche : false
debug(!B); // Affiche : true

Le résultat d'un NON logique sera l'inverse de la valeur. Si la valeur est true, elle devient false, et inversement.

Simplement, on a :

A  !A
false -> true
true -> false

Évidemment, si vous voulez tester :

debug("!false : " + !false);
debug("!true : " + !true);


Les opérateurs sont vraiment utiles, vous pouvez me croire. Qu’ils soient logiques ou arithmétiques, bientôt vous en utiliserez absolument partout.

Les Conditions

Pfiou, nous en avons fini avec les opérateurs. Peut-être que vous avez encore du mal à voir à quoi ils vont vous servir. Cela devrait devenir plus clair dans la suite.

Le "IF"

if est le mot-clé qui va nous permettre d'écrire une condition. En anglais, "if" signifie "si". Il permet de dire à votre poireau Si ceci, alors fais cela.

La syntaxe est la suivante :

if (condition) instruction;

Ici, la condition sera une "expression". Si cette expression vaut true, donc si elle est vrai, alors l’instruction sera exécutée. Par contre, si l’expression est fausse (si elle vaut false), alors l’instruction ne sera pas exécutée.


Mais cette syntaxe ne permet d'exécuter qu'une seule instruction.

Si vous souhaitez mettre plus d'instructions, il faudra utiliser cette syntaxe :

if (condition) 
{
	instruction;
	instruction;
	instruction;
}

Avec cette syntaxe, vous pouvez mettre autant d'instructions que vous le souhaitez. Voire même une seule, ou aucune. Cette syntaxe est un peu plus lisible et aérée que la précédente.

Si "condition" est une expression qui a pour résultat true, alors le bloc de code contenu entre les accolades "{" et "}" sera exécuté. Et si la condition n'est pas vérifiée et vaut donc false, il ne se passera rien.

Essayons ceci :

if (false) 
{
	debug("La condition est vraie !");
}

Il ne se passe rien ! La condition étant fausse, l'instruction debug n'est pas exécutée. Essayez de remplacer false par true dans la condition, vous verrez que cette fois-ci, le message apparaît.


Le "ELSE"

else est le mot-clé qui permet d'exécuter du code si la condition n'est pas remplie. En anglais, "else" signifie "sinon". Il permet de dire à votre poireau Si ceci, alors fais cela, sinon, fais ceci.

La syntaxe pour l'utiliser est la suivante :

if (condition) 
{
	// Instructions
}
else
{
	// Autres instructions
}

Comme précédemment, si la condition est vraie, le code dans les accolades qui suivent le IF sera exécuté. Mais si la condition n'est pas vraie, c'est le code se trouvant dans les accolades après le ELSE qui sera exécuté.

Améliorons le code vu plus haut :

if (false) 
{
	debug("La condition est vraie !");
}
else
{
	debug("La condition est fausse !");
}

Et voilà ! Avec true, vous aurez le message annonçant que la condition est vraie. Et avec false, vous aurez le message annonçant que la condition est fausse.


Le "ELSE IF"

Il est possible de "fusionner" les mots-clé if et esle afin de créer différents cas de figure. On obtient quelque chose comme ceci :

if (condition) 
{
	// "condition" est vraie
}
else if (condition2)
{
	// "condition" est fausse, mais "condition2" est vraie
}
else 
{
	// "condition" et "condition2" sont fausses
}

Vous voyez le topo ? Non ? Pas de panique ! Vous allez comprendre avec quelques exemples. Il est temps de mettre en pratique les différents opérateurs que vous avez découvert !

Les ternaires

Les ternaires sont une autre façon d'écrire une condition. Prenons une condition basique avec un if/else :

if (condition) 
{
	action1();
}
else 
{
	action2();
}

Le même code avec un ternaire donnera ceci :

(condition) ? action1() : action2();

On peut aussi s’en servir pour une affectation, par exemple :

var maVariable = (condition) ? valeur1 : valeur2;

Les ternaires ont le désavantage d'être beaucoup moins lisibles que la structure if. Mais ils sont un peu moins cher en opérations.

Si vous débutez, vous n'avez pas encore besoin d'optimiser la moindre opération de votre code. Préférez donc utiliser la structure if classique pour vos débuts.


Quelques exemples

Comparons !

Comme vous l'avez vu, il est possible de comparer des valeurs. Et que vaut le résultat d'une comparaison ? Un booléen, oui ! Ainsi, on peut facilement faire ce genre de choses :

if (3 < 4) 
{
	debug("3 est inférieur à 4 !");
}

Bon, ce n'est pas la découverte du siècle, mais vous commencez peut-être à imaginer tout ce que vous pourriez faire. Faisons une comparaison un peu plus intéressante, et utile... Récupérons la distance entre vous et votre adversaire !

var distance = getCellDistance(getCell(), getCell(getNearestEnemy()));

if (distance < 10) 
{
	debug("L'ennemi approche mon Commandant !");
}

Et voilà ! Vous êtes en mesure d'exécuter du code en fonction de la distance avec votre adversaire. Ici, le message ne s'affichera que si l'ennemi se trouve à moins de 10 cellules de vous.

Si vous avez un peu de mal avec la ligne :

var distance = getCellDistance(getCell(), getCell(getNearestEnemy()));

En voici une version plus simple à comprendre :

var maCellule = getCell();                     // On récupère la cellule de son poireau
var ennemi = getNearestEnemy();                // Puis on récupère l’id de l’ennemi
var celluleEnnemi = getCell(ennemi);           // Ensuite, la cellule de cet ennemi
var getCellDistance(maCellule, celluleEnnemi); // Et enfin, on obtient la distance entre les deux cellules


Vous pouvez aussi imbriquer vos conditions, comme ceci par exemple :

var enemy = getNearestEnemy();
var distance = getCellDistance(getCell(), getCell(enemy));

if (distance < 11) 
{
	if (distance < 8) 
	{
		useWeapon(enemy);
	}
	else
	{
		useChip(CHIP_SHOCK, enemy);
	}
}

Nos amis les booléens

Prenons la fonction lineOfSight, elle renvoie true s'il y a une ligne de vue entre les deux cellules passées en paramètres.

Testons si votre poireau peut voir son adversaire :

var enemy = getNearestEnemy();
var los = lineOfSight(getCell(), getCell(enemy));

if (los) 
{
	debug("J'le vois chef ! J'le vois !");
}
else 
{
	debug("Où est-il passé !? Il se cache ce lâche !");
}

Et hop, vous pouvez savoir si votre poireau voit son adversaire, et donc s'il peut lui tirer dessus.

N'oubliez pas que cette fonction renvoie un booléen, il est parfaitement inutile de faire quelque chose comme cela :

var myCell = getCell();
var enemyCell = getCell(getNearestEnemy());

if (lineOfSight(myCell, enemyCell) == true) 
{
	debug("J'le vois chef ! J'le vois !");
}

Le IF vérifie déjà si la condition est vraie, c'est comme si vous disiez à votre poireau : Est-ce que la condition "Il y a une ligne de vue est vraie" est vraie ? C'est redondant et vous prenez le risque que je vous tape sur les doigts.

Par contre, si c'est la condition inverse qui vous intéresse, vous pourriez vouloir faire quelque chose comme cela :

var myCell = getCell();
var enemyCell = getCell(getNearestEnemy());

if (lineOfSight(myCell, enemyCell) == false) 
{
	debug("Où est-il passé !? Il se cache ce poltron !");
}

Ce n'est pas mieux ! Le retour de lineOfSight vaut true ou false. Avec le retour, votre condition sera (true == false) ou (false == false). Ce qui est assez inutile.

Quelle est la bonne solution alors ? C'est d'utiliser le NON logique !

var myCell = getCell();
var enemyCell = getCell(getNearestEnemy());

if (lineOfSight(myCell, enemyCell)) 
{
	debug("J'le vois chef ! J'le vois !");
}

if (!lineOfSight(myCell, enemyCell)) 
{
	debug("Ou est t-il passé !? Il se cache ce poltron !");
}

Voilà comment on utilise correctement des booléens. Ce n'est plus redondant, c'est beau, c'est propre. On en mangerait.


Vous n'avez pas besoin des opérateurs ==, !=, === et !== avec des booléens. Il vous serviront principalement pour comparer des nombres, des constantes.

Par exemple :

if (getWeapon() != WEAPON_PISTOL)
{
	setWeapon(WEAPON_PISTOL);
}

Avec ce code, si vous n'avez pas d'armes dans les mains ou si ce n'est pas le Pistolet, alors votre poireau équipera ce dernier.

Mise en situation

Une des premières réflexions qui vous traversera l'esprit sera peut-être celle-ci :

"Hum, je pourrais utiliser le Pistolet si je le peux, et dans le cas contraire, utiliser Etincelle". Et bien pourquoi pas ?

Il vous faudra donc commencer par les conditions à réunir pour pouvoir utiliser le Pistolet.

Ce dernier possède une portée allant de 1 à 7. Il faut donc commencer par vérifier la distance à l'aide de getCellDistance :

if (getWeapon() != WEAPON_PISTOL)
{
	setWeapon(WEAPON_PISTOL);
}

var enemy = getNearestEnemy();
var distance = getCellDistance(getCell(), getCell(enemy));

if (distance <= 7) 
{
	useWeapon(enemy);
	useWeapon(enemy);
	useWeapon(enemy);
}

Mais ce n'est pas suffisant. La grande majorité des armes et des puces sont soumis à ce qu'on appelle "la ligne de vue". En clair, pour pouvoir utiliser le Pistolet, votre poireau doit pouvoir voir sa cible. Pour vérifier cela, on utilise la fonction lineOfSight.

if (getWeapon() != WEAPON_PISTOL)
{
	setWeapon(WEAPON_PISTOL);
}

var enemy = getNearestEnemy();
var distance = getCellDistance(getCell(), getCell(enemy));
var los = lineOfSight(getCell(), getCell(enemy));

if (distance <= 7 && los) 
{
	useWeapon(enemy);
	useWeapon(enemy);
	useWeapon(enemy);
}

Nous avons notre condition ! On peut la lire comme "Si la distance est inférieure ou égale à 7 et qu'il y a une ligne de vue".

Il n'y plus qu'à rajouter l'utilisation d'Etincelle.

if (getWeapon() != WEAPON_PISTOL)
{
	setWeapon(WEAPON_PISTOL);
}

var enemy = getNearestEnemy();
var distance = getCellDistance(getCell(), getCell(enemy));
var los = lineOfSight(getCell(), getCell(enemy));

if (distance <= 7 && los) 
{
	useWeapon(enemy);
	useWeapon(enemy);
	useWeapon(enemy);
}
else 
{
	useChip(CHIP_SPARK, enemy);
	useChip(CHIP_SPARK, enemy);
	useChip(CHIP_SPARK, enemy);
}

Ce code utilisera le Pistolet s'il y a la vue et la portée pour, sinon il utilisera Etincelle. Il n'y a pas besoin de vérifier la portée d'Etincelle. Si votre poireau est trop loin, il ne pourra juste pas l'utiliser.


Conclusion

Désormais, vous pouvez rendre votre code intelligent. Vous êtes capable de le faire s'adapter à la situation.

Le prochain chapitre parlera des boucles, une autre notion très importante en programmation.