Skip to content

Commit

Permalink
Merge pull request #10 from danielcdz/feat-add-unit-test-to-battle
Browse files Browse the repository at this point in the history
Feat add unit test to battle
  • Loading branch information
danielcdz authored Sep 8, 2024
2 parents 6746a6c + a13e301 commit 896e0c0
Show file tree
Hide file tree
Showing 5 changed files with 452 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -224,20 +224,16 @@
]
},
{
"type": "struct",
"name": "bytebeasts::models::potion::Potion",
"members": [
{
"name": "potion_id",
"type": "core::integer::u32"
},
"type": "enum",
"name": "core::bool",
"variants": [
{
"name": "potion_name",
"type": "core::felt252"
"name": "False",
"type": "()"
},
{
"name": "potion_effect",
"type": "core::integer::u32"
"name": "True",
"type": "()"
}
]
},
Expand Down Expand Up @@ -273,38 +269,42 @@
"items": [
{
"type": "function",
"name": "check_flee_success",
"name": "init_battle",
"inputs": [
{
"name": "player_beast",
"type": "bytebeasts::models::beast::Beast"
"name": "player_id",
"type": "core::integer::u32"
},
{
"name": "opponent_beast",
"type": "bytebeasts::models::beast::Beast"
"name": "opponent_id",
"type": "core::integer::u32"
}
],
"outputs": [
{
"type": "core::felt252"
"type": "core::integer::u32"
}
],
"state_mutability": "view"
"state_mutability": "external"
},
{
"type": "function",
"name": "apply_item_effect",
"name": "check_flee_success",
"inputs": [
{
"name": "potion",
"type": "bytebeasts::models::potion::Potion"
"name": "player_beast",
"type": "bytebeasts::models::beast::Beast"
},
{
"name": "target",
"name": "opponent_beast",
"type": "bytebeasts::models::beast::Beast"
}
],
"outputs": [],
"outputs": [
{
"type": "core::bool"
}
],
"state_mutability": "view"
},
{
Expand Down Expand Up @@ -343,22 +343,6 @@
"outputs": [],
"state_mutability": "external"
},
{
"type": "function",
"name": "init_battle",
"inputs": [
{
"name": "player_id",
"type": "core::integer::u32"
},
{
"name": "opponent_id",
"type": "core::integer::u32"
}
],
"outputs": [],
"state_mutability": "external"
},
{
"type": "function",
"name": "attack",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
kind = "DojoContract"
class_hash = "0x64c638398690cee9d2bcf829ecddf1f7ffcf3701ed00e2188dcd73fd023331b"
original_class_hash = "0x64c638398690cee9d2bcf829ecddf1f7ffcf3701ed00e2188dcd73fd023331b"
class_hash = "0x22eff2287b74c9f79832f32132c8154f28f916551d8650c8425f6c1c49adc31"
original_class_hash = "0x22eff2287b74c9f79832f32132c8154f28f916551d8650c8425f6c1c49adc31"
base_class_hash = "0x0"
abi = "manifests/dev/base/abis/contracts/bytebeasts-battle_system-461868ac.json"
reads = []
Expand Down
6 changes: 5 additions & 1 deletion src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ mod models {
mod potion;
mod role;
mod world_elements;
}
}

mod tests {
mod test_battle;
}
140 changes: 68 additions & 72 deletions src/systems/battle.cairo
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use starknet::ContractAddress;
use bytebeasts::{models::{beast::Beast, mt::Mt, player::Player, battle::Battle, potion::Potion},};

use bytebeasts::{
models::{beast::Beast, mt::Mt, player::Player, battle::Battle, potion::Potion},
};

#[dojo::interface]
trait IBattleActions {
fn check_flee_success(player_beast: Beast, opponent_beast: Beast) -> felt252;
fn apply_item_effect(potion: Potion, target: Beast);
fn init_battle(ref world: IWorldDispatcher, player_id: u32, opponent_id: u32) -> u32;
fn check_flee_success(player_beast: Beast, opponent_beast: Beast) -> bool;
fn calculate_damage(mt: Mt, attacker: Beast, defender: Beast) -> u32;
fn opponent_turn(ref world: IWorldDispatcher, battle_id: u32);
fn init_battle(ref world: IWorldDispatcher, player_id: u32, opponent_id: u32);
fn attack(ref world: IWorldDispatcher, battle_id: u32, mt_id: u32);
fn use_potion(ref world: IWorldDispatcher, battle_id: u32, potion_id: u32);
fn flee(ref world: IWorldDispatcher, battle_id: u32);
Expand All @@ -17,7 +16,6 @@ trait IBattleActions {
#[dojo::contract]
mod battle_system {
use super::{IBattleActions};
use starknet::{ContractAddress, get_caller_address};
use bytebeasts::{
models::{beast::Beast, mt::Mt, player::Player, battle::Battle, potion::Potion},
};
Expand All @@ -42,84 +40,78 @@ mod battle_system {

#[abi(embed_v0)]
impl BattleActionsImpl of IBattleActions<ContractState> {
// Función para comprobar si se ha conseguido huir
fn check_flee_success(player_beast: Beast, opponent_beast: Beast) -> felt252 {
if player_beast.level > opponent_beast.level {
1 // Success
} else {
0 // Fail
}
}
fn init_battle(ref world: IWorldDispatcher, player_id: u32, opponent_id: u32) -> u32 {
let player = get!(world, player_id, (Player));
let opponent = get!(world, opponent_id, (Player));
let active_beast_player = get!(world, player.beast_1, (Beast));
let active_beast_opponent = get!(world, opponent.beast_1, (Beast));

// Función para aplicar el efecto de una poción
fn apply_item_effect(potion: Potion, mut target: Beast) {
if potion.potion_effect == 1 {
target.current_hp += 20_u32;
if target.current_hp > target.hp {
target.current_hp = target.hp;
}
}
let battle_created_id = 1; // Hardcoded for now
set!(
world,
(Battle {
battle_id: battle_created_id,
player_id: player_id,
opponent_id: opponent_id,
active_beast_player: active_beast_player.beast_id,
active_beast_opponent: active_beast_opponent.beast_id,
battle_active: 1,
turn: 0,
})
);

let message = 'Battle started';
emit!(world, (Status { player_id: player_id, message: message }));

emit!(world, (StatusBattle { battle_id: battle_created_id, message: message }));

return battle_created_id;
}

// Funcion para calcular el daño de un ataque
fn check_flee_success(player_beast: Beast, opponent_beast: Beast) -> bool {
player_beast.level > opponent_beast.level
}

fn calculate_damage(mt: Mt, attacker: Beast, defender: Beast) -> u32 {
let base_damage = mt.mt_power * attacker.attack / defender.defense;

// Aplicar efectividad y otros modificadores (simplificado)
let effective_damage =
base_damage; // Extender con efectividad por tipo, aleatoriedad, etc.
//TODO: extend with effectivity by type, randomness, etc
let effective_damage = base_damage;

// how can we make It random
// TODO: investigate how can we make It random
// let hit_chance = random_felt252() % 100_u32;

let hit_chance = 50_u32; // Hardcoded for now
let hit_chance = 80_u32; // Hardcoded for now
if hit_chance > mt.mt_accuracy {
return 0_u32; // Ataque fallido
return 0_u32;
}

effective_damage
}

// Lógica del turno del oponente
fn opponent_turn(ref world: IWorldDispatcher, battle_id: u32) {
let mut battle = get!(world, battle_id, (Battle));

let mut player_beast = get!(world, battle.active_beast_player, (Beast));
let opponent_beast = get!(world, battle.active_beast_opponent, (Beast));
let mut opponent_beast = get!(world, battle.active_beast_opponent, (Beast));
let opponent_attack = get!(world, opponent_beast.mt1, (Mt));

let damage = self.calculate_damage(opponent_attack, opponent_beast, player_beast);
player_beast.current_hp -= damage;
if damage >= player_beast.current_hp {
player_beast.current_hp = 0;
} else {
player_beast.current_hp -= damage;
}
set!(world, (player_beast));

if player_beast.current_hp <= 0_u32 {
let message = 'Player Beast Knocked Out!';
emit!(world, (StatusBattle { battle_id, message }));
battle.battle_active = 0;
set!(world, (battle));
}
}

// Función para inicializar una batalla
fn init_battle(ref world: IWorldDispatcher, player_id: u32, opponent_id: u32) {
let player = get!(world, player_id, (Player));
let opponent = get!(world, opponent_id, (Player));
let active_beast_player = get!(world, player.beast_1, (Beast));
let active_beast_opponent = get!(world, opponent.beast_1, (Beast));

set!(
world,
(Battle {
battle_id: 1,
player_id: player_id,
opponent_id: opponent_id,
active_beast_player: active_beast_player.beast_id,
active_beast_opponent: active_beast_opponent.beast_id,
battle_active: 1,
turn: 0,
})
);
let message = 'Battle started';
emit!(world, (Status { player_id, message }));
}

// Función para realizar una acción
fn attack(ref world: IWorldDispatcher, battle_id: u32, mt_id: u32) {
let mut battle = get!(world, battle_id, (Battle));

Expand All @@ -134,50 +126,54 @@ mod battle_system {
} else {
opponent_beast.current_hp -= damage;
}
set!(world, (opponent_beast));

if opponent_beast.current_hp <= 0_u32 {
let message = 'Opponent\'s Beast Knocked Out!';
emit!(world, (StatusBattle { battle_id, message }));
let message = 'Opponent Beast Knocked Out!';
emit!(world, (StatusBattle { battle_id, message }));
battle.battle_active = 0;
set!(world, (battle));
} else {
let message = 'Attack Performed!';
emit!(world, (StatusBattle { battle_id, message }));
self.opponent_turn(battle_id);
emit!(world, (StatusBattle { battle_id, message }));
}
}

// Función para usar una poción
fn use_potion(ref world: IWorldDispatcher, battle_id: u32, potion_id: u32) {
let mut battle = get!(world, battle_id, (Battle));

let player_beast = get!(world, battle.active_beast_player, (Beast));
let mut player_beast = get!(world, battle.active_beast_player, (Beast));
let potion = get!(world, potion_id, (Potion));

self.apply_item_effect(potion, player_beast);
if potion.potion_effect <= player_beast.current_hp {
player_beast.current_hp += potion.potion_effect;
}
else {
player_beast.current_hp = player_beast.hp;
}

let message = 'Item Used!';
emit!(world, (StatusBattle { battle_id, message }));
set!(world, (player_beast));
player_beast = get!(world, battle.active_beast_player, (Beast));

// Turno del oponente
self.opponent_turn(battle_id);
let message = 'Item Used!';
emit!(world, (StatusBattle { battle_id, message }));
}

// Función para huir
fn flee(ref world: IWorldDispatcher, battle_id: u32) {
let mut battle = get!(world, battle_id, (Battle));

let player_beast = get!(world, battle.active_beast_player, (Beast));
let opponent_beast = get!(world, battle.active_beast_opponent, (Beast));

let flee_success = self.check_flee_success(player_beast, opponent_beast);
if flee_success == 1 {
if flee_success {
battle.battle_active = 0;
set!(world, (battle));
let message = 'Player Fled!';
emit!(world, (StatusBattle { battle_id, message }));
} else {
let message = 'Flee failed!';
emit!(world, (StatusBattle { battle_id, message }));
self.opponent_turn(battle_id);
emit!(world, (StatusBattle { battle_id, message }));
}
}
}
Expand Down
Loading

0 comments on commit 896e0c0

Please sign in to comment.