los motores siguen jugando el mismo juego

8

Acabo de terminar de personalizar un motor de ajedrez básicamente agregando un bitboard al motor tscp disponible de forma gratuita. Ahora lo estoy probando en winboard y noto que a menudo las dos máquinas jugarán el mismo juego varias veces en un partido. Me gustaría agregar algo de variedad a los juegos al menos hacer que elija movimientos iguales al azar. Solo estoy usando la búsqueda alfa-beta con un simple orden de movimiento. Estoy pensando en agregar un pequeño número aleatorio a los nodos de la hoja para romper los lazos, pero realmente no me gusta esta solución porque algunos de los bonos más pequeños que utiliza la función de evaluación son 3-5 centipawns. Así que no tengo suficiente "espacio" para que un número aleatorio rompa los lazos.

mi otro pensamiento era hacer que el motor escogiera al azar qué movimiento mantener cuando encontró una evaluación == alfa. Realmente no me gusta esto porque sospecho que favorece los movimientos ordenados en último lugar en la búsqueda.

La pregunta es ¿cómo puedo elegir al azar entre los nodos de hoja de puntuación iguales? y también de manera uniforme?

nak3c
fuente

Respuestas:

7

Nota:

Es una buena idea que su motor sea determinista. No hay razón para seleccionar un movimiento al azar. Solo lo haría para reducir la potencia de su motor. Si hace que su motor no sea determinista, le resultará muy difícil depurar y reproducir un error. Mi recomendación es no hacerlo.

No deberías modificar tu motor. Es posible que desee utilizar un libro de apertura y elegir una línea al azar. Muchas GUI de ajedrez pueden hacer eso, por ejemplo, el software CuteChess . Arena GUI también puede hacer eso.

Pero si insistes:

Echemos un vistazo al código fuente 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 inicia múltiples PV (no es compatible con TSCP, por lo que deberá codificarlo usted mismo).
  • Calcule un número aleatorio y agréguelo a la puntuación para cada PV
  • Compare cada PV ponderado y elija el mejor

Puede encontrar útiles los siguientes enlaces:

Recomendación: no lo hagas a menos que quieras debilitar tu motor.

SmallChess
fuente
el enfoque del libro funcionó muy bien, gracias! He publicado una pregunta de seguimiento sobre tablas de transposición y matrices triangulares.
nak3c