12
Apr
2010

Contexte

Lorsque l'on participe à des jeux de rôle, on doit presque toujours se munir de dés au nombre de faces surprenant.

Bien que les lancers de dés fassent partie du plaisir de ces jeux, il arrive que, lors d'une partie, les joueurs n'aient pas les dés qu'il faut, ou n'en aient pas suffisamment. Pour résoudre ce problème, voici le lanceur de dé virtuel ! (applaudissements)

Extrêmement polyvalent, ce programme a été conçu pour être le plus simple possible : pour reproduire le lancer de deux dés à 12 faces, par exemple, il vous suffira de taper "2d12".

Il est également possible de joindre à votre demande un modificateur, tel que "2d12+10", ou "2d12-3"; La somme des lancers de dés sera ajustée en conséquence.

Enfin, il est possible de donner au programme plusieurs ordres en même temps, en les séparant par des espaces : l'ordre "1d10 2d6+3" lancera un dé à dix faces, puis fera la somme de deux dés à six faces, plus 3.

Si vous voulez jeter un simple dé à six faces, tapez "1D6", et pour simuler le jet d'une pièce, (pour jouer à pile ou face), tapez "1d2".

Détails

Le principal intérêt (ou la principale difficulté, selon comment on voit les choses), de ce programme, était d'arriver à faire comprendre au programme un "ordre" le plus proche possible du langage humain.

A cette occasion, j'ai pu me perfectionner dans l'art ancestral ^^; des expressions rationnelles, qui permettent d'analyser une chaîne de caractères dont on connaît la structure, mais pas le contenu exact. Il s'agit d'un outil très puissant, que j'aimerai vous présenter.

Un exemple valant mieux qu'un long discours, voici comment j'ai créé l'expression rationnelle utilisée dans ce programme :

Naissance d'une expression rationnelle

les expressions rationnelles doivent être encadrées par un caractère; je choisis le dièse '#':

$expression = '##';

je sais qu'une demande faite par l'utilisateur doit commencer par un chiffre, ce qui est représenté par le symbole '\d':

$expression = '#\d#';

Mais il peut également s'agir d'un nombre, c'est-à-dire d'une suite de chiffres ; je rajoute donc le symbole '+', qui signifie 'il y a au moins une occurrence du terme précédent'.

$expression = '#\d+#';

Le premier nombre doit être suivi de la lettre 'd':

$expression = '#\d+d#';

Afin de ne pas faire de distinction entre le 'd' miniscule et le 'D' majuscule, je rajoute une option: la lettre i. L'expression devient ainsi insensible à la casse, l'utilisateur final pourra taper indifféremment "1d2" et "1D2".

$expression = '#\d+d#i';

Après la lettre, il y aura un autre chiffre ou nombre:

$expression = '#\d+d\d+#i';

Il convient ici d'aborder la notion de "capture" des chaînes de caractères : en encadrant certaines parties de parenthèses, je demande à PHP de "séparer" en différentes parties ce qui est demandé par l'utilisateur : d'un coté le nombre de dés, de l'autre le nombre de faces...

$expression = '#(\d+)d(\d+)#i';

Laissons de coté cette partie de l'expression pour le moment, et intéressons-nous à la partie qui définira le modificateur ("+" ou "-" ; suivi d'un nombre). Cette partie peut donc commencer par le symbole "+"...

(\+)

Notez que, ce symbole ayant une signification particulière dans une expression rationnelle (voir plus haut), il convient de rajouter le signe " \ ", signifiant "le caractère suivant est le caractère "+" lui même, pas une option".

Nous l'avons vu, le premier symbole de cette partie sera soit un "plus", soit un "moins". On représente cette situation à l'aide des crochets, qui définissent une "classe de caractères", et du symbole "|", qui veut dire "ou" :

([\+|-])

Le signe "plus" ou "moins" doit être suivi d'un nombre, nous ajoutons donc :

(([\+|-])(\d+))

Enfin, afin d'indiquer au programme que cette partie de l'expression est optionnelle, nous ajoutons encore un symbole "|" :

(([\+|-])(\d+)|)

L'expression se lit alors "je recherche soit le signe + ou - suivis d'un chiffre, soit rien du tout".

Nous pouvons maintenant lier les deux morceaux de l'expression :

$expression = '#(\d+)d(\d+)(([\+|-])(\d+)|)#i';

Et, cerise sur le gâteau, ajouter les caractères "?:", qui indiquent au programme que ces parenthèses-là ne définissent pas une expression à capturer séparément (comme c'est le cas avec les "(\d+)"), mais simplement la définition de motifs alternatifs, ici : "soit le signe + ou - suivis d'un chiffre, soit rien du tout".

Nous obtenons enfin :

$expression = '#(\d+)d(\d+)(?:([\+|-])(\d+)|)#i';

Trop facile.

Commentaires

1. le 02 ao?t 2010 (12 h 48), par Jazzbass :
bonjour, je vous écris depuis un commentaire car je n'ai pas trouvé votre mail. Voilà je suis entrain d'essayer de développer un jeu rpg en php et j'ai trouvé votre script de jet de dé très intéressant. Vous serait il possible de me faire parvenir les sources s'il vous plait ? Mon jeu est encore au stade experimental et en local uniquement, il ne verra meme peut etre jamais le jour si je n'ai pas trop le temps de m'y consacré. en tout cas s'il devient un jour disponible il sera gratuit, avec juste une petite partie don. J'espère que vous pourrez me faire parvenir votre script. Cordialement.
Réponse de Manu
Okay, je vous envoi un mail.
2. le 03 mai 2011 (13 h 08), par cécé :

Bonjour, juste pour savoir, comment sont générer "aléatoirement" le jets de dés?

Vous connaissez "RANDOM.ORG" ?

Voilà, c'était juste ma petite idée participative à votre projet :)

Bon après j'avoue c'est peut-être pas facile à mettre en oeuvre, mais vous garantiriez un vrai hasard.

Bonne continuation!

Réponse de Manu

Bonjour, merci pour le lien, je ne connaissait pas. J'utilise la fonction de hasard de PHP, rand(), qui malheureusement est pseudo-aléatoire.

3. le 04 mai 2011 (16 h 27), par marmouchon :

Dans le contexte d'un jeu de role entre amis je pense que le pseudo aléatoire suffit bien. Il ne s'agit pass de lotterie. De la même manière, je ne pense pas que les gens vont peser les dés en vrai pour valider qu'ils sont équilibré.

Mais utiliser ceci pour une lotterie ou un tournoi serait un tout autre problème oui.

Réponse de Manu

Ça tombe bien, Security Now va bientôt faire un épisode sur l'aléatoire. Je pourrais en faire un billet sympa.

L'ajout de commentaires est désactivé.

Manu