Open Source im professionellen Einsatz

Würfel-APIs bestücken

Die gleiche Schnittstelle implementiert auch Python-Entwickler Stefan Schwarzburg in der Funktion »turn()« seines Bots »xubuntix« und kommt dabei mit neun Zeilen Code aus (siehe Listing 3). Dort formuliert er drei Bedingungen, wann er würfelt, andernfalls gibt er ab. Das Muster dieser Einreichung wiederholt sich bei vielen Varianten, etwa bei »smitty« von Christoph Tenzer, der den gleichen Python-Wrapper namens »DiceBot« verwendet, aber dessen Schwellwerte etwas anders wählt (siehe Listing 4).

Listing 3:
»xubuntix« (Python)

01 def turn(self, mine, opp):
02     if opp>30 or (mine>40 and opp<20) or (mine>41):
03         self.roll()
04         return
05     elif sum(self.points) > 13:
06         self.save()
07     else:
08         self.roll()
09         return

Listing 4: »smitty«
(Python)

01 def turn(self, mine, opp):
02     if opp>30 or (mine>42 and opp<17) or (mine>40):
03         self.roll()
04         return
05     elif sum(self.points) > 13:
06         self.save()
07     else:
08         self.roll()
09         return

Rund 600 Zeilen kompakten Code benötigt C-Programmierer Simon Schuler für seinen Bot »polyflex«. Der Quelltext, der die »TURN«-Direktive behandelt, zeigt dass Entwickler in C viele Aufgaben von Hand umsetzen müssen, die in anderen Sprachen bereits eingebaut sind, etwa Netzwerksupport oder Regular Expressions (siehe Listing 5).

Listing 5:
»polyflex« (C)

01 void handle_turn(char *line) {
02       char *throwstr = "ROLLn", *savestr = "SAVEn";
04       int mecur;
05       if(last > 0) {
06              set_max(me,you,last);
07              last = 0;
08       }
09       turn = 1;
10       mecur = atoi(line + match[1].rm_so);
11       you = atoi(line + match[2].rm_so);
12       int cur = mecur - me;
13       int res;
14       char *msg;
15       if(cur >= get_limit(me,you)) {
16              msg = savestr;
17              me = mecur;
18              turn = 0;
19       } else {
20              msg = throwstr;
21       }
22       write_msg(msg);
23 }

Auf reichhaltige Bibliotheken und funktionale Programmierkonzepte greifen Haskell-Freunde zurück. Wie knapp sich damit nicht nur Algorithmen notieren, sondern auch Netzwerkverbindungen verwalten lassen, beweist der Ausschnitt aus den nur 80 Zeilen Code von Frank Recker, der damit den Bot »utz« verfasst hat (siehe Listing 6).

Listing 6: »utz«
(Haskell)

01   h <- connectTo "wettbewerb" (PortNumber 3333)
02 loop h z = do
03      f <- hGetLine h
04      putStrLn f
05      case (zerlege_string f) of
06        "HELO":_ -> helo h z
07        "TURN":x:y:_ -> turn h z (read x) (read y)
08        "THRW":x:_ -> thrw h z (read x)
09        [...]
10        _ -> error $ "loop: " ++ show f
11 
12 helo h Vor_Auth = sende h Nach_Auth "AUTH utz"
13

Er lässt sich dabei von Haskells Network-Package helfen [3]. Mittels »connectTo« holt er sich eine TCP-Verbindung zum Gameserver, iteriert über die Zeilen der Serverantworten und bearbeitet sie zeilenweise mit Hilfe von »hGetLine« in Zeile 9. Die folgenden Zeilen mit ihrem Case-Statement geben einen guten Eindruck von Haskells Arbeitsweise: Die Protokolleinheiten zerlegt die Sprache so, wie sie in der Spezifikation stehen. Passende Funktionen führen die jeweils nötige Arbeiten aus, wie ab Zeile 20.

Als Exot für die Netzwerkprogrammierung darf die Statistiksprache R gelten [4]. Das hielt Detlef Steuer nicht davon ab, seinen Bot »beatme« damit zu implementieren (siehe Listing 7). Verblüffenderweise hat er damit auch eines der kürzesten Programme abgeliefert, denn auch sein Code ist nur 80 Zeilen lang.

Listing 7: »beatme«
(R)

01 server <- "wettbewerb.linux-magazin.de"
02 port <- 3333
03 socket <- make.socket(server, port)
04 
05 load("Gp.Rdata")
06 
07 debug <-FALSE
08 ncat <- function(...) if (debug) cat(..., "n")
09 
10 dec <- function ( xa, xc, y) {
11   pass <- 1- Gp[y+1, y+1, xc+1]
12   wurf <- 1 - Gp[y+1, y+1, xa +1]
13   for (zahl in 1:5) {
14     if (xc+1+zahl > 50) wurf <- wurf +1 else  wurf <- wurf + Gp[xa+1, xc+1+zahl , y+1]
15   }
16   wurf <- wurf/6
17   if (pass > wurf) return(0) else return(1);
18 }
19 
20 myturn <- FALSE
21 while (TRUE){
22   server.message <- read.socket(socket)
23   command.lines<-strsplit(server.message, "n")[[1]]
24   for (lines in 1:length(command.lines)) ncat("SERVER:", command.lines[[lines]]  )
25   server.message <- command.lines[[ length(command.lines)]]
26   server.message<-strsplit(server.message, " ")
27   server.command <- server.message[[1]][1]
28   if (server.command == "DENY") break
29   if (server.command == "WIN") break
30   if (server.command == "DEF") break
31   if (server.command == "TURN") {
32     if (! myturn) {
33       myturn <- TRUE
34       xa <- as.numeric(server.message[[1]][2])
35       y <- as.numeric(server.message[[1]][3])
36       ncat("Spielstand zu Beginn:", xa, " ", y)
37       ncat("ROLL")
38       write.socket(socket, "ROLLn")
39     } else {
40       xc <-  as.numeric(server.message[[1]][2])
41       ncat("Spielstand:", xa, " ", xc, " ", y)
42       decision <- dec(xa, xc, y)
43       if (decision == 0 )
44          [...]

Sprachhits

Lag beim letzten Programmierwettbewerb [5] Python noch knapp vor Perl (18,7 Prozent der Einsendungen), so hat Larry Walls Skriptsprache diesmal hauchdünn die Nase vorn gegenüber 18,9 Prozent von Python. C++ bleibt auf einem komfortablen dritten Platz (14,6 Prozent). C und Bash (je 10,6 Prozent, zur Bash zählen auch einige hybride Sed- und Awk-Varianten) machen vermutlich wegen der Aufgabenstellung Plätze gut, dafür fallen Java (8,9 Prozent) und vor allem Ruby (3,3 Prozent) deutlich zurück. Für kleine Überraschungen auf dem siebten Platz sorgte einerseits PHP, sonst als Websprache bekannt (5,7 Prozent) und der funktionale Block, bestehend aus viel Haskell, etwas Lisp und ein wenig Scheme mit zusammen 4,9 Prozent. Außerhalb der Massenwertung standen die alte Lehrsprache Pascal, die sich im Java-Umfeld tummelnden Scala und Vala, die Wissenschaftssprache R sowie etwas Tcl (siehe Tabelle 2).

Tabelle 2: Top-10
der Sprachen

 

Platz

Sprache

Anteil

1

Perl

18,7%

2

Python

17,9%

3

C++

14,6%

4

C

10,6%

5

Bash

10,6%

6

Java

8,9%

7

PHP

5,7%

8

Funktionaler Block

4,9%

9

Ruby

3,3%

10

Sonstige

4,9%

Es ist aber nicht nur der Code, der Aufschluss über die Menschen hinter den Bots gewährt, sondern auch seine Bezeichnung: So verwendet jeder sechste Programmautor den eigenen Namen oder einen Teil davon bei der Anmeldung beim Spielserver. Ob das jedoch eine Kompensationshandlung für Elterngefühle gegenüber den eigenen Skripten ist oder schlicht der Wunsch, aufwändige Arbeiten an willfährige Maschinen zu delegieren, konnte noch niemand klären.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 4 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook