public static string FeedReef(object[] args) { if (args.Length != 1) { Runtime.Log("* No Args"); return("no args"); } byte[] reef = (byte[])args[0]; // I am the only one who can feed my reef if (!Runtime.CheckWitness(reef)) { Runtime.Log("* Not the Owner"); return("not owner"); } BigInteger currentBlockHeight = BlockchainHelper.GetHeight(); // used in the whole method BigInteger lastFedBH = ReefDao.GetBlockHeightFedReef(reef).AsBigInteger(); if (currentBlockHeight == lastFedBH) { Runtime.Log("* Fishes are not hungry"); return("not hungry"); } byte[] fishesAlive = ReefDao.GetReefFishesAlive(reef); // fishes alive on the reef, used in the whole method BigInteger fishesAliveLength = ListManager.GetLength(fishesAlive, FishManager.GetSize()); // used in the whole method Runtime.Log(" "); Runtime.Log("Fishes Alive:"); Runtime.Log(fishesAliveLength.AsByteArray().AsString()); Runtime.Log("------------"); BigInteger balance = FishCoinDao.BalanceOf(reef) / FishCoinProcess.DecimalsFactor; // if there is not enough food, there is nothing to do, the food will not be consumed if (balance < fishesAliveLength || balance <= 0) { Runtime.Log("* Not enough food"); return("no food"); } // variables used to generate random BigInteger consensusData = BlockchainHelper.GetConsensusData(); BigInteger randomStep = BlockchainHelper.GetRandomStep(); // a stepper to use a new random next time BigInteger aRandom = 0; // the random variable // if there is less than 2 fishes in the reef if (fishesAliveLength < 2) { Runtime.Log("* There is less than 2 fishes alive in the reef"); aRandom = BlockchainHelper.Random(consensusData, randomStep); randomStep = randomStep + 1; // 25% probability to arrive a new fish that got interested by the food you give away if (aRandom % 4 == 0) { Runtime.Log("* Immigrant arrived"); byte[] newImmigrant = FishManager.BuildImmigrant(reef, consensusData, randomStep); randomStep = randomStep + 4; // it was used 4 times inside the method fishesAlive = ListManager.Add(fishesAlive, newImmigrant); fishesAliveLength = fishesAliveLength + 1; Notifier.ImmigrantFish(reef, newImmigrant); } else { Runtime.Log("* No Immigrant today"); } } // if there is 2 or more fishes in the reef else { Runtime.Log("* There is 2 or more fishes in the reef"); aRandom = BlockchainHelper.Random(consensusData, randomStep); randomStep = randomStep + 1; // 33.3% probability to fishes get laid if (aRandom % 3 == 0) { Runtime.Log("* Fishs in love"); byte[] newBaby = new byte[0]; BigInteger indexFather; BigInteger indexMother; // if there is only 2 fishes they are the only possibility to mate if (fishesAliveLength == 2) { Runtime.Log("* Exactly 2 lovers"); indexFather = 0; indexMother = 1; } else { Runtime.Log("* More than 2 possible lovers"); // get a random fish to be the father aRandom = BlockchainHelper.Random(consensusData, randomStep); randomStep = randomStep + 1; indexFather = aRandom % fishesAliveLength; do { // get a random fish to be the mother, but a different fish of the father aRandom = BlockchainHelper.Random(consensusData, randomStep); randomStep = randomStep + 1; indexMother = aRandom % fishesAliveLength; Runtime.Log("* Looking for a pretty female"); } while (indexFather == indexMother); } byte[] father = ListManager.GetAt(fishesAlive, FishManager.GetSize(), indexFather); byte[] mother = ListManager.GetAt(fishesAlive, FishManager.GetSize(), indexMother); Runtime.Log("* Gestation"); newBaby = FishManager.BuildFromParents(consensusData, randomStep, father, mother); randomStep = randomStep + father.Length; // tried random that many times Runtime.Log("* Its a ... Fish!"); fishesAlive = ListManager.Add(fishesAlive, newBaby); fishesAliveLength = fishesAliveLength + 1; BigInteger newBornIndex = fishesAliveLength - 1; Notifier.NewBornFish(reef, newBaby); byte[] fatherFishType = FishManager.GetPropCarnivorous(father); byte[] motherFishType = FishManager.GetPropCarnivorous(mother); // if one of the parents are carnivorous and there is another silly fish ready to be a pray if (fatherFishType[0] == 0 || motherFishType[0] == 0 || fishesAliveLength > 3) { Runtime.Log("* There is pray for the predator"); BigInteger fathersFedWithFishBlockHeight = FishManager.GetFedWithFishBlockHeight(father).AsBigInteger(); BigInteger mothersFedWithFishBlockHeight = FishManager.GetFedWithFishBlockHeight(mother).AsBigInteger(); BigInteger indexPredator = -1; // zero means carnivorous // if has been more than 20 blocks since last time the father eat a fish if (fatherFishType[0] == 0 && currentBlockHeight - fathersFedWithFishBlockHeight > 20) { Runtime.Log("* The father is hungry"); indexPredator = indexFather; } else if (motherFishType[0] == 0 && currentBlockHeight - mothersFedWithFishBlockHeight > 20) { Runtime.Log("* The mother is hungry"); indexPredator = indexMother; } if (indexPredator > -1) { Runtime.Log("* It means that one of them is having a lunch"); byte[] predator = ListManager.GetAt(fishesAlive, FishManager.GetSize(), indexPredator); BigInteger indexPrey = 0; do { // get a random fish to be eaten, but a different fish of the father and the mother aRandom = BlockchainHelper.Random(consensusData, randomStep); randomStep = randomStep + 1; indexPrey = aRandom % fishesAliveLength; } while (indexPrey == indexMother || indexPrey == indexFather || indexPrey == newBornIndex); // saving the last blockheight when fish was fed with fish predator = FishManager.SetFedWithFishBlockHeight(predator, currentBlockHeight.AsByteArray()); fishesAlive = ListManager.EditAt(fishesAlive, FishManager.GetSize(), indexPredator, predator); // saving the predator dna inside the prey byte[] prey = ListManager.GetAt(fishesAlive, FishManager.GetSize(), indexPrey); // removing the prey from alive list (after everything, to not lose the right position after removing) fishesAlive = ListManager.RemoveAt(fishesAlive, FishManager.GetSize(), indexPrey); fishesAliveLength = fishesAliveLength - 1; byte[] fishesDead = ReefDao.GetReefFishesDead(reef); // fishes alive on the reef fishesDead = ListManager.Add(fishesDead, prey); ReefDao.UpdateReefFishesDead(reef, fishesDead); Notifier.FishEaten(reef, prey, predator); } else { Runtime.Log("* The predators are not hungry"); } } else { Runtime.Log("* No deaths today"); } } else { Runtime.Log("* They are not in the mood"); } } Runtime.Log("* Let's go sleep"); fishesAlive = IncrementQuantityOfFeeds(fishesAlive, fishesAliveLength); ReefDao.UpdateReefFishesAlive(reef, fishesAlive); FishCoinDao.SetTotalSupply(balance - fishesAliveLength); ReefDao.UpdateBlockHeightFedReef(reef, currentBlockHeight.AsByteArray()); BlockchainHelper.UpdateRandomStep(randomStep); Runtime.Log("* End :)"); return("success"); }