Möge Laplace mir helfen…
Über unseren Bloggerkollgen Patrick bin ich auf den Wettbewerb vom Linuxmagazin aufmerksam geworden. In diesem Programmierwettkampf geht es dabei um einen Bot, der in einem Glücksspiel besser abschneidet als der Bot des Gegners. Die Spielregeln sind einfach und auf der Hauptseite des Wettbewerbs erklärt:
Ein Spieler würfelt wiederholt und addiert seine Augenzahlen. Würfelt er eine sechs, verliert er seine gesammelten Punkte und der Mitspieler ist am Zug. Der aktive Spieler darf jedoch auch freiwillig an den Gegner abgeben: In dem Falle sichert er sich die bis dato gesammelten Punkte und fällt bei einer späteren sechs nur auf diesen Stand zurück. Wer zuerst 50 Punkte erreicht, gewinnt.
Klingt im ersten Moment gar nicht mal so schwierig. Ist es im Endeffekt auch nicht, wenn man die richtige Taktik wählt. Mittlerweile ist schon Einsendeschluss lange vorbei und die Auswertung hat begonnen. Die Veranstalter haben mittlerweile die Taktiken der besten Teilnehmer der Zwischenrunde gezeigt und erklärt, dabei ist mir aufgefallen, dass die von mir gewählte Taktik ebenfalls in der Spitzengruppe vertreten ist. Leider ist mein Bot bisher nicht in der Top 20, aber es freut mich, dass ich es rein theoretisch weit gebracht hätte. Es kommt hier meine Funktion play(), die entscheidet, ob gewürfelt wird, oder nicht.
Die Erklärung meiner Taktik
Nunja, man muss natürlich noch ein bisschen an den Werten arbeiten, um in der Spitzengruppe dabei zu sein. Im Grunde funktioniert es aber das so: Es wird ausgerechnet, wie groß die Wahrscheinlichkeit ist, dass auch in diesem Wurf KEINE sechs gewürfelt wird. Diese mathematische Wahrscheinlichkeit ($mathe) ist die Ausgangssituation für die Entscheidung. Der Prozentsatz wird allerdings im Nachhinein verändert, je nach Spielstand erhöht oder verringert. Liegt der Bot z.B. weit zurück, wird sie erhöht, bei großem Vorsprung verringert. Das hat zur Folge, dass je nach Spielsituation auf Risiko oder auf Sicherheit gespielt wird.
Diese Methode ist meiner Meinung nach sehr professionell, da hier vergleichsweise einfach Erweiterungen implementiert werden können. In meiner Ausführung ist z.B. die Taktik des Gegners nicht berücksichtigt. Da eine Runde nur bis 50 Punkte geht, fand ich die Taktik des Gegners vernachlässigbar. Wären die Gewinnpunkte deutlich höher, würde es sich sicherlich lohnen, seine eigene Taktik an die des Gegners anzupassen.
Außerdem kann man sehr einfach dem Bot sagen, wie riskant er spielen soll, indem man die Variable „gewinnchance“ verändert. Denn nachdem das Skript die mathematische Wahrscheinlichkeit nach den oben genannten Gesichtspunkten verfälscht hat, wird verglichen, ob die rechnerische Wahrscheinlichkeit noch größer ist, als die Grenzwahrscheinlichkeit. In diesem Fall wird gewürfelt, andernfalls gesichert. Um hier den besten Wert zu erhalten, habe ich gleich mehrere Bots auf die Testserver geworfen, so dass sie gegeneinander spielten. Dabei kam heraus, dass in über 500 Spielen der Bot mit 32% Gewinnwahrscheinlichkeit der erfolgreichste war.
Das Skript
Der Bot wurde in Bash programmiert. Hätte ich etwas mehr Zeit mit experimentieren verbracht, hätte ich die Werte für die Wahrscheinlichkeitsumrechnungen optimieren können. Doch mit dem jetzigen Wettbewerbsverlauf bin ich mehr als zufrieden, denn dabei sein ist schließlich alles! 🙂
name="bejonet" zahl="0" gewinnchance="32" #hier in ganzzahligen % angeben, wie groß die Gewinnchance mindestens sein muss um zu würfeln. mathehundert="0" play() { sechstel=$(echo "scale=2 ; 1/6 " | bc ) taktik=$(echo "scale=2 ; 5/6" | bc ) #taktik: 1 = wuerfeln!; 0 = nicht wuerfeln! standard: 0.83 meine="$1" seine="$2" differenz=$(echo "scale=2 ; $meine-$seine" | bc ) if [ "$meine" == "0" ] then taktik=1 zahl=1 fi mathe=$(echo "scale=2 ; (5/6)^$zahl" | bc ) taktik=$mathe if [ "$seine" -gt "40" ] then taktik=$(echo "scale=2 ; $taktik*1.5" | bc ) fi if [ "$seine" -gt "45" ] then taktik="1" fi if [ "$meine" -gt "40" ] then if [ "$differenz" -gt "25" ] then taktik=$(echo "scale=2 ; $taktik*0.75" | bc ) fi fi if [ "$differenz" -lt "-15" ] then taktik=$(echo "scale=2 ; $taktik*1.5" | bc ) fi if [ "$differenz" -lt "-2" ] then taktik=$(echo "scale=2 ; $taktik*1.2" | bc ) fi if [ "$meine" -gt "48" ] then mathehundert=$(echo "scale=0 ; $mathe*100" | bc ) mathehundert=$(echo "scale=0 ; $mathe/1" | bc ) taktikhundert=$(echo "scale=0 ; $mathehundert/1" | bc ) if [ "$mathehundert" -gt "40" ] then taktik="1" else taktik=$(echo "scale=2 ; $taktik*1.5" | bc ) fi fi if [ "$zahl" == "0" ] then taktik="1" fi taktikhundert=$(echo "scale=0 ; $taktik*100" | bc ) taktikhundert=$(echo "scale=0 ; $taktikhundert/1" | bc ) if [ "$taktikhundert" -gt "100" ] then taktik="1" fi ## hier wird gewuerfelt ## taktikhundert=$(echo "scale=0 ; $taktik*100" | bc ) taktikhundert=$(echo "scale=0 ; $taktikhundert/1" | bc ) if [ "$taktikhundert" -gt "$gewinnchance" ] then echo "ROLL" zahl=$(echo "scale=0 ; $zahl+1" | bc ) else if [ "$zahl" == "0" ] then echo "ROLL" else echo "SAVE" zahl="0" fi fi }
Bildquellen für das Featured-Bild: Flickr von Jeff Golden, Wikipedia: Laplace
Schreibe einen Kommentar