 Gut, fangen wir an, würde ich sagen. Nachdem wir anscheinend kein Herald haben, muss ich uns vorstellen. Ich bin der Thomas Alias Sifrik und neben mir steht der Hubert Alias Xor und wir sind vom Beitwerk, dem Hacker Space in Ingolstadt. Genau, wir waren ja letztes Mal schon hier gestanden und haben die Schlangenprogramm hier nach präsentiert. Dieses Jahr gibt es die Version 2.0. Genau, kurz worum geht es hier überhaupt? Wir spielen Multiplayer Snake nach dem Vorbild von sliver.io. Das heißt, man hat mehrere Schlangen auf dem Spielfeld, die Futter fressen und dadurch größer werden und natürlich ist das Ziel, möglichst viel zu fressen, möglichst groß zu werden und dabei nicht mehr anderen zu kollidieren, weil sonst stirbt man. Genau, nachdem das hier ein Programmierspiel ist, spielen wir natürlich nicht saver. Das heißt, unsere Schlangen laufen autonom und es gibt keine Benutzer-Interaktion. Wie gesagt, wir waren letztes Jahr schon da, hier ein kurzer Rückblick. Letztes Jahr haben wir in Lua programmiert. Wir hatten am Ende ungefähr 350 laufende Bots und leider nur fünf Frames pro Sekunde. Genau, das soll dieses Jahr auf jeden Fall besser werden. Genau, deswegen zu den neuen Features. Ich habe ein neues Backend programmiert auf Docker-Basis. Das heißt, die Bots laufen jetzt in Docker als eigenständige Programme. Deswegen haben wir auch die Programmiersprache wechseln können und zwar auf C++. Klingt jetzt vielleicht schlimmer als es ist, weil wir haben euch ein nettes Framework gebaut, das alles wegabstrahiert, was irgendwie kompliziert sein könnte. Wir haben auch die IDE überarbeitet. Da gibt es jetzt Build Logs und es sieht auch besser aus. Der Bot bekommt mehr Infos über die Server-Einstellungen. Das heißt, man kann jetzt mehr Sachen auslesen, wie zum Beispiel, wie schnell das Futter auf dem Feld verrottet. Das heißt, wie lang es noch existiert, wo man da hinkommt, bevor es weg ist zum Beispiel. Und zu guter Letzt kriegen die Bots jetzt Persistentenspeicher, nämlich vier Kilobyte aktuell. Die kann man zum Beispiel für Maschinen-Learning oder sowas benutzen, falls sich das wer geben will. So zur Umgebung für den Bot. In dem Docker ist ein G++ installiert, der auf API Linux läuft mit den Compiler-Flex, die wir hier sehen. Damit wird der Bot kompiliert. Die sind absichtlich ein bisschen ausführlich gestaltet mit wie all und pedentik, damit ihr seht, wo Probleme sein könnten. Es gibt nämlich keine Möglichkeit, den Bot live zu debacken. Wie vorher schon erwähnt, haben wir eine Abstraktionsschicht gebaut, die der Bot sieht. Die abstrahiert so ungefähr alles weg, was mit dem Game Server zu tun hat, sodass ihr nur noch die Daten kriegt, die für den Bot relevant sind. Ja, ich denke, das schaut euch am besten selber an, wie da die API ist. Ich denke, für Z++ ist es so einfach wie möglich. Genau. So, damit ihr nicht den Server alarm legt, gibt es natürlich Ressourcenbeschränkungen. Das heißt, ihr könnt eine CPU benutzen, das heißt einen Kern im Endeffekt. Ihr habt 32 Megabyte RAM, keinen Swap. Das Dataisystem wird nur lesbar sein, außer Slash Temp und Slash RAM. Das sind allerdings RAM-Discs. Das heißt, wenn ihr da reinschreibt, zählt es zu eurem RAM-Linit. Es gibt natürlich keinen Netzwerk, ihr solltet ihr mit anderen Bots absprechen können. Und der Server erwartet, dass der Bot nach 10 Millisekunden antwortet. Wenn das nicht passiert, wird eure Rückgabe für den Frame ignoriert. Und wenn es zu oft passiert, ich glaube aktuell sind es 30 Mal in Folge, dann wird euer Bot beendet und neu gestartet. Genau. Ja, dann wollte ich ein bisschen was zu unserem Backend erzählen dieses Jahr, weil wir sonst die Zeit für den Vortrag nicht voll kriegen. Und außerdem ist es schön kompliziert, da denke ich, kann man was draus lernen. Vielleicht auch, wie man es nicht macht. Genau. Auf der linken Seite seht ihr den Browser, das ist eure Benutzerschnittstelle, da läuft die ID-Iterie und der Fior. Und da ist quasi auch schon Ende bezüglich eurer Software. Danach kommt unsere Software. Die besteht zum einen aus Standardmodulen, das sind die blauen Sachen. Da haben wir den EngineX-Eis Reverse Proxy, eine Maria DB-Eis Datenbank und Docker. Und die Orangenkästen sind unsere Teile. Zum einen ist das die Website, das ist eine Django-Seite, der Release-Server, der ist dafür zuständig die Last auf die Clients zu verteilen. Das heißt, der ist sozusagen zwischen Schicht, zwischen den vielen Brausern, die da verbunden sein werden und dem Game Server, damit der Game Server abgeschirmt wird und keine Lastprobleme bekommt. Dann gibt es natürlich den Game Server selber, der ist für alles zuständig, was das Spiel betrifft. Das heißt, der führt die Bots aus, der verarbeitet die Kollisionen, das Fressen von Futter und halt alles, was dazugehört. Genau. Und der kommuniziert vor allem mit Docker und der Datenbank. Das werden wir auch noch sehen, wie das läuft. Genau. Rechts haben wir noch den Docker Bilder. Der ist dafür zuständig, den Code zu bauen, bevor der Game Server ihn ausführt. Das passiert nebenan, damit einfach der Game Server Asynchron arbeiten kann zu den Bildprozessen. Das heißt, die Bildprozesse blockieren nicht das Spiel. Ja, dann gehen wir mal ein paar Fälle durch. Zum Beispiel, was passiert eigentlich, wenn man neuen Code hoch lädt. Das sieht dann so aus. Los geht es natürlich im Browser auf der linken Seite. Ihr klickt auf ran und dann wird euer Code erst mal durch den Engine X durch die Webseite in die Datenbank geschrieben. Von da holt es irgendwann der Docker Bilder ab. Der fragt so alle zwei Sekunden nach, was es neues an Code gibt. Schreibt den Code ins Dateisystem und führt Docker ran aus mit dem Bildcontainer. Was man hier dann sieht, der Bildprozess, der arbeitet auf dem, auf dem, was hier framework heißt, das ist diese Abstraktionsschicht, von der ich vorher gesprochen habe. Da wird euer Code eingefügt, das dann durchkompiliert und raus fällt hoffentlich ein binary, das wieder im Dateisystem abgelegt wird. Natürlich kann das mal schiefgehen, wenn man einen Tipfieler oder so hat. Dann kommt kein binary raus, sondern nur der Bildlog. Der wird vom Docker Bilder zurückgelesen. Der Bildlog ist einfach nur, was der Compile-Prozess so ausgibt. Und der Docker Bilder speichert das zusammen mit dem Exitcode in die Datenbank und von da könnt ihr das wieder abfragen über die Webseite. Genau. So, jetzt haben wir den Code gebaut, jetzt muss wir ihn ausführen. Dazu fragt der Game Server regelmäßig ab, welche Bots überhaupt aktiv sind oder aktiv sein sollten, besser gesagt. Das gleicht er dann mit einer internen Liste ab, weil er weiß, welche gerade laufen und alle, die aktiv sein sollten und nicht laufen werden dann ausgeführt. Dafür legt er zuerst zwei Kommunikationsschnittstellen an für den Bot. Zum einen ein Shared Memory, das ist einfach POSIX Shared Memory, das heißt eine Datei auf TempFS, die mit M-Lab gemountet wird. Da passiert die meiste Kommunikation drüber. Also da wird das, was hier lokaler Welts Zustand heißt, reingespeichert. Zum Beispiel, welches Futter kann der Bot sehen, welche anderen Schlangensegmenten sind in der Nähe. Das schreibt der Game Server jeden Frame da rein. Und zwar nur das, was der Bot tatsächlich in Reichweite hat. Der Bot wiederum kann da Sachen reinschreiben, wie die Farben, die er haben will, also die Farben der Schlange und ja, so viel zum Shared Memory. Übers Unix Socket wird der Bot getriggert, jeden Frame. Das heißt, das wird ihm gesagt, jetzt rechnen wir mal, hier sind neue Daten. Der Bot rechnet dann und gibt den neuen Winkel und ja, zurück oberboosten will. Genau. Das Binary für den Bot-Prozess kommt natürlich aus dem Dateisystem, wo wir es vorher abgelegt haben. Jetzt wollen wir auch was von dem Ganzen sehen. Da kommt jetzt der Release Server ins Spiel. Der Game Server generiert sogenannte Welt Updates. Da steht alles drin, welche Bots sich wie bewegt haben, ob sie boosten, welches Votagart existiert. Das schickt er dem Release Server als Message Pack codiert. Einfach Message Pack, weil es effizient und schnell ist. Der Release Server liest es ein und liefert an jeden Kleint dann per Web Socket einen Chasen Stream aus. Jetzt Chasen, weil es einfach im Browser dekodierbar ist. Wir haben es auch mit Message Pack probiert, das ist auch sehr langsam ein Chavascript. Deswegen codiert der Release Server das um. Ja, genau. Das Web Socket wird durch den Engine X geproxied und landet so in eurem Browser. Der Code für den Viewer, der kommt von der Webseite. Das ist das, was hier als HTML etc. steht. Und ja, dann gibt es noch andere Daten, nämlich so Statistik-Sachen vor allem. Wie zu jeder Schlange, die gestorben ist, wird zum Beispiel gespeichert, wer sie getötet hat, also mit wem sie kollidiert ist, wie viele Punkte sie zu dem Zeitpunkt gehabt hat, wie viele Punkte sie maximal gehabt hat, während ihrer Lebenszeit. Das wird in der Datenbank gespeichert und zusätzlich allgemeine Statistiken, wie viele FPS hat der Server gerade. Ja, genau. Die Webseite kann dann daraus Auswertungen ziehen, wie zum Beispiel die Highscroll-Listen. Ja, so viel zum Backend. Und jetzt würden wir euch noch eine kurze Demo vom aktuellen System zeigen, die auf diesem Laptop läuft. Und zwar mit den Bots, die während der Entwicklungszeit so entstanden sind. Genau. Dafür würde ich kurz den Game Server starten und dann an den Hubert übergeben. Genau. Das heißt jetzt Demo. Ich starte den Game Server. Der startet jetzt so langsam die Bots. Und dann kann man hier klicken und es geht hoffentlich. Jo, hallo. Ich tu jetzt mal so, als hätte ich dieses Jahr auch groß mitprogrammiert. De facto habe ich im Wesentlichen ein bisschen an der Webseite gearbeitet. Ihr seht die Startseite, die ihr hoffentlich auch seht, wenn ihr demnächst auf Schlangenpunktbytewerk.org geht. Im Moment kämpfe ich noch ein bisschen. Das hat, glaube ich, auch mit dem Netz hier zu tun. Trotzdem schon mal Kudos an Herbert, der uns geholfen hat, unseren Programmierserver überhaupt hier noch rechtzeitig ans Laufen zu bringen. Also kurz nach dem Vortrag soll es hoffentlich für alle funktionieren. Und das, wenn ihr auf Schlangenpunktbytewerk.org schaut, solltet ihr daraus kommen. Was kann man auf der Webseite machen? Als erstes Mal kann man ohne, dass man irgendwie selber groß interagiert, auf Watch gehen. Dann sieht man das, was man dann hoffentlich auch bei uns auf dem Beamer sieht. Man sieht also jetzt die Schlangen. Ich kann auch auf einzelne Namen klicken, hoffe ich, wenn ich sie erwischt. Dann folgt das Server einer Schlange, dann kann man auch reinzoomen und kann sehen, was die tut. Ich weiß jetzt nicht, was dein Code tut, aber im Wesentlichen wird die Schlange einfach in jedem Frame. Wie gesagt, aktuell ist es limited bei 60 Frames. Es läuft mit maximal 60 Frames pro Sekunde und in jedem Frame schaut diese Schlange eben, was ist denn um mich herum? Was gibt es denn dafür ein Futter? Gibt es Gegner, wenn ja, wo sind die Hilfe? Ich weiche mal aus oder im Idealfall, wenn sich jemand die Arbeit macht heuer. Oh, da ist ein Gegner und ich bin größer als der. Ich versuche den einzugreisen und kann ihn danach aufressen. Also das ist der Spaß für alle, die nicht programmieren wollen. Man kann dazuschauen. Rechts sieht man die Statistiken, welcher Bot ist gerade der Größte? Wie viel hat er gefressen? Wie viel von dem Futter, das er gefressen hat, kommt von Schlangen, die er vorher selber getötet hat, also sprich, die in ihn reingerannt sind? Oder sie? Gut, wir sind jetzt schon eingeloggt. Wenn ich mich da kurz auslogge, kommen wir da wieder rein. Ich logge mich mal aus, dann sieht das so aus. Also dann kann man auch zuschauen. Aber man kann sich auch einloggen oder einen neuen Account anlegen. Vielleicht würde ich das glaube ich mal tun. Schön. Ich könnte sein, dass der Damm neu genug ist. So, ich speichere. Wenn ich mich einlogge, komme ich in dem raus, was wir IDI nennen. Das ist auch das, was hier oben unter Code erreichbar ist. Wir sehen zu linken ein JavaScript Standard Code Editor, in der schon mal ein Beispielskript ist, das allerdings nicht viel tut, außer Teile der AP herzuzeigen, so wie man sie benutzen würde. Dann sieht man im Unterbereich jetzt neu ein Fenster, was sieht man im Ausgabe her? Ein Fenster mit den Ausgaben vom Compiler oder halt mit dem Build-Log. Und außerdem ganz stimmt es nicht, dass man das Ding nicht live debaggen kann sein. Man kann schon Log-Ausgaben machen. Im begrenzten Maße, wie das Rate-Limiting dazu funktioniert, weiß ich gerade nicht. Ihr könnt alle fünf Rames eine Nachricht ausgeben oder 50 am Stück, wenn ihr lang genug keine Nachrichten ausgibt. Also es geht darum, einfach auf die Bandbreite zu beschränken, mit der man da Daten rauspalten kann. Ansonsten, man kann Log-Nachrichten machen und halt so klassisches Log-Debugging machen. Das wird dann da unten im Log-Output erscheinen. Auf der rechten Seite sieht man einen Live-View, die zentriert normalerweise auf den eigenen Wurmsuher läuft und macht auch den Zoom-Level hoffentlich gleich richtig. Außerdem gibt es da unten noch Neu, Neu, Neu, das Top-Memory. Warum da genau vier Beiz drinstehen oder acht Beiz drinstehen, müsstest du mir sagen? Jetzt mal neulich auffallen. Find ich auch gerade interessant. Eigentlich ist der ganze Bildschirm voll mit nullen. Genau. Vielleicht passiert das, bevor man auf Range klickt hat. Na gut, es passiert auf jeden Fall, wenn ich auf Delete klick, dann kann ich nämlich meine ganzen persistenten Daten löschen und man sieht hier ein Hex-Dump von den eigenen Daten, die der Wurm gespeichert hat, auf diesen 4096 Beiz, die man zur Verfügung hat. Die kann ich auch runterladen, dann sollte ich ein normales Downloadfenster kriegen. Ich kann auch neue Daten hier hochladen, also einfach ein Pfeil auswählen, hochladen und mit Refresh kann ich den jeweils aktuellen Stand anschauen. Aktuell heißt dabei, den letzten, den der Game Server hatte, wenn der Wurm gestorben ist. Genau. Also es wird nur in die Datenbank geschrieben, wenn die Schlange steht oder anderweitig neu gestartet wird. Genau. All das, wer Lust hat dazu, ist auch über eine Rest-AP verfügbar. Also man muss diese Web-IDI nicht verwenden. Die Web-IDI verwendet auch die Rest-AP. Ich finde mir auch nicht sicher, ob nicht das Request-Lock vom Web-Browser die beste Do-Co ist, die man dafür hat. Ich weiß es nicht. Auch viel Do-Co haben wir noch nicht dazu. Genau. Also wenn es sehen wollt, wie es funktioniert, macht es ein Web-Inspector auf im Browser eurer Wahl und schaut, was für Web-Request die IDI macht. Genau, das kann man auch so machen. Man kann sich AP Keys erzeugen. Vielleicht zeige ich das gleich noch als nächstes her, bevor man dann zum Programmieren kommt. Hier unter Profile oben gibt es Manage API Keys und da kann ich irgendwas, einen neuen API Key anlegen und den, ach so, das sollte man vielleicht schon noch dokumentieren, wie das funktioniert, weil wenn ich eingeloggt bin im Browser, dann brauche ich kein API Key. Wir liefern das noch nach, wie man den API Key verwendet. Jedenfalls kann ich damit die gleiche Chasen-Rest-API verwendet, wie die IDI das tut. So, nun zum Code. Unüblich für C++ hat man ein File zur Verfügung, in dem der Code landen muss. Auch das kann man sich automatisieren, wenn man möchte, ein anständiges Projekt anlegen will mit vielen Files, dann kann man die ja irgendwie zusammenbauen zu einem File und dann per Rest hochladen. Im Code passiert als erstes dieses Include-User-Code-Punkt her. Das zieht die ganze API mal an. Danach gibt es zwei Funktionen. Ich hoffe, hier zählen nichts Falsches. Genau. Die eine ist die Innit-Funktion, die aufgerufen wird, wenn der Bot gestartet wird. Und hier sieht man jetzt, wie man seinen Bot bunt machen kann. Also Clear Colors löscht erst mal alle Farben. Ich weiß nicht, wenn keine festgelegt sind, ist man grau, oder? Stimmt das noch? Ja. Genau. Und dann kommen X, wie lieb ich viele? Ich weiß es nicht. Ich glaube, 1024. Ausreichend viele einzelne Farben angeben. Und wenn man in die Live View reinschaut, dann sieht man ja, dass die Bots irgendwie so Abstufungen von Farben haben. Also man legt damit ein Farbmuster fest, dass sich immer wiederholt. Genau. Und dann wäre es gut, wenn man danach aus dieser Funktion den Boolen als Rückgabewert hat, True zurückgibt, weil sonst glaubt der Game Server, die Initialisierung ist viel geschlagen. Ich weiß nicht, wird er dann gleich wiedergestartet. Beim Innit wird er tatsächlich deaktiviert danach. Okay. Danach, die eigentlich relevante Funktion ist die Step-Funktion, beide Funktionen kriegen übrigens einen Pointer auf diese API mit, über die die ganzen Komfortfunktionen zur Verfügung stehen, um mit dem Game Server zu kommunizieren. Als erstes sehen wir schon mal, hier wird API Engel gesetzt. Engel ist der Winkel, in dem sich der Bot bewegen soll im nächsten Schritt ausgeben von der aktuellen Blickrichtung. Das heißt, und zwar in Radiance. Also in Werten von plus minus pi. Kann das jetzt nicht direkt in Winkel übertragen, aber was dieser Bot machen wird, ist einen sehr großen Kreisfahren, weil er nämlich immer im gleichen Winkel seinen Kopf weiter bewegt von Schritt zu Schritt. Danach sehen wir, wie man über die einzelnen Segmenten, die der Bot sieht, drüber etäriert. Damit könnte man zum Beispiel Gegner erkennen. Für jedes Segment, das wir sehen, das wird in dieser Sec-Variable abgelegt, gibt es einen Bullen Flag ist Self, ob das eines von unseren eigenen Segmenten ist oder nicht. Ich nehme an, man wird auch sehen, welchen Gegner es gehört, wenn man ein Gegner sieht. Das kann man sich rausholen. Also Sec hat ein Element BotID und die gehört logischerweise zum Bot und es gibt auch noch GetBots in der API und da kriegt man eine Zuordnung von BotID auf Namen. Das heißt, wenn man will, kann man die Namen von den anderen Bots herausfinden. Und zum Beispiel nur die angreifen, die man echt nicht mag oder so. So, jetzt schreckt er außerdem noch dieses Segment, das ich da gesehen habe und das offensichtlich nicht von mir ist. Wie weit ist das von meinem Kopf weg? Ich nehme an, das ist die Distanz vom Kopf und in dem Fall sieht man jetzt einfach nur, wie man die Logging-API verwendet. Also schlau wäre jetzt zu versuchen, irgendwie wegzukommen von dem, aber man kann natürlich auch einfach loggen, oh no, I'm going to die. Wie man Futter genau sucht, steht in der API-Beschreibung. Funktioniert im Endeffekt genauso, dass man alle Segment durch Food ersetzt. Und was man im einfachsten Fall zum Beispiel machen könnte, so was, zum Beispiel letztes Jahr eine nicht ganz erfolglose Strategie, einfach mal schauen. Das ganze Futter, das ich sehe, wenn ich mir das in Segment zerlege, um mich rum, in welchem Segment habe ich den meisten, das meiste Futter, dann versuche ich vielleicht dahin zu lenken. So als Beispiel, wie man mal anfangen könnte. Dann ist wieder die Geschichte, es ist eine Boole in Funktion, die gibt hier True Zurück und wenn man hier false-trick gibt, dann wird der Bot beendet und neu gestartet. Also kann man Selbstmord begehen, wenn man false-trick gibt. Okay, dann schaue ich jetzt mal, was passiert. Ich drücke jetzt mal auf Run. Wir sehen Safe Code as Version 1, Waiting for Build Output. Jetzt wird im Hintergrund der Docker-Container, der Docker-Bilder loslaufen, das ist jetzt fertig geworden und hat ein Build Output erzeugt. Oh wunder, unser Demo-Skript kompaliert. Und wir wurden gestartet. Puff. So, was wir jetzt nicht sehen im Log ist ein Oh no, I'm going to die. Es liegt ganz einfach daran, dass die Schlangen so groß sind. Also die andere, es wird nämlich immer von Mittelpunkt zu Mittelpunkt gemessen und 20 ist im Nachhinein gesehen ein zu kleiner Wert für den Vergleich. Okay, wunderbar. Kannst du mal 200 draus machen? Wir machen 200 draus, drücken ran. Code Safe as Version 2 erbaut. Wir laufen wieder. Sollen wir mal raus. Passiert in nächster Zeit was? Na ja, den könnt ihr treffen. Kriegen wir die Kurve? Nein, weil wir fahren bei uns herum. Okay. Puff. Oh no, I'm going to die, to die, to die, to die, to die. Genau so. Puff. Genau. Es funktioniert auch so, dass wenn ich irgendwie neu kompaliere, er automatisch umschaltet in diesen Build Output und sofern irgendein Log Output kommt, er dann wieder nach einer gewissen Zeit wieder umschaltet in diese Log Output. Genau. Vielleicht noch, wie man an diesen Versionen vom Build Output sieht, alle Versionen von eurem Boot bleiben in der Datenbank für immer und ewig und sind unseres und keine Ahnung. Man kann hier Load klicken und alle Versionen wieder laden, wenn man dann mal wieder zurück möchte. Und man kann die auch unter einem bestimmten Namen speichern und jetzt bin ich auf unsicherem Terrain, weil ich nicht weiß, ob das funktioniert. Es passiert einfach gar nichts, wenn ich auf Selfies klick. Nein, das funktioniert nicht. Man kann den Bots keine Namen geben oder den Versionen niemand. Aber vielleicht liefern wir das noch nach dem Laufe des Tages oder der GPN. Okay, ansonsten kann ich auch manuell sagen, das hat gerade keinen Daug oder ich dominiere das Spielfeld, das ist nicht cool. Ich starte den Bot selber neu, dann wird er halt gekillt und spawn neu oder ich kann auch einfach sagen stop, dann verschwindet mein Bot vom Spielfeld und kommt von alleine nicht wieder, solange bis ich wieder irgendeine Version geladen habe und dran geklickt habe. Genau. In den Preferences gibt es auch nichts zu sehen, bitte gehen Sie weiter. Okay, magst du zu den Highscores noch was sagen oder ich weiß nicht, funktioniert bei dir lokal diese AP Bescheidung, weil bei mir nämlich nicht. Wenn ich mir nicht sicher, ob ich die gebaut habe. Ja auch, okay. Also es gibt so eine DoxyGen generierte Beschreibung der API, die ist jetzt nicht in unserem Team, aber die ist hier unter API verfügbar. Ich nehme an, da bauen wir dann auch noch die Info-Reihen, wie man mit der Rest API richtig kommuniziert. Und dann gibt es noch die Highscores. Ja, jeder der letztes Jahr dabei war, wird die wahrscheinlich kennen, bis auf einen Punkt. Wer war denn eigentlich letztes Jahr schon dabei? Es war eine Zwischenfrage. Oh, na ja, ungefähr die Hälfte, würde ich sagen. Genau. Also zum einen gibt es Maxscore, das sind die Highscores, die gezählt werden, wenn die Schlangen sterben. Das heißt, in dem Frame, wo die Schlange stirbt, wird die Größe gespeichert. Genau. Und dann abwärtsortiert nach Nutzer da angezeigt. Es gibt jetzt neu den MaxAnytime-Score. Das ist die höchste Größe, die man jemals erreicht hat während der ganzen Lebenszeit. Das heißt, wenn die Schlange riesig ist, dann ein anerbott zieht, boostet, dadurch alle Masse verliert und dann stirbt, wird man trotzdem hier in dieser Highscore-Listik gut sein. Vielleicht soll man das Busten noch erklären. Ja, genau. Also neben dem Winkel, den die Schlange zurückgeben kann, kann die Schlange sagen, ob sie Busten will. Das heißt, sie wird in dem Frame, in dem Bust auf Truh ist, auf die doppelte Geschwindigkeit beschleunigt. Ist aber teuer, weil man verliert pro Frame ein pro Mill der Schlangenmasse. Macht für große Schlangen sehr viel aus. Ihr werdet das sehen. Genau. Dann zurück zu den Highscores. MaxAge ist eigentlich klar, es ist die Lebenszeit der Schlange in Frames, was hier steht. Und es gibt Konsum-Rät. Das ist ein bisschen komisch, wenn man das so anschaut. Da gewinnen nämlich immer die, die nicht lange leben. Das liegt einfach dran. Hier wird das gefressene Futter insgesamt durch die Lebenszeit der Schlange gerechnet. Wenn natürlich die Schlange jetzt in einem riesen Futterhaufen spawnen, sich sofort aufbläht und dann in die nächste reinrauscht, kommt hier ein sehr großer Wert raus. Genau. Also der hier ist mir so als Gag gedacht. Gut. Haben wir noch was? Python gibt es nächstes Jahr. Ja, guter Punkt. Wie bitte? Das sagt mir jetzt persönlich nichts. Ja, ich glaube, soweit sind wir noch nicht. Aber dieses Docker-Framework hat den Charme, dass man relativ einfach neue Frame, neue Bot-Frameworks einbauen kann. Das heißt, man kann jetzt quasi jede Programmiersprache unterstützen, die es irgendwie schafft diesen Shared-Memory zu lesen und irgendwie schafft, mit dem Unix-Socke zu kommunizieren. Das heißt, wenn jemand Bock hat, hier ein Python-Framework oder ein Rast-Framework zu bauen oder irgendwas Ähnliches, ihr seid aufgerufen. Ja, gut, der Punkt. Sondern ob das jetzt steht schon weggetan, kommt es noch? Nein, noch nicht. Wir werden hoffentlich heute noch den Source veröffentlichen von dem Ganzen. Dann könnt ihr auch sehen, wie das Framework funktioniert. So, jetzt muss ich irgendwie zur Präsentation zurückfinden, dass wir hier die letzte Folie zeigen können. Lange ist her. Nein? Hier. So, die letzte Folie. Ich wünsche euch viel Spaß beim Mitspielen. Hier steht die Adresse, unter der es hoffentlich demnächst verfügbar sein wird. Und wenn es Fragen gibt, gerne. Also, die Frage war, gibt es für den Bild Prozess-Resourcen-Limits? Ja, gibt es tatsächlich. Ich glaube, es sind tatsächlich die gleichen, wie beim Ausführen, nur dass es da ein Gigabyte-Ram gibt und das Dateisystem nicht read-only ist. Wir hoffen, dieses Jahr mit 60 FPS. Dazu als Hintergrund-Info, wir haben ja diese Testdatenbank hier gerade gezeigt, die ist jetzt wochenlang mit 60 FPS auf einem Utreut C2 gelaufen. Wer das nicht kennt, das ist so ein Raspberry Pi großes Board mit einem Quadchord drauf, braucht ungefähr 3 Watt. Der Vergleich zum letzten Jahr bezüglich was? Ach so. Wie gesagt, letztes Jahr haben wir 50 FPS gehabt auf unserem 10-Core Xeon mit Hyperthreading mit 350 Boards. Genau, wir haben es getestet vor ein paar Tagen. Da hat er 400 Boards mit 60 FPS geschafft. Oder vielleicht will man auch das Verhältnis von den 3 Watt zu dem Server heute. Ja, die sind abhängig von der Schlangengröße. Also, die Frage war, ob die 3 Winkel, die die Schlangen eben frei machen kann, begrenzt sind. Die sind tatsächlich abhängig von der Schlangengröße. Größere Schlangen können sich langsamer drehen. Aber es ist immer so, dass der Radius, den die Schlange fährt im Verhältnis zu ihrer Größe, konstant ist. Einfach ausprobieren, drehen Winkel auf 100 Sätzen, dann seht ihr, was passiert. Weiterifragen? Vielleicht nach wo wir sind, können wir mal sagen. Ja. Kennt man die absoluten Positionen der? Die absoluten, tatsächlich nicht. Ihr kriegt relative Winkel zu eurer aktuellen Bewegungsrichtung oder alternativ relative Koordinaten, aber im Weltkoordinatensystem. Also, die Ausrichtung ist am Spielfeld ausgerichtet, aber die Position ist nicht absolut am Spielfeld ausgerichtet, sondern im Verhältnis zum Kopf der Schlange. Genau, noch weitere Fragen. Ansonsten noch mal viel Spaß beim Spielen. Und wenn euch noch Fragen einfallen, wir sitzen diesen Gang nach vorne direkt vor der Launch auf der linken Seite. Wir werden den Beamer haben, der den Führer anzeigt, der ist, glaube ich, nicht zu verfehlen.