Pawno: terminal pleasure
Last summer I was about to start a new job where I’d be working with the Go programming language on a daily basis. Not having used it before and with a few weeks of freedom between jobs, I decided to implement a little chess engine in Go as a learning exercise. It turned out to be sufficiently interesting that I didn’t abandon the project and this week I reached a point where it finally felt usable enough to share. So, ladies and gentlemen, I give you: Pawno. A free, open-source, multiplayer chess game that runs in your terminal.
Pawno is released under the AGPL. You can find the source code and pre-built releases on GitLab. It’s also available in some package managers and there’s a yolo-install script for the brave/foolhardy. See the install instructions for more information.
In Pawno you can play chess locally against bot opponents or online versus other humans. The bot opponents aren’t very good, so you’re unlikely to get a decent game out of them. Network games are more interesting.
Network games don’t require an account or any kind of signup. Instead, ephemeral sessions are generated on the backend when creating and joining them. The creator of a network game receives a join code to be shared with the friend (or enemy) they want to play against. They need to share that join code through some other channel (email, Slack etc). Join codes are single-use and after both players have joined, they’re taken to the game board and can play a game of chess by taking turns to enter moves in an intuitive (hopefully) TUI.
There are some UI limitations currently, which I may or may not fix in the near future:
To castle, select your king as the piece and move it 2 squares left or right. There’s no dedicated UI for castling.
There’s no UI for making draw offers yet, although the mechanism exists in the backend and the game engine.
The backend runs on tiny (cheap) instances, so I made some design decisions to try and prevent resource exhaustion:
Local state: Player identity, user preferences and results are all stored locally. There are no persistent identifiers for players on the backend. That means there’s no shared leaderboard. As far as the server’s concerned, every game features 2 brand new players. If a bug or a game update causes bad local state, you can edit it or even delete the whole file on disk. Ditto if the leaderboard annoys you. 🙂
On Linux:
~/.local/share/pawno/state.jsonOn MacOS:
~/Library/Application\ Support/pawno/state.jsonOn Windows:
%APPDATA%\pawno\state.json
Aggressive connection management. Clients are configured to send heartbeats at 20-second intervals. If a minute passes without the server receiving an authenticated request (heartbeat or turn) from a connected client, the game is ended and signalled as a win for the opposing player. There’s no way to resume or reconnect games that have ended this way. 😔
Rate limiting. Unauthenticated requests, i.e. creating and joining network games, are rate-limited per IP address to discourage abuse. At some point, this will probably become insufficient mitigation and I’ll have to turn off the backend. Enjoy it while it lasts! ðŸ˜
If the backend survives long enough, I have a vague intention to write a native iOS client at some point, as an excuse to learn Swift. But other than that, I’m not planning to add new features. There’ll be no account creation or persistent identity or centralised leaderboard or in-game communication or anything like that. I plan to fix bugs for as long as it survives, but not much else.
If you find a bug, or multiple bugs (let’s face it, this is not unlikely), please let me know by opening an issue. I might be slow to respond on weekdays but if it’s a Saturday or Sunday I’ll do my best to fix it quickly.
And that’s it, hope you enjoy!