bugs ahoy and icons

This commit is contained in:
ntr
2019-04-10 18:31:11 +10:00
parent 4747bc7dec
commit 5b5de416e1
13 changed files with 330 additions and 140 deletions
+7 -1
View File
@@ -270,7 +270,13 @@ impl Game {
}
for (team_id, mob_id, target_id, s) in pve_skills {
self.add_skill(team_id, mob_id, target_id, s).expect("unable to add pve mob skill");
match self.add_skill(team_id, mob_id, target_id, s) {
Ok(_) => (),
Err(e) => {
println!("{:?}", self.cryp_by_id(mob_id));
panic!("{:?} unable to add pve mob skill {:?}", e, s);
},
}
}
self
+14 -11
View File
@@ -59,7 +59,9 @@ impl Instance {
self.players = iter::repeat_with(|| {
let bot_id = Uuid::new_v4();
let cryps = instance_mobs(bot_id);
Player::new(bot_id, self.id, &bot_id.to_string(), cryps).set_bot(true)
let mut p = Player::new(bot_id, self.id, &bot_id.to_string(), cryps).set_bot(true);
p.autobuy();
p
})
.take(15)
.collect::<Vec<Player>>();
@@ -199,16 +201,7 @@ impl Instance {
fn bot_vbox_phase(&mut self) -> &mut Instance {
for bot in self.players.iter_mut().filter(|p| p.bot) {
bot.vbox.fill();
// paths for what to do
// use a spec
// craft a spec
// craft a skill
// check for cryps w/ no skills
// create a skill()
// find base
// pick 2 random colours
bot.autobuy();
bot.set_ready(true);
}
@@ -585,6 +578,7 @@ mod tests {
let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account);
let mut player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true);
player.autobuy();
instance.add_player(player.clone());
assert!(instance.can_start());
@@ -605,4 +599,13 @@ mod tests {
assert_eq!(instance.rounds.len(), 3);
}
#[test]
fn instance_bot_vbox_test() {
let mut instance = Instance::new();
let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account);
let mut player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true);
}
}
+2 -2
View File
@@ -33,8 +33,8 @@ pub fn generate_mob() -> Cryp {
pub fn instance_mobs(team_id: Uuid) -> Vec<Cryp> {
iter::repeat_with(||
generate_mob()
.set_account(team_id)
.learn(Skill::Attack))
.set_account(team_id))
// .learn(Skill::Attack))
.take(3)
.collect::<Vec<Cryp>>()
}
+208 -2
View File
@@ -1,4 +1,5 @@
use uuid::Uuid;
use rand::prelude::*;
use serde_cbor::{from_slice, to_vec};
@@ -8,11 +9,13 @@ use failure::Error;
use failure::err_msg;
use account::Account;
use cryp::{Cryp, cryp_get};
use vbox::{Vbox};
use cryp::{Cryp, Colours, cryp_get};
use vbox::{Vbox, Var, VarEffect};
use rpc::{PlayerStateParams, PlayerCrypsSetParams};
use instance::{instance_get, instance_update};
const DISCARD_COST: u16 = 5;
#[derive(Debug,Clone,Copy,Serialize,Deserialize)]
pub struct Score {
pub wins: u8,
@@ -74,6 +77,193 @@ impl Player {
pub fn cryp_get(&mut self, id: Uuid) -> Result<&mut Cryp, Error> {
self.cryps.iter_mut().find(|c| c.id == id).ok_or(err_msg("cryp not found"))
}
pub fn autobuy(&mut self) -> &mut Player {
let mut rng = thread_rng();
// first check if any cryps have no skills
// if there is one find an item in vbox that gives a skill
while let Some(c) = self.cryps.iter().position(|c| c.skills.len() == 0) {
if let Some(s) = self.vbox.bound.iter().position(|v| v.into_skill().is_some()) {
let cryp_id = self.cryps[c].id;
self.vbox_apply(s, cryp_id).expect("could not apply");
continue;
}
println!("no skills available...");
}
// now keep buying and applying items cause whynot
// inb4 montecarlo gan
loop {
let (target_cryp_i, target_cryp_id) = match self.cryps.iter().any(|c| c.skills.len() < 3) {
true => {
let mut target_cryp_i = 0;
for (j, c) in self.cryps.iter().enumerate() {
if c.skills.len() < self.cryps[target_cryp_i].skills.len() {
target_cryp_i = j;
}
}
(target_cryp_i, self.cryps[target_cryp_i].id)
},
false => {
let i = rng.gen_range(0, 3);
(i, self.cryps[i].id)
},
};
let needs_skills = self.cryps[target_cryp_i].skills.len() < 3;
let group_i = match needs_skills {
true => 1,
false => 2,
};
if self.vbox.bound.len() < 3 {
if (needs_skills && self.vbox.bits < 4) || self.vbox.bits < 5 {
// println!("insufficient balance");
return self;
}
// get 2 colours and something else
if self.vbox.free[0].len() < 2 {
return self;
}
self.vbox_accept(0, 0).expect("could't accept colour 0");
self.vbox_accept(0, 0).expect("could't accept colour 1");
self.vbox_accept(group_i, 0).expect("could't accept group 0");
}
// println!("{:?}", self.vbox.bound);
let skills = [Var::Attack, Var::Block, Var::Buff, Var::Debuff, Var::Stun];
let combo_i = match group_i {
1 => self.vbox.bound.iter().position(|v| skills.contains(v)).expect("no skill found"),
2 => self.vbox.bound.iter().position(|v| v.into_spec().is_some()).expect("no spec found"),
_ => panic!("unknown group_i"),
};
// first 2 colours can be whatever
match self.vbox_combine(vec![0, 1, combo_i]) {
Ok(_) => {
// println!("refined {:?}", self.vbox.bound[self.vbox.bound.len() - 1]);
}
Err(e) => println!("{:?}", e),
};
let var_i = self.vbox.bound.len() - 1;
match self.vbox_apply(var_i, target_cryp_id) {
Ok(_) => {
// println!("{:?} improved", self.cryps[target_cryp_i].name);
},
Err(e) => println!("{:?}", e),
}
}
}
pub fn vbox_discard(&mut self) -> Result<&mut Player, Error> {
self.vbox.balance_sub(DISCARD_COST)?;
self.vbox.fill();
Ok(self)
}
pub fn vbox_accept(&mut self, group: usize, index: usize) -> Result<&mut Player, Error> {
self.vbox.accept(group, index)?;
Ok(self)
}
pub fn vbox_combine(&mut self, indices: Vec<usize>) -> Result<&mut Player, Error> {
self.vbox.combine(indices)?;
Ok(self)
}
pub fn vbox_reclaim(&mut self, index: usize) -> Result<&mut Player, Error> {
self.vbox.reclaim(index)?;
Ok(self)
}
pub fn vbox_apply(&mut self, index: usize, cryp_id: Uuid) -> Result<&mut Player, Error> {
let var = self.vbox.bound.remove(index);
match var.effect() {
Some(VarEffect::Skill) => {
let skill = var.into_skill().ok_or(format_err!("var {:?} has no associated skill", var))?;
let cryp = self.cryp_get(cryp_id)?;
// done here because i teach them a tonne of skills for tests
let max_skills = 3;
if cryp.skills.len() >= max_skills {
return Err(format_err!("cryp at max skills ({:?})", max_skills));
}
if cryp.knows(skill) {
return Err(format_err!("cryp already knows skill ({:?})" , skill));
}
cryp.learn_mut(skill);
},
Some(VarEffect::Spec) => {
let spec = var.into_spec().ok_or(format_err!("var {:?} has no associated spec", var))?;
let cryp = self.cryp_get(cryp_id)?;
cryp.spec_add(spec)?;
},
None => return Err(err_msg("var has no effect on cryps")),
}
// now the var has been applied
// recalculate the stats of the whole team
let team_colours = self.cryps.iter().fold(Colours::new(), |tc, c| {
Colours {
red: tc.red + c.colours.red,
green: tc.green + c.colours.green,
blue: tc.blue + c.colours.blue
}
});
for cryp in self.cryps.iter_mut() {
cryp.apply_modifiers(&team_colours);
}
Ok(self)
}
pub fn vbox_unequip(&mut self, target: Var, cryp_id: Uuid) -> Result<&mut Player, Error> {
if self.vbox.bound.len() >= 9 {
return Err(err_msg("too many vars bound"));
}
match target.effect() {
Some(VarEffect::Skill) => {
let skill = target.into_skill().ok_or(format_err!("var {:?} has no associated skill", target))?;
let cryp = self.cryp_get(cryp_id)?;
cryp.forget(skill)?;
},
Some(VarEffect::Spec) => {
let spec = target.into_spec().ok_or(format_err!("var {:?} has no associated spec", target))?;
let cryp = self.cryp_get(cryp_id)?;
cryp.spec_remove(spec)?;
},
None => return Err(err_msg("var has no effect on cryps")),
}
// now the var has been applied
// recalculate the stats of the whole team
let team_colours = self.cryps.iter().fold(Colours::new(), |tc, c| {
Colours {
red: tc.red + c.colours.red,
green: tc.green + c.colours.green,
blue: tc.blue + c.colours.blue
}
});
for cryp in self.cryps.iter_mut() {
cryp.apply_modifiers(&team_colours);
}
self.vbox.bound.push(target);
self.vbox.bound.sort_unstable();
Ok(self)
}
}
pub fn player_get(tx: &mut Transaction, account_id: Uuid, instance_id: Uuid) -> Result<Player, Error> {
@@ -191,3 +381,19 @@ pub fn player_mm_cryps_set(params: PlayerCrypsSetParams, tx: &mut Transaction, a
}
}
}
#[cfg(test)]
mod tests {
use mob::instance_mobs;
use super::*;
#[test]
fn player_bot_vbox_test() {
let player_account = Uuid::new_v4();
let cryps = instance_mobs(player_account);
let mut player = Player::new(player_account, Uuid::new_v4(), &"test".to_string(), cryps).set_bot(true);
player.autobuy();
println!("{:#?}", player);
}
}
+8 -8
View File
@@ -1075,23 +1075,23 @@ fn silence(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Re
}
fn purge(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
if [Category::BlueBuff, Category::RedBuff].contains(&ce.effect.category()) {
target.effects.remove(i);
while let Some(i) = target.effects
.iter()
.position(|ce| [Category::BlueBuff, Category::RedBuff].contains(&ce.effect.category())) {
let ce = target.effects.remove(i);
results.push(Resolution::new(source, target).event(Event::Removal { effect: ce.effect }));
}
}
return results;
}
fn purify(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -> Resolutions {
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
if [Category::BlueDebuff, Category::RedDebuff].contains(&ce.effect.category()) {
target.effects.remove(i);
while let Some(i) = target.effects
.iter()
.position(|ce| [Category::BlueDebuff, Category::RedDebuff].contains(&ce.effect.category())) {
let ce = target.effects.remove(i);
results.push(Resolution::new(source, target).event(Event::Removal { effect: ce.effect }));
}
}
return results;
}
+14 -85
View File
@@ -101,7 +101,7 @@ pub enum Var {
TestSiphon,
}
enum VarEffect {
pub enum VarEffect {
Skill,
Spec,
}
@@ -167,7 +167,7 @@ impl Var {
}
}
fn effect(&self) -> Option<VarEffect> {
pub fn effect(&self) -> Option<VarEffect> {
if let Some(_skill) = self.into_skill() {
return Some(VarEffect::Skill);
}
@@ -177,7 +177,7 @@ impl Var {
return None;
}
fn into_skill(&self) -> Option<Skill> {
pub fn into_skill(&self) -> Option<Skill> {
match self {
Var::Attack => Some(Skill::Attack),
Var::Amplify => Some(Skill::Amplify),
@@ -215,7 +215,7 @@ impl Var {
}
}
fn into_spec(&self) -> Option<Spec> {
pub fn into_spec(&self) -> Option<Spec> {
match *self {
Var::Speed => Some(Spec::Speed),
Var::RedSpeedI => Some(Spec::RedSpeedI),
@@ -255,6 +255,7 @@ impl From<Skill> for Var {
Skill::Blast => Var::Blast,
Skill::Block => Var::Block,
Skill::Curse => Var::Curse,
Skill::Clutch => Var::Clutch,
Skill::Decay => Var::Decay,
Skill::Empower => Var::Empower,
Skill::Haste => Var::Haste,
@@ -363,7 +364,7 @@ fn get_combos() -> Vec<Combo> {
Combo { units: vec![Var::Attack, Var::Blue, Var::Blue], var: Var::Blast },
Combo { units: vec![Var::Attack, Var::Red, Var::Green], var: Var::Purify },
Combo { units: vec![Var::Attack, Var::Green, Var::Blue], var: Var::Decay },
// Combo { units: vec![Var::Attack, Var::Red, Var::Blue], var: Var::Blast },
Combo { units: vec![Var::Attack, Var::Red, Var::Blue], var: Var::Blast }, // AAAAAAAAAAAAAAAAAA
Combo { units: vec![Var::Damage, Var::Red, Var::Red], var: Var::RedDamageI },
Combo { units: vec![Var::Damage, Var::Green, Var::Green], var: Var::GreenDamageI },
@@ -495,6 +496,7 @@ impl Vbox {
// actually move
self.bound.push(self.free[i].remove(j));
self.bound.sort_unstable();
Ok(self)
}
@@ -535,118 +537,45 @@ impl Vbox {
let combo = combos.iter().find(|c| c.units == input).ok_or(err_msg("not a combo"))?;
self.bound.push(combo.var);
self.bound.sort_unstable();
Ok(self)
}
}
const DISCARD_COST: u16 = 5;
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)?;
player.vbox.balance_sub(DISCARD_COST)?;
player.vbox.fill();
player.vbox_discard()?;
return player_update(tx, player, false);
}
pub fn vbox_accept(params: VboxAcceptParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?;
player.vbox.accept(params.group, params.index)?;
player.vbox_accept(params.group, params.index)?;
return player_update(tx, player, false);
}
pub fn vbox_combine(params: VboxCombineParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?;
player.vbox.combine(params.indices)?;
player.vbox_combine(params.indices)?;
return player_update(tx, player, false);
}
pub fn vbox_reclaim(params: VboxReclaimParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?;
player.vbox.reclaim(params.index)?;
player.vbox_reclaim(params.index)?;
return player_update(tx, player, false);
}
pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?;
let var = player.vbox.bound.remove(params.index);
match var.effect() {
Some(VarEffect::Skill) => {
let skill = var.into_skill().ok_or(format_err!("var {:?} has no associated skill", var))?;
let cryp = player.cryp_get(params.cryp_id)?;
// done here because i teach them a tonne of skills for tests
let max_skills = 3;
if cryp.skills.len() >= max_skills {
return Err(format_err!("cryp at max skills ({:?})", max_skills));
}
cryp.learn_mut(skill);
},
Some(VarEffect::Spec) => {
let spec = var.into_spec().ok_or(format_err!("var {:?} has no associated spec", var))?;
let cryp = player.cryp_get(params.cryp_id)?;
cryp.spec_add(spec)?;
},
None => return Err(err_msg("var has no effect on cryps")),
}
// now the var has been applied
// recalculate the stats of the whole team
let team_colours = player.cryps.iter().fold(Colours::new(), |tc, c| {
Colours {
red: tc.red + c.colours.red,
green: tc.green + c.colours.green,
blue: tc.blue + c.colours.blue
}
});
for cryp in player.cryps.iter_mut() {
cryp.apply_modifiers(&team_colours);
}
player.vbox_apply(params.index, params.cryp_id)?;
return player_update(tx, player, false);
}
pub fn vbox_unequip(params: VboxUnequipParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?;
if player.vbox.bound.len() >= 9 {
return Err(err_msg("too many vars bound"));
}
println!("{:?}", params);
match params.target.effect() {
Some(VarEffect::Skill) => {
let skill = params.target.into_skill().ok_or(format_err!("var {:?} has no associated skill", params.target))?;
let cryp = player.cryp_get(params.cryp_id)?;
cryp.forget(skill)?;
},
Some(VarEffect::Spec) => {
let spec = params.target.into_spec().ok_or(format_err!("var {:?} has no associated spec", params.target))?;
let cryp = player.cryp_get(params.cryp_id)?;
cryp.spec_remove(spec)?;
},
None => return Err(err_msg("var has no effect on cryps")),
}
// now the var has been applied
// recalculate the stats of the whole team
let team_colours = player.cryps.iter().fold(Colours::new(), |tc, c| {
Colours {
red: tc.red + c.colours.red,
green: tc.green + c.colours.green,
blue: tc.blue + c.colours.blue
}
});
for cryp in player.cryps.iter_mut() {
cryp.apply_modifiers(&team_colours);
}
player.vbox.bound.push(params.target);
player.vbox_unequip(params.target, params.cryp_id)?;
return player_update(tx, player, false);
}