diff --git a/src/interfaces/IWorld.cairo b/src/interfaces/IWorld.cairo index d246e1e..4d80bd9 100644 --- a/src/interfaces/IWorld.cairo +++ b/src/interfaces/IWorld.cairo @@ -1,5 +1,6 @@ use dojo_starter::model::game_model::{GameMode, Game}; use dojo_starter::model::player_model::{PlayerSymbol, Player}; +use dojo_starter::model::property_model::{Property}; use starknet::{ContractAddress}; @@ -11,7 +12,36 @@ pub trait IWorld { fn retrieve_player(ref self: T, addr: ContractAddress) -> Player; fn create_new_game( ref self: T, game_mode: GameMode, player_symbol: PlayerSymbol, number_of_players: u8, - ) -> u64; - fn create_new_game_id(ref self: T) -> u64; - fn retrieve_game(ref self: T, game_id: u64) -> Game; + ) -> u256; + fn create_new_game_id(ref self: T) -> u256; + fn retrieve_game(ref self: T, game_id: u256) -> Game; + fn generate_properties( + ref self: T, + id: u8, + game_id: u256, + name: felt252, + cost_of_property: u256, + rent_site_only: u256, + rent_one_house: u256, + rent_two_houses: u256, + rent_three_houses: u256, + rent_four_houses: u256, + cost_of_house: u256, + rent_hotel: u256, + is_mortgaged: bool, + group_id: u8, + ); + fn get_property(ref self: T, id: u8, game_id: u256) -> Property; + fn buy_property(ref self: T, property_id: u8, game_id: u256) -> bool; + fn sell_property(ref self: T, property_id: u8, game_id: u256) -> bool; + fn mortgage_property(ref self: T, property_id: u8, game_id: u256) -> bool; + fn unmortgage_property(ref self: T, property_id: u8, game_id: u256) -> bool; + fn collect_rent(ref self: T, property_id: u8, game_id: u256) -> bool; + fn transfer_from( + ref self: T, from: ContractAddress, to: ContractAddress, game_id: u256, amount: u256, + ); + fn buy_house_or_hotel(ref self: T, property_id: u8, game_id: u256) -> bool; + fn sell_house_or_hotel(ref self: T, property_id: u8, game_id: u256) -> bool; + fn mint(ref self: T, recepient: ContractAddress, game_id: u256, amount: u256); + fn get_players_balance(ref self: T, player: ContractAddress, game_id: u256) -> u256; } diff --git a/src/lib.cairo b/src/lib.cairo index 2f56f66..b472b96 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -8,6 +8,7 @@ pub mod interfaces { pub mod model { pub mod game_model; pub mod player_model; + pub mod property_model; } pub mod tests { diff --git a/src/model/game_model.cairo b/src/model/game_model.cairo index 73f9016..bf51a8f 100644 --- a/src/model/game_model.cairo +++ b/src/model/game_model.cairo @@ -10,11 +10,21 @@ pub struct GameCounter { } +#[derive(Serde, Copy, Drop, Introspect, PartialEq)] +#[dojo::model] +pub struct GameBalance { + #[key] + pub playe_address: ContractAddress, + #[key] + pub game_id: u256, + pub balance: u256, +} + #[derive(Drop, Serde)] #[dojo::model] pub struct Game { #[key] - pub id: u64, // Unique id of the game + pub id: u256, // Unique id of the game pub created_by: felt252, // Address of the game creator pub is_initialised: bool, // Indicate whether game with given Id has been created/initialised pub status: GameStatus, // Status of the game @@ -50,7 +60,7 @@ pub struct Game { pub trait GameTrait { // Create and return a new game fn new( - id: u64, + id: u256, created_by: felt252, game_mode: GameMode, player_hat: felt252, @@ -88,7 +98,7 @@ pub enum GameMode { impl GameImpl of GameTrait { fn new( - id: u64, + id: u256, created_by: felt252, game_mode: GameMode, player_hat: felt252, diff --git a/src/model/property_model.cairo b/src/model/property_model.cairo new file mode 100644 index 0000000..2b404cb --- /dev/null +++ b/src/model/property_model.cairo @@ -0,0 +1,128 @@ +use starknet::{ContractAddress, contract_address_const}; + +#[derive(Copy, Drop, Serde)] +#[dojo::model] +pub struct Property { + #[key] + pub id: u8, + #[key] + game_id: u256, + pub name: felt252, + pub owner: ContractAddress, + pub cost_of_property: u256, + pub rent_site_only: u256, + pub rent_one_house: u256, + pub rent_two_houses: u256, + pub rent_three_houses: u256, + pub rent_four_houses: u256, + pub cost_of_house: u256, + pub rent_hotel: u256, + pub is_mortgaged: bool, + pub group_id: u8, + pub for_sale: bool, + pub development: u8, +} + +#[derive(Drop, Copy, Serde)] +#[dojo::model] +pub struct PropertyToId { + #[key] + pub name: felt252, + pub id: u8, +} + +#[derive(Drop, Copy, Serde)] +#[dojo::model] +pub struct IdToProperty { + #[key] + pub id: u8, + pub name: felt252, +} + +pub trait PropertyTrait { + fn new( + id: u8, + game_id: u256, + name: felt252, + cost: u256, + rent_site_only: u256, + rent_one_house: u256, + rent_two_houses: u256, + rent_three_houses: u256, + rent_four_houses: u256, + cost_of_house: u256, + rent_hotel: u256, + group_id: u8, + ) -> Property; + fn set_owner(property: Property, new_owner: ContractAddress); + fn get_rent_amount(property: Property, houses: u8, hotel: bool) -> u256; + fn mortgage(property: Property); + fn lift_mortgage(property: Property); +} + +impl PropertyImpl of PropertyTrait { + fn new( + id: u8, + game_id: u256, + name: felt252, + cost: u256, + rent_site_only: u256, + rent_one_house: u256, + rent_two_houses: u256, + rent_three_houses: u256, + rent_four_houses: u256, + cost_of_house: u256, + rent_hotel: u256, + group_id: u8, + ) -> Property { + let zero_address: ContractAddress = contract_address_const::<0>(); + Property { + id, + game_id, + name, + owner: zero_address, + cost_of_property: cost, + rent_site_only: rent_site_only, + rent_one_house: rent_one_house, + rent_two_houses: rent_two_houses, + rent_three_houses: rent_three_houses, + rent_four_houses: rent_four_houses, + rent_hotel: rent_hotel, + cost_of_house, + is_mortgaged: false, + group_id, + for_sale: true, + development: 0, + } + } + + + fn set_owner(mut property: Property, new_owner: ContractAddress) { + property.owner = new_owner; + } + + fn get_rent_amount(mut property: Property, houses: u8, hotel: bool) -> u256 { + if property.is_mortgaged { + return 0; + } + if hotel { + return property.rent_hotel; + } + match houses { + 0 => property.rent_site_only, + 1 => property.rent_one_house, + 2 => property.rent_two_houses, + 3 => property.rent_three_houses, + 4 => property.rent_four_houses, + _ => property.rent_site_only // default fallback + } + } + + fn mortgage(mut property: Property) { + property.is_mortgaged = true; + } + + fn lift_mortgage(mut property: Property) { + property.is_mortgaged = false; + } +} diff --git a/src/systems/world.cairo b/src/systems/world.cairo index 21ba787..90da236 100644 --- a/src/systems/world.cairo +++ b/src/systems/world.cairo @@ -1,4 +1,6 @@ -use dojo_starter::model::game_model::{GameMode, Game, GameTrait, GameCounter, GameStatus}; +use dojo_starter::model::game_model::{ + GameMode, GameBalance, Game, GameTrait, GameCounter, GameStatus, +}; use dojo_starter::model::player_model::{ Player, PlayerSymbol, UsernameToAddress, AddressToUsername, PlayerTrait, }; @@ -9,11 +11,14 @@ use dojo_starter::interfaces::IWorld::IWorld; #[dojo::contract] pub mod world { use super::{ - IWorld, Player, GameMode, PlayerSymbol, Game, GameTrait, UsernameToAddress, + IWorld, Player, GameMode, GameBalance, PlayerSymbol, Game, GameTrait, UsernameToAddress, AddressToUsername, PlayerTrait, GameCounter, GameStatus, }; + use dojo_starter::model::property_model::{Property, PropertyTrait, PropertyToId, IdToProperty}; + use starknet::{ ContractAddress, get_caller_address, get_block_timestamp, contract_address_const, + get_contract_address, }; @@ -26,7 +31,7 @@ pub mod world { #[dojo::event] pub struct GameCreated { #[key] - pub game_id: u64, + pub game_id: u256, pub timestamp: u64, } @@ -44,7 +49,7 @@ pub mod world { #[dojo::event] pub struct GameStarted { #[key] - pub game_id: u64, + pub game_id: u256, pub timestamp: u64, } @@ -52,7 +57,7 @@ pub mod world { #[dojo::event] pub struct PlayerJoined { #[key] - pub game_id: u64, + pub game_id: u256, #[key] pub username: felt252, pub timestamp: u64, @@ -105,13 +110,22 @@ pub mod world { ); } - fn create_new_game_id(ref self: ContractState) -> u64 { + fn create_new_game_id(ref self: ContractState) -> u256 { let mut world = self.world_default(); let mut game_counter: GameCounter = world.read_model('v0'); let new_val = game_counter.current_val + 1; game_counter.current_val = new_val; world.write_model(@game_counter); - new_val + new_val.try_into().unwrap() + } + + fn get_players_balance( + ref self: ContractState, player: ContractAddress, game_id: u256, + ) -> u256 { + let world = self.world_default(); + + let players_balance: GameBalance = world.read_model((player, game_id)); + players_balance.balance } fn create_new_game( @@ -119,7 +133,7 @@ pub mod world { game_mode: GameMode, player_symbol: PlayerSymbol, number_of_players: u8, - ) -> u64 { + ) -> u256 { // Get default world let mut world = self.world_default(); @@ -207,13 +221,226 @@ pub mod world { player } - fn retrieve_game(ref self: ContractState, game_id: u64) -> Game { + fn retrieve_game(ref self: ContractState, game_id: u256) -> Game { // Get default world let mut world = self.world_default(); //get the game state let game: Game = world.read_model(game_id); game } + + fn generate_properties( + ref self: ContractState, + id: u8, + game_id: u256, + name: felt252, + cost_of_property: u256, + rent_site_only: u256, + rent_one_house: u256, + rent_two_houses: u256, + rent_three_houses: u256, + rent_four_houses: u256, + cost_of_house: u256, + rent_hotel: u256, + is_mortgaged: bool, + group_id: u8, + ) { + let mut world = self.world_default(); + let mut property: Property = world.read_model((id, game_id)); + + property = + PropertyTrait::new( + id, + game_id, + name, + cost_of_property, + rent_site_only, + rent_one_house, + rent_two_houses, + rent_three_houses, + rent_four_houses, + rent_hotel, + cost_of_house, + group_id, + ); + + let property_to_id: PropertyToId = PropertyToId { name, id }; + let id_to_property: IdToProperty = IdToProperty { id, name }; + + world.write_model(@property); + world.write_model(@property_to_id); + world.write_model(@id_to_property); + } + + fn get_property(ref self: ContractState, id: u8, game_id: u256) -> Property { + let mut world = self.world_default(); + let property = world.read_model((id, game_id)); + property + } + 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 buy_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)); + let contract_address = get_contract_address(); + let zero_address: ContractAddress = contract_address_const::<0>(); + let amount: u256 = property.cost_of_property; + + if property.owner == zero_address { + self.transfer_from(caller, contract_address, game_id.try_into().unwrap(), amount); + } else { + assert(property.for_sale == true, 'Property is not for sale'); + self.transfer_from(caller, property.owner, game_id.try_into().unwrap(), amount); + } + + property.owner = caller; + property.for_sale = false; + + world.write_model(@property); + true + } + fn mortgage_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, 'Only the owner can mortgage '); + assert(property.is_mortgaged == false, 'Property is already mortgaged'); + + let amount: u256 = property.cost_of_property / 2; + let contract_address = get_contract_address(); + + self.transfer_from(contract_address, caller, game_id, amount); + + property.is_mortgaged = true; + world.write_model(@property); + + true + } + + fn unmortgage_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, 'Only the owner can unmortgage'); + assert(property.is_mortgaged == true, 'Property is not mortgaged'); + + let mortgage_amount: u256 = property.cost_of_property / 2; + let interest: u256 = mortgage_amount * 10 / 100; // 10% interest + let repay_amount: u256 = mortgage_amount + interest; + + self.transfer_from(caller, get_contract_address(), game_id, repay_amount); + + property.is_mortgaged = false; + world.write_model(@property); + + true + } + + fn collect_rent(ref self: ContractState, property_id: u8, game_id: u256) -> bool { + let mut world = self.world_default(); + let caller = get_caller_address(); + let property: Property = world.read_model((property_id, game_id)); + let zero_address: ContractAddress = contract_address_const::<0>(); + + assert(property.owner != zero_address, 'Property is unowned'); + assert(property.owner != caller, 'You cannot pay rent to yourself'); + assert(property.is_mortgaged == false, 'No rent on mortgaged properties'); + + let rent_amount: u256 = match property.development { + 0 => property.rent_site_only, + 1 => property.rent_one_house, + 2 => property.rent_two_houses, + 3 => property.rent_three_houses, + 4 => property.rent_four_houses, + 5 => property.rent_hotel, + _ => panic!("Invalid development level"), + }; + + self.transfer_from(caller, property.owner, game_id, rent_amount); + + true + } + + + fn transfer_from( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + game_id: u256, + amount: u256, + ) { + let mut world = self.world_default(); + + let mut sender: GameBalance = world.read_model((from, game_id)); + let mut recepient: GameBalance = world.read_model((to, game_id)); + assert(sender.balance >= amount, 'insufficient funds'); + sender.balance -= amount; + recepient.balance += amount; + world.write_model(@sender); + world.write_model(@recepient); + } + + fn buy_house_or_hotel(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)); + let contract_address = get_contract_address(); + + assert(property.owner == caller, 'Only the owner '); + assert(property.is_mortgaged == false, 'Cannot develop'); + assert(property.development < 5, 'Maximum development '); + + let cost: u256 = property.cost_of_house; + self.transfer_from(caller, contract_address, game_id, cost); + + property.development += 1; // Increases to 5 (hotel) max + + world.write_model(@property); + + true + } + + fn sell_house_or_hotel(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)); + let contract_address = get_contract_address(); + + assert(property.owner == caller, 'Only the owner '); + assert(property.development > 0, 'No houses to sell'); + + let refund: u256 = property.cost_of_house / 2; + + self.transfer_from(contract_address, caller, game_id, refund); + + property.development -= 1; + + world.write_model(@property); + + true + } + fn mint(ref self: ContractState, recepient: ContractAddress, game_id: u256, amount: u256) { + let mut world = self.world_default(); + + let mut receiver: GameBalance = world.read_model((recepient, game_id)); + let balance = receiver.balance + amount; + receiver.balance = balance; + world.write_model(@receiver); + } } #[generate_trait] diff --git a/src/tests/test_world.cairo b/src/tests/test_world.cairo index 8ad49d9..4e5f51f 100644 --- a/src/tests/test_world.cairo +++ b/src/tests/test_world.cairo @@ -13,7 +13,11 @@ mod tests { use dojo_starter::model::game_model::{ - Game, m_Game, GameMode, GameStatus, GameCounter, m_GameCounter, + Game, m_Game, GameMode, GameStatus, GameCounter, m_GameCounter, GameBalance, m_GameBalance, + }; + + use dojo_starter::model::property_model::{ + Property, m_Property, IdToProperty, m_IdToProperty, PropertyToId, m_PropertyToId, }; use dojo_starter::model::player_model::{ Player, m_Player, UsernameToAddress, m_UsernameToAddress, AddressToUsername, @@ -27,6 +31,10 @@ mod tests { resources: [ TestResource::Model(m_Player::TEST_CLASS_HASH), TestResource::Model(m_Game::TEST_CLASS_HASH), + TestResource::Model(m_GameBalance::TEST_CLASS_HASH), + TestResource::Model(m_Property::TEST_CLASS_HASH), + TestResource::Model(m_IdToProperty::TEST_CLASS_HASH), + TestResource::Model(m_PropertyToId::TEST_CLASS_HASH), TestResource::Model(m_UsernameToAddress::TEST_CLASS_HASH), TestResource::Model(m_AddressToUsername::TEST_CLASS_HASH), TestResource::Model(m_GameCounter::TEST_CLASS_HASH), @@ -217,4 +225,481 @@ mod tests { assert(game_id == 1, 'Wrong game id'); println!("game_id: {}", game_id); } + #[test] + fn test_property() { + let caller_1 = contract_address_const::<'aji'>(); + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + actions_system + .generate_properties(1, 1, 'Eth_Lane', 200, 10, 100, 200, 300, 400, 300, 500, false, 4); + + let property = actions_system.get_property(1, 1); + + assert(property.id == 1, 'wrong id'); + } + + #[test] + fn test_buy_property() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + actions_system + .generate_properties(1, 1, 'Eth_Lane', 200, 10, 100, 200, 300, 400, 300, 500, false, 4); + + let property = actions_system.get_property(1, 1); + + assert(property.id == 1, 'wrong id'); + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id: u256 = actions_system + .create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + let game: Game = actions_system.retrieve_game(game_id); + assert(game.created_by == username, 'Wrong game id'); + let property = actions_system.get_property(1, game_id); + assert(property.owner == caller_1, 'invalid property txn'); + } + + + #[test] + fn test_mint_and_balance() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + let player_balance = actions_system.get_players_balance(caller_1, game_id); + assert(player_balance == 10000, 'mint failure'); + } + + #[test] + fn test_buy_property_from_a_player() { + let caller_1 = contract_address_const::<'aji'>(); + let caller_2 = contract_address_const::<'ajidokwu'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + actions_system.mint(caller_2, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + actions_system.sell_property(1, game_id); + + testing::set_contract_address(caller_2); + actions_system.buy_property(1, game_id); + + let property = actions_system.get_property(1, game_id); + assert(property.owner == caller_2, 'invalid property txn'); + } + + #[test] + #[should_panic] + fn test_put_another_player_property_for_sale() { + let caller_1 = contract_address_const::<'aji'>(); + let caller_2 = contract_address_const::<'ajidokwu'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + actions_system.mint(caller_2, game_id, 10000); + + testing::set_contract_address(caller_1); + + actions_system.buy_property(1, game_id); + + testing::set_contract_address(caller_2); + actions_system.sell_property(1, game_id); + } + + + #[test] + #[should_panic] + fn test_buy_property_thats_not_for_sale_from_a_player() { + let caller_1 = contract_address_const::<'aji'>(); + let caller_2 = contract_address_const::<'ajidokwu'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + actions_system.mint(caller_2, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + testing::set_contract_address(caller_2); + actions_system.buy_property(1, game_id); + + let property = actions_system.get_property(1, game_id); + assert(property.owner == caller_2, 'invalid property txn'); + } + + #[test] + fn test_mortgage_property() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + let balance_before_mortgage = actions_system.get_players_balance(caller_1, game_id); + actions_system.mortgage_property(1, game_id); + let balance_after_mortgage = actions_system.get_players_balance(caller_1, game_id); + let property = actions_system.get_property(1, game_id); + println!( + "This is the before and this is the after before {} and after {}", + balance_after_mortgage, + balance_before_mortgage, + ); + assert(property.is_mortgaged, 'invalid is_mortgaged txn'); + } + + #[test] + #[should_panic] + fn test_mortgage_another_player_property() { + let caller_1 = contract_address_const::<'aji'>(); + let caller_2 = contract_address_const::<'ajidokwu'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + testing::set_contract_address(caller_2); + actions_system.mortgage_property(1, game_id); + + let property = actions_system.get_property(1, game_id); + assert(property.is_mortgaged, 'invalid is_mortgaged txn'); + } + + #[test] + fn test_unmortgage_property() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + actions_system.mortgage_property(1, game_id); + let balance_before_unmortgage = actions_system.get_players_balance(caller_1, game_id); + actions_system.unmortgage_property(1, game_id); + let balance_after_unmortgage = actions_system.get_players_balance(caller_1, game_id); + let property = actions_system.get_property(1, game_id); + assert(!property.is_mortgaged, 'invalid is_mortgaged txn'); + } + + #[test] + fn test_upgrade_property() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + actions_system.buy_house_or_hotel(1, game_id); + + let property = actions_system.get_property(1, game_id); + assert(property.development == 1, 'invalid uy property txn'); + } + + #[test] + #[should_panic] + fn test_upgrade_someone_else_property() { + let caller_1 = contract_address_const::<'aji'>(); + let caller_2 = contract_address_const::<'ajidokwu'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + actions_system.mint(caller_2, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + testing::set_contract_address(caller_2); + actions_system.buy_house_or_hotel(1, game_id); + + let property = actions_system.get_property(1, game_id); + assert(property.development == 1, 'invalid uy property txn'); + } + + #[test] + #[should_panic] + fn test_upgrade_property_more_than_allowed() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + } + + #[test] + fn test_downgrade_property() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + actions_system.sell_house_or_hotel(1, game_id); + + let property = actions_system.get_property(1, game_id); + assert(property.development == 2, 'invalid uy property txn'); + } + + #[test] + #[should_panic] + fn test_downgrade_someone_else_property() { + let caller_1 = contract_address_const::<'aji'>(); + let caller_2 = contract_address_const::<'ajidokwu'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + actions_system.mint(caller_2, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + testing::set_contract_address(caller_2); + actions_system.sell_house_or_hotel(1, game_id); + + let property = actions_system.get_property(1, game_id); + assert(property.development == 1, 'invalid uy property txn'); + } + + #[test] + #[should_panic] + fn test_downgrade_property_more_than_allowed() { + let caller_1 = contract_address_const::<'aji'>(); + let username = 'Ajidokwu'; + + let ndef = namespace_def(); + let mut world = spawn_test_world([ndef].span()); + world.sync_perms_and_inits(contract_defs()); + + let (contract_address, _) = world.dns(@"world").unwrap(); + let actions_system = IWorldDispatcher { contract_address }; + + testing::set_contract_address(caller_1); + actions_system.register_new_player(username, false); + + testing::set_contract_address(caller_1); + let game_id = actions_system.create_new_game(GameMode::MultiPlayer, PlayerSymbol::Hat, 4); + assert(game_id == 1, 'Wrong game id'); + + actions_system.mint(caller_1, game_id, 10000); + + testing::set_contract_address(caller_1); + actions_system.buy_property(1, game_id); + + actions_system.buy_house_or_hotel(1, game_id); + actions_system.buy_house_or_hotel(1, game_id); + actions_system.sell_house_or_hotel(1, game_id); + actions_system.sell_house_or_hotel(1, game_id); + actions_system.sell_house_or_hotel(1, game_id); + } }