Regelbasierte Systeme am Beispiel Tichu

Transcription

Regelbasierte Systeme am Beispiel Tichu
Regelbasierte Systeme am Beispiel Tichu
Maturaarbeit von Simon Rösch, 1MNd
Betreut von Tobias Bäumlin
Erstellt von Dezember 2007 bis Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
1 Einleitung
Als es vor knapp einem Jahr darum ging, ein Thema für die Maturaarbeit zu wählen,
war für mich klar, dass ich etwas im Bereich Informatik machen möchte. Da ich auch
ein sehr angefressener Tichu-Spieler bin, kam ich auf die Idee ein Programm zu schreiben, das Tichu spielen kann. Ich war mir aber auch bewusst, dass dies nicht einfach
sein würde und habe die Idee deshalb lange nur mit mir herumgetragen. Als mir dann
keine bessere Idee kam, habe ich begonnen mit Kollegen, die in der Informatikbranche
tätig sind, über mein Projekt zu sprechen. Ich habe nicht nur ermunternde Ratschläge
bekommen, aber nach einem längeren Gespräch mit Moritz Kobel, der mein Projekt
als durchführbar einstufte und mich dazu ermunterte, es zu versuchen, habe ich mich
definitiv für dieses Projekt entschieden.
Da ich nun wusste, was ich machen wollte, brauchte ich noch einen Betreuer. Für
mich kam eigentlich nur Tobias Bäumlin in Frage, da er mich im Programmieren unterrichtete. Dieser sagte nach etwas zögern auch zu. Zusammen haben wir dann beschlossen, dass es wohl am einfachsten wäre, das Problem mit einem Expertensystem
zu lösen. Da es ein viel zu grosser Aufwand gewesen wäre, ein Expertensystem selber
zu schreiben, machte ich mich auf die Suche nach einem bereits bestehenden System,
das ich für meine Zwecke adaptieren konnte. Gleichzeitig habe ich auch schon eine
erste Version des Programms geschrieben, das jedoch noch sehr zufällig spielte. Nach
der gefundenen Lösung, das regelbasierte System Drools, konnte es dann definitiv
losgehen.
Nach der praktischen Arbeit brauchte ich nicht mehr gross nachzudenken, worüber ich
schreiben sollte, die Themen waren ziemlich klar. Regelsysteme und Tichu mussten
erklärt werden und auch eine Beschreibung meines Projektes durfte nicht fehlen.
An dieser Stelle möchte ich es nicht unterlassen, mich bei denjenigen zu bedanken, die
mich bei meiner Arbeit unterstützten. Es sind dies namentlich mein Betreuer Tobias
Bäumlin, der mir immer mit Ratschlägen zur Seite gestanden ist, sowie Moritz Kobel,
der mich zum Projekt motiviert hat. Ein grosser Dank geht auch an Urs Hostettler, der
mir per Mail einige tichubezogene Fragen beantwortete und mir die Erlaubnis gab, die
Spielkarten von Fata Morgana zu scannen und in meiner Arbeit zu verwenden.
Auch den Lektoren AnnaTina, Christoph und Jürg Rösch möchte ich an dieser Stelle
herzlich danken, sowie allen anderen, die mir während der Arbeit in irgendeiner Weise
geholfen haben.
--
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
2 Inhaltsverzeichnis
1
Einleitung
3
2
Inhaltsverzeichnis
4
3
Abstract
6
4 Regelbasierte Systeme
4.1 Regelbasierte Logik
4.2 Der Aufbau eines regelbasierten Systems
4.3 Vorteile eines regelbasierten Systems
7
7
9
9
5 Drools
5.1 Der Rete-Algorithmus
5.2 Die Regelsprache
5.3 Der Einbau in ein Java-Programm
5.4 Das Eclipse-Plugin
11
11
12
15
16
6 Tichu
6.1 Geschichte
6.2 Der Autor
6.3 Die Spielvorbereitungen
6.4 Die Spielregeln
6.5 Die Sonderkarten
6.6 Bomben
6.7 Das Ende einer Runde
6.8 Das Ansagen
17
17
17
18
18
19
20
20
20
7 Wahrscheinlichkeitsberechnungen bei Tichu
7.1 Die Annäherungsformel
21
23
8 Das Projekt
25
8.1 Die Vereinfachungen
25
8.2 Die Realisation
25
8.3 Der Spielablauf
25
8.4 Das Mischen der Karten
26
8.5 Das Schupfen
26
8.6 Das Berechnen von möglichen Kombinationen
26
8.7 Das Prüfen von Kombinationen
27
8.8 Wahrscheinlichkeit einer Kombination
27
8.9 Die optimalen Kombinationen
27
8.10 Die History
29
8.11 Das Userinterface
29
8.12 Der Computerplayer
29
8.13 Schwellenwahrscheinlichkeitswert-Bestimmung30
8.14 Die Endphase30
8.15 Spielstrategien30
8.16 Schupfen31
--
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
8.17 UML-Diagramm von meinem Programm32
9
Fazit
33
10 Quellenverzeichnis
34
10.1 Literatur34
10.2 Internetadressen34
10.3 Computerprogramme34
10.4 Bildnachweis34
11 Anhang
35
11.1 Resultate der Schwellenwahrscheinlichkeitswert-Bestimmung35
11.2 Resultate Offensiv vs. Defensiv35
11.3 Resultate Offensiv vs. Ultraoffensiv36
11.4 Mail von Urs Hostettler37
11.5 Digitaler Anhang38
--
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
3 Abstract
Ein Programm, das gut Tichu spielen soll, braucht eine Komponente, die entscheidet,
wann welcher Zug gemacht werden soll. Dazu eignen sich Regelbasierte Systeme, da
diese einen relativ einfachen Weg bieten, das Spielstrategie-Wissen dem Computer
zu übergeben. Ein solches Regelbasiertes System ist Drools. Drools basiert auf Java,
hat eine einfache Syntax und ist, obwohl es OpenSource ist, äusserst gut dokumentiert. Mit Hilfe von diesem System habe ich ein Programm erstellt, das eine etwas
vereinfachte Version von Tichu spielen kann. Dabei eine gute Strategie zu entwickeln
erwies sich als äusserst schwierig. Am Schluss hatte ich drei verschiedene Strategien,
aus denen ich im Test ermittelte, welche die beste sei. Gesamthaft gesehen, ist es mir
aber nicht gelungen, ein Programm zu schreiben, das wirklich gut Tichu spielen kann,
da ich mich auch selber beim Tichu Spielen oft auf meine Intuition verlasse, was der
Computer nicht kann. Trotzdem war es aber eine sehr interessante Arbeit und ich habe
dabei neue Programmiertechniken kennen gelernt und kann das Spiel Tichu jetzt auch
von einer ganz anderen Perspektive aus ansehen.
--
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
4 Regelbasierte Systeme
Die Künstliche Intelligenz (englisch „Artificial Intelligence“) ist das Teilgebiet der
Informatik, das sich damit befasst Probleme automatisch und intelligent zu lösen. Eine
Art, dem Computer Intelligenz beizubringen, sind Expertensysteme. Wie der Name
schon sagt, wird dabei versucht dem Computer das gleiche (oder wenn möglich bessere) Wissen zu geben, das auch ein menschlicher Experte auf dem entsprechenden Gebiet hat. Solche Systeme sind dann notwendig, wenn die zu verarbeitenden Daten nicht
in schön strukturierter Form vorliegen. Karl Kurbel hat in seinem Buch „Entwicklung
und Einsatz von Expertensystemen“ [L1] ein Expertensystem wie folgt definiert:
„Ein Expertensystem ist ein Programm, das in einem eng abgegrenzten
Anwendungsbereich die spezifischen Problemlösungsfähigkeiten eines
menschlichen Experten zumindest annähernd erreicht oder übertrifft.“
Das wichtigste in einem Expertensystem ist das Wissen, denn darauf basiert das ganze
Programm. Dieses Wissen kann aber in verschiedenen Formen vorliegen wie z.B. in
Objekten, Constraints oder Regeln. Expertensysteme, die auf Regeln basieren, nennt
man regelbasierte Systeme. Da es mir am einfachsten schien, das Wissen für die Strategie eines „künstlichen Tichuphilen“ mit Regeln darzustellen, wählte ich für mein
Programm ein Regelsystem. Wie immer in der Informatik wären sicher auch andere
Lösungswege möglich gewesen.
4.1 Regelbasierte Logik
Eine Regel besteht immer aus einer Prämisse und einer Konklusion und hat den Aufbau Wenn Prämisse, dann Konklusion. Die Prämisse bezieht sich immer auf eine Faktenbasis und beschreibt die Situation, die eintreten muss, damit die Regel feuert, das
heisst, die Konklusion ausgeführt wird. Die Prämisse wird oft auch „left-hand side“
genannt, da sie die linke Seite der Regel stellt. Analog dazu nennt man die Konklusion
auch „right-hand side“. Die Konklusion kann in einem Regelsystem ganz unterschiedlich aussehen: Sie kann beispielsweise ein direktes Resultat enthalten, die Faktenbasis
verändern oder neue Fakten zur Faktenbasis hinzufügen resp. Fakten entfernen. Durch
die Veränderung der Faktenbasis werden nun die Prämissen anderer Regeln erfüllt,
was zur Folge hat, dass diese gefeuert werden müssen, was wiederum ein Resultat
oder eine weitere Veränderung der Faktenbasis zur Folge hat. Auf diese Weise können
mit Regeln und dazugehöriger Faktenbasis Probleme gelöst werden.
Solche Regeln können jedoch auch zu Widersprüchen führen, die das Regelsystem
lösen können muss.
Regel 1: Wenn der Kunde eine Kundenkarte hat, dann gibt es Fr. 10.Reduktion.
Regel 2: Wenn das Produkt aus der Elektrogeräteabteilung kommt und
mehr als Fr. 250.- kostet, dann gibt es 10% Rabatt.
Beispiel 4.1
Was muss nun der Kunde bezahlen, der eine Kundenkarte besitzt und ein Produkt
aus der Elektrogeräteabteilung kaufen will, das im Originalpreis 255.- kosten würde?
Da beide Regeln gleichzeitig zutreffen, sind sie im Konflikt. In diesem Fall muss das
Siehe Kapitel 6.1
--
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
Regelsystem also wissen, welche Regel zuerst ausgeführt werden soll. Dazu gibt es
mehrere Möglichkeiten: Den Regeln werden verschiedene Prioritäten zugewiesen, es
wird die erste/letzte zutreffende Regel gewählt, es wird die spezifischere/allgemeinere
Regel gewählt oder es wird zufällig eine Regel ausgewählt.
Weiter stellt sich die Frage, ob überhaupt von beiden Rabatten gleichzeitig profitiert
werden kann. Wenn ja, wird dann die Regel 2 noch ausgeführt, nachdem Regel 1 ausgeführt wurde und das Produkt ja eigentlich nur noch Fr. 245.- kosten würde? Das Regelsystem muss also auch genau vorgeben, wann geprüft wird, wie viele und welche
Regeln ausgeführt werden. Es bietet sich die Möglichkeit, nur eine bestimmte Anzahl
Regeln auszuführen (bspw. nur ein Rabatt, nicht kumulierbar) oder alle Regeln auszuführen, die passen. Auch entscheidend ist, ob nach dem Ausführen einer Regel erneut
geprüft wird, welche Regeln zutreffen (also die Faktenbasis aktualisiert wird) oder die
Regeln nur für eine Faktenbasis überprüft werden.
Wie diese Probleme gelöst werden, hängt vom jeweiligen Regelsystem ab. Oft hat
der Anwender aber auch die Möglichkeit, gewisse Teile der Konfliktlösungsstrategien
selber zu definieren.
Aber auch noch mit Hilfe dieser Konfliktlösungsstrategien sind nicht alle Probleme
gelöst, denn was passiert, wenn es 2 Regeln gibt,
Regel 1: Wenn A < 5, dann A = A·A
Regel 2: Wenn A > 5, dann A = 3
Beispiel 4.2
und die Faktenbasis nach dem ausführen jeder Regel neu geladen wird? – Man befindet sich in einer Endlosschleife und das Regelsystem wird früher oder später abstürzen. Obwohl diese beiden Regeln kaum jemand programmieren würde, muss der
Programmierer auch beim Aufstellen von Regeln aufpassen und sich immer ganz im
Klaren sein, was er genau macht.
Ein weiteres Regelbeispiel:
Regel 1:
Regel 2:
Wenn ein Tier 2 Beine und 2 Flügel hat, dann ist es ein Vogel.
Wenn ein Vogel klein ist und eine rote Brust hat, dann ist es ein
Rotkehlchen.
Beispiel 4.3
Diese beiden Regeln können nun verschieden angewendet werden. Man kann daraus
schliessen, dass ein kleines Tier mit 2 Beinen, 2 Flügeln und einer roten Brust ein Rotkehlchen ist. Dabei handelt es sich um die „Vorwärtsverkettung“. Es gibt aber auch die
Möglichkeit, die Regeln umzukehren und daraus zu schliessen, dass ein Rotkehlchen
ein kleiner Vogel mit roter Brust ist. Diese Methode wird dann „Rückwärtsverkettung“
genannt. Es macht aber nicht immer Sinn, Regeln umzukehren.
Regel:
Wenn ich ins Dählhölzli gehen will, dann muss ich zuerst nach
Bern fahren.
Beispiel 4.4
Wenn wir diese Regeln umkehren, erhalten wir als Resultat, dass ich ins Dählhölzli
gehen will, wenn ich nach Bern fahre, was nicht immer zutreffen muss.
--
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
4.2 Der Aufbau eines regelbasierten Systems
Grundsätzlich haben alle regelbasierten Systeme den gleichen Aufbau. Im „Working
Memory“ sind alle Facts gespeichert, die für die Regelanwendung notwendig sind.
Das Regelsystem muss also eine Möglichkeit bieten, dem „Working Memory“ Fakten
hinzuzufügen, diese zu aktualisieren oder zu entfernen. Im „Producion Memory“ sind
alle Regeln gespeichert. Auch hier braucht es je nach Bedarf die Möglichkeit automatisch Regeln anzupassen, hinzuzufügen oder zu löschen. Zwischen diesen beiden
Komponenten steht der Regelinterpreter (die Inferenzmaschine, engl. inference engine). Der Regelinterpreter sucht anhand der Fakten im „Working Memory“ die zutreffenden Regeln und führt diese anhand der Konfliktlösungsstrategie aus.
Praktisch, aber nicht zwingend notwendig, ist eine Erklärungskomponente, die erklären kann welche Regeln, auf Grund welcher Fakten, in welcher Reihenfolge gefeuert
wurden. Dies ist besonders bei der Entwicklung wichtig, da es sonst schwer ist, herauszufinden, wieso das erhaltene Resultat nicht mit dem erwarteten Resultat übereinstimmt.
Meistens treten Regelsysteme auch nicht alleine auf, sondern sind Teil einer Applikation. Dann braucht es auch noch Komponenten, die es der Applikation erlauben, das
„Working Memory“ und bei Bedarf auch das „Production Memory“ anzupassen.
4.3 Vorteile eines regelbasierten Systems
Ein grosser Vorteil von Regeln ist die sehr übersichtliche Struktur der Regeln selber,
durch die man Aussagen fast so formulieren kann, wie man es im alltäglichen Leben
auch tut. Auf diese Art können sehr schwierige Probleme gelöst werden, die auf „traditionelle“ Art zu programmieren extrem schwierig wäre. Auch kann es sein, dass die
Lösung eines Problems gar nicht vollständig bekannt ist, wodurch es unmöglich wäre,
ein „traditionelles“ Programm zu schreiben, durch Regeln das Problem aber (annähernd) gelöst werden kann.
Zudem lässt die einfache Struktur der Regeln zu, dass ein Experte auf dem jeweiligen
Gebiet (nach einer kurzen Einarbeitungszeit) ohne Programmierkenntnisse Regeln
selbstständig aufstellen und verändern kann.
Ein Regelsystem bietet auch den Vorteil, dass genau erklärt werden kann, wieso was
ausgeführt worden ist. Dies kann gerade in der Entwicklungsphase extrem wichtig
sein, nämlich wenn das Programm nicht die Lösung hervorbringt, die es eigentlich
sollte.
Ein weiterer Vorteil ist die strikte Trennung zwischen Daten und Logik. Da die Regeln
separat gespeichert sind, wird die Logik viel übersichtlicher. Auch kann die Logik
schnell ausgetauscht werden, sei es in einem Geschäftsprogramm, bei dem die Regeln
oft und schnell ändern oder um zwei verschiedene Spielstrategien in einem programmierten Spiel auszuprobieren.
Nach dieser Reihe von Vorteilen eines Regelbasierten Systems stellt sich die Frage,
wieso man denn nicht immer Regelsysteme verwendet. Die Drools Dokumentation
gibt auf die Frage, wann man ein Regelsystem brauchen soll, folgende Antwort:
When there is no satisfactory traditional programming approach to solve the problem. (Deutsch: „Wenn es keinen zufriedenstellenden, traditionellen Weg gibt, um das Problem zu lösen.) [I4]
--
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
Diese Aussage braucht aber noch etwas Erklärung, denn wann gibt es keinen traditionellen Lösungsweg? – Genau dort wo Regelsysteme Vorteile bieten: Wenn es keine
algorithmische Lösung gibt, die Logik sich oft verändert oder die Experten selber
nicht programmieren können.
-10-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
5 Drools
Auf dem Markt gibt es viele Regelsysteme, die alle ihre Vor- und Nachteile haben.
Da ich wusste, dass ich meine Maturaarbeit in Java schreiben wollte, habe ich nach
einem Regelsystem gesucht, das auf Java basiert. Im Buch „Java Rules Engines“ von
Lars Wunderlich bin ich auf Drools gestossen. Da Drools eine Open Source Rules
Engine ist, also im Internet gratis heruntergeladen werden kann, waren auch meine
finanziellen Erwartungen erfüllt. Das Buch von Lars Wunderlich bot mir einen einfachen Einstieg und die sehr ausführliche Online-Dokumentation von Drools hat mir
die restlichen Fragen beantwortet.
5.1 Der Rete-Algorithmus
Wie im Kapitel „4.2. Der Aufbau eines regelbasierten Systems“ erklärt, braucht jedes
Regelsystem einen Regelinterpreter, der herausfindet, welche Regeln gefeuert werden sollen. Bei Drools erfüllt dies der etwas angepasste Rete-Algorithmus, der von
Dr. Charles Forgy entwickelt und 1978-79 in seiner Dissertation dokumentiert wurde.
Der Rete-Algorithmus lässt sich in zwei Teile aufteilen: die Regelerfassung und die
Ausführung. Bei der Regelerfassung wird aus den Regeln ein Netzwerk (rete lat. =
Netz) erzeugt, das danach bei der Ausführung genutzt wird, um Daten zu filtern und so
herauszufinden, welche Regeln feuern sollen. Das Netzwerk besteht aus einer Menge
von Nodes (engl. Knoten), die von den Daten von oben nach unten passiert werden
müssen. Bei jedem Node können
nur die Daten passieren, die der
Anforderung entsprechen.
Das Netz ist aus grundsätzlich 4
verschiedenen Arten von Nodes
aufgebaut: RootNodes (WurzelKnoten), 1-Input-Nodes (1-Eingang-Knoten), 2-Input-Nodes
(2-Eingang-Knoten) und Endnodes. Jedes Netzwerk beginnt
mit dem RootNode. An diesem
Punkt werden alle Objekte aus
dem „Working Memory“ in das
Netzwerk eingefügt. Anschliessend kommt für jedes Objekt,
das irgendwo in den Prämissen
der Regeln vorkommt, ein ObjectTypNode, der zu den 1-Input-Nodes (1-Eingang-Knoten)
gehört. Bei diesen Nodes werden nur die Objekte von einem
bestimmten Typ durchgelassen.
Nachdem die Objekte nach ihrem Typ sortiert wurden, können
für die jeweiligen Objekte Variablen auf bestimmte Werte geprüft werden. Dies geschieht bei Abb. 1: Beispiel eines Rete-Netzwerkes
-11-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
den AlphaNodes, die wiederum zu den 1-Input-Nodes gehören. Nun kann es aber auch
sein, dass in einer Regel zwei Werte miteinander verglichen werden. Dazu dienen die
beiden 2-Input-Nodes. Die beiden Eingänge werden linker und rechter Eingang genannt. Der linke Eingang übernimmt eine Liste von Objekten, ein sogenanntes Tupel,
das durch den 1-InputNode LeftInputNodeAdapter erstellt wird. Der rechte Eingang
übernimmt ein normales einzelnes Objekt. Dieses Objekt wird dann mit jedem Objekt
aus dem Tupel verglichen und die Paare, die passen, werden weitergeleitet. Es gibt
zwei Arten von 2-Input-Nodes: Der JoinNode prüft zwei Werte zweier Objekte und
liefert sie weiter, wenn sie übereinstimmen, der NotNode macht genau das Gegenteil,
liefert die Objekte also weiter, wenn die geprüften Werte nicht übereinstimmen. Der
letzte Node ist der Endnode. Ein solcher wird erreicht, wenn alle Bedingungen einer
Regel erfüllt sind.
Der Vorteil vom Rete-Algorithmus ist, dass im Vergleich zu einem ganz naiven Regelinterpreter, der jede Regel einzeln prüft, mit einem Rete-Netzwerk schnell und mit
nur wenig Aufwand die Regeln gefunden werden, deren Prämissen erfüllt sind. Gerade
bei grossen Datenmengen ist dies von grosser Bedeutung.
5.2 Die Regelsprache
Drools besitzt eine eigene Regelsprache, die jedoch im Aufbau nicht kompliziert ist
und für Java-Programmierer sehr einfach zu erlernen ist. Die Regeln werden in einer
(oder mehreren) Datei gespeichert, die typischerweise die Endung .drl hat, was aber
nicht zwingend ist. In einer solchen Datei können beliebig viele Regeln und Funktionen abgespeichert werden. Wie bei Java-Klassen können auch die Regeldateien in
Packages zusammengefasst werden. Dies wird über den Befehl „package PackageName“ erreicht, welcher am Anfang der Datei stehen muss. Die Reihenfolge der folgenden Elemente einer Regeldatei spielt keine Rolle. Ich werde die einzelnen Elemente
anschliessend der Reihe nach erläutern, zuerst aber noch einige allgemeine Bemerkungen zur Regelerstellung in Drools: Kommentare können wie in Java einzeilig mit //
und mehrzeilig mit /* ... */ erstellt werden. Zusätzlich können einzeilige Kommentare
auch mit # anstelle von // eingeleitet werden. Weiter gibt es auch bei Drools eine Liste
von reservierten Wörtern, die nicht benutzt werden dürfen, ausser natürlich in ihrer
jeweiligen Funktion: rule, query, when, then, end, null, and, or, not, exists, collect,
accumulate, from, forall, true, false und eval. Weiter gibt es eine Liste mit Wörtern die
man besser auch nicht benutzt, obwohl es in den meisten Fällen wahrscheinlich funktionieren würde: package, function, global, import, template, attributes, enabled, salience, duration, init, action, reverse, result, contains, axcludes, memberOf, matches,
in, date-effective, date-expires, no-loop, auto-focus, activation-group, agenda-group,
dialect und rule-flow-group.
Die Semikola (`;`) zum abschliessen eines Befehls sind in der Prämisse optional, in
der Konklusion jedoch zwingend notwendig. Zeilenumbrüche sind an jeder Stelle optional. Es empfiehlt sich jedoch seine persönliche Darstellung zur Strukturierung des
Codes zu entwickeln.
import
Analog zu Java funktioniert auch der import-Befehl in Drools. Die Klasse java.lang
sowie Klassen aus dem selben package werden automatisch importiert, alle restlichen
Klassen, die benötigt werden, müssen mit diesem Befehl importiert werden.
-12-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
global
Der Vollständigkeit halber sei hier erwähnt, dass es die Möglichkeit gibt, globale Variablen in Drools zu definieren. Diese dürfen aber nicht verändert werden, da dies der
Regelinterpreter nicht bemerken würde, weil sie nicht Teil des „Working Memory“
sind.
function
Mit function bietet Drools die Möglichkeit in der Regeldatei selber Methoden zu definieren. Dies ist praktisch, wenn man mehrere Regeln mit der selben Konklusion hat,
die dann einfach nur noch den Methodenaufruf enthält. Der Aufbau der Methode ist
gleich wie in Java:
function int add(int a, int b){
return a+b;
}
Beispiel 5.1
Mit function hat man aber auch die Möglichkeit Methoden aus anderen Klassen zu
importieren. Dies funktioniert mit folgender Syntax:
import function mein.package.Klasse.add;
Beispiel 5.2
In beiden Fällen können die Funktionen ganz einfach über ihren Namen aufgerufen
werden.
System.out.print( add(1, 2) ) //Ausgabe: 3
Beispiel 5.3
rule
Der Aufbau einer Regel ist simpel:
rule „<Name>“
<Attribute>
when
<Prämisse>
then
<Konklusion>
end
Beispiel 5.4
Der Name ist der Name der Regel, der praktischerweise auch etwas über die Regel
aussagt (Namen wie Regel 1, Regel 2 führen bei grösseren Regelmengen schnell zur
Unübersichtlichkeit). Es dürfen nicht zwei Regeln mit dem selben Namen existieren,
ansonsten gibt es einen Fehler beim Laden der Regeln.
Eine Regel kann diverse Attribute haben, ich möchte hier die wichtigsten kurz beschreiben:
No-loop übernimmt einen Wert vom Typ Boolean, Standard ist false. Wenn die Konklusion der Regel einen Fakt so verändert, dass die Regel erneut zutreffen würde, wird
die Regel nur ausgeführt, wenn no-loop auf false gesetzt ist. No-loop = true verhindert
ein erneutes ausführen der Regel.
Salience übernimmt einen Wert vom Typ Integer, Standard ist 0. Salience ist eine Art
-13-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
Priorität, das heisst Regeln mit höherem Salience Wert werden zuerst ausgeführt.
Die Prämisse setzt sich bei Drools aus null oder mehr Bedingungen zusammen. Ist die
Prämisse leer, ist sie immer erfüllt und die Regel wird immer ausgeführt. Die wichtigste Art Bedingungen zu formulieren sind Pattern. Mehrere Pattern werden standardmässig durch UND verknüpft.
Das einfachste Pattern ist eines ohne constraints, das nur einen Objekt-Typ prüft. Für
die Prämisse
Buch( )
Beispiel 5.5
wird die Regel für jedes Objekt vom Typ Buch im „Working Memory“ ausgeführt. Damit man weiss, welches Objekt gepasst hat und dieses weiterverarbeiten kann (in einer
zweiten Bedingung der Prämisse oder in der Konklusion), muss es in einer Variable
gespeichert werden. Variablen in Drools können das Vorzeichen `$` haben, welches
nicht zwingend notwendig ist, aber der Übersichtlichkeit dient. Einer Variable kann
man mit `:` ein Objekt zuweisen.
$b : Buch()
Beispiel 5.6
Ein Pattern kann aber auch Bedingungen, sogenannte Constraints, enthalten. Mehrere
Constraints werden mit `&&` (UND), `||` (ODER) oder `,` (UND) verbunden:
$b : Buch( autor==“Franz Hohler“, neu=true )
//Buch vom Autor Franz Hohler das neu ist
Beispiel 5.7
Die Connectors werden in der Reihenfolge `&&`, `||`, `,` berücksichtigt. Durch Setzen
von Klammern, kann dies geändert werden:
$b : Buch( autor==“Franz Hohler“ && preis<=20 || neu==true)
//Buch, das von Franz Hohler ist und weniger als 20.- kostet oder ein
//Buch, das neu ist
$b : Buch( autor==“Franz Hohler“ && (preis<=20 || neu==true) )
//Buch, das von Franz Hohler ist und weniger als 20.- kostet oder neu ist
Beispiel 5.8
Die Werte der Objektevariablen werden überprüft indem beim Objekt die Funktion
getVariablenname aufgerufen wird. Diese Funktion muss natürlich im Objekt als public Funktion ohne Argumente definiert sein und den Variablenwert zurückliefern.
Analog dazu braucht Drools zum Setzen von Variablenwerten (in der Konklusion)
die Funktion setVariablenname(variablentyp variable). Diese braucht aber zum Setzen
eines Wertes nicht aufgerufen zu werden, sondern kann wie üblich mit
$objekt.variable = 123;
Beispiel 5.9
gesetzt werden; Drools wandelt das dann zu einem Funktionsaufruf um.
Drools bietet auch sämtliche Vergleichsoperatoren: `<`, `<=`, `=>`, `>`, `==`, `!=`.
Dazu kommen je nach Variablentyp noch weitere spezifische Operatoren, auf die ich
hier nicht weiter eingehen möchte.
Weiter bietet Drools Operatoren zum Testen von Bedingungen, die für jedes Objekt
-14-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
eines Types im „Working Memory“ gelten müssen (forall), für die Existenz eines Objektes (exists) resp. die Nichtexistenz (not) oder für die Existenz des einen oder des
anderen (or).
In der Konklusion der Regel kann normaler Java-Code programmiert werden. Auch
auf die in der Prämisse in Variablen gespeicherten Objekte kann wie auf ein normales
Java-Objekt zugegriffen werden. Drools bietet zudem noch Methoden zum Aktualisieren des „Working Memory“. Mit update(); kann dem „Working Memory“ mitgeteilt
werden, dass ein Objekt aktualisiert wurde. Wird dies nicht getan, werden weitere Regeln so ausgeführt, als ob das Objekt nicht verändert worden wäre. Mit retract(); kann
ein Objekt aus dem „Working Memory“ entfernt werden und mit insert(); kann analog
dazu ein neues Objekt eingefügt werden.
5.3 Der Einbau in ein Java-Programm
Bis jetzt habe ich immer nur über „Working Memory“ etc. geschrieben, aber wie das
in Java dann wirklich aussieht, habe ich nicht erklärt. Damit Drools läuft, müssen die
Drools Librarys verfügbar sein und die entsprechenden Klassen importiert werden.
Danach muss zuerst eine RuleBase erzeugt werden. Dazu schreibt man sich am besten
eine Funktion, die das Einlesen der Regeln übernimmt. Man muss nämlich zuerst die
Regeldatei einlesen, dann daraus ein Package machen und dieses in die RuleBase einfügen.
public static RuleBase readRule() throws Exception{
Reader source = new InputStreamReader( DroolsTest.class.
getResourceAsStream(„/Regeldatei.drl“));
PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( source );
Package pkg = builder.getPackage();
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage( pkg );
return ruleBase;
}
Beispiel 5.10
Das „Working Memory“ selber ist ein Objekt vom Typ StatefulSession, das aus der
ruleBase, die wir oben erstellt haben, erstellt werden kann:
final StatefulSession workingMemory = ruleBase.newStatefulSession();
Beispiel 5.11
Danach können dem „Working Memory“ beliebig Objekte hinzugefügt werden, was
über die Funktion des StatefulSession-Objekts insert(Object) geschieht.
workingMemory.insert(buch);
Beispiel 5.12
Wenn alle Objekte hinzugefügt wurden, kann das Feuern der Regeln mit fireAllRules()
ausgelöst werden.
workingMemory.fireAllRules();
-15-
Beispiel 5.13
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
Damit es nach mehrmaligem Ausführen dieses Prozesses nicht zum Speicherüberlauf
kommt, muss die Funktion workingMemory.dispose(); aufgerufen werden, welche die
Referenz auf das Objekt in der ruleBase löscht, damit die Garbage Collection das Objekt löschen kann.
5.4 Das Eclipse-Plugin
Drools bietet ein Plugin für die Java-Entwicklungsumgebung Eclipse, das praktisch,
aber nicht zwingend notwendig ist. Das Plugin ermöglicht es, Drools-Projekte zu erstellen, die dann auch schon die benötigten Librarys eingebunden haben und je nach
Wunsch auch schon eine Beispiel-Klasse mit zugehöriger Regeldatei beinhaltet. Wenn
das Plugin installiert ist, werden Drools-Regeldateien automatisch als solche erkannt
und der Umgang wird durch farbige Hervorhebung der Keywords erleichtert. Weiter
kann das Plugin auch das Rete-Netzwerk einer Regeldatei anzeigen, es zeigt einem
also, wie die Regeln schliesslich umgesetzt werden.
Schade am Plugin ist, dass es die Referenzen in Regeldateien auf andere Teile im
Javacode nicht erkennt. Dies führt zum Beispiel dazu, dass, wenn eine Klasse oder
eine Variable umbenennt wird, dies in den Regeldateien nicht automatisch aktualisiert
wird. Da dies in Eclipse ansonsten sehr einfach funktioniert, vergisst man oft, beim
Ändern eines Namens dies auch in der Regeldateien zu tun, was aber glücklicherweise
meist in einer Fehlerausgabe des Drools-Compiler endet.
-16-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
6 Tichu
Tichu ist ein Kartenspiel für 4 Spieler, welche in zwei Teams aufgeteilt sind, die sich
übers Kreuz gegenüber sitzen. Ein Tichuspiel besteht aus mehreren Runden und endet
in der Regel sobald ein Team mindestens 1000 Punkte erreicht hat. Gespielt wird mit
56 Karten, nämlich den Karten 2-10, J (Bauer), Q (Dame), K (König) und A (Ass) in
je 4 Farben (rot, grün, blau und schwarz) und 4 Sonderkarten. Das Ziel des Spieles ist
es, möglichst schnell seine Karten abzulegen, dabei möglichst viele Punkte zu machen
und wenn möglich auch noch mit dem Partner zusammen zu spielen.
6.1 Geschichte
Tichu ist in Europa seit 1991 bekannt. Die in der Spielanleitung von Fata Morgana
beschriebene Geschichte, dass Tichu in China, genauer in der Region Nanjing täglich
von Millionen von Chinesen gespielt wird, wurde mir vom offiziellen Schweizer Autor
des Spieles, Urs Hostettler bestätigt. Er wies mich jedoch darauf hin, dass er dem Spiel
noch die Sonderkarten und das Schupfen hinzugefügt hat. Ebenfalls gilt in China, im
Gegensatz zu Europa, meist die 2 als höchste Karte und nicht das Ass.
Tichu ist seither auch noch in anderen Verlagen erschienen und wird neben der
Schweiz auch in Deutschland oft gespielt. Es finden auch jährlich mehrere Tichumeisterschaften statt. Bei der Deutschen Tichu-Meisterschaft (kurz DTM), die seit 1994
jährlich (bis 1998 in Dortmund, seither in Würzburg) stattfindet, ist es Tradition, dass
der Sieger für ein Jahr bestimmen darf, wie ein „Tichuspieler“ genannt werden soll,
da diese Frage schon in der Spielanleitung von Fata Morgana aufgeworfen wurde. So
kam es dazu, dass man 1998 vom „Tichupathen“, 2001 vom „Tichupotter“ oder 2008
von „Tichuphilen“ sprechen sollte.
Seit einigen Jahren kann man Tichu auch online in der sogenannten Brettspielwelt
(www.brettspielwelt.de) mit Usern aus der ganzen Welt zusammen spielen. Es finden
auch dort immer wieder online Tichu-Turniere statt.
Laut Wikipedia soll es bis jetzt noch kein Programm geben, das es ermöglicht offline
gegen den Computer Tichu zu spielen.
6.2 Der Autor
Urs Hostettler wurde am 14. August 1949 in Bern
geboren. Er studierte Mathematik und ist mit einer
Psychologin verheiratet. Auch heute lebt er noch in
Bern und arbeitet für den Spieleverlag Fata Morgana. Er war 1982 auch Mitgründer des bekannten
Berner Spielladens „Drachennest“. Neben Tichu
hat er noch andere bekannte und fast ebenso gute
Spiele erfunden, wie bspw. „Anno Domini“ oder
„Kreml“.
Urs Hostettler entwickelt aber nicht nur neue
Spiele, sondern spielt auch immer wieder selber
mit. So gewann er beispielsweise 1997 die DTM.
Er ist aber auch als Schriftsteller sowie als Musiker tätig.
Abb. 2: Urs Hostettler im Mai 2007
-17-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
6.3 Die Spielvorbereitungen
Zu Beginn des Spieles werden die Karten verteilt. Der Sieger der letzten Runde mischt
die Karten, lässt abheben, legt den Kartenstapel in die Tischmitte und nimmt sich die
oberste Karte. Reihum nehmen sich alle Spieler jeweils die oberste Karte, bis keine
mehr vorhanden ist. Diese Verteilmethode ist am Anfang etwas ungewohnt, aber man
gewöhnt sich daran. Auch diese Tradition wurde aus China importiert.
Vor Spielbeginn muss nun jeder Spieler jedem Mitspieler eine Karte „schupfen“. Das
heisst jeder Spieler legt vor jeden Mitspieler eine seiner Handkarten verdeckt auf den
Tisch, die er diesem geben will. Da er dadurch auch drei Karten bekommt, hat er
schliesslich wieder 14 Karten auf der Hand. Der Spieler, der nun die Karte Mahjong
(siehe 6.5. Sonderkarten) auf der Hand hält, beginnt mit ausspielen.
Abb. 3: Die Tichu-Karten von Fata Morgana
6.4 Die Spielregeln
Viele Regeln gibt es eigentlich nicht. Wenn man am ausspielen ist, hat man 6 Spielmöglichkeiten. Entweder man spielt eine einzelne Karte, ein Paar, ein Trio, ein Fullhouse, das aus einem Paar und einem Trio besteht, eine Strasse, die aus mindestens
fünf aufeinanderfolgenden Einzelkarten besteht oder eine Paarfolge, eine so genannte
Treppe, die aus beliebig vielen aufeinanderfolgenden Paaren besteht. Es ist auch erlaubt Bomben auszuspielen, dazu siehe Kapitel Bomben.
Der in Spielreihenfolge nächster Spieler hat nun 2 Möglichkeiten. Entweder er passt,
das heisst er sagt: „Ich passe!“ und gibt somit das Spiel an den nächsten Spieler weiter, oder er spielt die gleiche Kombination wie der Spieler vor ihm, aber mit höherem
Wert. Über die Höhe einer Kombination entscheidet grundsätzlich die tiefste Karte,
ausser bei einem Full House, bei welchem das Trio massgebend ist. Es ist zu beachten,
dass exakt die gleiche Kombination gespielt werden muss. Das heisst eine Strasse mit
sechs Karten kann nicht mit einer Strasse mit fünf oder sieben Karten überspielt werden, sondern nur mit einer Strasse mit ebenfalls sechs Karten.
Passen nacheinander drei Spieler, gehört der Stich dem Spieler der die letzten Karten
gespielt hat. Er kann nun die Karten verdeckt vor sich ablegen und kommt ans Aus
-18-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
spielen. Sollte er keine Karten mehr haben, „erbt“ der in Spielreihenfolge nächste
Spieler das Ausspielrecht.
Abb. 4: Mögliche Kombinationen: Linke Spalte: Einzelkarte, Paar, Trio, Fullhouse (v.o.n.u.) Rechte Spalte: Strasse, Treppe,
Bombe, Strassenbombe (v.o.n.u.)
6.5 Die Sonderkarten
Es gibt 4 Sonderkarten: Hund, Mahjong, Phönix und Drache.
Hund
Der Hund kann nur als einzelne Karte ausgespielt werden. Nach dieser Karte kann der Partner erneut eine beliebige Kartenkombination
ausspielen. Ist der Partner nicht mehr im Spiel, erbt der in Spielreihenfolge nächste Spieler.
Mahjong
Der Mahjong ist die 1. Wer diese Karte besitzt, beginnt das Spiel.
Der Mahjong kann als Einzelkarte mit dem Wert 1 gespielt oder
in einer Strasse eingebaut werden. Beim Ausspielen des Mahjongs
kann sich der Ausspieler einen Kartenwert wünschen (Bsp. 7 – keine
Farbe und keine Sonderkarten). Sobald ein Spieler eine Karte mit
diesem Wert spielen kann, ohne eine Spielregel zu verletzen, muss
er das tun.
Abb. 5: Hund
Abb. 6: Mahjong
Phönix
Der Phönix ist eine Art Joker. Er kann als Einzelkarte gespielt werden, wobei er ausgespielt einen Wert von 1,5 hat und ansonsten hat
er immer ein halbes mehr Wert als die Karte die zuvor gespielt wurde. Er kann aber auch als Joker in eine Kombination eingebaut werAbb. 7: Phönix
-19-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
den, in der er eine beliebige Karte ersetzt. Der Nachteil der Karte:
Sie gibt -25 Punkte.
Drache
Der Drache ist die absolut höchste Einzelkarte, auch höher als ein
auf ein Ass gespielter Phönix. Er gibt zwar 25 Punkte, der Stich darf
aber nicht zu sich genommen werden, sondern muss einem der beiden Gegner abgegeben werden.
Abb. 8: Drache
6.6 Bomben
Es gibt zwei Arten von Bomben: Vier Karten mit dem gleichen Wert oder eine Strasse
in derselben Farbe. Bomben können jederzeit gespielt werden, auch wenn man nicht
an der Reihe ist, und sind das absolut höchste. Nachdem ein Spieler eine Bombe gespielt hat, kommt der in Spielreihenfolge nächste Spieler nach ihm an die Reihe. Eine
Bombe kann nur mit einer höheren Bombe überspielt werden. Strassen-Bomben sind
höher als Vierer-Bomben. Strassen-Bomben mit mehr Karten sind höher als StrassenBomben mit weniger Karten. Ansonsten gelten die üblichen Regeln für die Höhe.
6.7 Das Ende einer Runde
Hat nur noch ein Spieler Karten, ist die Runde zu Ende. Der Spieler, der noch Karten
hat, gibt seine restlichen Handkarten an das Gegnerteam und seine Stiche an den Spieler, der als erster fertig wurde. Im Team werden nun die Punkte der Stiche zusammen
gezählt: Die 5er zählen 5 Punkte, die 10er und Könige je 10 Punkte, Phönix -25 Punkte
und Drache 25 Punkte, also total 100 Punkte.
Werden beide Spieler eines Teams als erstes nacheinander fertig, ist das Spiel ebenfalls
zu ende. Dieses Team hat dann einen sogenannten Doppelsieg erreicht und erhält 200
Punkte, während die Gegner leer ausgehen.
6.8 Das Ansagen
Das lustigste am ganzen Spiel ist das sogenannte Ansagen. Jeder Spieler hat die Möglichkeit, bevor er seine erste Karte ausspielt, ein Tichu anzusagen. Falls der Spieler
dann als erster fertig wird, bekommt sein Team 100 Punkte zusätzlich. Wird jedoch ein
anderer Spieler als erster fertig, bekommt das Team -100 Punkte.
Es gibt auch das „Grosse Tichu“, welches eigentlich genau gleich funktioniert wie das
normale „Tichu“, muss aber bereits vor dem Aufnehmen der 9. Karte angesagt werden
und gibt ± 200 Punkte.
Das „Grosse Tichu“ wird eigentlich nur relativ selten ausgesprochen, da es mit 8 Karten noch sehr schwierig abzuschätzen ist, ob man als erster fertig wird. Oft gibt es aber
die Situation, dass nur mit dem Aussprechen eines „Grossen Tichus“ der Gegner noch
eingeholt werden kann.
Das normale Tichu (auch „Kleines Tichu“ genannt) ist um einiges häufiger. Bei erfahrenen Spielern wird durchschnittlich etwa in 2 von 3 Runden ein Tichu ausgesprochen.
Da mit einem Tichu gleichviele Punkte erreicht werden wie mit den Stichpunkten, sind
für das Endresultat des Spieles oft nur die ausgesprochenen Tichus entscheidend.
-20-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
7 Wahrscheinlichkeitsberechnungen bei Tichu
Damit der Computer die Stärke einer Kombination abschätzen kann, muss er berechnen können, wie gross die Wahrscheinlichkeit ist, dass er mit dieser Kombination einen Stich macht. Diese Wahrscheinlichkeit entspricht der Wahrscheinlichkeit, dass die
beiden Gegner keine Kombination haben, mit der sie die Kombination des Computers
abstechen könnten. (Ein guter Tichu-Partner sticht den Partner nicht ab, wenn dieser
die Möglichkeit auf einen Stich hat.)
Die Wahrscheinlichkeit, dass die beiden Gegner keine höhere Kombination haben, ist
eins minus die Wahrscheinlichkeit, dass sie eine haben. Die Wahrscheinlichkeit, dass
sie eine haben, ist die Wahrscheinlichkeit für den Gegner 1 + die Wahrscheinlichkeit
für den Gegner 2 - die Wahrscheinlichkeit, dass beide eine haben.
Ich möchte nun zeigen, wie die Wahrscheinlichkeit, dass ein Gegner eine höhere Kombination hat, berechnet werden kann. Ich werde es am Beispiel des Trios machen und
von einem Spezialfall ausgehend immer allgemeiner werden. Dazu müssen aber zuerst
einige Variablen eingeführt werden, die das Wissen des Computers wiedergeben:
.
Nehmen wir an, in X gebe es nur noch ein Trio, das heisst nur noch von einem Kartenwert sind noch 3 Karten vorhanden, 4 sind an keinem Ort mehr vorhanden. Das noch
mögliche Trio habe die Höhe 10. Der Computer soll nun berechnen, wie gross die
Wahrscheinlichkeit ist, dass er mit seinem Trio mit der Höhe 3 einen Stich macht. Er
muss nun also berechnen, wie gross die Wahrscheinlichkeit ist, dass einer der beiden
Gegner dieses Trio hat. In diesem Spezialfall, indem nur noch ein Gegner ein Trio haben kann, darf er die Wahrscheinlichkeit für den Gegner 1 und die Wahrscheinlichkeit
für den Gegner 2 addieren. Die Wahrscheinlichkeit für einen Gegner berechnet sich als
Anzahl günstige Fälle über Anzahl mögliche Fälle. Die Anzahl günstige Fälle sind alle
Fälle in denen er die Kombination hat und die Anzahl mögliche Fälle sind alle seine
möglichen Hände. Um die günstigen Fälle zu berechnen, können aus X weitere 3 Karten abgezogen werden und auch von den Handkarten des Gegners, denn die 3 Karten
aus dem Trio muss er sicher haben. Für die restlichen Karten können noch beliebig
viele aus X ausgewählt werden:
.
Die möglichen Fälle lassen sich aus
-21-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
berechnen. Daraus kann die Wahrscheinlichkeit, dass ein Gegner das Trio hat, berechnet werden:
.
Die Berechnung für Gegner 2 erfolgt genau gleich und da in diesem Fall die Wahrscheinlichkeiten addiert werden dürfen, ergibt sich eine Stichwahrscheinlichkeit von
.
Erweitern wir den sehr einfachen Fall, dass nur ein weiteres Trio möglich ist auf 2.
Sagen wir es sei neben dem 10er-Trio auch noch ein 5er-Trio möglich. Die Wahrscheinlichkeit, dass einer der Gegner ein 10er-Trio hat, berechnet sich immer noch
gleich. Dazu kommt aber zusätzlich die Wahrscheinlichkeit, dass einer der Gegner
ein 5er-Trio hat. Auch diese kann man über die oben hergeleitete Formel berechnen.
Nun muss man vom erhaltenen Resultat noch die Wahrscheinlichkeit zweier Sonderfälle abziehen, da diese doppelt gerechnet wurden: Die Wahrscheinlichkeit, dass ein
Gegner beide Trios hat und die Wahrscheinlichkeit, dass die beiden Gegner je ein Trio
haben.
Die Wahrscheinlichkeit, dass ein Gegner beide Trios hat, lässt sich wie oben berechnen, nur dass er von den X Karten nun zwingend 6 bestimmte haben muss, also:
.
Die Wahrscheinlichkeit, dass die Gegner je ein Trio haben, heisst, dass jeder Gegner
nur ein Trio haben darf. Deshalb müssen in seiner Hand 3 Karten fix sein, aber aus X
müssen 6 Karten entfernt werden, da es dort ja zwei Trios gibt. Da bei beiden Gegner
ein Trio sein muss, muss man die beiden Werte multiplizieren:
.
Daraus folgt die kleine Formel für die Stichwahrscheinlichkeit eines Trios der Höhe 3,
wenn noch 2 weitere, höhere Trios möglich sind:
.
-22-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
Nun müsste man eigentlich auch noch weiter rechnen, denn im Tichu kann es bis zu
12 höhere Trios geben und der Computer müsste für jeden Fall die Wahrscheinlichkeit
ausrechnen können. Mathematisch ist es aber sehr aufwändig und am Schluss gäbe es
eine riesige Formel. Ich möchte darauf aufmerksam machen, dass wir auch den Fall
vernachlässigt haben, in dem von einer Kartenhöhe alle vier Karten in X enthalten
sind. Dann gibt es auf dieser Höhe 4 verschiedene Trios, die Formel für ein einzelnes
Trio müsste dann noch mit vier multipliziert werden und der Fall abgezogen werden,
in dem der Spieler alle 4 Karten hat.
Ich würde es mir zutrauen, mit genügend zeitlichem Aufwand alle 12 Formeln zur
Stichwahrscheinlichkeitsberechnung von Trios herzuleiten. Bei Paaren wird es jedoch
schon viel schwieriger, da es dort noch den Fall geben kann, dass beide Gegner je ein
Paar von der selben Höhe haben, der dann auch berücksichtigt werden müsste. Spätestens bei Strassen würde es aber definitiv zu kompliziert für mich, da es bereits mehrere Strassen gibt, wenn nur schon eine Karte der möglichen Strassen doppelt vorkommt
etc. Da es für mich aussichtslos erschien, für jeden Fall eine Formel zu finden, mit der
ich die Stichwahrscheinlichkeit aller Kombinationen berechnen könnte, habe ich mich
dazu entschieden, eine Annäherungsformel zu suchen.
7.1 Die Annäherungsformel
Bei der Annäherungsformel habe ich die Wahrscheinlichkeit jeweils für die beiden
Gegner einzeln berechnet. Dabei habe ich jeweils folgende Grundformel verwendet:
.
Dies stimmt für eine Kombination einer bestimmten Höhe, wenn es für diese Kombination nur noch eine Möglichkeit gibt. Da es jedoch für eine Kombination von einer
bestimmten Höhe (Bsp. Paar Höhe 7) auch noch mehrere Möglichkeiten geben kann
(Falls in X noch drei 7 enthalten sind, noch drei), wird diese Formel mit einem Faktor
multipliziert, der angibt, wie viele Karten es für jede Karte in der Kombination durchschnittlich noch zur Verfügung hat. Dieser Faktor berechnet sich aus
.
Danach wird diese Wahrscheinlichkeit für jede Kombination aufsummiert:
.
Die Stichwahrscheinlichkeit wird dann wie oben aus
-23-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
berechnet. Da die Formel nicht exakt ist, kann es vorkommen, dass die Wahrscheinlichkeit kleiner 0 ist. Da die Abschätzung aber nur bei grösseren Stichwahrscheinlichkeiten entscheidend ist, wird in einem solchen Fall die Wahrscheinlichkeit auf Null
gesetzt, da sie klein zu sein scheint.
Die einzige Wahrscheinlichkeit, die nicht direkt mit dieser Formel berechnet werden
kann, ist die Wahrscheinlichkeit von Fullhouses. Dort wird zuerst die Wahrscheinlichkeit ausgerechnet, dass einer der Gegner ein Trio hat und anschliessend mit der
Wahrscheinlichkeit multipliziert, dass einer ein Paar hat, natürlich nur, falls sie noch
fünf oder mehr Karten haben.
Diese Abschätzungen sind unexakt, wessen ich mir bewusst bin, aber sie dienen dem
Computer abzuschätzen, bei welchen Kombinationen er mit einem Stich rechnen kann
und bei welchen nicht, was ohne diese Formel nicht möglich wäre. Es wäre auch zu
untersuchen, wie sich Verbesserung dieser Formel auf die Spielstärke des Computers
auswirken würde.
-24-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
8 Das Projekt
Nach viel Theorie möchte ich nun zeigen, wie ich diese in der Praxis umgesetzt habe.
Das Ziel war es, ein Programm zu schreiben, das Tichu (möglichst gut) spielen kann.
Es sollte sowohl möglich sein, dass vier Spieler vom Computer gesteuert werden oder
nur drei und einer durch den Benutzer. Da Tichu relativ viele Regeln hat, musste ich
das Spiel etwas vereinfachen. Ich will nicht sagen, dass es unmöglich wäre, alle Regeln zu beachten, es hätte aber den Rahmen meiner Arbeit gesprengt.
8.1 Die Vereinfachungen
Die einzige Sonderkarte, deren Funktion ich vollständig umgesetzt habe, ist der Hund.
Er kann nur alleine ausgespielt werden und danach darf der Partner ausspielen. Beim
Mahjong habe ich die Funktion des Wünschens ausgelassen. Phönix und Drache sind
beide nur als Einzelkarten spielbar und haben bestimmte Werte (Phönix = Ass + 1,
Drache = Ass + 2), der Phönix gibt wie im Originalspiel -25 Punkte, der Drache +
25.
Bomben werden in meinem Spiel zwar als eigenständige Kombinationen behandelt,
sie können jedoch nur tiefere Bomben der selben Art überspielen. Natürlich können
sie wie jede andere Kombination ausgespielt werden.
Auch das Ansagen habe ich weggelassen, aber nicht primär wegen der schwierigen
Entscheidung, wann ein Tichu angesagt werden soll, sondern weil in einem Spiel mit
einem angesagten Tichu strategisch ganz anders gespielt werden müsste.
Bei der Planung wollte ich das Schupfen auch weglassen, habe es aber später noch
hinzugefügt, da das Schupfen der Teil eines Tichuspiels mit den am besten definierten
Strategie-Regeln ist.
Ansonsten funktioniert alles wie im Kapitel 6. Tichu beschrieben.
8.2 Die Realisation
Ich war mir bewusst, dass es nicht einfach sein wird, ein solches Programm zu schreiben. Deshalb habe ich darauf verzichtet, eine grafische Oberfläche zu programmieren.
Als ich vor 10 Monaten begonnen habe, eine erste Version des Programmes zu schreiben, hat mich die Taktik des Computers überhaupt nicht interessiert. Es ging mir darum, ein Programm zu schreiben, in dem der Computer nach den Regeln (mit meinen
Vereinfachungen) spielt. Der Computer hat also berechnet, welche Spielmöglichkeiten
er hat und daraus, mehr oder weniger zufällig, eine ausgewählt. Als dieses Programm
schliesslich fehlerfrei lief, habe ich begonnen mit Drools eine Spielstrategie des Computers zu entwickeln, was sich als grosse Herausforderung herausstellte. Bevor ich
jedoch darüber berichte, möchte ich den Aufbau des Grundprogramms erklären.
8.3 Der Spielablauf
Ein Tichu-Spiel ist ein Objekt vom Typ game. Dieses besitzt eine Funktion void start()
und void start(int runden). Diese Funktion startet das Spiel und regelt danach den
ganzen Spielablauf und gibt am Ende der Runde den Punktestand aus. Die beiden
Funktionen unterscheiden sich nur darin, dass die ohne Argument das Spiel beendet,
: Eine Strassenbombe mit 6 Karten kann nicht über eine Strassenbombe mit 5 Karten gespielt werden.
-25-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
sobald ein Team 1000 oder mehr Punkte erreicht hat, während die andere nach der in
runden angegebenen Anzahl Runden das Spiel beendet.
Für das Verteilen der Karten, das Schupfen und das Spielen werden dann die jeweiligen Funktionen aufgerufen. Falls ein Spieler vom User gesteuert wird, wird dazu
die Klasse userinterface.java verwendet, das Spielen des Computers übernimmt die
Klasse computerplayer.java.
8.4 Das Mischen der Karten
Da die 56 Karten zufällig auf die vier Spieler verteilt werden sollen, müssen sie zuerst gemischt werden. Dies sollte eigentlich zufällig geschehen, was der Computer
aber nicht kann. Was der Computer kann, ist Pseudozufallszahlen generieren, was für
das Mischen der Karten ausreichend zufällig ist. Mit der Funktion java.lang.Math.
random() können Zufallszahlen zwischen 0 und 1 generiert werden. Dieser Zufallsgenerator hat einen Ausgangszustand, der bestimmt, welche Zufallszahl zurückgegeben
wird. Gleichzeitig wird bei einem Funktionsaufruf aber auch anschliessend noch der
Zustand des Generators verändert, damit beim nächsten Mal eine neue Zahl ausgegeben wird und nicht immer dieselbe. Solche Algorithmen werden rekursive arithmetische Zufallszahlengeneratoren genannt.
Um die 56 Karten zu mischen, wird für die 1. Position eine der 56 Karten ausgewählt,
für die zweite, wird dann noch eine aus den verbleibenden 55 Karten ausgewählt. Dieser Misch-Algorithmus gewährleistet, dass jede Kartenreihenfolge gleich wahrscheinlich ist. Beim Verteilen spielt es dann also auch keine Rolle, ob der erste Spieler die
ersten 14 Karten bekommt oder die erste, die fünfte, die neunte etc.
8.5 Das Schupfen
Jeder Spieler wählt 3 Karten und ordnet diese dem Spieler zu, dem er sie schupfen
will. Haben dies alle Spieler getan, tauscht der erste Spieler mit jedem anderen Spieler
eine Karte aus, der zweite dann noch mit den zwei verbleibenden und der dritte muss
noch mit einem Spieler eine Karte austauschen. Danach müssen die Karten von jedem
Spieler neu sortiert werden und die möglichen Kombinationen neu berechnet werden.
8.6 Das Berechnen von möglichen Kombinationen
Das Suchen von möglichen Kombinationen ist ziemlich kompliziert. Bei Einzelkarten
natürlich nicht, bei Strassen, Treppen oder Fullhouses hingegen schon. Deshalb habe
ich mir die Mühe gespart, einen Algorithmus zu schreiben, der diese Kombinationen
findet, sondern habe die Karten in alle kombinatorisch möglichen Kombinationen aufgeteilt (Bei 14 Handkarten sind das
,
was 16‘383 ergibt.) und dann geprüft, ob es eine gültige Kombination ist oder nicht,
was viel einfacher ist, als das Suchen von Kombinationen. Im gleichen Schritt wird
dann auch noch gerade die Kombinationsart ermittelt, die in einem Integer gespeichert
wird. (Einzelkarte = 1, Paar = 2, Trio = 3, Quartett = 4, Treppe = 22, 222, ... 2222222,
Fullhouse = 23, Strasse = 5-14, Strassenbombe = 99999905 - 99999914)
-26-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
8.7 Das Prüfen von Kombinationen
Als erstes wird geprüft, ob die Sonderkarten richtig eingesetzt wurden, das heisst nur
der Mahjong darf in einer Kombination mit mehr als einer Karte sein, da die anderen
Sonderkarten nur als Einzelkarte eingesetzt werden können. Danach wird geprüft: Ist
die Länge der Kombination (d.h. die Anzahl Karten) eins, ist es eine Einzelkarte. Ist
die Länge zwei und beide Karten haben die gleiche Höhe, ist es ein Paar, bei drei
gleich hohen Karten ein Trio. Bei einer Kombination mit vier Karten muss unterschieden werden zwischen Doppelpaar und Quartett, haben alle Karten den gleichen Wert
ist es ein Quartett, haben die ersten zwei und die zweiten zwei je die gleiche Höhe und
unterscheiden sich in der Höhe um eins, ist es ein Doppelpaar. Auf diese Weise werden
dann auch noch Strassen, grössere Treppen und Strassenbomben gefunden. Falls keine
Kombination zugeordnet werden konnte, ist die Kombination ungültig und als Resultat wird -1 zurückgegeben. Es gibt auch eine Kombination ohne Karte, das Passen, die
den Wert 0 hat.
8.8 Wahrscheinlichkeit einer Kombination
Mit der unter 7 Wahrscheinlichkeitsrechnung bei Tichu hergeleiteten Formel, kann die
Stichwahrscheinlichkeit einer Kombination ungefähr berechnet werden.
Da dazu die Binomialkoeffizienten benötigt werden und Java dazu standardmässig
keine Methode bietet, musste ich diese selber schreiben. Auch die Funktion der Fakultät bietet Java standardmässig leider nicht. Da mein Programm aber bis 42! (42!
= 1.4·1051) rechnen können muss, reichen der Wertebereich der von int (-231 ... 231-1)
und long (-263 ... 263-1) bei weitem nicht aus. Für solche Fälle stellt Java die Klasse
BigInteger und BigDouble zur Verfügung, die es ermöglicht beliebig grosse Zahlen
darzustellen. Das Rechnen mit solch grossen Zahlen ist etwas gewöhnungsbedürftig,
da jede Rechenoperation eine Methode des Objektes ist.
BigInteger gross = new BigInteger.ValueOf( Math.pow(10, 10) );
gross = gross.multiply( gross.add( BigInteger.ONE ) );
Beispiel 8.1
Über die Methode ValueOf() kann ein BigInteger erzeugt werden, der dann den Wert
hat, der im Argument vom Typ long angegeben wird. Für die Werte 0, 1 und 10 gibt es
die direkte Möglichkeit ein Objekt zu erzeugen. Um einen BigInteger wieder zurück
in einen normalen Integer zu verwandeln (falls das möglich ist), bietet die Klasse die
Methode intValue(). BigDouble funktioniert analog zu BigInteger.
8.9 Die optimalen Kombinationen
Strategisch hat es sich als praktisch herausgestellt, die „optimalen“ Kombinationen
zu berechnen. In allen optimalen Kombinationen darf jede Karte der Hand nur einmal gebraucht werden. Eine Möglichkeit für die optimalen Kombinationen, wären 14
Einzelkarten. Es versteht sich, dass dies strategisch (in den meisten Fällen) sehr ungeschickt wäre. Je grösser eine Kombination, desto kleiner ist die Wahrscheinlichkeit,
dass jemand darüber spielen kann. Um die grössten Kombinationen zu finden, teilt das
Programm die Karten in Bereiche auf, in denen kein Wert fehlt.
-27-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
2r, 2g, 3r, 3g, 4b, 7g, 8r, 10r, Jr, Qs, Kr, Ks, Ph, Dr
2r, 2g, 3r, 3g, 4b | 7g | 9g, 10r, Jr, Qs, Kr, Ks | Ph, Dr
Beispiel 8.2
Danach wird in jedem Bereich einzeln geklärt, welches die optimale Kombination ist,
da nur die Fullhouses Karten aus mehreren Bereichen benötigen können, was später
berücksichtigt wird. Die Bereiche werden unterschieden in solche mit weniger als
fünf Werten und solche mit fünf oder mehr Werte. Im Beispiel 8.2 haben alle Bereiche
ausser der dritte weniger als fünf verschiedene Werte. In diesen Bereichen sind die einzigen möglichen Kombinationen Einzelkarten, Paare, Trios und Quartette. Für jeden
Wert wird also geschaut, wie viele Karten mit diesem Wert vorhanden sind und die
entsprechende Kombination als optimal gesetzt. Dabei muss noch überprüft werden,
ob Treppen bestehen. Für jedes Paar wird solange auf der nächsten Höhe geschaut, ob
dort auch ein Paar ist, bis dies nicht mehr der Fall ist.
2r, 2g, 3r, 3g, 4b
2r, 2g, 3r, 3g → optimal
4b → optimal
Beispiel 8.3
In den Bereichen mit mehr als fünf Karten ist es etwas komplizierter, da dort Strassen
möglich sind. Es ist aber nicht immer der Fall, dass Strassen optimale Kombinationen
sind, denn wenn mehr als die Hälfte der Karten doppelt vorkommen, gibt es weniger
Einzelkarten, wenn Paare gespielt werden. Es werden also die Einzelkarten gezählt,
die entstehen, wenn die Strasse gespielt wird und die Einzelkarten die entstehen, wenn
wie in kleinen Bereichen gespielt wird. Wenn es weniger Einzelkarten gibt, wenn die
Strasse gespielt wird, wird die Strasse auf optimal gesetzt. Bei jedem Wert wird anschliessend geschaut, wie viele Karten noch nicht gebraucht werden und diese auch
als optimale Kombination gesetzt. Wenn es beim Strasse Spielen mehr Einzelkarten
gibt, werden die optimalen Kombinationen wie in kleinen Bereichen gesetzt. Sollte
der Fall eintreten, dass bei beiden gleich viele Einzelkarten entstehen, wird die durchschnittliche Höhe der Einzelkarten errechnet und es wird so auf optimal gesetzt, dass
die durchschnittliche Höhe der entstehenden Einzelkarten möglichst gross ist.
9g, 10r, Jr, Qs, Kr, Ks
9g, 10r, Jr, Qs, Kr Ks → optimal
→ optimal
8r, 8s, 9r, 10s, 10r, Js, Jr, Qs, Qg
8r, 8s → optimal
9r → optimal
10s, 10r, Js, Jr, Qs, Qg → optimal
3r, 3g, 4r, 5b, 6r, 6b, 7s, 8r, 8g
3r, 4r, 5b, 6r, 7s, 8r
→ optimal
3g
→ optimal
6b
→ optimal
8g
→ optimal
Beispiel 8.4
Diese Aufteilung in optimale und nicht optimale Kombinationen ist zwar nicht schlecht,
aber sie könnte noch verbessert werden. Wenn beispielsweise viele tiefe Einzelkarten
-28-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
existieren, die optimal sind und ein hohes Paar, wird das hohe Paar besser einzeln
gespielt. Mein Algorithmus ist also ziemlich unflexibel und könnte noch verbessert
werden.
8.10 Die History
Die History ist eigentlich der Kern des Programms. Dort läuft das ganze Spiel ab, werden alle Spielinformationen gespeichert und auch die Ausgabe für den Benutzer wird
von dort aus gesteuert.
8.11 Das Userinterface
Falls ein Spieler nicht vom Computer gesteuert werden soll, übernimmt dies die Klasse userinterface. Sie besitzt die gleichen Methoden wie die Klasse computerplayer,
braucht aber zum wählen der Kombination nicht Regeln, sondern fragt den User. In
der Methode play(int wer, history history) werden alle zurzeit spielbaren Kombinationen ausgerechnet und zusammen mit einer Nummer ausgegeben. Der User braucht
dann nur die Nummer zu tippen, die er gerne spielen möchte.
Beim Schupfen funktioniert es eigentlich gleich, nur dass dort nicht die Kombinationen ausgegeben werden, sondern die einzelnen Karten.
8.12 Der Computerplayer
Der Computerplayer regelt die Strategie des Computerspielers. Falls der Spieler noch
Karten hat, werden die optimalen Kombinationen auf optimal gesetzt und alle Kombinationen dem Regelsystem übergeben. Danach regelt das Regelsystem das Spielen.
Hat der Spieler keine Karten mehr, wird er automatisch zum Passen gezwungen.
Allgemeineregeln.drl
In dieser Datei sind die Regeln gespeichert, die für alle Strategien benötigt werden.
Die erste Regel ist ganz einfach, aber wichtig. Sie sagt nämlich aus, dass der Spieler
passen soll, wenn er nicht spielen kann, das heisst keine Kombination hat, die über
die aktuell ausgespielte Kombination gespielt werden könnte. Danach werden die
aktuellen, optimalen Kombinationen in gute und schlechte aufgeteilt. Dazu wird ein
Schwellenwahrscheinlichkeitswert verwendet, alle Kombinationen die eine grössere
Stichwahrscheinlichkeit haben, sind gut, die anderen schlecht. (Wie der Schwellenwert
ermittelt wurde, siehe Kapitel 8.13. Schwellenwahrscheinlichkeitswert-Bestimmung.)
Bei den schlechten wird auch gleichzeitig geschaut, ob es eine gute Kombination von
der gleichen Art gibt, denn dann kann die schlechte ausgespielt werden und mit der
guten wieder gestochen werden. Je nach Ausgabe-Modus werden dann auch noch alle
Kombinationen zusammen mit ihrem Optimal-Wert, ihrer Wahrscheinlichkeit und der
Aufteilung in gut und schlecht ausgegeben.
Anschliessend folgt die jeweilige Spiel-Strategie des Computerspielers, welche ich
unter 8.15. Die Spielstrategien erklären werde.
Am Schluss sind noch einige Regeln, die nie ausgeführt werden sollten, aber notwendig sind, um das mogeln des Computers sicher zu verhindern. Falls in der spezifischen
Strategie nicht gespielt wurde, gibt es hier noch je eine Regel, die zufällig etwas ausspielt, spielt oder passt.
-29-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
8.13 Schwellenwahrscheinlichkeitswert-Bestimmung
Zur Ermittlung des Schwellenwahrscheinlichkeitswert liess ich zwei Teams mit verschiedenen Schwellenwahrscheinlichkeitswerten, aber der gleichen Strategie (defensiv) gegeneinander spielen. Da beim Tichu das Kartenglück eine sehr grosse Rolle
spielt, musste ich viele Runden spielen, um deutlich zu erkennen, welches Team besser spielt. Dazu habe ich viermal 200 Runden gespielt und geschaut, wer in den 200
Runden durchschnittlich mehr Punkt gemacht hat. Zuerst wählte ich die Werte 0.8
und 0.5, wobei deutlich herauskam, dass 0.5 der bessere Wert ist. In einem weiteren
Versuch wählte ich die Werte 0.6 und 0.5. Hier kam kein genaues Resultat heraus, da
je zweimal das Team mit 0.6 und zweimal das mit 0.5 besser war. Ich bin schliesslich
davon ausgegangen, dass der allgemein optimalste Wert deshalb irgendwo zwischendrin liegen wird und habe den Wert auf 0.55 gesetzt.
8.14 Die Endphase
In der Endphase, das heisst, wenn nur noch 2 Spieler im Spiel sind und zusammen weniger als 6 Karten haben, übernimmt eine andere Klasse das Spielen des Computers.
Die Klasse durchrechnen rechnet das Spiel mit allen möglichen Spielmöglichkeiten
der beiden verbleibenden Spieler durch und spielt danach die Kombination, mit der
durchschnittlich am Spielende am meisten Punkte erzielt werden.
Damit das Spiel durchgerechnet werden kann, muss der aktuelle Spielstand (d.h. die
History und die Spieler) kopiert werden und nach dem Durchrechnen wieder eingesetzt werden. Damit eine Klasse kopiert werden kann, muss sie serialisierbar sein.
Durch das Serialisieren einer Klasse, wird sie in ein Format gebracht, in dem sie in
eine Datei geschrieben werden oder über ein Netzwerk transportiert werden könnte.
Ist die Klasse in dieser Form vorhanden, kann man sie auch deserialisieren, also daraus
wieder eine normale Klasse erstellen.
Das Durchspielen aller Spielmöglichkeiten wird durch eine rekursive Methode erzielt.
8.15 Spielstrategien
Die strategischen Regeldateien haben alle den gleichen Aufbau: Es gibt drei Arten von
Regeln, die verschiedene Salience-Werte haben. Die als erstes geprüften Regeln sind
die, die entscheiden, ob der Spieler passen soll. Danach gibt es Regeln, die über das
Ausspielen entscheiden und solche die das normale Spielen regeln.
defensiv.drl
Die defensive Strategie war die erste, die ich entwickelt habe. In dieser Strategie
werden nur Kombinationen gespielt, die auf optimal gesetzt wurden. Haben sie eine
kleinere Stichwahrscheinlichkeit als der Schwellenwahrscheinlichkeitswert, werden
sie wann immer möglich gespielt, ansonsten nur, wenn jede schlechte Kombination
durch eine gute gedeckt ist. Beim Spielen einer Kombination wird immer darauf geschaut, dass die tiefst mögliche optimale Kombination gespielt wird.
Der Spieler spielt seine guten Karten also erst aus, wenn er seine schlechten losgeworden ist. Hat er keine schlechte Kombination ohne Deckung mehr (resp. beim Ausspielen max. eine), spielt er die Kombination aus, die die Deckung mit der besten
Stichwahrscheinlichkeit hat.
-30-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
offensiv.drl
Auch in der offensiven Strategie werden nur optimale Kombinationen gespielt, es wird
jedoch immer gespielt, wenn gespielt werden kann, egal ob die Wahrscheinlichkeit der
Kombination grösser oder kleiner als der Schwellenwahrscheinlichkeitswert, wird die
tiefste optimale Kombination gespielt. Gepasst wird also nur, wenn keine optimale
Kombination gespielt werden könnte.
Beim Ausspielen werden die Kombinationen gespielt, die keine Deckung haben. Sobald alle ausser eine Kombination gedeckt sind, wird die Kombination mit der besten
Deckung ausgespielt.
Offensiv vs. Defensiv
Wie bei der Schwellenwahrscheinlichkeitswert-Bestimmung liess ich ein Team mit
der defensiven Strategie und eines mit der offensiven gegeneinander spielen. Dabei
kam das heraus, was man mit einiger Überlegung auch hätte vorhersagen können: Das
offensive Team ist durchschnittlich über 200 Runden um 22.5 Punkte besser als das
defensive. Das Problem ist, dass das defensive Team sehr lange wartet bis es wirklich
beginnt zu spielen, dadurch macht das offensive Team auch schon mit tiefen Karten
Stiche und wird so oft vor dem defensiven fertig.
Ultraoffensiv.drl
Da ich herausgefunden habe, dass es besser ist, wenn offensiv gespielt wird, habe
ich noch eine ultraoffensive Strategie entwickelt. Diese spielt genau gleich wie die
offensive, spielt jedoch wenn keine optimale Kombination vorhanden ist, die tiefste
mögliche Kombination, auch wenn sie nicht optimal ist.
Ultraoffensiv vs. Offensiv
Schliesslich liess ich die ultraoffensive Strategie gegen die offensive spielen, um herauszufinden, welche besser ist. Dass die ultraoffensive Strategie so viel besser ist, hat
mich erstaunt. Durchschnittlich wurden pro Runde mit der ultraoffensiven Strategie
32.18 Punkte mehr erzeugt, was sogar noch mehr ist als bei Offensiv vs. Defensiv.
Das Problem ist jedoch wahrscheinlich, dass meine offensive Strategie immer noch
ziemlich defensiv ist, da nur optimale Kombinationen gespielt werden. Wie gut die
Ultraoffensive wirklich ist, kann ich nicht genau sagen, da ich kein wirklicher Vergleich habe. Da kein anderes Computerprogramm existiert, gegen das ich mein Programm testen kann und sehr viele Runden gespielt werden müssen, damit der Effekt
des Kartenglücks nur noch einen kleinen Einfluss hat, hatte ich keine Möglichkeit, die
wirkliche Stärke meines Programms zu testen.
8.16 Schupfen
Eigentlich wollte ich das Schupfen nicht implementieren, doch da ich beim Suchen im
Internet nach taktischen Regeln, immer anstelle von Tipps zum eigentlichen Spiel auf
Tipps zum Schupfen und Tichu ansagen gestossen bin, habe ich es trotzdem gemacht.
Wie das Spielen wird mit Regeln geschupft. Die Regeln zum Schupfen an den Gegner
sind ziemlich einfach: Man schupft die zwei Karten, die man am schlechtesten brauchen kann. Dies sind im Normalfall die zwei tiefsten Karten, die in keiner Kombination sind. Gibt es keine sehr tiefen einzelnen Karten, kann auch ein tiefes Paar auseinandergerissen werden und je eine Karte den Gegnern geschupft werden. Wenn es auch
kein solches Paar gibt, kann von einer langen Strasse die tiefste Karte weggeschupft
-31-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
werden, falls dadurch die Strasse aber nicht kleiner als fünf Karten lang wird.
Was dem Partner geschupft werden soll, ist umstritten. Da aber in meinem vereinfachten Spiel keine Tichus angesagt werden können, ist es meist angebracht, dem Partner
die höchste einzelne Karte zu schupfen.
8.17 UML-Diagramm von meinem Programm
-32-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
9 Fazit
Dass ich im Rahmen meiner Arbeit, nicht den perfekten künstlichen Tichuphilen programmieren werde, war für mich ganz klar. Schon vor der Arbeit war für mich offensichtlich, dass es nicht möglich ist, so gut zu spielen, dass jedes Spiel gewonnen wird,
da das Kartenglück einen viel zu grossen Einfluss hat. Trotzdem wäre es mein Ziel
gewesen, dass mein Programm in jeder Situation das spielt, was ich von ihm erwarten
würde, also ich (aufgrund des selben Wissens) auch spielen würde. Dadurch hätte der
Computerspieler mindestens so gut gespielt wie ich. Während der Arbeit wurde mir
aber immer klarer, dass ich auch dieses Ziel nicht erreichen würde. Obwohl ich mit
Drools eine einfache Möglichkeit gefunden habe, Strategieregeln aufzustellen, war es
mir nicht möglich, meine persönliche Strategie in Regeln zu verwandeln. Oft konnte
ich gar nicht begründen, wieso ich diesen Zug machte, ich also intuitiv spielte, was der
Computer nicht kann.
Ich will aber meine Arbeit nicht als völlig misslungen ansehen, denn ich habe mein
Hauptziel, ein Programm zu schreiben, das Tichu spielen kann, erreicht. Das Programm spielt zwar auf dem Niveau eines Anfängers, verstösst jedoch nicht gegen die
Spielregeln.
Die Arbeit war für mich auch sehr interessant, da ich neue Programmiermethoden kennen lernte. Auch glaube ich, dass ich selber seither besser Tichu spiele, da ich lernte,
das Spiel von einer ganz anderen Seite anzusehen und oft nach rationalen Gründen für
meine Taktik zu suchen, anstatt auf meine Intuition zu vertrauen.
Auf dem Markt gibt es bis heute noch kein Computerprogramm, gegen das man Tichu
spielen kann und das wird auch so bleiben. Möchte ich mein Programm verkaufen,
müsste ich sämtliche Spielregeln implementieren und auch die Strategie noch deutlich
verbessern. Doch was es nun gibt, ist jemand, der sich bereits mit dem Thema beschäftigte und das Problem auch ansatzweise löste.
-33-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
10 Quellenverzeichnis
10.1 Literatur
L1
Karl Kurbel (1989): Entwicklung und Einsatz von Expertensystemen. Eine anwendungsorientierte Einführung in wissensbasierte Systeme, 2. Auflage, ISBN
3-540-55237-5, Springer-Verlag, Heidelberger Platz 3, D-14197 Berlin
L2
Guido Krüger (2000), Handbuch der Java-Programmierung, 2. Auflage, ISBN
3-8273-1710-X, Addison Wesley Verlag, Martin-Koller-Strasse 10-12, D-81829
München
L3
Christian Ullenboom (2006), Java ist auch eine Insel. Das umfassende Handbuch, 5. Auflage, ISBN 3-89842-747-1, Galileo Press, Rheinwerkallee 4,
D-53227 Bonn
L4
Lars Wunderlich (2006): Java Rules Engines. Entwicklung von regelbasierten
Systemen, ISBN 3-935042-75-2, entwickler.press, Software & Support Verlag
GmbH, Geleitstrasse 14, D-60599 Frankfurt
L5
Urs Hostettler (1991): Tichu Spielanleitung, Fata Morgana Spiele, Güterstrasse
32, 3008 Bern
10.2 Internetadressen
I1
http://de.wikipedia.org/
I2
http://en.wikipedia.org/
I3
http://forum.chip.de/java-delphi-pascal/array-mischen-401401.html Anleitung
zum Misch-Algorithmus
I4
http://www.jboss.org/drools/documentation.html Drools Documentation, Version 4.0.4 (17.2.08)
10.3 Computerprogramme
C1 Drools, Version 4.0.4, http://www.jboss.org/drools/
C2 Eclipse SDK, Version 3.2.2, http://www.eclipse.org/
C3 Fat Jar Eclipse Plug-In, Version 0.0.27 , http://fjep.sourceforge.net/
10.4 Bildnachweis
Bild 1: Drools Documentation, http://www.jboss.org/drools/ (17.2.08)
Bild 2: Wikipedia, http://de.wikipedia.org/wiki/Urs_Hostettler (22.10.08)
Bild 3 - 8: Tichukarten von Fata Morgana
-34-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
11 Anhang
11.1 Resultate der Schwellenwahrscheinlichkeitswert-Bestimmung
Team 0/2 spielt mit 0.8, Team 1/3 mit 0.5
Jeweils 200 Runden
Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3
Punkte
11945
13255
10930
12370
10905
14895
11910
13190
Punkteschnitt pro
Runde
59.725
66.275
54.650
61.850
54.525
74.475
59.550
65.950
Team 0/2 spielt mit 0.6, Team 1/3 mit 0.5
Jeweils 200 Runden
Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3
Punkte
12110
12690
13090
12110
12335
12265
11115
13485
Punkteschnitt pro
Runde
60.550
63.450
65.450
60.550
61.675
61.325
55.575
67.425
11.2 Resultate Offensiv vs. Defensiv
Team 0/2 spielt offensiv, Team 1/3 defensiv
Jeweils 200 Runden
Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3
Punkte
16020
9580
15435
10065
13600
10500
14100
11000
Punkteschnitt pro
Runde
80.100
47.900
77.175
50.325
68.000
52.500
70.500
55.000
Durchschnittlicher Vor- 22.513
sprung von Team 0/2
-35-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
11.3 Resultate Offensiv vs. Ultraoffensiv
Team 0/2 spielt offensiv, Team 1/3 ultraoffensiv
Jeweils 200 Runden
Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3 Team 0/2 Team 1/3
Punkte
9100
15500
11390
14010
8405
16795
8585
16915
Punkteschnitt pro
Runde
45.500
77.500
56.950
70.050
42.025
83.975
42.925
84.575
Durchschnittlicher Vor- 32.175
sprung von Team 1/3
-36-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
11.4 Mail von Urs Hostettler
hallo simon
Seit gut einem halben Jahr arbeite ich an meiner Maturaarbeit, da ich im Sommer 2009 im Gymnasium Neufeld in Bern die Matura ablegen werde. Ich habe
mir zum Ziel gesetzt, ein Programm zu schreiben, das Tichu spielen können soll.
Das Programm funktioniert eigentlich schon ziemlich gut (ich habe das Spiel
jedoch etwas vereinfacht), einzig die Spiel-Strategie des Computers lässt noch
etwas zu wünschen übrig.
schön!
1. Wie ist Tichu wirklich entstanden? Waren Sie wirklich auf einer China-Reise
und haben das Spiel in Nanjing so kennen gelernt, wie es heute in der Schweiz
und in Deutschland gespielt wird?
was in der spielanleitung steht, stimmt.
wir haben noch einige extras hinzugefügt: spezialkarten, schupfen.
in china wird das spiel je nach gegend in verschiedenen versionen gespielt.
mit bridgekarten, wobei die herz 5 die rolle des drachens, der höchsten
einzelkarte, übernimmt.
2. Darf ich in meiner Maturaarbeit die Tichu-Karten vom Fata Morgana Verlag
abdrucken?
ja
3. Haben Sie, wenn Sie Tichu spielen eine bestimmte Strategie, die weder angesagte Tichus, noch Sonderkarten, das Abstechen des Partners oder das Schupfen
betrifft?
ich begreife die frage nicht ganz. da nimmst du ja fast alles, was eine
BESTIMMTE strategie ermöglicht/erfordert, aus.
4. Wissen Sie, seit wann Tichu in der Brettspielwelt.de spielbar ist?
nein, weiss ich nicht, sorry.
viel erfolg - sag nur, wenn ich was helfen kann
urs hostettler
-37-
Oktober 2008
Regelbasierte Systeme am Beispiel Tichu
Simon Rösch, 1MNd
11.5 Digitaler Anhang
-38-
Oktober 2008