diff --git a/src/interfaces/IActions.cairo b/src/interfaces/IActions.cairo index f932f42..d32326f 100644 --- a/src/interfaces/IActions.cairo +++ b/src/interfaces/IActions.cairo @@ -1,7 +1,7 @@ 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; +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; @@ -42,10 +42,41 @@ pub trait IActions { 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; + + 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, + trade_type: TradeOffer, + ) -> u256; + + fn accept_trade(ref self: T, trade_id: u256, game_id: u256) -> bool; + + fn reject_trade(ref self: T, trade_id: u256, game_id: u256) -> bool; + + fn counter_trade( + ref self: T, + game_id: u256, + original_offer_id: u256, + offered_property_ids: Array, + requested_property_ids: Array, + cash_offer: u256, + cash_request: u256, + trade_type: TradeOffer, + ) -> u256; + fn approve_counter_trade(ref self: T, trade_id: u256) -> bool; + fn get_trade(self: @T, trade_id: u256) -> TradeOfferDetails; // Dice & player movement 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 diff --git a/src/model/game_player_model.cairo b/src/model/game_player_model.cairo index f0cc122..91685c7 100644 --- a/src/model/game_player_model.cairo +++ b/src/model/game_player_model.cairo @@ -30,6 +30,7 @@ pub struct GamePlayer { pub no_section8: u8, pub is_bankrupt: bool, pub is_active: bool, + pub jail_turns: u8, } @@ -78,6 +79,7 @@ impl GamePlayerImpl of GamePlayerTrait { no_section6: 0, no_section7: 0, no_section8: 0, + jail_turns: 0, } } diff --git a/src/model/property_model.cairo b/src/model/property_model.cairo index 44bd328..056e57d 100644 --- a/src/model/property_model.cairo +++ b/src/model/property_model.cairo @@ -1,5 +1,30 @@ use starknet::{ContractAddress, contract_address_const}; +#[derive(Serde, Copy, Drop, Introspect, PartialEq)] +#[dojo::model] +pub struct TradeCounter { + #[key] + pub id: felt252, + pub current_val: u256, +} + +#[derive(Clone, Drop, Serde)] +#[dojo::model] +pub struct TradeOfferDetails { + #[key] + pub id: u256, + pub from: ContractAddress, + pub to: ContractAddress, + pub game_id: u256, + pub offered_property_ids: Array, + pub requested_property_ids: Array, + pub cash_offer: u256, + pub cash_request: u256, + pub trade_type: TradeOffer, + pub status: TradeStatus, + pub is_countered: bool, + pub approve_counter: bool, +} #[derive(Copy, Drop, Serde)] #[dojo::model] pub struct Property { @@ -38,6 +63,27 @@ pub enum PropertyType { VisitingJail, } +#[derive(Serde, Copy, Drop, Introspect, PartialEq, Debug)] +pub enum TradeOffer { + PropertyForProperty, + PropertyForCash, + CashForProperty, + CashPlusPropertyForProperty, + PropertyForCashPlusProperty, + CashForChanceJailCard, + CashForCommunityJailCard, + CommunityJailCardForCash, + ChanceJailCardForCash, +} + +#[derive(Serde, Copy, Drop, Introspect, PartialEq, Debug)] +pub enum TradeStatus { + Accepted, + Rejected, + Pending, + Countered, +} + #[derive(Drop, Copy, Serde)] #[dojo::model] @@ -84,10 +130,39 @@ 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/systems/actions.cairo b/src/systems/actions.cairo index 45f3a59..c277252 100644 --- a/src/systems/actions.cairo +++ b/src/systems/actions.cairo @@ -3,7 +3,8 @@ pub mod actions { use dojo_starter::interfaces::IActions::IActions; use dojo_starter::model::property_model::{ - Property, PropertyType, PropertyTrait, PropertyToId, IdToProperty, + 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}; @@ -463,6 +464,63 @@ pub mod actions { true } + fn pay_jail_fine(ref self: ContractState, game_id: u256) -> bool { + let mut world = self.world_default(); + let caller = get_caller_address(); + let mut player: GamePlayer = world.read_model((caller, game_id)); + let mut game: Game = world.read_model(game_id); + + assert(game.status == GameStatus::Ongoing, 'Game not started'); + assert(player.jailed, 'Not in jail'); + + // Pay the fine + let fine_amount: u256 = 50; + assert(player.balance >= fine_amount, 'Insufficient funds to pay fine'); + + player.balance -= fine_amount; + player.jailed = false; + player.jail_turns = 0; + + world.write_model(@game); + world.write_model(@player); + + true + } + + fn use_getout_of_jail_chance(ref self: ContractState, game_id: u256) -> bool { + let mut world = self.world_default(); + let caller = get_caller_address(); + let mut player: GamePlayer = world.read_model((caller, game_id)); + let mut game: Game = world.read_model(game_id); + assert(player.chance_jail_card, 'No chance card'); + assert(player.jailed, 'Not in jail'); + assert(game.status == GameStatus::Ongoing, 'Game not started'); + // Use the card + player.chance_jail_card = false; + player.jailed = false; + player.jail_turns = 0; + world.write_model(@game); + world.write_model(@player); + true + } + + fn use_getout_of_jail_community_chest(ref self: ContractState, game_id: u256) -> bool { + let mut world = self.world_default(); + let caller = get_caller_address(); + let mut player: GamePlayer = world.read_model((caller, game_id)); + let mut game: Game = world.read_model(game_id); + assert(player.comm_free_card, 'No community chest card'); + assert(player.jailed, 'Not in jail'); + assert(game.status == GameStatus::Ongoing, 'Game not started'); + // Use the card + player.comm_free_card = false; + player.jailed = false; + player.jail_turns = 0; + world.write_model(@game); + world.write_model(@player); + true + } + fn move_player(ref self: ContractState, game_id: u256, steps: u8) -> u8 { let mut world = self.world_default(); @@ -470,29 +528,58 @@ pub mod actions { let mut game_player: GamePlayer = world.read_model((caller, game_id)); let mut game: Game = world.read_model(game_id); - assert(game.next_player == caller, 'Not your turn'); - assert(game.status == GameStatus::Ongoing, 'Game is not ongoing'); + assert!(game.next_player == caller, "Not your turn"); + assert!(game.status == GameStatus::Ongoing, "Game is not ongoing"); - // Move player - game_player = GamePlayerTrait::move(game_player, steps); + // Handle jailed players + if game_player.jailed { + game_player.jail_turns += 1; + if game_player.jail_turns > 3 { + // Automatically release player after 3 turns + game_player.jailed = false; + game_player.jail_turns = 0; + } else { + // Still in jail, no move + world.write_model(@game_player); + return game_player.position; + } + } + + // Now free to move + game_player = GamePlayerTrait::move(game_player, steps); game_player.dice_rolled = steps; + // Passed or landed on Go if game_player.position >= 40 { game_player.position %= 40; game_player.balance += 200; } + // Landing on "Go To Jail" space + if game_player.position == 30 { + game_player.position = 10; + game_player.jailed = true; + game_player.jail_turns = 0; + + world.write_model(@game_player); + world.write_model(@game); + return game_player.position; + } + + // Handle landing on property let mut property = self.get_property(game_player.position, game_id); - property = self.handle_property_landing(game_player.clone(), property.clone()); + property = self.handle_property_landing(game_player.clone(), property); // Update state world.write_model(@game_player); world.write_model(@game); + world.write_model(@property); game_player.position } + fn buy_property(ref self: ContractState, mut property: Property) -> bool { // get the world let mut world = self.world_default(); @@ -611,40 +698,809 @@ pub mod actions { } - // fn offer_trade( - // ref self: ContractState, - // game_id: u256, - // to: ContractAddress, - // offered_property_ids: Array, - // requested_property_ids: Array, - // cash_offer: u256, - // cash_request: u256, - // ) { - // let mut world = self.world_default(); - // let caller = get_caller_address(); - - // // Validate trade parameters - // assert(offered_property_ids.len() > 0 || cash_offer > 0, 'No properties or cash - // offered'); - // assert(requested_property_ids.len() > 0 || cash_request > 0, 'No properties or cash - // requested'); - - // // Ensure the recipient is a valid player in the game - // let recipient_username = self.get_username_from_address(to); - // assert(recipient_username != 0, 'Recipient not registered'); - - // // Create and store the trade offer - // let trade_id = world.get_next_trade_id(); - // let trade_offer = TradeOffer { - // trade_id, - // from: caller, - // to, - // offered_property_ids, - // requested_property_ids, - // cash_offer, - // cash_request, - // status: TradeStatus::Pending, - // }; + fn offer_trade( + ref self: ContractState, + game_id: u256, + to: ContractAddress, + offered_property_ids: Array, + requested_property_ids: Array, + cash_offer: u256, + cash_request: u256, + trade_type: TradeOffer, + ) -> u256 { + let caller = get_caller_address(); + + let mut world = self.world_default(); + let mut game: Game = world.read_model(game_id); + + assert!(game.next_player == caller, "Not your turn"); + assert!(game.status == GameStatus::Ongoing, "Game is not ongoing"); + + let id = self.create_trade_id(); + + // Validate inputs here (as you do) + let mut offer: TradeOfferDetails = world.read_model(id); + // Create the offer struct + + offer.id = id; + offer.from = caller; + offer.to = to; + offer.game_id = game_id; + offer.offered_property_ids = offered_property_ids; + offer.requested_property_ids = requested_property_ids; + offer.cash_offer = cash_offer; + offer.cash_request = cash_request; + offer.trade_type = trade_type; + offer.status = TradeStatus::Pending; + + world.write_model(@offer); + + id + } + + fn accept_trade(ref self: ContractState, trade_id: u256, game_id: u256) -> bool { + let mut world = self.world_default(); + let caller = get_caller_address(); + + let mut offer: TradeOfferDetails = world.read_model(trade_id); + assert!(caller == offer.to, "Only recipient can accept trade"); + + // Load offer + + let mut initiator: GamePlayer = world.read_model((offer.from, offer.game_id)); + let mut receiver: GamePlayer = world.read_model((offer.to, offer.game_id)); + + if offer.trade_type == TradeOffer::PropertyForCash { + // Transfer properties from initiator to receiver + let mut i = 0; + while i < offer.offered_property_ids.len() { + let prop_id = *offer.offered_property_ids[i]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Manual transfer of ownership + assert!( + property.owner == initiator.address, "Initiator does not own this property", + ); + property.owner = receiver.address; + + // Create a new array excluding the property being traded + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut j = 0; + + while j < initiator.properties_owned.len() { + let owned_prop_id = *initiator.properties_owned[j]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + j += 1; + }; + + // Assign back the new array + initiator.properties_owned = new_properties_owned; + + // Now add the property to the receiver + receiver.properties_owned.append(prop_id); + match property.group_id { + 0 => {}, + 1 => receiver.no_section1 += 1, + 2 => receiver.no_section2 += 1, + 3 => receiver.no_section3 += 1, + 4 => receiver.no_section4 += 1, + 5 => receiver.no_section5 += 1, + 6 => receiver.no_section6 += 1, + 7 => receiver.no_section7 += 1, + 8 => receiver.no_section8 += 1, + _ => {}, + } + match property.group_id { + 0 => {}, + 1 => initiator.no_section1 -= 1, + 2 => initiator.no_section2 -= 1, + 3 => initiator.no_section3 -= 1, + 4 => initiator.no_section4 -= 1, + 5 => initiator.no_section5 -= 1, + 6 => initiator.no_section6 -= 1, + 7 => initiator.no_section7 -= 1, + 8 => initiator.no_section8 -= 1, + _ => {}, + } + + // Save updated property + world.write_model(@property); + + i += 1; + }; + + // Transfer cash from receiver to initiator + assert!(receiver.balance >= offer.cash_request, "Receiver has insufficient cash"); + receiver.balance -= offer.cash_request; + initiator.balance += offer.cash_request; + + // Persist updated players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::PropertyForProperty { + // Transfer offered properties from initiator to receiver + let mut i = 0; + while i < offer.offered_property_ids.len() { + let prop_id = *offer.offered_property_ids[i]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Ensure the initiator owns it + assert!( + property.owner == initiator.address, "Initiator does not own this property", + ); + property.owner = receiver.address; + + // Remove from initiator properties_owned + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut k = 0; + while k < initiator.properties_owned.len() { + let owned_prop_id = *initiator.properties_owned[k]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + k += 1; + }; + initiator.properties_owned = new_properties_owned; + + // Add to receiver properties_owned + receiver.properties_owned.append(prop_id); + + // Update section counters + match property.group_id { + 0 => {}, + 1 => { + receiver.no_section1 += 1; + initiator.no_section1 -= 1; + }, + 2 => { + receiver.no_section2 += 1; + initiator.no_section2 -= 1; + }, + 3 => { + receiver.no_section3 += 1; + initiator.no_section3 -= 1; + }, + 4 => { + receiver.no_section4 += 1; + initiator.no_section4 -= 1; + }, + 5 => { + receiver.no_section5 += 1; + initiator.no_section5 -= 1; + }, + 6 => { + receiver.no_section6 += 1; + initiator.no_section6 -= 1; + }, + 7 => { + receiver.no_section7 += 1; + initiator.no_section7 -= 1; + }, + 8 => { + receiver.no_section8 += 1; + initiator.no_section8 -= 1; + }, + _ => {}, + } + + // Write updated property + world.write_model(@property); + + i += 1; + }; + + // Transfer requested properties from receiver to initiator + let mut j = 0; + while j < offer.requested_property_ids.len() { + let prop_id = *offer.requested_property_ids[j]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Ensure the receiver owns it + assert!( + property.owner == receiver.address, "Receiver does not own this property", + ); + property.owner = initiator.address; + + // Remove from receiver properties_owned + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut l = 0; + while l < receiver.properties_owned.len() { + let owned_prop_id = *receiver.properties_owned[l]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + l += 1; + }; + receiver.properties_owned = new_properties_owned; + + // Add to initiator properties_owned + initiator.properties_owned.append(prop_id); + + // Update section counters + match property.group_id { + 0 => {}, + 1 => { + initiator.no_section1 += 1; + receiver.no_section1 -= 1; + }, + 2 => { + initiator.no_section2 += 1; + receiver.no_section2 -= 1; + }, + 3 => { + initiator.no_section3 += 1; + receiver.no_section3 -= 1; + }, + 4 => { + initiator.no_section4 += 1; + receiver.no_section4 -= 1; + }, + 5 => { + initiator.no_section5 += 1; + receiver.no_section5 -= 1; + }, + 6 => { + initiator.no_section6 += 1; + receiver.no_section6 -= 1; + }, + 7 => { + initiator.no_section7 += 1; + receiver.no_section7 -= 1; + }, + 8 => { + initiator.no_section8 += 1; + receiver.no_section8 -= 1; + }, + _ => {}, + } + + // Write updated property + world.write_model(@property); + + j += 1; + }; + + // Write updated players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::CashForProperty { + // Transfer cash from initiator to receiver + assert!(initiator.balance >= offer.cash_offer, "Initiator has insufficient cash"); + initiator.balance -= offer.cash_offer; + receiver.balance += offer.cash_offer; + + // Transfer requested properties from receiver to initiator + let mut j = 0; + while j < offer.requested_property_ids.len() { + let prop_id = *offer.requested_property_ids[j]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Ensure the receiver owns it + assert!( + property.owner == receiver.address, "Receiver does not own this property", + ); + property.owner = initiator.address; + + // Remove from receiver properties_owned + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut l = 0; + while l < receiver.properties_owned.len() { + let owned_prop_id = *receiver.properties_owned[l]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + l += 1; + }; + receiver.properties_owned = new_properties_owned; + + // Add to initiator properties_owned + initiator.properties_owned.append(prop_id); + + // Update section counters + match property.group_id { + 0 => {}, + 1 => { + initiator.no_section1 += 1; + receiver.no_section1 -= 1; + }, + 2 => { + initiator.no_section2 += 1; + receiver.no_section2 -= 1; + }, + 3 => { + initiator.no_section3 += 1; + receiver.no_section3 -= 1; + }, + 4 => { + initiator.no_section4 += 1; + receiver.no_section4 -= 1; + }, + 5 => { + initiator.no_section5 += 1; + receiver.no_section5 -= 1; + }, + 6 => { + initiator.no_section6 += 1; + receiver.no_section6 -= 1; + }, + 7 => { + initiator.no_section7 += 1; + receiver.no_section7 -= 1; + }, + 8 => { + initiator.no_section8 += 1; + receiver.no_section8 -= 1; + }, + _ => {}, + } + + // Write updated property + world.write_model(@property); + + j += 1; + }; + + // Write updated players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::CashPlusPropertyForProperty { + // Transfer offered properties from initiator to receiver + let mut i = 0; + while i < offer.offered_property_ids.len() { + let prop_id = *offer.offered_property_ids[i]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Ensure the initiator owns it + assert!( + property.owner == initiator.address, "Initiator does not own this property", + ); + property.owner = receiver.address; + + // Remove from initiator properties_owned + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut k = 0; + while k < initiator.properties_owned.len() { + let owned_prop_id = *initiator.properties_owned[k]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + k += 1; + }; + initiator.properties_owned = new_properties_owned; + + // Add to receiver properties_owned + receiver.properties_owned.append(prop_id); + + // Update section counters + match property.group_id { + 0 => {}, + 1 => { + receiver.no_section1 += 1; + initiator.no_section1 -= 1; + }, + 2 => { + receiver.no_section2 += 1; + initiator.no_section2 -= 1; + }, + 3 => { + receiver.no_section3 += 1; + initiator.no_section3 -= 1; + }, + 4 => { + receiver.no_section4 += 1; + initiator.no_section4 -= 1; + }, + 5 => { + receiver.no_section5 += 1; + initiator.no_section5 -= 1; + }, + 6 => { + receiver.no_section6 += 1; + initiator.no_section6 -= 1; + }, + 7 => { + receiver.no_section7 += 1; + initiator.no_section7 -= 1; + }, + 8 => { + receiver.no_section8 += 1; + initiator.no_section8 -= 1; + }, + _ => {}, + } + + // Write updated property + world.write_model(@property); + + i += 1; + }; + + // Transfer cash from initiator to receiver + assert!(initiator.balance >= offer.cash_offer, "Initiator has insufficient cash"); + initiator.balance -= offer.cash_offer; + receiver.balance += offer.cash_offer; + + // Transfer requested properties from receiver to initiator + let mut j = 0; + while j < offer.requested_property_ids.len() { + let prop_id = *offer.requested_property_ids[j]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Ensure the receiver owns it + assert!( + property.owner == receiver.address, "Receiver does not own this property", + ); + property.owner = initiator.address; + + // Remove from receiver properties_owned + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut l = 0; + while l < receiver.properties_owned.len() { + let owned_prop_id = *receiver.properties_owned[l]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + l += 1; + }; + receiver.properties_owned = new_properties_owned; + + // Add to initiator properties_owned + initiator.properties_owned.append(prop_id); + + // Update section counters + match property.group_id { + 0 => {}, + 1 => { + initiator.no_section1 += 1; + receiver.no_section1 -= 1; + }, + 2 => { + initiator.no_section2 += 1; + receiver.no_section2 -= 1; + }, + 3 => { + initiator.no_section3 += 1; + receiver.no_section3 -= 1; + }, + 4 => { + initiator.no_section4 += 1; + receiver.no_section4 -= 1; + }, + 5 => { + initiator.no_section5 += 1; + receiver.no_section5 -= 1; + }, + 6 => { + initiator.no_section6 += 1; + receiver.no_section6 -= 1; + }, + 7 => { + initiator.no_section7 += 1; + receiver.no_section7 -= 1; + }, + 8 => { + initiator.no_section8 += 1; + receiver.no_section8 -= 1; + }, + _ => {}, + } + + // Write updated property + world.write_model(@property); + + j += 1; + }; + + // Write updated players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::PropertyForCashPlusProperty { + // Transfer offered properties from initiator to receiver + let mut i = 0; + while i < offer.offered_property_ids.len() { + let prop_id = *offer.offered_property_ids[i]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Ensure the initiator owns it + assert!( + property.owner == initiator.address, "Initiator does not own this property", + ); + property.owner = receiver.address; + + // Remove from initiator properties_owned + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut k = 0; + while k < initiator.properties_owned.len() { + let owned_prop_id = *initiator.properties_owned[k]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + k += 1; + }; + initiator.properties_owned = new_properties_owned; + + // Add to receiver properties_owned + receiver.properties_owned.append(prop_id); + + // Update section counters + match property.group_id { + 0 => {}, + 1 => { + receiver.no_section1 += 1; + initiator.no_section1 -= 1; + }, + 2 => { + receiver.no_section2 += 1; + initiator.no_section2 -= 1; + }, + 3 => { + receiver.no_section3 += 1; + initiator.no_section3 -= 1; + }, + 4 => { + receiver.no_section4 += 1; + initiator.no_section4 -= 1; + }, + 5 => { + receiver.no_section5 += 1; + initiator.no_section5 -= 1; + }, + 6 => { + receiver.no_section6 += 1; + initiator.no_section6 -= 1; + }, + 7 => { + receiver.no_section7 += 1; + initiator.no_section7 -= 1; + }, + 8 => { + receiver.no_section8 += 1; + initiator.no_section8 -= 1; + }, + _ => {}, + } + + // Write updated property + world.write_model(@property); + + i += 1; + }; + + // Transfer cash from receiver to initiator + assert!(receiver.balance >= offer.cash_request, "Receiver has insufficient cash"); + receiver.balance -= offer.cash_request; + initiator.balance += offer.cash_request; + + // Transfer requested properties from receiver to initiator + let mut j = 0; + while j < offer.requested_property_ids.len() { + let prop_id = *offer.requested_property_ids[j]; + let mut property: Property = world.read_model((prop_id, game_id)); + + // Ensure the receiver owns it + assert!( + property.owner == receiver.address, "Receiver does not own this property", + ); + property.owner = initiator.address; + + // Remove from receiver properties_owned + let mut new_properties_owned: Array = ArrayTrait::new(); + let mut l = 0; + while l < receiver.properties_owned.len() { + let owned_prop_id = *receiver.properties_owned[l]; + if owned_prop_id != prop_id { + new_properties_owned.append(owned_prop_id); + } + l += 1; + }; + receiver.properties_owned = new_properties_owned; + + // Add to initiator properties_owned + initiator.properties_owned.append(prop_id); + + // Update section counters + match property.group_id { + 0 => {}, + 1 => { + initiator.no_section1 += 1; + receiver.no_section1 -= 1; + }, + 2 => { + initiator.no_section2 += 1; + receiver.no_section2 -= 1; + }, + 3 => { + initiator.no_section3 += 1; + receiver.no_section3 -= 1; + }, + 4 => { + initiator.no_section4 += 1; + receiver.no_section4 -= 1; + }, + 5 => { + initiator.no_section5 += 1; + receiver.no_section5 -= 1; + }, + 6 => { + initiator.no_section6 += 1; + receiver.no_section6 -= 1; + }, + 7 => { + initiator.no_section7 += 1; + receiver.no_section7 -= 1; + }, + 8 => { + initiator.no_section8 += 1; + receiver.no_section8 -= 1; + }, + _ => {}, + } + + // Write updated property + world.write_model(@property); + + j += 1; + }; + + // Write updated players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::CashForChanceJailCard { + // Initiator pays cash to receiver for receiver's chance jail card + assert!(initiator.balance >= offer.cash_offer, "Initiator has insufficient cash"); + assert!(receiver.chance_jail_card, "Receiver does not have a chance jail card"); + assert!(!initiator.chance_jail_card, "Initiator already owns a chance jail card"); + + // Transfer cash + initiator.balance -= offer.cash_offer; + receiver.balance += offer.cash_offer; + + // Transfer the card + receiver.chance_jail_card = false; + initiator.chance_jail_card = true; + + // Write back players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::CommunityJailCardForCash { + // Initiator pays cash to receiver for receiver's community jail card + assert!(initiator.balance >= offer.cash_offer, "Initiator has insufficient cash"); + assert!(receiver.comm_free_card, "Receiver does not have a community jail card"); + assert!(!initiator.comm_free_card, "Initiator already owns a community jail card"); + + // Transfer cash + initiator.balance -= offer.cash_offer; + receiver.balance += offer.cash_offer; + + // Transfer the card + receiver.comm_free_card = false; + initiator.comm_free_card = true; + + // Write back players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::CashForCommunityJailCard { + // Receiver pays cash to initiator for initiator's community jail card + assert!(receiver.balance >= offer.cash_request, "Receiver has insufficient cash"); + assert!(initiator.comm_free_card, "Initiator does not have a community jail card"); + assert!(!receiver.comm_free_card, "Receiver already owns a community jail card"); + + // Transfer cash + receiver.balance -= offer.cash_request; + initiator.balance += offer.cash_request; + + // Transfer the card + initiator.comm_free_card = false; + receiver.comm_free_card = true; + + // Write back players + world.write_model(@initiator); + world.write_model(@receiver); + } else if offer.trade_type == TradeOffer::ChanceJailCardForCash { + // Receiver pays cash to initiator for initiator's chance jail card + assert!(receiver.balance >= offer.cash_request, "Receiver has insufficient cash"); + assert!(initiator.chance_jail_card, "Initiator does not have a chance jail card"); + assert!(!receiver.chance_jail_card, "Receiver already owns a chance jail card"); + + // Transfer cash + receiver.balance -= offer.cash_request; + initiator.balance += offer.cash_request; + + // Transfer the card + initiator.chance_jail_card = false; + receiver.chance_jail_card = true; + + // Write back players + world.write_model(@initiator); + world.write_model(@receiver); + } + + offer.status = TradeStatus::Accepted; + + // Save updated player and property data + world.write_model(@initiator); + world.write_model(@receiver); + world.write_model(@offer); + + true + } + + fn reject_trade(ref self: ContractState, trade_id: u256, game_id: u256) -> bool { + let mut world = self.world_default(); + let caller = get_caller_address(); + + let mut offer: TradeOfferDetails = world.read_model(trade_id); + assert!(caller == offer.to, "Only recipient can reject trade"); + offer.status = TradeStatus::Rejected; + + world.write_model(@offer); + + true + } + + fn counter_trade( + ref self: ContractState, + game_id: u256, + original_offer_id: u256, + offered_property_ids: Array, + requested_property_ids: Array, + cash_offer: u256, + cash_request: u256, + trade_type: TradeOffer, + ) -> u256 { + let caller = get_caller_address(); + + let mut world = self.world_default(); + let mut game: Game = world.read_model(game_id); + + assert!(game.status == GameStatus::Ongoing, "Game is not ongoing"); + + let mut original_offer: TradeOfferDetails = world.read_model(original_offer_id); + + // Ensure the caller is the recipient of the original offer + assert!( + original_offer.to == caller, "Only the receiver of the original trade can counter", + ); + + original_offer.id = original_offer.id; + original_offer.game_id = game_id; + original_offer.offered_property_ids = offered_property_ids; + original_offer.requested_property_ids = requested_property_ids; + original_offer.cash_offer = cash_offer; + original_offer.cash_request = cash_request; + original_offer.trade_type = trade_type; + original_offer.status = TradeStatus::Countered; + original_offer.is_countered = true; + + world.write_model(@original_offer); + + original_offer.id + } + + fn approve_counter_trade(ref self: ContractState, trade_id: u256) -> bool { + let mut world = self.world_default(); + let caller = get_caller_address(); + + let mut offer: TradeOfferDetails = world.read_model(trade_id); + assert!(caller == offer.from, "Only the initiator can approve the counter trade"); + assert!(offer.status == TradeStatus::Countered, "Trade is not pending"); + + // Process the trade + offer.status = TradeStatus::Pending; + offer.is_countered = false; + offer.approve_counter = true; + + true + } + + fn get_trade(self: @ContractState, trade_id: u256) -> TradeOfferDetails { + let world = self.world_default(); + let trade: TradeOfferDetails = world.read_model(trade_id); + trade + } + fn sell_house_or_hotel(ref self: ContractState, property_id: u8, game_id: u256) -> bool { let mut world = self.world_default(); @@ -927,7 +1783,7 @@ pub mod actions { property.property_type == PropertyType::CommunityChest, 'not on community chest', ); if card == "Advance to Go (Collect $200)" { - player.position = 1; + player.position = 0; player.balance += 200; } else if card == "Bank error in your favor - Collect $200" { player.balance += 200; @@ -938,7 +1794,7 @@ pub mod actions { } else if card == "Get Out of Jail Free" { player.comm_free_card = true; } else if card == "Go to Jail" { - player.position = 11; // jail position + player.position = 10; // jail position player.jailed = true; } else if card == "Grand Opera Night - collect $50 from every player" { let mut i = 0; @@ -2152,6 +3008,51 @@ pub mod actions { world.write_model(@game_counter); new_val } + + fn create_trade_id(ref self: ContractState) -> u256 { + let mut world = self.world_default(); + let mut trade_counter: TradeCounter = world.read_model('v0'); + let new_val = trade_counter.current_val + 1; + trade_counter.current_val = new_val; + world.write_model(@trade_counter); + new_val + } + + + fn property_transfer( + ref self: ContractState, + mut initiator_property: Property, + mut initiator: GamePlayer, + mut receiver: GamePlayer, + ) -> (GamePlayer, GamePlayer, Property) { + let mut world = self.world_default(); + assert(initiator_property.game_id == receiver.game_id, 'Not in the same Game'); + + // Update property owner + initiator_property.owner = receiver.address; + + // Build new properties array excluding the transferred property + let mut new_properties = array![]; + let mut i = 0; + while (i < initiator.properties_owned.len()) { + let prop_id = *initiator.properties_owned[i]; + let prop = self.get_property(prop_id, initiator.game_id); + if prop.id != initiator_property.id { + new_properties.append(prop.id); + } + i += 1; + }; + initiator.properties_owned = new_properties; + + // Add property to receiver's properties + receiver.properties_owned.append(initiator_property.id); + + world.write_model(@initiator); + world.write_model(@receiver); + world.write_model(@initiator_property); + + (initiator, receiver, initiator_property) + } } } diff --git a/src/tests/test_world.cairo b/src/tests/test_world.cairo index 222511c..01a2183 100644 --- a/src/tests/test_world.cairo +++ b/src/tests/test_world.cairo @@ -25,6 +25,8 @@ mod tests { use dojo_starter::model::property_model::{ Property, m_Property, IdToProperty, m_IdToProperty, PropertyToId, m_PropertyToId, + TradeCounter, m_TradeCounter, TradeOfferDetails, m_TradeOfferDetails, TradeOffer, + TradeStatus, }; use dojo_starter::model::utility_model::{ Utility, m_Utility, IdToUtility, m_IdToUtility, UtilityToId, m_UtilityToId, @@ -65,6 +67,8 @@ mod tests { 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), TestResource::Event(actions::e_PlayerCreated::TEST_CLASS_HASH), TestResource::Event(actions::e_GameCreated::TEST_CLASS_HASH), TestResource::Event(actions::e_PlayerJoined::TEST_CLASS_HASH), @@ -2159,5 +2163,1495 @@ mod tests { assert(ply.position == 2, 'position error'); assert(ply.balance == 1450, 'bal error'); } + + #[test] + fn test_process_community_chest_individually() { + 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'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 2); + + let mut g = actions_system.retrieve_game(1); + let mut p = actions_system.retrieve_game_player(caller_1, 1); + + let mut community_chest: ByteArray = "Advance to Go (Collect $200)"; + + let (_, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + assert(ply.position == 0, 'position error'); + assert(ply.balance == 1700, 'bal error'); + + g = actions_system.finish_turn(g); + testing::set_contract_address(caller_2); + actions_system.move_player(1, 2); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "Bank error in your favor - Collect $200"; + + let (_, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + g = actions_system.finish_turn(g); + + assert(ply.position == 2, 'position error'); + assert(ply.balance == 1700, 'bal error'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 2); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + community_chest = "Bank error in your favor - Collect $200"; + + let (_, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 2, 'position error'); + assert(ply.balance == 1900, 'bal error'); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 15); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "Doctor fee - Pay $50"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 17, 'position error'); + assert(ply.balance == 1650, 'bal error'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 15); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + community_chest = "From sale of stock - collect $50"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 17, 'position error'); + assert(ply.balance == 1950, 'bal error'); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 16); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "Get Out of Jail Free"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 33, 'position error'); + assert(ply.balance == 1650, 'bal error'); + assert(ply.comm_free_card, 'jail card error'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 16); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + community_chest = "Grand Opera Night - collect $50 from every player"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 33, 'position error'); + assert(ply.balance == 2000, 'bal error'); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 9); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "Go to Jail"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 10, 'position error'); + assert(ply.balance == 1800, 'bal error'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 9); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + community_chest = "Holiday Fund matures - Receive $100"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 2, 'position error'); + assert(ply.balance == 2300, 'bal error'); + + testing::set_contract_address(caller_2); + actions_system.use_getout_of_jail_community_chest(1); + actions_system.move_player(1, 7); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "Income tax refund - Collect $20"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 17, 'position error'); + assert(ply.balance == 1820, 'bal error'); + + // // // HERE + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 15); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + community_chest = "Life insurance matures - Collect $100"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 17, 'position error'); + assert(ply.balance == 2400, 'bal error'); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 16); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "Pay hospital fees of $100"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 33, 'position error'); + assert(ply.balance == 1720, 'bal error'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 16); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + community_chest = "Pay school fees of $150"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 33, 'position error'); + assert(ply.balance == 2250, 'bal error'); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 9); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "Street repairs - $40 per house, $115 per hotel"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 2, 'position error'); + assert(ply.balance == 1920, 'bal error'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 9); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + community_chest = "Won second prize in beauty contest - Collect $10"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 2, 'position error'); + assert(ply.balance == 2460, 'bal error'); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 15); + + let g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + community_chest = "You inherit $100"; + + let (g, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + actions_system.finish_turn(g); + + assert(ply.position == 17, 'position error'); + assert(ply.balance == 2020, 'bal error'); + } + + #[test] + fn test_going_jail_and_using_community_and_chance_cards() { + 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'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 2); + + let mut g = actions_system.retrieve_game(1); + let mut p = actions_system.retrieve_game_player(caller_1, 1); + + let mut community_chest: ByteArray = "Get Out of Jail Free"; + + let (_, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 7); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + let chance = "Get out of Jail Free"; + + let (_, ply1) = actions_system.process_chance_card(g.clone(), p, chance); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 5); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + let chance = "Go to Jail"; + + let (_, ply) = actions_system.process_chance_card(g.clone(), p, chance); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 10); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + let chance = "Go to Jail"; + + let (game, ply1) = actions_system.process_community_chest_card(g.clone(), p, chance); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + actions_system.use_getout_of_jail_community_chest(game.id); + actions_system.move_player(1, 5); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + testing::set_contract_address(caller_2); + actions_system.use_getout_of_jail_chance(game.id); + actions_system.move_player(1, 10); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + let pl = actions_system.retrieve_game_player(caller_2, 1); + + assert!(p.jail_turns == 0, "p jail_turns not zero"); + assert!(!p.jailed, "p still jailed"); + assert!(!p.chance_jail_card, "p still has chance card"); + assert!(!p.comm_free_card, "p still has community card"); + + assert!(pl.jail_turns == 0, "pl jail_turns not zero"); + assert!(!pl.jailed, "pl still jailed"); + assert!(!pl.chance_jail_card, "pl still has chance card"); + assert!(!pl.comm_free_card, "pl still has community card"); + } + + #[test] + fn test_going_to_jail_pay_fine_and_miss_3_turns() { + 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'); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 2); + + let mut g = actions_system.retrieve_game(1); + let mut p = actions_system.retrieve_game_player(caller_1, 1); + + let mut community_chest: ByteArray = "Get Out of Jail Free"; + + let (_, ply) = actions_system.process_community_chest_card(g.clone(), p, community_chest); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 7); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + let chance = "Get out of Jail Free"; + + let (_, ply1) = actions_system.process_chance_card(g.clone(), p, chance); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 5); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + let chance = "Go to Jail"; + + let (_, ply) = actions_system.process_chance_card(g.clone(), p, chance); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 10); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + let chance = "Go to Jail"; + + let (game, ply1) = actions_system.process_community_chest_card(g.clone(), p, chance); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + actions_system.pay_jail_fine(game.id); + actions_system.move_player(1, 5); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + assert!(p.jail_turns == 0, "p jail_turns not zero"); + assert!(!p.jailed, "p still jailed"); + assert!(p.balance == 1450, "pl balance error"); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 10); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + let pl = actions_system.retrieve_game_player(caller_2, 1); + + testing::set_contract_address(caller_1); + + actions_system.move_player(1, 5); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_1, 1); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 10); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + let pl = actions_system.retrieve_game_player(caller_2, 1); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 10); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + + actions_system.move_player(1, 5); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + testing::set_contract_address(caller_1); + actions_system.move_player(1, 10); + g = actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + + actions_system.move_player(1, 5); + g = actions_system.finish_turn(g); + + g = actions_system.retrieve_game(1); + p = actions_system.retrieve_game_player(caller_2, 1); + + g = actions_system.retrieve_game(1); + let pl = actions_system.retrieve_game_player(caller_2, 1); + + assert!(pl.jail_turns == 0, "pl.jail_turns not zero"); + assert!(pl.balance == 1500, "pl.balance not 1500"); + assert!(!pl.jailed, "pl is still jailed"); + assert!(pl.chance_jail_card, "pl does not have chance jail card"); + assert!(!pl.comm_free_card, "pl still has community jail card"); + assert!(pl.position == 15, "pl.position not 15"); + } + + #[test] + fn test_offer_trade_property_for_cash() { + 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, 4); + + 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, 5); + let ppt = actions_system.get_property(5, 1); + + let buyppt = actions_system.buy_property(ppt); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 1); + let mut property = actions_system.get_property(1, 1); + + actions_system.buy_property(property); + + assert(buyppt, 'Buy property failed'); + + testing::set_contract_address(caller_1); + // let ppt = actions_system.get_property(5, 1); + + let mut offered_property_ids: Array = array![]; + let mut requested_property_ids: Array = array![]; + offered_property_ids.append(5); + requested_property_ids.append(1); + let mut trade_id = actions_system + .offer_trade( + 1, + caller_2, + offered_property_ids, + requested_property_ids, + 0, + 250, + TradeOffer::PropertyForCash, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + // requested_property_ids, cash_offer, cash_request, trade_type ); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + let ppt = actions_system.get_property(5, 1); + + let pptfelt: felt252 = ppt.owner.into(); + + assert(ppt.owner == caller_2, 'property tf failed'); + assert(aji.balance == 1550, 'debit failed'); + assert(aji.properties_owned.len() == 0, 'aji .len failed'); + assert(*collins.properties_owned[1] == ppt.id, 'ownership transfer failed'); + assert(aji.no_section1 == 0, 'Section update'); + assert(collins.no_section1 == 1, 'Section update'); + } + + #[test] + fn test_offer_trade_property_for_property() { + 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, 4); + + 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, 6); + let ppt = actions_system.get_property(6, 1); + + let buyppt = actions_system.buy_property(ppt); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 1); + let mut property = actions_system.get_property(1, 1); + + actions_system.buy_property(property); + + assert(buyppt, 'Buy property failed'); + + testing::set_contract_address(caller_1); + // let ppt = actions_system.get_property(5, 1); + + 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_2, + offered_property_ids, + requested_property_ids, + 0, + 0, + TradeOffer::PropertyForProperty, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + // requested_property_ids, cash_offer, cash_request, trade_type ); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + let ppt = actions_system.get_property(6, 1); + let ppp = actions_system.get_property(1, 1); + + let ppt_felt: felt252 = ppt.owner.into(); + let ppp_felt: felt252 = ppp.owner.into(); + + println!("ppt_felt : {}", ppt_felt); + println!("ppp_felt : {}", ppp_felt); + + assert(ppt.owner == caller_2, 'trade failed'); + assert(ppp.owner == caller_1, 'trade failed'); + assert(aji.no_section1 == 1, 'Section update'); + assert(collins.no_section1 == 0, 'Section update'); + assert(aji.no_section2 == 0, 'Section update'); + assert(collins.no_section2 == 1, 'Section update'); + } + + #[test] + fn test_offer_trade_cash_for_property() { + 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, 4); + + 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, 6); + let ppt = actions_system.get_property(6, 1); + + let buyppt = actions_system.buy_property(ppt); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 1); + let mut property = actions_system.get_property(1, 1); + + actions_system.buy_property(property); + + assert(buyppt, 'Buy property failed'); + + testing::set_contract_address(caller_1); + // let ppt = actions_system.get_property(5, 1); + + 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_2, + offered_property_ids, + requested_property_ids, + 250, + 0, + TradeOffer::CashForProperty, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + // requested_property_ids, cash_offer, cash_request, trade_type ); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + let ppt = actions_system.get_property(6, 1); + let ppp = actions_system.get_property(1, 1); + + let ppt_felt: felt252 = ppt.owner.into(); + let ppp_felt: felt252 = ppp.owner.into(); + + println!("aji balance : {} ", aji.balance); + println!("collins balance : {} ", collins.balance); + + assert(ppt.owner == caller_1, 'trade failed'); + assert(ppp.owner == caller_1, 'trade failed'); + assert(aji.no_section1 == 1, 'Section update'); + assert(collins.no_section1 == 0, 'Section update'); + assert(aji.no_section2 == 1, 'Section update'); + assert(collins.no_section2 == 0, 'Section update'); + } + #[test] + // fn test_offer_trade_property_for_cash_and_property() { + fn test_offer_cash_plus_property_for_property() { + 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, 4); + + 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, 6); + let ppt = actions_system.get_property(6, 1); + + let buyppt = actions_system.buy_property(ppt); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 1); + let mut property = actions_system.get_property(1, 1); + + actions_system.buy_property(property); + + assert(buyppt, 'Buy property failed'); + + testing::set_contract_address(caller_1); + // let ppt = actions_system.get_property(5, 1); + + 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_2, + offered_property_ids, + requested_property_ids, + 250, + 0, + TradeOffer::CashPlusPropertyForProperty, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + // requested_property_ids, cash_offer, cash_request, trade_type ); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + let ppt = actions_system.get_property(6, 1); + let ppp = actions_system.get_property(1, 1); + + let ppt_felt: felt252 = ppt.owner.into(); + let ppp_felt: felt252 = ppp.owner.into(); + + println!("ppt_felt : {}", ppt_felt); + println!("ppp_felt : {}", ppp_felt); + println!("aji balance : {} ", aji.balance); + println!("collins balance : {} ", collins.balance); + + assert(ppt.owner == caller_2, 'trade failed'); + assert(ppp.owner == caller_1, 'trade failed'); + assert(aji.no_section1 == 1, 'Section update'); + assert(collins.no_section1 == 0, 'Section update'); + assert(aji.no_section2 == 0, 'Section update'); + assert(collins.no_section2 == 1, 'Section update'); + } + #[test] + fn test_offer_trade_property_for_cash_and_property() { + 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, 4); + + 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, 6); + let ppt = actions_system.get_property(6, 1); + + let buyppt = actions_system.buy_property(ppt); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 1); + let mut property = actions_system.get_property(1, 1); + + actions_system.buy_property(property); + + assert(buyppt, 'Buy property failed'); + + testing::set_contract_address(caller_1); + // let ppt = actions_system.get_property(5, 1); + + 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_2, + offered_property_ids, + requested_property_ids, + 0, + 250, + TradeOffer::PropertyForCashPlusProperty, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + // requested_property_ids, cash_offer, cash_request, trade_type ); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + let ppt = actions_system.get_property(6, 1); + let ppp = actions_system.get_property(1, 1); + + let ppt_felt: felt252 = ppt.owner.into(); + let ppp_felt: felt252 = ppp.owner.into(); + + println!("ppt_felt : {}", ppt_felt); + println!("ppp_felt : {}", ppp_felt); + println!("aji balance : {} ", aji.balance); + println!("collins balance : {} ", collins.balance); + + assert(ppt.owner == caller_2, 'trade failed'); + assert(ppp.owner == caller_1, 'trade failed'); + assert(aji.no_section1 == 1, 'Section update'); + assert(collins.no_section1 == 0, 'Section update'); + assert(aji.no_section2 == 0, 'Section update'); + assert(collins.no_section2 == 1, 'Section update'); + } + + #[test] + fn test_offer_trade_cash_for_chaance_jail_card() { + 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, 4); + + 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, 7); + 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_chance_card(g.clone(), p, chance); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 1); + let mut property = actions_system.get_property(1, 1); + actions_system.buy_property(property); + + testing::set_contract_address(caller_1); + let mut ga = actions_system.retrieve_game(1); + actions_system.move_player(1, 1); + actions_system.finish_turn(ga); + + 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, + requested_property_ids, + 50, + 0, + TradeOffer::CashForChanceJailCard, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + + println!("aji balance : {} ", aji.balance); + println!("collins balance : {} ", collins.balance); + + assert(!aji.chance_jail_card, 'Section update'); + assert(collins.chance_jail_card, 'Section update'); + } + + #[test] + fn test_offer_trade_chance_jail_card_for_cash() { + 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, 4); + + 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, 7); + 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_chance_card(g.clone(), p, chance); + actions_system.finish_turn(g.clone()); + + testing::set_contract_address(caller_2); + actions_system.move_player(1, 1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + 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_2, + offered_property_ids, + requested_property_ids, + 0, + 50, + TradeOffer::ChanceJailCardForCash, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + + println!("aji balance : {} ", aji.balance); + println!("collins balance : {} ", collins.balance); + + assert(!aji.chance_jail_card, 'Section update'); + assert(collins.chance_jail_card, 'Section update'); + } + + #[test] + fn test_offer_trade_cash_for_community_jail_card() { + 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, 4); + + 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); + actions_system.move_player(1, 1); + let mut property = actions_system.get_property(1, 1); + actions_system.buy_property(property); + + testing::set_contract_address(caller_1); + 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_2, + offered_property_ids, + requested_property_ids, + 0, + 50, + TradeOffer::CashForCommunityJailCard, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 2); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_2); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + actions_system.move_player(1, 5); + + println!("aji balance : {} ", aji.balance); + println!("collins balance : {} ", collins.balance); + + assert(!aji.comm_free_card, 'Section update'); + assert(collins.comm_free_card, 'Section update'); + } + + #[test] + fn test_offer_trade_community_jail_card_for_cash() { + 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, 4); + + 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, + requested_property_ids, + 50, + 0, + TradeOffer::CommunityJailCardForCash, + ); + + println!("trade id : {} ", trade_id); + + actions_system.move_player(1, 5); + let g = actions_system.retrieve_game(1); + actions_system.finish_turn(g); + + testing::set_contract_address(caller_1); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + + assert(!aji.comm_free_card, 'Section update'); + assert(collins.comm_free_card, 'Section update'); + } + + #[test] + fn test_offer_test_counter_trade() { + 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, 4); + + 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 + .counter_trade( + 1, + 1, + offered_property_ids, + requested_property_ids.clone(), + 50, + 0, + TradeOffer::CommunityJailCardForCash, + ); + + testing::set_contract_address(caller_2); + testing::set_contract_address(caller_2); + actions_system.approve_counter_trade(1); + + testing::set_contract_address(caller_1); + let s = actions_system.accept_trade(1, 1); + assert(s, 'accept failed'); + + let aji = actions_system.retrieve_game_player(caller_1, 1); + let mut collins = actions_system.retrieve_game_player(caller_2, 1); + assert(!aji.comm_free_card, 'Section update'); + assert(collins.comm_free_card, 'Section update'); + } + + #[test] + fn test_offer_test_reject_trade() { + 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, 4); + + 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.reject_trade(trade_id, 1); + + let trade = actions_system.get_trade(trade_id); + assert(trade.status == TradeStatus::Rejected, 'Trade not rejected'); + } }