Skip to main content

Blackjack

The following documentation goes through an example implementation of the popular casino game blackjack on Sui. This guide walks through its components, providing a detailed look at the module's functions, structures, constants, and their significance in the overall gameplay mechanism.

Building an on-chain blackjack game shares a lot of similarities with a coin flip game. For that reason, this example covers only the smart contracts (Move modules) and frontend logic.

info

For more details on building a backend and deploying to Sui, check out the Coin Flip app example.

You can also find the full repository for this example here.

Gameplay

In this single-player version of blackjack, the player competes against a dealer, which is automated by the system. The dealer is equipped with a public BLS key that plays a central role in the game's mechanics. Players generate randomness for the game by interacting with their mouse on the screen, after which they place their bet to start the game. Upon initiating the game, the dealer's backend, actively listening for the start transaction, processes it by signing and subsequently dealing two cards to the player and one to itself.

The player has the options to 'Hit' or 'Stand.' Selecting 'Stand' triggers the dealer to draw cards until the total reaches 17 or higher. After the dealer stops, typically at a sum of 17 or more, the smart contract steps in to compare the totals and declare the winner. On the other hand, choosing 'Hit' prompts the dealer to draw an additional card for the player.

Smart contracts

Game module

The single_player_blackjack.move module includes several constants that define game statuses and help track the game's progress:

  • IN_PROGRESS
  • PLAYER_WON_STATUS
  • HOUSE_WON_STATUS
  • TIE_STATUS

There are also constants for error handling, such as EInvalidBlsSig, EInsufficientBalance, and others, ensuring robust game mechanics.

Structs like GameCreatedEvent, GameOutcomeEvent, HitRequested, and StandRequested capture the various events and actions within a game. HouseAdminCap and HouseData are crucial for maintaining the house's data, including balance and public key, while the Game struct contains all the necessary information about each game, such as player data, cards, and the current status.

The module's functions can be broadly categorized into initialization, game management, and utility functions. The init function sets up the house admin capability, while initialize_house_data prepares the house for the game by setting up the balance and public key. place_bet_and_create_game is the entry point for players to start a new game, involving a bet and random input. The functions first_deal, hit, and stand govern the core gameplay, handling the dealing of cards and player choices.

Utility functions like get_next_random_card and get_card_sum are essential for the game's mechanics, generating random cards and calculating hand values. The module also includes accessors for retrieving various pieces of game and house data.

For testing purposes, the module provides special functions like set_init_hash_for_testing, get_house_admin_cap_for_testing, and destroy_for_testing, ensuring that developers can thoroughly test the game mechanics and house data handling.

Counter module

The next module, counter_nft.move, introduces the Counter NFT, a key component in the game's mechanics. It serves as the Verifiable Random Function (VRF) input, ensuring uniqueness in each game. The Counter NFT's value increases after each use, maintaining its distinctiveness for every new game. For first-time players, the creation of a Counter NFT is mandatory. To enhance user experience, the user interface can automate this process by integrating the Counter NFT's creation with the game initiation in a single transaction block. This seamless integration simplifies the process for the player, allowing them to focus on the gameplay. This counter serves the same purpose as the one in the Coin Flip example.

Frontend

The BlackjackBoard component, a central element of the blackjack game's frontend module, is structured to create an interactive and responsive gaming experience. Written in React, it integrates several features and functions to handle the game's logic and user interactions effectively.

State management and setup

  • State Hooks: The module uses React's useState to manage various game states, including playerHand, dealerHand, playerTotal, dealerTotal, and more. These states are vital for tracking the current game status and updating the UI accordingly.

  • Randomness Generation: A unique feature of this component is the generation of randomness based on the user's mouse movements (handleMouseMove), used to ensure fair game outcomes. The userCreatedRandomness state stores this data, which is then converted to a hexadecimal string (randomnessHex) for use in the game.

  • Modal for Game Initialization: A modal is implemented to facilitate the creation of a new game. It captures the randomness and uses handlePlayGame from the useGame hook to initiate the game with the backend.

  • Card Management: The component generates a deck of cards and maps them to a Map object (cards) for easy retrieval and display.

UI components and styling

  • Card Display: Cards are rendered using a combination of JSX and CSS, displaying the suit symbols and values, with conditional styling (getSuitColor) based on the card suit.

  • Game Status Updates: The UI provides immediate feedback on game events, such as a bust or game completion, using toasts (toast) and loading indicators (Hearts from react-loader-spinner).

User interaction and feedback

  • Game Creation and Exploration: Players can start new games using a dedicated button that triggers the openNewGameModal function. Links are also provided for players to view game details on the Sui explorer, enhancing transparency and engagement.

  • Mouse Movement Tracking: The module includes functionality to track and utilize mouse movements, contributing to the game's randomness generation, which is crucial for fair play and unpredictability.

Comparison: Blackjack and Coin Flip

Similarities

  • Blockchain-Based Logic: Both games are built on Sui, leveraging its capabilities for decentralized applications. The core game logic for each resides in Move modules, ensuring secure and verifiable gameplay.

  • State Management: In both games, state management is crucial. For blackjack, this involves managing the player and dealer's hands and scores using React state hooks. In Satoshi Coin Flip, the state is managed through Move structs like HouseData, which track the house's balance and other game-related details.

  • Randomness and Fair Play: Both games emphasize randomness for fairness. Blackjack uses a Counter NFT and player mouse movements to generate randomness, while Satoshi Coin Flip only uses a Counter NFT as a unique input for the Verifiable Random Function (VRF) in each game.

  • Smart Contract Interactions: Each game involves smart contract interactions for game actions like placing bets, dealing cards (Blackjack), or making guesses (Coin Flip). These interactions are crucial for executing the game's logic on the blockchain.

Differences

  • Game Mechanics and Complexity: Blackjack is a more complex game with multiple actions (hit, stand, deal) and state updates, requiring a more dynamic frontend. In contrast, Satoshi Coin Flip has a simpler mechanic centered around a single bet and guess outcome.

  • User Interface (UI) Complexity: The Blackjack game involves a more intricate UI to display cards, manage game states, and player interactions. Satoshi Coin Flip, being simpler in gameplay, requires a less complex UI.

  • Backend Processing: In Blackjack, the dealer is automated (the machine), and the player's actions directly influence game outcomes. In the Coin Flip game, the house (smart contract) plays a more passive role, primarily in initializing and finalizing the game based on the player's guess.

  • Module Structure and Focus: The Blackjack game focuses more on frontend interactions and real-time updates. The Satoshi Coin Flip game, however, delves deeper into backend logic, with structures like HouseCap and house_data for initializing and managing game data securely on the blockchain.

  • Multi-Version Implementation: The Satoshi Coin Flip game mentions two versions – one susceptible to MEV attacks and another that is resistant, indicating a focus on security and user experience variations. Such variations aren't implemented in Blackjack.

info

The complete app example can be found in the balackjack-sui repo.