diff --git a/server/COMBOS.md b/server/COMBOS.md index 7d865d55..ed80bbc6 100644 --- a/server/COMBOS.md +++ b/server/COMBOS.md @@ -71,7 +71,6 @@ Combine `Base Skill Buff + 2 Red & 1 Blue` Buff `Base ally targetted skill - significantly increase ally speed` ### Slow ### - Combine `Base Skill Debuff + 1 Red & 2 Blue` Buff `Base ally targetted skill - significantly decrease enemy speed` diff --git a/server/src/vbox.rs b/server/src/vbox.rs index ad54fd7c..785d6ada 100644 --- a/server/src/vbox.rs +++ b/server/src/vbox.rs @@ -16,17 +16,34 @@ use failure::err_msg; use account::Account; use rpc::{VboxStateParams, VboxAcceptParams, VboxDiscardParams, VboxCombineParams}; -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +#[derive(Debug,Clone,Copy,PartialEq,Eq,Ord,PartialOrd,Serialize,Deserialize)] pub enum Var { - Red, - Green, Blue, + Green, + Red, Attack, Block, Stun, Buff, Debuff, + + Heal, + Throw, + Hex, +} + +impl Var { + fn is_base(&self) -> bool { + match self { + Var::Attack | + Var::Block | + Var::Stun | + Var::Debuff | + Var::Buff => true, + _ => false, + } + } } #[derive(Debug,Clone,Serialize,Deserialize)] @@ -56,6 +73,12 @@ impl Vbox { (Var::Red, 1), (Var::Green, 1), (Var::Blue, 1), + + (Var::Attack, 1), + (Var::Block, 1), + (Var::Buff, 1), + (Var::Debuff, 1), + (Var::Stun, 1), ]; self.free = iter:: @@ -83,6 +106,83 @@ impl Vbox { Ok(self) } + + pub fn combine(&mut self, mut indices: Vec) -> Result<&mut Vbox, Error> { + if indices.len() != 3 { + return Err(err_msg("exactly 3 indices required")); + } + + if !indices.iter().all(|i| self.bound.get(*i).is_some()) { + return Err(err_msg("var missing index")); + } + + // 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 + .iter() + .enumerate() + .map(|(i, index)| { + self.bound.remove(*index - i) + }) + .collect::>(); + + let base_index = vars + .iter() + .position(|v| v.is_base()) + .ok_or(err_msg("no base item selected"))?; + + 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 new = match base { + Var::Attack => match colours { + [0,2,0] => Var::Heal, + _ => return Err(err_msg("not a combo")), + }, + Var::Block => match colours { + [0,2,0] => Var::Heal, + _ => return Err(err_msg("not a combo")), + + }, + Var::Buff => match colours { + [0,2,0] => Var::Heal, + [1,1,0] => Var::Heal, + [0,1,1] => Var::Heal, + _ => return Err(err_msg("not a combo")), + + }, + Var::Debuff => match colours { + [0,2,0] => Var::Heal, + _ => return Err(err_msg("not a combo")), + + }, + Var::Stun => match colours { + [2,0,0] => Var::Throw, + [0,0,2] => Var::Hex, + _ => return Err(err_msg("not a combo")), + + }, + _ => return panic!("wrong base {:?}", base), + }; + + self.bound.push(new); + + Ok(self) + } } pub fn vbox_create(vbox: Vbox, tx: &mut Transaction, account: &Account) -> Result { @@ -165,12 +265,27 @@ pub fn vbox_discard(params: VboxDiscardParams, tx: &mut Transaction, account: &A pub fn vbox_accept(params: VboxAcceptParams, tx: &mut Transaction, account: &Account) -> Result { let mut vbox = vbox_get(tx, params.game_id, account)?; - vbox.accept(params.index)?; - return vbox_write(vbox, tx); } pub fn vbox_combine(params: VboxCombineParams, tx: &mut Transaction, account: &Account) -> Result { - return vbox_get(tx, params.game_id, account) + let mut vbox = vbox_get(tx, params.game_id, account)?; + vbox.combine(params.indices)?; + return vbox_write(vbox, tx); } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn combine_test() { + let mut vbox = Vbox::new(Uuid::new_v4(), Uuid::new_v4()); + vbox.bound = vec![Var::Attack, Var::Green, Var::Green]; + vbox.combine(vec![1,2,0]).unwrap(); + + println!("{:?}", vbox); + assert_eq!(vbox.bound[0], Var::Heal); + } +} \ No newline at end of file