I just whipped up a chess server, running on wss://chorus.mikedilger.com:444/ using all ephemeral events, no access control required.
I was having a horrible week, doing huge coding but getting no wins and probably have to throw out my efforts. I really needed a win. So I did this chess thing which was (for me) easy with super rapid progress.
Here is the protocol, anybody can write a client for this. People connect and get paired up and play each other. There is no fancy Elo score matching yet. Nor did I write a client yet. Just the server... which is currently running and listening for chess events tagging this pubkey(hex): dbb45efeb8cc10e6f75fdff7e561e7db39cc7ba6592f4c22e26f3ee36b2e7bc2
(NIP-64 is not related to this work... yet)
Please somebody write a nice client.
// Event kinds (not yet allocated in nostr)
const REQ_TO_PLAY: EventKind = EventKind::Ephemeral(20300);
/*
* {
* "pubkey": <player-asking>,
* "kind": 20300,
* "tags": [
* ["p", <server-pubkey>],
* ],
* "content": "",
* ...
* }
*/
const RESP_TO_PLAY: EventKind = EventKind::Ephemeral(20301);
/*
* {
* "pubkey": <server>,
* "kind": 20301,
* "tags": [
* ["p": <player-asking>],
* ],
* "content": "queued", // 'queued' or 'error:<error>' or 'started:<d-tag-of-game>'
* ...
* }
*
*/
const GAME_STATE: EventKind = EventKind::Ephemeral(20302);
/*
* {
* "pubkey": <server>
* "kind": 20302,
* "tags": [
* ["d": <game-id>],
* ["p": <pubkey-for-white>],
* ["p": <pubkey-for-black>],
* ],
* "content": <FEN>,
* ...
* }
*/
const GAME_MOVE: EventKind = EventKind::Ephemeral(20303);
/*
* {
* "pubkey": <player>,
* "kind": 20303,
* "tags": [
* ["d": <game-id>],
* ["e": <last-game-state-event-being-reacted-to>],
* ["p", <server-pubkey>],
* ["p": <pubkey-for-white>],
* ["p": <pubkey-for-black>],
* ],
* "content": <long-algebraic-move>, // or various other signals like 'quit' TBD.
* ...
* }
*/
const GAME_ERROR: EventKind = EventKind::Ephemeral(20304);
/*
* If the game is known, and the error event came from a player of the game:
* {
* "pubkey": <server>,
* "kind": 20304
* "tags": [
* "e": <event-that-was-in-error>,
* "d": <game-id>, // if relevant (not present if game not found)
* "p": <pubkey-for-white>, // if game not found, this is the author of event reacted to
* "p": <pubkey-for-black>, // only if game was found, this is the other player
* ],
* "content": <error message>
* ...
* }
*
* If the game is not known:
* {
* "pubkey": <server>,
* "kind": 20304
* "tags": [
* ["e": <event-that-was-in-error>],
* ["p": <pubkey-of-error-event>],
* ],
* "content": <error message>
* ...
* }
*/
NOTES:
1. FEN notation: https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
2. Long algebraic move is just the source, then the dest, then the promotion piece if it is a pawn promotion, e.g. b7b8Q or e2e4 or b1c3.
3. The engine does not detect checkmate, for the time being you have to submit 3 illegal moves to lose.
4. If I restart the engine (and I surely will) it will forget all the current games.
The client does NOT need to understand chess. But it should understand the 8x8 board, the initial piece layout, moving a piece from source to destination, and allowing the player to move a piece and submit that to the server.
Love this! I do the same. When my main project is getting bumpy I write something fun to get that win!
I’ve been wanting to build an open world space strategy game on Nostr where relays are different galaxies with randomly generated resources that can be mined via pow events. Haven’t really put much thought into it, but I will at some point. 😅
Nice! I do the same thing on bad days. Small victories, especially in something you are passionate about, are the key to nurturing yourself and holding on.