Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement join game function #84

Merged
merged 14 commits into from
Oct 17, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@
"name": "game_mode",
"type": "starkludo::models::game::GameMode"
},
{
"name": "game_status",
"type": "starkludo::models::game::GameStatus"
},
{
"name": "player_green",
"type": "core::felt252"
Expand Down Expand Up @@ -400,6 +404,30 @@
],
"outputs": [],
"state_mutability": "external"
},
{
"type": "function",
"name": "join_game",
"inputs": [
{
"name": "game_id",
"type": "core::integer::u64"
},
{
"name": "player_color",
"type": "core::felt252"
},
{
"name": "username",
"type": "core::felt252"
}
],
"outputs": [
{
"type": "starkludo::models::game::Game"
}
],
"state_mutability": "external"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
kind = "DojoContract"
class_hash = "0x4cecefc87acb36b188cec659cfde8d7cbfafaf8684297f7d66cadd573cbfec5"
original_class_hash = "0x4cecefc87acb36b188cec659cfde8d7cbfafaf8684297f7d66cadd573cbfec5"
class_hash = "0x4822d5336e093bd5060f977312516677c87cda7cc86ebac5941cf148054a2bf"
original_class_hash = "0x4822d5336e093bd5060f977312516677c87cda7cc86ebac5941cf148054a2bf"
base_class_hash = "0x0"
abi = "manifests/dev/base/abis/contracts/starkludo-GameActions-72b46dc4.json"
reads = []
Expand Down
47 changes: 44 additions & 3 deletions onchain/src/systems/game_actions.cairo
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use starkludo::models::{game::{Game, GameTrait, GameMode}, player::{Player}};
use starkludo::models::{game::{Game, GameTrait, GameMode, GameStatus}, player::{Player}};
use starknet::{ContractAddress, get_block_timestamp};
use core::poseidon::PoseidonTrait;
use core::hash::HashStateTrait;


#[dojo::interface]
trait IGameActions {
fn create(
Expand All @@ -18,14 +19,18 @@ trait IGameActions {
fn restart(ref world: IWorldDispatcher, game_id: u64);
fn terminate_game(ref world: IWorldDispatcher, game_id: u64);
fn invite_player(ref world: IWorldDispatcher, game_id: u64, player_username: felt252);
fn join_game(
ref world: IWorldDispatcher, game_id: u64, player_username: felt252, player_color: felt252
);
}


#[dojo::contract]
mod GameActions {
// use Zero;
// use core::num::traits::Zero;
use core::array::ArrayTrait;
use super::{IGameActions, Game, GameTrait, GameMode, Player};
use super::{IGameActions, Game, GameTrait, GameMode, Player, GameStatus};
use starknet::{ContractAddress, get_caller_address, get_block_timestamp};

#[abi(embed_v0)]
Expand All @@ -38,7 +43,7 @@ mod GameActions {
player_yellow: felt252,
player_blue: felt252,
player_red: felt252,
number_of_players: u8
number_of_players: u8,
) -> Game {
// Get the current block timestamp
let id = get_block_timestamp();
Expand Down Expand Up @@ -156,6 +161,42 @@ mod GameActions {
// Update the game state in the world
set!(world, (game));
}


fn join_game( ref world: IWorldDispatcher, game_id: u64, player_username: felt252, player_color: felt252 ) {
let mut game: Game = get!(world, game_id, (Game));

assert(game.game_status == GameStatus::Waiting, 'Game is not pending');

let mut player: Player = get!(world, player_username, (Player));
assert(player.owner != 0.try_into().unwrap(), 'Player does not exist');
let players = array![
game.player_green, game.player_yellow, game.player_blue, game.player_red
];
let players_span = players.span();
let mut i = 0;
while i < 4 {
assert(players_span[i] != @player_username, 'Player already in game');
i += i;
};
match player_color {
0 => game.player_green = player_username,
1 => game.player_yellow = player_username,
2 => game.player_blue = player_username,
3 => game.player_red = player_username,
_ => panic!("Invalid player color")
}

// Update game status if all players have joined
if game.player_green != 0
&& game.player_yellow != 0
&& game.player_blue != 0
&& game.player_red != 0 {
game.game_status = GameStatus::Ongoing;
}

set!(world, (game));
}
}
}

Expand Down
40 changes: 40 additions & 0 deletions onchain/src/tests/test_game.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,45 @@ mod tests {
// // Assert that the player was invited. if false then player was not invited
// assert(is_player_invited, Errors::INVALID_PLAYER);
}


#[test]
#[ignore]
fn test_join_game() {
let caller = contract_address_const::<'Benjamin'>();
let player_red = 'player_red';
let player_blue = 'player_blue';
let player_yellow = 'player_yellow';
let player_green = 'player_green';
let number_of_players = 4;
let game_mode: GameMode = GameMode::MultiPlayer;
testing::set_account_contract_address(caller);
testing::set_contract_address(caller);

let (game, game_actions, world, _) = create_and_setup_game(
game_mode, number_of_players, player_red, player_blue, player_yellow, player_green
);

let game_id: u64 = game.id;
let new_player = 'player_red';
let player_color: felt252 = 0;

// Check game status before joining
let game_before_join = get!(world, game_id, Game);
assert_eq!(
game_before_join.game_status,
GameStatus::Waiting,
"Game should be in Waiting status before joining"
);

// Attempt to join the game
game_actions.join_game(game_id, new_player, player_color);

// Verify the game state after joining
let updated_game = get!(world, game_id, Game);
assert_eq!(
updated_game.player_green, new_player.into(), "Player should have joined the game"
);
}
}

Loading