contract MonsterOwnership is MonstersBase, ERC721 {
    function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return monsterIndexToOwner[_tokenId] == _claimant;
    }

    function _isTradeable(uint256 _tokenId) public view returns (bool) {
        return monsterIdToTradeable[_tokenId];
    }

    /// @dev Checks if a given address currently has transferApproval for a particular monster.
    /// @param _claimant the address we are confirming monster is approved for.
    /// @param _tokenId monster id, only valid when > 0
    function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return monsterIndexToApproved[_tokenId] == _claimant;
    }

    function balanceOf(address _owner) public view returns (uint256 count) {
        return ownershipTokenCount[_owner];
    }

    function transfer(address _to, uint256 _tokenId) public payable {
        transferFrom(msg.sender, _to, _tokenId);
    }

    function transferFrom(address _from, address _to, uint256 _tokenId) public payable {
        require(monsterIdToTradeable[_tokenId]);
        // Safety check to prevent against an unexpected 0x0 default.
        require(_to != address(0));
        // Disallow transfers to this contract to prevent accidental misuse.
        // The contract should never own any monsters (except very briefly
        // after a gen0 monster is created and before it goes on auction).
        require(_to != address(this));
        // Check for approval and valid ownership
        
        require(_owns(_from, _tokenId));
        // checks if _to was aproved
        require(_from == msg.sender || msg.sender == address(monsterAuction) || _approvedFor(_to, _tokenId));

        // Reassign ownership (also clears pending approvals and emits Transfer event).
        _transfer(_from, _to, _tokenId);
    }

    function totalSupply() public view returns (uint) {
        return monsters.length;
    }

    function tokensOfOwner(address _owner) public view returns (uint256[] ownerTokens) {
        uint256 tokenCount = balanceOf(_owner);

        if (tokenCount > 0) {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 totalMonsters = totalSupply();
            uint256 resultIndex = 0;

            uint256 monsterId;

            for (monsterId = 0; monsterId <= totalMonsters; monsterId++) {
                if (monsterIndexToOwner[monsterId] == _owner) {
                    result[resultIndex] = monsterId;
                    resultIndex++;
                }
            }

            return result;
        }

        return new uint256[](0);
    }

    bytes4 internal constant INTERFACE_SIGNATURE_ERC165 =
        bytes4(keccak256("supportsInterface(bytes4)"));

    bytes4 internal constant INTERFACE_SIGNATURE_ERC721 =
        bytes4(keccak256("ownerOf(uint256)")) ^
        bytes4(keccak256("countOfDeeds()")) ^
        bytes4(keccak256("countOfDeedsByOwner(address)")) ^
        bytes4(keccak256("deedOfOwnerByIndex(address,uint256)")) ^
        bytes4(keccak256("approve(address,uint256)")) ^
        bytes4(keccak256("takeOwnership(uint256)"));

    function supportsInterface(bytes4 _interfaceID) external pure returns (bool) {
        return _interfaceID == INTERFACE_SIGNATURE_ERC165 || _interfaceID == INTERFACE_SIGNATURE_ERC721;
    }

    function ownerOf(uint256 _deedId) external view returns (address _owner) {
        var owner = monsterIndexToOwner[_deedId];
        require(owner != address(0));
        return owner;
    }

    function _approve(uint256 _tokenId, address _approved) internal {
        monsterIndexToApproved[_tokenId] = _approved;
    }

    function countOfDeeds() external view returns (uint256 _count) {
        return totalSupply();
    }

    function countOfDeedsByOwner(address _owner) external view returns (uint256 _count) {
        var arr = tokensOfOwner(_owner);
        return arr.length;
    }

    function deedOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 _deedId) {
        return tokensOfOwner(_owner)[_index];
    }

    function approve(address _to, uint256 _tokenId) external payable {
        // Only an owner can grant transfer approval.
        require(_owns(msg.sender, _tokenId));

        // Register the approval (replacing any previous approval).
        monsterIndexToApproved[_tokenId] = _to;

        // Emit approval event.
        Approval(msg.sender, _to, _tokenId);
    }

    function takeOwnership(uint256 _deedId) external payable {
        transferFrom(this.ownerOf(_deedId), msg.sender, _deedId);
    }
}
function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) {
    return monsterIndexToApproved[_tokenId] == _claimant;
}

/// @dev Checks if a given address currently has transferApproval for a particular monster.
/// @param _claimant the address we are confirming monster is approved for.
/// @param _tokenId monster id, only valid when > 0