Merge branch 'master' of ssh://cryps.gg:40022/~/cryps

This commit is contained in:
Mashy 2019-03-15 14:03:49 +10:00
commit 31060f681e
5 changed files with 151 additions and 130 deletions

6
client/src/scenes/item.list.js Normal file → Executable file
View File

@ -152,9 +152,9 @@ class ItemList extends Phaser.Scene {
drawInventory(graphics); drawInventory(graphics);
drawVbox(graphics); drawVbox(graphics);
this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 0.5, `Varibox - $${vbox.balance} available`, TEXT.HEADER); this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 0.5, `vBox - ${vbox.bits}b`, TEXT.HEADER);
this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 11, 'Inventory', TEXT.HEADER); this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 11, 'inventory', TEXT.HEADER);
this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 18, 'Combiner', TEXT.HEADER); this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 18, 'iCombinator', TEXT.HEADER);
this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 23, `Wins: ${player.score.wins}`, TEXT.HEADER); this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 23, `Wins: ${player.score.wins}`, TEXT.HEADER);
this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 24, `Losses: ${player.score.losses}`, TEXT.HEADER); this.add.text(X + ITEM_WIDTH * 0.5, Y + ITEM_HEIGHT * 24, `Losses: ${player.score.losses}`, TEXT.HEADER);

View File

@ -9,11 +9,14 @@
# WORK WORK # WORK WORK
## NOW ## NOW
cost system for items
be able to reclaim skills / specs from cryp be able to reclaim skills / specs from cryp
combo specs combo specs
randomise skill speed randomise skill speed
scoreboard
constants
round system for games round system for games
join instance join instance
is pve? is pve?

View File

@ -58,7 +58,7 @@ impl Instance {
self.players = iter::repeat_with(|| { self.players = iter::repeat_with(|| {
let bot_id = Uuid::new_v4(); let bot_id = Uuid::new_v4();
let cryps = instance_mobs(bot_id); let cryps = instance_mobs(bot_id);
Player::new(bot_id, self.id, cryps).set_bot(true) Player::new(bot_id, self.id, &bot_id.to_string(), cryps).set_bot(true)
}) })
.take(15) .take(15)
.collect::<Vec<Player>>(); .collect::<Vec<Player>>();
@ -212,7 +212,7 @@ impl Instance {
.iter() .iter()
.filter(|p| round.player_ids.contains(&p.id) && p.bot) .filter(|p| round.player_ids.contains(&p.id) && p.bot)
.count() == 2 { .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 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(); let b = self.players.clone().into_iter().find(|p| p.id == round.player_ids[1]).unwrap();
@ -400,7 +400,7 @@ pub fn instance_join(params: InstanceJoinParams, tx: &mut Transaction, account:
return Err(format_err!("incorrect team size. ({:})", 3)); return Err(format_err!("incorrect team size. ({:})", 3));
} }
let mut player = Player::new(account.id, instance.id, cryps); let mut player = Player::new(account.id, instance.id, &account.name, cryps);
player.vbox.fill(); player.vbox.fill();
let player = player_create(tx, player, account)?; let player = player_create(tx, player, account)?;
@ -515,7 +515,7 @@ mod tests {
let player_id = Uuid::new_v4(); let player_id = Uuid::new_v4();
let cryps = instance_mobs(player_id); let cryps = instance_mobs(player_id);
let player = Player::new(player_id, instance.id, cryps).set_bot(true); let player = Player::new(player_id, instance.id, &"test".to_string(), cryps).set_bot(true);
instance.add_player(player); instance.add_player(player);
assert!(instance.can_start()); assert!(instance.can_start());
@ -529,7 +529,7 @@ mod tests {
assert!(instance.vbox_phase_finished()); assert!(instance.vbox_phase_finished());
instance.games_phase_start(); instance.games_phase_start();
println!("{:#?}", instance); // println!("{:#?}", instance);
assert!(instance.games_phase_finished()); assert!(instance.games_phase_finished());
} }

View File

@ -24,7 +24,7 @@ pub struct Player {
pub id: Uuid, pub id: Uuid,
pub instance: Uuid, pub instance: Uuid,
pub account: Uuid, pub account: Uuid,
// name: String, pub name: String,
pub vbox: Vbox, pub vbox: Vbox,
pub score: Score, pub score: Score,
pub cryps: Vec<Cryp>, pub cryps: Vec<Cryp>,
@ -33,11 +33,12 @@ pub struct Player {
} }
impl Player { impl Player {
pub fn new(account: Uuid, instance: Uuid, cryps: Vec<Cryp>) -> Player { pub fn new(account: Uuid, instance: Uuid, name: &String, cryps: Vec<Cryp>) -> Player {
Player { Player {
id: Uuid::new_v4(), id: Uuid::new_v4(),
account, account,
instance, instance,
name: name.clone(),
vbox: Vbox::new(account, instance), vbox: Vbox::new(account, instance),
score: Score { wins: 0, losses: 0 }, score: Score { wins: 0, losses: 0 },
cryps, cryps,
@ -179,7 +180,7 @@ pub fn player_cryps_set(params: PlayerCrypsSetParams, tx: &mut Transaction, acco
player_update(tx, p, false) player_update(tx, p, false)
}, },
Err(_) => { Err(_) => {
return player_create(tx, Player::new(account.id, Uuid::nil(), cryps), &account) return player_create(tx, Player::new(account.id, Uuid::nil(), &account.name, cryps), &account)
} }
} }
} }

View File

@ -17,7 +17,7 @@ use skill::{Skill};
use spec::{Spec}; use spec::{Spec};
use player::{Player, player_get, player_update}; 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 { pub enum Var {
// colours // colours
Blue, Blue,
@ -81,18 +81,28 @@ enum VarEffect {
} }
impl Var { impl Var {
fn is_base(&self) -> bool { fn cost(&self) -> u16 {
match self { match self {
Var::Attack | Var::Red => 1,
Var::Block | Var::Green => 1,
Var::Stun | Var::Blue => 1,
Var::Debuff |
Var::Buff => true,
Var::Hp | Var::Attack => 2,
Var::Damage => true, Var::Block => 2,
Var::Buff => 2,
Var::Debuff => 2,
Var::Stun => 2,
_ => false, Var::Damage => 3,
Var::Hp => 3,
Var::Speed => 3,
_ => {
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());
},
} }
} }
@ -157,20 +167,67 @@ impl Var {
} }
} }
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] fn get_combos() -> Vec<(Vec<Var>, Var)> {
enum ColourCode { let mut combinations = vec![
RR, (vec![Var::Attack, Var::Red, Var::Red] , Var::Strike ),
GG, (vec![Var::Attack, Var::Green, Var::Green] , Var::Heal ),
BB, (vec![Var::Attack, Var::Blue, Var::Blue] , Var::Blast ),
RG, (vec![Var::Attack, Var::Red, Var::Green] , Var::Strike ),
BR, (vec![Var::Attack, Var::Green, Var::Blue] , Var::Heal ),
GB, (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)] #[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Vbox { pub struct Vbox {
pub id: Uuid, pub id: Uuid,
pub balance: u16, pub bits: u16,
pub free: Vec<Vec<Var>>, pub free: Vec<Vec<Var>>,
pub bound: Vec<Var>, pub bound: Vec<Var>,
pub instance: Uuid, pub instance: Uuid,
@ -197,7 +254,7 @@ impl Vbox {
instance: instance_id, instance: instance_id,
free: vec![], free: vec![],
bound: starting_items, bound: starting_items,
balance: 9, bits: 18,
}; };
vbox.fill(); vbox.fill();
@ -205,6 +262,21 @@ impl Vbox {
return vbox; return vbox;
} }
pub fn balance_sub(&mut self, amount: u16) -> Result<&mut Vbox, Error> {
let new_balance = self.bits
.checked_sub(amount)
.ok_or(format_err!("insufficient balance: {:?}", self.bits))?;
self.bits = new_balance;
Ok(self)
}
pub fn balance_add(&mut self, amount: u16) -> &mut Vbox {
self.bits = self.bits.saturating_add(amount);
self
}
pub fn fill(&mut self) -> &mut Vbox { pub fn fill(&mut self) -> &mut Vbox {
let colours = vec![ let colours = vec![
(Var::Red, 1), (Var::Red, 1),
@ -248,10 +320,16 @@ impl Vbox {
return Err(err_msg("too many vars bound")); return Err(err_msg("too many vars bound"));
} }
// check item exists
self.free self.free
.get(i).ok_or(format_err!("no var group at index {:?}", i))? .get(i).ok_or(format_err!("no var group at index {:?}", i))?
.get(j).ok_or(format_err!("no var at index {:?}", j))?; .get(j).ok_or(format_err!("no var at index {:?}", j))?;
// check can purchase
let cost = self.free[i][j].cost();
self.balance_sub(cost)?;
// actually move
self.bound.push(self.free[i].remove(j)); self.bound.push(self.free[i].remove(j));
Ok(self) Ok(self)
@ -259,8 +337,10 @@ impl Vbox {
pub fn drop(&mut self, i: usize) -> Result<&mut Vbox, Error> { pub fn drop(&mut self, i: usize) -> Result<&mut Vbox, Error> {
self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?; self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?;
self.bound.remove(i); let dropped = self.bound.remove(i);
// balance update let refund = dropped.cost();
println!("refunding {:?} for {:?}", refund, dropped);
self.balance_add(refund);
Ok(self) Ok(self)
} }
@ -275,8 +355,8 @@ impl Vbox {
// have to sort the indices and keep track of the iteration // have to sort the indices and keep track of the iteration
// because when removing the elements the array shifts // because when removing the elements the array shifts
indices.sort(); indices.sort_unstable();
let mut vars = indices let mut input = indices
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, index)| { .map(|(i, index)| {
@ -284,107 +364,23 @@ impl Vbox {
}) })
.collect::<Vec<Var>>(); .collect::<Vec<Var>>();
let base_index = vars // sort the input to align with the combinations
.iter() // combos are sorted when created
.position(|v| v.is_base()) input.sort_unstable();
.ok_or(err_msg("no base item selected"))?; 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); self.bound.push(combo.1);
// 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);
Ok(self) Ok(self)
} }
} }
const DISCARD_COST: u16 = 5;
pub fn vbox_discard(params: VboxDiscardParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> { pub fn vbox_discard(params: VboxDiscardParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?; let mut player = player_get(tx, account.id, params.instance_id)?;
player.vbox.balance_sub(DISCARD_COST)?;
player.vbox.fill(); player.vbox.fill();
return player_update(tx, player, false); return player_update(tx, player, false);
} }
@ -447,4 +443,25 @@ mod tests {
vbox.combine(vec![1,2,0]).unwrap(); vbox.combine(vec![1,2,0]).unwrap();
assert_eq!(vbox.bound[0], Var::Heal); 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);
}
} }