Tequila Train Game
Tequila Train is a game similar to the Mexican Train game but has several differences in rules. Tequila Train involves a hub, trains, and tequila shots, with each player receiving between 4 to 8 tiles at the start. The game has a playable limit of 8 players using 91 tiles.
Rules
Each player receives their dominoes, and the number of tiles they receive is automatically calculated based on the number of players.
- 2...4 players: 8 tiles per each player
- 5 players: 7 tiles per each player
- 6 players: 6 tiles per each player
- 7 players: 5 tiles per each player
- 8 players: 4 tiles per each player
Also, each player gets their own train differentiated by the color. Each player revise their tiles and see if they have matching dot numbers on both sides of one tile. 12 dots is the maximum number of each side. The player with the highest double places it in the center of the Tequila Train Hub. In case of nobody has a tile with matching numbers, each player will receive one additional tile, each player will continue receiving one additional tile till someone will receive the tile with the matching numbers on both sides.
The domino must be placed so that one end is touching the end of a domino already on the table and such that the end of the new domino matches (shows the same number of dots) the end of the domino it is adjacent to. Unless the tile is a double, the tile can be placed square in any one of the three directions as long as the two matching sides are touching fully.
First player only places the first tile (maximum double) and then the turn goes to the next player. If, in a later turn, the player draws a domino that enables them to start their train, they can only play this one domino. The player can remove their train but they are free to leave it as is (see below).
If a player is unable to play and the boneyard is empty, the player must simply pass and ensure that a marker is placed upon their train.
In case if a player doesn’t have a matching tile they put a train in their line and skip their turn. Since they have a train another player can put their tile in the line. For the next turn the player with the train can take additional tile from the tiles pool.
Anyone who wants to get their train back after playing a domino to their track should drink one shot of tequila or they will leave their train on the board.
The aim is to be the first player to get rid of all the dominoes in their hand. As soon as this happens, even if the last tile is a Double, the game ends.
How to run
Source code can be found in the GitHub: https://github.com/gear-dapps/tequila-train
Clone the repo and enter to the project directory:
git clone https://github.com/gear-dapps/tequila-train
cd tequila-train
Build the smart contract
Install Rust on your system using the following command:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Add specific toolchains using these commands:
rustup toolchain add nightly
rustup target add wasm32-unknown-unknown --toolchain nightlyAlternatively, you can run the following command to initialize the contracts:
make init-contracts
Build the contract using the following command:
cd contracts
cargo build --releaseAlternatively, you can run the following command to build the contract:
make contracts
Find the program binary
tequila_train.opt.wasm
incontracts/target/wasm32-unknown-unknown/release
directory, and the meta filetequila_train.meta.txt
incontracts
directory.
Upload program and meta to the network
Go to https://idea.gear-tech.io/ and choose Workshop node (
wss://node-workshop.gear.rs
).Upload the program binary Wasm
contracts/target/wasm32-unknown-unknown/release/tequila_train.opt.wasm
and the meta filecontracts/tequila_train.meta.txt
.Use the list of players' IDs as a payload when initializing the program. For example, if you want to play on behalf of Alice (
0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
) and Bob (0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48
), you are to pass the following init payload:[
"0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d",
"0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48"
]Copy the program ID after successful uploading.
Build and run user interface
Install yarn on your system using the following command:
npm install --global yarn
Install the dependencies using the following command:
yarn --cwd frontend
Alternatively, you can run the following command to install the dependencies:
make init-frontend
Change the program ID to the correct one obtained after uploading the program to the network (see previous steps) in
frontend/.env.example.local
.REACT_APP_NODE_ADDRESS=wss://node-workshop.gear.rs
REACT_APP_GAME_ADDRESS=0x3c1095f86e129b72fab05384bd9ff30bf32e155b5dd58a797ab8a4a941209a77
Build the user interface using the following command:
yarn --cwd frontend build
Alternatively, you can run the following command to build the user interface:
make frontend
Serve the user interface using the following command:
yarn --cwd frontend start
Alternatively, you can run the following command to serve the user interface:
make serve
Once the user interface starts running, players can access the game by visiting the URL on the screen.
Implementation details
One user (he may be a player or not) uploads the game program and initializes it. Initialization data is a vector of players’ public addresses:
pub struct Players {
players: Vec<ActorId>,
}
Program makes all preparations during initialization.
- Each player gets their dominoes; the tile count is calculated automatically depending on the player count.
- The program tries to find the maximum double through users. If it doesn’t, it adds one tile to each user and repeats this step until double has been found.
- Program chooses the double and selects the first user.
#[no_mangle]
extern "C" fn init() {
let players_init: Players = msg::load().expect("Failed to decode `Players'");
// All game initializing logic is inside GameState constructor
unsafe { GAME_STATE = GameState::new(&players_init) }
}
Every player move is the command message sent to the program:
- Pass: skip the turn if there is no tile to place.
- Turn: place selected tile to the selected track. Additionally, in certain circumstances the player may get their train back.
/// Command to the program
pub enum Command {
Skip,
Place {
tile_id: u32,
track_id: u32,
remove_train: bool,
},
}
User interface gets the program state after every action and renders it in the browser.
/// The whole game state
pub struct GameState {
pub players: Vec<ActorId>,
pub tracks: Vec<TrackData>,
pub shots: Vec<u32>,
pub start_tile: u32,
pub current_player: u32,
pub tile_to_player: BTreeMap<u32, u32>,
pub tiles: Vec<Tile>,
pub remaining_tiles: BTreeSet<u32>,
pub state: State,
}
/// Information about the player's track
pub struct TrackData {
pub tiles: Vec<Tile>,
pub has_train: bool,
}
/// Domino tile
pub struct Tile {
pub left: Face,
pub right: Face,
}
/// Tile's face (number of dots)
pub enum Face {
Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Eleven,
Twelve,
}
/// The state of the game
pub enum State {
Playing,
Stalled,
Winner(ActorId),
}
Source code
The source code of the Tequila Train Game smart contract is available on GitHub. They can be used as is or modified to suit your own scenarios.