Motoren spielen immer das gleiche Spiel

8

Ich habe gerade das Anpassen einer Schach-Engine abgeschlossen, indem ich der frei verfügbaren tscp-Engine im Grunde ein Bitboard hinzugefügt habe. Jetzt teste ich es in Winboard und stelle fest, dass die beiden Maschinen oft dasselbe Spiel mehrmals in einem Match spielen. Ich möchte den Spielen etwas Abwechslung verleihen, indem ich sie zumindest zufällig gleiche Züge auswählen lasse. Ich verwende nur die Alpha-Beta-Suche mit einfacher Zugreihenfolge. Ich denke darüber nach, nur eine kleine Zufallszahl zu den Blattknoten hinzuzufügen, um Bindungen zu lösen, aber ich mag diese Lösung nicht wirklich, weil einige der kleineren Boni, die die Bewertungsfunktion verwendet, 3-5 Centipawns sind. Ich habe also nicht genug "Platz" für Zufallszahlen, um die Krawatten zu lösen.

Mein anderer Gedanke war, dass der Motor zufällig auswählt, welche Bewegung beibehalten werden soll, wenn eine Bewertung == alpha gefunden wird. Ich mag das nicht wirklich, weil ich vermute, dass es Bewegungen bevorzugt, die zuletzt bei der Suche bestellt wurden.

Die Frage ist, wie ich zufällig aus den Blattknoten mit gleicher Punktzahl auswählen kann. und auch gleichmäßig?

nak3c
quelle

Antworten:

7

Hinweis:

Es ist eine gute Idee, wenn Ihr Motor deterministisch ist. Es gibt keinen Grund, einen Zug zufällig auszuwählen. Sie würden es nur tun, um Ihre Motorstärke zu verringern. Wenn Sie Ihre Engine nicht deterministisch machen, fällt es Ihnen sehr schwer, einen Fehler zu debuggen und zu reproduzieren. Meine Empfehlung ist, es nicht zu tun.

Sie sollten Ihren Motor nicht modifizieren. Möglicherweise möchten Sie ein Eröffnungsbuch verwenden und zufällig eine Zeile auswählen. Viele Schach-GUI können das, zum Beispiel die CuteChess- Software. Arena GUI kann das auch.

Aber wenn Sie darauf bestehen:

Werfen wir einen Blick auf den Stockfish-Quellcode .

 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 startet Multi-PV (wird in TSCP nicht unterstützt, Sie müssen es also selbst codieren!)
  • Berechnen Sie eine Zufallszahl und addieren Sie sie zur Punktzahl für jede PV
  • Vergleichen Sie jede gewichtete PV und wählen Sie die beste aus

Die folgenden Links sind möglicherweise hilfreich:

Empfehlung: Tun Sie dies nur, wenn Sie Ihren Motor schwächen möchten.

SmallChess
quelle
Der Buchansatz hat super funktioniert, danke! Ich habe eine Folgefrage zu Transpositionstabellen und dreieckigen Arrays gestellt.
Nak3c