Bomberman On-Chain Game
Transitional example: This example uses an older Cougr pattern and is preserved for compatibility reference. For the current recommended approach, see
snake.
This example demonstrates how to implement a Bomberman game as a smart contract on the Stellar blockchain using Soroban and cougr-core.
Overview
This contract implements a simplified version of the classic Bomberman game where players can:
- Initialize a game with a grid
- Spawn and move players around the grid
- Place bombs that have individually configurable blast power
- Trigger chain reactions - a bomb overlapped by an explosion detonates instantly in the same tick
- Pick up power-ups that improve stats (blast radius, bomb capacity, movement speed)
- Handle collisions and scoring
- Check for game-over conditions
Setup
Prerequisites
- Rust (latest stable version)
- Cargo
- Stellar CLI (install with
cargo install --locked stellar-cli)
Installation
- Install Rust from https://rustup.rs/
- Install Stellar CLI:
cargo install --locked stellar-cli
Building the Contract
# Build the Rust code
cargo build
# Build the WASM file
stellar contract build
Testing and Validation
# Formatting check
cargo fmt --check
# Lint check
cargo clippy --all-targets --all-features -- -D warnings
# Run unit tests
cargo test
# Build WASM (target wasm32v1-none)
stellar contract build
Game Logic
ECS Components
| Component | Fields | Notes |
|---|---|---|
PlayerComponent | id, x, y, lives, bomb_capacity, score, bomb_power, speed | All player state |
BombComponent | x, y, timer, power, owner_id | Power set from bomb_power at placement time |
ExplosionComponent | x, y, timer | Despawned after EXPLOSION_DURATION ticks |
GridComponent | cells: Vec<CellType> | Walls, destructible blocks |
GameStateComponent | current_tick, game_over, winner_id | Global match state |
PowerUpComponent | x, y, power_up_type | Capacity | Power | Speed |
Power-ups
Three power-up types are supported and modelled as first-class ECS entities:
| Type | Effect |
|---|---|
Capacity | bomb_capacity += 1 - player may place one more active bomb |
Power | bomb_power += 1 - new bombs have a larger blast radius |
Speed | speed += 1 - reserved for future movement throttling |
Power-ups are spawned at game start (deterministic grid positions) and when a
bomb destroys a destructible block (~25% chance via (x+y)%4==0).
Walking over a PowerUpComponent entity silently applies the buff and removes
the entity from the world (PickupSystem).
Chain Reactions
The ChainReactionSystem runs inside update_tick:
- Bombs whose timer hits
0are placed in adetonation_queue. - Each bomb is detonated in order - explosions are spawned immediately.
- After each detonation, every remaining live bomb is checked for overlap with a fresh explosion cell. A hit bomb is removed and pushed to the back of the queue, so it detonates in the same tick - forming a cascade.
- The process repeats until the queue is empty.
Systems at a Glance
| System | Where | What it does |
|---|---|---|
BombTimerSystem | update_tick | Decrements bomb timers |
ChainReactionSystem | update_tick | Cascades detonations within one tick |
ExplosionPropagationSystem | detonate_bomb | Spawns explosion entities in 4 directions |
PowerUpSpawnSystem | init_game + detonate_bomb | Creates PowerUpComponent entities |
PickupSystem | move_player | Applies buff when player steps on a power-up |
Contract Functions
init_game(): Initializes the game statemove_player(player_id, direction): Moves a player in the specified directionplace_bomb(player_id): Places a bomb at the player's current positionupdate_tick(): Advances timers, triggers explosions, handles collisionsget_score(player_id): Returns the current score for a playercheck_game_over(): Checks if the game has ended
Integration with Cougr-Core
This example demonstrates how cougr-core simplifies on-chain game development by providing:
- Persistent storage management for game state
- Transaction validation
- Generic game logic utilities
- Efficient data structures for complex game states
Deployment
Prerequisites for Deployment
- Test Account: Fund a test account using the Friendbot: https://faucet-stellar.acachete.xyz
- Stellar CLI: Install with
cargo install --locked stellar-cli - WASM Build: Ensure the contract builds successfully
To Testnet
-
Build the WASM file:
stellar contract build -
Deploy the contract:
stellar contract deploy \ --wasm target/wasm32v1-none/release/bomberman.wasm \ --source <your-secret-key> \ --network <NETWORK> -
the contract ID for future invocations (e.g.,
<CONTRACT_ID>)
https://stellar.expert/explorer/testnet/account/GAQAXKUQYNBHZYZ2OYISPXDZDP2HV57534VMGARGGIICH2BGNKDTKXOX
Testing the Contract
Invoke functions to test gameplay:
# Initialize game
stellar contract invoke \
--id <contract-id> \
--source <your-secret-key> \
--network <NETWORK> \
-- \
init_game
# Move player (directions: 0=up, 1=right, 2=down, 3=left)
stellar contract invoke \
--id <contract-id> \
--source <your-secret-key> \
--network <NETWORK> \
-- \
move_player \
--player_id 1 \
--direction 1
# Place bomb
stellar contract invoke \
--id <contract-id> \
--source <your-secret-key> \
--network <NETWORK> \
-- \
place_bomb \
--player_id 1
# Update game tick (advances timers, processes explosions)
stellar contract invoke \
--id <contract-id> \
--source <your-secret-key> \
--network <NETWORK> \
-- \
update_tick
# Get player score
stellar contract invoke \
--id <contract-id> \
--source <your-secret-key> \
--network <NETWORK> \
-- \
get_score \
--player_id 1
# Check game status
stellar contract invoke \
--id <contract-id> \
--source <your-secret-key> \
--network <NETWORK> \
-- \
check_game_over
Example Game Sequence
- Initialize: Call
init_gameto set up the world - Spawn Players: In a full implementation, add player spawning functions
- Gameplay Loop:
- Move players with
move_player - Place bombs with
place_bomb - Advance game state with
update_tick - Check scores and game status periodically
- Move players with
- Game Over: Monitor
check_game_overfor completion
Cost Monitoring
Monitor transaction costs during testing:
- Rent: Storage costs on Stellar ledger
- Fees: Network transaction fees
- CPU/RAM: Contract execution costs
Use --simulate flag to estimate costs before actual deployment:
stellar contract invoke --simulate [other flags]
Troubleshooting
Common Issues
- Rust version conflicts: Update Rust with
rustup update - Stellar CLI not found: Ensure it's in your PATH after installation
- Compilation errors: Check that all dependencies are correctly specified in Cargo.toml
Debug Commands
# Verbose build
cargo build --verbose
# Check Stellar CLI version
stellar --version
# Simulate contract deployment
stellar contract deploy --wasm target/wasm32v1-none/release/bomberman.wasm --simulate
Architecture
The contract uses the cougr-core ECS (Entity–Component–System) pattern for all game state:
- Entities: Numeric IDs created by
world.spawn_entity()/ removed byworld.despawn_entity() - Components: Plain structs implementing
ComponentTrait(typedserialize/deserialize) - Systems: Free functions / inline blocks inside contract entry-points that compose over component queries
All state is persisted in a single SimpleWorld under DataKey::World.
The separation of components and systems makes it straightforward to add new mechanics without touching unrelated code.