Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

244 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

♠️ ♥️ Solitaire ♣️ ♦️

Introduction

The following documentation goes through an example implementation of the popular game Solitaire 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.

The Blockchain-based Single Player Solitaire Game is designed to provide a decentralized and secure gaming experience for enthusiasts of the classic Solitaire card game. Leveraging blockchain technology ensures transparency, immutability, fairness and transaction speed in the gaming process. This use case outlines the key features and benefits of integrating Solitaire with Sui for a single-player gaming experience.

Gameplay

In this on-chain version of Klondike solitaire, the player creates a game whose rules are entirely governed by the smart contract. The player has the ability to choose between two modes: Normal mode which is the original Klondike solitaire and Easy mode which is a game with all the Aces placed on the piles. After initiating the game, the player has to place all the cards starting from Ace to King of each suit to the respective pile. The allowed moves are opening one deck card each time, placing a card from deck to column or a pile, placing a card from column to a different column or a pile and placing a card from pile to column. When the player manages to place all cards to the 4 piles, he needs to click the button "View Results" to register the win onchain and be able to view the history of past games.

Smart Contracts

The smart contract of Solitaire consists of one module solitaire.move which includes all the rules and the state of the game.

Constants: Those constants are some indexes that serve as a reference for solitaire rules enforcing

    const CARD_COUNT: u64 = 52;
    const PILE_COUNT: u64 = 4;
    const COLUMN_COUNT: u64 = 7;
    const CLUBS_INDEX: u64 = 0;
    const SPADES_INDEX: u64 = 13;
    const HEARTS_INDEX: u64 = 26;
    const DIAMONDS_INDEX: u64 = 39;

Structs: As mentioned above the entire game is an onchain object which is represented by the Game struct:

    struct Game has key {
        id: UID,
        deck: Deck,
        piles: vector<Pile>,
        columns: vector<Column>,
        // This is the stack with all the cards that are not revealed yet
        available_cards: vector<u64>,
        player: address,
        start_time: u64,
        end_time: u64,
        player_moves: u64,
        difficulty: String,
    }

The Deck object starts with all the cards hidden, and each time a card is revealed, it is added in the card vector of the Deck, with the open_deck_card function. Once all cards are revealed, the function rotate_open_deck_cards is used to get the next card.

The piles vector consists of the 4 piles and each Pile object has the cards that are placed on top of it. The columns vector consists of the 7 columns and each Column object has a number of hidden_cards and a vector with the cards that are placed on it. The available_cards vector contains all the cards that are not revealed yet.

Game as Owned Object: Each game created with the function init_normal_game or init_easy_game is a single owned object by the account who invokes one of those functions. With that approach we ensure that move transactions are executed with low latency since we take advantage of the fast path.

Randomization:

The game utilizes Sui's native onchain randomness API for all random card operations, ensuring truly unpredictable and verifiable randomness. This implementation leverages Sui's built-in randomness beacon, which provides cryptographically secure random values that are deterministic within each transaction but unpredictable across transactions.

The randomness is used primarily during game initialization for card shuffling and deck setup. The randomness API ensures that each game starts with a properly shuffled deck while maintaining the integrity and fairness that blockchain gaming requires.

Frontend

In the development of our frontend, we have leveraged Next.js alongside React, as well as the Sui TypeScript SDK to facilitate interactions with the smart contract. To enhance the user experience, we have integrated the game rules directly within the frontend interface. This approach ensures that users are guided through legal gameplay, preventing potential transaction errors whenever an illegal move is attempted.

System Overview

A C4 diagram is available to visually represent all the aforementioned components and their interactions here: https://github.com/MystenLabs/solitaire/tree/main/docs. To access the diagram you can either:

  1. Copy+paste the contents of workspace.dsl to the structurizr’s DSL
  2. Run docker compose up and access the diagram on localhost:8080

About

An on-chain version of the solitaire card game.

Resources

Stars

3 stars

Watchers

18 watching

Forks

Releases

Packages

Used by

Contributors

Languages