Pay-To-Play Tic-Tac-Toe

squidKid Deluxe
5 min readMar 22, 2021

I chose to build Pay-To-Play Tic-Tac-Toe for the Reach Bounty Hack as my 7th grade homeschool science fair project. I worked with litepresence and we developed our dApp using Reach and JavaScript. Reach is the safest and easiest blockchain smart-contracting language. It currently supports two blockchains: Algorand and Ethereum. The Reach development team plans to add more smart-contract supporting blockchains in the future. The Bounty Hack program provided an incentive to learn the Reach language to develop dApps. After four weeks of competing in the Bounty Hack-A-Thon, we were thrilled to achieve second place for our Pay-To-Play Tic-Tac-Toe dApp.

Pay-To-Play Tic-Tac-Toe deviates from traditional tic-tac-toe in that each space on the board has a fee that is calculated by how many wins can be made utilizing the chosen space. The game was engineered with a few additional features, listed below:

  • Each fee is scaled to the initial wager so that each player never pays more than the full game wager.
  • A double win occurs when a player gets two sets of three-in-a-rows; that player is awarded their full wager.
  • When the game comes to a tie, each player wins their opponent’s expenditure and loses their own.
  • A 3D version of the game was created by stacking three tic-tac-toe boards on top of each other.
  • It was determined that it was impossible for a player to win if their opponent played the center of the cube, so that move was made “illegal”.

For both the 2D and 3D versions of the game, web and command-line interfaces were created. The web applications were polished as much as possible, with 3D-like perspective planes on the game boards. With the help of litepresence, images were used everywhere in the place of a plain-colored game board.

It wasn’t until I had completed the tutorial and figured out how to get Reach running that I began to feel confident. The first thing that I did was copy all of the finished CLI code for the tic-tac-toe engine within the reach-lang repository into my working folder. When we first asked the Reach community for help, we were struggling with a balance assertion error. Reach CTO Jay McCarthy told us that we were transferring an incorrect amount to the participants after the game was completed. This was corrected by calculating the end funds to be transferred from the wager so that no participant paid more than the wager (which our invariant statement earlier in the code allowed for).

Our 2D version is pretty much exactly the same as regular tic-tac-toe, except for the pay-to-play function discussed earlier. Aided by Reach, this part was not particularly challenging. It was quite the learning experience, however, because it was the first dApp we had ever written. The graphics of the CLI were quite easy because the workshop render() function required very few changes to modify the graphics to a more interesting Calvin-S ASCII-art font (GitHub).

The graphics for the web application were not too difficult, but the perspective on the game board (on different-sized monitors) proved to be a time-consuming challenge. In the backend (taken from the Reach docs), we changed the mathematical calculations from booleans to integers.

The 3D version of Pay-To-Play Tic-Tac-Toe had initially been a game mode. We decided it would go onto our list of things to do if given the chance. When the deadline for Demo Day was extended, we decided to implement it with GUIs similar to what we already had.

Developing it was a good deal more difficult than developing the 2D version — mostly due to the complexities of learning the details of Reach matrix math. The consensus steps of the Reach program went fairly unchanged from 2D to 3D, but the globals and functions were greatly modified. Due to the 27 item long board array, new winning and fee functions had to be created.

We ended up discarding the original idea of using a 3x3x3 matrix due to difficulties creating the correct data type to be passed to and from the board from the JS frontend. litepresence came up with an equation to convert the X, Y, and Z data into a single integer to aid in passing the coordinates of the move from the frontend to the backend (and vice versa).

When attempting to deploy on Algorand, we found that there was a very small byte limit on the size of the compiled consensus steps. Our code for the 2D game originally had a 1600 byte compiled consensus step size; far too large for the Algorand compiler (which wanted less than 1000 bytes). Removing the double-win logic and more efficiently calculating the wins and ties reduced the size of the consensus steps by approximately 200 bytes.

Then Jay McCarthy suggested we try to use boolean math, rather than the integer math methods that we had adopted. After switching the integer math back to boolean math, the consensus size was still slightly too large (at 1039 bytes). After shrinking a few of the winning calculations down to one-line or, or || calculations, we finally managed to get the code under the 1000 byte limit. Due to the byte limit, we were unfortunately unable to deploy the 3D version on Algorand.

If given the opportunity, there are a few things that we would like to change about the game itself as well as the Reach language:

Game changes would include:

  • We would like to add to the game a ‘play again’ button to allow the players to play again using the same contract.
  • Add a “FOMO” game mode (e.g. play until one player is three wins ahead of the other and wins the total pot of all games played).
  • Add a “Best of Three” game mode (where players commit to three games and the winner gets the total pot of all three).
  • Add an AI so that the game could be played by only one person and the developer could incur income by bot.
  • Implement a Python chat server with a JS client for chatting and contract info transfer. litepresence has already developed the Python chat server, which can be found on his GitHub.

Enhancements we’d like to see in Reach include:

  • Improved stack trace on the Reach end would expedite development. The error messages could have been more helpful.
  • Allowing var or let in regular steps would have enabled more sophisticated logic and mathematical statements.
  • Increasing the byte limit on the Algorand compiler, allowing for the development of more advanced games on Algorand (rather than Ethereum).
  • Add a small Reach compiler app which informs a developer how many bytes a given constant or function was (to enable correct sizing for Algorand).

The gas fees for Algorand were also a lot smaller than those on Ethereum. To create a $100 contract on ETH, the gas fee was approximately $77, whereas on ALGO, the fee was about one tenth of a cent. In the end, building Pay-To-Play Tic-Tac-Toe was a lot of fun. We thank the Reach Discord team for helping us through our many problems, talking us through the deployment on Algorand, and providing financial incentive to learn a new language, through their Bounty Hack program.

--

--