diff options
author | Marcin Chrzanowski <m@m-chrzan.xyz> | 2021-02-16 22:28:18 -0500 |
---|---|---|
committer | Marcin Chrzanowski <m@m-chrzan.xyz> | 2021-02-16 23:13:49 -0500 |
commit | 4bf167df5d0abee939bf3ebfa925c4fe22cd0502 (patch) | |
tree | b524ecb75308afec3a8a2f5a034d864c5c8c5c55 /src/blog/hex-curler.html | |
parent | f49446993a09a417566b0ca33fdf498048edf9e5 (diff) |
Move git links in blog
Diffstat (limited to 'src/blog/hex-curler.html')
-rw-r--r-- | src/blog/hex-curler.html | 136 |
1 files changed, 0 insertions, 136 deletions
diff --git a/src/blog/hex-curler.html b/src/blog/hex-curler.html deleted file mode 100644 index 8f5f1c6..0000000 --- a/src/blog/hex-curler.html +++ /dev/null @@ -1,136 +0,0 @@ -title: "Hex Curler: A Minimalist Webgame" -date: August 29, 2019 ---- -<p> -I just published Hex Curler, a tiny dungeon crawler, based on Jeff Moore's -<a href='http://www.1km1kt.net/rpg/hex'>Hex</a>. -</p> - -<p> -You can play it by running the following in a bash shell: - -<pre> -c=x; while [ $c ]; do clear; curl -c k -b k hex.m-chrzan.xyz/$c; read c; done -</pre> -</p> - -<p> -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 <code>curl</code>, a CLI tool already -available on most Unix-like systems. -</p> - -<p> -The source code is available <a href='https://gitlab.com/m-chrzan/hex-curler'>on -my GitLab</a>. -</p> - -<h3>Let's get curling</h3> -<p> -The whole concept arose from two ideas I had: - -<ul> - <li> - <code>curl</code> and a simple web server could be used to create a - simple remote CLI program. - </li> - <li> - For a webapp that implements a simple state-transition system (like a - simple game), one could forget about session management and a database, - and just store the state client-side in a cookie. - </li> -</ul> - -I abstracted these ideas away into a Ruby class called <code>Engine</code> and a -skeleton Sinatra app. -</p> - -<p> -To create a new "curling" system, you extend <code>Engine</code> and implement -four methods: - -<ul> - <li> - <code>step</code>: performs a single step of the state-transition - function. - </li> - <li> - <code>message</code>: outputs a message related to the most recent - <code>step</code>. - </li> - <li> - <code>hash_to_state</code> and <code>state_to_hash</code>: these are - just overhead glue methods. They should deserialize and serialize - between your engine's internal state and a Ruby <code>Hash</code>. - </li> -</ul> - -You also need to define a <code>secret</code> which is a string that is used to -validate that a submitted cookie represents a valid state. More on this later. -</p> - -<p> -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: - -<pre> -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 -</pre> -</p> - -<h3><em>O</em>(1) space webapp</h3> -<p> -Hex Curler is hosted online but has no session management, no database. It's an -<em>O</em>(1) space webapp. -</p> - -<p> -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. -</p> - -<p> -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 <code>checksum</code> 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. -</p> - -<p> -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. -</p> - -<p> -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. -</p> |