BVM
  • About bvm
    • Development infrastructure for Bitcoin
    • Follow our progress
  • getting started
    • Build a Bitcoin L2 with BVM Studio
    • Level up with Bitcoin dapps
    • Deploy your own Bitcoin dapp
  • L1 Scaling solutions
    • What are Bitcoin Shards? [WIP]
    • Compute sharding [WIP]
    • Data sharding [WIP]
    • Case studies [WIP]
      • SHARD_BVM
        • Bitcoin Virtual Machine #0
      • SHARD_DA [WIP]
      • SHARD_AI [WIP]
  • L2 Scaling solutions
    • What are Bitcoin rollups?
    • Optimistic rollups
    • ZK rollups
  • l3 scaling solutions
    • What are Bitcoin appchains?
    • Rollups from appchains to L2s
  • Bitcoin decentralized bridges
    • Bitcoin <> BVM bridge
    • Bitcoin <> Ethereum bridge [WIP]
    • Bitcoin <> Solana bridge [WIP]
  • bvm studio
    • Overview
    • Build a Bitcoin L2
    • Monitor a Bitcoin L2
    • Scale a Bitcoin L2
    • Building blocks
  • bitcoin heartbeats
    • Overview
    • Chain heartbeats
      • Key metrics
      • Bitcoin's 5 levels of scalability
    • Wallet heartbeats [WIP]
    • Dapp heartbeats [WIP]
  • bitcoin api
    • RaaS API
    • Chain API [WIP]
  • bitcoin dapps
    • Overview
    • EVM code tutorials
      • Build a Bitcoin Name System
      • Build an Ordinals alternative
      • BFS: Build an IPFS alternative
      • Decentralized AI
      • Auction
      • Decentralized Discord
      • Fully onchain Tic-Tac-Toe
      • BRC-721: NFTs
      • Operate your project using a DAO
      • Raise funds through a Crowdsale
      • Issue your own governance token
    • SVM code tutorials [WIP]
Powered by GitBook
On this page
  • Write the Tic Tac Toe smart contracts
  • Deploy the contracts
  • Build an UI to interact with the Tic Tac Toe contracts
  1. bitcoin dapps
  2. EVM code tutorials

Fully onchain Tic-Tac-Toe

Let's build Trustless Tic Tac Toe, a decentralized, unstoppable, and open game.

  • create a new match.

  • seek and match with another player based on Elo ranking.

  • play Tic Tac Toe.

  • update Elo ranking to use for better matching in the future matches.

You can treat this Tic Tac Toe tutorial as a template for implementing a PvP turn based game so you can build your own future games.

Write the Tic Tac Toe smart contracts

It turns out that writing the Tic Tac Toe smart contract is pretty simple.

First, we need to extend TurnBasedGame contract that implemented the following standard functions that will need for building PvP turn based games:

  • turnDuration: the duration of each turn

  • turnTimePivot: the starting time of the current turn

  • player1TimePool, player2TimePool: the total game time (countdown) for the two players

  • findMatch: the game only allows a maximum of one waiting match. If there is one available then use joinMatch, if not then use createMatch

  • createMatch: create a new match, may need to override to add game setup logic, player state

  • joinMatch: join an existing match

  • cancelMatch: cancel the match, can only be called after createMatch but before any player joins

  • affirmTimeOut: Normally, when a timeout occurs, the losing client will call resign to trigger the endGame function. Suppose the losing client is disconnected, the winning client can proactively call affirmTimeOut to end the game.

  • resign, offerDraw, cancelDraw, rejectDraw, acceptDraw: functions as their names suggest, no specific notes

  • getTurn: returns (bool, int256, int256) which includes:

    • the current player's turn (true for player1, false for player2)

    • the remaining time for the current turn (can be negative when the match times out)

    • the total remaining time for the current player's turn

  • The initial ELO of a new player is set to 1500 by default in the DEFAULT_ELO variable.

Of course, you can also override these functions to your custom logic if needed. The complete TurnBasedGame smart contract code can be found at:

Next, we need to implement an additional move function for players to submit their moves. This function should include game logic, check for timeouts, and update the turn in MatchData. If the game reaches a win/loss result, the endGame function should be called. When you build your own game, you will need to implement this function for your game logic.

function makeMove(uint256 _matchId, uint _xCoordinate, uint _yCoordinate, bool _checkWinner) external notTimeOutMatch(_matchId) notEndedMatch(_matchId) {
        Game storage game = games[_matchId];
        bool p1Turn = matches[_matchId].turn;

        if (game.board[_xCoordinate][_yCoordinate] != Players.None) {
            revert MoveProhibited();
        }

        unchecked {
            uint40 timeUsed = uint40(block.timestamp - matches[_matchId].turnTimePivot);

            if (p1Turn) {
                if (msg.sender != matches[_matchId].player1) revert MoveProhibited();
                matches[_matchId].player1TimePool -= timeUsed;
                game.board[_xCoordinate][_yCoordinate] = Players.PlayerOne;
            } else {
                if (msg.sender != matches[_matchId].player2) revert MoveProhibited();
                matches[_matchId].player2TimePool -= timeUsed;
                game.board[_xCoordinate][_yCoordinate] = Players.PlayerTwo;
            }
            matches[_matchId].totalMoved++;
            matches[_matchId].turn = !p1Turn;
            matches[_matchId].turnTimePivot = uint40(block.timestamp);

            emit Move(_matchId, msg.sender, uint8(_xCoordinate), uint8(_yCoordinate), timeUsed);

            if (_checkWinner) {
                Winners winner = calculateWinner(_matchId, _xCoordinate, _yCoordinate);
                if (winner != Winners.None) {
                    MatchResult result = MatchResult(uint8(winner));
                    endGame(_matchId, result);
                }
            }
        }
    }

Deploy the contracts

We've published the game’s repository to Github for you to get started.

git clone https://github.com/TrustlessComputer/tic-tac-toe-game-template

To compile the contracts, use the built-in hardhat compile task.

cd contracts
npm install
npx hardhat compile

Finally, to deploy the contracts, review config file hardhat.config.ts. The network configs should look like this.

networks: {
    nos: {
      url: "https://node.l2.trustless.computer/",
      accounts: {
        mnemonic: "<your mnemonic with funds>"
      },
      timeout: 100_000,
    },
    blockscoutVerify: {
      blockscoutURL: "https://explorer.l2.trustless.computer/",
      ...
    }
  }

Run the deploy scripts using hardhat-deploy.

cd contracts
npx hardhat run --network nos scripts/1-TicTacToe.ts
Make sure the accounts in hardhat.config.ts have some $BVM.

Build an UI to interact with the Tic Tac Toe contracts

There are two things the game UI needs to support so players can interact with Tic Tac Toe contracts above via the UI:

  • Creating transactions for creating a new game, making a move to the Tic Tac Toe contract via web3 libraries and then displaying the game state on the UI.

The complete Tic Tac Toe game UI code can be found at:

Build the source code:

yarn install
yarn dev

and view it on browser at http://localhost:6010. The game UI should look like this:

Happy building!

PreviousDecentralized DiscordNextBRC-721: NFTs

Last updated 10 months ago

The complete TicTacToe smart contract code can be found at:

Creating an internal NOS wallet. This is an EVM-compatible wallet, players need to buy from and send TC token to the wallet so that they can create transactions to the Tic Tac Toe contract and pay NOS network gas fee.

We have deployed the full Tic Tac Toe source code on NOS mainnet, you can experience the final result at:

topup page
https://newbitcoincity.com/tic-tac-toe
https://github.com/TrustlessComputer/tic-tac-toe-game-template/blob/main/contracts/contracts/TurnBasedGame.sol
https://github.com/TrustlessComputer/tic-tac-toe-game-template/blob/main/contracts/contracts/TicTacToe.sol
https://github.com/TrustlessComputer/tic-tac-toe-game-template/tree/main/ui