Bester Ansatz zum Schreiben einer Schachengine? [geschlossen]


15

Ich bin ein Schachenthusiast und ein Programmierer. Ich habe vor kurzem beschlossen, mit meinen Schach- und Programmierkenntnissen eine Schachengine zu bauen. Also hier ist meine Frage:

Welche Sprache (ich bin mit Java, C ++ und Python vertraut) und Methodik sollte ich beim Schreiben einer Schachengine anpassen?

Eine kleine Anleitung wäre sehr dankbar.

Bearbeiten:

Also habe ich beschlossen, es in JavaScript zu machen. Ich lade diese Schach-Benutzeroberfläche von Github herunter und jetzt bin ich fertig! Mein erster Schritt wäre, legale Schritte dafür zu schreiben. Kann mich jemand in die richtige Richtung weisen? (Ich bin neu in jQuery, habe aber viel Programmiererfahrung).

PS: Ich versuche nicht, einen sehr effizienten Motor zu bauen (ich weiß, wie schwierig er ist), ich möchte mich nur mit dem Prozess vertraut machen und dabei einige neue Techniken erlernen.


5
Jede gängige Sprache und Methodik würde diesbezüglich nichts Besonderes an einer Schachengine bewirken.
Yannis

3
Ich würde genauer auf Ziele eingehen. Wenn Sie es nur auf eine Reihe roter Regeln reduzieren wollen, ist es eine große Aufgabe, aber jeder Programmierer kann das auf brachiale Weise durchgehen. Wenn Sie sich mit Themen wie Mustererkennung oder Abwägen von Risiko und Belohnung beschäftigen möchten, können die Antworten auf diese Fragen saftig werden.
Erik Reppen

Haben Sie die pädagogische Sektion im Chess Engine Wiki durchgesehen? Diese scheinen speziell dazu gedacht zu sein, Schachprogrammierung zu lehren und sind alle Open Source. Auch wenn Sie nicht verwenden die eigentlichen Quellcode der Dokumentation wird in der Regel erklären , was hinter der Entwicklung ist: en.wikipedia.org/wiki/Chess_engine#Categorizations
user60812

1
Der wirklich schwierige Teil ist, wie man eine bestimmte Position bewertet, da man sehen muss, ob Position A besser ist als Position B, um zu wählen.

1
Es ist überhaupt nicht klar, was Sie wissen wollen. Haben Sie sich für eine Darstellung einer Position entschieden? Wenn ja, besteht der nächste Schritt darin, einen Bewegungsgenerator zu schreiben und zu testen. Ich bin mir nicht sicher, was jQuery Ihrer Meinung nach damit zu tun hat.
Kevin Cline

Antworten:


19

2072-bewertete Schachspielerin hier. Ich habe diese Website über ein Wochenende in reinem JavaScript erstellt. Es ist keine Schachengine (ich habe sie entworfen, um unterhaltsame Eröffnungspositionen als eine Art perverse Chess960-Engine zu schaffen), aber es ist ein Ausgangspunkt. Der Quellcode ist hier .

Die Herstellung einer Funktionsplatine ist mit vielen Komplikationen verbunden. Diese beinhalten:

  • Zunächst muss herausgefunden werden, wie die grundlegenden rechtlichen Schritte dargestellt werden sollen. Man muss mit den Anfangs- und Endkoordinaten rechnen. Beispielsweise muss bei Turmbewegungen eine der Koordinaten davor und danach gleich sein. Bei Springerzügen muss die Summe der absoluten Werte der Koordinatenänderungen 3 betragen und beide Koordinaten müssen sich ändern. Bei Bischofszügen bleibt entweder die Summe der Koordinaten gleich oder beide erhöhen sich um den gleichen Betrag. Bauern sind am kniffligsten, weil Sie nicht nur herausfinden müssen, ob sie zwei oder eines der Quadrate bewegen können (überprüfen Sie die Reihe und die Farbe, anstatt zu speichern, wie viele Züge sie gemacht haben), sondern auch mit dem gesamten Einfang diagonal umgehen müssen -Fordere Sache.
  • Das Erfassen ist eine Herausforderung, da es sich um Bauern und Schach handelt. Man kann nicht einfach sagen, dass es eine Festnahme ist, wenn sich eine Figur auf das Quadrat einer anderen bewegt. Schließlich können sich die Bauern nicht auf ein anderes Feld bewegen, um es einzufangen - sie haben ihre eigene Art, es einzufangen.
  • Sie müssen einen effizienten Weg finden, um herauszufinden, ob sich feindliche Teile im Weg eines Teils befinden, um zu entscheiden, ob es legal ist oder nicht.
  • Scheck ist eine Herausforderung. Nach jedem Zug müssen Sie alle Felder überprüfen, auf die die gegnerischen Figuren gehen können, um festzustellen, ob einer von ihnen Ihren König betrifft, und in diesem Fall handelt es sich um einen illegalen Zug.
  • Rochade, en passant, Beförderung, Patt, erzwungene Auslosung, Wiederholung - angesichts des Ausmaßes des Problems ist keine davon trivial zu handhaben.

Alle Schachengines arbeiten, indem sie alle (möglicherweise eine heuristisch bestimmte Teilmenge) der erlaubten Züge in einer Position betrachten und Zahlen auswerten, um ihre relativen Werte darzustellen, indem sie diese Züge ausführen und für die resultierenden Positionen rekursiv dasselbe tun. Deine doppelten Probleme sind hier

  • So speichern Sie diese Daten effizient
  • So gehen Sie bei dieser rekursiven Suche vor - schließlich können Sie sie nicht für immer laufen lassen, also müssen Sie ein Limit festlegen und dann herausfinden, wie Sie Ihren Algorithmus so gestalten, dass er die bestmögliche und gründlichste Suche innerhalb dieses Limits ausführt. Sie möchten beispielsweise sicherstellen, dass für jeden möglichen Startzug mindestens eine Bewertung vorliegt, aber Sie möchten möglicherweise auch mehr Zeit für die Bewertung erfolgversprechenderer Züge aufwenden, anstatt für jeden Zug die gleiche Zeit einzuplanen.

Dies alles zusätzlich zum Entwurf des Algorithmus, zu dem es eine Fülle von Informationen gibt.

Was die Sprache angeht (obwohl Sie sich vermutlich bereits für JavaScript entschieden haben), kommt es meiner Meinung nach mehr auf Ihr Ziel an als auf alles andere. Ich wollte meine online machen (und JavaScript verbessern), also war JavaScript meine Wahl. Jede objektorientierte Programmiersprache ist jedoch ausreichend.

Sobald Sie sich mit Ihrer Arbeit vertraut gemacht haben, werden sich die folgenden Ressourcen wahrscheinlich als sehr hilfreich erweisen:

Viel Glück!


Vielen Dank, es hat mir sehr geholfen, loszulegen. Obwohl es noch viel zu lernen und zu implementieren gibt, sind Schach-Engines nie einfach zu schreiben. Aber ich denke, es ist gut, mit etwas zu arbeiten, das du liebst!
Adnan Zahid

Genau. Ich wollte einen wirklich abwechslungsreichen Lebenslauf von Projekten haben, aber ehrlich gesagt genieße ich es einfach, Schachsachen mehr zu entwickeln.
Andrew Latham

Die Domain lathamcity.com steht derzeit zum Verkauf. Ist der Code jetzt auf einer anderen Website verfügbar?
IkWeetHetOokNiet

14

Das Problem mit "Schachprogramm" als Konzept ist, dass es viele Stücke gibt, die viel Zeit in Anspruch nehmen können und Sie im Moment nicht unbedingt interessieren. Sie können jahrelang nur an Grafiken, einer Alpha-Beta-Suche oder einer Visualisierung arbeiten, um sie für die Suchmaschine zu entwickeln, oder ... es gibt viele Teile.

Ich empfehle, ein Open-Source-Schachprogramm zu finden (es muss viele geben) und die Teile zu verbessern, die Sie am meisten interessieren. Sie können schließlich das gesamte Programm ersetzen, eine Funktion nach der anderen, oder Sie können genug lernen und motiviert sein, es wegzuwerfen und Ihr eigenes Programm von Grund auf neu zu entwerfen. In jedem Fall ist der Schlüssel, "Licht" zu starten und die Seile zu lernen, bevor versucht wird, ein gesamtes Programm zu entwerfen.


Durch die Konformität mit einem der etablierten Schnittstellenprotokolle können Sie jedes vorhandene Frontend mit Ihrer Engine verwenden.

Ich hoffe, Alpha Beta braucht nicht Jahre, um zu schreiben
Kevin

1
Nicht Jahre zu schreiben, aber Jahre zu grok :)
Ddyer

9

Wenn Sie mit den Schachregeln vertraut sind, ist http://www.frayn.net/beowulf/theory.html ein guter Ausgangspunkt für grundlegende Techniken. Eine umfangreiche Sammlung von Materialien und Links finden Sie hier: http: // chessprogramming .wikispaces.com / Und drittens: Lernen Sie von anderen Code. Schauen Sie sich die Quellen von Crafty an . Es ist die führende Open Source Engine. Sehr wichtig wird es sein, über Testfälle nachzudenken, um zu sehen, ob Sie Verbesserungen vornehmen: Beginnen Sie zum Beispiel mit einigen einfachen Endspielpositionen mit 3 oder 4 Zahlen.


3

Wie bereits erwähnt, ist es nicht besonders schwer, eine Schachengine zu bauen. Vielleicht sollten Sie sich darauf konzentrieren, wie Sie diese Anwendung verwenden und (möglicherweise) bereitstellen möchten, da dies wahrscheinlich Ihre Wahl der Sprache bestimmt.

Wenn dies nur eine unterhaltsame Übung ist, können Sie sie in Javascript codieren und als Webseite bereitstellen. Wenn Sie es nie zu einem Experten-Schachspiel machen wollen, können zumindest andere mit ihm und seinem Quellcode spielen.

Wenn Sie gleichzeitig eine bestimmte Technologie erlernen möchten, sagen Sie WPF, dann ist dies möglicherweise eine gute Möglichkeit, zwei Fliegen mit einer Klappe zu schlagen. MVVM könnte für diese App übertrieben sein, aber Sie würden es zumindest lernen.

Wenn Sie Android-Geräte ansprechen möchten, ist Java eine gute Wahl. Ebenso Objective-C für iOS-Geräte.

Kurz und gut, Sprachwahl gibt es nicht im luftleeren Raum.


3

Ich gehe davon aus, dass Sie bereits über das Konzept von Min-Max, Bäumen und Beschneiden, Heuristik und anderen Grundlagen Bescheid wissen. Was ich hier schreibe, sind nur einige Details, die möglicherweise unterschätzt wurden.

Ich habe mit Begleitung eines Freundes vor einiger Zeit unsere eigene Schachengine geschrieben. Ich teile einige Probleme und Ideen, die wir hatten, und ich hoffe, Sie finden sie nützlich.

Da wir beide Java-Programmierer waren, wurde unsere Sprache zu Java und wir begannen mit einem objektorientierten Ansatz. Stücke waren Objekte, Tafel war Objekt, Akten und Ränge (Zeilen und Spalten in der Schachliteratur) waren Objekte. Und das war falsch. Der Overhead war enorm und das Programm hatte Mühe, mehr als 2 Züge (4 Lagen) im Suchbaum zu machen.

Bei einigen Suchanfragen kam uns eine brillante Idee (allerdings nicht unsere!): Teile und Board als lange Ganzzahlen (64 Bit) darstellen. Dies ist sinnvoll, da ein Schachbrett 64 Felder hat. Der Rest war etwas weiser (läuft sehr nahe an der CPU = extrem schnell). Stellen Sie sich zum Beispiel eine binäre 64-Bit-Ganzzahl vor, in der die Quadrate auf dem Brett angezeigt werden, die Ihre Figur angreifen kann. Wenn Sie nun ein logisches "UND" zwischen zwei Zahlen wie folgt ausführen, besagt ein Ergebnis ungleich Null, dass Sie ein Quadrat mit Angreifern haben. Es gibt verschiedene Möglichkeiten, das Schachbrett und die Figuren zu präsentieren:

1 - Entscheiden Sie über Ihre Board-Präsentation

Dann brauchst du und öffnest die Datenbank. Die Eröffnung des Schachs ist irgendwie gelöst und es wird dringend empfohlen, ein Eröffnungsbuch zu haben. In diesem Fall haben Sie viel zusätzliche Zeit in Blitzspielen.

2 - Finden Sie sich ein Eröffnungsbuch.

Wir haben das gemacht, aber wir waren noch lange nicht gut:

3 - Eine gute Schachengine sollte 6 Züge (12 Lagen) vor sich haben.

Also haben wir damals die Totzeit genutzt (wenn es sich um eine Mensch-gegen-Computer-Engine handelt).

4 - Nutze die Zeit, in der der Gegner nachdenkt, um einige Ebenen deines Baumes zu erstellen.

Und trotzdem waren wir weit weg von 12 Lagen. Durch mehr Studium entdecken wir einige Tricks! Zum Beispiel wurde vorgeschlagen, eine Lage des Baumes zu überspringen und von der nächsten Lage zu beginnen (als gäbe es keinen Gegner). Die Idee ist, dass, wenn ein Zug extrem idiotisch ist, warum man die Zeit verschwendet und sieht, wie der Gegner auf diesen Zug reagiert. Ein guter Motor sollte jedoch in der Lage sein, zwischen einem idiotischen Zug und einem genialen Königinopfer zu unterscheiden.

5 - Erlernen Sie die Programmiertricks für dieses spezielle Problem (Schach).

In diesem Zustand waren ich und mein Freund immer noch schlecht: / Wir konnten - und wir haben es teilweise getan - die berechneten Positionen speichern. Wenn Sie eine Position berechnen, speichern Sie diese für die Zukunft! Gleiches gilt für Schleifen im Suchbaum. Der Punkt war das effiziente Speichern / Abrufen von:

6 - Speichern Sie die von Ihnen generierten Daten ... Effizient!

und schlussendlich:

7 - Code mit maximaler Optimierung.

Dieses Problem ist sowohl in der CPU-Zeit als auch im Speicher extrem teuer. Es ist sehr wichtig, dass Sie Ihren Code sehr effizient schreiben. Denken Sie daran, dass es sich um den Verzweigungsfaktor 35 handelt. Dies bedeutet, dass ein nutzloses "Wenn" irgendwo in Ihrer Heuristik zu 3.3792205e+18nutzlos werden kann, wenn es irgendwo tief in Ihrem Suchbaum liegt.

Schachprogrammierung ist eine sehr, sehr interessante Herausforderung und es ist an der Zeit, Ihre Programmierfähigkeiten auf eine harte Probe zu stellen. Es gibt einige weitere Punkte, die ich vorschlagen kann, aber ich bin sicher, Sie werden sie selbst entdecken. Es gibt viele weitere Punkte, die ich nicht kenne, aber Sie können sie im Internet finden!

Viel Glück und hab Spaß!

ps Ich kenne Javascript nicht sehr gut, aber irgendetwas sagt mir, dass die Schwierigkeit des Problems ausschlaggebend ist. Wenn man bedenkt, was C ++ alles zu bieten hat, ist es vielleicht besser, Javascript zu löschen und es in C ++ zu tun.


2

Gemäß Ihrer Bearbeitung sind Sie in der Lage, "legale" Schritte zu definieren.

Es gibt zwei Möglichkeiten, Schachzüge zu beschreiben. Beschreibende Notation und algebraische Notation. Was Sie wahrscheinlich wollen, ist eine Funktion, die das Stück, die Startposition und die Endposition als Parameter verwendet. z.B. Ritter von QN1 bis QB2 ist ungültig, aber Ritter von QN1 bis Q2 sind gültig. Wenn Sie darüber nachdenken, ist die algebraische Notation möglicherweise einfacher, da die relative Position einfach berechnet werden kann.

Um sicherzustellen , dass Sie die minimale Menge an Code schreiben erforderlich ist , würde ich mit dem Schreiben von Tests für diese Funktion startet zuerst . Wenn Sie die algebraische Notation verwenden, benötigen Sie wahrscheinlich keinen Test pro Teil / Anfang / Ende. Bringen Sie jeden Test zum Laufen und korrigieren Sie die Duplizierung, bevor Sie mit dem nächsten Schritt fortfahren. Ihr Code wird sauberer.

Sobald Sie die legalen und illegalen Schritte für jedes Teil ausreichend behandelt haben, füge ich Checks für andere Variablen hinzu (z. B. die Umstellung eines Königs auf Scheck- und Partnerbedingungen).

Ich empfehle Qunit für Unit-Tests und Jasmin für Verhaltenstests in JavaScript.


1

Ich habe tatsächlich eine Schachengine geschrieben. Bereiten Sie sich auf ein Vergnügen und einen Albtraum vor. Als meine Freunde und ich das machten, fand ein zeitgesteuerter Programmierwettbewerb statt, und wir entschieden uns für Java. Ich halte Java oder C für die beste Wahl, aber ich sehe, dass Sie sich für Javascript entschieden haben. Ich kann es nicht wirklich klopfen, weil ich damit nicht vertraut bin.

Das Hauptproblem hierbei wird sein, dass es mit jedem Teil so viele Move / Win-Szenarien gibt, die Sie berücksichtigen müssen. Daher würde ich empfehlen, dass Sie alle möglichen Situationen für jedes Teil aufschreiben, bevor Sie mit dem eigentlichen Codieren beginnen. Nur ohne Planung einzuspringen, macht dieses lustige Projekt zu einer sich wiederholenden Aufgabe. Aber das ist wirklich die Hauptsache. Planen Sie zuerst außerhalb des Codes und stellen Sie sicher, dass Sie jedes Szenario für ein Teil zu einem Zeitpunkt erhalten.

Viel Glück


1

Für die Computer-Spieler-Entscheidungen im Spiel kann ich das Buch "Künstliche Intelligenz: Ein moderner Ansatz" (Buch-Website http://aima.cs.berkeley.edu/ ) nicht genug empfehlen . Abhängig von Ihrem mathematischen Hintergrund (dabei hilft die Graphentheorie) mag es ein wenig hoch sein, aber es ist so einfach geschrieben, wie dieses akademische Zeug sein kann, und es enthält eine sehr aktuelle Übersicht (und eine gewisse Tiefe) der Techniken Programme dazu bringen, Dinge zu entscheiden.

Es zeigt Ihnen Dinge wie die Angabe eines Ziels (z. B. Schachmatt oder Null), die Bewertung, wie nahe ein bestimmter Zustand (Platinenlayout) an diesem Ziel liegt, wie die verschiedenen möglichen Folgezustände ab dem aktuellen erzeugt werden und wie man einen immensen Problemraum durchquert.

Eine Sache, die beim Entwerfen eines KI-Algorithmus hilfreich sein könnte, besteht darin, herauszufinden, wie man entscheidet, welcher Zug als nächstes gespielt wird, als hätte man die ganze Zeit auf der Welt, ausgehend von einer Situation, die einem gewonnenen Spiel sehr nahe kommt. Sie optimieren es so, dass es in angemessener Zeit (Stunden) eine Lösung findet, und finden dann Wege, um einen Siegespfad zu wählen, obwohl Sie noch nicht alle Ergebnisse untersucht haben, sodass Sie das "Denken" tatsächlich unterbrechen können eine Wendung ist die Zeit wert.

Nur dann würde ich versuchen, die Darstellung zu optimieren, um die einzelnen Berechnungen zu beschleunigen, wie beispielsweise die Verwendung langer Ganzzahlen. Egal wie schnell Sie einen einzelnen Vergleich durchführen können, wenn die Art und Weise, wie Sie den Problemraum durchlaufen, keine gute Heuristik aufweist, wird es Ewigkeiten dauern, dies zu tun.


0

Sie können wirklich gehen, wie Sie wollen, aber das sind meine Gedanken zu diesem Thema:

Ich würde Java verwenden, da dies es Ihnen ermöglicht, ein sehr hohes Niveau zu erreichen und Benutzerschnittstellenbibliotheken (AWT, Swing) direkt zur Verfügung zu haben. Sie können das Schachbrett und die Figuren objektorientiert modellieren. Andere Objekte könnten für den Zugverlauf und die Wertung stehen. Sogar die Spieler könnten Objekte sein, und dann könnten Sie in Zukunft Ihre PlayerKlasse erweitern, um einen künstlichen intelligenten Computerspieler bereitzustellen.

Vielleicht möchten Sie einen Blick auf den Model-View-Controller (MVC) werfen, da dies in diesem Fall ein sehr nützlicher Ansatz ist, um Ihre Modellobjekte (Domänenmodell) an die Benutzeroberfläche (Ansicht) zu binden und dem Benutzer zu ermöglichen, die zu manipulieren Modell (über den Controller).

Möglicherweise möchten Sie auch eine testgetriebene Entwicklung anwenden , die nicht nur sicherstellt, dass sich alle Methoden wie erwartet verhalten, sondern Sie auch dazu zwingt, testbaren, modularen Code zu schreiben.


4
Eine Schachengine hat nichts mit der Benutzeroberfläche zu tun, sondern nur mit dem "Verstand", der den besten Zug berechnet.
CSE

@CSE - Dies hängt von Ihrer Definition der Engine ab .
Daniel AA Pelsmaeker

@CSE - Wie Adnan bearbeiten zeigt, er war eigentlich auf der Suche auch für eine UI. Meine Antwort ist also relevant.
Daniel AA Pelsmaeker

-8

Die Schachregeln selbst sind ziemlich einfach. Sie müssen nur in der Lage sein, eine Matrix (zweidimensionales Array) für die Tafel zu erstellen und einen Weg zu finden, um die Konzepte der Teile, die Bewegungsregeln für jedes Teil, die Bestätigung, dass ein Zug legal ist und die Bedingungen, die dies signalisieren, zu codieren das Ende des Spiels. Nichts besonderes. Sie sollten die Sprache verwenden, die Sie am besten kennen.

Wenn Sie nun eine KI zum Schachspielen erstellen möchten, die die Rolle eines Spielers übernimmt, wird es schwierig. Aber auch hier ist die Wahl der Sprache nicht das größte Problem. Verständnis der AI-Prinzipien ist. Das wird ein viel wichtigerer Faktor sein.

(Allerdings kann diese Art der Entscheidungsfindung extrem rechenintensiv sein, und Sie möchten wahrscheinlich lieber etwas verwenden, das sich zu nativem Code kompiliert, als zu einer Skriptsprache. Und C ++ ist eine sehr schlechte Wahl, nicht weil es nicht gut ist -angepasst an dieses Problem, aber nur, weil es im Allgemeinen eine sehr schlechte Sprache ist. Der Versuch, komplexe Dinge darin zu implementieren, ist eine gute Möglichkeit, alle möglichen Kopfschmerzen für sich selbst zu verschlüsseln.)


15
Ich denke, Sie müssten etwas genauer wissen, warum C ++ für diese bestimmte Aufgabe nicht geeignet ist, um Holy Warz zu vermeiden.
Erik Reppen

9
-1 für den Versuch, einen heiligen Krieg zu beginnen.
Doc Brown

1
Warum ist C ++ Ihrer Meinung nach im Allgemeinen eine sehr schlechte Sprache?
Anthony

Ich denke, du hast ihn auf jeden Fall falsch verstanden. Ich teile seine Meinung, dass C ++ eine gute Sprache ist, aber es wird zu einem Schmerz, wenn Sie sich mit komplexen Dingen beschäftigen!
Adnan Zahid
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.