ETH Price: $2,144.40 (-1.97%)

Transaction Decoder

Block:
7989513 at Jun-19-2019 03:21:33 PM +UTC
Transaction Fee:
0.00006466 ETH $0.14
Gas Used:
64,660 Gas / 1 Gwei

Emitted Events:

81 master.RollDice( player=[Sender] 0xc82a13cdbf985ca55f166da1dde4abafd2e88da7, city=1, id=54, unmovable=True )

Account State Difference:

  Address   Before After State Difference Code
0x0aC10Bf0...a5b659303
(Spark Pool)
3,176.710974919703456613 Eth3,176.711039579703456613 Eth0.00006466
0xc82A13CD...fd2E88da7
0.00086478 Eth
Nonce: 1
0.00080012 Eth
Nonce: 2
0.00006466

Execution Trace

master.CALL( )
  • slave.CALL( )
  • slave.ownerOf( _tokenId=54 ) => ( 0x5Dd39A3fc1c33e4411438E79Bf86d4fAb4f6932f )
    File 1 of 2: master
    pragma solidity ^0.4.25;
    
     library SafeMath{
         function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a);
            return c;
        } 
           
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a);
            uint256 c = a - b;
            return c; 
        }
        
         function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            if (a == 0) { 
                return 0;
            }
            uint256 c = a * b;
            require(c / a == b);
            return c;
        }
         
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b > 0);
            uint256 c = a / b;
            return c;
        }
     }
     
     library SafeMath16{
         function add(uint16 a, uint16 b) internal pure returns (uint16) {
            uint16 c = a + b;
            require(c >= a);
    
            return c;
        }
        
        function sub(uint16 a, uint16 b) internal pure returns (uint16) {
            require(b <= a);
            uint16 c = a - b;
            return c;
        }
        
         function mul(uint16 a, uint16 b) internal pure returns (uint16) {
            if (a == 0) {
                return 0;
            }
            uint16 c = a * b;
            require(c / a == b);
            return c;
        }
        
        function div(uint16 a, uint16 b) internal pure returns (uint16) {
            require(b > 0);
            uint16 c = a / b;
            return c;
        }
     }
    
    contract owned {
    
        address public manager;
    
        constructor() public{
            manager = msg.sender;
        }
     
        modifier onlymanager{
            require(msg.sender == manager);
            _;
        }
    
        function transferownership(address _new_manager) public onlymanager {
            manager = _new_manager;
        }
    }
    
    
    contract byt_str {
        function stringToBytes32(string memory source) pure public returns (bytes32 result) {
           
            assembly {
                result := mload(add(source, 32))
            }
        }
    
        function bytes32ToString(bytes32 x) pure public returns (string) {
            bytes memory bytesString = new bytes(32);
            uint charCount = 0;
            for (uint j = 0; j < 32; j++) {
                byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
                if (char != 0) {
                    bytesString[charCount] = char;
                    charCount++;
                }
            }
            bytes memory bytesStringTrimmed = new bytes(charCount);
            for (j = 0; j < charCount; j++) {
                bytesStringTrimmed[j] = bytesString[j];
            }
            return string(bytesStringTrimmed);
        }
    
    }
    
    
    interface ERC20_interface {
      function decimals() external view returns(uint8);
      function totalSupply() external view returns (uint256);
      function balanceOf(address who) external view returns (uint256);
      
      function transfer(address to, uint256 value) external returns(bool);
      function transferFrom(address _from, address _to, uint256 _value) external returns (bool success) ;
    }
    
    
    interface ERC721_interface{
         function balanceOf(address _owner) external view returns (uint256);
         function ownerOf(uint256 _tokenId) external view returns (address);
         function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
         function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
         function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
         function approve(address _approved, uint256 _tokenId) external payable;
         function setApprovalForAll(address _operator, bool _approved) external;
         function getApproved(uint256 _tokenId) external view returns (address);
         function isApprovedForAll(address _owner, address _operator) external view returns (bool);
     } 
     
     
     interface slave{
        function master_address() external view returns(address);
        
        function transferMayorship(address new_mayor) external;
        function city_number() external view returns(uint16);
        function area_number() external view returns(uint8);
        
        function inquire_totdomains_amount() external view returns(uint16);
        function inquire_domain_level_star(uint16 _id) external view returns(uint8, uint8);
        function inquire_domain_building(uint16 _id, uint8 _index) external view returns(uint8);
        function inquire_tot_domain_attribute(uint16 _id) external view returns(uint8[5]);
        function inquire_domain_cooltime(uint16 _id) external view returns(uint);
        function inquire_mayor_cooltime() external view returns(uint);
        function inquire_tot_domain_building(uint16 _id) external view returns(uint8[]);
        function inquire_own_domain(address _sender) external view returns(uint16[]);
        function inquire_land_info(uint16 _city, uint16 _id) external view returns(uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8);
        
        function inquire_building_limit(uint8 _building) external view returns(uint8);
        
        function domain_build(uint16 _id, uint8 _building) external;
        function reconstruction(uint16 _id, uint8 _index, uint8 _building)external;
        function set_domian_attribute(uint16 _id, uint8 _index) external;
        function domain_all_reward(uint8 _class, address _user) external;
        function mayor_reward(address _user) external; 
        function inquire_mayor_address() external view returns(address);
     
        function domain_reward(uint8 _class, address _user, uint16 _id) external;
        function transfer_master(address _to, uint16 _id) external;
        function retrieve_domain(address _user, uint _id) external;
        function at_Area() external view returns(string);
        function set_domain_cooltime(uint _cooltime) external;
     } 
     
     interface trade{
        function set_city_pool(uint _arina, uint16 _city )external;
        function inquire_pool(uint16 _city) external view returns(uint);
        function exchange_arina(uint _arina, uint16 _city, address _target) external;
     }
    
     contract master is owned, byt_str {
        using SafeMath for uint;
        using SafeMath16 for uint16;
        
        
        address arina_contract = 0xe6987cd613dfda0995a95b3e6acbabececd41376;
         
        address GIC_contract = 0x340e85491c5f581360811d0ce5cc7476c72900ba;
        address trade_address;
        address mix_address;
        
        uint16 public owner_slave_amount = 0; 
        uint random_seed;
        uint public probability = 1000000;
        bool public all_stop = false;
        
        
        struct _info{
            uint16 city; 
            uint16 domain; 
            bool unmovable; 
            bool lotto; 
            bool build; 
            bool reward;
        }
        
        
        address[] public owner_slave; 
       
        mapping (uint8 => string) public area; 
        mapping (uint8 => string) public building_type;  
        mapping (uint8 => uint) public building_price; 
         
        mapping(address => _info) public player_info;  
        
        mapping(bytes32 => address) public member;
        mapping(address => bytes32) public addressToName;
        
        
        
        event set_name(address indexed player, uint value); 
        event FirstSign(address indexed player,uint time); 
        event RollDice(address indexed player, uint16 city, uint16 id, bool unmovable); 
        event Change_city(address indexed player, uint16 city, uint16 id, bool unmovable);
        event Fly(address indexed player, uint16 city, uint16 id, bool unmovable);
        
        event PlayLotto(address indexed player,uint player_number, uint lotto_number);
        
        event PayArina(address indexed player, uint value, uint16 city, uint16 id);
        event BuyArina(address indexed player, uint value, uint16 city, uint16 id);
        event PayEth(address indexed player, uint value, uint16 city, uint16 id);
        event BuyEth(address indexed player, uint value, uint16 city, uint16 id);
        
        event Build(address indexed player, uint8 building, uint value);
        event Reconstruction(address indexed player, uint8 building, uint value);
        
        
    
    
      function register(string _name) public{
          if(keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(""))) {
              revert();
          } 
          bytes32 byte_name =  stringToBytes32(_name);
       
          if(addressToName[msg.sender] == 0x0){
              member[byte_name] = msg.sender;
              addressToName[msg.sender] = byte_name;
              emit FirstSign(msg.sender,now); 
          }else{
              revert(); 
          }
          
      }
    
    
    
        function() public payable{}
        
        function rollDice() external{
            require(!all_stop);
            require(owner_slave_amount >= 1);
            require(!player_info[msg.sender].unmovable,"不可移動");
            uint16 random = uint16((keccak256(abi.encodePacked(now, random_seed))));
            random_seed.add(1);
            
            if(player_info[msg.sender].city == 0){
                player_info[msg.sender].city = 1;
            }
            
            uint16 in_city = player_info[msg.sender].city;
            
            
            uint16 tot_domains = inquire_city_totdomains(in_city);
            uint16 go_domains_id = random % tot_domains; 
            
            
            
            player_info[msg.sender].domain = go_domains_id;
            
            address city_address = owner_slave[in_city];
            address domain_owner = ERC721_interface(city_address).ownerOf(go_domains_id);
            
            if (domain_owner != 0x0){
                if(domain_owner == msg.sender){
                    player_info[msg.sender].build = true; 
                    
                }
                else{
                    player_info[msg.sender].unmovable = true; 
                    player_info[msg.sender].reward = false;
                }
    		}
            
            emit RollDice(msg.sender, in_city, go_domains_id, player_info[msg.sender].unmovable);
        }
        
        function change_city(address _sender, uint16 go_city) private{
            require(!all_stop);
            require(owner_slave_amount >= 1);
            require(!player_info[_sender].unmovable,"不可移動"); 
            
            uint16 random = uint16((keccak256(abi.encodePacked(now, random_seed))));
            random_seed.add(1);
            
            uint16 tot_domains = inquire_city_totdomains(go_city);
            uint16 go_domains_id = random % tot_domains; 
            
            player_info[_sender].city = go_city;
            player_info[_sender].domain = go_domains_id;
            
            
            address city_address = owner_slave[go_city];
            address domain_owner = ERC721_interface(city_address).ownerOf(go_domains_id);
            
            if (domain_owner != 0x0){
                if(domain_owner == _sender){
                    player_info[_sender].build = true; 
                    
                }
                else{
                    player_info[_sender].unmovable = true; 
                    player_info[msg.sender].reward = false;
                }
    		}
             
            emit Change_city(_sender, go_city, go_domains_id, player_info[_sender].unmovable);
        }
        
        function fly(uint16 _city, uint16 _domain) public payable{
            require(msg.value == 0.1 ether);
            require(owner_slave_amount >= 1);
            require(!player_info[msg.sender].unmovable);
            
            address[] memory checkPlayer;
            checkPlayer = checkBuildingPlayer(player_info[msg.sender].city,14);
         
            
            player_info[msg.sender].city = _city;
            player_info[msg.sender].domain = _domain;
            
            address city_address = owner_slave[_city];
            address domain_owner = ERC721_interface(city_address).ownerOf(_domain);
            uint exchange_player_ETH;
            
    
            if(checkPlayer.length!=0){
                exchange_player_ETH = msg.value.div(10).mul(1);
                
                for(uint8 i = 0 ; i< checkPlayer.length;i++){
        	        checkPlayer[i].transfer(exchange_player_ETH.div(checkPlayer.length));
                }
            } 
    
            
            if (domain_owner != 0x0){
                if(domain_owner == msg.sender){
                    player_info[msg.sender].build = true; 
                    
                }
                else{
                    player_info[msg.sender].unmovable = true; 
                    player_info[msg.sender].reward = false;
                }
    		}
            player_info[msg.sender].lotto = true;
            emit Fly(msg.sender, _city, _domain , player_info[msg.sender].unmovable);
        }
        
        function playLotto() external{
            require(!all_stop);
            require(player_info[msg.sender].lotto);
            
            uint random = uint((keccak256(abi.encodePacked(now, random_seed))));
            uint random2 = uint((keccak256(abi.encodePacked(random_seed, msg.sender))));
            random_seed = random_seed.add(1);
    
            address _address = inquire_slave_address(player_info[msg.sender].city);
             
            if(player_info[msg.sender].unmovable == false){
                (,uint8 _star) = slave(_address).inquire_domain_level_star(player_info[msg.sender].domain);
                    if(_star <= 1){
                        _star = 1;
                    }
                probability = probability.div(2**(uint(_star)-1));                   
                uint8[] memory buildings = slave(_address).inquire_tot_domain_building(player_info[msg.sender].domain);
                for(uint8 i=0;i< buildings.length;i++){
                    if(buildings[i] == 8 ){
                        probability = probability.div(10).mul(9);      
                        break; 
                    }
                }
            }
            
            uint lotto_number = random % probability;
            uint player_number =  random2 % probability;
            
            probability = 1000000;   
            
            if(lotto_number == player_number){
                msg.sender.transfer(address(this).balance.div(10));
            }
            
            player_info[msg.sender].lotto = false;
            
            
            emit PlayLotto(msg.sender, player_number, lotto_number);
        }
    
         
    
    
        function payRoadETH_amount(uint8 _level, uint8 _star) public pure returns(uint){
             
            if(_level <= 1){
        	   return  0.02 ether * 2**(uint(_star)-1) ;
        	} 
        	else if(_level > 1) {    
        	   return  0.02 ether * 2**(uint(_star)-1)*(3**(uint(_level)-1))/(2**(uint(_level)-1)) ;
        	} 
        }
         
        function buyLandETH_amount(uint8 _level, uint8 _star) public pure returns(uint){
    
             
            if(_level <= 1){
        	   return  0.2 ether * 2**(uint(_star)-1) ;
        	} 
        	else if(_level > 1) {    
        	   return  0.2 ether * 2**(uint(_star)-1)*(3**(uint(_level)-1))/(2**(uint(_level)-1)) ;
        	} 
        }
         
        function payARINA_amount(uint8 _level, uint8 _star) public pure returns(uint){
    
            
            if(_level <= 1){
        	return (10**8) * (2**(uint(_star)-1)*10);
        	} 
        	
        	else if(_level > 1) {   
        	return (10**8) * (2**(uint(_star)-1)*10)*(3**(uint(_level)-1))/(2**(uint(_level)-1));
        	}
    
        }
         
        function buyLandARINA_amount() public pure returns(uint){
            return 2000*10**8;
        }
     
        function payRent_ETH() external payable{
            require(!all_stop);
            require(player_info[msg.sender].unmovable,"檢查不可移動");
            
            uint16 city = player_info[msg.sender].city; 
            uint16 domains_id = player_info[msg.sender].domain;  
            
            address city_address = owner_slave[city];
    		address domain_owner = ERC721_interface(city_address).ownerOf(domains_id);
    		
    		if (domain_owner == 0x0){
    		    revert("不用付手續費");
    		}
            
            (uint8 _level,uint8 _star) = slave(city_address).inquire_domain_level_star(domains_id);
            
            uint _payRoadETH_amount = payRoadETH_amount(_level, _star);
            
            require(msg.value == _payRoadETH_amount);
            
            player_info[msg.sender].unmovable = false;
    
            uint payRent_ETH_50toOwner = msg.value.div(10).mul(5);
    		uint payRent_ETH_10toTeam = msg.value.div(10);
    		uint payRent_ETH_20toCity = msg.value.div(10).mul(2); 
    		uint payRent_ETH_20toPool = msg.value.div(10).mul(2);
    		uint pay = payRent_ETH_50toOwner + payRent_ETH_10toTeam + payRent_ETH_20toCity + payRent_ETH_20toPool;
    		require(msg.value == pay);
    
    		domain_owner.transfer(payRent_ETH_50toOwner); 
            manager.transfer(payRent_ETH_10toTeam); 
            city_address.transfer(payRent_ETH_20toCity); 
            
            player_info[msg.sender].lotto = true;
            player_info[msg.sender].reward = true;
            emit PayEth(msg.sender, msg.value, city, domains_id);
        }
        
        function buyLand_ETH() external payable{
            require(!all_stop);
            require(player_info[msg.sender].unmovable,"檢查不可移動");
            
            uint16 city = player_info[msg.sender].city;
            uint16 domains_id = player_info[msg.sender].domain;
            
            address city_address = owner_slave[city];
            address domain_owner = ERC721_interface(city_address).ownerOf(domains_id);
            
            (uint8 _level,uint8 _star) = slave(city_address).inquire_domain_level_star(domains_id);
            
            uint _buyLandETH_amount = buyLandETH_amount(_level, _star);
            require(msg.value == _buyLandETH_amount); 
            
            if(domain_owner == 0x0){
                revert("第一次請用Arina購買");
            }
            
            uint BuyLand_ETH_50toOwner;
            uint BuyLand_ETH_10toTeam;
            uint BuyLand_ETH_20toCity; 
            uint BuyLand_ETH_20toPool;
            uint pay;
            
            if(_level <= 1){
                BuyLand_ETH_50toOwner = msg.value.div(10).mul(5);
            	BuyLand_ETH_10toTeam = msg.value.div(10);
            	BuyLand_ETH_20toCity = msg.value.div(10).mul(2); 
            	BuyLand_ETH_20toPool = msg.value.div(10).mul(2);
            	pay = BuyLand_ETH_50toOwner + BuyLand_ETH_10toTeam + BuyLand_ETH_20toCity +BuyLand_ETH_20toPool;
            	require(msg.value == pay);
            		 
            	domain_owner.transfer(BuyLand_ETH_50toOwner); 
                manager.transfer(BuyLand_ETH_10toTeam); 
                city_address.transfer(BuyLand_ETH_20toCity); 
                
            }
            else{
                BuyLand_ETH_50toOwner = msg.value.div(10).mul(8);
            	BuyLand_ETH_10toTeam = msg.value.div(20);
            	BuyLand_ETH_20toCity = msg.value.div(20);
            	BuyLand_ETH_20toPool = msg.value.div(10);
            	pay = BuyLand_ETH_50toOwner + BuyLand_ETH_10toTeam + BuyLand_ETH_20toCity +BuyLand_ETH_20toPool;
            	require(msg.value == pay);
            		
            	domain_owner.transfer(BuyLand_ETH_50toOwner); 
                manager.transfer(BuyLand_ETH_10toTeam); 
                city_address.transfer(BuyLand_ETH_20toCity); 
                
            }
            
            slave(city_address).transfer_master(msg.sender, domains_id); 
            
            player_info[msg.sender].unmovable = false;
            player_info[msg.sender].lotto = true;
            emit BuyEth(msg.sender, msg.value, city, domains_id);
        }
         
        function _payRent_ARINA(address _sender, uint _value) private{
            require(!all_stop);
            
            require(player_info[_sender].unmovable,"檢查不可移動");
            
            uint16 city = player_info[_sender].city;
            uint16 domains_id = player_info[_sender].domain; 
            
            address city_address = owner_slave[city];
    		address domain_owner = ERC721_interface(city_address).ownerOf(domains_id);
    		
    		if(domain_owner == 0x0){
                revert("空地不用付手續費");
            }
    
            (uint8 _level,uint8 _star) = slave(city_address).inquire_domain_level_star(domains_id);
            
            uint _payARINA_amount = payARINA_amount(_level, _star);
            
        	require(_value == _payARINA_amount,"金額不對");
            ERC20_interface arina = ERC20_interface(arina_contract);
            require(arina.transferFrom(_sender, domain_owner, _value),"交易失敗"); 
    
            player_info[_sender].unmovable = false;
            player_info[_sender].reward = true;
            
            emit PayArina(_sender, _value, city, domains_id);
        }
    
        function _buyLand_ARINA(address _sender, uint _value) private{ 
            
            
            require(!all_stop);
            uint16 city = player_info[_sender].city;
            uint16 domains_id = player_info[_sender].domain;
            
            address city_address = owner_slave[city];
    		address domain_owner = ERC721_interface(city_address).ownerOf(domains_id);
            
            if(domain_owner != 0x0){
                revert("空地才能用Arina買");
            }
            
            uint _buyLandARINA_amount = buyLandARINA_amount();
            
            require(_value ==  _buyLandARINA_amount,"金額不對");
            ERC20_interface arina = ERC20_interface(arina_contract);
            require(arina.transferFrom(_sender, trade_address, _value)); 
            
            slave(city_address).transfer_master(_sender, domains_id); 
            trade(trade_address).set_city_pool(_value,city);          
            
            player_info[_sender].unmovable = false;
            emit BuyArina(_sender, _value, city, domains_id);
        }
        
        function _build(address _sender, uint8 _building,uint _arina) private {
            require(!all_stop);
            require(player_info[_sender].build == true,"不能建設");
            uint16 city = player_info[_sender].city;
            uint16 domains_id = player_info[_sender].domain;
            
            address city_address = owner_slave[city];
    		address domain_owner = ERC721_interface(city_address).ownerOf(domains_id);
    		require(_sender == domain_owner,"擁有者不是自己");
    		
    		slave(city_address).domain_build(domains_id, _building);
    		player_info[_sender].build = false;
    		
    		emit Build(_sender, _building,_arina);
        }
        
        function reconstruction(uint8 _index, uint8 _building)public payable{
            uint16 city = player_info[msg.sender].city;
            uint16 domains_id = player_info[msg.sender].domain;
            uint BuyLand_ETH_toTeam;
            address city_address = owner_slave[city];
    		address domain_owner = ERC721_interface(city_address).ownerOf(domains_id);
    		require(msg.sender == domain_owner, "限定擁有者");
             
            uint arina_price = inquire_type_price(_building);
            uint eth_price = arina_price.mul(10**6); 
            
            require(msg.value == eth_price,"價格不對");
            BuyLand_ETH_toTeam = msg.value.div(10).mul(7);
            manager.transfer(BuyLand_ETH_toTeam); 
            slave(city_address).reconstruction(domains_id, _index, _building);
            player_info[msg.sender].lotto = true;
            emit Reconstruction(msg.sender, _building,eth_price);
        }
        
        function domain_attribute(uint16 _city,uint16 _id, uint8 _index) public{
            require(msg.sender == mix_address);
            require(!all_stop);
            address city_address = owner_slave[_city];
            slave(city_address).set_domian_attribute(_id,_index);
        }
         
        
        function reward(uint8 _class, uint16 _city, uint16 _domains_id) public{
            require(!all_stop);
            if(inquire_owner(_city,_domains_id) != msg.sender){     
                require(!player_info[msg.sender].unmovable,"不可移動"); 
                require(_city == player_info[msg.sender].city && _domains_id == player_info[msg.sender].domain);
                require(player_info[msg.sender].reward == true);
                player_info[msg.sender].reward = false;
            }
         
            address city_address = owner_slave[_city];
            slave(city_address).domain_reward(_class, msg.sender, _domains_id);
        }  
         
        function all_reward(uint8 _class,uint16 _city) public{
            address city_address;
            
            city_address = owner_slave[_city];
            slave(city_address).domain_all_reward(_class, msg.sender);
            
            
        }
          
        function mayor_all_reward(uint16 _city) public{
    
            address city_address = owner_slave[_city];
            address _mayor = slave(city_address).inquire_mayor_address();
            require(msg.sender == _mayor);
            slave(city_address).mayor_reward(msg.sender);
            
        }
         
        function set_member_name(address _owner, string new_name) payable public{
             require(msg.value == 0.1 ether);
             require(addressToName[msg.sender].length != 0); 
             require(msg.sender == _owner);
               
             bytes32 bytes_old_name = addressToName[msg.sender];   
             member[bytes_old_name] = 0x0;
             
             if(keccak256(abi.encodePacked(new_name)) == keccak256(abi.encodePacked(""))) {
                 revert(); 
             } 
             bytes32 bytes_new_name =  stringToBytes32(new_name);    
            
             member[bytes_new_name] = msg.sender; 
             addressToName[msg.sender] = bytes_new_name;
             emit set_name(msg.sender,msg.value);
              
        }
        
        function exchange(uint16 _city,uint _value) payable public{
            uint rate;
            uint pool = trade(trade_address).inquire_pool(_city);
            
            uint exchange_master_ETH;
            uint exchange_player_ETH;
            uint exchange_Pool_ETH;
            require(msg.value == _value*10 ** 13);
            require(_city == player_info[msg.sender].city);
            address[] memory checkPlayer;
            
            
            if(pool > 500000 * 10 ** 8){ 
                rate = 10000;
            }else if(pool > 250000 * 10 ** 8 && pool <= 500000 * 10 ** 8  ){
                rate = 5000;
            }else if(pool > 100000 * 10 ** 8 && pool <= 250000 * 10 ** 8  ){
                rate = 3000;
            }else if(pool <= 100000 * 10 ** 8){
                revert();
            } 
            uint exchangeArina = _value * rate * 10 ** 3;
            trade(trade_address).exchange_arina(exchangeArina,_city, msg.sender);
            
            checkPlayer = checkBuildingPlayer(_city,15);
            
            if(checkPlayer.length !=0){
                exchange_master_ETH = msg.value.div(10).mul(8);
                exchange_player_ETH = msg.value.div(10).mul(1);
                exchange_Pool_ETH = msg.value.div(10).mul(1);
                
                for(uint8 i = 0 ; i< checkPlayer.length;i++){
        	        checkPlayer[i].transfer(exchange_player_ETH.div(checkPlayer.length));
        	    }
            }else{
                exchange_master_ETH = msg.value.div(10).mul(9);
                exchange_Pool_ETH = msg.value.div(10);
            }
    
            manager.transfer(exchange_master_ETH); 
            
    
        } 
         
        function checkBuildingPlayer(uint16 _city,uint8 building) public view  returns(address[] ){  
            
            
            address[] memory _players = new address[](100);
            uint16 counter = 0;
            for(uint8 i=0 ; i<100; i++){
                uint8[] memory buildings = slave(owner_slave[_city]).inquire_tot_domain_building(i);
                if(buildings.length != 0){
                    for(uint8 j = 0; j < buildings.length; j++){ 
                        if(buildings[j] == building){
                            _players[counter] = inquire_owner(_city,i); 
                            counter = counter.add(1);
                            break;
                        } 
                    }  
                    
                }
            } 
            address[] memory players = new address[](counter);
            
            for (i = 0; i < counter; i++) {
                players[i] = _players[i];
            }
            
            
            return players;
        
        }
        
        
         
         
     
    
    
        
        
        
        
    
        function inquire_owner(uint16 _city, uint16 _domain) public view returns(address){
            address city_address = owner_slave[_city];
            return ERC721_interface(city_address).ownerOf(_domain);
        }
        
        function inquire_have_owner(uint16 _city, uint16 _domain) public view returns(bool){
            address city_address = owner_slave[_city];
            address domain_owner = ERC721_interface(city_address).ownerOf(_domain);
            if(domain_owner == 0x0){
            return false;
            }
            else{return true;}
        }
    
        
        function inquire_domain_level_star(uint16 _city, uint16 _domain) public view 
        returns(uint8, uint8){
            address _address = inquire_slave_address(_city);
            return slave(_address).inquire_domain_level_star(_domain);
        }
        
        function inquire_slave_address(uint16 _slave) public view returns(address){
            return owner_slave[_slave];
        }
        
        
        
        
        
        
        function inquire_city_totdomains(uint16 _index) public view returns(uint16){
            address _address = inquire_slave_address(_index);
            return  slave(_address).inquire_totdomains_amount();
        }
        
        function inquire_location(address _address) public view returns(uint16, uint16){
            return (player_info[_address].city, player_info[_address].domain);
        }
         
        function inquire_status(address _address) public view returns(bool, bool, bool){
            return (player_info[_address].unmovable, player_info[_address].lotto, player_info[_address].reward);
        }
        
        function inquire_type(uint8 _typeid) public view returns(string){
            return building_type[_typeid];
        }
        
        function inquire_type_price(uint8 _typeid) public view returns(uint){
            return building_price[_typeid];
        } 
        
        function inquire_building(uint16 _slave, uint16 _domain, uint8 _index)
        public view returns(uint8){
            address _address = inquire_slave_address(_slave);
            return slave(_address).inquire_domain_building(_domain, _index);
        }
        
        function inquire_building_amount(uint16 _slave,uint8 _building) public view returns(uint8){
            address _address = inquire_slave_address(_slave);
            return slave(_address).inquire_building_limit(_building);
        }
         
        function inquire_tot_attribute(uint16 _slave, uint16 _domain)
        public view returns(uint8[5]){
            address _address = inquire_slave_address(_slave);
            return slave(_address).inquire_tot_domain_attribute(_domain);
        }
        
    
        function inquire_cooltime(uint16 _slave, uint16 _domain)
        public view returns(uint){
            address _address = inquire_slave_address(_slave);
            return slave(_address).inquire_domain_cooltime(_domain);
        }
         
        
        
        
        
        
         
        function inquire_tot_building(uint16 _slave, uint16 _domain)
        public view returns(uint8[]){
            address _address = inquire_slave_address(_slave);
            return slave(_address).inquire_tot_domain_building(_domain);
        }
        
        function inquire_own_domain(uint16 _city) public view returns(uint16[]){
     
            address _address = inquire_slave_address(_city);
            return slave(_address).inquire_own_domain(msg.sender);
        }
        
        function inquire_land_info(uint16 _city, uint16 _id) public view returns(uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8){
        
            address _address = inquire_slave_address(_city);
            return slave(_address).inquire_land_info(_city,_id);
        }
         
        function inquire_GIClevel(address _address) view public returns(uint8 _level){
            uint GIC_balance = ERC20_interface(GIC_contract).balanceOf(_address);
            if (GIC_balance <= 1000*10**18){
                return 1;
            }
            else if(1000*10**18 < GIC_balance && GIC_balance <=10000*10**18){
                return 2;
            }
            else if(10000*10**18 < GIC_balance && GIC_balance <=100000*10**18){
                return 3;
            }
            else if(100000*10**18 < GIC_balance && GIC_balance <=500000*10**18){
                return 4;
            }
            else if(500000*10**18 < GIC_balance){
                return 5;
            }
            else revert();
        }
    
    
    
        
        function receiveApproval(address _sender, uint256 _value,
        address _tokenContract, bytes _extraData) public{
            
            require(_tokenContract == arina_contract);
              
            bytes1 action = _extraData[0];
        
        
            if (action == 0x0){ 
                  
                _payRent_ARINA(_sender, _value);
            }
          
            else if(action == 0x1){ 
              
                _buyLand_ARINA(_sender, _value);
            } 
           
            else if(action == 0x2){ 
                require(_value == 100*10**8);
                uint16 _city = uint16(_extraData[1]);
                 
                
                address[] memory checkPlayer;
                checkPlayer = checkBuildingPlayer(player_info[_sender].city,17);  
               
                if(checkPlayer.length != 0){
                    for(uint8 i=0;i<checkPlayer.length;i++){
                        require(ERC20_interface(arina_contract).transferFrom(_sender, checkPlayer[i], _value.div(checkPlayer.length)),"交易失敗");
                    } 
                }else{
                    require(ERC20_interface(arina_contract).transferFrom(_sender, trade_address, _value),"交易失敗");
                    trade(trade_address).set_city_pool(_value,player_info[_sender].city);
                }
                
                 
                change_city(_sender, _city);
                
            }
          
            else if(action == 0x3){ 
             
                uint8 _building = uint8(_extraData[1]);
                
                  
                uint build_value = inquire_type_price(_building);
        		
        		require(_value == build_value,"金額不對"); 
                 
                require(ERC20_interface(arina_contract).transferFrom(_sender, trade_address, _value),"交易失敗");
                trade(trade_address).set_city_pool(_value,player_info[_sender].city);
                
                _build(_sender, _building,_value);
            }
            else{revert();}
    
        }
        
    
    
        function set_all_stop(bool _stop) public onlymanager{
            all_stop = _stop;
        }
    
        function withdraw_all_ETH() public onlymanager{
            manager.transfer(address(this).balance);
        }
         
        function withdraw_all_arina() public onlymanager{
            uint asset = ERC20_interface(arina_contract).balanceOf(address(this));
            ERC20_interface(arina_contract).transfer(manager, asset);
        }
        
        function withdraw_ETH(uint _eth_wei) public onlymanager{
            manager.transfer(_eth_wei);
        }
        
        function withdraw_arina(uint _arina) public onlymanager{
            ERC20_interface(arina_contract).transfer(manager, _arina); 
        }
        
        function set_arina_address(address _arina_address) public onlymanager{
            arina_contract = _arina_address;
        }
      
        
        
        
        
        
        
        function set_slave_mayor(uint16 _index, address newMayor_address) public onlymanager{
            address contract_address = owner_slave[_index];
            slave(contract_address).transferMayorship(newMayor_address); 
        }
         
        function push_slave_address(address _address) external onlymanager{
            
            require(slave(_address).master_address() == address(this));
            owner_slave.push(_address);
            owner_slave_amount = owner_slave_amount.add(1); 
        } 
        
        function change_slave_address(uint16 _index, address _address) external onlymanager{
            owner_slave[_index] = _address; 
        }
        
        function set_building_type(uint8 _type, string _name) public onlymanager{
            building_type[_type] = _name;
        }
        
        function set_type_price(uint8 _type, uint _price) public onlymanager{
            building_price[_type] = _price;
        }
        
        function set_trade_address(address _trade_address) public onlymanager{ 
           trade_address = _trade_address;
        }
        
        function set_mix_address(address _mix_address) public onlymanager{ 
           mix_address = _mix_address;
        }
        
        function set_cooltime(uint16 _index, uint _cooltime) public onlymanager{
            address contract_address = owner_slave[_index];
            slave(contract_address).set_domain_cooltime(_cooltime); 
        }
        
    
    
        constructor() public{
            random_seed = uint((keccak256(abi.encodePacked(now))));
            
            owner_slave.push(address(0));
            
            area[1] = "魔幻魔法區";
            area[2] = "蒸氣龐克區";
            area[3] = "現代區";
            area[4] = "SCI-FI科幻未來區";
                    
            
            
            
            building_type[0] = "null" ; 
            building_type[1] = "Farm" ; 
            building_type[2] = "Mine" ; 
            building_type[3] = "Workshop" ; 
            building_type[4] = "Bazaar" ; 
            building_type[5] = "Arena" ;
            building_type[6] = "Adventurer's Guild" ; 
            building_type[7] = "Dungeon" ; 
            building_type[8] = "Lucky Fountain" ; 
            building_type[9] = "Stable" ; 
            building_type[10] = "Mega Tower" ; 
            
            building_type[11] = "Fuel station" ; 
            building_type[12] = "Research Lab" ; 
            building_type[13] = "Racecourse" ; 
            building_type[14] = "Airport" ; 
            building_type[15] = "Bank" ; 
            building_type[16] = "Department store" ; 
            building_type[17] = "Station" ;
            building_type[18] = "Hotel" ; 
            building_type[19] = "Shop" ; 
            building_type[20] = "Weapon factory" ; 
            
            
             
            
            building_price[0] = 0 ; 
            building_price[1] = 2000*10**8 ;
            building_price[2] = 2000*10**8 ;
            building_price[3] = 2000*10**8 ; 
            building_price[4] = 2000*10**8 ; 
            building_price[5] = 5000*10**8 ;
            building_price[6] = 5000*10**8 ;
            building_price[7] = 5000*10**8 ;
            building_price[8] = 5000*10**8 ;
            building_price[9] = 5000*10**8 ;
            building_price[10] = 5000*10**8 ; 
            
            building_price[11] = 2000*10**8 ; 
            building_price[12] = 10000*10**8 ;
            building_price[13] = 5000*10**8 ;
            building_price[14] = 20000*10**8 ; 
            building_price[15] = 10000*10**8 ; 
            building_price[16] = 5000*10**8 ;
            building_price[17] = 5000*10**8 ;
            building_price[18] = 5000*10**8 ;
            building_price[19] = 5000*10**8 ;
            building_price[20] = 5000*10**8 ;
        }
        
     }

    File 2 of 2: slave
    pragma solidity ^0.4.25;
    
    
    
    
    
      
    
    contract owned {
        address public master_address;
        address public mayor;
        address public contract_owner; 
        
     
        constructor() public{
            
            master_address = 0x0ac10bf0342fa2724e93d250751186ba5b659303; 
            mayor = msg.sender;
            contract_owner = msg.sender;
        }  
        modifier onlyMaster{ 
            require(msg.sender == master_address);
            _;
        }  
     
        modifier onlyowner{
            require(msg.sender == contract_owner);
            _;
        }
    
        function transferMastership(address new_master) public onlyowner {
            master_address = new_master;
        }
    
        function transferMayorship(address new_mayor) public onlyMaster {
            mayor = new_mayor;
        } 
        
        
        
        
    }
    
    interface IERC165 {
        function supportsInterface(bytes4 interfaceID) external view returns (bool);
    }
    
    interface IERC721Receiver {
        function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
    }
    
    contract ERC165 is IERC165 {
        bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    
        mapping(bytes4 => bool) private _supportedInterfaces;
    
        constructor () internal {
            _registerInterface(_INTERFACE_ID_ERC165);
        }
    
        function supportsInterface(bytes4 interfaceId) external view returns (bool) {
            return _supportedInterfaces[interfaceId];
        }
    
        function _registerInterface(bytes4 interfaceId) internal {
            require(interfaceId != 0xffffffff);
            _supportedInterfaces[interfaceId] = true;
        }
    }
    
     
    
    interface ERC20_interface {
      function balanceOf(address who) external view returns (uint256);
      function transfer(address to, uint256 value) external returns(bool);
    }
    
     interface treasure{
         function callTreasureMin(uint8 index, address target, uint mintedAmount) external;
         function callTreasureBurn(uint8 index, address target, uint burnedAmount) external;
     }
    
    
    
    contract ERC20 {
      uint256 public totalSupply;
      function balanceOf(address who) public view returns (uint256);
      function transfer(address to, uint256 value) public returns(bool);
    
      event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    library Address {
    
        function isContract(address account) internal view returns (bool) { 
            uint256 size;
            assembly { size := extcodesize(account) }
            return size > 0;
        }
    }
    
    library SafeMath{
    
         function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a);
    
            return c;
        }
    
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a);
            uint256 c = a - b;
            return c;
        }
    
         function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            if (a == 0) {
                return 0;
            }
            uint256 c = a * b;
            require(c / a == b);
            return c;
        }
    
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b > 0);
            uint256 c = a / b;
            return c;
        }
    
     }
     
     library SafeMath8{
         function add(uint8 a, uint8 b) internal pure returns (uint8) {
            uint8 c = a + b;
            require(c >= a);
    
            return c;
        }
    
        function sub(uint8 a, uint8 b) internal pure returns (uint8) {
            require(b <= a);
            uint8 c = a - b;
            return c;
        }
    
     }
     
     library SafeMath16{
         function add(uint16 a, uint16 b) internal pure returns (uint16) {
            uint16 c = a + b;
            require(c >= a);
    
            return c;
        }
    
        function sub(uint16 a, uint16 b) internal pure returns (uint16) {
            require(b <= a);
            uint16 c = a - b;
            return c;
        }
    
         function mul(uint16 a, uint16 b) internal pure returns (uint16) {
            if (a == 0) {
                return 0;
            }
            uint16 c = a * b;
            require(c / a == b);
            return c;
        }
    
        function div(uint16 a, uint16 b) internal pure returns (uint16) {
            require(b > 0);
            uint16 c = a / b;
            return c;
        }
     }
    
    
    contract ERC721{
    
         event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
         event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
         event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
    
         function balanceOf(address _owner) public view returns (uint256);
         function ownerOf(uint256 _tokenId) public view returns (address);
         function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) public payable;
         function safeTransferFrom(address _from, address _to, uint256 _tokenId) public payable;
         function transferFrom(address _from, address _to, uint256 _tokenId) public payable;
         function approve(address _approved, uint256 _tokenId) external payable;
         function setApprovalForAll(address _operator, bool _approved) external;
         function getApproved(uint256 _tokenId) public view returns (address);
         function isApprovedForAll(address _owner, address _operator) public view returns (bool);
     }
    
    contract external_function{
        function inquire_totdomains_amount() public view returns(uint16);
        
        
    
        function inquire_domain_level_star(uint16 _id) public view returns(uint8, uint8);
        function inquire_domain_building(uint16 _id, uint8 _index) public view returns(uint8);
        function inquire_domain_attribute(uint16 _id, uint8 _index) public view returns(uint8);
        function inquire_tot_domain_attribute(uint16 _id) public view returns(uint8[5]);
        function inquire_domain_cooltime(uint16 _id) public view returns(uint);
        function inquire_mayor_cooltime() public view returns(uint);
        function inquire_mayor_address() public view returns(address);
        function inquire_own_domain(address _sender) public view returns(uint16[]);
        
        function inquire_land_info(uint16  _city_number, uint16 _id) public pure returns(uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8);
        function inquire_building_limit(uint8 _building) public view returns(uint8);
      
        function domain_build(uint16 _id,  uint8 _building) external;
        function reconstruction(uint16 _id, uint8 _index, uint8 _building)external;
        function set_domian_attribute(uint16 _id, uint8 _index) external;
        function domain_all_reward(uint8 _class, address _user) external;
        function mayor_reward(address _user)external;
        
    
        function domain_reward(uint8 _class, address _user, uint16 _id) external;
        function transfer_master(address _to, uint16 _id) public;
        function retrieve_domain(uint16 _id) external;
        function set_domain_cooltime(uint cooltime) external;
    }
    
    interface master{
        function inquire_location(address _address) external view returns(uint16, uint16);
    }
    
    interface trade{
        function set_city_box_amount(uint16 _city, uint8 _index, uint _amount ) external;
    }
    
    
    
    contract slave is ERC165, ERC721, external_function, owned{
        
        event openBoxAmount(address indexed target, uint8 boxIndex, uint boxAmount); 
    
        constructor() public{
            
            _registerInterface(_InterfaceId_ERC721);
            
            random_seed = uint((keccak256(abi.encodePacked(now))));
         
        }    
                
        
          
        address public treasure_contract = 0x1570158e0ad7c5b95c69abe0ce4536f522a1cde6; 
        address public arina_contract = 0xe6987cd613dfda0995a95b3e6acbabececd41376;
        address trade_address = 0x167ee8dDfd7045090CDf8FF38864c6744Ef952d9;
        
           
        uint8 public area_number = 1;  
        uint8 public building_number = 20;
        uint16 public city_number = 1; 
                     
        uint random_seed;         
        uint mayorCooltime;    
                             
                  
        string name = "land1";   
        string symbol = "land1"; 
       
        using SafeMath for uint256; 
        using SafeMath16 for uint16;
        using SafeMath8 for uint8; 
        using Address for address;
    
        bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
        bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd;
    
    
        
        mapping (address => uint256) private owned_domain_amount;
    
        mapping (address => uint16[]) public owned_domain_id;
    
        
        mapping (address => mapping (address => bool)) private _operatorApprovals;
        mapping (uint8 => uint8) same_building_limit;
    
        struct domain{
            address owner; 
            address backup; 
     
            uint8 star; 
            uint8 level; 
            uint8[] building; 
            uint cooltime; 
            
            address approvals; 
            
            uint8[5] attribute; 
            
        }
    
     
        uint public every_cooltime = 86400;
    
     
        uint8 public building_amount = 4; 
        uint8 public building_type_amount = 20; 
        
     
    
        uint8 level_limit = 100; 
        uint8 star_limit = 5; 
    
        uint8 public domains_amount = 100; 
    
        domain[100] public citys; 
    
    
        function set_treasure_contract(address _treasure_contract) public onlyowner{
            treasure_contract = _treasure_contract;
        }
    
        function set_arina_contract(address _arina_contract) public onlyowner{
            arina_contract = _arina_contract;
        }
    
        function set_building_amount(uint8 _building_amount) public onlyowner{
            building_amount = _building_amount;
        }
    
        function set_building_type_amount(uint8 _building_type_amount) public onlyowner{
            building_type_amount = _building_type_amount;
        }
    
        function set_level_limit(uint8 _level_limit) public onlyowner{
            level_limit = _level_limit;
        }
    
        function set_star_limit(uint8 _star_limit) public onlyowner{
            star_limit = _star_limit;
        }
    
        function set_city_number(uint8 _city_number) public onlyowner{
            city_number = _city_number;
        }
    
        function set_area_number(uint8 _area_number) public onlyowner{
            area_number = _area_number;
        }
         
        function set_trade_address(address _trade_address) public onlyowner{ 
           trade_address = _trade_address;
        } 
        
    
        function withdraw_all_ETH() public onlyowner{
            contract_owner.transfer(address(this).balance);
        }
    
        
        
        
        
    
        function withdraw_ETH(uint _eth_wei) public onlyowner{
            contract_owner.transfer(_eth_wei);
        }
    
        
        
        
    
    
    
        
        function inquire_own_domain(address _sender) public view returns(uint16[]){
            uint16[] memory _own_domains = new uint16[](citys.length);
    
            uint16 counter = 0;
            for (uint16 i = 0; i < citys.length; i++) {
    
                if (citys[i].owner == _sender) {
                    _own_domains[counter] = i;
                    counter = counter.add(1);
                }
            }
    
            uint16[] memory own_domains = new uint16[](counter);
    
            for (uint16 j = 0; j < counter; j++) {
                own_domains[j] = _own_domains[j];
            }
    
            return own_domains;
        }
    
        function inquire_domain_level(uint16 _id) public view returns(uint8){
            if(citys[_id].level <= level_limit){
                return citys[_id].level;
            }
            else
                return 0;
        }
    
        function inquire_domain_star(uint16 _id) public view returns(uint8){
            return citys[_id].star;
        }
        
    
        function inquire_domain_level_star(uint16 _id) public view returns(uint8, uint8){
            uint8 _level;
            if(citys[_id].level <= level_limit){
                _level = citys[_id].level;
            }
            else {
                _level = 0 ;
            }
            return (_level, citys[_id].star);
        }
    
        function inquire_domain_building(uint16 _id, uint8 _index) public view returns(uint8){
            return citys[_id].building[_index];
        }
    
    
        function inquire_tot_domain_building(uint16 _id) public view returns(uint8[]){
            return citys[_id].building;
        }
    
        function inquire_domain_cooltime(uint16 _id) public view returns(uint){
            return citys[_id].cooltime;
        } 
        
        function inquire_mayor_address() public view returns(address){
            return mayor;
        }
        
        function inquire_mayor_cooltime() public view returns(uint){
            return mayorCooltime;
        }
     
    
        function inquire_totdomains_amount() public view returns(uint16){
          return uint16(citys.length);
        }
        
        function inquire_domain_attribute(uint16 _id, uint8 _index) public view returns(uint8){
            return citys[_id].attribute[_index];
        }
        
        function inquire_tot_domain_attribute(uint16 _id) public view returns(uint8[5]){
            return citys[_id].attribute;
        }
        
        function inquire_building_limit(uint8 _building) public view returns(uint8){
            return same_building_limit[_building];
        }
        
      
    
    
    
        function() payable public{
        }
    
        function domain_build(uint16 _id,  uint8 _building) external onlyMaster{
            require(citys[_id].building.length < building_amount,"不能超出可建設區塊數");
            
            require(_building != 0, "不能蓋空地");
            require(_building <= building_type_amount,"不能超出可建設種類"); 
            
            if(isBuilded(_id,_building)){
     
                if(_building == 14){
                    require(same_building_limit[14] < building_number);
                    same_building_limit[14] = same_building_limit[14].add(1);
                }else if(_building == 15){
                    require(same_building_limit[15] < building_number);
                    same_building_limit[15] = same_building_limit[15].add(1);
                }else if(_building == 17){
                    require(same_building_limit[17] < building_number);
                    same_building_limit[17] = same_building_limit[17].add(1);
                }   
                    
                citys[_id].building.push(_building);
            }
    
            if(citys[_id].star < star_limit){ 
                citys[_id].star = citys[_id].star.add(1);
            }
        }
    
        function reconstruction(uint16 _id, uint8 _index, uint8 _building)
        external onlyMaster{
    
            require(_index < building_amount); 
            require(_building != 0); 
            require(_building <= building_type_amount); 
    
            require(citys[_id].building[_index] != 0); 
            uint8 old_building = citys[_id].building[_index];
            if(isBuilded(_id,_building)){
                
                 
                 
                if(_building == 14){
                    require(same_building_limit[14] < building_number);
                    same_building_limit[14] = same_building_limit[14].add(1);
                }else if(_building == 15){
                    require(same_building_limit[15] < building_number);
                    same_building_limit[15] = same_building_limit[15].add(1);
                }else if(_building == 17){
                    require(same_building_limit[17] < building_number);
                    same_building_limit[17] = same_building_limit[17].add(1);
                } 
                
                citys[_id].building[_index] = _building;
                
                if(old_building == 14){
                    same_building_limit[14] = same_building_limit[14].sub(1);
                }else if(old_building == 15){
                    same_building_limit[15] = same_building_limit[15].sub(1);
                }else if(old_building == 17){
                    same_building_limit[17] = same_building_limit[17].sub(1);
                }
             
            }
     
        }
        
        function set_domian_attribute(uint16 _id, uint8 _index) external onlyMaster{  
             
            uint8 produce;
             
            if(_index == 0){
                (produce,,,,,,,,,) =inquire_land_info(city_number,_id);
                 
            }else if(_index == 1){ 
                (,produce,,,,,,,,) =inquire_land_info(city_number,_id);
            }else if(_index == 2){
                (,,produce,,,,,,,) =inquire_land_info(city_number,_id);
            }else if(_index == 3){
                (,,,produce,,,,,,) =inquire_land_info(city_number,_id);
            }else{
                (,,,,produce,,,,,) =inquire_land_info(city_number,_id);
            } 
            
            require((citys[_id].attribute[_index] + produce) < 10);
             
              
            citys[_id].attribute[_index] = citys[_id].attribute[_index].add(1);
        }
        
        function isBuilded(uint16 _id,  uint8 _building) public view returns(bool){ 
            
            uint8 produce01;
            uint8 produce02;
            uint8 produce03; 
            uint8 produce04;
            uint8 produce05;
            uint8 produce07;
            uint8 produce08;
            uint8 produce09;
            
            (produce01,produce02,produce03,produce04,produce05,,produce07,produce08,produce09,) = inquire_land_info(city_number,_id);
            
            produce01 = produce01.add(citys[_id].attribute[0]); 
            produce02 = produce02.add(citys[_id].attribute[1]);
            produce03 = produce03.add(citys[_id].attribute[2]);
            produce04 = produce04.add(citys[_id].attribute[3]);
            produce05 = produce05.add(citys[_id].attribute[4]);
    
      
            if(_building == 1){
                require(produce01 > 6 && produce09 > 4 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 2){
                require(produce02 > 6 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 3 ){
               require(produce05 > 6 && checkBuild(_id,_building),"土地特性需求不滿足條件");
               return true;
            }else if(_building == 4 ){
                require(produce07 > 7 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 5 || _building == 7){
                require(produce08 < 3 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true; 
            }else if(_building == 6 ){
                require(produce07 > 3 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 8 ){
                require(produce08 > 7 && produce09 > 4 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 9 ){
                require(produce01 > 4 && produce09 > 4 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 10 ){
                require(produce03 > 6 && produce07 < 3 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 11 ){
                require(produce04 > 6 && produce03 < 3 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else if(_building == 15 || _building == 16 || _building == 18){
                require(produce07 > 7 && produce08 > 7 && checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }else{
                require(checkBuild(_id,_building),"土地特性需求不滿足條件");
                return true;
            }
        }
        
        function checkBuild(uint16 _id,  uint8 _building) public view returns(bool){     
            bool same = true;                                                            
             for(uint m=0;m<citys[_id].building.length;m++){
                if(citys[_id].building[m] == _building){
                    same = false;                                                        
                    return same;
                }   
            }
            return same;
        }
            
    
    
        function domain_reward(uint8 _class, address _user, uint16 _id) external onlyMaster{
            
            uint8 star = inquire_domain_star(_id);
            uint8 treasure_level = _treasure_level(star,_id);
           
            
            uint amount = 1;
            uint8 index = _class*5+treasure_level-1;
            
            if(citys[_id].owner == _user){                                          
                require(citys[_id].cooltime <= now);
                treasure(treasure_contract).callTreasureMin(index, _user , amount);
                citys[_id].cooltime = now.add(every_cooltime);
                emit openBoxAmount(_user,index,amount);
            }else{                                                                  
                for(uint n=0;n<citys[_id].building.length;n++){
                    if(_class == 0 && citys[_id].building[n] == 1){
                        amount++;
                        break;
                    }else if(_class == 1 && citys[_id].building[n] == 2){
                        amount++;
                        break;
                    }else if(_class == 2 && citys[_id].building[n] == 10){
                        amount++;
                        break;
                    }else if(_class == 3 && citys[_id].building[n] == 11){
                        amount++;
                        break;
                    }else if(_class == 4 && citys[_id].building[n] == 3){
                        amount++;
                        break;
                    }
                } 
                
                
                if(amount==2){        
                    treasure(treasure_contract).callTreasureMin(index, _user , amount);
                    treasure(treasure_contract).callTreasureMin(index, citys[_id].owner , 1);
                    emit openBoxAmount(_user,index,amount); 
                     
                }else{
                    treasure(treasure_contract).callTreasureMin(index, _user , amount);
                    emit openBoxAmount(_user,index,amount);  
                }
    
            }
    
        }
      
        
        function domain_all_reward(uint8 _class, address _user) external onlyMaster{
            uint16[] memory domains ;
            domains = inquire_own_domain(_user);            
            
            uint[] memory amounts = new uint[](5);  
            uint8[] memory boxIndex = new uint8[](5);
            uint8 star;
            uint8 treasure_level;
            uint8 index;
            uint8 newIndex;
            
          
            if(domains.length!=0){
                for(uint16 i = 0 ; i<domains.length;i++){
                     if(citys[domains[i]].owner == _user && citys[domains[i]].cooltime <= now){
                        
                        star = inquire_domain_star(domains[i]);
                        treasure_level = _treasure_level(star,domains[i]);
                        
                        index = _class*5+treasure_level-1; 
                        newIndex = index - (_class*5);
                        boxIndex[newIndex]=index;
                        amounts[newIndex] = amounts[newIndex].add(1);
                     
                        citys[domains[i]].cooltime = now.add(every_cooltime);
                         
                     }
                }
                
                for(uint8 m = 0 ; m < amounts.length; m++ ){
                    if(amounts[m]!=0){
                         treasure(treasure_contract).callTreasureMin(boxIndex[m], _user , amounts[m]);
                         emit openBoxAmount(_user,boxIndex[m],amounts[m]);                 
                    } 
                }
            }
      
        }
        
        
        
         function mayor_reward(address _user) external onlyMaster {
            require(_user == mayor); 
            require(mayorCooltime <= now);
            
            uint8 _class;
        
            uint[] memory amounts = new uint[](30);
            uint8[] memory boxIndex = new uint8[](30);
            uint8 star;
            uint8 treasure_level;
            uint8 index;
            
             
            for(uint16 k=0 ; k < citys.length ; k++){     
         
                  star = inquire_domain_star(k);
                  treasure_level = _treasure_level(star,k);
                  
                  _class = uint8(keccak256(abi.encodePacked(now + uint(k),blockhash(block.number-1))))%6; 
                  index = _class*5+treasure_level-1;
                
                  
                  boxIndex[index]=index;
                  amounts[index] = amounts[index].add(1);
              
            }
              
            for(uint8 m = 0 ; m < amounts.length; m++ ){
                if(amounts[m]!=0){
                     treasure(treasure_contract).callTreasureMin(boxIndex[m], trade_address , amounts[m]);
                     emit openBoxAmount(_user,boxIndex[m],amounts[m]);                 
                     trade(trade_address).set_city_box_amount(city_number, boxIndex[m], amounts[m]) ;
                } 
            }
    
            mayorCooltime = now.add(every_cooltime);
            
         }
     
        
        function inquire_land_info(uint16  _city_number, uint16 _id) public pure returns(uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8){
          require(0 < _city_number);
          
          bytes32 _result = keccak256(abi.encodePacked(_id,_city_number));
    
            if(_city_number<5){
                return (uint8(_result[0] ) % 5 + 2,
                        uint8(_result[1] ) % 5 + 1,
                        uint8(_result[2] ) % 5,
                        uint8(_result[3] ) % 5 + 3,
                        uint8(_result[4] ) % 9 + 2,
                        uint8(_result[5] ) % 8 + 1,
                        uint8(_result[6] ) % 8 + 3,
                        uint8(_result[7] ) % 5 + 4,
                        uint8(_result[8] ) % 6 + 3,
                        uint8(_result[9] ) % 7 + 2);
            }else if(_city_number<9){
                return (uint8(_result[0] ) % 5 + 1,
                        uint8(_result[1] ) % 5 + 6,
                        uint8(_result[2] ) % 6 + 1,
                        uint8(_result[3] ) % 4 + 2,
                        uint8(_result[4] ) % 6 ,
                        uint8(_result[5] ) % 6,
                        uint8(_result[6] ) % 5 + 2,
                        uint8(_result[7] ) % 9,
                        uint8(_result[8] ) % 5,
                        uint8(_result[9] ) % 6 + 5);
            }else if(_city_number<13){
                return (uint8(_result[0] ) % 6 + 5,
                        uint8(_result[1] ) % 4,
                        uint8(_result[2] ) % 5 + 6,
                        uint8(_result[3] ) % 3,
                        uint8(_result[4] ) % 5 + 3 ,
                        uint8(_result[5] ) % 5 + 6,
                        uint8(_result[6] ) % 4,
                        uint8(_result[7] ) % 11,
                        uint8(_result[8] ) % 6 + 5,
                        uint8(_result[9] ) % 7);
            }else{
                return (uint8(_result[0] ) % 3,
                        uint8(_result[1] ) % 5 + 4,
                        uint8(_result[2] ) % 2,
                        uint8(_result[3] ) % 6 + 5,
                        uint8(_result[4] ) % 7 + 2 ,
                        uint8(_result[5] ) % 5 + 1,
                        uint8(_result[6] ) % 4 + 7,
                        uint8(_result[7] ) % 7,
                        uint8(_result[8] ) % 5 + 2,
                        uint8(_result[9] ) % 8);
            }
    
        }
        
    
        function _treasure_level(uint8 _star,uint16 _id) view private returns(uint8){
            
            
            uint random = uint((keccak256(abi.encodePacked(now, random_seed.add(_id)))));
    
            uint ItemLv2_Deno = 20;
            uint ItemLv3_Deno = 80; 
            uint ItemLv4_Deno = 320;
            uint ItemLv5_Deno = 1280;  
    
            uint Item_numerator = 2**(uint(_star) - 1);
    
    	    uint ItemLv2_Random =  (random % ItemLv2_Deno).add(1);
        	uint ItemLv3_Random =  (random % ItemLv3_Deno).add(1);
        	uint ItemLv4_Random =  (random % ItemLv4_Deno).add(1);
        	uint ItemLv5_Random =  (random % ItemLv5_Deno).add(1);
    
            if(Item_numerator >= ItemLv5_Random){
                return 5;
            }
            else if(Item_numerator >= ItemLv4_Random){
                return 4;
            }
            else if(Item_numerator >= ItemLv3_Random){
                return 3;
            }
            else if(Item_numerator >= ItemLv2_Random){
                return 2;
            }
            else {
                return 1;
            }
        }
    
        
        function transfer_master(address _to, uint16 _id) public onlyMaster{
            require(_to != address(0));
    
            address domain_owner = citys[_id].owner;
    
            if (domain_owner != 0x0){
                owned_domain_amount[domain_owner] = owned_domain_amount[domain_owner].sub(1);
            }
    
            if(citys[_id].star == 0){
                citys[_id].star = citys[_id].star.add(1); 
            }
    
            owned_domain_amount[_to] = owned_domain_amount[_to].add(1);
            owned_domain_id[_to].push(_id);
            citys[_id].owner = _to;
            if(citys[_id].level < level_limit){
                citys[_id].level = citys[_id].level.add(1);
            }
    
            
        }
    
        function retrieve_domain(uint16 _id) external onlyMaster{
            require(msg.sender == citys[_id].backup);
            transfer_master(contract_owner, _id);
            emit Transfer(citys[_id].owner, contract_owner, _id);
        }
        
        function set_domain_cooltime(uint _cooltime) external onlyMaster{
            every_cooltime = _cooltime;
        }
         
        function set_building_number(uint8 _building_number) public onlyMaster{
            building_number = _building_number;
        }
    
    
    
        function balanceOf(address _owner) public view returns (uint256){
            require(_owner != address(0));
            return owned_domain_amount[_owner];
        }
        function ownerOf(uint256 _tokenId) public view returns (address){
            address owner = citys[_tokenId].owner;
            return owner;
        }
        function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data) public payable{
            transferFrom(_from, _to, _tokenId);
            require(_checkOnERC721Received(_from, _to, _tokenId, _data));
        }
        function safeTransferFrom(address _from, address _to, uint256 _tokenId) public payable{
            safeTransferFrom(_from, _to, _tokenId, "");
        }
        function transferFrom(address _from, address _to, uint256 _tokenId) public payable{
            require(_isApprovedOrOwner(msg.sender, _tokenId));
            _transferFrom(_from, _to, _tokenId);
        }
        function approve(address _approved, uint256 _tokenId) external payable{
            address owner = ownerOf(_tokenId);
            require(_approved != owner);
            require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
    
            citys[_tokenId].approvals = _approved;
            emit Approval(owner, _approved, _tokenId);
        }
        function setApprovalForAll(address _operator, bool _approved) external{
            require(_operator != msg.sender);
            _operatorApprovals[msg.sender][_operator] = _approved;
            emit ApprovalForAll(msg.sender, _operator, _approved);
        }
        function getApproved(uint256 _tokenId) public view returns (address){
            require(_exists(_tokenId));
            return citys[_tokenId].approvals;
        }
        function isApprovedForAll(address _owner, address _operator) public view returns (bool){
            return _operatorApprovals[_owner][_operator];
        }
    
        function _exists(uint256 _tokenId) internal view returns (bool) {
            address owner = citys[_tokenId].owner;
            return owner != address(0);
        }
    
        function _isApprovedOrOwner(address _spender, uint256 _tokenId) internal view returns (bool) {
            address owner = ownerOf(_tokenId);
            return (_spender == owner || getApproved(_tokenId) == _spender || isApprovedForAll(owner, _spender));
        }
    
        function _transferFrom(address _from, address _to, uint256 _tokenId) internal {
            require(ownerOf(_tokenId) == _from);
            require(_to != address(0));
    
            _clearApproval(_tokenId);
    
            owned_domain_amount[_from] = owned_domain_amount[_from].sub(1);
            owned_domain_amount[_to] = owned_domain_amount[_to].add(1);
    
            citys[_tokenId].owner = _to;
    
            emit Transfer(_from, _to, _tokenId);
        }
    
        function _checkOnERC721Received(address _from, address _to, uint256 _tokenId, bytes memory _data)
            internal returns (bool)
        {
            if (!_to.isContract()) {
                return true;
            }
    
            bytes4 retval = IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
            return (retval == _ERC721_RECEIVED);
        }
    
        function _clearApproval(uint256 _tokenId) private {
            if (citys[_tokenId].approvals != address(0)) {
                citys[_tokenId].approvals = address(0);
            }
        }
    
    
    }