diff --git a/src/RaidGeld.sol b/src/RaidGeld.sol index 2dcce8b..8529188 100644 --- a/src/RaidGeld.sol +++ b/src/RaidGeld.sol @@ -66,13 +66,14 @@ contract RaidGeld is ERC20, Ownable, Constants { BUY_IN_DAO_TOKEN_AMOUNT = 500 * 10 ** daoToken.decimals(); } - function init_player(address player) private { + function start_game(address player) private { bool existing_player = players[player].is_registered; // Mint some starting tokens to the player _mint(player, INITIAL_GELD); // Reset or set player reset_player(player); + players[player].has_active_session = true; if (existing_player) { // TODO: Emit new run @@ -87,24 +88,26 @@ contract RaidGeld is ERC20, Ownable, Constants { uint32 current_n_runs = player.n_runs + 1; uint256 current_total_rewards = player.total_rewards; bool current_is_registered = player.is_registered; + uint32 current_prestige_level = player.prestige_level; // Set initial states - players[msg.sender] = Player({ + players[addr] = Player({ total_minted: INITIAL_GELD, created_at: block.timestamp, last_raided_at: block.timestamp, n_runs: current_n_runs, total_rewards: current_total_rewards, has_active_session: false, - is_registered: current_is_registered + is_registered: current_is_registered, + prestige_level: current_prestige_level }); - armies[msg.sender] = Army({ + armies[addr] = Army({ moloch_denier: Raider({level: 0}), apprentice: Raider({level: 0}), anointed: Raider({level: 0}), champion: Raider({level: 0}), profit_per_second: 0 }); - bosses[msg.sender] = Boss({level: 0, variant: 0}); + bosses[addr] = Boss({level: 0, boss_variants: RaidGeldUtils.generate_boss_variants(block.prevrandao)}); } // New player want to register with ETH @@ -122,7 +125,7 @@ contract RaidGeld is ERC20, Ownable, Constants { sqrtPriceLimitX96: 0 }); router.exactInputSingle(params); - init_player(msg.sender); + start_game(msg.sender); } // New player wants to register with dao @@ -132,8 +135,7 @@ contract RaidGeld is ERC20, Ownable, Constants { require( daoToken.transferFrom(msg.sender, address(this), BUY_IN_DAO_TOKEN_AMOUNT), "Failed to transfer DAO tokens" ); - // Init player - init_player(msg.sender); + start_game(msg.sender); } // Override for default number of decimals @@ -251,17 +253,23 @@ contract RaidGeld is ERC20, Ownable, Constants { uint256 geld_to_burn = balanceOf(msg.sender) >= RaidGeldUtils.getBossPower(boss_to_attack.level) ? RaidGeldUtils.getBossPower(boss_to_attack.level) : balanceOf(msg.sender); - bool hasWonBattle = RaidGeldUtils.calculateBossFight( - boss_to_attack.level, geld_to_burn, block.prevrandao - ); + bool hasWonBattle = RaidGeldUtils.calculateBossFight(boss_to_attack.level, geld_to_burn, block.prevrandao); if (hasWonBattle) { // Burn geld, get some sweet DAO Token and continue _burn(msg.sender, geld_to_burn); uint256 reward = RaidGeldUtils.calculateBossReward(boss_to_attack.level); players[msg.sender].total_rewards += reward; daoToken.transferFrom(address(this), msg.sender, reward); + if (boss_to_attack.level == 6) { + // User ascends! Moloch is defeated + players[msg.sender].prestige_level += 1; + player_dies(msg.sender); + } else { + // else go to next boss + bosses[msg.sender].level += 1; + } } else { - // Whoops u die + // Whoops u died, boss defeated you player_dies(msg.sender); } } diff --git a/src/RaidGeldStructs.sol b/src/RaidGeldStructs.sol index 5d70a96..61d6703 100644 --- a/src/RaidGeldStructs.sol +++ b/src/RaidGeldStructs.sol @@ -19,11 +19,12 @@ struct Player { uint256 last_raided_at; uint256 total_rewards; uint32 n_runs; + uint32 prestige_level; bool is_registered; bool has_active_session; } struct Boss { - uint8 variant; uint8 level; + uint8[7] boss_variants; } diff --git a/src/RaidGeldUtils.sol b/src/RaidGeldUtils.sol index f793a44..c8da473 100644 --- a/src/RaidGeldUtils.sol +++ b/src/RaidGeldUtils.sol @@ -23,25 +23,25 @@ library RaidGeldUtils { function getBossPower(uint8 level) internal pure returns (uint256 power) { require(level <= 7, "Bosses only go to level 7"); - if (level == 0) return 9000000; // 900e4 - else if (level == 1) return 90000000; // 900e5 - else if (level == 2) return 900000000; // 900e6 - else if (level == 3) return 9000000000; // 900e7 - else if (level == 4) return 90000000000; // 900e8 - else if (level == 5) return 900000000000; // 900e9 - else if (level == 6) return 9000000000000; // 900e10 + if (level == 0) return 9000000; + else if (level == 1) return 90000000; + else if (level == 2) return 900000000; + else if (level == 3) return 9000000000; + else if (level == 4) return 90000000000; + else if (level == 5) return 900000000000; + else if (level == 6) return 9000000000000; } function getBossCumulativeChance(uint8 level) internal pure returns (uint256 chance) { // for boss chances (percent) [99, 89, 80, 70, 62, 51, 40] // where cumulative chance is in the form of 18 precision related to 1e18 require(level <= 7, "Bosses only go to level 7"); - if (level == 0) return 99e16; - else if (level == 1) return 8811e14; - else if (level == 2) return 7048e14; - else if (level == 3) return 493416e12; - else if (level == 4) return 30591792e10; - else if (level == 5) return 1560181392e8; + if (level == 0) return 99e16; + else if (level == 1) return 8811e14; + else if (level == 2) return 7048e14; + else if (level == 3) return 493416e12; + else if (level == 4) return 30591792e10; + else if (level == 5) return 1560181392e8; else if (level == 6) return 6240725568e7; } @@ -82,11 +82,7 @@ library RaidGeldUtils { } // Calculates whether user survives the fight - function calculateBossFight(uint8 bossLevel, uint256 geldBurnt, uint256 prevrandao) - internal - pure - returns (bool) - { + function calculateBossFight(uint8 bossLevel, uint256 geldBurnt, uint256 prevrandao) internal pure returns (bool) { uint256 bossPower = getBossPower(bossLevel); require(geldBurnt <= bossPower, "Cant try to defeat boss with more than what boss power is"); uint256 random_n = random(prevrandao, 1, 100); @@ -97,6 +93,19 @@ library RaidGeldUtils { return roll >= bossPower; } + function generate_boss_variants(uint256 prevrandao) internal pure returns (uint8[7] memory boss_variants) { + // We shuffle the possible variants so each run is a bit different + uint8[6] memory array = [0, 1, 2, 3, 4, 5]; + for (uint256 i = array.length - 1; i > 0; i--) { + // generate a pseudo-random index based on the prevrandao + uint256 j = uint256(keccak256(abi.encodePacked(prevrandao, i))) % (i + 1); + // swap elements at i and j + (array[i], array[j]) = (array[j], array[i]); + } + // Last boss is always the same old super Moloch + return [array[0], array[1], array[2], array[3], array[4], array[5], 6]; + } + // TODO: Implement actual randomness function random(uint256 prevrandao, uint256 min, uint256 max) internal pure returns (uint256) { // returns 0 - 100 diff --git a/test/RaidGeld.t.sol b/test/RaidGeld.t.sol index b58297c..c0bea26 100644 --- a/test/RaidGeld.t.sol +++ b/test/RaidGeld.t.sol @@ -42,7 +42,7 @@ contract raid_geldTest is Test, Constants { function fundAccount(address _acc) private { vm.deal(_acc, 10 ether); - stdstore.target(DAO_TOKEN).sig("balanceOf(address)").with_key(_acc).checked_write(100 ether); + stdstore.target(DAO_TOKEN).sig("balanceOf(address)").with_key(_acc).checked_write(1000 ether); } function registerPlayer() private {