Skip to content

Commit

Permalink
✅ Create test
Browse files Browse the repository at this point in the history
  • Loading branch information
bal7hazar committed Sep 27, 2023
1 parent 1e28c13 commit 84161b6
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 92 deletions.
6 changes: 3 additions & 3 deletions Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ initializer_class_hash = "0xbeef"
[tool.dojo.env]
rpc_url = "http://localhost:5050/"
# Default account for katana with seed = 0
account_address = "0x3ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0"
private_key = "0x300001800000000300000180000000000030000000000003006001800006600"
# world_address = "0x7d1f066a910bd86f532fa9ca66766722c20d47462fb99fb2fb0e1030262f9c5"
account_address = "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973"
private_key = "0x1800000000300000180000000000030000000000003006001800006600"
# world_address = "0x6b08c1b1d210f1041b7a861f9cdbb13c09ec9c11cd04daae2cd1bbeede44f61"

# Madara testnet
# rpc_url = "https://api.cartridge.gg/x/shinai/madara"
Expand Down
11 changes: 6 additions & 5 deletions src/components/game.cairo
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
#[derive(Component, Copy, Drop, Serde, SerdeLen)]
struct Game {
#[key]
game_id: u32,
account: felt252,
id: u32,
over: bool,
seed: felt252,
number: u8,
player_count: u8,
}

trait GameTrait {
fn new(player: felt252, game_id: u32, seed: felt252, number: u8) -> Game;
fn new(account: felt252, id: u32, seed: felt252, player_count: u8) -> Game;
fn set_over(ref self: Game, over: bool);
}

impl GameImpl of GameTrait {
fn new(player: felt252, game_id: u32, seed: felt252, number: u8) -> Game {
Game { game_id: game_id, over: false, seed: seed, number: number }
fn new(account: felt252, id: u32, seed: felt252, player_count: u8) -> Game {
Game { account, id, over: false, seed, player_count }
}

fn set_over(ref self: Game, over: bool) {
Expand Down
40 changes: 23 additions & 17 deletions src/entities/map.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use array::{ArrayTrait, SpanTrait};
use nullable::{NullableTrait, nullable_from_box, match_nullable, FromNullableResult};
use poseidon::PoseidonTrait;
use hash::HashStateTrait;
use debug::PrintTrait;

// Internal imports

Expand All @@ -27,6 +28,8 @@ struct Map {
/// Errors module
mod errors {
const INVALID_ARMY_COUNT: felt252 = 'Map: Invalid army count';
const TILES_EMPTY: felt252 = 'Map: Tiles empty';
const INVALID_TILE_NUMBER: felt252 = 'Map: Invalid tile number';
}

/// Trait to initialize and manage tile from the Map.
Expand All @@ -35,37 +38,39 @@ trait MapTrait {
/// # Arguments
/// * `id` - The territory id.
/// * `seed` - A seed to generate the map.
/// * `player_number` - The number of players.
/// * `tile_number` - The number of tiles.
/// * `army_number` - The number of army of each player.
/// * `player_count` - The number of players.
/// * `tile_count` - The number of tiles.
/// * `army_count` - The number of army of each player.
/// # Returns
/// * The initialized `Map`.
fn new(id: u8, seed: felt252, player_number: u32, tile_number: u32, army_number: u32) -> Map;
fn new(id: u8, seed: felt252, player_count: u32, tile_count: u32, army_count: u32) -> Map;
}

/// Implementation of the `TileTrait` for the `Tile` struct.
impl MapImpl of MapTrait {
fn new(id: u8, seed: felt252, player_number: u32, tile_number: u32, army_number: u32) -> Map {
fn new(id: u8, seed: felt252, player_count: u32, tile_count: u32, army_count: u32) -> Map {
// [Check] There is enough army to supply at least 1 unit per tile
assert(player_number * army_number >= tile_number, errors::INVALID_ARMY_COUNT);
assert(player_count * army_count >= tile_count, errors::INVALID_ARMY_COUNT);
// [Compute] Seed in u256 for futher operations
let base_seed: u256 = seed.into();
// Use the deck mechanism to shuffle the tiles
let mut deck = DeckTrait::new(seed, tile_number);
let mut deck = DeckTrait::new(seed, tile_count);
// Each player draw R/N where R is the remaining cards and N the number of players left
let mut realms: Felt252Dict<Nullable<Span<Tile>>> = Default::default();
let mut player_index: u32 = 0;
loop {
if player_index == player_number {
if player_index == player_count {
break;
}
let turns_number = deck.remaining / (player_number - player_index);
let turns_count = deck.remaining / (player_count - player_index);
// [Check] At least 1 tile per player
assert(turns_count > 0, errors::INVALID_TILE_NUMBER);
let mut turn_index = 0;
// Draw the tiles for the current player with a single unit army
let mut remaining_army = army_number;
let mut remaining_army = army_count;
let mut tiles: Array<Tile> = array![];
loop {
if turn_index == turns_number {
if turn_index == turns_count {
break;
}
let tile_id = deck.draw() - 1;
Expand All @@ -75,17 +80,18 @@ impl MapImpl of MapTrait {
turn_index += 1;
};
// Spread army on the tiles
let mut remaining_army = army_number - turns_number;
let mut remaining_army = army_count - turns_count;
let mut tile_index = 0;
let mut nonce = 0;
loop {
if remaining_army == 0 {
break;
}
// Random number between 0 or 1
let (unit, nonce) = _random(seed, nonce);
let (unit, new_nonce) = _random(seed, nonce);
nonce = new_nonce;
// Increase army of the current tile with the unit
let mut tile: Tile = tiles.pop_front().unwrap();
let mut tile: Tile = tiles.pop_front().expect(errors::TILES_EMPTY);
// TODO: Check if it is better to conditonate the following lines
tile.army += unit;
remaining_army -= unit.into();
Expand Down Expand Up @@ -121,9 +127,9 @@ mod tests {

const SEED: felt252 = 'seed';
const PLAYER_NUMBER: u32 = 4;
const TILE_NUMBER: u32 = 42;
const ARMY_NUMBER: u32 = 30;
const NONCE: u32 = 12;
const TILE_NUMBER: u32 = 10;
const ARMY_NUMBER: u32 = 4;
const NONCE: u32 = 0;

#[test]
#[available_gas(100_000)]
Expand Down
6 changes: 5 additions & 1 deletion src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ mod systems {
mod create;
}

mod tests {}
#[cfg(test)]
mod tests {
mod setup;
mod create;
}
23 changes: 12 additions & 11 deletions src/systems/create.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ mod create {
// Errors

mod errors {
const TILES_UNBOX_ISSUE: felt252 = 'Tiles unbox issue';
const TILES_UNBOX_ISSUE: felt252 = 'Tiles: unbox issue';
}

fn execute(ctx: Context, player: felt252, seed: felt252, name: felt252, number: u8) {
fn execute(ctx: Context, account: felt252, seed: felt252, name: felt252, player_count: u8) {
// [Command] Game entity
let game_id = ctx.world.uuid();
let mut game = GameTrait::new(player, game_id, seed, number);
let mut game = GameTrait::new(account, game_id, seed, player_count);
set!(ctx.world, (game));

// [Command] Player entities
// Use the deck mechanism to define the player order, human player is 1
let mut deck = DeckTrait::new(game.seed, game.number.into());
let mut index = 0;
let mut deck = DeckTrait::new(game.seed, game.player_count.into());
let mut player_index = 0;
loop {
if index == game.number {
if player_index == game.player_count {
break;
}
let card = deck.draw() - 1;
Expand All @@ -54,19 +54,20 @@ mod create {
PlayerTrait::new(game_id, card, card.into())
};
set!(ctx.world, (player));
player_index += 1;
};

// [Command] Tile entities
let mut map = MapTrait::new(
id: 1,
seed: game.seed,
player_number: game.number.into(),
tile_number: TILE_NUMBER,
army_number: ARMY_NUMBER
player_count: game.player_count.into(),
tile_count: TILE_NUMBER,
army_count: ARMY_NUMBER
);
let mut player_index = 0;
loop {
if player_index == game.number {
if player_index == game.player_count {
break;
}
let mut tiles = match match_nullable(map.realms.get(player_index.into())) {
Expand All @@ -76,7 +77,7 @@ mod create {
loop {
match tiles.pop_front() {
Option::Some(tile) => {
let tile: TileComponent = tile.convert(game.game_id);
let tile: TileComponent = tile.convert(game.id);
set!(ctx.world, (tile));
},
Option::None => {
Expand Down
79 changes: 79 additions & 0 deletions src/tests/create.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Core imports

use traits::{Into, TryInto};
use core::result::ResultTrait;
use array::{ArrayTrait, SpanTrait};
use option::OptionTrait;
use box::BoxTrait;
use clone::Clone;
use debug::PrintTrait;

// Starknet imports

use starknet::{ContractAddress, syscalls::deploy_syscall};
use starknet::class_hash::{ClassHash, Felt252TryIntoClassHash};

// Dojo imports

use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait};
use dojo::test_utils::spawn_test_world;

// Internal imports

use zrisk::constants::TILE_NUMBER;
use zrisk::components::game::Game;
use zrisk::components::player::Player;
use zrisk::components::tile::Tile;
use zrisk::tests::setup::setup;

// Constants

const ACCOUNT: felt252 = 'ACCOUNT';
const SEED: felt252 = 'SEED';
const NAME: felt252 = 'NAME';
const PLAYER_COUNT: u8 = 4;

#[test]
#[available_gas(1_000_000_000)]
fn test_create() {
// [Setup]
let world = setup::spawn_game();

// [Create]
world.execute('create', array![ACCOUNT, SEED, NAME, PLAYER_COUNT.into()]);

// [Assert] Game
let game: Game = get!(world, ACCOUNT, (Game));
assert(game.id == 0, 'Game: wrong id');
assert(game.seed == SEED, 'Game: wrong seed');
assert(game.over == false, 'Game: wrong status');
assert(game.player_count == PLAYER_COUNT, 'Game: wrong player count');

// [Assert] Players
let mut player_index: u8 = 0;
loop {
if player_index == PLAYER_COUNT {
break;
}
let player: Player = get!(world, (0, player_index).into(), (Player));
assert(player.game_id == game.id, 'Player: wrong game id');
assert(player.order == player_index, 'Player: wrong order');
assert(player.name == player_index.into() || player.name == NAME, 'Player: wrong name');
player_index += 1;
};

// [Assert] Tiles
let mut tile_index: u8 = 0;
loop {
if TILE_NUMBER == tile_index.into() {
break;
}
let tile: Tile = get!(world, (0, tile_index).into(), (Tile));
assert(tile.game_id == game.id, 'Tile: wrong game id');
assert(tile.tile_id == tile_index, 'Tile: wrong tile id');
assert(tile.army > 0, 'Tile: wrong army');
assert(tile.owner < PLAYER_COUNT.into(), 'Tile: wrong owner');
assert(tile.dispatched == 0, 'Tile: wrong dispatched');
tile_index += 1;
};
}
55 changes: 0 additions & 55 deletions src/tests/move.cairo

This file was deleted.

37 changes: 37 additions & 0 deletions src/tests/setup.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
mod setup {
// Core imports

use core::traits::Into;
use array::ArrayTrait;

// Starknet imports

use starknet::ContractAddress;

// Dojo imports

use dojo::world::{IWorldDispatcherTrait, IWorldDispatcher};
use dojo::test_utils::spawn_test_world;

// Internal imports

use zrisk::components::game::{game, Game};
use zrisk::components::player::{player, Player};
use zrisk::components::tile::{tile, Tile};
use zrisk::systems::create::create;

fn spawn_game() -> IWorldDispatcher {
// [Setup] Components
let mut components = array::ArrayTrait::new();
components.append(game::TEST_CLASS_HASH);
components.append(player::TEST_CLASS_HASH);
components.append(tile::TEST_CLASS_HASH);

// [Setup] Systems
let mut systems = array::ArrayTrait::new();
systems.append(create::TEST_CLASS_HASH);

// [Deploy]
spawn_test_world(components, systems)
}
}

0 comments on commit 84161b6

Please sign in to comment.