Tetris AI

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Freitag 28. September 2007, 10:13

Ich wollte gerne einen Tetrinet-Bot haben, da ich gerne mal zwischendurch ein kleines Spielchen spielen moechte, ohne immer Internet-Zugang zu haben. Das Herz der Tetris-AI findet sich hier: Sourcecode. Man kann es als eigenstaendiges Programm ausfuehren und zusehen, wie das Programm allein vor sich hin spielt... (Windows-User sollten in der main-Methode das display_colour() durch display() ersetzen.)

Im Moment ist nur der Classic Mode implementiert, d.h. es gibt keine Spezialbloecke. Die AI basiert auf der Idee, zu einem zu plazierenden Block an allen moeglichen Positionen die leeren und besetzten Nachbarn mit bestimmten Gewichtungen zu zaehlen. Zu jedem moeglichen Tetris-Block speichere ich dazu drei "Matrizen": Eine fuer die Abmessungen des Blocks selbst, eine fuer die Gewichtung der besetzten Nachbarn und eine fuer die Gewichtung der leeren Nachbarn. Dieses einfache Prinzip funktioniert schon ziemlich gut, alleine spielt die AI eigentlich endlos.

Wenn man allerdings gegen die AI spielt, ist sie noch relativ einfach zu besiegen. Was die AI im Gegensatz zum Menschen noch nicht kann:
  • * An ueberlappenden Bloecken vorbeimanoevrieren
    * Den naechsten zu spielenden Block schon mit einbeziehen ("Vorschau")
    * Es darauf anlegen, mehr als eine Zeile auf einmal abzubauen
Das erste ist noch relativ einfach zu implementieren, der Rest schon ziemlich kompliziert. Naja, man kann die AI natuerlich auch dadurch schwerer zu besiegen machen, indem man sie sehr schnell spielen laesst. Oder man spielt gegen mehrere AIs im Team...
Zuletzt geändert von Rebecca am Dienstag 2. Oktober 2007, 15:29, insgesamt 1-mal geändert.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
abgdf

Freitag 28. September 2007, 11:47

Hallo,

muß erstmal begreifen, was das so macht ...
In Zeile 743 erhalte ich noch eine Fehlermeldung.
Meintest Du:

Code: Alles auswählen

if lines > 1:
    if lines < 4:
        addlines = lines - 1
    else:
        addlines = 4
?
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Freitag 28. September 2007, 11:53

Ja. Ab Python 2.5 kann man das in einer Zeile schreiben. :)
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

Freitag 28. September 2007, 12:39

Müsste ``addlines = max(lines - 1, 4)`` nicht auch gehen? Wenn man es denn unbedingt in einer Zeile haben möchte. :-)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Freitag 28. September 2007, 13:21

BlackJack hat geschrieben:max(lines - 1, 4)
Das waere immer 4...
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Freitag 28. September 2007, 15:37

Wie wärs mit:

Code: Alles auswählen

addlines = max(0, min(4, lines-1))

Gruss
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Dienstag 2. Oktober 2007, 15:35

Ich habe es jetzt erweitert, sodass auch an ueberhaengenden Bloecken vorbeimanoevriert werden kann, allerdings wird dabei der Block nicht nochmal gedreht.

Ich habe ein paar Unittests dafuer geschrieben, habe aber ein Problem mit failUnlessRaises:

Code: Alles auswählen

import unittest
import game

class Field(unittest.TestCase):    

    def test_add_line(self):
        field = game.Field()
        field.fill_random()
        self.failUnlessRaises(game.PlayerDeadException, field.add_line(),
                                  "Can't insert line into full field.")


if __name__ == "__main__":
    unittest.main()


Nach meinem Verstaendnis sollte der Test erfolgreich sein, aber ich bekomme einen Error wegen der geschmissenen PlayerDeadException:

Code: Alles auswählen

======================================================================
ERROR: test_add_line (__main__.Field)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test1.py", line 11, in test_add_line
    self.failUnlessRaises(game.PlayerDeadException, field.add_line(),
  File "/suse/home/rbreu/zeugs/python/tetribot/game.py", line 498, in add_line
    raise PlayerDeadException()
PlayerDeadException
:?:
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Dienstag 2. Oktober 2007, 15:48

Rebecca hat geschrieben:Ich habe ein paar Unittests dafuer geschrieben, habe aber ein Problem mit failUnlessRaises:
Nach meinem Verstaendnis sollte der Test erfolgreich sein, aber ich bekomme einen Error wegen der geschmissenen PlayerDeadException:
Vage Vermutung: Liegt es daran, daß nicht game.PlayerDeadException sondern PlayerDeadException geraist wird?
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Dienstag 2. Oktober 2007, 15:54

Bau ich den obigen Code um und fange die Exception ab:

Code: Alles auswählen

import unittest
import game

class Field(unittest.TestCase):    

    def test_add_line(self):
        field = game.Field()
        field.fill_random()
        try:
            self.failUnlessRaises(game.PlayerDeadException, field.add_line(),
                                  "Can't insert line into full field.")
        except Exception, e:
            print type(e)


if __name__ == "__main__":
    unittest.main()   
erhalte ich:

Code: Alles auswählen

<class 'game.PlayerDeadException'>
Das ist exakt dasselbe. (Oder ich habe Tomaten auf den Augen.)
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

Dienstag 2. Oktober 2007, 15:58

Vielleicht solltest Du `field.add_line` nicht aufrufen sondern nur übergeben!?
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Dienstag 2. Oktober 2007, 16:11

BlackJack hat geschrieben:Vielleicht solltest Du `field.add_line` nicht aufrufen sondern nur übergeben!?
Hehe, guter Tipp. Jaja, die Tomaten... War mich voll am Wundern, weil ich ja auch noch faelschlicherweise einen String mit uebergeben habe und er schon wegen falscher Anzahl von Paramter haette meckern sollen... :oops:
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Donnerstag 4. Oktober 2007, 14:52

D'oh! :)
Antworten