multiJSnake

Vor Kurzem habe ich ein Server-Client Snake in meine Liste von simplen Snake-Clonen [1, 2, 3, 4, 5, 6] eingereiht. Wie ich in meinem Artikel „RestfulSnake“ bereits angedeutet hatte, habe ich es um eine Multiplayer Komponente erweitert.

multiJSnake

Das grundlegende Design ist, dass der Server in festen Intervallen den nächsten Zeitschritt berechnet, den Spielzustand an alle Spieler schickt und auf Steuerkommandos von den Spielern lauscht. Dass der Server die gesamte Spiellogik verwaltet ist einerseits möglich, weil Snake einen relativ kleinen Zustand hat und nicht extrem empfindlich auf Latenzen reagiert. Außerdem können Spieler nicht (so einfach) schummeln, wenn der Spiel-Zustand auf dem Server berechnet wird.

Hier sehen wir auch schon das erste Problem für die alte Kommunikation per http: Da der Server nicht von sich aus Nachrichten an die Clients schicken kann, müssten die Clients pollen, was zu einem ganzen Haufen an Problemen führen kann (Poll kurz vor dem Tick zum nächsten Zeitschritt, Last, uneinheitliche Antwortzeiten und Races bei schlechtem Netzwerk, …) Genau für diesen Zweck sind aber Websocket-Verbindungen wie geschaffen! Da SpringBoot vernünftige Mechanismen mitbringt, um Websockets zu handhaben, ist die Umstellung sogar vergleichsweise schmerzfrei.

Das größte Problem ist nun, dass die meisten Leute „Rest“ als synonym für „json über http“ verstehen. Also muss ein neuer Name her — leider war „multisnake“ auf Heroku schon belegt, sodass ich mit „multiJSnake“ subtil darauf hinweise, dass Java und JavaScript das fundament bilden.

Ausprobiert werden kann es auf multijsnake.herokuapp.com und weitere Spieler können durch einen Einladungslink in die eigene Session eingeladen werden. Die Quellen sind natürlich auf Github: github.com/surt91/multiJSnake.

RestfulSnake

Vor wenigen Monaten hatte ich eine handvoll Bewerbungsgespräche. Von „Programmieraufgaben“, die durch das Erkennen der Fibonacci-Sequenz gelöst wurden bis zu „Wie viele Grashalme gibt es in deiner Heimatstadt?“ war alles dabei. Unter anderem auch „Wir glauben, dass du noch nie Java angefasst hast, deshalb sollst du ein Programm in Java schreiben, über das wir nächste Woche reden können!“

Also bin ich jetzt Java-Experte. Und das bedeutet, dass es Zeit ist für eine weitere Snake-Version [1, 2, 3, 4, 5].

Um besonders professionell zu wirken, habe ich mich für eine Client-Server-Architektur entschieden. Steuerkommandos werden per http post zum Server geschickt und in der Antwort steht die neue Position der Schlange. Das Backend nutzt Spring Boot und läuft auf einem Tomcat Server. Das Frontend besteht hauptsächlich aus dem Visualisierungs-Code von jsnake, aber echte Nerds werden es natürlich bevorzugen per curl zu spielen.

Normalerweise würde man es natürlich mittels Kubernetes und Docker auf AWS laufen lassen, aber stattdessen habe ich mich dafür entschieden Heroku zu nutzen, um ein kleines Unternehmen zu unterstützen. Auf multijsnake.herokuapp.com kann man also eine Partie spielen. Und die Quellen liegen wie immer auf GitHub

Überraschenderweise funktioniert das tatsächlich erstaunlich gut — solange die Latenz unter ~150 ms bleibt. Und dieses Design schreit geradezu nach einen Multiplayer-Modus…

Noch mehr Fraktale

Seit meinem ersten Eintrag über meinen Fraktal-tweetenden Bot @AFractalADay, habe ich selbigen noch um ein paar Fraktale erweitert, die ich hier kurz festhalten möchte. Der ganze Code ist auf Github.

Chaotic Maps

Eine Quadratic Map ist eine Rekursionsgleichung mit einem quadratischen Term, also beispielsweise

$$x_{i+1} = a_0 x^2 + a_1 x + a_2.$$

Das berühmteste Mitglied dieser Familie ist die Logistic-Map mit \(a_0=1, a_1=r, a_2=0\), die chaotisches Verhalten für \(3.56995 < r < 4\) zeigt. Aber leider ist sie nur eindimensional und ihr Attraktor deshalb nicht besonders hübsch.

Um visuell ansprechende Fraktale daraus zu erzeugen, brauchen wir also ein System aus zwei Rekursionsgleichungen, die wir als \(x\)- und \(y\)-Koordinaten betrachten können:

\begin{align*} x_{i+1} &= a_{0} + a_{1} x + a_{2} x^2 + a_{3} x y + a_{4} y + a_{5} y^2\\ y_{i+1} &= a_{6} + a_{7} x + a_{8} x^2 + a_{9} x y + a_{10} y + a_{11} y^2. \end{align*}

Jetzt haben wir 12 freie Parameter, die einen riesigen Parameterraum aufspannen, in dem etwa 1.6% aller Möglichkeiten chaotisches Verhalten mit einem seltsamen Attraktor zeigen.

Quadratic Map

Chaotische Differentialgleichungssysteme

Ein echter Klassiker ist das Differentialgleichungssystem, das die Chaostheorie begründet hat und nach dem der Schmetterlingseffekt benannt ist [1, 2]. Für bestimmte Paramtersätze verlaufen die Bahnkurven entlang eines seltsamen Attraktors, dessen fraktale Dimension \(\approx 2.06\) ist. Da der vollständige Attraktor somit in einer zweidimensionalen Projektion etwas langweilig aussieht, habe ich hier nur eine Trajektorie über kurze Zeit dargestellt.

Lorenz-Attraktor

Und es gibt eine ganze Menge weitere Differntialgleichungssysteme (und chaotic maps), die chaotische Attraktoren aufweisen. Deshalb zeige ich hier noch einen Rössler-Attraktor, der eine vereinfachte Version des Lorenz-Systems ist:

\begin{align*} \frac{\mathrm{d}x}{\mathrm{d}t} &= -(y+z)\\ \frac{\mathrm{d}y}{\mathrm{d}t} &= x + ay\\ \frac{\mathrm{d}z}{\mathrm{d}t} &= b + xz - cz \end{align*}

Und hier haben wir das Glück, dass auch seine Projektion sehr ansehnlich ist.

Rössler-Attraktor

Ich persönlich frage mich, nun wie der Attraktor für das Doppelpendel aussieht. Es ist anscheinend kein Fraktal, aber es sieht dennoch ganz interessant aus:

Doppelpendel

Ising model

Das Ising Modell für Ferromagnetismus wird auch als Drosophila der statistischen Physik bezeichnet: Es ist ein einfaches Modell, dass einen Phasenübergang aufweist — Eisen verliert seine magnetischen Eigenschaften oberhalb der Curie-Temperatur.

Es besteht aus magnetischen Momenten, Spins, die gerne in die gleiche Richtung zeigen wie ihre Nachbarn, aber durch hohe Temperatur gestört werden. Oder etwas formaler: Die innere Energie \(U\) wird durch den Hamiltonian \(\mathcal{H} = - \sum_{<ij>} s_i s_j\) bestimmt, wobei \(s_i = \pm 1\), je nachdem ob der Spin up oder down ist und die Summe über benachbarte Spins läuft. Das System wird immer einen Zustand anstreben, der die freie Energie \(F=U-TS\) minimiert. Das kann entweder passieren, indem \(U\) möglichst klein ist oder die Entropie \(S\) möglichst hoch. Bei großen Werten der Temperatur \(T\) bekommt der Entropie-Term ein höheres Gewicht, sodass Zustände mit hoher Entropie, also zufälligen Spinausrichtungen, bevorzugt sind, bei niedrigen Temperaturen werden Konfigurationen mit niedriger innerer Energie bevorzugt, also solche in denen alle Spins in die selbe Richtung zeigen. Die Temperatur, bei der sich beide Terme die Waage halten, nennt man kritische Temperatur. Hier bilden sich Regionen von Spins, die in die gleiche Richtung zeigen, auf allen Größenskalen. Die fraktale Dimension dieser Regionen ist 187/96, was solche kritische Konfigurationen interessant anzusehen macht. Ich empfehle auf das folgende Bild zu klicken und etwas hineinzuzoomen.

Kritisches Ising System