10
votes

Déterminer si deux positions d'échecs sont égales

Je débrouge actuellement ma table de transposition pour un moteur de variante d'échecs où des pièces peuvent être placées (à l'origine non pas sur la planche) forte>. J'ai besoin de savoir combien de fois je frappe des collisions clés. Je sauve la liste de la pièce dans chaque index de table, ainsi que les données de hachage habituelles. Ma solution simple pour déterminer si deux positions sont égales échoue sur les transpositions car je comparais de manière linéairement les deux listes de pièces.

Veuillez ne pas suggérer que je devrais stocker par carte centrée au lieu de la pièce centrée sur la carte / fort>. Je dois stocker la liste des pièces en raison de la nature unique des pièces plafonnées et capturées. Les pièces de ces états sont comme si elles occupent une localisation de chevauchement et de position. S'il vous plaît regarder la description de la manière dont les pièces sont stockées forts>. p> xxx pré>

une transposition se passe forte> lorsque des pièces sont déplacées dans un autre ordre, mais le résultat final est la même position de la carte. Par exemple, les positions suivantes sont égales par correspondance: p> xxx pré>

Ce qui suit est un algorithme général non optimisé fort>; et la boucle intérieure est similaire à une autre Problème général , mais avec la retenue supplémentaire que les valeurs de 0 à 63 ne se produiront qu'une fois (c.-à-d. . Seulement une pièce par carré). P>

bool operator==(const Position &b)
{
    for (int i = 0; i < 32; i++)
        if (piece[i] != b.piece[i])
            return false;
    return true;
}


0 commentaires

7 Réponses :


6
votes

Pourquoi ne pas conserver une chaîne de 64 octets dans votre base de données correspondant à la disposition de l'échiquier? Chaque type de pièce, y compris «Pas de pièce», représente une lettre (différentes capsules pour les deux couleurs, c'est-à-dire ABC pour Black, ABC pour blanc). La comparaison de la carte se résume à une comparaison de chaîne simple.

En général, la comparaison de la perspective de l'échiquier, au lieu du point de vue de la pièce, se débarrassera de votre problème de transposition!


5 commentaires

Cela fonctionnerait pour les échecs traditionnels. Mais dans la variante des échecs que j'écris, pièces peut également être placable . Ce qui signifie que la solution de perspective de votre conseil ne fonctionnerait pas comme des pièces à placer ou qui étaient mortes ne serait pas répertoriée dans la chaîne de 64 octets. Le tableau ne contient pas toutes les données et mon problème est que la liste des pièces est plus difficile à détecter les transpositions .


Hm, dommage. Il y aurait toujours un moyen de contourner cela en ajoutant les 64 caractères de la Commission par une liste ordonnée de toutes les pièces mortes (c'est-à-dire AABAC). Mais peut-être que ça commence à devenir peu pratique? C'est un problème classique de Time de stockage VS Tradeoff.


Justin. Développez simplement la carte stockée pour permettre une zone de pièces «non placées» à l'extérieur du tableau.


@Esben: Cela ne fonctionnerait pas, sauf trier comme je l'ai mentionné, car cette zone non passée ressemble davantage à une piscine sans position.


Jochem. Définissez ensuite certains commandes standard. Ou juste les trier



1
votes

Dans la perspective de la pièce, vous pouvez le faire:

for each color:
    for each piece type:
        start new list for board A
        for each piece of this piece type on board A
            add piece position to the list
        start new list for board B
        for each piece of this piece type on board B
            add piece position to the list
        order both lists and compare them


4 commentaires

Encore une fois, cela ne fonctionnerait pas pour ma variante. Les morceaux sur la planche sont uniques, mais les pièces placables / capturées ne sont pas. Par exemple, le début du jeu commence avec toutes les valeurs "-2" (placement). Vous perdez les informations de type pièce des groupements d'index. Sans que la perte de 2 pions serait la même que la perte de 2 tevokes. De plus, l'idée de somme ne fonctionnera pas Voir ce .


L'idée de somme n'est pas d'exclure rapidement certaines commissions (comme on pouvait s'y attendre serait la case la plus courante). Parce que pour être égal, la somme devrait au moins être égale. Je pense que cela fonctionnerait, placable n'est qu'un autre index. Si vous avez un pion sur B2, la liste ordonnée rendra toujours -2, -2, -2, -2, -2, -2, -2, x (x étant l'indice B2). Dans votre question, vous avez dit -1 était placé mais d'accord.


Oui, les positions égales ont des sommes égales, mais l'inverse n'est pas vrai. De plus, ma solution simple peut déjà détecter des positions égales dans lesquelles les pièces ne sont pas transposées. Mais une transposition ne peut être détectée, et c'est ce dont j'ai besoin.


Donc, essentiellement une copie par morceaux, trier et comparer. Cela fonctionnerait, mais je cherche une solution sans copie / tri. Le coût unique pour cela n'est rien, mais plus de 100 000 personnes s'ajoute.



1
votes

et une troisième option (j'espère vraiment que poster 3 réponses à une question est correcte, Stackoverflow-wise;)):

Gardez toujours vos morceaux du même type dans l'ordre d'index, c'est-à-dire que le premier pion dans la liste doit toujours avoir l'index le plus bas. Si un mouvement a lieu qui enfreint cela, passez simplement les positions de pions dans la liste. L'utilisation ne verra pas la différence, un pion est un pion.

Maintenant, lorsque vous comparez des positions, vous pouvez être sûr qu'il n'y a pas de problème de transposition et vous pouvez simplement utiliser votre boucle proposée.


4 commentaires

Je ne pense pas que cela fonctionnerait car ma fonction de recherche est récursive et ne serait probablement pas en mesure de défaire le déménagement si je continue à échanger les morceaux. L'objet de déplacement utilise l'index pour faire / éteindre les mouvements. Vous ne faites que d'ajouter plus de frais généraux.


C'est une très bonne approche de la question comme demandé: plus généralement, lors de la comparaison des objets (tels que des positions du conseil) où il y a plus d'une représentation valide pour le même objet (en raison de la transposition, etc.), une stratégie puissante consiste à essayer de trouver Un représentant "canonique" - c'est-à-dire pour chaque position de la carte qui peut avoir de nombreuses représentations, en choisir un comme "droit", puis en comparant deux positions (ou à l'avance), transformez-les dans ce "droit" ("canonique") Représentation - De cette façon, s'ils ne comparent pas égaux, vous pouvez être certains sont des positions différentes.


BTW La récursion ne devrait pas être un problème (il suffit d'avoir une fonction qui déplace une pièce et met à jour la représentation, puis appelez-la une fois sur le chemin de déplacement d'une pièce, et de nouveau sur le point de passer pour le déplacer). Et dans la grande majorité des cas, la mise à jour est triviale - au plus échanger deux entrées - de sorte que les cas «durs» doivent être suffisamment rares pour en faire une victoire globale. Mais si vous êtes prêt à changer de représentation de votre conseil d'administration, la solution d'Amoss est meilleure et Mathieu PAGÉ explique comment utiliser le hachage pour la rendre encore plus efficace ...


@Justin: Alors, essayez de le faire fonctionner. Par exemple, chaque fois que vous construisez une nouvelle position (évoluant ou en arrière), vous pouvez vous assurer qu'il est en ordre canonique. Et, sérieusement, arrêtez de pleurer - vous consacrez plus de texte pour vous plaindre de la manière dont les idées de tout le monde ne pouvaient pas fonctionner pour vous que vous ne devez poser la question.



1
votes

Compte tenu de votre choix de représentation de l'état du jeu, vous devez trier les indices des pions noirs, les indices de pions blancs, etc., d'une manière ou d'une autre. Si vous ne le faites pas au cours de la création d'un nouvel état de jeu, vous devrez le faire à la comparaison. Parce que vous n'avez besoin que de trier un maximum de 8 éléments, cela peut être fait assez vite.

Il y a quelques alternatives pour représenter vos états de jeu:

  • représente chaque type de pièce comme champ de bits. Les 64 premiers bits signifient qu'il existe un élément de ce type sur ce tableau coordonnant; Ensuite, il y a n bits de "placement" et n bits de "morts", qui doivent être remplis d'un côté ( n est le nombre de morceaux de ce type).

    ou

    • Donnez à chaque type de pièce un identifiant unique, par ex. Les pions blancs pourraient être 0x01. Un état de jeu consiste en une matrice de 64 pièces (la carte) et de deux listes ordonnées de pièces "placables" et "mortes". Le maintien de l'ordre de ces listes peut être effectué de manière assez efficace lors de l'insertion et de la suppression.

      Ces deux alternatives n'auraient pas de problème de transposition.

      Quoi qu'il en soit, j'ai l'impression que vous tremblez avec des micro-optimisations lorsque vous devriez d'abord le faire fonctionner.


0 commentaires

4
votes

"Ne suggère pas que je devrais stocker par carte centrale au lieu de la pièce centrée sur la pièce".

Vous êtes si concentré sur ne pas le faire, que vous manquiez la solution évidente. comparer spécifique au tableau. Pour comparer deux listes de position l1 et l2 , placez tous les éléments de l1 sur une carte (temporaire). Ensuite, pour chaque élément de L2 , vérifiez s'il est présent sur le tableau temporaire. Si un élément de L2 n'est pas présent sur la planche (et donc dans l1 ), renvoie inégal.

Si après avoir retiré tous les éléments de L2 , il reste des pièces à gauche sur la carte, puis l1 doit avoir eu des éléments non présents dans l2 et les listes sont égales. l1 et l2 ne sont égaux que lorsque la carte temporaire est vide par la suite.

Une optimisation consiste à vérifier les longueurs de l1 et l2 premier. Non seulement cela va-t-il prendre de nombreuses divergences rapidement, il élimine également la nécessité de supprimer les elemetns de L2 de la BAORD et du chèque "vide vide" à la fin. Cela n'est nécessaire que pour attraper le cas où l1 est un véritable superset de l2 . Si l1 et l2 ont la même taille, et l2 est un sous-ensemble de l1 , puis l1 et l2 doit être égal.


1 commentaires

Cette réponse ne résout pas complètement le problème. (Je pense que cela peut être étendu à le faire sans trop de problèmes, mais à l'heure actuelle, il ne tient pas compte de la différence entre les pièces qui sont "placables" par rapport aux pièces "mortes" ...)



8
votes

Il y a beaucoup de recherches effectuées sur les échecs informatiques et la manière de créer un hasch unique pour une position est un problème bien connu avec une solution universelle utilisée par pratiquement tous les moteurs d'échecs.

Ce que vous devez faire est d'utiliser hachage zobriste pour créer un unique (pas vraiment unique, mais nous verrons plus tard pourquoi ce n'est pas un problème en pratique) clé pour chaque position différente. algorithme appliqué aux échecs est expliqué ici . P>

lorsque vous démarrez votre programme Vous créez ce que nous appelons Zobrist Keys. Ce sont des entiers aléatoires de 64 bits pour chaque pièce / paires carrées. Dans C, vous auriez une matrice de 2 dimensions comme ceci: p>

// remove one pawn from the off-the-board
boardHash = boardHash ^ offTheBoardZobKeys[WHITE_PAWN][numberOfWhitePawsOffTheBoard];

// Put a pawn on a2
boardHash = boardHash ^ zobKeys[WHITE_PAWN][A2];


2 commentaires

J'utilise déjà une variante de hachage de Zobrist. Mais j'utilise Ajout / Sub à cause des pièces placables.


Je ne sais pas comment vous utilisez ajout / sous ... à la place de Xor? Mais vous avez simplement besoin de trouver un moyen de retrouver le statut des pièces «hors du conseil». Cela peut être fait avec l'algorithme habituel, j'ai expliqué une façon de le faire dans mon édition.



3
votes

Votre principale objection à stocker les états sage est que vous avez un sac de pièces moins de position. Pourquoi ne pas maintenir un tableau + un vecteur de morceaux? Cela répondrait à vos besoins et il présente l'avantage de représenter une représentation canonique pour vos États. Par conséquent, vous n'avez pas besoin de tri et utilisez cette représentation en interne ou convertiez-la lorsque vous devez comparer:

Piece-type in A1
... 63 more squares
Number of white pawns off-board
Number of black pawns off-board
... other piece types


0 commentaires