diff --git a/src/interfaces/IActions.cairo b/src/interfaces/IActions.cairo index 3efdc83..b585b80 100644 --- a/src/interfaces/IActions.cairo +++ b/src/interfaces/IActions.cairo @@ -2,13 +2,6 @@ use dojo_starter::model::game_model::{GameType, Game}; use dojo_starter::model::game_player_model::{PlayerSymbol, GamePlayer}; use dojo_starter::model::player_model::Player; use dojo_starter::model::property_model::{Property, TradeOffer, TradeOfferDetails}; -use dojo_starter::model::utility_model::Utility; -use dojo_starter::model::rail_road_model::RailRoad; -use dojo_starter::model::community_chest_model::CommunityChest; -use dojo_starter::model::chance_model::Chance; -use dojo_starter::model::jail_model::Jail; -use dojo_starter::model::go_free_parking_model::Go; -use dojo_starter::model::tax_model::Tax; use starknet::{ContractAddress}; @@ -35,13 +28,7 @@ pub trait IActions { // Board spaces retrieval fn get_property(self: @T, id: u8, game_id: u256) -> Property; - fn get_utility(self: @T, id: u8, game_id: u256) -> Utility; - fn get_chance(self: @T, id: u8, game_id: u256) -> Chance; - fn get_jail(self: @T, id: u8, game_id: u256) -> Jail; - fn get_go(self: @T, id: u8, game_id: u256) -> Go; - fn get_community_chest(self: @T, id: u8, game_id: u256) -> CommunityChest; - fn get_railroad(self: @T, id: u8, game_id: u256) -> RailRoad; - fn get_tax(self: @T, id: u8, game_id: u256) -> Tax; + fn use_getout_of_jail_chance(ref self: T, game_id: u256) -> bool; fn use_getout_of_jail_community_chest(ref self: T, game_id: u256) -> bool; @@ -65,6 +52,7 @@ pub trait IActions { fn reject_trade(ref self: T, trade_id: u256, game_id: u256) -> bool; + fn leave_game(ref self: T, game_id: u256, transfer_to: ContractAddress); fn counter_trade( ref self: T, game_id: u256, @@ -82,21 +70,10 @@ pub trait IActions { fn roll_dice(ref self: T) -> (u8, u8); fn move_player(ref self: T, game_id: u256, steps: u8) -> u8; fn pay_jail_fine(ref self: T, game_id: u256) -> bool; - // fn handle_chance(ref self: T, game_id: u256, random_index: u32) -> @ByteArray; - // Handling landings on board - // fn draw_chance_card(ref self: T, game_id: u256) -> Chance; - // fn draw_community_chest_card(ref self: T, game_id: u256) -> CommunityChest; - // fn pay_tax(ref self: T, game_id: u256, tax_id: u8) -> bool; - // fn go_to_jail(ref self: T, game_id: u256) -> bool; - - // Jail specific actions - // fn pay_jail_fee(ref self: T, game_id: u256) -> bool; - // fn use_jail_card(ref self: T, game_id: u256) -> bool; // Property transactions fn buy_property(ref self: T, property: Property) -> bool; - fn sell_property(ref self: T, property_id: u8, game_id: u256) -> bool; fn mortgage_property(ref self: T, property: Property) -> bool; fn unmortgage_property(ref self: T, property: Property) -> bool; fn pay_rent(ref self: T, property: Property) -> bool; @@ -112,18 +89,9 @@ pub trait IActions { fn process_community_chest_card( ref self: T, game: Game, player: GamePlayer, card: ByteArray, ) -> (Game, GamePlayer); - // Trading system - // fn offer_trade( - // ref self: T, - // game_id: u256, - // to: ContractAddress, - // offered_property_ids: Array, - // requested_property_ids: Array, - // cash_offer: u256, - // cash_request: u256 - // ); - // fn accept_trade(ref self: T, game_id: u256, trade_id: u256) -> bool; - // fn decline_trade(ref self: T, game_id: u256, trade_id: u256) -> bool; + + fn bankruptcy_check(ref self: T, player: GamePlayer, amount_owed: u256); + fn vote_to_kick_player(ref self: T, game_id: u256, target_player: ContractAddress); // // Auctions // fn start_auction(ref self: T, property_id: u8, game_id: u256); @@ -135,8 +103,6 @@ pub trait IActions { ref self: T, from: GamePlayer, to: GamePlayer, amount: u256, ) -> Array; fn mint(ref self: T, recepient: ContractAddress, game_id: u256, amount: u256); - // Bankruptcy & ending game -// fn declare_bankruptcy(ref self: T, game_id: u256) -> bool; -// fn check_winner(self: @T, game_id: u256) -> Option; -// fn end_game(ref self: T, game_id: u256) -> bool; + + } diff --git a/src/lib.cairo b/src/lib.cairo index a37dae8..6ebf4a9 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -11,13 +11,6 @@ pub mod model { pub mod game_model; pub mod player_model; pub mod property_model; - pub mod utility_model; - pub mod rail_road_model; - pub mod chance_model; - pub mod community_chest_model; - pub mod jail_model; - pub mod go_free_parking_model; - pub mod tax_model; pub mod game_player_model; } diff --git a/src/model/bank_model.cairo b/src/model/bank_model.cairo deleted file mode 100644 index 8b13789..0000000 --- a/src/model/bank_model.cairo +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/model/chance_model.cairo b/src/model/chance_model.cairo deleted file mode 100644 index 9d8a057..0000000 --- a/src/model/chance_model.cairo +++ /dev/null @@ -1,46 +0,0 @@ -#[derive(Copy, Drop, Serde)] -#[dojo::model] -pub struct Chance { - #[key] - pub id: u8, - #[key] - game_id: u256, - name: felt252, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct ChanceToId { - #[key] - pub name: felt252, - pub id: u8, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct IdToChance { - #[key] - pub id: u8, - pub name: felt252, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct ChanceCard { - #[key] - pub id: u8, - #[key] - pub game_id: u256, - pub text: felt252, -} - -pub trait ChanceTrait { - fn new(id: u8, game_id: u256) -> Chance; -} - -impl ChanceImpl of ChanceTrait { - fn new(id: u8, game_id: u256) -> Chance { - Chance { id, game_id, name: 'Chance' } - } -} - diff --git a/src/model/community_chest_model.cairo b/src/model/community_chest_model.cairo deleted file mode 100644 index dc227bf..0000000 --- a/src/model/community_chest_model.cairo +++ /dev/null @@ -1,35 +0,0 @@ -#[derive(Copy, Drop, Serde)] -#[dojo::model] -pub struct CommunityChest { - #[key] - pub id: u8, - #[key] - game_id: u256, - name: felt252, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct CommunityChestToId { - #[key] - pub name: felt252, - pub id: u8, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct IdToCommunityChest { - #[key] - pub id: u8, - pub name: felt252, -} - -pub trait CommunityChestTrait { - fn new(id: u8, game_id: u256) -> CommunityChest; -} - -impl CommunityChestImpl of CommunityChestTrait { - fn new(id: u8, game_id: u256) -> CommunityChest { - CommunityChest { id, game_id, name: 'Community Chest' } - } -} diff --git a/src/model/game_model.cairo b/src/model/game_model.cairo index f5c8de1..ad0ff37 100644 --- a/src/model/game_model.cairo +++ b/src/model/game_model.cairo @@ -1,5 +1,4 @@ use starknet::{ContractAddress, contract_address_const}; -use dojo_starter::model::game_player_model::{GamePlayer, PlayerSymbol, GamePlayerTrait}; // Keeps track of the state of the game #[derive(Serde, Copy, Drop, Introspect, PartialEq)] @@ -206,4 +205,3 @@ pub impl GameBalanceImpl of IGameBalance { true } } - diff --git a/src/model/game_player_model.cairo b/src/model/game_player_model.cairo index 91685c7..1ae05a2 100644 --- a/src/model/game_player_model.cairo +++ b/src/model/game_player_model.cairo @@ -31,6 +31,7 @@ pub struct GamePlayer { pub is_bankrupt: bool, pub is_active: bool, pub jail_turns: u8, + pub strikes: u8, } @@ -80,6 +81,7 @@ impl GamePlayerImpl of GamePlayerTrait { no_section7: 0, no_section8: 0, jail_turns: 0, + strikes: 0, } } diff --git a/src/model/go_free_parking_model.cairo b/src/model/go_free_parking_model.cairo deleted file mode 100644 index 543c912..0000000 --- a/src/model/go_free_parking_model.cairo +++ /dev/null @@ -1,26 +0,0 @@ -#[derive(Copy, Drop, Serde)] -#[dojo::model] -pub struct Go { - #[key] - pub id: u8, - #[key] - pub game_id: u256, - pub name: felt252, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct GoToId { - #[key] - pub name: felt252, - pub id: u8, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct IdToGo { - #[key] - pub id: u8, - pub name: felt252, -} - diff --git a/src/model/jail_model.cairo b/src/model/jail_model.cairo deleted file mode 100644 index 3de5413..0000000 --- a/src/model/jail_model.cairo +++ /dev/null @@ -1,36 +0,0 @@ -#[derive(Copy, Drop, Serde)] -#[dojo::model] -pub struct Jail { - #[key] - pub id: u8, - #[key] - pub game_id: u256, - pub name: felt252, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct JailToId { - #[key] - pub name: felt252, - pub id: u8, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct IdToJail { - #[key] - pub id: u8, - pub name: felt252, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct JailCard { - #[key] - pub id: u8, - #[key] - pub game_id: u256, - pub text: felt252, -} - diff --git a/src/model/property_model.cairo b/src/model/property_model.cairo index 056e57d..d653834 100644 --- a/src/model/property_model.cairo +++ b/src/model/property_model.cairo @@ -130,39 +130,12 @@ pub trait PropertyTrait { fn change_game_property_ownership( ref self: Property, new_owner: ContractAddress, owner: ContractAddress, ) -> bool; - // fn property_transfer( -// initiator_property: Property, initiator: GamePlayer, receiver: GamePlayer, -// ) -> (GamePlayer, GamePlayer, Property); + } impl PropertyImpl of PropertyTrait { - // fn property_transfer( - // mut initiator_property: Property, mut initiator: GamePlayer, mut receiver: GamePlayer, - // ) -> (GamePlayer, GamePlayer, Property) { - // assert(initiator_property.game_id == receiver.game_id, 'Not in the same Game'); - - // // Update the property owner - // initiator_property.owner = receiver.address; - - // // Build a new properties array for initiator excluding the transferred property - // let mut new_properties = array![]; - // let mut i = 0; - // while (i < initiator.properties_owned.len()) { - // let prop = initiator.properties_owned[i]; - // if prop.property_id != initiator_property.property_id { - // new_properties.append(prop); - // } - // i += 1; - // }; - // initiator.properties_owned = new_properties; - - // // Add the property to receiver's properties - // receiver.properties_owned.append(initiator_property); - - // (initiator, receiver, initiator_property) - // } - + fn new( id: u8, game_id: u256, diff --git a/src/model/rail_road_model.cairo b/src/model/rail_road_model.cairo deleted file mode 100644 index 0ba5458..0000000 --- a/src/model/rail_road_model.cairo +++ /dev/null @@ -1,99 +0,0 @@ -use starknet::{ContractAddress, contract_address_const}; -#[derive(Copy, Drop, Serde)] -#[dojo::model] -pub struct RailRoad { - #[key] - pub id: u8, - #[key] - game_id: u256, - pub name: felt252, - pub owner: ContractAddress, - pub cost_of_railroad: u256, - pub is_mortgaged: bool, - pub for_sale: bool, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct RailRoadToId { - #[key] - pub name: felt252, - pub id: u8, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct IdToRailRoad { - #[key] - pub id: u8, - pub name: felt252, -} - -pub trait RailRoadTrait { - fn new(id: u8, game_id: u256, name: felt252) -> RailRoad; - fn change_railroad_ownership( - railroad: RailRoad, new_owner: ContractAddress, owner: ContractAddress, - ) -> bool; - fn get_rent_amount(railroad: RailRoad, railroad_owned: u8) -> u256; - fn mortgage(railroad: RailRoad, owner: ContractAddress); - fn lift_mortgage(railroad: RailRoad, owner: ContractAddress); -} - -impl RailRoadImpl of RailRoadTrait { - fn new(id: u8, game_id: u256, name: felt252) -> RailRoad { - let zero_address: ContractAddress = contract_address_const::<0>(); - RailRoad { - id, - game_id, - name, - owner: zero_address, - cost_of_railroad: 200, - is_mortgaged: false, - for_sale: true, - } - } - - - // change to ref - fn change_railroad_ownership( - railroad: RailRoad, new_owner: ContractAddress, owner: ContractAddress, - ) -> bool { - // after checks - - true - } - - // change to non changing state - fn get_rent_amount(mut railroad: RailRoad, railroad_owned: u8) -> u256 { - let mut rent = 0; - if railroad.is_mortgaged { - return rent; - } - if railroad_owned == 1 { - rent = 25; - } - if railroad_owned == 2 { - rent = 50; - } - if railroad_owned == 3 { - rent = 100; - } - if railroad_owned == 4 { - rent = 200; - } else { - rent = 0; - } - - rent - } - - - // change to ref - fn mortgage(mut railroad: RailRoad, owner: ContractAddress) { // railroad.is_mortgaged = true; - } - - fn lift_mortgage( - mut railroad: RailRoad, owner: ContractAddress, - ) { // railroad.is_mortgaged = false; - } -} diff --git a/src/model/tax_model.cairo b/src/model/tax_model.cairo deleted file mode 100644 index af8a7e4..0000000 --- a/src/model/tax_model.cairo +++ /dev/null @@ -1,27 +0,0 @@ -#[derive(Copy, Drop, Serde)] -#[dojo::model] -pub struct Tax { - #[key] - pub id: u8, - #[key] - pub game_id: u256, - pub name: felt252, - pub tax_amount: u256, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct TaxToId { - #[key] - pub name: felt252, - pub id: u8, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct IdToTax { - #[key] - pub id: u8, - pub name: felt252, -} - diff --git a/src/model/utility_model.cairo b/src/model/utility_model.cairo deleted file mode 100644 index 2accc46..0000000 --- a/src/model/utility_model.cairo +++ /dev/null @@ -1,95 +0,0 @@ -use starknet::{ContractAddress, contract_address_const}; -#[derive(Copy, Drop, Serde)] -#[dojo::model] -pub struct Utility { - #[key] - pub id: u8, - #[key] - game_id: u256, - pub name: felt252, - pub owner: ContractAddress, - pub cost_of_utility: u256, - pub is_mortgaged: bool, - pub for_sale: bool, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct UtilityToId { - #[key] - pub name: felt252, - pub id: u8, -} - -#[derive(Drop, Copy, Serde)] -#[dojo::model] -pub struct IdToUtility { - #[key] - pub id: u8, - pub name: felt252, -} - -pub trait UtilityTrait { - fn new(id: u8, game_id: u256, name: felt252) -> Utility; - fn change_utility_ownership( - utility: Utility, new_owner: ContractAddress, owner: ContractAddress, - ); - fn get_rent_amount(utility: Utility, utilities_owned: u8, dice_rolled: u8) -> u256; - fn mortgage_utility(utility: Utility, owner: ContractAddress) -> bool; - fn lift_utility_mortgage(utility: Utility, owner: ContractAddress) -> bool; - fn up_utility_up_for_sale(ref self: Utility, owner: ContractAddress) -> bool; -} - -impl UtilityImpl of UtilityTrait { - fn new(id: u8, game_id: u256, name: felt252) -> Utility { - let zero_address: ContractAddress = contract_address_const::<0>(); - Utility { - id, - game_id, - name, - owner: zero_address, - cost_of_utility: 150, - is_mortgaged: false, - for_sale: true, - } - } - - - // use ref state - fn change_utility_ownership( - mut utility: Utility, new_owner: ContractAddress, owner: ContractAddress, - ) { //implement after checks especially ownership ... - } - - // change to no change state - fn get_rent_amount(mut utility: Utility, utilities_owned: u8, dice_rolled: u8) -> u256 { - let mut rent = 0; - if utility.is_mortgaged { - return rent; - } - if utilities_owned == 1 { - rent = 4 * dice_rolled.into(); - } - if utilities_owned == 2 { - rent = 10 * dice_rolled.into(); - } - - rent - } - - //change to ref state changing - fn mortgage_utility(mut utility: Utility, owner: ContractAddress) -> bool { - true - } - - //change to ref state changing - fn lift_utility_mortgage(mut utility: Utility, owner: ContractAddress) -> bool { - true - } - - // - fn up_utility_up_for_sale(ref self: Utility, owner: ContractAddress) -> bool { - // implement after checks ... to chage the state for_sale - true - } -} diff --git a/src/systems/actions.cairo b/src/systems/actions.cairo index 2171325..7b49b5b 100644 --- a/src/systems/actions.cairo +++ b/src/systems/actions.cairo @@ -6,8 +6,6 @@ pub mod actions { Property, PropertyType, PropertyTrait, PropertyToId, IdToProperty, TradeOffer, TradeOfferDetails, TradeCounter, TradeStatus, }; - use dojo_starter::model::utility_model::{Utility, UtilityTrait, UtilityToId, IdToUtility}; - use dojo_starter::model::rail_road_model::{RailRoad, RailRoadTrait, RailRoadToId, IdToRailRoad}; use dojo_starter::model::game_model::{ GameType, Game, GameBalance, GameTrait, GameCounter, GameStatus, IGameBalance, }; @@ -15,11 +13,6 @@ pub mod actions { Player, UsernameToAddress, AddressToUsername, PlayerTrait, IsRegistered, }; use dojo_starter::model::game_player_model::{GamePlayer, PlayerSymbol, GamePlayerTrait}; - use dojo_starter::model::chance_model::{Chance, ChanceTrait}; - use dojo_starter::model::community_chest_model::{CommunityChest, CommunityChestTrait}; - use dojo_starter::model::jail_model::{Jail}; - use dojo_starter::model::go_free_parking_model::{Go}; - use dojo_starter::model::tax_model::{Tax}; use starknet::{ ContractAddress, get_caller_address, get_block_timestamp, contract_address_const, get_contract_address, @@ -136,29 +129,7 @@ pub mod actions { ); } - fn get_tax(self: @ContractState, id: u8, game_id: u256) -> Tax { - let world = self.world_default(); - let tax: Tax = world.read_model((id, game_id)); - tax - } - - fn get_go(self: @ContractState, id: u8, game_id: u256) -> Go { - let world = self.world_default(); - let go: Go = world.read_model((id, game_id)); - go - } - - fn get_chance(self: @ContractState, id: u8, game_id: u256) -> Chance { - let world = self.world_default(); - let chance: Chance = world.read_model((id, game_id)); - chance - } - - fn get_community_chest(self: @ContractState, id: u8, game_id: u256) -> CommunityChest { - let world = self.world_default(); - let community_chest: CommunityChest = world.read_model((id, game_id)); - community_chest - } + fn get_property(self: @ContractState, id: u8, game_id: u256) -> Property { let world = self.world_default(); @@ -166,24 +137,7 @@ pub mod actions { property } - fn get_utility(self: @ContractState, id: u8, game_id: u256) -> Utility { - let world = self.world_default(); - let utility: Utility = world.read_model((id, game_id)); - utility - } - - fn get_railroad(self: @ContractState, id: u8, game_id: u256) -> RailRoad { - let world = self.world_default(); - let railroad: RailRoad = world.read_model((id, game_id)); - railroad - } - - fn get_jail(self: @ContractState, id: u8, game_id: u256) -> Jail { - let world = self.world_default(); - let jail: Jail = world.read_model((id, game_id)); - jail - } - + fn start_game(ref self: ContractState, game_id: u256) -> bool { let mut world = self.world_default(); let mut game: Game = world.read_model(game_id); @@ -342,20 +296,6 @@ pub mod actions { } - fn sell_property(ref self: ContractState, property_id: u8, game_id: u256) -> bool { - let mut world = self.world_default(); - let caller = get_caller_address(); - let mut property: Property = world.read_model((property_id, game_id)); - - assert(property.owner == caller, 'Can only sell your property'); - - property.for_sale = true; - world.write_model(@property); - - true - } - - fn mortgage_property(ref self: ContractState, mut property: Property) -> bool { let mut world = self.world_default(); @@ -1959,6 +1899,164 @@ pub mod actions { world.write_model(@game); (game, player) } + + + fn leave_game(ref self: ContractState, game_id: u256, transfer_to: ContractAddress) { + let mut world = self.world_default(); + let caller = get_caller_address(); + + // Load game and player + let mut game: Game = world.read_model(game_id); + let mut quitting_player: GamePlayer = world.read_model((caller, game_id)); + + // assert(quitting_player.in_game, "Player not in game"); + + // Transfer properties to another player + let mut i = 0; + let len = quitting_player.properties_owned.len(); + while i < len { + if quitting_player.properties_owned.len() == 0 { + break; + } + let prop_id = *quitting_player.properties_owned.at(i); + let mut prop: Property = world.read_model((game_id, prop_id)); + prop.owner = transfer_to; + world.write_model(@prop); + i += 1; + }; + + // Remove player from game + let mut new_game_players: Array = array![]; + let mut i = 0; + while i < game.game_players.len() { + let candidate = *game.game_players.at(i); + if candidate != caller { + new_game_players.append(candidate); + } + i += 1; + }; + + game.game_players = new_game_players; + game.number_of_players -= 1; + + // End game if only one player left + if game.number_of_players == 1 { + if game.game_players.len() > 0 { + let winner = *game.game_players.at(0); + game.winner = winner; + game.status = GameStatus::Ended; + } else { + // Fallback case: no players left, just mark game ended + game.status = GameStatus::Ended; + } + } + + // Save updates + // quitting_player.in_game = false; + quitting_player.properties_owned = array![]; + world.write_model(@quitting_player); + world.write_model(@game); + } + + fn bankruptcy_check(ref self: ContractState, player: GamePlayer, amount_owed: u256) { + let mut world = self.world_default(); + + let net_worth = self.calculate_net_worth(player.clone()); + + if net_worth > amount_owed { + return; // Not bankrupt + } + + // Get property at player's current position + let game_id = player.game_id; + let tile_pos = player.position; + let property: Property = self.get_property(tile_pos, game_id); + + // If no owner or already owned by the player, do nothing + if property.owner == get_contract_address() || property.owner == player.address { + println!("No valid new owner for bankrupt transfer"); + return; + } + + // Transfer properties + let mut i = 0; + let props_len = player.properties_owned.len(); + while i < props_len { + let prop_id = *player.properties_owned.at(i); + let mut prop: Property = self.get_property(prop_id, game_id); + prop.owner = property.owner; + world.write_model(@prop); + i += 1; + }; + + // Clear player's balance and properties + let mut updated_player = player.clone(); + updated_player.balance = 0; + updated_player.properties_owned = array![]; + world.write_model(@updated_player); + + println!( + "Player {:?} is bankrupt. Assets transferred to {:?}", + player.address, + property.owner, + ); + } + + fn vote_to_kick_player(ref self: ContractState, game_id: u256, target_player: ContractAddress) { + let mut world = self.world_default(); + let caller = get_caller_address(); + + // Ensure caller is not voting for himself + assert!(caller != target_player, "You can't vote to kick yourself"); + + // Load target and caller players + let mut target: GamePlayer = world.read_model((target_player, game_id)); + let caller_player: GamePlayer = world.read_model((caller, game_id)); + + // Ensure both are in the same game + assert!(target.game_id == game_id, "Not same game"); + + // Increase strike (can also implement vote tracking to prevent multiple votes) + target.strikes += 1; + + // Save updated target player + world.write_model(@target); + + // Count total players + let game: Game = world.read_model(game_id); + let total_players: u8 = game.number_of_players; + let strike_percent = (target.strikes * 100) / total_players; + + + + // Kick if strikes >= 70% + if strike_percent >= 70 { + + + // Transfer all properties to the bank + let bank = get_contract_address(); + let mut i = 0; + while i < target.properties_owned.len() { + let prop_id = *target.properties_owned.at(i); + let mut property: Property = world.read_model((prop_id, game_id)); + property.owner = bank; + world.write_model(@property); + i += 1; + }; + + // Clear player data + target.properties_owned = array![]; + target.balance = 0; + target.strikes = 0; + // target.has_left = true; + + // Save updated player + world.write_model(@target); + + + } +} + } #[generate_trait] @@ -3178,4 +3276,3 @@ pub mod actions { } } } - diff --git a/src/tests/test_world.cairo b/src/tests/test_world.cairo index 963890a..54580c2 100644 --- a/src/tests/test_world.cairo +++ b/src/tests/test_world.cairo @@ -28,17 +28,7 @@ mod tests { TradeCounter, m_TradeCounter, TradeOfferDetails, m_TradeOfferDetails, TradeOffer, TradeStatus, }; - use dojo_starter::model::utility_model::{ - Utility, m_Utility, IdToUtility, m_IdToUtility, UtilityToId, m_UtilityToId, - }; - use dojo_starter::model::rail_road_model::{ - RailRoad, m_RailRoad, IdToRailRoad, m_IdToRailRoad, RailRoadToId, m_RailRoadToId, - }; - use dojo_starter::model::chance_model::{Chance, m_Chance}; - use dojo_starter::model::community_chest_model::{CommunityChest, m_CommunityChest}; - use dojo_starter::model::jail_model::{Jail, m_Jail}; - use dojo_starter::model::go_free_parking_model::{Go, m_Go}; - use dojo_starter::model::tax_model::{Tax, m_Tax}; + use starknet::{testing, get_caller_address, contract_address_const}; fn namespace_def() -> NamespaceDef { @@ -55,17 +45,6 @@ mod tests { TestResource::Model(m_AddressToUsername::TEST_CLASS_HASH), TestResource::Model(m_IsRegistered::TEST_CLASS_HASH), TestResource::Model(m_GameCounter::TEST_CLASS_HASH), - TestResource::Model(m_Utility::TEST_CLASS_HASH), - TestResource::Model(m_IdToUtility::TEST_CLASS_HASH), - TestResource::Model(m_UtilityToId::TEST_CLASS_HASH), - TestResource::Model(m_RailRoad::TEST_CLASS_HASH), - TestResource::Model(m_IdToRailRoad::TEST_CLASS_HASH), - TestResource::Model(m_RailRoadToId::TEST_CLASS_HASH), - TestResource::Model(m_Chance::TEST_CLASS_HASH), - TestResource::Model(m_CommunityChest::TEST_CLASS_HASH), - TestResource::Model(m_Jail::TEST_CLASS_HASH), - TestResource::Model(m_Go::TEST_CLASS_HASH), - TestResource::Model(m_Tax::TEST_CLASS_HASH), TestResource::Model(m_GamePlayer::TEST_CLASS_HASH), TestResource::Model(m_TradeCounter::TEST_CLASS_HASH), TestResource::Model(m_TradeOfferDetails::TEST_CLASS_HASH), @@ -4079,5 +4058,80 @@ mod tests { assert(winner == caller_1, 'Winner is not Aji'); assert(game.status == GameStatus::Ended, 'Game not finished'); } + + #[test] + fn test_leave_game() { + let caller_1 = contract_address_const::<'aji'>(); + let caller_2 = contract_address_const::<'collins'>(); + let username = 'Ajidokwu'; + let username_1 = 'Collins'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"actions").unwrap(); + let actions_system = IActionsDispatcher { contract_address }; + + testing::set_contract_address(caller_2); + actions_system.register_new_player(username_1); + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username); + + testing::set_contract_address(caller_1); + actions_system.create_new_game(GameType::PublicGame, PlayerSymbol::Hat, 2); + + testing::set_contract_address(caller_2); + actions_system.join_game(PlayerSymbol::Dog, 1); + + testing::set_contract_address(caller_1); + let started = actions_system.start_game(1); + assert(started, 'Game start fail'); + + let game_p = actions_system.retrieve_game(1); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 2); + let chance = "Get Out of Jail Free"; + + let mut g = actions_system.retrieve_game(1); + let mut p = actions_system.retrieve_game_player(caller_1, 1); + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, chance); + actions_system.finish_turn(g); + + p = actions_system.retrieve_game_player(caller_1, 1); + assert!(p.comm_free_card, "p does not have community jail card"); + + testing::set_contract_address(caller_2); + let mut offered_property_ids: Array = array![]; + let mut requested_property_ids: Array = array![]; + offered_property_ids.append(6); + requested_property_ids.append(1); + let mut trade_id = actions_system + .offer_trade( + 1, + caller_1, + offered_property_ids.clone(), + requested_property_ids.clone(), + 50, + 0, + TradeOffer::ChanceJailCardForCash, + ); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + actions_system.leave_game(1, caller_2); + + let game = actions_system.retrieve_game(1); + println!("players from array left : {}", game.game_players.len()); + println!("number_of_players left : {}", game.number_of_players); + assert!(game.game_players.len() == 1, "Game has more than one player"); + assert!(game.status == GameStatus::Ended, "Game is not finished"); + } }