From 8f6595c19043585652d5603096b9540cab14efa4 Mon Sep 17 00:00:00 2001
From: Marcin Chrzanowski
+I just published Hex Curler, a tiny dungeon crawler, based on Jeff Moore's
+Hex.
+
+You can play it by running the following in a bash shell:
+
+
+c=x; while [ $c ]; do clear; curl -c k -b k hex.m-chrzan.xyz/$c; read c; done
+
+
+This was an exercise in minimalism. The game server is implemented in less than
+a thousand lines of Ruby code. It is completely stateless, requiring no
+database. The front end "client" is a single line of bash, less than 80
+characters long. The only dependency is curl
, a CLI tool already
+available on most Unix-like systems.
+
+The source code is available on +my GitLab. +
+ ++The whole concept arose from two ideas I had: + +
curl
and a simple web server could be used to create a
+ simple remote CLI program.
+ Engine
and a
+skeleton Sinatra app.
+
+
+
+To create a new "curling" system, you extend Engine
and implement
+four methods:
+
+
step
: performs a single step of the state-transition
+ function.
+ message
: outputs a message related to the most recent
+ step
.
+ hash_to_state
and state_to_hash
: these are
+ just overhead glue methods. They should deserialize and serialize
+ between your engine's internal state and a Ruby Hash
.
+ secret
which is a string that is used to
+validate that a submitted cookie represents a valid state. More on this later.
+
+
++The Sinatra skeleton instantiates an engine with the received cookie, +runs a step, sends back the new state in the returned cookie, and responds with +the engine's message. The code for it fits in half of a browser window: + +
+require 'sinatra' +require 'sinatra/cookies' + +# exposes `Hex`, which extends `Engine`, implementing a simple dungeon crawler +require './hex_engine' + +def secret + # get secret from environment + ENV['HEX_SECRET'] +end + +get '/:command' do |command| + # `new` uses `hash_to_state` to initialize the engine's state + engine = Hex.new cookies.to_h + engine.step command + # `state_h` uses `state_to_hash` to serialize the engine's new state + engine.state_h.each_pair do |key, value| + cookies[key] = value + end + engine.message +end ++ + +
+Hex Curler is hosted online but has no session management, no database. It's an +O(1) space webapp. +
+ ++As mentioned before, the game's state is stored in a cookie. The server need +only know the contents of that cookie to return a new state back to the user. +
+ +
+To prevent a user from tampering with the cookie, for example by increasing
+their health to a ridiculous number, becoming invulnerable to enemies in Hex,
+the cookie also contains a checksum
field. This checksum is the
+hash of the state together with an appended secret only known by the game
+server. The server will refuse to respond to requests whose cookie does not have
+a valid checksum.
+
+This introduces some interesting possibilities. For example, let's say Alice +wants to boast to her friends about how she just beat Hex, ended with 100 HP +remaining, and had upgraded her magic armor to level 5. Her friend Bob doesn't +just have to take her word for it, or trust a screenshot that could have easily +been photoshopped. +
+ ++Alice can send Bob her state cookie. If a request to the game server with it +succeeds, Bob can be assured that he has cryptographic proof of Alice's +claims. +
-- cgit v1.2.3