Home Up Mail an Joachim Pimiskern Impressum

Go-Programmierung

Joachim Pimiskern

Letzte Änderung: 15.Jan.2012


Go ist auch ein Computerspiel, eine Kommunikationsplattform, eine Wissenschaft die an Universitäten gelehrt wurde (und wird?), ein Meditationsstil, ein riesiger Fundus fernöstlicher Weisheiten, es ist Literatur und bildende Kunst, ein mathematisches Problem, eine Herausforderung für Programmierer, eine Brücke zu östlichen Philosophien.
(Michael Enezian)

Vorwort

Nachdem ich des öfteren nach der Funktionsweise von Augos gefragt worden bin, möchte nun einige Techniken erläutern. Bei Augos ging es nicht um ein kommerzielles Produkt, sondern um eine Drosophila zur Untersuchung einiger Methoden der Künstlichen Intelligenz.

Veröffentlichungsform: hier soll immer mal wieder einige Kapitel eingefügt werden, je nachdem, wieviel Zeit mir zur Verfügung steht.

Inhalt

Einleitung   
  Definitionen 
  Repräsentation eines Spielfelds in einem Computerprogramm
  Ko-Regel 
Basisfunktionen eines Go-Programms   
  Innerhalb eines Spielfelds 
  Gebietsberechnung 
  Freiheitenberechnung 
  Test, ob ein Zug legal ist 
  Einen Zug ausführen 
Der Denkprozeß
  Kurze Einführung in die Spieltheorie
  Lokale Muster 
  Der letzte Zug des Gegners 
  Expertensysteme 
  Ziele in der Go-Programmierung 
  Ziele haben 
  Gewinnung von strategischen Zielen 
Auszählen am Ende einer Go-Partie
Diverse Aufgabenstellungen   
  Partien laden und speichern 
Anhang
  Weiterführende Literatur

Einleitung

Definitionen

Eine Kette ist eine Menge zusammenhängender Steine derselben Farbe. Auch ein einzelner Stein falle hier unter diese Kategorie. Merke: es ist einfach, Ketten zu erkennen.

Einige Ketten
Hier hat Weiß vier Ketten, Schwarz zwei

Eine Gruppe ist eine Menge von Ketten, die sich in räumlicher Nähe befinden und die üblicherweise das gleiche Schicksal teilen, also entweder alle gemeinsam leben oder sterben. Auch eine einzelne Kette falle hier unter diese Kategorie.



Einige Gruppen
Hier hat Weiß eine Gruppe links oben,
eine weitere Gruppe oben am Rand
und Schwarz hat eine Gruppe rechts oben.
Jede Gruppe besteht aus zwei Steinen.

Nun könnte man einwenden, Weiß besitze am oberen Rand nur eine einzige Gruppe, bestehend aus vier Steinen. Schwarz kann aber auf G17 invadieren und so die beiden Weißen Gruppen getrennt halten. Um dies zu erkennen, muß man bereits eine gewisse Spielstärke besitzen - man muß bereits Go spielen können. Das sieht nach einem Zirkelschluß aus, denn man kann diese Spielstärke ja nicht voraussetzen, sondern will sie aus einfacheren Elementen aufbauen.

Eine Heuristik bzw. heuristische Regel ist eine Aussage oder eine Anweisung die in den meisten Fällen korrekt ist, aber nicht unbedingt in allen Fällen. Beispielsweise gibt es beim Go die Aussage: "Dreidrei lebt immer". Damit ist gemeint, daß man, wenn man irgendwo im Eck ein neues Leben beginnen will, möglichst auf dem Punkt (3,3) anfangen soll. Beim Go gibt es eine Fülle solcher Strategeme oder Tips, die man teilweise sehr leicht einem Computer beibringen kann. Oft genügt dazu lokale Mustererkennung. Diese wird später erläutert.




Repräsentation eines Spielfelds in einem Computerprogramm

Bei Augos ist das Spielfeld ein zweidimensionales Array [0..18,0..18] von Integerzahlen. Empfehlung: besser ist es, einen dynamisch allozierten linearen Speicherbereich zu verwenden (malloc(),free()) und den Ort vermöge des Terms y * Breite + x umzurechnen, wobei x die Werte 0 bis Breite-1 und y die Werte 0 bis Hoehe-1 annehmen darf.

Spielsteine des Computers werden durch den Wert +1, Spielsteine des Gegners durch -1 repräsentiert. Leere Punkte werden durch 0 dargestellt. In einem Go-Programm wird man nicht mit einem einzigen Feld auskommen, sondern für die verschiedensten Zwecke weitere Felder halten, so z.B., um den Einfluß von Steinen auszudrücken oder den Wert von alternativen Zügen zu speichern.



Eine Go-Stellung Interne Repräsentation der Stellung



Ko-Regel

Die Ko-Regel soll Endlospartien vermeiden. Die chinesischen Regeln sagen, daß eine Gesamtstellung nicht wiederholt werden darf. Um dies per Programm sicherzustellen, kann man eine Liste der bisherigen Stellungen in einer Datei speichern. Alternativ kann man angesichts heutiger Speichergrößen auch alle bisher gespielten Stellungen im Hauptspeicher halten oder man merkt sich nur die Züge und rekonstruiert ggf. die Stellung.

Aus Gründen der Effizienz hält man sich einen Fingerabdruck (z.B. CRC oder nur Anzahl der schwarzen und weißen Steine) jeder bisherigen Stellung im Hauptspeicher und liest die komplette Stellung aus der Datei nur dann für einen Vergleich ein, wenn ein in Frage kommender Zug zu einer Stellung mit einem Fingerabdruck führen würde, der schon einmal da war.

Bei Augos wurden die japanischen Regeln verwendet. Diese sagen, daß ein einzelner schlagender Stein nicht gleich wieder geschlagen werden darf.

Empfehlung: die chinesische Ko-Regel ist zu bevorzugen, besonders auf kleinen Brettern. Die chinesischen Regeln erlauben größere Variantenvielfalt.




Basisfunktionen eines Go-Programms

Es gibt einige besonders wichtige Funktionen, die auch ein sehr primitives Go-Programm aufweisen sollte.

Innerhalb(x,y) Prüft nach, ob ein Punkt innerhalb des Spielfeldes liegt.
Gebiet(x,y,Feld) Liefert zu einem Punkt auf einem Feld die Zusammenhangskomponente aller Punkte der gleichen Farbe.
Freiheiten(x,y,Feld) Liefert eine Liste der Freiheiten der Kette, die sich am Punkt (x,y) befindet.
Legal(x,y,f,Feld,KoInfo) Testet, ob ein Zug an Stelle (x,y) auf dem Feld für Farbe f legal ist unter Berücksichtigung der Ko-Information KoInfo (z.B. Zug-Historie oder letzter geschlagener einzelner Stein)
Ausfuehren(x,y,f,Feld,KoInfo) Führt einen Zug der Farbe f auf einem Feld aus und ändert die KoInfo.
TreppFangbar(x,y,Feld,KoInfo) Testet, ob eine Kette, die zwei Freiheiten besitzt, mittels einer Treppe gefangen werden kann. Diese Funktion ist nicht zwingend notwendig, aber ein Programm, das stur eine nichtfunktionierende Treppe läuft, verliert sehr rasch.

Innerhalb eines Spielfelds

Bei Augos bis einschließlich Version 6 ist die Brettgröße fest als 19*19 vorgegeben. Dem Leser sei aber empfohlen, die Brettgröße variabel zu gestalten. Das Brett habe die Größe Breite * Höhe. Somit ergibt sich eine Funktion für den Test, ob ein Zug innerhalb des Spielfelds liegt, zu

Definition Innerhalb(x,y): boolean
Falls (x >= 0) und (x < Breite) und (y >= 0) und (y < Hoehe) 
  return true
sonst
  return false

Gebietsberechnung

Die Funktion Gebiet() hat einen Punkt (x,y) als Parameter sowie ein Feld F. Sie liefert eine Liste von Punkten zurück. Hierzu wird ein Hilfsfeld M für Markierungen sowie ein Stapel (auch Stack oder Keller genannt) von Punkten verwendet. f ist eine Variable für die betrachtete "Farbe".

Definition Gebiet(x,y,F): Liste
- result := []
- f := F[x,y]
- Leere den Stapel
- Leere Feld M
- M[x,y] := 1     
- Staple (x,y)
- Solange der Stapel nicht leer ist
   - Nimm einen Punkt (a,b) vom Stapel
   - Addiere (a,b) zu result
   - Für alle (c,d) aus {(a+1,b),(a-1,b),(a,b+1),(a,b-1)}
      - Falls Innerhalb(c,d) und M[c,d] = 0 und F[c,d] = f
        - M[c,d] := 1
        - Staple(c,d)
- return result

Freiheitenberechnung

Um die Freiheiten einer Kette zu berechnen, kann man auf die bereits vorhandene Funktion Gebiet() zurückgreifen.

Definition Freiheiten(x,y,F): Liste
- result := []
- L := Gebiet(x,y,F)
- Leere Feld M
- Für alle (a,b) aus L
   - Für alle (c,d) aus {(a+1,b),(a-1,b),(a,b+1),(a,b-1)}
     - Falls Innerhalb(c,d) und M[c,d] = 0 und F[c,d] = 0
       - Addiere (c,d) zu result
       - M[c,d] := 1
- return result

Test, ob ein Zug legal ist

Dieser Test ist zweiteilig. Zuerst wird auf ein Hilfsfeld G gesetzt. Etwaige geschlagene gegnerische Steine werden von G entfernt und in einer Liste gesammelt. Der gesetzte Stein muß nun mindestens eine Freiheit haben.

Der zweite Teil, KoBehandlung(...), besteht in der Untersuchung in Bezug auf die Ko-Regel. Die japanischen Regeln besagen, daß ein einzelner schlagender Stein nicht sofort wieder geschlagen werden darf. In diesem Falle besteht KoInfo nur in der Nennung des letzten einzelnen Schlagsteines, und der Test auf Verletzung der Ko-Regel besteht darin, zu prüfen, ob die Liste Geschlagen nur in diesem einen Stein besteht.

Definition Legal(x,y,f,F,KoInfo):
- Kopiere das Spielfeld F nach G
- Geschlagen := []
- Falls G[x,y] != 0,
    - return false
- G[x,y] := f
- Für alle (a,b) aus {(x+1,y),(x-1,y),(x,y+1),(x,y-1)}
    - Falls Innerhalb(a,b) und G[a,b] = -f und Freiheiten(a,b,G) = []
      - l := Gebiet(a,b,G)
      - Für alle (c,d) aus l 
        - G[c,d] := 0
        - Addiere (c,d) zu Geschlagen
- Falls Freiheiten(x,y,G) = 0
  - return false
- return KoBehandlung(G,Geschlagen,KoInfo)

Einen Zug ausführen

Diese Funktion ähnelt dem Test, ob ein Zug legal ist, wo auf ein Hilfsfeld gesetzt wird. Hier aber wird auf das 'richtige' Feld F gesetzt, und Tests auf Legalität finden hier nicht statt.

Definition Ausfuehren(x,y,f,Feld,KoInfo):
- Geschlagen := []
- F[x,y] := f
- Für alle (a,b) aus {(x+1,y),(x-1,y),(x,y+1),(x,y-1)}
    - Falls Innerhalb(a,b) und F[a,b] = -f und Freiheiten(a,b,F) = []
      - l := Gebiet(a,b,F)
      - Für alle (c,d) aus l 
        - F[c,d] := 0
        - Addiere (c,d) zu Geschlagen
- UpdateKoInfo(F,Geschlagen,KoInfo)



Der Denkprozeß

Kurze Einführung in die Spieltheorie

In diesem Kapitel geht es um eine der Möglichkeiten, ein Computerprogramm in die Lage zu versetzen, sich für eine von mehreren Alternativen zu entscheiden. Genauer gesagt, es geht um Zweipersonen-Nullsummen-Strategiespiele mit vollständiger Information. Es wird erläutert, was es mit Suchbäumen auf sich hat.

Der Zustand des Spiels besteht üblicherweise im Inhalt eines Spielfeldes, der Stellung. Für die weitere Betrachtungsweise nehmen wir an, daß eine schnelle Bewertung existiert, die einer Stellung eine Zahl zuordnet. Für Schach bietet sich an, z.B. den Materialwert in Bauerneinheiten aufzusummieren und dabei eigene Figuren als positiv, gegnerische Figuren als negativ zu werten.

Beim Go ist es schwieriger, eine Stellung zu beurteilen, denn die Aussage, daß z.B. 41 schwarze und 50 weiße Steine auf dem Brett stehen, sagt wenig darüber aus, wer besser steht. Gelingt es aber, eine Teil-Stellung zu extrahieren, so kann der Materialwert sehr wohl aussagekräftig sein, Beispielsweise bei Treppen, Geta oder Tsumego.

Wenn man durch einen Zug eine Stellung in eine Folgestellung überführen muß, so erscheint es sinnvoll, eine mit einer möglichst großen Bewertung zu wählen (Im Rahmen dieser Überlegungen möge es stets eine Zugmöglichkeit geben. Den Fall, daß man auch passen darf, kann man dadurch behandeln, daß man eine Folgestellung vorsieht, die denselben Wert wie die Ausgangsstellung besitzt).



Einen Zug weit vorausdenken Hier sollte man den Zug ausführen, der zur Stellung mit der Bewertung 23 führt.

Anders sieht die Sache aus, wenn man noch die Antwort des Gegners auf den eigenen Zug berücksichtigen muß. Unser Gegner wird stets bestrebt sein, unseren Gewinn möglichst klein zu halten.



Zwei Züge weit vorausdenken Hier ist eine Stellung, die uns 50 Punkte bringt, die beste Zukunft. Um diese zu erreichen, muß man den Zug b ausführen. Der Gegner wird aber nicht so liebenswürdig sein, dann den Zug g zu machen, sondern wird dann f wählen, was uns nur 7 Punkte einbringt. Wenn man den besten Zug c aus dem Beispiel zuvor mit der Ein-Zug-Vorausschau ausführt, wird der Gegner mit h antworten, was uns nicht 23 Punkte, sondern letztlich nur 15 Punkte bringt. Der beste Zug ist d, worauf der Gegner dann mit j anworten wird, so daß d 18 Punkte wert ist.

Man sieht, daß man bei dieser Betrachtungsweise von Strategiespielen an den Blättern den Spielbaums beginnen muß, um eine Stellung zu beurteilen. Der Gegner wird stets darum bemüht sein, unseren Gewinn zu minimieren, während wir ihn maximieren wollen.

N(s,i) sei eine Funktion, die zu einer Stellung s die i-te Nachfolgestellung liefert.

Definition Bewerte(s): integer
- Falls IstBlatt(s)
    - return eb(s)
- Falls GegnerIstAmZug(s)
    - return Minimum(Bewerte(N(s,i))) über alle i
- Falls man in S selbst am Zug ist,
    - return Maximum(Bewerte(N(s,i))) über alle i
Einsatzgebiete von Minimax beim Computer-Go:

Anders als bei Schach, Mühle oder beispielsweise Dame kann Minimax nicht für globale Entscheidungen eingesetzt werden, weil der Spielbaum zu groß ist, ausgenommen bei sehr kleinen Brettern, sagen wir, höchstens der Größe 5*5. Sinnvolle Anwendungen für Baumberechnungen beim Computer-Go sind jedoch Funktionen zum Entscheiden lokaler Situationen, z.B. Treppen und Tsumego.




Lokale Muster

Das menschliche Auge sieht nur in einem winzigen Ausschnitt des Sichtfeldes scharf, mit Hilfe der Makula. Der Mensch muß deswegen ein Schriftstück oder eine Go-Stellung abtasten, indem er seinen Blick schweifen läßt.


Der Fokus des Blickfeldes

Dieses zu modellieren ist auch bei einem Go-Programm sinnvoll. Mit einem Endlichen Automaten (bisweilen auch Zustandsautomat genannt) ist das leicht zu realisieren. Ein Endlicher Automat ist ein primitives informationsverarbeitendes Gerät. Er besitzt eine endliche Anzahl von Zuständen. In einem Zeittakt liest er genau ein Zeichen aus einem seriellen Eingabekanal und geht in einen Folgezustand, der eindeutig aus der Kombination Ausgangszustand + Eingabezeichen bestimmt ist. Beim Erreichen des Zielzustands wird dann eine Ausgabe ausgelöst (Genauer gesagt, es handelt sich hierbei um einen Moore-Automaten. Nur der Vollständigkeit halber sei erwähnt, daß es noch das Modell der Mealy-Automaten gibt, deren Ausgabe nicht vom Zielzustand abhängt sondern von der Kombination Ausgangszustand + Eingabezeichen).

Ausgabe bedeutet hier, daß der Endliche Automat bescheid sagt, daß ein bestimmtes Muster erkannt worden ist, wenn ein bestimmter Zustand erreicht worden ist.

Bei Augos wird die Mustererkennung durch eine Baum-Datenstruktur realisiert. Jeder Knoten hat 4 Nachfolgeknoten, für die Eingabezeichen s (schwarz), w (weiß), l (leer) und a (außerhalb).


Entscheidungsbaum zur Mustererkennung

Der Eingabestrom wird durch durch spiralförmiges Abtasten des Spielfelds in der Umgebung eines Punktes bereitgestellt. Kommt man beim Abtasten auf einen Punkt außerhalb des Spielfelds, wird das Eingabezeichen a (wie außerhalb) angenommen.


Scannen des Spielfelds gemäß der Form einer Schneckennudel
Dieses Muster wird durch die Zeichenfolge
[..x.o......................x.....o..aaaaaaaaaaaaaa.............a]
repräsentiert.

Muster beim Go haben eine achtzählige Symmetrie. Es gibt vier Rotationen und davon jeweils zwei spiegelbildliche Varianten.


Schneckennudelkoordinaten Schneckennudelkoordinaten Schneckennudelkoordinaten Schneckennudelkoordinaten
Schneckennudelkoordinaten Schneckennudelkoordinaten Schneckennudelkoordinaten Schneckennudelkoordinaten



Der letzte Zug des Gegners

Oft liest man in Problembüchern "Weiß hat gerade den markierten Stein gesetzt. Wie sollte Schwarz antworten?". Hier wird der Eindruck erweckt, der beste Zug von Schwarz wäre ein anderer, wenn ein anderer Stein markiert wäre. Eine einfache Technik für Go-Programme ist es, in lokalen Mustern den letzten Zug des Gegners und einen Vorschlag für einen eigenen Zug anzugeben. So erreicht man schnell spektakuläre Erfolge. Dies funktioniert aber nur eine zeitlang gut und läßt Initiative vermissen. Außerdem gibt es im Go oft genug Situationen, wo man einen Zug des Gegners ganz woanders beantworten muß.

Ein Go-Programm sollte sich in eine vorgegebene Gesamtstellung eindenken können, ohne Rücksicht auf den bisherigen Spielverlauf.




Expertensysteme

Ein Expertensystem besteht üblicherweise aus den Komponenten

Aufbau eines Expertensystems

Die Dialogkomponente ist dafür da, um mit dem Anwender zu kommunizieren. Die Wissensbasis enthält anwendungsspezifisches Wissen. Meist ist dieses Wissen in einer speziellen Sprache notiert, die sich von der Sprache, mit der das Expertensystem selbst programmiert ist, unterscheidet. Aufgabe jener Sprachen ist es, Aussagen und Regeln darstellen zu können. Geeignet sind z.B. Lisp oder Prolog.

Leere Expertensysteme, in die noch kein Wissen in Form von Aussagen und Regeln eingegeben wurde, heißen auch Expertensystemshells.

Der Wissens-Ingenieur befüllt das Expertensystem mit Aussagen und Regeln aus einem bestimmten Fachgebiet. Das nötige Fachwissen bekommt er, indem er einen Experten interviewt.

Die Inferenzmaschine ist das Herz eines Expertensystems. Sie wendet die Regeln auf die Aussagen an und erzeugt dabei entweder neue Aussagen (vorwärtsverkettende Vorgehensweise) oder sie beweist, daß eine Aussage aus den Aussagen der Wissensbasis und den Regeln gefolgert werden kann (rückwärtsverkettende Vorgehensweise).

Klassisches Beispiel der Anwendung einer Regel auf eine Aussage ist: Sokrates ist ein Mensch (Aussage). Alle Menschen sind sterblich (Regel). In Lisp sähe die Wissensbasis z.B. so aus:

  (mensch sokrates)
  (implies (mensch ?x) (sterblich ?x))

Die Inferenzmaschine würde daraus folgern: (sterblich sokrates), und diese Aussage zur Wissensbasis hinzufügen.

Bei Augos4 ist ein Lisp-Interpreter eincompiliert. Das Expertenwissen liegt in Form von .lsp-Dateien vor. Der Lisp-Interpreter, Inflisp, ist im Sourcecode frei verfügbar.

Lisp hat den Vorteil, daß man mal schnell etwas ausprobieren kann, ohne jedesmal neu compilieren zu müssen, denn Lisp-Code wird interpretiert. Weil sich eine gewisse Struktur von Aussagen und Regeln herauskristallisierte, wurde die Wissensbasis ab Augos5 statt in Lisp direkt in Form von Objekten der Programmiersprache Object Pascal (der Sprache von Delphi) implementiert.

Ziele sind Objekt-Instanzen. Am besten lassen sich Ziele mit Sätzen der natürlichen Sprache vergleichen. Klassennamen der Ziel-Klassen entsprechen Verben, und Subjekt und Objekt sind Member-Variablen. Ziele haben eine Text-Repräsentation zu Ausgabezwecken. So könnte ein Ziel etwa lauten:

  EyeMove Group: 269 Place: 270

Dieses Ziel bedeutet: um für die Gruppe 269 ein Auge zu machen, setze auf den Platz 270. Bei Augos kann jeder Platz auf dem Brett sowohl durch XY-Koordinaten (zweidimensional) als auch durch eine einzige Zahl (eindimensional) ausgedrückt werden. Ketten werden nach dem Ort des Steins mit der kleinsten eindimensionalen Koordinate benannt.

Ein anderes Ziel könnte sein:

  MoreLiberties Chain: 99 Place: 138 

Dies bedeutet: um die Anzahl der Freiheiten der Kette 99 zu vermehren, setze auf 138.

Bei vielen Programmen für Strategiespiele wird ein Zug derart ausgewählt, daß zunächst allen Zügen ein Wert zugeordnet wird - anschließend wird der Zug genommen, dessen Wert maximal ist. Diese Vorgehensweise ist bei Go aber problematisch, denn es gibt sehr viele Einflüsse, aus denen der Wert eines Zuges zusammengesetzt ist. Man will aber vermeiden, daß viele unbedeutende Argumente gegen einen Zug ein bedeutendes Argument für einen Zug einfach durch ihre Menge überstimmen. Deswegen werden bei Augos Ziele durch Prioritäts-Regeln verglichen.

Eine Augos-Regel ist ein Objekt mit einer Vergleichsfunktion, die als Parameter zwei Ziele bekommt und als Ausgabe einen der Werte -1, 0 oder +1 liefert. Das Resultat -1 bedeutet, daß das erste Ziel weniger wert ist als das zweite. 0 bedeutet, die Ziele sind gleich viel wert. +1 bedeutet, das erste Ziel hat einen höheren Wert als das zweite.

Die Regeln bei Augos sind hierarchisch angeordnet. Sie tragen eine Prioritätszahl. Zuerst werden alle Regeln der höchsten Prioritätsstufe angewandt und die Ergebnisse aufsummiert. Ist die Summe größer oder kleiner als 0, so steht das Ergebnis eines Zielvergleichs fest. Erst wenn diese Summe gleich 0 ist, werden Regeln einer niedrigeren Prioritätsstufe betrachtet usw.




Ziele in der Go-Programmierung



Ziele haben

Ziele im Sinne von Augos sind Listen, bestehend aus einem Verb und einer Reihe von beliebig vielen Objekten. Mit Objekt ist hier meist der Name einer Kette oder ein Punkt auf dem Spielfeld gemeint.

Beispiele:

VERTEIDIGEN 100
ANGREIFEN 53
NEUES-LEBEN-BEGINNEN
VERBINDEN 41 43
BESETZEN 234
VERZICHTEN

Es gibt eine Ziel-Hierarchie, auf deren unterster Ebene stets Wünsche / Anweisungen / Befehle zum Besetzen einzelner Punkte stehen. Auf oberster Ebene könnte man Ziel GEWINNEN nennen, aber dieses Oberziel ist trivialerweise immer vorhanden.

Bei Augos sind die Ziele höchster Stufe stets die Namen von Ketten. Handelt es sich um eine eigene Kette, so ist diese Kette zu retten. Mögliche Unterziele: sich ausdehnen, an andere Kette anbinden, zwei Augen machen, einen Fluchtsprung machen usw. Handelt es sich um eine gegnerische Kette, so ist diese zu töten, und mögliche Unterziele sind: diese Kette umzingeln, eine Freiheit wegnehmen usw.

In der Praxis wird man zur rechnerinternen Repräsentation von Zielen nicht Strings nehmen, sondern Klassen von einer allgemeineren Klasse TGoal oder so ableiten. Sinnvoll ist eine Methode ToString(), mit der man ein Ziel textuell ausgeben kann.



Gewinnung von strategischen Zielen

- Ordne alle Ketten einer der Kategorien {sicher, angreifbar, rettbar, tot} zu.

sicher Gegner kann in einem Zug allein nicht schaden.
angreifbar Gegner kann einen zwingen, dort zu reagieren.
rettbar Wenn Gegner am Zug ist, kann er Kette bzw.Gruppe töten, wenn man selbst am Zug ist, kann man sie retten.
tot Wenn man selber am Zug ist, kann man dennoch nichts mehr für die Kette/Gruppe tun.

Wie die Klassifikation der Gruppen bzw. Ketten geschehen soll, ist nicht Gegenstand dieses Kapitels. Jedem Programmierer ist selbst überlassen, Methoden der Klassifikation zu finden. Es ist sogar so, daß die Ermittlung des Status einer Gruppe / Kette so schwierig ist wie Gospielen selber. In der Praxis sollte man also nach Näherungslösungen suchen.

- Baue einen Graphen auf, dessen Knoten die Ketten, und dessen Kanten räumliche Nähe repräsentieren.

- Berechne die taktischen Werte aller Ketten.

Sichere und tote Ketten bekommen den taktischen Wert 0, angreifbare und rettbare Ketten bekommen den Wert Anzahl Steine * 2 + Anzahl Freiheiten.

Rechtfertigung: man muß beim Go eine gegnerische Kette nicht herausschlagen, sondern kann sie großräumig umzingeln, so daß noch das nichtbesetzte Gebiet einverleibt wird. Man gewinnt also die Steine der Kette, die Felder, wo sich die Kette drauf befindet und noch das Gebiet drumherum, das hier grob abgeschätzt wird als die Anzahl der Freiheiten der Kette.

- Berechne die strategischen Werte einer Gruppe

Der strategische Wert einer Gruppe ist die Summe aus dem taktischen Wert der Gruppe + Summe der taktischen Werte der gegnerischen Nachbargruppen.

- Ableitung von Zielen

Ermittle die Kette mit dem höchsten strategischen Wert. Falls es eine Kette der eigenen Farbe ist, tue etwas für die Kette: erhöhe die Freiheiten, entferne eine Nachbarkette, binde die Kette an, mache zwei Augen ... Falls es eine Kette der gegnerischen Farbe ist, unternimm etwas gegen die Kette: umzingle die Kette, nimm eine Freiheit weg, schlage die Kette raus, ...




Auszählen am Ende einer Go-Partie

Eine Go-Partie ist zuende, wenn beide Spieler sich einig sind. D.h. wenn beide Spiele unmittelbar nacheinander auf einen Zug verzichten (sie passen).

Im vorliegenden Fall sei die Partie als beendet erklärt worden, oder es soll einfach so zwischendurch geschätzt werden, wie das Territorium zwischen Schwarz und Weiß aufgeteilt werden soll. Normalerweise würde man noch neutrale Punkte besetzen. Das sind die freien Felder, die sich zwischen lebenden weißen und lebenden schwarzen Steinen befinden. Aber dies sei hier unterlassen worden.



Ende einer Go-Partie


Am Ende einer Partie ist der Status jeder Kette entweder "sicher" oder "tot". Ketten mit dem Status "angreifbar" oder "rettbar" sollte es nicht mehr geben. Und zwar deswegen, weil das Go-Programm dann noch Ziele hätte, die es verfolgen könnte. Das Go-Programm würde also die Partie nicht abbrechen wollen, falls es den Status irgendeiner Kette noch beeinflussen könnte.



Lebende und tote Ketten


Die toten Steine werden vom Brett entfernt und es verbleiben nur noch lebende Steine.



Gefangene Steine entfernen


Um leere Punkte auf dem Go-Brett einem der beiden Spieler zuzuordnen, benötigt man eine Art Kraftfeld. Eines, das nicht durch gegnerische Mauern hindurchwirkt.

Eine Möglichkeit wäre, leeren Feldern die Distanz zum nächsten Stein einer vorgegebenen Farbe zuzuordnen, und zwar eine Art Manhattan-Distanz. Bei der Manhattan-Distanz zählt man die Beträge der Distanz in X-Richtung und der in Y-Richtung zusammen. Das ist eine vereinfachte Sicht der Dinge, denn da ist ja noch die Forderung, daß Mauern gegnerischer Steine umgangen werden müssen.

Am einfachsten kann man das nun verwendete Feldstärkemaß bezüglich einer Farbe definieren, indem man für jedes freie Feld auf dem Go-Brett den Abstand zum nächsten Stein dieser Farbe bestimmt, wobei man Schritte nur entlang von Linien zählt und Felder mit Steinen der gegnerischen Farbe nicht betreten werden dürfen.

Algorithmisch geht man besser von den besetzten Feldern der betreffenden Farbe aus und flutet schrittweise das Spielfeld, das ist effizienter als von leeren Feldern aus den nächsten Stein zu suchen.



Wanderung schwarzer Steine


Die Feldstärke für schwarze Gruppen wird bestimmt, dann separat für weiße Gruppen. Man sieht, daß es Felder gibt, die 0 sind, also die durch den oben beschriebenen Wanderungsprozeß nicht betreten werden können, weil eine Mauer aus gegnerischen Steinen die Wanderung behindert. Auf diese Weise identifiziert man Territorium des Gegners. Felder, die auf keinem der beiden Bretter mit 0 markiert sind, stehen sowohl unter schwarzem als auch unter weißem Einfluß: sie sind neutral.

Schwarzes Einflußgebiet Weißes Einflußgebiet


Hier sind die Punkte, die als neutral erkannt worden sind, rot markiert. Das beschriebene Verfahren kann entweder dazu verwendet werden, um am Ende der Partie Gebiet auszuzählen oder aber, um noch Zugvorschläge für das Go-Programm zu erhalten, nämlich zum Besetzen der neutralen Felder.

Neutrale Punkte


Am Ende hat Schwarz 23 Punkte Gebiet, Weiß 20. 13 Punkte sind neutral. Steine, die im Verlauf der Partie geschlagen wurden oder wegen Beendigung der Partie vom Brett genommen wurden, müssen separat verbucht werden.


Diverse Aufgabenstellungen

Partien laden und speichern

Das Dateiformat SGF (Smart Game Format) ist ein Quasi-Standard für die Speicherung von Go-Partien. Es ist sehr leicht, eine Partie im SGF-Format abzuspeichern, aber es ist aufwendig, SGF zu lesen und Partien darzustellen. Denn SGF unterstützt diverse Markierungen von Punkten, Varianten und sogar Partie-Sammlungen in einer einzigen Datei.

Augos unterstützt sowohl das Schreiben als auch das Lesen von SGF-Dateien. Der SGF-Parser wurde als eine Delphi-Komponente realisiert. Wer ein Go-Programm mit Delphi entwickelt, kann diese Komponente verwenden, um Go-Partien, die im SGF-Format vorliegen, in einem TreeView (Steuerelement zur Anzeige von Baum-Strukturen) darzustellen.

TSgfParser, ein SGF-Parser für Delphi

Empfohlen sei dem Leser, zumindest eine zusätzliche Möglichkeit der Speicherung von Partien im SGF-Format anzubieten, dann aber ein eigenes Format zu verwenden, das leicht zu programmieren ist. Für das Nachspielen von Partien gibt es bereits sehr schöne freie SGF-Editoren, die mitunter eben nicht selber Go spielen können, so daß man sich nicht mehr mit diesem Thema beschäftigen muß.




Anhang

Weiterführende Literatur

SGF File Format FF[4] (Arno Hollosi)





Home Up Mail an Joachim Pimiskern Impressum