Schach: Alle legalen Schachzüge erhalten

8

Ich mache das Spiel Schach und habe praktisch alles außer einer Sache: Ich muss es schaffen, dass es für einen Spieler unmöglich ist, ein Stück in Schach zu bringen. Ich habe Probleme damit, dieses Problem anzugehen.

Was ich gerade im Pseudocode habe, um gültige Moves zu generieren, ist: Klasse getMoveLocations (Ich habe einen Ort definiert, der eines dieser Quadrate im Schach ist): Wenn dieser Ort in Grenzen ist und das Stück an diesem Ort das eines Gegners ist UND die simulierte Bewegung nicht dazu führt, dass das Brett in Schach ist, dann füge diesen Ort zu den möglichen Orten hinzu, zu denen sich das Stück bewegen kann.

>

Das Problem dabei ist, wie ich überprüfe, ob ein Schachbrett "in Schach" ist. In meinem Code sieht es ein Schachbrett als "Check" an, indem es die Zugpositionen aller Gegner sammelt und sieht, ob sich einer dieser gegnerischen Zugpositionen mit dem Standort des Königs überschneidet.

Leider startet hier die Endlosschleife; Um die Filmstandorte aller Feinde zu sammeln, müssen die möglichen Zugpositionen jedes Feindes sicherstellen, dass seine Züge ihn nicht in Schach halten. Um sicherzustellen, dass sich keine der Positionen des Feindes in Schach befindet, muss er alle möglichen Zugpositionen der Alliierten usw. sammeln.

Ich bin ratlos, wie ich einen funktionierenden Algorithmus bekomme. Obwohl mein Code "theoretisch" logisch sinnvoll ist, kann er nicht implementiert werden. Ich interessiere mich für A) eine effizientere Art der Implementierung einer Möglichkeit, alle legalen Bewegungen zu überprüfen, oder B) eine Möglichkeit, diese Endlosschleife zu beheben

    
Mike 29.05.2013, 01:03
quelle

4 Antworten

8

Es gibt eine viel effizientere Methode, um zu bestimmen, ob eine Seite in Schach ist: Sie scannen einfach vom König nach außen und sehen, ob Sie Teile finden, die ihn angreifen können. Überprüfen Sie zum Beispiel von der Position des Königs aus, ob sich feindliche Läufer auf einer Diagonalen befinden, usw. Sie müssen überhaupt keine Bewegungsliste erstellen, sodass eine Rekursion nicht notwendig ist. Hier ist ein Pseudocode:

%Vor%

Wie Sie sehen können, gibt es einige Codewiederholungen, aber Sie können es kürzer machen. Ich habe es so gelassen, dass es einfach zu verstehen ist. Sie können legale Bewegungen erzeugen, indem Sie die pseudo-legalen Bewegungen, wie Sie sie jetzt machen, erzeugen und die, die Sie in der obigen Subroutine in Schach lassen, auslassen. Dies hat den zusätzlichen Vorteil, dass es natürlich passant ist. Hier ist ein Pseudocode:

%Vor%

Bei der Rochade müssen Sie immer noch prüfen, ob es Angriffe auf die Felder zwischen König und Turm gibt. Glücklicherweise ist dies einfach, da Sie das obige Unterprogramm auf andere Quadrate als die des Königs anwenden können.

Ich nehme an, Sie verwenden keine Bitboards oder 0x88, sondern stattdessen eine einfache Array-Darstellung. Dies macht es ein bisschen schwierig, legale Move-Generierung zu implementieren (ohne zwischenzeitliche pseudo-legale Moves), da es sehr schnell die Erstellung von Angriffskarten erfordert, um fixierte Teile zu bestimmen. Wenn Sie ehrgeizig sind, ist dies eine Möglichkeit.

Als zusätzliche Anmerkung bin ich etwas enttäuscht von den anderen Antworten hier. Und ich würde nicht einmal meine eigene Antwort jedem empfehlen, der einen guten Move-Generator schreiben möchte (es ist nur für diejenigen gedacht, die mit der Schachprogrammierung nicht vertraut sind). Dies ist ein Thema, das gründlich untersucht wurde und bekannte Lösungen hat, jedoch originelle Ideen hervorruft. Natürlich ist daran nichts falsch, aber warum das Rad neu erfinden und noch schlimmer? Sehen Sie sich bewährte Methoden zur Generierung von Bewegungen an .

    
Zong 29.05.2013 01:24
quelle
2

Ändern Sie Ihre Prozedur getMoveLocations , um ein Flag zu akzeptieren, das angibt, ob Sie sich Gedanken machen müssen, in die Prüfung zu wechseln. Zum Beispiel, wenn ein Stück gepinnt ist, kann es sich immer noch bewegen, um den gegnerischen König zu erobern. Wenn das Flag so eingestellt ist, dass es die Prüfrisiken ignoriert, bricht der Überspring-Test die Rekursion ab.

Alternativ (und äquivalent) schreiben Sie eine separate Methode zum Generieren von Zügen, die das Problem des Verschiebens in die Kontrolle ignoriert. Verwenden Sie dieses Verfahren als Teil Ihres Tests "Prüfen Sie, ob das Board in Schach ist".

    
Ted Hopp 29.05.2013 01:10
quelle
1

Ein Zug versetzt Ihre Seite in Kontrolle (und ist somit nicht erlaubt), wenn die Bewegung es einem gegnerischen Teil ermöglicht, eine angreifende Bewegung auf Ihren König auszuführen.

Beachte, dass es eine andere Sache ist, deinen Gegner in Schach zu halten - wenn du deinen Gegner in Schach bringst, ist er an der Reihe, zu reagieren. Wenn Sie sich selbst in Schach halten könnten, hätten Sie keine Gelegenheit zu antworten. Sie könnten Ihren König gefangen nehmen, und es wäre immer der richtige Schritt, egal wie schlecht eine Position ist, oder ob sie "in Schach" wären - sie haben gewonnen! Danach ist nichts mehr übrig.

Um zu sehen, ob ein Zug dich in Schach hält, schau, ob ein gegnerisches Stück einen Angriff auf deinen König ausführen könnte. Das ist es. Sie rekursiv keine zukünftigen Checks oder ähnliches - wenn sie den König JETZT angreifen können, ist er ungültig.

    
Patashu 29.05.2013 01:19
quelle
0

Es scheint, dass einige Poster Schach-Engines nicht ausreichend verstehen, also lies bitte sorgfältig und recherchiere vor dem Versuch zu argumentieren:

Anstatt zu überprüfen, ob sie sich dorthin bewegen können, prüfen Sie, ob sie dort angreifen können. Das wirst du wahrscheinlich später für deine Bewertungsfunktion sowieso wollen ...

Ich weiß nicht, ob und wie viele Engines dies tun, aber ich weiß, dass Stockfish das tut (siehe evaluate.cpp im src-Ordner), also nehme ich an, dass es bei den GOOD-Engines ziemlich normal ist. Wenn es für die Auswertung sowieso getan werden muss, können Sie es auch in der Bewegungserzeugung verwenden.

    
Andrew W 29.05.2013 02:38
quelle

Tags und Links