contract Fog is usingOraclize {
  address public owner;

  address private playerAddress;
  uint private playerValue;

  event OwnershipTransferred(
    address indexed owner,
    address indexed newOwner
  );

  event Winner(address indexed to, uint indexed value);
  event CupCake(address indexed to, uint indexed value);
  event Looser(address indexed from, uint indexed value);

  constructor() payable public {
    owner = msg.sender;
    oraclize_setProof(proofType_Ledger); // sets the Ledger authenticity proof in the constructor
  }

  function move() payable public {
    require(msg.value >= 10000000000000000); // min 0.01 Ether

    playerAddress = msg.sender;
    playerValue = msg.value;

    uint N = 1; // number of random bytes we want the datasource to return
    uint delay = 0; // number of seconds to wait before the execution takes place
    uint callbackGas = 200000; // amount of gas we want Oraclize to set for the callback function

    oraclize_newRandomDSQuery(delay, N, callbackGas); // this function internally generates the correct oraclize_query and returns its queryId
  }

  // the callback function is called by Oraclize when the result is ready
  // the oraclize_randomDS_proofVerify modifier prevents an invalid proof to execute this function code:
  // the proof validity is fully verified on-chain
  function __callback(bytes32 _queryId, string _result, bytes _proof) public
  {
    if (msg.sender != oraclize_cbAddress()) revert();

    if (oraclize_randomDS_proofVerify__returnCode(_queryId, _result, _proof) != 0) {
      // the proof verification has failed
    } else {
      uint dice = uint(keccak256(abi.encodePacked(_result))) % 3;

      // Winner
      if (dice == 0) {
        uint doubleValue = mul(playerValue, 2);

        playerAddress.transfer(doubleValue);
        emit Winner(playerAddress, doubleValue);

        // Looser
      } else if (dice == 1) {
        emit Looser(playerAddress, playerValue);

        // Woa! Refund 80%
      } else if (dice == 2) {
        uint eightyPercent = div(mul(playerValue, 80), 100);

        playerAddress.transfer(eightyPercent);
        emit CupCake(playerAddress, eightyPercent);
      }
    }
  }

  function drain(uint value) public onlyOwner {
    require(value >= 0 && value < address(this).balance);
    owner.transfer(value);
  }

  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    emit OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }

  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  function() public payable { }

  /**
  * @dev Multiplies two numbers, reverts on overflow.
  */
  function mul(uint256 _a, uint256 _b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (_a == 0) {
      return 0;
    }

    uint256 c = _a * _b;
    require(c / _a == _b);

    return c;
  }

  /**
  * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b > 0); // Solidity only automatically asserts when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
  require(b > 0); // Solidity only automatically asserts when dividing by 0
  uint256 c = a / b;
  // assert(a == b * c + a % b); // There is no case in which this doesn't hold

  return c;
}

/**
 * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
 */