Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/apsillers/stacklife
Conway's Game of Life for your Stack Exchange profile
https://github.com/apsillers/stacklife
Last synced: 3 months ago
JSON representation
Conway's Game of Life for your Stack Exchange profile
- Host: GitHub
- URL: https://github.com/apsillers/stacklife
- Owner: apsillers
- License: mit
- Created: 2014-04-03T20:24:48.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2014-10-11T19:37:27.000Z (about 10 years ago)
- Last Synced: 2024-04-24T12:19:51.128Z (7 months ago)
- Language: JavaScript
- Size: 189 KB
- Stars: 23
- Watchers: 3
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
stacklife
=========[Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_game_of_life) for a Stack Exchange profile. See a deployed implementation on [my Stack Overflow profile](http://www.stackoverflow.com/users/710446/apsillers).
While the client-side markdown is designed to fit inside of a Stack Exchange profile, this code could easily be used in any HTML environment that allows links and images.
## Example
The example below is fully interactive.
[![](http://l.apsillers.com:8001/00)](http://l.apsillers.com:8001/w00)
[![](http://l.apsillers.com:8001/01)](http://l.apsillers.com:8001/w01)
[![](http://l.apsillers.com:8001/02)](http://l.apsillers.com:8001/w02)
[![](http://l.apsillers.com:8001/03)](http://l.apsillers.com:8001/w03)
[![](http://l.apsillers.com:8001/04)](http://l.apsillers.com:8001/w04)
[![](http://l.apsillers.com:8001/05)](http://l.apsillers.com:8001/w05)
[![](http://l.apsillers.com:8001/06)](http://l.apsillers.com:8001/w06)
**Controls:**
[![](http://l.apsillers.com:8001/10)](http://l.apsillers.com:8001/w10)
[![](http://l.apsillers.com:8001/11)](http://l.apsillers.com:8001/w11)
[![](http://l.apsillers.com:8001/12)](http://l.apsillers.com:8001/w12)
[![](http://l.apsillers.com:8001/13)](http://l.apsillers.com:8001/w13)
[![](http://l.apsillers.com:8001/14)](http://l.apsillers.com:8001/w14)
[![](http://l.apsillers.com:8001/15)](http://l.apsillers.com:8001/w15)
[![](http://l.apsillers.com:8001/16)](http://l.apsillers.com:8001/w16)
[Step](http://l.apsillers.com:8001/s) [Random Noise](http://l.apsillers.com:8001/r)
[![](http://l.apsillers.com:8001/20)](http://l.apsillers.com:8001/w20)
[![](http://l.apsillers.com:8001/21)](http://l.apsillers.com:8001/w21)
[![](http://l.apsillers.com:8001/22)](http://l.apsillers.com:8001/w22)
[![](http://l.apsillers.com:8001/23)](http://l.apsillers.com:8001/w23)
[![](http://l.apsillers.com:8001/24)](http://l.apsillers.com:8001/w24)
[![](http://l.apsillers.com:8001/25)](http://l.apsillers.com:8001/w25)
[![](http://l.apsillers.com:8001/26)](http://l.apsillers.com:8001/w26)
[Clear](http://l.apsillers.com:8001/c) [Random Feature](http://l.apsillers.com:8001/f)
[![](http://l.apsillers.com:8001/30)](http://l.apsillers.com:8001/w30)
[![](http://l.apsillers.com:8001/31)](http://l.apsillers.com:8001/w31)
[![](http://l.apsillers.com:8001/32)](http://l.apsillers.com:8001/w32)
[![](http://l.apsillers.com:8001/33)](http://l.apsillers.com:8001/w33)
[![](http://l.apsillers.com:8001/34)](http://l.apsillers.com:8001/w34)
[![](http://l.apsillers.com:8001/35)](http://l.apsillers.com:8001/w35)
[![](http://l.apsillers.com:8001/36)](http://l.apsillers.com:8001/w36)
Click a cell to toggle it.
[![](http://l.apsillers.com:8001/40)](http://l.apsillers.com:8001/w40)
[![](http://l.apsillers.com:8001/41)](http://l.apsillers.com:8001/w41)
[![](http://l.apsillers.com:8001/42)](http://l.apsillers.com:8001/w42)
[![](http://l.apsillers.com:8001/43)](http://l.apsillers.com:8001/w43)
[![](http://l.apsillers.com:8001/44)](http://l.apsillers.com:8001/w44)
[![](http://l.apsillers.com:8001/45)](http://l.apsillers.com:8001/w45)
[![](http://l.apsillers.com:8001/46)](http://l.apsillers.com:8001/w46)
[View source](//github.com/apsillers/stacklife)
[![](http://l.apsillers.com:8001/50)](http://l.apsillers.com:8001/w50)
[![](http://l.apsillers.com:8001/51)](http://l.apsillers.com:8001/w51)
[![](http://l.apsillers.com:8001/52)](http://l.apsillers.com:8001/w52)
[![](http://l.apsillers.com:8001/53)](http://l.apsillers.com:8001/w53)
[![](http://l.apsillers.com:8001/54)](http://l.apsillers.com:8001/w54)
[![](http://l.apsillers.com:8001/55)](http://l.apsillers.com:8001/w55)
[![](http://l.apsillers.com:8001/56)](http://l.apsillers.com:8001/w56)
[![](http://l.apsillers.com:8001/60)](http://l.apsillers.com:8001/w60)
[![](http://l.apsillers.com:8001/61)](http://l.apsillers.com:8001/w61)
[![](http://l.apsillers.com:8001/62)](http://l.apsillers.com:8001/w62)
[![](http://l.apsillers.com:8001/63)](http://l.apsillers.com:8001/w63)
[![](http://l.apsillers.com:8001/64)](http://l.apsillers.com:8001/w64)
[![](http://l.apsillers.com:8001/65)](http://l.apsillers.com:8001/w65)
[![](http://l.apsillers.com:8001/66)](http://l.apsillers.com:8001/w66)## Server setup
1. After downloading the code, run `npm install` inside the project directory to install Express.
2. In `lifeserver.js`, change the `profileUrl` variable to the URL of the HTML page that will display the Life grid.
3. Optionally, to enable HTTPS, copy your SSL cert/key files into the directory and uncomment the HTTPS code at the top of `lifeserver.js`.
3. Run `node ifeserver.js` (with `sudo` if necessary to listen on ports `80` and `443`).
## Client setup
1. In `client.md`, replace each instance of `${host}` with the scheme and hostname of your server, with no trailing slash, e.g., `http://example.com`.
2. If deploying to Stack Exchange, ensure your hostname is short enough to fit in the 3000 character limit. Also, you can save space by using `//` as the scheme (e.e., `//example.com` instead of `http://example.com`) which will use the scheme of the containing page. (Note that this means that your server must support HTTPS whenever Stack Exchange upgrades to HTTPS, or if a user is using [HTTPS Everywhere](https://www.eff.org/https-everywhere).)
3. Copy the contents of `client.md` to your profile or other page.
## How it works
The server maintains the global state of the Life game. The client HTML/markdown displays the state of each cell as an image in a grid. An HTTP server listens for requests with particular paths:
* `/00` (or any two numbers) - serve an image representing the state of the cell at that {row,col} position (black for live, white for dead)
* `/w00` (or any two numbers) - toggle the state of the cell at {row,col}
* `/c` - clear all cells
* `/r` - fill cells with random noise
* `/f` - clear cells and draw a random feature (glider, oscillator, etc.)
* `/s` - step into the next Life generationAll requests redirect back to the profile page after they perform their specified server-side action (except for the `/00` request, which serves an image instead of performing a redirect).
## Future work
Future modifications might include:
* using cookies to allow each user to have a separate game state
* using query strings in the profile URL (passed to the server via `Referer` header) to have saved states sharable via URL
* applying the general principles to a completely new game (chess, minesweeper, etc.). This would work especially well for a game with very few inputs and output that can be rendered as a single image, since multi-image output requires a high volume of separate HTTP requests. For example, a video game console simulator with a D-pad and a few buttons, plus a single screen image, rendered server-side with Imagemagick, would only require a few HTTP requests.