contract PetBase is PopulationControl{
    
    // events
    event Birth(address owner, uint64 petId, uint16 quality, uint256 genes);
    event Death(uint64 petId);
    
    event Transfer(address from, address to, uint256 tokenId);
    
    // data storage
    struct Pet {
        uint256 genes;
        uint64 birthTime;
        uint16 quality;
    }
    
    mapping (uint64 => Pet) pets;
    mapping (uint64 => address) petIndexToOwner;
    mapping (address => uint256) public ownershipTokenCount;
    mapping (uint64 => uint64) breedTimeouts;
 
    uint64 tokensCount;
    uint64 lastTokenId;

    // pet creation
    function createPet(
        uint256 _genes,
        uint16 _quality,
        address _owner
    )
        internal
        returns (uint64)
    {
        Pet memory _pet = Pet({
            genes: _genes,
            birthTime: uint64(now),
            quality: _quality
        });
               
        lastTokenId++;
        tokensCount++;
		
        uint64 newPetId = lastTokenId;
                
        pets[newPetId] = _pet;
        
        _transfer(0, _owner, newPetId);
        
        breedTimeouts[newPetId] = uint64( now + (breedTimeout / 2) );
        emit Birth(_owner, newPetId, _quality, _genes);

        return newPetId;
    }
    
    // transfer pet function
    function _transfer(address _from, address _to, uint256 _tokenId) internal {
        uint64 _tokenId64bit = uint64(_tokenId);
        
        ownershipTokenCount[_to]++;
        petIndexToOwner[_tokenId64bit] = _to;
        if (_from != address(0)) {
            ownershipTokenCount[_from]--;
        }
        
         emit Transfer(_from, _to, _tokenId);
    }
    
	// calculation of recommended price
    function recommendedPrice(uint16 quality) public pure returns(uint256 price) {
        
        require(quality <= uint16(0xF000));
        require(quality >= uint16(0x1000));
        
        uint256 startPrice = 1000;
        
        price = startPrice;
        
        uint256 revertQuality = uint16(0xF000) - quality;
        uint256 oneLevel = uint16(0x2000);
        uint256 oneQuart = oneLevel/4;
        
        uint256 fullLevels = revertQuality/oneLevel;
        uint256 fullQuarts =  (revertQuality % oneLevel) / oneQuart ;
        
        uint256 surplus = revertQuality - (fullLevels*oneLevel) - (fullQuarts*oneQuart);
        
        
        // coefficeint is 4.4 per level
        price = price * 44**fullLevels;
        price = price / 10**fullLevels;
        
        // quart coefficient is sqrt(sqrt(4.4))
        if(fullQuarts != 0)
        {
            price = price * 14483154**fullQuarts;
            price = price / 10**(7 * fullQuarts);
        }

        // for surplus we using next quart coefficient
        if(surplus != 0)
        {
            uint256 nextQuartPrice = (price * 14483154) / 10**7;
            uint256 surPlusCoefficient = surplus * 10**6  /oneQuart;
            uint256 surPlusPrice = ((nextQuartPrice - price) * surPlusCoefficient) / 10**6;
            
            price+= surPlusPrice;
        }
        
        price*= 50 szabo;
    }
    
	// grade calculation based on parrot quality
    function getGradeByQuailty(uint16 quality) public pure returns (uint8 grade) {
        
        require(quality <= uint16(0xF000));
        require(quality >= uint16(0x1000));
        
        if(quality == uint16(0xF000))
            return 7;
        
        quality+= uint16(0x1000);
        
        return uint8 ( quality / uint16(0x2000) );
    }
}
// Pet base contract
function createPet(
    uint256 _genes,
    uint16 _quality,
    address _owner
)
    internal
    returns (uint64)
{
    Pet memory _pet = Pet({
        genes: _genes,
        birthTime: uint64(now),
        quality: _quality
    });
               
    lastTokenId++;
    tokensCount++;
		
    uint64 newPetId = lastTokenId;
                
    pets[newPetId] = _pet;
        
    _transfer(0, _owner, newPetId);
        
    breedTimeouts[newPetId] = uint64( now + (breedTimeout / 2) );
    emit Birth(_owner, newPetId, _quality, _genes);

    return newPetId;
}

// pet creation