CryptoHorse.sol - CryptoHorse source code
pragma solidity ^0.4.19;
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function Ownable() public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract ERC721 {
function totalSupply() public view returns (uint256 total);
function balanceOf(address _owner) public view returns (uint256 balance);
function ownerOf(uint256 _tokenId) external view returns (address owner, uint256 tokenId);
function approve(address _to, uint256 _tokenId) external;
function transfer(address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
event Transfer(address from, address to, uint256 tokenId);
event Approval(address owner, address approved, uint256 tokenId);
}
contract HorseControl {
address public ceoAddress=0xC229F1e3D3a798725e09dbC6b31b20c07b95543B;
address public ctoAddress=0x01569f2D20499ad013daE86B325EE30cB582c3Ba;
modifier onCEO() {
require(msg.sender == ceoAddress);
_;
}
modifier onCTO() {
require(msg.sender == ctoAddress);
_;
}
modifier onlyC() {
require(
msg.sender == ceoAddress ||
msg.sender == ctoAddress
);
_;
}
}
contract GeneScienceInterface is HorseControl{
/*
* Genetics is a secret by nature
* for more informations please contact code@cryptohorse.ch
* if you are an programmer, please contact jobs@cryptohorse.ch
*/
}
contract HoresBasis is GeneScienceInterface {
event Birth(address owner, uint256 HorseId, uint256 mareId, uint256 stallionId);
event Transfer(address from, address to, uint256 tokenId);
struct Horse {
uint64 birthTime;
uint64 unproductiveEndBlock;
uint32 mareId;
uint32 stallionId;
uint32 stallionWithId;
uint16 unproductiveIndex;
uint16 generation;
}
uint32[5] public sterile = [
uint32(15 minutes),
uint32(120 minutes),
uint32(480 minutes),
uint32(1800 minutes),
uint32(3000 minutes)
];
uint256 public secondsPerBlock = 15;
Horse[] horses;
mapping (uint256 => address) public horseOwnerIndex;
mapping (uint256 => uint256) public horseIndexPrice;
mapping (uint256 => bool) horseIndexForSale;
mapping (address => uint256) tokenOwnershipCount;
uint256 public saleFee = 20;
uint256 public BirthFee = 4 finney;
function _transfer(address _from, address _to, uint256 _tokenId) internal {
tokenOwnershipCount[_to]++;
horseOwnerIndex[_tokenId] = _to;
if (_from != address(0)) {
tokenOwnershipCount[_from]--;
}
Transfer(_from, _to, _tokenId);
}
function _sell(address _from, uint256 _tokenId, uint256 value) internal {
if(horseIndexForSale[_tokenId]==true){
uint256 price = horseIndexPrice[_tokenId];
require(price<=value);
uint256 Fee = price / saleFee;
uint256 oPrice= price - Fee;
address _to = msg.sender;
tokenOwnershipCount[_to]++;
horseOwnerIndex[_tokenId] = _to;
horseIndexForSale[_tokenId]=false;
if (_from != address(0)) {
tokenOwnershipCount[_from]--;
}
Transfer(_from, _to, _tokenId);
_from.transfer(oPrice);
ceoAddress.transfer(Fee);
uint256 bidExcess = value - oPrice - Fee;
_to.transfer(bidExcess);
}else{
_to.transfer(value);
}
}
function _newHorse(
uint256 _mareId,
uint256 _stallionId,
uint256 _generation,
/* secret genetic */,
address _owner
)
internal
returns (uint)
{
Horse memory _horse = Horse({
birthTime: uint64(now),
unproductiveEndBlock: 0,
mareId: uint32(_mareId),
stallionId: uint32(_stallionId),
stallionWithId: 0,
unproductiveIndex: 0,
generation: uint16(_generation)
});
uint256 newHorseId;
newHorseId = horses.push(_horse)-1;
makeDna(_mareId, _stallionId, newHorseId, /* secret genetic */);
require(newHorseId == uint256(uint32(newHorseId)));
Birth(
_owner,
newHorseId,
uint256(_horse.mareId),
uint256(_horse.stallionId)
);
_transfer(0, _owner, newHorseId);
return newHorseId;
}
function makeDna( uint256 _mareId,
uint256 _stallionId,
uint256 _newId,
/* secret genetic */)internal{
if(_mareId!=0 && _stallionId!=0){
Horse storage stallion = horses[_stallionId];
Horse storage mare = horses[_mareId];
GeneScienceInterface.mixGenes(/* secret genetic */);
}else{
/* secret genetic */
}
}
function setSecondsPerBlock(uint256 secs) external onlyC {
require(secs < sterile[0]);
secondsPerBlock = secs;
}
}
contract HorseOwnership is HoresBasis, ERC721{
string public constant name = "CryptoHorse";
string public constant symbol = "CHC";
uint8 public constant decimals = 0;
function horseForSale(uint256 _tokenId, uint256 price) external {
address ownerof = horseOwnerIndex[_tokenId];
require(ownerof == msg.sender);
horseIndexPrice[_tokenId] = price;
horseIndexForSale[_tokenId]= true;
}
function horseNotForSale(uint256 _tokenId) external {
address ownerof = horseOwnerIndex[_tokenId];
require(ownerof == msg.sender);
horseIndexForSale[_tokenId]= false;
}
function _owns(address _applicant, uint256 _tokenId) internal view returns (bool) {
return horseOwnerIndex[_tokenId] == _applicant;
}
function balanceOf(address _owner) public view returns (uint256 count) {
return tokenOwnershipCount[_owner];
}
function transfer(
address _to,
uint256 _tokenId
)
external
payable
{
require(_to != address(0));
require(_to != address(this));
require(_owns(msg.sender, _tokenId));
_transfer(msg.sender, _to, _tokenId);
}
function approve(
address _to,
uint256 _tokenId
)
external
{
require(_owns(msg.sender, _tokenId));
Approval(msg.sender, _to, _tokenId);
}
function transferFrom(address _from, address _to, uint256 _tokenId ) external payable {
if(_from != msg.sender){
require(_to == msg.sender);
require(_from==horseOwnerIndex[_tokenId]);
_sell(_from, _tokenId, msg.value);
}
}
function totalSupply() public view returns (uint) {
return horses.length;
}
function ownerOf(uint256 _tokenId) external view returns (address owner, uint256 tokenId) {
owner = horseOwnerIndex[_tokenId];
tokenId=_tokenId;
return;
}
function horseFS(uint256 _tokenId) external view returns (bool buyable, uint256 tokenId) {
buyable = horseIndexForSale[_tokenId];
tokenId=_tokenId;
return;
}
function horsePr(uint256 _tokenId) external view returns (uint256 price, uint256 tokenId) {
price = horseIndexPrice[_tokenId];
tokenId=_tokenId;
return;
}
}
contract HorseStud is HorseOwnership {
event Pregnant(address owner, uint256 mareId, uint256 stallionId, uint256 unproductiveEndBlock);
uint256 public pregnantHorses;
function _isStallionPermitted(uint256 _stallionId, uint256 _mareId) internal view returns (bool) {
address mareOwner = horseOwnerIndex[_mareId];
address stallionOwner = horseOwnerIndex[_stallionId];
return (mareOwner == stallionOwner);
}
function setBirthFee(uint256 val) external onCTO {
BirthFee = val;
}
function setSaleFee(uint256 val) external onCTO {
saleFee = val;
}
function isReadyToBear(uint256 _horseId) public view returns (bool) {
require(_horseId > 0);
Horse storage knight = horses[_horseId];
require(knight.unproductiveIndex<4);
bool ready = (knight.stallionWithId == 0) && (knight.unproductiveEndBlock <= uint64(block.number));
return ready;
}
function isPregnant(uint256 _horseId) public view returns (bool) {
require(_horseId > 0);
return horses[_horseId].stallionWithId != 0;
}
function _canScrewEachOther(uint256 _mareId, uint256 _stallionId) private view returns(bool) {
if (_mareId == _stallionId) {
return false;
}
uint256 matronSex=/* secret genetic */;
uint256 sireSex=/* secret genetic */;
if(matronSex!=1){
return false;
}
if(sireSex!=2){
return false;
}
if(matronSex==sireSex){
return false;
}
return true;
}
function canBearWith(uint256 _mareId, uint256 _stallionId)
external
view
returns(bool)
{
require(_mareId > 0);
require(_stallionId > 0);
return _canScrewEachOther( _mareId, _stallionId) &&
_isStallionPermitted(_stallionId, _mareId);
}
function _bearWith(uint256 _mareId, uint256 _stallionId) internal {
Horse storage stallion = horses[_stallionId];
Horse storage mare = horses[_mareId];
mare.stallionWithId = uint32(_stallionId);
stallion.unproductiveEndBlock = uint64((sterile[stallion.unproductiveIndex]/secondsPerBlock) + block.number);
mare.unproductiveEndBlock = uint64((sterile[mare.unproductiveIndex]/secondsPerBlock) + block.number);
if (stallion.unproductiveIndex < 5) {
stallion.unproductiveIndex += 1;
}
if (mare.unproductiveIndex < 5) {
mare.unproductiveIndex += 1;
}
pregnantHorses++;
Pregnant(horseOwnerIndex[_mareId], _mareId, _stallionId, mare.unproductiveEndBlock);
bearChild(_mareId);
}
function stallionWith(uint256 _mareId, uint256 _stallionId) external payable {
require(_owns(msg.sender, _mareId));
require(_owns(msg.sender, _stallionId));
Horse storage mare = horses[_mareId];
require(isReadyToBear(_mareId));
require(isReadyToBear(_stallionId));
bool (mare.stallionWithId == 0) && (mare.unproductiveEndBlock <= uint64(block.number));
Horse storage stallion = horses[_stallionId];
bool (stallion.stallionWithId == 0) && (stallion.unproductiveEndBlock <= uint64(block.number));
require(_canScrewEachOther(
_mareId,
_stallionId
));
if(BirthFee>= msg.value){
ceoAddress.transfer(BirthFee);
uint256 rest=msg.value-BirthFee;
msg.sender.transfer(rest);
_bearWith(uint32(_mareId), uint32(_stallionId));
}else{
msg.sender.transfer(msg.value);
}
}
function bearChild(uint256 _mareId) internal {
Horse storage mare = horses[_mareId];
require(mare.birthTime != 0);
bool (mare.stallionWithId != 0) && (mare.unproductiveEndBlock <= uint64(block.number));
uint256 stallionId = mare.stallionWithId;
Horse storage stallion = horses[stallionId];
uint16 parentGen = mare.generation;
if (stallion.generation > mare.generation) {
parentGen = stallion.generation;
}
address owner = horseOwnerIndex[_mareId];
_newHorse(_mareId, stallionId, parentGen + 1, /* secret genetic */, owner);
mare.stallionWithId=0;
pregnantHorses--;
}
}
contract HorseMinting is HorseStud {
uint256 public GEN_0_LIMIT = 20000;
uint256 public gen0Count;
function createGen0Horse(/* secret genetic */, address _owner) external onCTO {
address horseOwner = _owner;
if (horseOwner == address(0)) {
horseOwner = ctoAddress;
}
require(gen0Count < GEN_0_LIMIT);
_newHorse(0, 0, 0, /* secret genetic */, horseOwner);
gen0Count++;
}
}
contract GetTheHorse is HorseMinting {
function getHorse(uint256 _id)
external
view
returns (
uint256 price,
uint256 id,
bool forSale,
bool isGestating,
bool isReady,
uint256 unproductiveIndex,
uint256 nextActionAt,
uint256 stallionWithId,
uint256 birthTime,
uint256 mareId,
uint256 stallionId,
uint256 generation
) {
price = horseIndexPrice[_id];
id = uint256(_id);
forSale = horseIndexForSale[_id];
Horse storage knight = horses[_id];
isGestating = (knight.stallionWithId != 0);
isReady = (knight.unproductiveEndBlock <= block.number);
unproductiveIndex = uint256(knight.unproductiveIndex);
nextActionAt = uint256(knight.unproductiveEndBlock);
stallionWithId = uint256(knight.stallionWithId);
birthTime = uint256(knight.birthTime);
mareId = uint256(knight.mareId);
stallionId = uint256(knight.stallionId);
generation = uint256(knight.generation);
}
}