function breed(uint _momId, uint _dadId) public returns(uint newKittyId) {
require(tokenOwner[_momId] == msg.sender && tokenOwner[_dadId] == msg.sender, "Should own both kitties before breeding.");
uint newDna = _mixDna(kitties[_momId].dna, kitties[_dadId].dna);
uint newGen = _calcGen(kitties[_momId].generation, kitties[_dadId].generation);
newKittyId = _createKitty(_momId, _dadId, newGen, newDna, msg.sender);
}
function _mixDna(uint _momDna, uint _dadDna) internal pure returns(uint newDna) {
uint newDnaFirstHalf = _momDna / 100000000;
uint newDnaSecondHalf = _dadDna % 100000000;
newDna = newDnaFirstHalf * 100000000;
newDna = newDna + newDnaSecondHalf;
}
function _calcGen(uint _momGen, uint _dadGen) internal pure returns(uint newGen) {
if (_momGen <= _dadGen) {
newGen = _dadGen + 1;
}
else {
newGen = _momGen + 1;
}
}
1 Like
breed function
function breed(uint256 _dadId, uint256 _momId) public returns (uint256) {
//check ownership
//figure out the generation of the fish
//create a new fish with new dna, give it to msg.sender
require(msg.sender == ownerToken[_dadId] && msg.sender == ownerToken[_momId],
"You must own both the sire and mother to breed");
uint256 _dadGen = fishies[_dadId].generation;
uint256 _momGen = fishies[_momId].generation;
uint256 _childGen = 0;
if(_dadGen == _momGen && _dadGen < 1) {
_childGen = 1;
}
else {
if(_dadGen > _momGen) {
_childGen = _dadGen + 1;
}
else {
_childGen = _momGen + 1;
}
}
uint256 _dadGenes = fishies[_dadId].genes;
uint256 _momGenes = fishies[_momId].genes;
uint256 newDna = _mixDna(_dadGenes, _momGenes);
return _createFishy(_momId, _dadId, _childGen, newDna, msg.sender);
}
_mixDna function
function _mixDna(uint256 _dadDna, uint256 _momDna) internal pure returns (uint256) {
//dadDna: 11 22 33 44 55 66 77 88
//momDna: 88 77 66 55 44 33 22 11
uint256 _firstDadHalf = (_dadDna / 100000000); //11223344
uint256 _secondMomHalf = (_momDna % 100000000); //44332211
uint256 _babyDna = ((_firstDadHalf * 100000000) + _secondMomHalf);
return _babyDna;
/* NOTE - An advanced mixing option would have the ability to evaluate
each 2-digit section, and determine which parent to utilize for that
section of child dna */
//Have a loop that iterates to pull each section
//Use a 'random' function to do a "coin-flip" and pick a parent dna section
//With each section assigned, run another loop which brings all the sections together
}
Regarding the generation of the Kitty. I added an additional constraint that only same generation of kitty can breed.
Code:
function breedKitty(uint256 _dadId, uint256 _momId) public returns (uint256) {
require(_exists[_dadId] && _exists[_momId], "NFT does not exists!");
require(owners[_dadId] == msg.sender && owners[_momId] == msg.sender, "NFT does not belong to the address!");
require(kitties[_dadId].generation == kitties[_momId].generation, "Generation must match to breed!");
uint256 newDna = _mixDna(kitties[_dadId].dna, kitties[_momDna].dna);
uint256 gen = kitties[_dadId].generation.add(1);
return _createKitty(newDna, _momId, _dadId, gen, msg.sender);
}
function _mixDna(uint256 _dadDna, uint256 _momDna) public return (uint256) {
uint256 dadPart = _dadDna/10**8;
uint256 momPart = _momDna % 10**8;
uint256 newDna = dadPart * 10**8;
newDna = newDna + momPart;
return newDna;
}
2 Likes
Hi, this is my solution:
function breed(uint256 mumId_, uint256 dadId_)
external
returns (uint256 _newKittenId)
{
(, , , , uint256 _dadGeneration, uint256 _dadDNA, ) = getKitty(dadId_);
(, , , , uint256 _mumGeneration, uint256 _mumDNA, ) = getKitty(mumId_);
require(
(_owns(msg.sender, dadId_) && _owns(msg.sender, mumId_)),
"Kitties: Only owner of both parent kitties can use this function to breed new kitties"
);
uint256 _newKittyGene = _mixDNA(_dadDNA, _mumDNA);
uint256 _generation = _dadGeneration < _mumGeneration
? _mumGeneration
: _dadGeneration;
_newKittenId = _createKitty(
mumId_,
dadId_,
_generation,
_newKittyGene,
msg.sender
);
}
function _mixDNA(uint256 dadDNA_, uint256 mumDNA_)
internal
pure
returns (uint256 _newDNA)
{
uint256 _newDNAPartOne = dadDNA_ / (10 ^ 8);
uint256 _newDNAPartTwo = mumDNA_ % (10 ^ 8);
_newDNA = _newDNAPartOne * (10 ^ 8) + _newDNAPartTwo;
}
1 Like
Here is my solution:
function breed(uint256 _dadId, uint256 _mumId) external returns(uint256) {
require(kittyToOwner[_dadId] == msg.sender, "Both paretns must be yours!");
require(kittyToOwner[_mumId] == msg.sender, "Both paretns must be yours!");
( uint256 mumGenes,,,,uint256 mumGeneration, ) = getKitty(_mumId);
( uint256 dadGenes,,,,uint256 dadGeneration, ) = getKitty(_dadId);
uint256 newDna = _mixDna(dadGenes, mumGenes);
// calculate genereation (takes the heighest gen + 1 --> dad gen: 1, mum gen: 4, kid gen: 5):
uint256 gen = mumGeneration >= dadGeneration ? mumGeneration+1 : dadGeneration+1;
return _createKitty(_mumId, _dadId, gen, newDna, msg.sender);
}
1 Like
DNA Mixing Assignment
breed
function breed(uint256 _dadId, uint256 _momId) public onlyOwner returns (uint256) {
//check ownership
//figure out the generation of the fish
//create a new fish with new dna, give it to msg.sender
require(msg.sender == ownerToken[_dadId] && msg.sender == ownerToken[_momId],
"You must own both parents to breed");
uint256 _dadGen = fishies[_dadId].generation;
uint256 _momGen = fishies[_momId].generation;
uint256 _childGen = 0;
if(_dadGen == _momGen && _dadGen < 1) {
_childGen = 1;
}
else {
if(_dadGen > _momGen) {
_childGen = _dadGen + 1;
}
else {
_childGen = _momGen + 1;
}
}
uint256 _dadGenes = fishies[_dadId].genes;
uint256 _momGenes = fishies[_momId].genes;
uint256 newDna = _mixDna(_dadGenes, _momGenes);
return _createFishy(_momId, _dadId, _childGen, newDna, msg.sender);
}
_mixDna
function _mixDna(uint256 _dadDna, uint256 _momDna) internal pure returns (uint256) {
//dadDna: 11 22 33 44 55 66 77 88
//momDna: 88 77 66 55 44 33 22 11
uint256 _firstDadHalf = (_dadDna / 100000000); //11223344
uint256 _secondMomHalf = (_momDna % 100000000); //44332211
uint256 _babyDna = ((_firstDadHalf * 100000000) + _secondMomHalf);
return _babyDna;
/* NOTE - An advanced mixing option would have the ability to evaluate
each section, and determine which parent to utilize for that
section of child dna */
//Have a loop that iterates to pull each section
//Use a 'random' function to do a "coin-flip" and pick a parent dna section
//With each section assigned, run another loop which brings all the sections together
}
1 Like
Ive made it all in a single function. I decided that the generation will be mums generation +1
function Breed(uint32 mumId, uint32 dadId)public returns(uint256){
require(_isApprovedOrOwner(_msgSender(), mumId), "ERC721: transfer caller is not owner nor approved");
require(_isApprovedOrOwner(_msgSender(), dadId), "ERC721: transfer caller is not owner nor approved");
uint dadGenes = kitties[dadId].genes;
uint mumGenes = kitties[mumId].genes;
uint16 kittyGeneration =kitties[mumId].generation+1;
uint _fromDad = dadGenes/100000000;
uint fromDad = _fromDad*100000000;
uint fromMum = mumGenes % 100000000;
uint kittyGenes = fromDad+fromMum;
return kittyGenes;
return _createNewKitty(kittyGenes, mumId, dadId, kittyGeneration, msg.sender);
}
2 Likes
My solution…
function breed(uint256 _dadId, uint256 _mumId) public returns (uint256) {
require(_owns(msg.sender, _dadId), "Dad Id is not owned by you");
require(_owns(msg.sender, _mumId), "Mum Id is not owned by you");
(uint256 dadDna,,,,uint256 dadGeneration) = getKitty(_dadId); // only necessary values retrieved
(uint256 mumDna,,,,uint256 mumGeneration) = getKitty(_mumId); // => Dna and generation
uint256 newDna = _mixDna(dadDna, mumDna);
// new generation: highest one + 1
uint256 kittyGen = (dadGeneration < mumGeneration) ? mumGeneration + 1 : dadGeneration + 1;
_createKitty(_mumId, _dadId, kittyGen, newDna, msg.sender);
}
function _mixDna(uint256 _dadDna, uint256 _mumDna) internal pure returns (uint256) {
uint256 leftHalfDad = _dadDna / 100000000;
uint256 rightHalfMum = _mumDna % 100000000;
return leftHalfDad * 100000000 + rightHalfMum;
}
2 Likes
function breed(uint256 _dadId, uint256 _momId) public returns (uint256) {
//Check ownership
require(_owns(msg.sender,_dadId) && _owns(msg.sender,_momId), "Both cats have to be owned by you to enable breeding");
//Figure out the calculation for the new cat Generation (now that we have the DNA).
( uint256 _dadDNA,,,, uint256 dadGeneration ) = getKitty(_dadId);
( uint256 _momDNA,,,, uint256 momGeneration ) = getKitty(_momId);
uint256 newCatDna = _mixDna(_dadDNA, _momDNA);
//Create new cat w/ new properties & give it to msg.sender
uint256 kidGeneration = 0;
if (dadGeneration < momGeneration) {
kidGeneration = momGeneration + 1;
kidGeneration / 2;
}
else if (dadGeneration > momGeneration) {
kidGeneration = dadGeneration + 1;
kidGeneration / 2;
}
else {kidGeneration = momGeneration + 1;
}
return _createKitty(_momId, _dadId, kidGeneration, newCatDna, msg.sender);
}
function _mixDna(uint256 _dadDna, uint256 _momDna) internal returns (uint256) {
uint256 firstHalf = _dadDna / 100000000;
uint256 secondHalf = _momDna % 100000000;
uint256 newDNA = firstHalf * 100000000;
newDNA = newDNA + secondHalf;
return newDNA;
}
1 Like
**mix dna **
function _mixDna(uint256 _dadDna, uint256 _mumDna)
internal
pure
returns (uint256)
{
//dadDna: 11 22 33 44 55 66 77 88
//mumDna: 88 77 66 55 44 33 22 11
uint256 dadSide = _dadDna / 100000000;
uint256 mumSide = _mumDna % 100000000;
uint256 newDna = (dadSide * 100000000) + mumSide;
return newDna;
}
breed
function breed(uint256 _dadId, uint256 _mumId) public returns (uint256) {
//check ownership
//check you got the dna
//figure out the generation
//create a new cat with new properties, give it to msg.sender
require(
_owns(msg.sender, _dadId) && _owns(msg.sender, _mumId),
"You must own both cats in order to breed"
);
uint256 newDna = _mixDna(_dadId, _mumId);
uint256 kidGen = 0;
uint256 mumGen = kitties[_mumId].generation;
uint256 dadGen = kitties[_dadId].generation;
if (dadGen < mumGen) {
kidGen = mumGen + 1;
kidGen /= 2;
} else if (dadGen > mumGen) {
kidGen = dadGen + 1;
kidGen /= 2;
} else {
kidGen = mumGen = 1;
}
_createKitty(newDna, _mumId, _dadId, kidGen, msg.sender);
return newDna;
}
}```
1 Like
Breed
function breed(uint256 _dadId, uint256 _mumId) public returns (uint256){
//check ownership
//You got the DNA
//figure out the Generation
//Creat a new cat with the new properties, give it to the msg.sender
require(_owns(msg.sender, _dadId), "The user doesn't own the token");
require(_owns(msg.sender, _mumId), "The user doesn't own the token");
( uint256 dadDna,,,,uint256 DadGeneration ) = getKitty(_dadId);
( uint256 mumDna,,,,uint256 MumGeneration ) = getKitty(_mumId);
uint256 newDna = _mixDna(dadDna, mumDna);
uint256 kidGen = 0;
if(DadGeneration < MumGeneration){
kidGen = MumGeneration + 1;
kidGen /=2
}else if (DadGeneration > MumGeneration) {
kidGen = DadGeneration + 1;
KidGen /= 2;
}else{
KidGen = MumGeneration + 1;
}
_createKitty(_mumId, _dadId, kidGen, newDna, msg.sender);
}
Mix DNA
function _mixDna(uint256 _dadDna, uint256 _mumDna) internal returns (uint256) {
//dadDna: 11 22 33 44 55 66 77 88
//mumDna: 88 77 66 55 44 33 22 11
uint256 firstHalf = _dadDna / 100000000; // 11223344
uint256 secondHalf = _mumDna % 100000000; // 44332211
uint256 newDna = firstHalf * 100000000;
newDna = newDna + secondHalf; // 1122334444332211
return newDna;
}
2 Likes
breed function:
function breed(uint _dadId, uint _momId) external returns(uint) {
require(_owns(msg.sender, _dadId) && _owns(msg.sender, _momId),"You dont own these cats");
uint dadGeneration = kitties[_dadId].generation;
uint momGeneration = kitties[_momId].generation;
uint newGeneration;
if(dadGeneration > momGeneration) {
newGeneration = dadGeneration++;
}
else {
newGeneration = momGeneration++;
}
uint dadDna = kitties[_dadId].genes;
uint momDna = kitties[_momId].genes;
uint newDna = _mixDna(dadDna, momDna);
_createKitty(newDna, _momId, _dadId, newGeneration, msg.sender);
return newDna;
}
_mixDna function:
function _mixDna(uint _dadDna, uint _momDna) internal pure returns(uint) {
uint firstHalf= _dadDna / 100000000;
uint secondHalf= _momDna % 100000000;
uint newDna = (firstHalf * 100000000) + secondHalf;
return newDna;
}
2 Likes
function breed(uint256 _dadId, uint256 _momId) public returns(uint256){
require(_owns(msg.sender,_dadId));
require(_owns(msg.sender,_momId));
{uint256 dadDNA,,,, uint256 dadGen} = getKitty(_dadId);
{uint256 momDNA,,,, uint256 momGen} = getKitty(_momId);
uint256 newDNA = _mixDNA(dadDNA,momDNA);
uint256 childGen = 0;
if(dadGen < momGen){
childGen = momGen++;
}else if(dadGen > momGen){
childGen = dadGen++;
}else{
childGen = momGen++;
}
_createKitty(_momId, _dadId, childGen, newDNA, msg.sender);
}
2 Likes
//breeding new Bears
function breed(uint256 dadId, uint256 mumId) public returns (uint256) {
//check ownership
require(_owns(msg.sender, dadId) || getApproved(dadId) == msg.sender, "msg.sender is not the token owner of the father!");
require(_owns(msg.sender, mumId) || getApproved(mumId) == msg.sender, "msg.sender is not the token owner of the mother!");
//new generation is determined
uint256 dadGen = bears[dadId].generation;
uint256 mumGen = bears[mumId].generation;
uint256 newGen;
if(dadGen > mumGen) {
newGen = dadGen++;
}
else {
newGen = mumGen++;
}
//DNA String is made
uint256 dadDna = bears[dadId].genes;
uint256 mumDna = bears[mumId].genes;
uint256 newDna = _mixDna(dadDna, mumDna);
//create new bear
_createBear(newDna, mumId, dadId, newGen, msg.sender);
}
//Dna of parent bears gets mixed
function _mixDna(uint256 _dadDna, uint256 _mumDna) internal returns (uint256) {
uint256 firstDnaHalf = _dadDna / 100000000;
uint256 secondDnaHalf = _mumDna % 100000000;
uint256 newDna = firstDnaHalf * 100000000;
newDna = newDna + secondDnaHalf;
return newDna;
}
Hi All,
This is the breed
function:
function breed(uint32 _mumId, uint32 _dadId) external {
_validateToken(_mumId);
_validateToken(_dadId);
// Check ownership
require(tokenowners[_mumId] == msg.sender, "Caller does not own mum id");
require(tokenowners[_dadId] == msg.sender, "Caller does not own dad id");
// Calculate the new dna
Kitty storage mum = kitties[_mumId];
Kitty storage dad = kitties[_dadId];
uint256 newGenes = _mixGenes(mum.genes, dad.genes);
// mint the new kitty
_createKitty(_mumId, _dadId, mum.generation+1, newGenes, msg.sender);
}
and a very basic _mixGenes
function:
function _mixGenes(uint256 mumDna, uint256 dadDna) private pure returns (uint256 childDna){
childDna = (mumDna / 1000000)*1000000 + dadDna % 1000000;
}
Unit tests:
4_breed_test.js
const Kitty = artifacts.require('Kittycontract');
const truffleAssert = require('truffle-assertions');
contract("Test breed function", accounts =>{
let kitty
let mumId
let dadId
let childId
beforeEach(async()=>{
kitty = await Kitty.new()
let mum = await kitty.createKittyGen0(10203040123501)
truffleAssert.eventEmitted(mum, 'Birth', event=>{
mumId = event.tokenId
return true
})
let dad = await kitty.createKittyGen0(50708090234602)
truffleAssert.eventEmitted(dad, 'Birth', event=>{
dadId = event.tokenId
return true
})
let child = await kitty.breed(mumId, dadId)
truffleAssert.eventEmitted(child, 'Birth', event=>{
childId = event.tokenId
return true
})
})
afterEach(async()=>{
kitty = 0
mumId = 0
dadId = 0
childId = 0
})
it("caller should own a new cat with higher generation", async()=>{
var childOwner = await kitty.ownerOf(childId)
assert(childOwner == accounts[0], "Account 0 should own the new cat")
var childKitty = await kitty.getKitty(childId)
assert(childKitty.generation == 1, "Wrong generation")
assert(childKitty.mumId == mumId.toNumber(), "wrong mum")
assert(childKitty.dadId == dadId.toNumber(), "wrong dad")
})
it("new cat genes should be properly mixed", async()=>{
var childKitty = await kitty.getKitty(childId)
assert(childKitty.genes == 10203040234602, "Wrong mixed genes")
})
it("should fail if caller does not own any of the cats", async()=>{
// Does not own any
await truffleAssert.reverts(
kitty.breed(mumId, dadId, {from: accounts[1]})
)
})
it("should fail if caller owns 1 cat out of 2", async()=>{
await kitty.transfer(accounts[1], mumId)
// Owns one
await truffleAssert.reverts(
kitty.breed(mumId, dadId, {from: accounts[1]})
)
})
it("should pass if caller owns both cats", async()=>{
await kitty.transfer(accounts[1], mumId)
await kitty.transfer(accounts[1], dadId)
// Owns one
await truffleAssert.passes(
kitty.breed(mumId, dadId, {from: accounts[1]})
)
})
}
)
Kittycontract
uint256 private constant secondsPerGeneration = 1000000;
uint256[] public cooldowns = [
1 minutes, // for generation 0 cats
2 minutes, // for generation 1 cats
3 minutes, // for generation 2 cats
4 minutes // for generation 3+ cats
];
function breed(uint256 _dadId, uint256 _mumId) public returns(uint256) {
// Check ownership of both parents
require(_owns(payable(msg.sender), _dadId), "Caller does not own the father");
require(_owns(payable(msg.sender), _mumId), "Caller does not own the mother");
// Get parent DNA
(uint256 dadGenes, , , , uint16 dadGeneration) = getKitty(uint32(_dadId));
(uint256 mumGenes, , , , uint16 mumGeneration) = getKitty(uint32(_mumId));
// Generation
uint16 newGeneration = dadGeneration > mumGeneration ? dadGeneration : mumGeneration;
// create and return new cat to msg.sender
uint256 newDna = _mixDna(dadGenes, mumGenes);
return newDna;
}
function _canBreed(uint256 _kittyId) internal view returns (bool) {
Kitty storage kitty = kitties[_kittyId];
uint256 secondsSinceBirth = uint256(block.timestamp).sub(kitty.birthTime);
uint256 cooldown = secondsPerGeneration.mul(kitty.generation.add(1));
return secondsSinceBirth >= cooldown && kitty.cooldownEndBlock <= uint64(block.number);
}
function _mixDna(uint256 _dadDna, uint256 _mumDna) internal returns(uint256) {
// dadDna = 11 22 33 44 55 66 77 88
// mumDna = 88 77 66 55 44 33 22 11
uint256 multiplicator = 100000000; // 100 000 000
uint256 firstHalf = _dadDna / multiplicator; // 11 22 33 44
uint256 secondHalf = _mumDna % multiplicator; // 44 33 22 11
uint256 newDna = firstHalf * multiplicator; // 11 22 33 44 00 000 000
newDna = newDna + secondHalf; // 11 22 33 44 44 33 22 11
return newDna;
}
function createKitty(
uint256 _mumId,
uint256 _dadId,
uint256 _generation,
uint256 _genes,
address _owner
) private returns (uint256) {
uint256 cooldownEndBlock = 0; // set initial cooldown end block to 0
if (_generation == 0) {
cooldownEndBlock = block.number + (1 days / cooldowns[0]);
} else {
uint256 lastGenCooldownEndBlock = kitties[kitties.length - 1].cooldownEndBlock;
cooldownEndBlock = lastGenCooldownEndBlock + (1 days / cooldowns[_generation]);
}
Kitty memory _kitty = Kitty({
genes: _genes,
birthTime: uint64(block.timestamp),
mumId: uint32(_mumId),
dadId: uint32(_dadId),
generation: uint16(_generation),
cooldownEndBlock: uint64(cooldownEndBlock)
});
kitties.push(_kitty);
uint256 newKittenId = kitties.length - 1;
emit Birth(_owner, newKittenId, _mumId, _dadId, _genes);
_transfer(address(0), _owner, newKittenId);
return newKittenId;
}