diff --git a/server/src/instance.rs b/server/src/instance.rs index da16a67e..dcb0eb16 100644 --- a/server/src/instance.rs +++ b/server/src/instance.rs @@ -212,7 +212,7 @@ impl Instance { .iter() .filter(|p| round.player_ids.contains(&p.id) && p.bot) .count() == 2 { - println!("should play a game between {:?}", round.player_ids); + // println!("should play a game between {:?}", round.player_ids); let a = self.players.clone().into_iter().find(|p| p.id == round.player_ids[0]).unwrap(); let b = self.players.clone().into_iter().find(|p| p.id == round.player_ids[1]).unwrap(); @@ -529,7 +529,7 @@ mod tests { assert!(instance.vbox_phase_finished()); instance.games_phase_start(); - println!("{:#?}", instance); + // println!("{:#?}", instance); assert!(instance.games_phase_finished()); } diff --git a/server/src/vbox.rs b/server/src/vbox.rs index 733f3fa8..dc9921ef 100644 --- a/server/src/vbox.rs +++ b/server/src/vbox.rs @@ -17,7 +17,7 @@ use skill::{Skill}; use spec::{Spec}; use player::{Player, player_get, player_update}; -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq,PartialOrd,Ord,Eq)] pub enum Var { // colours Blue, @@ -81,38 +81,28 @@ enum VarEffect { } impl Var { - fn is_base(&self) -> bool { + fn cost(&self) -> u16 { match self { - Var::Attack | - Var::Block | - Var::Stun | - Var::Debuff | - Var::Buff => true, + Var::Red => 1, + Var::Green => 1, + Var::Blue => 1, - Var::Hp | - Var::Damage => true, + Var::Attack => 2, + Var::Block => 2, + Var::Buff => 2, + Var::Debuff => 2, + Var::Stun => 2, - _ => false, - } - } + Var::Damage => 3, + Var::Hp => 3, + Var::Speed => 3, - fn cost(&self) -> Result { - match self { - Var::Red => Ok(1), - Var::Green => Ok(1), - Var::Blue => Ok(1), - - Var::Attack => Ok(2), - Var::Block => Ok(2), - Var::Buff => Ok(2), - Var::Debuff => Ok(2), - Var::Stun => Ok(2), - - Var::Damage => Ok(3), - Var::Hp => Ok(3), - Var::Speed => Ok(3), - - _ => Err(err_msg("var not purchasable")), + _ => { + let combos = get_combos(); + let combo = combos.iter().find(|c| c.1 == *self) + .unwrap_or_else(|| panic!("unable to find components for {:?}", self)); + return combo.0.iter().fold(0, |acc, c| acc + c.cost()); + }, } } @@ -177,14 +167,61 @@ impl Var { } } -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -enum ColourCode { - RR, - GG, - BB, - RG, - BR, - GB, +fn get_combos() -> Vec<(Vec, Var)> { + let mut combinations = vec![ + (vec![Var::Attack, Var::Red, Var::Red] , Var::Strike ), + (vec![Var::Attack, Var::Green, Var::Green] , Var::Heal ), + (vec![Var::Attack, Var::Blue, Var::Blue] , Var::Blast ), + (vec![Var::Attack, Var::Red, Var::Green] , Var::Strike ), + (vec![Var::Attack, Var::Green, Var::Blue] , Var::Heal ), + (vec![Var::Attack, Var::Red, Var::Blue] , Var::Blast ), + + (vec![Var::Block, Var::Red, Var::Red] , Var::Parry ), + (vec![Var::Block, Var::Green, Var::Green] , Var::Reflect ), + (vec![Var::Block, Var::Blue, Var::Blue] , Var::Toxic ), + (vec![Var::Block, Var::Red, Var::Green] , Var::Taunt ), + (vec![Var::Block, Var::Green, Var::Blue] , Var::Shield ), + // (vec![Var::Block, Var::Red, Var::Blue] , Var::Blast), + + (vec![Var::Buff, Var::Red, Var::Red] , Var::Empower), + (vec![Var::Buff, Var::Green, Var::Green] , Var::Triage), + (vec![Var::Buff, Var::Blue, Var::Blue] , Var::Amplify), + (vec![Var::Buff, Var::Red, Var::Green] , Var::Clutch), + // (vec![Var::Buff, Var::Green, Var::Blue] , Var::Heal), + (vec![Var::Buff, Var::Red, Var::Blue] , Var::Haste), + + (vec![Var::Debuff, Var::Red, Var::Red] , Var::Snare), + (vec![Var::Debuff, Var::Green, Var::Green] , Var::Purge), + (vec![Var::Debuff, Var::Blue, Var::Blue] , Var::Curse), + // (vec![Var::Debuff, Var::Red, Var::Green] , Var::Siphon), + (vec![Var::Debuff, Var::Green, Var::Blue] , Var::Siphon), + (vec![Var::Debuff, Var::Red, Var::Blue] , Var::Slow), + + (vec![Var::Stun, Var::Red, Var::Red] , Var::Strangle), + (vec![Var::Stun, Var::Green, Var::Green] , Var::Throw), + (vec![Var::Stun, Var::Blue, Var::Blue] , Var::Ruin), + // (vec![Var::Stun, Var::Red, Var::Green] , Var::Strike), + (vec![Var::Stun, Var::Green, Var::Blue] , Var::Silence), + (vec![Var::Stun, Var::Red, Var::Blue] , Var::Hex), + + (vec![Var::Damage, Var::Red, Var::Red] , Var::RedDamageI), + (vec![Var::Damage, Var::Green, Var::Green] , Var::GreenDamageI), + (vec![Var::Damage, Var::Blue, Var::Blue] , Var::BlueDamageI), + // (vec![Var::Damage, Var::Red, Var::Green] , Var::Strike), + // (vec![Var::Damage, Var::Green, Var::Blue] , Var::Silence), + // (vec![Var::Damage, Var::Red, Var::Blue] , Var::Hex), + + (vec![Var::Hp, Var::Red, Var::Red] , Var::RedShieldI), + (vec![Var::Hp, Var::Green, Var::Green] , Var::LifeI), + (vec![Var::Hp, Var::Blue, Var::Blue] , Var::BlueShieldI), + (vec![Var::Hp, Var::Red, Var::Green] , Var::LRSI), + (vec![Var::Hp, Var::Green, Var::Blue] , Var::LBSI), + (vec![Var::Hp, Var::Red, Var::Blue] , Var::RBSI), + ]; + + combinations.iter_mut().for_each(|set| set.0.sort_unstable()); + + return combinations; } #[derive(Debug,Clone,Serialize,Deserialize)] @@ -289,7 +326,7 @@ impl Vbox { .get(j).ok_or(format_err!("no var at index {:?}", j))?; // check can purchase - let cost = self.free[i][j].cost()?; + let cost = self.free[i][j].cost(); self.balance_sub(cost)?; // actually move @@ -301,9 +338,9 @@ impl Vbox { pub fn drop(&mut self, i: usize) -> Result<&mut Vbox, Error> { self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?; let dropped = self.bound.remove(i); - - // calculate total cost - // self.balance_add(dropped.cost()?); + let refund = dropped.cost(); + println!("refunding {:?} for {:?}", refund, dropped); + self.balance_add(refund); Ok(self) } @@ -318,8 +355,8 @@ impl Vbox { // have to sort the indices and keep track of the iteration // because when removing the elements the array shifts - indices.sort(); - let mut vars = indices + indices.sort_unstable(); + let mut input = indices .iter() .enumerate() .map(|(i, index)| { @@ -327,100 +364,13 @@ impl Vbox { }) .collect::>(); - let base_index = vars - .iter() - .position(|v| v.is_base()) - .ok_or(err_msg("no base item selected"))?; + // sort the input to align with the combinations + // combos are sorted when created + input.sort_unstable(); + let combos = get_combos(); + let combo = combos.iter().find(|c| c.0 == input).ok_or(err_msg("not a combo"))?; - let base = vars.remove(base_index); - - // fold colours into RGB - let colours = vars - .iter() - .fold([0, 0, 0], |mut acc, c| { - match c { - Var::Red => acc[0] += 1, - Var::Green => acc[1] += 1, - Var::Blue => acc[2] += 1, - _ => (), - }; - acc - }); - - let colour_code = match colours { - [2,0,0] => ColourCode::RR, - [0,2,0] => ColourCode::GG, - [0,0,2] => ColourCode::BB, - [1,1,0] => ColourCode::RG, - [0,1,1] => ColourCode::GB, - [1,0,1] => ColourCode::BR, - _ => return Err(err_msg("not a combo")), - }; - - let new = match base { - Var::Attack => match colour_code { - ColourCode::RR => Var::Strike, - ColourCode::GG => Var::Heal, - ColourCode::BB => Var::Blast, - ColourCode::RG => Var::Slay, // - ColourCode::GB => return Err(err_msg("unhandled skill combo")), - ColourCode::BR => Var::Banish, // - }, - Var::Block => match colour_code { - ColourCode::RR => Var::Parry, - ColourCode::GG => Var::Reflect, - ColourCode::BB => Var::Toxic, - ColourCode::RG => Var::Taunt, - ColourCode::GB => Var::Shield, - ColourCode::BR => return Err(err_msg("unhandled skill combo")), - }, - Var::Buff => match colour_code { - ColourCode::RR => Var::Empower, - ColourCode::GG => Var::Triage, - ColourCode::BB => Var::Amplify, - ColourCode::RG => Var::Clutch, - ColourCode::GB => return Err(err_msg("unhandled skill combo")), - ColourCode::BR => Var::Haste, - }, - Var::Debuff => match colour_code { - ColourCode::RR => Var::Snare, - ColourCode::GG => Var::Purge, - ColourCode::BB => Var::Curse, - ColourCode::RG => return Err(err_msg("unhandled skill combo")), - ColourCode::GB => Var::Siphon, - ColourCode::BR => Var::Slow, - }, - Var::Stun => match colour_code { - ColourCode::RR => Var::Strangle, - ColourCode::GG => Var::Throw, - ColourCode::BB => Var::Ruin, - ColourCode::RG => return Err(err_msg("unhandled skill combo")), - ColourCode::GB => Var::Silence, - ColourCode::BR => Var::Hex, - }, - - // SPECS - Var::Damage => match colour_code { - ColourCode::RR => Var::RedDamageI, - ColourCode::GG => Var::GreenDamageI, - ColourCode::BB => Var::BlueDamageI, - ColourCode::RG => return Err(err_msg("unhandled skill combo")), - ColourCode::GB => return Err(err_msg("unhandled skill combo")), - ColourCode::BR => return Err(err_msg("unhandled skill combo")), - }, - Var::Hp => match colour_code { - ColourCode::RR => Var::RedShieldI, - ColourCode::GG => Var::LifeI, - ColourCode::BB => Var::BlueShieldI, - ColourCode::RG => Var::LRSI, - ColourCode::GB => Var::LBSI, - ColourCode::BR => Var::RBSI, - }, - - _ => panic!("wrong base {:?}", base), - }; - - self.bound.push(new); + self.bound.push(combo.1); Ok(self) } @@ -493,4 +443,25 @@ mod tests { vbox.combine(vec![1,2,0]).unwrap(); assert_eq!(vbox.bound[0], Var::Heal); } + + #[test] + fn combos_test() { + let mut input = vec![Var::Green, Var::Attack, Var::Green]; + let combos = get_combos(); + + // sort input so they align + input.sort_unstable(); + + let combo = combos.iter().find(|c| c.0 == input); + assert!(combo.is_some()); + } + + #[test] + fn drop_test() { + let mut vbox = Vbox::new(Uuid::new_v4(), Uuid::new_v4()); + vbox.bound = vec![Var::Strike]; + vbox.drop(0).unwrap(); + assert_eq!(vbox.bits, 22); + } + } \ No newline at end of file