Inspiration
We were inspired by websites where crowds can interact together on the same piece of content - /r/place and more recently websites like onemillioncheckboxes.com. We wanted to see what happens if a group of people played chess together, if the wisdom of crowds really works or if the lowest common denominator would win.
We were also excited to create group experiences based around streamers, similar to where streamers battled their viewers in games, which Eric Rosen did here, or subscriber battles, where two chess streamers' subscribers compete in a tournament e.g. this clip from Hikaru vs GothemChess. Rhess lets two teams play against each other, which as far as we know hasn't been done before.
We’d also love to see the game used for settling silly arguments - in a game with teams Pineapple on Pizza vs Pizza Purists, who is smarter?
What it does
/r/rhess is a subreddit where you can play Rhess. On it, you can create games, share them and play them.
When creating a game you may configure the team names for who plays White or Black, who may join which team, the start time for the game and more. This creates a new game post with a countdown timer until the game begins. Users may then join a team on that post, and they’ll be notified when the game starts. When it's your team's turn, you may vote for the next move, and the vote with the most moves gets played.
How we built it
- devvit
We built Rhess using the Devvit API in typescript to create custom “blocks” posts, store data in redis, and schedule private messages for the game starting.
- chess.js
We used the open source chess.js library to handle move notation, validation, and the chess logic for us. E.g. What are the possible moves for a piece, and is it currently game over?
- python
We used python to compile some open source (CC0) assets (pixel art chess pieces and fonts) to SVG format for use in the game. We wrote our own SVG font handling for text rendering - including word and letter breaks, and auto scaling text to fit a div.
Challenges we ran into
- How to make a move with peer-to-peer?
Devvit doesn’t have a traditional server-client architecture. You can schedule code to run on the server with a certain interval, but it isn’t designed to be run often. No matter how short you set the interval, it can often take over a minute before the code runs, which isn’t good enough when we want moves to be made in less than 30 seconds.
So the challenge was how do we accomplish this with peer-to-peer? Essentially, every 30 seconds (or whatever the move timer is set to) we want one of the clients to act as the server, and make a chess move. If all the clients try updating at the same time, you can get race conditions, where 1 client is voting for a move, while 2 clients are trying to pick a move to play, and different clients end up retrieving different board states from the server.
What we went with was using redis transactions. By watching the state of the board in redis for that particular post, all the updates to the data can be done in a transaction. Whichever client completes their transaction first actually updates the server, while all the other client’s transactions fail, and they simply retrieve the new server state.
- Bug with sorted set in a transaction
We wanted to use a sorted set to store the vote counts for each move, but updating the sorted set in a transaction was throwing an error. We reported it on discord, and it did end up being fixed. But in the meantime, we just switched to using a hashset, and sorting the data ourselves. The amount of data stored here will never be too great, so it wasn’t a big deal :)
- How to restrict which players can be on each team?
We imagined that some users would like to restrict which players can join each team. E.g. A steamer may want to be the only player on their team v.s. everybody else. We initially thought about creating a whitelist of usernames for each side. But we decided that it’s a bit of a hassle, and can easily lead to mistakes and wasted time. So instead, when a Rhess post is created, we added optional password fields for each team. And then you can only join a password-protected team if you enter the correct password.
Accomplishments that we're proud of
It was really cool to see the game actually working! I think it was more of a challenge to get the project done with blocks rather than webview, and we’re proud that we managed to make it work.
What we learned
We learned that it was a good choice to get something working early! By working hard early on, we got the project off to a good start. There was some structure to the code, so it made it easier to work on different parts of the code at the same time, without ending up with lots of merge conflicts. And it meant we had enough time to get all the features done that we wanted to, because it always takes longer than you expect.
We learned that it’s good to test your code often! No matter what framework you are using, reading the docs doesn’t always tell you the full story. By testing the code often, we quickly found out the following, and we could make sure to come up with workarounds before continuing:
- The scheduler didn’t run consistently often enough to be used for making moves
- Updating a sorted set in a transaction throws an error
- Updating client state within useAsync doesn’t work
What's next for Rhess
We think the game is in a good state right now. It would be very nice to see a streamer try it out!
Built With
- chess.js
- devvit
- redis
- scheduler
- typescript

Log in or sign up for Devpost to join the conversation.