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

feat(contract): implement end_turn #37

Merged
merged 8 commits into from
Aug 24, 2023
Merged

feat(contract): implement end_turn #37

merged 8 commits into from
Aug 24, 2023

Conversation

rkdud007
Copy link
Contributor

@rkdud007 rkdud007 commented Aug 10, 2023

  • end_game _system
    • When someone scored a goal, call this system
    • Reset round and update player score
    • A player has won 2 rounds the game ends
    • Emit EndGame
  • end_game_test

@vercel
Copy link

vercel bot commented Aug 10, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
tsubasa ❌ Failed (Inspect) Aug 24, 2023 2:28pm

@rkdud007
Copy link
Contributor Author

currently end_game_test cause this error : dojoengine/dojo#737

@0xLucqs
Copy link
Contributor

0xLucqs commented Aug 10, 2023

can you format plz ?

contracts/src/events.cairo Outdated Show resolved Hide resolved
contracts/src/systems/end_game.cairo Outdated Show resolved Hide resolved
contracts/src/systems/end_game.cairo Outdated Show resolved Hide resolved
@rkdud007
Copy link
Contributor Author

@LucasLvy , Base on your comment I might confused about Round/Game/Turn terms. Here's my understanding--correct me if i'm wrong:

  • Turn: A player takes an action (e.g., placing a card), computes defense, attacks, etc. Once completed, it's the other player's turn.

  • Round: 1. A player can score a goal to end the round / 2. Ends when neither player has cards left; draw.

  • Game: End when a player wins 2 rounds. Scores can be 0:2 or 1:2. ( no draw )

If this is correct, I would implement all in end_turn system:

end_turn system:
Purpose: Before ending a turn, check if conditions to end the round or game are met.

  1. Retrieve the current game status.
  2. Determine if the round should end (either due to a goal or a draw), and then update the round status.
  3. Check if the game should end and update the game status accordingly.
  • plus if then we need to Add Round component and modify Game component structure

@0xLucqs
Copy link
Contributor

0xLucqs commented Aug 10, 2023

agree with everything you said, and indeed the Draw variant should be removed from the Outcome variant. I don't think we should add a round component though, what would it hold ?

@rkdud007
Copy link
Contributor Author

If we need to track each status of Round also, we need Round as Component ( to store each outcome) . But if we do not need to track it, Then can just use original Game format :)

Round

struct Round {
    #[key]
    game_id: felt252,
    #[key]
    round_id: felt252,
     /// Current turn of the round.
    turn: felt252,
    /// Outcome of Round (player1/player2/draw)
    outcome: Option<Outcome>,
}

Game

struct Game {
    /// Game id, computed as follows pedersen_hash(player1_address, player2_address) ??
    #[key]
    game_id: felt252,
    /// player 1 address.
    player1: ContractAddress,
    /// player 2 address.
    player2: ContractAddress,
    /// Rounds won by the player 1.
    player1_score: u8,
    /// Rounds won by the player 2.
    player2_score: u8,
     /// Rounds
    rounds : Array<Round>,
    /// Winner of the game. As long as it is `None` it means that the game is playing, cannot be Draw
    outcome: Option<Outcome>,
}

@0xLucqs
Copy link
Contributor

0xLucqs commented Aug 10, 2023

I don't think we need to track them. There will be events that the frontend can listen to but we don't need details onchain the scores will be enough

@rkdud007 rkdud007 marked this pull request as draft August 11, 2023 07:43
@rkdud007
Copy link
Contributor Author

rkdud007 commented Aug 11, 2023

Decided to wait until attack and place_card system to be implemented . Reason is :

I would implement `turn_system` like this
 fn execute(ctx: Context, game_id: felt252, turn_calldata: TurnCalldata ){
        let game = get!(ctx.world, game_id, Game);
        // base on turn_calldata info decide attact/placecard
        if () {
        ctx.world.execute('attack_system', attack_calldata);
        else if () {
         ctx.world.execute('place_card_system', place_card_calldata);
         }

        // Switch to the other player's turn
        game.turn += 1,

        // emit EndTurn
        let mut values = ArrayTrait::new();
        serde::Serde::serialize(
            @EndTurn { game_id, turn: game.turn + 1, round_number: game.round_number }, ref values
        );
        emit(ctx, 'EndTurn', values.span());

        // Check round end conditions

        /// THIS IS THE CASE ROUND IS ENDED
        // if score goal 
        // Reset round and update player score
        game.turn = 0;
        if (scored_player == game.player1) {
            game.player1_score += 1;
        } else if (scored_player == game.player2) {
            game.player2_score += 1;
        }

        // emit EndTurn
        let mut values = ArrayTrait::new();
        serde::Serde::serialize(@EndRound { game_id, round_number: game.round_number }, ref values);
        emit(ctx, 'EndRound', values.span());

        /// THIS IS THE CASE GAME IS ENDED
        /// A player has won 2 rounds the game ends
        let mut game_outcome = game.outcome;
        if (game.player1_score == 2) {
            let winner = Outcome::Player1((game.player1));
            game_outcome = Option::Some(winner);
        } else if (game.player2_score == 2) {
            let winner = Outcome::Player2((game.player2));
            game_outcome = Option::Some(winner);
        }

        set!(
            ctx.world, Game {
                game_id: game_id,
                player1: game.player1,
                player2: game.player2,
                player1_score: game.player1_score,
                player2_score: game.player2_score,
                turn: game.turn,
                outcome: game_outcome,
            }
        );
    }
}

where turn_calldata would define about which player chose to do which decision in this turn.

turn_calldata example

enum Decision {
   /// some data needed to get information when execute attack 
   Attack,
   /// some data needed to get information when execute placecard 
   PlaceCard,
}

struct TurnCalldata {
   caller: ContractAddress,
   decision: Decision
}

So again, Base on that, would better to wait until attack (#26 ) and place_card (#23 ) system to implemented. Because end_turn need to imply logic for either attack/place_card during the turn and determine whether end round/game. -- turned into draft.

@rkdud007
Copy link
Contributor Author

after looking at current implemention codes,

  • if score goal, Reset round and update player score will be on attack system.
  • we can pass params used in place_card_system and call that inside end_turn, but i don't think its necessary.

So just implemented turn switch and end game base on score

@rkdud007 rkdud007 changed the title feat(contract): implement end_game feat(contract): implement end_turn Aug 23, 2023
contracts/src/events.cairo Outdated Show resolved Hide resolved
contracts/src/systems/end_turn.cairo Outdated Show resolved Hide resolved
contracts/src/systems/end_turn.cairo Outdated Show resolved Hide resolved
@vercel
Copy link

vercel bot commented Aug 24, 2023

@rkdud007 is attempting to deploy a commit to the keep-starknet-strange Team on Vercel.

A member of the Team first needs to authorize it.

@0xLucqs 0xLucqs merged commit fc6d538 into keep-starknet-strange:main Aug 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants