les moteurs continuent de jouer au même jeu

8

Je viens de terminer l'écriture de la personnalisation d'un moteur d'échecs en ajoutant essentiellement un bitboard au moteur tscp disponible gratuitement. Maintenant, je le teste dans Winboard et je remarque que souvent les deux machines joueront le même jeu plusieurs fois dans un match. J'aimerais ajouter une certaine variété aux jeux en lui faisant au moins choisir des mouvements égaux au hasard. J'utilise simplement la recherche alpha-bêta avec un ordre de déplacement simple. Je pense simplement à ajouter un petit nombre aléatoire aux nœuds feuilles pour rompre les liens, mais je n'aime pas vraiment cette solution car certains des petits bonus que la fonction d'évaluation utilise sont de 3 à 5 centipawns. Je n'ai donc pas assez de "place" pour que le nombre aléatoire brise les liens.

mon autre pensée était d'avoir le moteur choisir aléatoirement qui se déplacerait pour garder quand il trouverait une évaluation == alpha. Je n'aime pas vraiment cela parce que je soupçonne que cela favorise les mouvements commandés en dernier dans la recherche.

La question est de savoir comment puis-je choisir au hasard parmi les nœuds foliaires à score égal? et aussi uniformément?

nak3c
la source

Réponses:

7

Remarque:

C'est une bonne idée que votre moteur soit déterministe. Il n'y a aucune raison de sélectionner un mouvement au hasard. Vous ne le feriez que pour réduire la puissance de votre moteur. Si vous rendez votre moteur non déterministe, il vous sera très difficile de déboguer et de reproduire un bogue. Ma recommandation est de ne pas le faire.

Vous ne devez pas modifier votre moteur. Vous pouvez utiliser un livre d'ouverture et choisir une ligne au hasard. De nombreuses interfaces graphiques d'échecs peuvent le faire, par exemple, le logiciel CuteChess . L'interface graphique de l'arène peut également le faire.

Mais si vous insistez:

Jetons un coup d'œil au code source de Stockfish .

 Move Skill::pick_best(size_t multiPV) {

    const RootMoves& rootMoves = Threads.main()->rootMoves;
    static PRNG rng(now()); // PRNG sequence should be non-deterministic

    // RootMoves are already sorted by score in descending order
    Value topScore = rootMoves[0].score;
    int delta = std::min(topScore - rootMoves[multiPV - 1].score, PawnValueMg);
    int weakness = 120 - 2 * level;
    int maxScore = -VALUE_INFINITE;

    // Choose best move. For each move score we add two terms, both dependent on
    // weakness. One is deterministic and bigger for weaker levels, and one is
    // random. Then we choose the move with the resulting highest score.
    for (size_t i = 0; i < multiPV; ++i)
    {
        // This is our magic formula
        int push = (  weakness * int(topScore - rootMoves[i].score)
                    + delta * (rng.rand<unsigned>() % weakness)) / 128;

        if (rootMoves[i].score + push > maxScore)
        {
            maxScore = rootMoves[i].score + push;
            best = rootMoves[i].pv[0];
        }
    }

    return best;   }
  • Stockfish démarre le multi-PV (non pris en charge dans TSCP, vous devrez donc le coder vous-même!)
  • Calculez un nombre aléatoire et ajoutez-le au score de chaque PV
  • Comparez chaque PV pondéré et choisissez le meilleur

Vous pouvez trouver les liens suivants utiles:

Recommandation: ne le faites que si vous souhaitez affaiblir votre moteur.

SmallChess
la source
l'approche du livre a très bien fonctionné, merci! J'ai posté une question de suivi concernant les tableaux de transposition et les tableaux triangulaires.
nak3c