1
0
forked from mico/idle_moloch
idle_moloch/src/RaidGeldUtils.sol
2024-10-30 00:28:48 +01:00

103 lines
4.1 KiB
Solidity

// 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);
}
}