Kommentare 1

Spielen mit Perl – irgendwie…

In diesem Beitrag unserer kleinen Perl-Reihe zeigt Renée Bäcker, wie Spielen noch mehr Spaß machen kann: Wenn man es nämlich automatisiert und so nebenbei noch die Automatisierungsmöglichkeiten von Perl erproben kann. Dann mal auf die Plätze, fertig, los:

Nein, heute geht es nicht darum, Spiele mit Perl zu programmieren – darum kümmern sich andere. Ich möchte heute in ein Thema einsteigen, für das Perl bekannt ist: Automatisierung. Aber was haben Spiele mit Automatisierung zu tun? Ganz einfach: Man kann auch automatisiert spielen.

Unter Windows ist eine der „Killer-Applikationen“ das Spiel „Minesweeper“. Ich habe das eine zeitlang gespielt, aber irgendwann war es wenig interessant. Also musste das Spiel interessanter gestaltet werden: Ich möchte nicht mehr selbst spielen, sondern der Computer soll das für mich tun. Ich bin dann auch gleich auf CPAN fündig geworden. Paul Fenwick hat das Modul App::SweeperBot geschrieben. Also per CPAN-Shell installiert und ausprobiert. Herrlich, wie man sich jetzt in der Mittagspause bei einem Minesweeper-Spiel so richtig gut erholen kann.

Wie hat Paul das gemacht? Paul Fenwick benutzt für die Hauptaufgaben die Module Win32::GuiTest, Image::Magick und Win32::Screenshot.
Als erstes wird Minesweeper gestartet:

    Win32::Process::Create(
        my $minesweeper,
        "$ENV{SystemRoot}\\system32\\winmine.exe",
        "",
        0,
        NORMAL_PRIORITY_CLASS,
        "."
    ) or croak "Cannot spawn minesweeper! - ".
        Win32::FormatError(Win32::GetLastError());

Danach wird mit Win32::GuiTest das Minesweeper-Fenster lokalisiert und werden die Koordinaten ermittelt

    our $id=(FindWindowLike(0, "^Minesweeper"))[0];
    our($l,$t,$r,$b)=GetWindowRect($id);

Minesweeper ist nicht ganz so einfach zu automatisieren, weil bei jeder neuen Runde das Spielfeld neu aufgebaut ist und die Minen an anderen Stellen liegen. Diese „Zufallskomponente“ führt dazu, dass immer wieder ein Screenshot des Spiels gemacht und mit ImageMagick analysiert wird.

    my $image=CaptureRect(
        $l+SQUARE1X+($sx-1)*SQUARE_W,
        $t+$Square1Y+($sy-1)*SQUARE_H,
        SQUARE_W,
        SQUARE_H
    );
    my $sig = $image->Get("signature");

Mit Hilfe der Methoden aus Win32::GuiTest werden dann die einzelnen Felder angeklickt, wenn diese keine Mine enthalten können.

    $this->click(
        $l+SQUARE1X+($sx-1)*SQUARE_W+SQUARE_W/2,
        $t+$Square1Y+($sy-1)*SQUARE_H+SQUARE_W/2,
        $button
    );

App::SweeperBot zeigt, dass mithilfe des nahezu unerschöpflichen CPANs auch eine Aufgabe, wie Spiele zu automatisieren, relativ leicht zu realisieren ist.

Bei Spielen, die immer gleich ablaufen und keine Zufallskomponente haben, ist die Automatisierung besonders einfach. Ich habe mir zum Spaß ein paar Online-Gewinnspiele von größeren Unternehmen angeschaut und habe dann angefangen, Code für diese Spiele zu schreiben. Am Gewinnspiel habe ich aber nicht teilgenommen, weil ich ja nur beim Programmieren meinen Spaß haben wollte.

Für die Automatisierung habe ich auch das Modul Win32::GuiTest genommen. Damit lässt sich alles simulieren, was man mit Tastatur und Maus so anstellen kann.

Als erstes muss ich das Spiel starten und genau wie beim SweeperBot wird ein Prozess gestartet, nur dass es diesmal der Browser ist. Das Testspiel ist ein einfaches Spiel mit 4 Fragen und jeweils 3 Antworten. Ich muss also die Maus zu einer Checkbox hinter der richten Antwort bewegen und dort dann klicken. Dann kommt automatisch die nächste Frage. Nachdem der Browser gestartet wurde, kann das Spiel losgehen… Beim Schreiben des Programms muss man das Spiel immer wieder ausprobieren, damit man die Koordinaten bekommt, zu denen die Maus bewegt werden muss.

Der folgende Code ist der komplette Code, um das Spiel automatisiert zu spielen. Nur der Code für den Prozessstart wurde ausgelassen. Insgesamt sind es inklusive der Kommentare und mit großzügigen Zeilenumbrüchen keine 50 Zeilen Code.

    # get window
    my ($window) = FindWindowLike( 0, "Mozilla Firefox" );

    my @coordinates = (
        [ 440,485 ],
        [ 440,420 ],
        [ 440,452 ],
        [ 440,510 ],
    );

    for my $coordinate ( @coordinates ) {
        # move mouse to correct answer
        MouseMoveAbsPix( @$coordinate );

        # click on checkbox
        SendMouse('{LEFTCLICK}');

        sleep 4; # wait for next question
    }

Dieser Blog-Beitrag sollte zeigen, dass man mit Perl sehr leicht Programme automatisiert ausführen lassen kann. Ernsthafte Anwendungen können so Programmabläufe simulieren. Ich habe damit z.B. schon wxPerl-Anwendungen getestet.

Die Win32::GuiTest-Dinge lassen sich auch nach *NIX portieren, da für X11-Systeme das Modul X11::GUITest existiert. Über letzteres Modul gibt es auch einen Artikel in der 10. Ausgabe des Perl-Magazins.

Über den Autor: Renée Bäcker ist seit 2002 begeisterter Perl-Programmierer und seit 2003 selbständig. Auf der Suche nach einem Perl-Magazin ist er nicht fündig geworden und hat selbst das Perl-Magazin “$foo” gestartet. In der Perl-Community ist Renée recht aktiv – als Moderator bei Perl-Community.de, Organisator des kleinen Frankfurt Perl-Community Workshop und Mitglied im Orga-Team des deutschen Perl-Workshops.

Sag's weiter:

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert