Advertisement
Guest User

Untitled

a guest
Jun 27th, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.88 KB | None | 0 0
  1. // *** main.rs
  2. use std::fmt;
  3. use std::cmp::Ordering;
  4.  
  5. fn main() {
  6. // ONLY CHANGE THINGS BELOW THIS LINE
  7. let champion_number = 11; // e.g. 5 for Kenny, 10 for Felice
  8. let pet_number = 10; // e.g. 4 for Lake Lizard, 7 for Elephant Fighter
  9. let pet_level = 2;
  10. let arena_league = League::Gold; // e.g. Bronze, Silver, Gold, Diamond
  11. let arena_division = 1;
  12. let arena_battle = 1;
  13. // ONLY CHANGE THINGS ABOVE THIS LINE
  14.  
  15. let champion = Champion::build_champion(champion_number);
  16. println!("\n*** Champion stats:");
  17. champion.print_stats();
  18.  
  19. let base_pet = Pet::build_pet(champion.multiplier, pet_number, pet_level);
  20. println!("\n*** Base pet stats:");
  21. base_pet.print_stats();
  22.  
  23. let arena = Arena::new(arena_league, arena_division, arena_battle);
  24. println!("\n*** Arena:");
  25. arena.print_stats();
  26.  
  27. let enemy = arena.get_enemy();
  28. println!("\n*** Enemy stats:");
  29. enemy.print_stats();
  30.  
  31. println!("\n*** Optimising pets:");
  32. let bps = arena.get_bps();
  33. println!("{} BPs available to spend", bps);
  34. let upgraded_pets = PetUpgrader::get_possible_upgraded_pets(&base_pet, bps);
  35. println!(
  36. "Found {} possible upgraded pets to check",
  37. upgraded_pets.len()
  38. );
  39.  
  40. println!("\n*** Optimising battles...");
  41. optimise_battles(&upgraded_pets, &enemy);
  42. }
  43.  
  44. fn optimise_battles(pets: &[Pet], enemy: &Enemy) {
  45. // Try with different combinations of potions in order: ATK & DEF, DEF only, ATK only, neither
  46. let potion_configs = vec![(true, true), (false, true), (true, false), (false, false)];
  47.  
  48. // Try with the first potion config (majority of cases)
  49. let battle = Battle::new(potion_configs[0].0, potion_configs[0].1);
  50. let result = battle.get_best_result(pets, enemy);
  51. if result.0 > 0.25 {
  52. // We are done
  53. display_result(potion_configs[0].0, potion_configs[0].1, result);
  54. return;
  55. }
  56.  
  57. // Now we need to loop through the other potion configs
  58. let mut prev_result = result;
  59. for x in 1..4 {
  60. // Try this potion configuration
  61. let battle = Battle::new(potion_configs[x].0, potion_configs[x].1);
  62. let result = battle.get_best_result(pets, enemy);
  63. if result.0 > 0.25 {
  64. // We are done - show the previous result
  65. display_result(
  66. potion_configs[x - 1].0,
  67. potion_configs[x - 1].1,
  68. prev_result,
  69. );
  70. return;
  71. }
  72.  
  73. // This is the best yet
  74. prev_result = result;
  75. }
  76.  
  77. // Display the last result
  78. display_result(potion_configs[3].0, potion_configs[3].1, prev_result);
  79. }
  80.  
  81. fn display_result(use_atk_potion: bool, use_def_potion: bool, result: (f32, &Pet)) {
  82. println!("Use ATK potion : {}", use_atk_potion);
  83. println!("Use DEF potion : {}", use_def_potion);
  84. println!("HP potions reqd : {:.1}", result.0);
  85. println!("Optimal pet : {}", result.1.name);
  86. }
  87.  
  88. // *** lib.rs
  89. fn print_midas_number(number: f32) -> String {
  90. if number <= 0.0 {
  91. number.to_string()
  92. } else {
  93. let multiplier = number.log(1000.0).floor() as i32;
  94. let fraction = number / 1000.0_f32.powi(multiplier);
  95.  
  96. let suffix = match multiplier {
  97. 0 => "",
  98. 1 => " K",
  99. 2 => " M",
  100. 3 => " B",
  101. 4 => " T",
  102. 5 => " Qa",
  103. 6 => " Qi",
  104. 7 => " Sx",
  105. 8 => " Sp",
  106. 9 => " Oc",
  107. 10 => " No",
  108. _ => panic!("Number too big {}", number),
  109. };
  110.  
  111. format!("{:6.2}{}", fraction, suffix)
  112. }
  113. }
  114.  
  115. // *** champion.rs
  116. pub struct Champion {
  117. pub name: String,
  118. pub multiplier: f32,
  119. }
  120.  
  121. impl Champion {
  122. pub fn build_champion(champion_number: i32) -> Champion {
  123. Champion {
  124. name: Champion::get_name_for_number(champion_number),
  125. multiplier: Champion::get_multiplier_for_number(champion_number),
  126. }
  127. }
  128.  
  129. pub fn print_stats(&self) {
  130. println!("{}", self.name);
  131. println!(
  132. "Multiplier : {} (+{}%)",
  133. self.multiplier,
  134. (self.multiplier - 1.0) * 100.0
  135. );
  136. }
  137.  
  138. fn get_name_for_number(champion_number: i32) -> String {
  139. match champion_number {
  140. 1 => "Gilligan",
  141. 2 => "Audrey",
  142. 3 => "Scarlet",
  143. 4 => "Irwin",
  144. 5 => "Kenny",
  145. 6 => "Adeline",
  146. 7 => "Valeria",
  147. 8 => "Aurelius",
  148. 9 => "Felix",
  149. 10 => "Felice",
  150. 11 => "Tempestus",
  151. 12 => "Sylvar",
  152. 13 => "Benedict",
  153. 14 => "Lin",
  154. 15 => "Volv",
  155. _ => panic!("Unknown champion_number: {}", champion_number),
  156. }.to_string()
  157. }
  158.  
  159. fn get_multiplier_for_number(champion_number: i32) -> f32 {
  160. match champion_number {
  161. 1 | 2 => 1.0,
  162. 3 => 1.5,
  163. 4 => 3.1,
  164. 5 => 4.6,
  165. 6 => 6.3,
  166. 7 => 8.7,
  167. 8 => 12.2,
  168. 9 => 18.0,
  169. 10 => 27.0,
  170. 11 => 40.8,
  171. 12 => 59.2,
  172. 13 => 90.4,
  173. 14 => 541.0,
  174. 15 => 3201.0,
  175. _ => panic!("Unknown champion_number: {}", champion_number),
  176. }
  177. }
  178. }
  179.  
  180. // *** pet.rs
  181. pub struct Pet {
  182. pub name: String,
  183. pub health: f32,
  184. pub attack: f32,
  185. pub defence: f32,
  186. pub lifesteal: f32,
  187. pub block: f32,
  188. pub reflect: f32,
  189. }
  190.  
  191. impl Pet {
  192. pub fn build_pet(champion_multiplier: f32, pet_number: i32, pet_level: i32) -> Pet {
  193. let pet_multiplier = 6_f32.powi(pet_number - 1) * (1.0 + 0.2 * (pet_level as f32 - 1.0));
  194. let total_multiplier = champion_multiplier * pet_multiplier;
  195.  
  196. Pet {
  197. name: format!(
  198. "{} (level {})",
  199. Pet::get_name_for_number(pet_number),
  200. pet_level
  201. ),
  202. health: 720_f32 * total_multiplier,
  203. attack: 62_f32 * total_multiplier,
  204. defence: 24_f32 * total_multiplier,
  205. lifesteal: if pet_number > 1 {
  206. 51_f32 * total_multiplier
  207. } else {
  208. 0.0
  209. },
  210. block: if pet_number > 3 {
  211. 42_f32 * total_multiplier
  212. } else {
  213. 0.0
  214. },
  215. reflect: if pet_number > 6 {
  216. 54_f32 * total_multiplier
  217. } else {
  218. 0.0
  219. },
  220. }
  221. }
  222.  
  223. pub fn print_stats(&self) {
  224. println!("{}", self.name);
  225. println!("Health : {}", print_midas_number(self.health));
  226. println!("Attack : {}", print_midas_number(self.attack));
  227. println!("Defence : {}", print_midas_number(self.defence));
  228. println!("Lifesteal : {}", print_midas_number(self.lifesteal));
  229. println!("Block : {}", print_midas_number(self.block));
  230. println!("Reflect : {}", print_midas_number(self.reflect));
  231. }
  232.  
  233. fn get_name_for_number(pet_number: i32) -> String {
  234. match pet_number {
  235. 1 => "Midaeum Gardens Parrot",
  236. 2 => "Wild Mountain Boar",
  237. 3 => "Bonebreaker Python",
  238. 4 => "Lake Lizard",
  239. 5 => "Royal Eagle",
  240. 6 => "Gastonia Defender",
  241. 7 => "Elephant Fighter",
  242. 8 => "Fullmoon Werewolf",
  243. 9 => "Bloodthirsty Tiger",
  244. 10 => "Rhino of the Valley",
  245. 11 => "Flameguard Goblin",
  246. 12 => "Poisonous Hydra",
  247. 13 => "Snowmountain Yeti",
  248. 14 => "Astral Pegasus",
  249. 15 => "Swarm Soldier",
  250. 16 => "Lava Hound",
  251. 17 => "Forest Keeper",
  252. 18 => "Armored Nightmare",
  253. 19 => "Crystal Golem",
  254. 20 => "Dragon of the Void",
  255. _ => panic!("Unknown pet_number: {}", pet_number),
  256. }.to_string()
  257. }
  258. }
  259.  
  260. // *** arena.rs
  261. pub enum League {
  262. Bronze,
  263. Silver,
  264. Gold,
  265. Diamond,
  266. }
  267.  
  268. pub struct Arena {
  269. league: League,
  270. division: i32,
  271. battle: i32,
  272. }
  273.  
  274. impl Arena {
  275. pub fn new(league: League, division: i32, battle: i32) -> Arena {
  276. if division < 1 || division > 5 {
  277. panic!("Division {} not allowed", division);
  278. }
  279.  
  280. if battle < 1 || battle > Arena::get_total_battles(&league, division) {
  281. panic!("Battle {} not allowed", battle);
  282. }
  283.  
  284. Arena {
  285. league: league,
  286. division: division,
  287. battle: battle,
  288. }
  289. }
  290.  
  291. pub fn print_stats(&self) {
  292. let league_name = match self.league {
  293. League::Bronze => "Bronze",
  294. League::Silver => "Silver",
  295. League::Gold => "Gold",
  296. League::Diamond => "Diamond",
  297. };
  298. let division_name = match self.division {
  299. 1 => "I",
  300. 2 => "II",
  301. 3 => "III",
  302. 4 => "IV",
  303. 5 => "V",
  304. _ => unreachable!(),
  305. };
  306.  
  307. println!(
  308. "{} {} {} / {}",
  309. league_name,
  310. division_name,
  311. self.battle,
  312. Arena::get_total_battles(&self.league, self.division)
  313. );
  314. }
  315.  
  316. pub fn get_bps(&self) -> i32 {
  317. let mut bps = 0;
  318.  
  319. let cuumulative_division_num =
  320. Arena::get_cumulative_division_num(&self.league, self.division);
  321.  
  322. // Add BPs from complete divisions
  323. for div in 1..cuumulative_division_num {
  324. bps += 2 * div * (div + 3);
  325. }
  326.  
  327. // Add BPs from complete battles in this division
  328. bps += (self.battle - 1) * cuumulative_division_num;
  329.  
  330. bps
  331. }
  332.  
  333. pub fn get_enemy(&self) -> Enemy {
  334. let all_enemy_healths =
  335. vec![vec![640.0, 988.0, 1270.0, 1600.0, 4500.0],
  336. vec![6000.0, 8500.0, 10500.0, 13000.0, 15000.0, 30000.0],
  337. vec![60000.0, 80000.0, 110000.0, 130000.0, 150000.0, 165000.0, 300000.0],
  338. vec![6e5, 1e6, 1.2e6, 1.3e6, 1.4e6, 1.6e6, 1.9e6, 4.2e6],
  339. vec![7.2e6, 9.2e6, 1.3e7, 1.4e7, 1.5e7, 1.6e7, 1.7e7, 1.9e7, 4.3e7],
  340. vec![1.2e8, 1.3e8, 1.5e8, 1.6e8, 1.8e8, 2.1e8, 2.3e8, 2.5e8, 3e8, 6.3e8],
  341. vec![1e9, 1.1e9, 1.2e9, 1.5e9, 1.7e9, 1.8e9, 2e9, 2.3e9, 2.8e9, 3e9, 6.2e9],
  342. vec![1e10, 1.1e10, 1.2e10, 1.5e10, 1.7e10, 1.8e10, 2e10, 2.3e10, 2.5e10, 2.7e10, 2.8e10, 6.8e10],
  343. vec![1e11, 1.1e11, 1.2e11, 1.3e11, 1.5e11, 1.7e11, 1.8e11, 2e11, 2.2e11, 2.3e11, 2.7e11, 3e11, 5e11],
  344. vec![6e11, 6.5e11, 7e11, 8.3e11, 9e11, 1e12, 1.1e12, 1.2e12, 1.4e12, 1.5e12, 1.6e12, 1.7e12, 1.9e12, 4e12],
  345. vec![5e12, 5.5e12, 6e12, 6.5e12, 7e12, 7.5e12, 8.5e12, 9e12, 1e13, 1.1e13, 1.3e13, 1.4e13, 1.5e13, 1.7e13, 3.7e13],
  346. vec![4e13, 4.5e13, 5e13, 5.5e13, 7e13, 7.5e13, 8e13, 8.5e13, 9e13, 9.5e14, 1e14, 1.05e14, 1.1e14, 1.12e14, 1.15e14, 2e14],
  347. vec![2.1e14, 2.2e14, 2.3e14, 2.4e14, 2.6e14, 2.8e14, 3e14, 3.5e14, 3.8e14, 4.4e14, 4.6e14, 4.8e14, 5.2e14, 5.4e14, 6.05e14, 6.9e14, 1.3e15],
  348. vec![1.7e15, 2.2e15, 2.3e15, 2.7e15, 3.6e15, 4e15, 4.5e15, 4.8e15, 4.9e15, 5e15, 5.1e15, 5.2e15, 5.3e15, 5.4e15, 5.5e15, 5.6e15, 6.1e15, 1.3e16],
  349. vec![2e16, 2.2e16, 2.3e16, 2.4e16, 2.5e16, 2.7e16, 2.8e16, 2.9e16, 3.1e16, 3.4e16, 3.6e16, 4.0e16, 4.3e16, 4.6e16, 4.8e16, 5.0e16, 5.5e16, 5.7e16, 1.4e17],
  350. vec![2e17, 2.2e17, 2.3e17, 2.4e17, 2.5e17, 2.6e17, 2.7e17, 2.8e17, 2.9e17, 3e17, 3.4e17, 3.6e17, 3.9e17, 4.5e17, 4.7e17, 5.4e17, 5.8e17, 6.4e17, 6.7e17, 1.2e18],
  351. vec![1.8e18, 1.9e18, 2e18, 2.2e18, 2.3e18, 2.4e18, 2.5e18, 2.6e18, 2.7e18, 2.8e18, 2.9e18, 3e18, 3.3e18, 3.4e18, 3.9e18, 4e18, 4.4e18, 4.8e18, 5.5e18, 6.6e18, 1.7e19],
  352. vec![2e19, 2.2e19, 2.4e19, 2.6e19, 2.8e19, 3e19, 3.3e19, 3.5e19, 3.9e19, 4.4e19, 4.6e19, 4.7e19, 5e19, 5.5e19, 6e19, 6.5e19, 7.5e19, 8e19, 8.5e19, 9e19, 9.5e19, 2e20],
  353. vec![2.1e20, 2.2e20, 2.3e20, 2.4e20, 2.5e20, 2.6e20, 2.7e20, 2.8e20, 2.9e20, 3e20, 3.1e20, 3.2e20, 3.3e20, 3.4e20, 3.5e20, 3.6e20, 3.7e20, 3.8e20, 3.9e20, 4e20, 4.1e20, 4.2e20, 6.1e20],
  354. vec![6.5e20, 6.8e20, 7.2e20, 7.4e20, 7.6e20, 7.8e20, 8e20, 8.2e20, 8.4e20, 8.6e20, 8.8e20, 9e20, 9.2e20, 9.4e20, 9.8e20, 1e21, 1.05e21, 1.1e21, 1.2e21, 1.3e21, 1.35e21, 1.4e21, 1.5e21, 2.4e21]];
  355.  
  356. let cuumulative_division_num =
  357. Arena::get_cumulative_division_num(&self.league, self.division);
  358. let enemy_health =
  359. all_enemy_healths[(cuumulative_division_num - 1) as usize][(self.battle - 1) as usize];
  360.  
  361. Enemy::build_enemy(self.battle, enemy_health)
  362. }
  363.  
  364. fn get_cumulative_division_num(league: &League, division: i32) -> i32 {
  365. let league_num = match *league {
  366. League::Bronze => 0,
  367. League::Silver => 1,
  368. League::Gold => 2,
  369. League::Diamond => 3,
  370. };
  371. 5 * league_num + division
  372. }
  373.  
  374. fn get_total_battles(league: &League, division: i32) -> i32 {
  375. Arena::get_cumulative_division_num(league, division) + 4
  376. }
  377. }
  378.  
  379. // *** enemy.rs
  380. pub struct Enemy {
  381. pub name: String,
  382. pub health: f32,
  383. pub damage: f32,
  384. }
  385.  
  386. impl Enemy {
  387. pub fn build_enemy(enemy_number: i32, health: f32) -> Enemy {
  388. Enemy {
  389. name: Enemy::get_name_for_number(enemy_number),
  390. health: health,
  391. damage: health / 8.0,
  392. }
  393. }
  394.  
  395. pub fn print_stats(&self) {
  396. println!("{}", self.name);
  397. println!("Health : {}", print_midas_number(self.health));
  398. }
  399.  
  400. fn get_name_for_number(enemy_number: i32) -> String {
  401. match enemy_number {
  402. 1 => "Cave Bug",
  403. 2 => "Sharpbeak",
  404. 3 => "Great Tarantula",
  405. 4 => "Tunnel Minion",
  406. 5 => "Goblin Gladiator",
  407. 6 => "Desert Scorpion",
  408. 7 => "Eyeball Terror",
  409. 8 => "Seashore Goblin",
  410. 9 => "Robotic Gatekeeper",
  411. 10 => "Swarm Beast",
  412. 11 => "Ancient Cyclops",
  413. 12 => "Valhalla Devourer",
  414. 13 => "Druid Hermit",
  415. 14 => "Alien Insect",
  416. 15 => "Fearless Zombie",
  417. 16 => "Mountain Troll King",
  418. 17 => "Undead Warrior",
  419. 18 => "Orc Overlord",
  420. 19 => "Lava Annihilator",
  421. 20 => "The Unbreakable",
  422. 21 => "Evil Shaman",
  423. 22 => "Soul Drainer",
  424. 23 => "Underworld Soulkeeper",
  425. 24 => "Shadow King",
  426. _ => panic!("Unknown enemy_number: {}", enemy_number),
  427. }.to_string()
  428. }
  429. }
  430.  
  431. // *** pet_upgrader.rs
  432. pub struct PetUpgrader {}
  433.  
  434. impl PetUpgrader {
  435. pub fn get_possible_upgraded_pets(pet: &Pet, battle_points: i32) -> Vec<Pet> {
  436. let upgrades = PetUpgradeGenerator::get_possible_upgrades(pet, battle_points);
  437. upgrades
  438. .iter()
  439. .map(|u| PetUpgrader::upgrade_pet(pet, u))
  440. .collect()
  441. }
  442.  
  443. fn upgrade_pet(base_pet: &Pet, upgrade: &PetUpgrade) -> Pet {
  444. Pet {
  445. name: format!("{} - upgraded with {}", base_pet.name, upgrade),
  446. health: base_pet.health * (1.0 + 0.1 * upgrade.upgrades[0] as f32),
  447. attack: base_pet.attack * (1.0 + 0.1 * upgrade.upgrades[1] as f32),
  448. defence: base_pet.defence * (1.0 + 0.1 * upgrade.upgrades[2] as f32),
  449. lifesteal: base_pet.lifesteal * (1.0 + 0.1 * upgrade.upgrades[3] as f32),
  450. block: base_pet.block * (1.0 + 0.1 * upgrade.upgrades[4] as f32),
  451. reflect: base_pet.reflect * (1.0 + 0.1 * upgrade.upgrades[5] as f32),
  452. }
  453. }
  454. }
  455.  
  456. #[derive(Debug, Clone)]
  457. struct PetUpgrade {
  458. upgrades: [i32; 6],
  459. }
  460.  
  461. impl fmt::Display for PetUpgrade {
  462. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  463. write!(
  464. f,
  465. "(H:{}, A:{}, D:{}, L:{}, B:{}, R:{})",
  466. self.upgrades[0],
  467. self.upgrades[1],
  468. self.upgrades[2],
  469. self.upgrades[3],
  470. self.upgrades[4],
  471. self.upgrades[5]
  472. )
  473. }
  474. }
  475.  
  476. struct PetUpgradeGenerator {}
  477.  
  478. impl PetUpgradeGenerator {
  479. fn get_possible_upgrades(pet: &Pet, battle_points: i32) -> Vec<PetUpgrade> {
  480. let mut max_depth = 5;
  481. if pet.reflect == 0.0 {
  482. max_depth = 4;
  483. }
  484. if pet.block == 0.0 {
  485. max_depth = 3;
  486. }
  487. if pet.lifesteal == 0.0 {
  488. max_depth = 2;
  489. }
  490. let (prespend_level, prespend_cost) = PetUpgradeGenerator::get_prespend(battle_points);
  491. let total_prespend_cost = 2 * prespend_cost;
  492. if total_prespend_cost > 0 {
  493. println!("Prespending {} BPs", total_prespend_cost);
  494. }
  495. let pet_upgrade = PetUpgrade {
  496. upgrades: [prespend_level, prespend_level, 0, 0, 0, 0],
  497. };
  498. PetUpgradeGenerator::generate_upgrades(
  499. &pet_upgrade,
  500. battle_points - total_prespend_cost,
  501. 0,
  502. max_depth,
  503. )
  504. }
  505.  
  506. fn get_prespend(battle_points: i32) -> (i32, i32) {
  507. // No prespend for low BPs
  508. if battle_points < 300 {
  509. return (0, 0);
  510. }
  511.  
  512. // Spend upto a quarter or a third of the BPs
  513. let max_prespend = battle_points / if battle_points < 1000 { 4 } else { 3 };
  514. let mut level = 0;
  515. let mut cost = 0;
  516. loop {
  517. let upgrade_cost = PetUpgradeGenerator::get_upgrade_cost(level);
  518. if cost + upgrade_cost > max_prespend {
  519. return (level, cost);
  520. }
  521. level += 1;
  522. cost += upgrade_cost;
  523. }
  524. }
  525.  
  526. fn generate_upgrades(
  527. pet_upgrade: &PetUpgrade,
  528. battle_points: i32,
  529. depth: usize,
  530. max_depth: usize,
  531. ) -> Vec<PetUpgrade> {
  532. if depth == max_depth {
  533. // Just fill it up
  534. let mut pet_upgrade = pet_upgrade.clone();
  535. let mut battle_points = battle_points;
  536. loop {
  537. let cost = PetUpgradeGenerator::get_upgrade_cost(pet_upgrade.upgrades[depth]);
  538. if cost > battle_points {
  539. break;
  540. }
  541. pet_upgrade.upgrades[depth] += 1;
  542. battle_points -= cost;
  543. }
  544.  
  545. // Need to check that we wouldn't have covered this case before
  546. for i in 0..max_depth {
  547. let cost = PetUpgradeGenerator::get_upgrade_cost(pet_upgrade.upgrades[i]);
  548. if cost <= battle_points {
  549. return vec![];
  550. }
  551. }
  552.  
  553. return vec![pet_upgrade];
  554. }
  555.  
  556. let mut pet_upgrades = vec![];
  557. let mut pet_upgrade = pet_upgrade.clone();
  558. let mut battle_points = battle_points;
  559. loop {
  560. for pu in PetUpgradeGenerator::generate_upgrades(
  561. &pet_upgrade,
  562. battle_points,
  563. depth + 1,
  564. max_depth,
  565. ) {
  566. pet_upgrades.push(pu);
  567. }
  568.  
  569. let cost = PetUpgradeGenerator::get_upgrade_cost(pet_upgrade.upgrades[depth]);
  570. if cost > battle_points {
  571. break;
  572. }
  573. pet_upgrade.upgrades[depth] += 1;
  574. battle_points -= cost;
  575. }
  576. pet_upgrades
  577. }
  578.  
  579. fn get_upgrade_cost(current_level: i32) -> i32 {
  580. if current_level < 10 {
  581. current_level + 1
  582. } else {
  583. current_level + 1 + PetUpgradeGenerator::get_upgrade_cost(current_level - 10)
  584. }
  585. }
  586. }
  587.  
  588. // *** battle.rs
  589. pub struct Battle {
  590. pub use_attack_potion: bool,
  591. pub use_defence_potion: bool,
  592. }
  593.  
  594. impl Battle {
  595. pub fn new(use_attack_potion: bool, use_defence_potion: bool) -> Battle {
  596. Battle {
  597. use_attack_potion: use_attack_potion,
  598. use_defence_potion: use_defence_potion,
  599. }
  600. }
  601.  
  602. pub fn get_best_result<'a>(&self, pets: &'a [Pet], enemy: &Enemy) -> (f32, &'a Pet) {
  603. let results_by_pet = pets.iter().map(|p| (self.do_battle(p, enemy), p)).collect::<Vec<_>>();
  604. let best_result = results_by_pet.iter().min_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal)).unwrap();
  605.  
  606. (if best_result.0 < 0.0 {0.0} else {best_result.0}, best_result.1)
  607. }
  608.  
  609. fn do_battle(&self, pet: &Pet, enemy: &Enemy) -> f32 {
  610. let pet_hp = pet.health;
  611. let enemy_hp = enemy.health;
  612. let potion_hp = 0.25 * pet.health;
  613.  
  614. let attack_adjust = if self.use_attack_potion { 1.5 } else { 1.0 };
  615. let defence_adjust = if self.use_defence_potion { 0.5 } else { 1.0 };
  616.  
  617. // Apply ATTACK
  618. let mut pet_attack_per_round = attack_adjust * pet.attack;
  619.  
  620. // Apply LIFESTEAL
  621. let mut enemy_attack_per_round = -0.25 * pet.lifesteal;
  622.  
  623. // Apply DEFENCE
  624. enemy_attack_per_round += defence_adjust * (enemy.damage * 1.05 - pet.defence);
  625.  
  626. // Apply BLOCK
  627. enemy_attack_per_round -= 0.3 * pet.block;
  628.  
  629. // Apply REFLECT
  630. pet_attack_per_round += 0.3 * pet.reflect;
  631.  
  632. // Compute end of battle stats
  633. let battle_rounds = (enemy_hp / pet_attack_per_round).ceil();
  634. let pet_hp_after_battle = pet_hp - battle_rounds * enemy_attack_per_round;
  635.  
  636. -pet_hp_after_battle / potion_hp
  637. }
  638. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement