Une donne de solitaire doit être imprévisible quand tu la commences et reproductible quand tu veux l’examiner plus tard. Ces deux exigences sont compatibles si le mélange part d’une graine : un nombre qui détermine l’ordre du paquet.
Cards4.net applique cette approche à ses jeux de solitaire. La graine nous permet de recréer une donne pour la rejouer, pour un défi quotidien ou pour un rapport de bug. Ce qui varie d’un mode à l’autre, c’est la façon dont nous choisissons ce nombre, et ce choix compte quand on décrit une donne comme aléatoire ou solvable.
D’un nombre à un paquet
Notre moteur de cartes commun transmet la graine au générateur pseudo-aléatoire exsplus d’Erlang, puis appelle Enum.shuffle d’Elixir pour réordonner les cartes. Le générateur produit une suite de valeurs reproductible : c’est pourquoi la même entrée peut nous donner le même paquet mélangé.
Pour recréer une position de départ, il nous faut aussi le jeu et sa variante. Klondike, FreeCell et Spider disposent leurs cartes différemment, et le nombre d’enseignes de Spider modifie le paquet lui-même. Une graine n’a donc de sens qu’avec ces règles et l’implémentation qui l’interprète.
Cette reproductibilité vaut pour l’implémentation actuelle. Une modification de l’ordre initial du paquet ou de la procédure de mélange pourrait changer la donne obtenue. La graine est une référence utile pour une partie, mais ce n’est pas une promesse que toute implémentation future interprétera ce nombre de façon identique.
D’où vient la graine
Pour une demande ordinaire de partie solo aléatoire, le serveur choisit un nombre entre zéro et 2^63 - 1 à l’aide du module rand d’Erlang. Il transmet ensuite ce nombre au moteur de jeu. Cette sélection ne tient compte ni des victoires ou défaites récentes du joueur, ni de l’historique de son compte.
Le moteur contient aussi une fonction auxiliaire capable d’obtenir une graine à partir de :crypto.strong_rand_bytes. Sa présence ne signifie pas que chaque demande de partie l’utilise : le chemin de requête ordinaire décrit ci-dessus choisit sa graine avec rand.
Cette distinction compte, car ni le générateur de la requête ni le mélange exsplus initialisé par la graine ne doivent être décrits comme cryptographiquement sûrs. La documentation d’Erlang distingue explicitement ses générateurs pseudo-aléatoires des générateurs adaptés à la cryptographie. Notre implémentation nous fournit des donnes de solitaire reproductibles ; elle ne constitue pas un protocole cryptographique d’équité.
Combien d’ordres sont possibles ?
Un paquet de 52 cartes distinctes possède 52! ordres possibles, soit environ 8.07 × 10^67. Ce nombre compte chaque choix possible pour la première carte, multiplié par chaque choix restant pour la deuxième, et ainsi de suite.
Une graine de 63 bits ne peut prendre que 2^63 valeurs, soit environ 9.22 × 10^18. Comme chaque graine produit un seul résultat avec une implémentation fixe, elle peut atteindre au plus autant d’ordres du paquet, voire moins si des graines différentes produisent le même ordre. Nous ne pouvons pas prétendre échantillonner tous les arrangements possibles d’un paquet physique.
Ce plus petit nombre reste grand, mais sa taille seule ne prouve pas la qualité de la distribution. De même, quelques donnes gênantes ne démontrent pas que le mélange est biaisé. Une enquête sérieuse exige des graines enregistrées, les réglages de jeu concernés et suffisamment de résultats pour tester une affirmation précise.
Les donnes solvables viennent d’un ensemble plus restreint
Le mode solvable ajoute une étape de sélection avant le mélange. Des solveurs hors ligne essaient des donnes et enregistrent les graines pour lesquelles ils trouvent un chemin gagnant. Lorsque la bibliothèque correspondante est disponible, le serveur choisit au hasard une entrée de cet ensemble.
La donne obtenue est reproductible de la même manière qu’une donne ordinaire, mais elle provient d’une collection filtrée. Les donnes que le solveur n’a pas pu terminer en sont absentes, même lorsqu’une solution pourrait exister. L’ensemble est fini : il est donc possible de revoir une donne.
Les défis quotidiens puisent aussi dans ces bibliothèques, en utilisant le jeu, la variante et la date UTC pour choisir une entrée. Tous ceux qui jouent au défi du jour dans la même variante reçoivent la même position. Le choix est fixé pour la journée au lieu d’être fait séparément pour chaque joueur.
Les donnes numérotées de FreeCell à la Microsoft utilisent leur propre algorithme de compatibilité. Leurs numéros appartiennent à ce système ; ils ne sont pas interchangeables avec nos graines de mélange ordinaires. Le guide des numéros de donne explique comment en ouvrir une en particulier.
Ce que tu peux vérifier toi-même
La page d’équité peut reconstruire, à partir de leurs graines publiques, les positions de départ du Klondike Turn 1 et Turn 3, de FreeCell et des variantes de Spider à une, deux et quatre enseignes. Comparer le résultat avec la donne d’origine permet de vérifier que la graine et le tableau concordent.
Cet outil utilise notre backend. Il n’établit pas de façon indépendante comment la graine a été choisie, ne prouve pas qu’un processus de sélection était impartial et ne montre pas qu’une donne est gagnable. Ce sont des questions distinctes.
Pour une donne suspecte ou un rapport de bug, conserve la graine et la variante avec une description de ce qui s’est passé. Une position reproductible nous donne quelque chose à examiner. Qualifier un mélange d’équitable est bien moins utile si nous n’expliquons pas aussi ce qui peut réellement être vérifié.
Questions fréquentes
Puis-je reproduire une donne de Cards4.net ?
Pour les jeux de solitaire pris en charge, la même graine, la même variante et la même implémentation du mélange reproduisent la même position de départ. La page d’équité peut reconstruire cette position.
Quel générateur aléatoire le mélange utilise-t-il ?
Le moteur de cartes commun initialise avec la graine le générateur pseudo-aléatoire exsplus d’Erlang, puis appelle Enum.shuffle. Les demandes ordinaires de partie solo utilisent aussi un générateur pseudo-aléatoire pour choisir une graine de 63 bits.
Le mélange peut-il produire tous les ordres possibles du paquet ?
Non. Une implémentation fixe avec une graine de 63 bits peut produire au plus 2^63 résultats différents, bien moins que les 52! arrangements d’un paquet standard.
La page d’équité prouve-t-elle que le choix de la graine est impartial ?
Non. Elle vérifie qu’une graine reproduit une position de départ. Comme elle utilise notre backend, ce n’est ni un audit indépendant ni une preuve de la façon dont la graine a été choisie.