use std::ops::{Add, AddAssign};
use smallvec::{SmallVec, smallvec, ToSmallVec};
use crate::world::Player;
#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub struct Orbs {
pub health: f32,
pub energy: f32,
}
impl Add for Orbs {
type Output = Orbs;
fn add(self, other: Orbs) -> Orbs {
Orbs {
health: self.health + other.health,
energy: self.energy + other.energy,
}
}
}
impl AddAssign for Orbs {
fn add_assign(&mut self, other: Orbs) {
*self = *self + other;
}
}
impl Orbs {
pub fn heal(&mut self, amount: f32, player: &Player) {
self.health = (self.health + amount).min(player.max_health());
}
pub fn recharge(&mut self, amount: f32, player: &Player) {
self.energy = (self.energy + amount).min(player.max_energy());
}
}
pub fn either(a: &[Orbs], b: &[Orbs]) -> SmallVec<[Orbs; 3]> {
if b.is_empty() || a.is_empty() {
smallvec![Orbs::default()]
} else {
let mut sum: SmallVec<[Orbs; 3]> = a.to_smallvec();
for b_ in b {
let mut used = false;
for a_ in &mut sum {
if b_.energy >= a_.energy && b_.health >= a_.health {
*a_ = *b_;
used = true;
}
}
if !used && sum.iter().all(|a_| a_.energy < b_.energy) || sum.iter().all(|a_| a_.health < b_.health) {
sum.push(*b_);
}
}
sum
}
}
pub fn either_single(a: &[Orbs], b: Orbs) -> SmallVec<[Orbs; 3]> {
if a.is_empty() {
smallvec![Orbs::default()]
} else {
let mut sum: SmallVec<[Orbs; 3]> = a.to_smallvec();
let mut used = false;
for a_ in &mut sum {
if b.energy >= a_.energy && b.health >= a_.health {
*a_ = b;
used = true;
}
}
if !used && sum.iter().all(|a_| a_.energy < b.energy) || sum.iter().all(|a_| a_.health < b.health) {
sum.push(b);
}
sum
}
}
pub fn both(a: &[Orbs], b: &[Orbs]) -> SmallVec<[Orbs; 3]> {
if b.is_empty() {
a.to_smallvec()
} else if a.is_empty() {
b.to_smallvec()
} else {
let mut product = SmallVec::<[Orbs; 3]>::with_capacity(a.len());
for a_ in a {
for b_ in b {
let orbs = *a_ + *b_;
if !product.contains(&orbs) {
product.push(orbs);
}
}
}
product.iter().filter(|orbs| {
!product.iter().any(|other| other.energy > orbs.energy && other.health >= orbs.health || other.energy >= orbs.energy && other.health > orbs.health)
}).copied().collect()
}
}
pub fn both_single(a: &[Orbs], b: Orbs) -> SmallVec<[Orbs; 3]> {
if a.is_empty() {
smallvec![b]
} else {
let mut product = SmallVec::<[Orbs; 3]>::with_capacity(a.len());
for a_ in a {
let orbs = *a_ + b;
if !product.contains(&orbs) {
product.push(orbs);
}
}
product.iter().filter(|orbs| {
!product.iter().any(|other| other.energy > orbs.energy && other.health >= orbs.health || other.energy >= orbs.energy && other.health > orbs.health)
}).copied().collect()
}
}