Der naheliegende Weg, ein Spiel zu bauen, ist, das Telefon entscheiden zu lassen. Die Partie endet, die App berechnet das Ergebnis und teilt dem Server mit, was geschehen ist. Schnell, einfach – und der Server hat überhaupt keine Meinung.
Es heißt aber auch: Das Ergebnis ist, was die App sagt. Und eine App ist ein Programm auf dem Rechner eines anderen, den dieser ändern kann.
Was wir stattdessen tun
Jedes Spiel hier zeichnet die Züge auf – nicht das Resultat, die Züge. Am Ende geht diese Liste an unsere Server, und der Server spielt dieselbe Partie aus derselben Ausgangsstellung noch einmal, mit denselben Regeln auf denselben Zügen.
Erreicht er Ihr Ergebnis, wird die Partie angenommen und jede Belohnung aus der Kopie des Servers berechnet. Andernfalls wird sie abgelehnt und nichts gutgeschrieben.
Die Engine ist auf beiden Seiten derselbe Code, und sie ist deterministisch: bei gleichem Startwert und gleichen Zügen muss dasselbe Brett entstehen. Diese Forderung prägt erstaunlich viel am Entwurf. Alles Zufällige muss aus einem Startwert kommen, den auch der Server hat. Alles, was die Uhr liest, muss eine Zeit lesen, auf die sich beide Seiten einigen. Eine Regel, die sich auf einem schnellen Gerät anders verhält als auf einem langsamen, können wir nicht haben.
Was es kostet
Einige Millisekunden pro beendeter Partie und eine echte Einschränkung dafür, wie die Spiele geschrieben werden können. Es findet außerdem unsere eigenen Fehler, was weniger angenehm ist, als es klingt.
Ein Beispiel, weil es die ehrliche Sorte ist. Eine Ernte wurde verteilt, indem über die Schlüssel eines JSON-Objekts iteriert wurde. Zwei Kopien desselben Inhalts – eine aus einer Datei, eine aus der Datenbank – lieferten diese Schlüssel in unterschiedlicher Reihenfolge, und der Speicher füllte sich unterwegs. Gleiche Regeln, gleiche Züge, anderes Ergebnis. Ehrliche Spielende bekamen Partien abgelehnt, mit einer Meldung über einen Ort mit 590 statt 591 Lasten. Im Spiel sah nichts falsch aus; die Wiederholung war schlicht mit sich selbst uneins.
Für jeden Unit-Test war dieser Fehler unsichtbar, denn beide Hälften bestanden für sich. Erst dass die zwei Seiten über verschiedene Wege beliefert wurden, legte ihn offen.
Was es bringt
Eine Bestenliste, in die niemand direkt schreiben kann, und eine Belohnung, die sich nicht erfinden lässt. Das ist zweimal dieselbe Eigenschaft: Sie verdienen, was die Wiederholung sagt.
Es erlaubt uns auch, präzise zu sein, wenn etwas schiefgeht. Eine abgelehnte Partie ist kein vager Vorwurf, sondern eine Abweichung an bekannter Stelle – und fast immer eine mitten im Spiel abgebrochene Verbindung statt eines Zutuns der Spielenden.