From 9a964c5e680b64ede04e27a613ea84349fe61e13 Mon Sep 17 00:00:00 2001 From: danielcdz Date: Fri, 13 Jun 2025 20:20:27 -0600 Subject: [PATCH] Implement Battle trait --- .../combat_game/src/models/battle.cairo | 105 +++++++++++++++++- .../dojo_examples/combat_game/src/store.cairo | 40 +------ 2 files changed, 108 insertions(+), 37 deletions(-) diff --git a/backend/dojo_examples/combat_game/src/models/battle.cairo b/backend/dojo_examples/combat_game/src/models/battle.cairo index 2e9e80b..0378e89 100644 --- a/backend/dojo_examples/combat_game/src/models/battle.cairo +++ b/backend/dojo_examples/combat_game/src/models/battle.cairo @@ -1,5 +1,11 @@ -use starknet::ContractAddress; -use combat_game::types::battle_status::BattleStatus; +use starknet::{ContractAddress, get_block_timestamp}; +use core::num::traits::zero::Zero; +use combat_game::{ + helpers::{pseudo_random::PseudoRandom::generate_random_u8}, + types::{ + battle_status::BattleStatus, + }, +}; #[derive(Copy, Drop, Serde, Debug, Introspect, PartialEq)] #[dojo::model] @@ -12,5 +18,100 @@ pub struct Battle { pub status: BattleStatus, pub winner_id: ContractAddress, pub battle_type: u8, + pub timestamp_start: u64, + pub timestamp_last_action: u64 } +#[generate_trait] +pub impl BattleImpl of BattleTrait { + fn new(id: u256, player1: ContractAddress, player2: ContractAddress, battle_type: u8) -> Battle { + let current_timestamp = get_block_timestamp(); + let players = array![player1, player2]; + Battle { + id: id, + player1: player1, + player2: player2, + current_turn: *players + .at( + generate_random_u8( + id.try_into().unwrap(), 0, 0, players.len().try_into().unwrap() - 1, + ) + .into(), + ), + status: BattleStatus::Waiting, + winner_id: Zero::zero(), + battle_type: battle_type, + timestamp_start: current_timestamp, + timestamp_last_action: current_timestamp + } + } + + fn end(ref self: Battle, winner: ContractAddress ) { + self.status = BattleStatus::Finished.into(); + self.winner_id = winner; + self.timestamp_last_action = get_block_timestamp(); + } + + fn update_timestamp(ref self: Battle) { + self.timestamp_last_action = get_block_timestamp(); + } + + fn is_active(ref self: Battle) -> bool { + self.status == BattleStatus::Active + } + + fn is_finished(ref self: Battle) -> bool { + self.status == BattleStatus::Finished + } + + fn switch_turn(ref self: Battle) { + self.current_turn = if self.current_turn == self.player1 { self.player2 } else { self.player1 }; + } + +} + +#[cfg(test)] +mod tests { + use starknet::{contract_address_const}; + use super::{Battle, BattleTrait}; + + #[test] + fn test_end() { + let mut battle = testing_battle(); + let winner = contract_address_const::<0x1>(); + battle.end(winner); + + assert!(battle.winner_id == winner); + } + + #[test] + fn test_is_active() { + let mut battle = testing_battle(); + + assert!(battle.is_active() == false, "Wrong battle status"); + } + + #[test] + fn test_is_finished() { + let mut battle = testing_battle(); + + assert!(battle.is_finished() == false, "Wrong battle status"); + } + + #[test] + fn test_switch_turn() { + let mut battle = testing_battle(); + + let current_turn = battle.current_turn; + + battle.switch_turn(); + assert!(battle.current_turn != current_turn); + } + + // MOCK + fn testing_battle() -> Battle { + BattleTrait::new(1, contract_address_const::<0x1>(), contract_address_const::<0x2>(), 1) + } +} + + diff --git a/backend/dojo_examples/combat_game/src/store.cairo b/backend/dojo_examples/combat_game/src/store.cairo index dad22e9..e594ea4 100644 --- a/backend/dojo_examples/combat_game/src/store.cairo +++ b/backend/dojo_examples/combat_game/src/store.cairo @@ -1,10 +1,10 @@ use dojo::{model::ModelStorage, world::WorldStorage}; use core::num::traits::zero::Zero; use combat_game::{ - helpers::{pseudo_random::PseudoRandom::generate_random_u8}, constants::SECONDS_PER_DAY, + constants::SECONDS_PER_DAY, models::{ player::Player, beast::{Beast, BeastTrait}, skill, skill::{Skill, SkillTrait}, - beast_skill::BeastSkill, beast_stats::{BeastStats, BeastStatsActionTrait}, battle::Battle, + beast_skill::BeastSkill, beast_stats::{BeastStats, BeastStatsActionTrait}, battle::{Battle, BattleTrait}, }, types::{ beast_type::BeastType, skill::SkillType, status_condition::StatusCondition, @@ -234,45 +234,15 @@ impl StoreImpl of StoreTrait { player2: ContractAddress, battle_type: u8, ) -> Battle { - let players = array![player1, player2]; - let battle = Battle { - id: battle_id, - player1, - player2, - current_turn: *players - .at( - generate_random_u8( - battle_id.try_into().unwrap(), 0, 0, players.len().try_into().unwrap(), - ) - .into(), - ), - status: BattleStatus::Waiting, - winner_id: Zero::zero(), - battle_type: battle_type, - }; + let battle = BattleTrait::new(battle_id, player1, player2, battle_type); self.world.write_model(@battle); battle } fn create_rematch(ref self: Store, battle_id: u256) -> Battle { let battle = self.read_battle(battle_id); - let players = array![battle.player1, battle.player2]; - - let rematch = Battle { - id: battle_id, - player1: battle.player1, - player2: battle.player2, - current_turn: *players - .at( - generate_random_u8( - battle_id.try_into().unwrap(), 0, 0, players.len().try_into().unwrap(), - ) - .into(), - ), - status: BattleStatus::Waiting, - winner_id: Zero::zero(), - battle_type: battle.battle_type, - }; + + let rematch = BattleTrait::new(battle_id, battle.player1, battle.player2, battle.battle_type); self.world.write_model(@rematch); rematch }