// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {Army} from "../src/RaidGeldStructs.sol"; library RaidGeldUtils { uint256 public constant PRECISION = 10000; uint256 constant PRICE_FACTOR = 11500; // base price * (0.00666) * 11 per each next unit uint256 constant MOLOCH_DENIER_PROFIT = 2533; uint256 constant APPRENTICE_PROFIT = 27863; uint256 constant ANOINTED_PROFIT = 306493; uint256 constant CHAMPION_PROFIT = 3371423; // each costs 10 times plus a bit more uint256 constant MOLOCH_DENIER_BASE_COST = 380000; uint256 constant APPRENTICE_BASE_COST = 3420000; uint256 constant ANOINTED_BASE_COST = 30096000; uint256 constant CHAMPION_BASE_COST = 255816000; // Boss lvels uint256[7] constant BOSS_POWERS = [ 9000000, // 900e4 90000000, // 900e5 900000000, // 900e6 9000000000, // 900e7 90000000000, // 900e8 900000000000, // 900e9 9000000000000 // 900e10 ]; // First boss is almost guaranteed, others arent uint256[7] constant BOSS_CHANCES = [99, 89, 80, 70, 62, 51, 40]; // These are cumulative chances from above with precision 18 uint256[7] constant CUMULATIVE_BOSS_CHANCES = [99e16, 8811e14, 7048e14, 493416e12, 30591792e10, 1560181392e8, 6240725568e7]; uint256 constant RISK_BETA = 15e17; function calculateUnitPrice(uint8 unit, uint16 currentLevel, uint16 units) internal pure returns (uint256) { require(unit <= 3, "No matching unit found"); uint256 rollingPriceCalculation = MOLOCH_DENIER_BASE_COST; uint256 price = 0; if (unit == 1) { rollingPriceCalculation = APPRENTICE_BASE_COST; } else if (unit == 2) { rollingPriceCalculation = ANOINTED_BASE_COST; } else if (unit == 3) { rollingPriceCalculation = CHAMPION_BASE_COST; } // Each level costs 15% more than previous for (uint256 i = 0; i < currentLevel + units; i++) { if (i >= currentLevel) { price += rollingPriceCalculation; } rollingPriceCalculation = rollingPriceCalculation * PRICE_FACTOR / PRECISION; } return price; } function calculateProfitsPerSecond(Army memory army) internal pure returns (uint256) { // Each next unit scales progressivelly better uint256 moloch_denier_profit = army.moloch_denier.level * MOLOCH_DENIER_PROFIT; uint256 apprentice_profit = army.apprentice.level * APPRENTICE_PROFIT; uint256 anointed_profit = army.anointed.level * ANOINTED_PROFIT; uint256 champion_profit = army.champion.level * CHAMPION_PROFIT; return moloch_denier_profit + apprentice_profit + anointed_profit + champion_profit; } // Returns how much Dao Token player is due for winning function calculateBossReward(uint256 bossLevel) public view returns (uint256) { return BOSS_POWERS[bossLevel] * (CUMULATIVE_BOSS_CHANCES[bossLevel] * 10 / 5) ** 2; } // Calculates whether user survives the fight function calculateBossFight(uint8 bossLevel, uint256 geldBurnt, uint256 timestamp, uint256 difficulty) internal pure returns (uint256) { uint256 bossPower = BOSS_POWERS[bossLevel]; require(geldBurnt <= bossPower, "Cant try to defeat boss with more than what boss power is"); uint256 random_n = random(timestamp, difficulty, 1, 100); // Relative power as in, you can only put in 800 geld to defeat 900 geld boss, // but you will get exponentially worse chances uint256 relativePower = ((geldBurnt ** 2) * 100) / bossPower ** 2; uint256 roll = (random_n * relativePower * PRECISION) / (100 * PRECISION); return roll >= bossPower; } // TODO: Implement actual randomness function random(uint256 timestamp, uint256 difficulty, uint256 min, uint256 max) internal pure returns (uint256) { // returns 0 - 100 require(max >= min, "Max must be greater than or equal to min"); uint256 range = max - min + 1; return min + (uint256(keccak256(abi.encodePacked(timestamp, difficulty))) % range); } }