Dagaz: Aus dem Nebel

Bild All dies ist die Königin der Königin Mab.
Sie webt im Stall einer Mähne
Und die Haare werfen ein Gewirr nieder ...

William Shakespeare

Es war eine lange Veröffentlichung , aber es wurde viel getan. Es wurde ein Sitzungsmanager angezeigt , mit dem Sie versehentlich ausgeführte Züge zurücksetzen können. An einigen Stellen wurde Sounddesign hinzugefügt. Und doch habe ich mir eine coole Möglichkeit ausgedacht, mehrere alternative Optionen für die Erstplatzierung in einem Spiel zu finden. Und vor allem - ich bin endlich mit unvollständigen Informationen zu den Spielen gekommen.

Ich werde erklären, worum es geht. Bei den üblichen Brettspielen wie Schach oder Dame haben die Spieler zu jeder Zeit im Spiel vollständige Informationen über die Position der Figuren (ihre eigenen und die des Gegners), die Regeln für das Verschieben der Figuren, die Ziele des Spiels usw. Solche Spiele sind ziemlich gut studiert und fallen in die Kategorie " Spiele mit vollständigen Informationen ". Stellen Sie sich nun vor, dass einige dieser Informationen vor dem Player verborgen sind.


Der Nebel des Krieges ist eine großartige Illustration des Themas. Nach den Regeln des „ blinden Schachs “ können die Spieler nicht alle Teile des Feindes sehen, sondern nur diejenigen, die auf den Feldern platziert sind und mit einem Zug einer ihrer Teile erreicht werden können. Ich habe diese Regel zwei Mal ergänzt:

  1. Natürlich sieht der Spieler seine Figuren immer, aber anhand der Art und Weise, wie sie angezeigt werden - in normaler Form oder durchscheinend - kann er beurteilen, ob der Gegner sie sieht.
  2. Nur zu Dekorationszwecken habe ich „Wolken“ auf Bereiche gelegt, die derzeit unsichtbar sind.

Nachdem ich das allgemeine Prinzip beherrscht hatte, wurde ich ein wenig mitgerissen und machte eine große Anzahl von Spielen mit dem "Nebel des Krieges". Zusätzlich zu Schach selbst habe ich "dunkle" Optionen für Xiang , Changi , Shatrange , Sittuyin und viele andere Spiele. Es gibt sogar eine " Blind Guns "! Alle diese Spiele haben eines gemeinsam:

Der Computer betrügt!
Ich habe nicht einmal versucht, Änderungen an den Algorithmen der Bots für diese Spiele vorzunehmen, da ich darauf gewettet habe, dass ungleiche Bedingungen ihr im Vergleich zu Menschen extrem schwaches Spiel zumindest teilweise ausgleichen. Wie ich bereits geschrieben habe, ist die Entwicklung einer hochwertigen KI für Brettspiele eine sehr schwierige Aufgabe. Natürlich haben die Regeln Ausnahmen. Selbst bei einem sehr schwachen Spiel des Bots wird es für eine Person schwierig sein, ein ungewohntes Spiel zu spielen, das buchstäblich mit Fallen vollgestopft ist. Was können wir über seine "dunkle" Version sagen?

Im Allgemeinen ist dies jedoch kein sehr korrekter Ansatz. Ich möchte einen Bot sehen, der genau mit den Daten seines Gegners umgehen kann - man. Warum ist das wichtig? Alles ist sehr einfach - durch die Art und Weise, wie der Bot spielt, ist es manchmal sehr leicht zu erraten, ob er Zugriff auf versteckte Informationen (Peeps) hat oder nicht. Und natürlich ist es für eine Person viel interessanter, mit diesem Bot zu spielen, der nicht guckt (das Spielen mit einer anderen Person ist noch interessanter, aber das ist eine andere Geschichte).

Und hier lohnt es sich, ein Spiel zu wählen, das sich geringfügig vom Schach unterscheidet (da ich nicht bereit bin, einen "ehrlichen" Bot zu entwickeln, der "blind" Schach spielt). Es gibt viele solcher Spiele und es kann nicht gesagt werden, dass sie einfacher sind als Schach oder Dame. Sie sind einfach anders und erfordern einen individuellen Ansatz.

Zum Beispiel
Es gibt ein Kinderspiel, mit dem ich noch keinen Bot entwickelt habe. Es heißt "Dschungel" oder Dou Shou Qi . Das Ziel des Spiels ist es, feindliches Gebiet zu durchdringen. Jeder der Spieler hat eine „Höhle“ - ein zentrales Feld in der ersten Zeile. Wenn eine der feindlichen Figuren das Versteck betritt, hat er gewonnen (Sie können das Versteck nicht mit Ihren eigenen Figuren besetzen).


Die Zahlen sind nach Dienstalter geordnet. Der Elefant schlägt alle Figuren, gefolgt von: Löwe, Tiger, Leopard, Hund, Wolf, Katze und Ratte. Eine Ratte kann nur einen Elefanten und eine andere Ratte schlagen. Außerdem ist dies die einzige Figur, die sich im Wasser bewegen kann (in der Mitte des Bretts befinden sich zwei Reservoire). Ein Tiger und ein Löwe können über Wasser springen, aber nur, wenn die Ratte das Wasser nicht blockiert. Mit Ausnahme von Sprüngen bewegen sich alle Figuren auf die gleiche Weise - vertikal oder horizontal zu einem benachbarten Feld. Das Versteck ist von Fallen umgeben. Die Figur in der Falle ist für jede feindliche Figur anfällig.

Wie Sie sehen können, sind die Regeln ziemlich einfach. Was verhindert die Entwicklung eines Bots für dieses Spiel? Zuallererst die langsamen Zahlen. Wenn es Bedrohungen gibt, kann ich die Vorteile des Austauschs schätzen, aber für den größten Teil des Spiels laufen die Teile einfach über ziemlich lange Strecken nacheinander. Ich kann es mir nicht leisten, das Spiel für eine große Anzahl von Zügen vorwärts anzusehen (aufgrund von Einschränkungen bei der Dauer der Berechnung des Zuges), wodurch die Änderungen außerhalb des Betrachtungshorizonts liegen und alle Züge für mich gleichwertig werden.

Zunächst entschied ich mich für BanQi - Chinese Blind Chess. Dies ist ein sehr originelles Spiel mit versteckten Informationen, ähnlich dem "Dschungel". Für mich ist es wichtig, dass die Entwicklungen im Zusammenhang mit der Erstellung eines Bots für dieses Spiel in anderen Spielen wie Dou Shou Qi , Luzhan Qi , Stratego oder sogar (möglicherweise) Tafl verwendet werden können .


Ich erzähle dir von den Regeln. Das Spiel läuft auf der Hälfte des Bretts für "Chinesisches Schach" ( Xiang Qi ), während das ursprüngliche Layout des Bretts keine Rolle spielt. Die Stücke werden innerhalb der Zellen platziert (wie bei herkömmlichen) und nicht an den Schnittpunkten von Linien (wie beim chinesischen Schach). Zu Beginn des Spiels werden alle Teile gründlich gemischt und verdeckt auf das Brett gelegt (da die traditionellen Stücke von Syants eine Art Fässer sind und ihre Anzahl mit der Anzahl der Felder auf der Hälfte des Bretts übereinstimmt, gibt es keine Schwierigkeit).

Als nächstes wechseln die Spieler ihre Züge. Durch Ausführen eines Zuges kann der Spieler jedes der geschlossenen Teile umdrehen oder ein zuvor geöffnetes Teil seiner Farbe bewegen. Die Farben der Spieler werden vom ersten Zug an bestimmt. Wenn das erste schwarze Stück geöffnet wird, spielt der Spieler, der es geöffnet hat, schwarz. Alle Figuren im Spiel gehen den gleichen Weg (mit Ausnahme der „Kanone“ in der taiwanesischen Version, die ich später diskutieren werde) - auf einer benachbarten Zelle vertikal oder horizontal. Die Möglichkeit der Aufnahme wird durch die Reihenfolge des Dienstalters der Figuren bestimmt:

Allgemein> Berater> Elefant> Wagen> Pferd> Kanone> Soldat

Ältere Figuren schlagen jünger oder gleich, mit einer Ausnahme: Ein Soldat schlägt den General (eine Art " Stein-Papier-Schere "). Es bleibt noch ein paar Worte über das taiwanesische BanQi zu sagen:

  1. Im Gegensatz zur chinesischen Version kann in Taiwan BanQi ein General einen Soldaten nicht schlagen.
  2. Die Kanone bewegt sich gemäß den XiangQi- Regeln, dh zu einer beliebigen Anzahl von Feldern, die mit niedriger Geschwindigkeit orthogonal sind (wie ein Streitwagen), oder trifft eine feindliche Figur mit einem Sprung durch den "Wagen", wenn sie eine Angriffsbewegung ausführt.

Es gibt auch eine Hongkong-Version, die sich jedoch praktisch nicht von den Chinesen unterscheidet, außer dass die Reihenfolge des Dienstalters der Zahlen geändert wurde. Ich beschloss, mich auf die taiwanesische Version der Regeln als die taktisch interessanteste zu konzentrieren.

Worauf sollte ich bei der Entwicklung eines Bots achten?
Erstens sieht das Spiel sehr einfach aus, ist es aber nicht. Selbst wenn Sie die mit den taiwanesischen Waffen verbundenen Nuancen nicht berücksichtigen, sind die Kosten für die Zahlen nicht intuitiv. Obwohl der "Berater" weniger Figuren schlagen kann als der "General", ist er der Hauptprotagonist im Spiel. Erstens hat der Spieler zwei Berater. Außerdem ist jedem Berater nur ein feindlicher General überlegen, während der General von bis zu fünf Soldaten angegriffen werden kann! Aus dem gleichen Grund sind die Kosten eines Soldaten in einem Spiel höher als die Kosten eines Generals. Am Ende kann er die stärkste Figur schlagen! Die zweite wichtige Überlegung legt eines der "Canterbury" -Puzzles von Henry Dudeney nahe.


Dies ist eher eine Scherzaufgabe als ein komplettes Rätsel. Alle Figuren können vertikal oder horizontal zu einem benachbarten Feld gehen. Weiß bewegt sich zuerst, während Weiß und Schwarz immer zwei Züge machen (in verschiedenen Teilen)! Unter diesen Bedingungen kann der linke Trottel niemals den linken Esel fangen, und der rechte Trottel kann niemals den rechten fangen (Sie können es selbst überprüfen). Natürlich kann der rechte Narr den linken Esel problemlos fangen. Es geht nur um Parität!

Dieses Problem gab mir einige Gedanken. Erstens besteht die Aufgabe des Bots in Spielen wie BanQi oder DouShouQi darin, zunächst den kürzesten Weg zu finden. Aus jedem der aktiven Teile (dem eigenen oder dem Gegner) müssen Bewegungsketten zu allen möglichen Zielen aufgebaut werden (einschließlich der eigenen Teile, um den möglichen Austausch zu berechnen). Danach müssen die Ketten ausgewertet werden und die folgenden Optionen sind hier möglich.

  1. Die angreifende Figur schlägt die angegriffene - eine profitable (Bonus-) Kette, die anhand der Kosten der angegriffenen Figur (abzüglich der Kosten der angreifenden Figur, wenn diese geschützt ist) unter Berücksichtigung der Länge der Kette geschätzt wird.
  2. Die angreifende Figur schlägt die angegriffene - keine profitable (Straf-) Kette, geschätzt durch den Wert der angreifenden Figur.
  3. Die Figuren schlagen sich gegenseitig (zum Beispiel sind sie gleich) - hier hängt alles von der Parität ab, die ungeraden Ketten sind vorteilhaft und die geraden sollten als Strafketten betrachtet werden (wenn es keine anderen Figuren auf dem Spielfeld gäbe, würde die Parität das Ergebnis des Spiels vollständig bestimmen).

Natürlich ist nicht alles so einfach. Zumindest sollten Sie sich an den spezifischen Verlauf der Kanonen in Taiwans BanQi erinnern (für den „Dschungel“ gibt es noch mehr Sonderfälle), aber hier können Sie beginnen. Mit einem vollständigen Satz ausgewerteter Ketten können Sie Bewegungen bewerten. Die Kosten für den Umzug sollten sich aus den Kosten der Ketten (sowohl Bonus als auch Gratis) zusammensetzen, deren Länge sich verringert.

Zunächst ist es wichtig zu verstehen, dass es unwahrscheinlich ist, dass hier Minimax- Algorithmen effektiv eingesetzt werden können. Bewegungen, die zuvor verborgene Teile aufdecken, ändern die Positionsschätzung zu radikal. Ohne Informationen über versteckte Teile ist es fast unmöglich, eine Position zu sehen, die viele Schritte voraus ist. Aber jede Wolke hat einen Silberstreifen, aber wir können viel komplexere (rechnerische) Heuristiken verwenden, um die Bewegungen selbst zu bewerten!

Ich habe bereits einen Bot, der Bewegungen anhand ihrer Heuristik bewertet (für ein lustiges Spiel erforderlich). Dies ist ein sehr einfacher Algorithmus. Alle Züge werden in absteigender Reihenfolge nach Heuristik sortiert (Züge mit einem negativen heuristischen Wert werden im Allgemeinen verworfen), wonach sie der Reihe nach gescannt werden. Wenn der nächste Zug zu einer Position führt, von der aus keine feindliche Reaktion zu einem sofortigen Sieg führt, hält der Bot dies für die beste. Mit diesem Algorithmus können Sie sich nicht um die Positionsschätzung kümmern, sondern müssen über Heuristiken schwitzen.

Zunächst bauen wir Ketten
var getChains = function(design, board) { var player = board.getValue(board.player); if (player === null) return []; if (_.isUndefined(board.chains)) { board.chains = []; var pieces = getGoals(design, board); var targets = getTargets(design, board, pieces); _.each(pieces.positions, function(pos) { var goals = pieces; var f = true; var piece = board.getPiece(pos); if (piece === null) return; if (!chinese && (piece.type == 12)) { goals = targets; f = false; } var group = [ pos ]; var level = []; level[pos] = 0; for (var i = 0; i < group.length; i++) { if (_.indexOf(goals.positions, group[i]) >= 0) { //  ... } if ((i > 0) && (board.getPiece(group[i]) !== null)) continue; _.each(design.allDirections(), function(dir) { p = design.navigate(board.player, group[i], dir); while (p !== null) { if (_.indexOf(group, p) >= 0) break; group.push(p); level[p] = level[ group[i] ] + 1; if (f || (board.getPiece(p) !== null)) break; p = design.navigate(board.player, p, dir); } }); } }); } return board.chains; } 

Natürlich speichere ich alle Zwischendaten im Spielzustand zwischen, um sie nicht mehrmals zu lesen. Zusätzlich wird hier ein Trick verwendet, der bei der Berechnung verbundener Bereiche sehr nützlich ist. Ich iteriere über das Gruppenarray und füge bei Bedarf zusätzliche Elemente in die Schleife ein. Alle Schwierigkeiten sind mit Waffen verbunden. Für sie sind die Ziele der Ketten nicht die Figuren selbst, sondern die Felder, von denen aus letztere angegriffen werden können.

Die Ketten werden genau wie gesagt ausgewertet
 var getChainPrice = function(design, board, attacker, attacking, len) { var player = board.getValue(board.player); if ((player === null) || (attacker == null) || (attacking === null)) return 0; if (attacker.player == attacking.player) return 0; var isAttacking = isAttacker(design, attacker.type, attacking.type); var isAttacked = isAttacker(design, attacking.type, attacker.type); if (!chinese && (attacker.type == 12)) { isAttacking = true; isAttacked = (attacking.type == attacker.type) && (len == 1); } var price = 0; var f = (len % 2 == 0); if (attacker.player != player) f = !f; if (isAttacking) { if (isAttacked) { price = f ? (len - design.price[attacker.type]) : (design.price[attacking.type] - len); } else { price = design.price[attacking.type] - len; if (f) price = (price / 2) | 0; } } else { if (isAttacked) { price = len - design.price[attacker.type]; } } return price; } 

... abhängig von der Länge und Parität der Kette sowie unter Berücksichtigung der Kosten der angreifenden und angegriffenen Figuren. Aber das ist nur die halbe Miete! Es ist notwendig, jede der möglichen Bewegungen unter Verwendung der konstruierten Ketten zu bewerten. Ich führe eine weitere Zwischenstruktur ein - möchte die verfügbaren Daten aggregieren. Die Bewertung des Kurses besteht aus der Bewertung von Wünschen, die erfüllt werden:

So etwas in der Art
 var addWish = function(board, comment, price, src, dst) { if (_.isUndefined(board.wish[src])) { board.wish[src] = []; } if (_.isUndefined(dst)) dst = src; if (_.isUndefined(board.wish[src][dst])) { board.wish[src][dst] = price; } else { board.wish[src][dst] += price; } } var getWish = function(design, board) { if (_.isUndefined(board.wish)) { ... } return board.wish; } Dagaz.AI.heuristic = function(ai, design, board, move) { var wish = getWish(design, board); if (move.isSimpleMove() && !_.isUndefined(wish[ move.actions[0][0][0] ]) && !_.isUndefined(wish[ move.actions[0][0][0] ][ move.actions[0][1][0] ])) { return wish[ move.actions[0][0][0] ][ move.actions[0][1][0] ]; } return 0; } 

Was die getWish- Funktion selbst betrifft , beginnt hier die Magie (und dies ist der Ort, an dem ich höchstwahrscheinlich mehr als einmal gepflügt habe). Zunächst teile ich die Bewertung von Zügen anhand offener Informationen und die Einführung neuer Teile in das Spiel. Das ist nicht ganz richtig, aber bisher weiß ich einfach nicht, wie ich so unterschiedliche Meinungen in Einklang bringen kann. Wenn aufgrund offener Informationen keine Wünsche gebildet wurden, versucht der Bot, neue Figuren zu öffnen (hier gibt es auch einige Tricks).

  1. Wenn eine feindliche Kanone offen und von geschlossenen Figuren umgeben ist, ist es sinnvoll, eine der Figuren daneben zu öffnen, da es wahrscheinlich ist, dass sie die Waffe angreifen kann und die Waffe sie auf keinen Fall schlagen kann.
  2. Wenn eine andere Figur als eine Kanone geöffnet ist, können Sie versuchen, eine Figur zu öffnen, die sich durch den "Wagen" von dort befindet, da die Möglichkeit besteht, dass es sich um eine Kanone handelt.
  3. Wenn sich von der feindlichen Seite eine Angriffskette befindet, kann eines der Teile neben der Kette geöffnet werden, um den Angriff abzufangen.
  4. Wenn Sie die Figur nicht schützen können, können Sie die Figur daneben öffnen und versuchen, die Situation auf einen Austausch zu reduzieren.

Natürlich ist es nützlich, die Wahrscheinlichkeit des Öffnens einer bestimmten Figur zu bewerten.
 var getShadow = function(design, board) { var player = board.getValue(board.player); if (player === null) return []; if (_.isUndefined(board.shadow)) { board.shadow = []; _.each(design.allPositions(), function(pos) { var piece = board.getPiece(pos); if ((piece !== null) && (piece.type < 7)) { var value = piece.type + 7; if (piece.player != player) { value = -value; } board.shadow.push(value); } }); } return board.shadow; } var isFriend = function(design, x) { return x > 0; } var isPiece = function(design, x, y) { return x == y; } var isAttacker = function(design, x, enemy) { if (x < 0) return false; if ((x == 13) && (enemy == 7)) return true; if (!chinese && (x == 7) && (enemy == 13)) return false; if (!chinese && (x == 12)) return false; return x <= enemy; } var isDefender = function(design, x, enemy, friend) { if (!isAttacker(design, x, enemy)) return false; return design.price[friend] <= design.price[enemy]; } var estimate = function(design, board, p, y, z) { var shadow = getShadow(design, board); if (shadow.length == 0) return 0; var r = 0; _.each(shadow, function(x) { if (p(design, x, y, z)) r++; }); return (100 * r) / shadow.length; } 

Der Spieler kann die Wahrscheinlichkeiten bewerten, indem er die Zahlen verfolgt, die das Spiel abgebrochen haben. Im Prinzip kann der Bot dasselbe tun, aber es gibt einen einfacheren Weg - die noch nicht offenen Zahlen in großen Mengen zu betrachten und die Wahrscheinlichkeit des Öffnens der gewünschten anhand der gesammelten Informationen zu bewerten. Darüber hinaus ist der Erfolg des ausgewählten Zuges nicht garantiert, aber wenn die Wahrscheinlichkeit eines günstigen Ergebnisses gering ist, wird der Zug überhaupt nicht ausgewählt.

Im Prinzip hat sich der Ansatz ausgezahlt, aber es gibt noch viel zu tun.
Während Defensivbewegungen nicht sehr gut sind. Einige Figuren treffen tapfer auf den stärkeren Feind, anstatt vor ihm wegzulaufen (obwohl es in ihrem Fall in der Regel schon nutzlos ist, wegzulaufen). Es gibt auch Schwierigkeiten, die Aktionen verschiedener Figuren zu koordinieren (dies kann nützlich sein, um die Überreste feindlicher Figuren zu „treiben“). Der Ansatz selbst sieht sehr vielversprechend aus, aber die Heuristik muss noch berücksichtigt werden.

Heuristiken, die auf „Ketten“ von Zügen basieren, können nicht nur in BanQi, sondern auch in vielen anderen Spielen nützlich sein, wobei „langsame“ Teile überwiegen (wenn nicht als definierendes Kriterium, dann zumindest für eine vorläufige Bewertung der Qualität von Zügen in komplexeren Algorithmen) am wenigsten). Dieser Ansatz ist besonders bei Spielen gefragt, bei denen die Verwendung von Minimax-Algorithmen schwierig oder sogar unmöglich ist (wie zum Beispiel Yonin Shogi ).


Natürlich werde ich weiterhin an Spielen mit unvollständigen Informationen arbeiten. Das Bild zeigt das philippinische " Spiel der Generäle ", noch nicht fertig. Dies ist das einfachste Spiel einer großen Familie, einschließlich Spiele wie LuzhanQi und Stratego . Und natürlich erwarte ich immer noch einen funktionierenden Bot für den " Dschungel "!

Und für diejenigen, die mich noch lesen, kann ich ein weiteres lustiges Puzzlespiel mit versteckten Informationen anbieten:


Ich habe es in meiner Kindheit auf einem programmierbaren Taschenrechner namens Fox Hunt gespielt. Acht Füchse sind zufällig auf dem Feld versteckt, die mit der „Poke-Methode“ gefunden werden müssen. Wenn Sie einen leeren Bereich auswählen, wird die Gesamtzahl der Füchse in alle acht Richtungen angezeigt. Es ist unmöglich zu verlieren, aber Sie können um die minimale Anzahl von Klicks konkurrieren. Und wenn Sie mit Kopfhörern spielen, verringern Sie den Ton. Vielleicht habe ich es mit Soundeffekten übertrieben.

Source: https://habr.com/ru/post/de422427/


All Articles