CryptoKitties

pragma solidity ^0.6.2;

contract CryptoKitties{
 
    mapping(uint256 => address payable) public kittyIndexToOwner;    // 猫咪拥有者
    mapping(uint256 => Kitty) public tokenToKitty;  // token对应的猫咪
    uint32 index;  //  猫咪数量
    NFT nft;
 
    struct Kitty{
        uint32 genes;  // 256位的整数,代表猫的遗传因子。这个数值将决定猫的外表
        uint64 birthTime;   // 这只猫诞生时的区块时间
        uint64 cooldownEndBlock;    // 这只猫下一次可以进行繁殖的最快时间
        uint32 matronId;    //   这只猫的母亲ID
        uint32 sireId;      //  这只猫的父亲ID
        uint32 siringWithId;    // 如果这只猫现在作为母猫怀孕中,将会被设置为其对应父猫的ID,否则为0
        uint16 cooldownIndex;   // 这只猫在每一次繁殖后需要多久才能再一次进行繁殖
        uint16 generation;  // 这只猫的世代。初期通过购买蛋得到的猫为世代0,其余的猫的世代为其父母的最大世代+1
    }
    
    constructor(address _nftContractAddress) public{
        nft = NFT(_nftContractAddress);
        for(uint256 i=1; i<100; i++){
            create(0);
        }
    }
    
    // 打入ETH生产1代猫
    function productKitty() public payable{
         require(msg.value == 1 ether,"product payable eth is not nought");
         create(1);
    }
    
    // 繁殖
    function reproduction(uint256 _matronId,uint256 _sireId) public payable{
        Kitty memory matronKitty = tokenToKitty[_matronId];    
        require(kittyIndexToOwner[matronKitty.genes] == msg.sender,"matron have to be their own");  // 繁殖时母系必须是自己的
        require(matronKitty.siringWithId == 0 || (matronKitty.siringWithId>0 && matronKitty.cooldownEndBlock <= block.number),"this matron already pregnant");  // 不在孕期
        Kitty memory sireKitty = tokenToKitty[_sireId];
        if(kittyIndexToOwner[sireKitty.genes] == msg.sender){  // 如果繁殖时父系不是自己的,那么需要支付一笔eth费用给对方
            require(msg.value == 0.1 ether,"reproduction payable value is not nought");
            kittyIndexToOwner[sireKitty.genes].transfer(msg.value);
        }
        _reproduction(matronKitty,sireKitty);   // 繁殖
        matronKitty.siringWithId = sireKitty.genes;     // 设置母系繁殖状态
        matronKitty.cooldownEndBlock = uint64(block.number + matronKitty.cooldownIndex); // 设置母系下一次可繁殖时间
        tokenToKitty[_matronId] = matronKitty; //  更新母系状态
    }
    
    function _reproduction(Kitty memory _matronKitty,Kitty memory _sireKitty) private{
        index += 1;
        Kitty memory kitty = Kitty({
        genes: index,
        birthTime: uint64(now),
        cooldownEndBlock: 0,
        matronId: _matronKitty.matronId,
        sireId: _sireKitty.sireId,
        siringWithId: 0,
        cooldownIndex: uint16(7 * 86400),
        generation: _matronKitty.generation + 1
        });
        kittyIndexToOwner[index] = msg.sender;
        bool success = nft.mint();
        require(success,"create is fail");
        uint256 tokenId = nft.maxTokenId();
        tokenToKitty[tokenId] = kitty;
    }
    
    // 生产0代创世猫咪
    function create(uint16 _generation) private{
        index += index;
        Kitty memory kitty = Kitty({
        genes: index,
        birthTime: uint64(now),
        cooldownEndBlock: 0,
        matronId: uint32(0),
        sireId: uint32(0),
        siringWithId: 0,
        cooldownIndex: uint16(7 * 86400),
        generation: _generation
        });
        kittyIndexToOwner[index] = msg.sender;
        bool success = nft.mint();
        require(success,"create is fail");
        uint256 tokenId = nft.maxTokenId();
        tokenToKitty[tokenId] = kitty;
    }
    
}

interface NFT{
    // 查询token的拥有者
    function ownerOf(uint256 _tokenId) external view returns (address);
    // 授权
    function approve(address _to,uint256 _tokenId) external;
    // token代理人提币
    function takeOwnership(uint256 _tokenId) external;
    // 转账 
    function transfer(address _to, uint256 _tokenId) external;
    // 铸币
    function mint() external returns(bool);
    // 查看最新铸出来的token ID
    function maxTokenId() external view returns(uint256);
}

你可能感兴趣的:(CryptoKitties)