max targets and multiplayer test

This commit is contained in:
ntr 2018-12-03 23:48:24 +11:00
parent b38be6d7bb
commit 63ec7a27ad
4 changed files with 302 additions and 231 deletions

View File

@ -147,6 +147,7 @@ function createSocket(events) {
// this object wraps the reply types to a function // this object wraps the reply types to a function
const handlers = { const handlers = {
cryp_spawn: crypSpawn, cryp_spawn: crypSpawn,
cryp_learn: () => true,
game_pve: gamePve, game_pve: gamePve,
game_state: gameState, game_state: gameState,
game_joinable_list: gameJoinableList, game_joinable_list: gameJoinableList,
@ -183,10 +184,12 @@ function createSocket(events) {
position: 'topRight', position: 'topRight',
}); });
events.loginPrompt(); if (!account) events.loginPrompt();
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
send({ method: 'account_login', params: { name: 'ntr', password: 'grepgrepgrep' } }); send({ method: 'account_login', params: { name: 'ntr', password: 'grepgrepgrep' } });
} }
return true;
}); });
// Listen for messages // Listen for messages
@ -200,7 +203,10 @@ function createSocket(events) {
ws.addEventListener('close', (event) => { ws.addEventListener('close', (event) => {
console.error('WebSocket closed', event); console.error('WebSocket closed', event);
// account = null; toast.warn({
message: 'disconnected',
position: 'topRight',
});
return setTimeout(connect, 5000); return setTimeout(connect, 5000);
}); });

View File

@ -248,7 +248,7 @@ impl Cryp {
return None; return None;
} }
println!("reduced effect {:?}", effect); // println!("reduced effect {:?}", effect);
return Some(effect); return Some(effect);
}).collect::<Vec<CrypEffect>>(); }).collect::<Vec<CrypEffect>>();
@ -266,9 +266,9 @@ impl Cryp {
.filter(|e| e.effect.modifications().contains(&Stat::PhysDmg)) .filter(|e| e.effect.modifications().contains(&Stat::PhysDmg))
.map(|cryp_effect| cryp_effect.effect) .map(|cryp_effect| cryp_effect.effect)
.collect::<Vec<Effect>>(); .collect::<Vec<Effect>>();
println!("{:?} phys_dmg mods : {:?}", self.name, phys_dmg_mods); // println!("{:?} phys_dmg mods : {:?}", self.name, phys_dmg_mods);
let modified_phys_dmg = phys_dmg_mods.iter().fold(self.phys_dmg.base, |acc, m| m.apply(acc)); let modified_phys_dmg = phys_dmg_mods.iter().fold(self.phys_dmg.base, |acc, m| m.apply(acc));
println!("{:?} phys_dmg : {:?}", self.name, modified_phys_dmg); // println!("{:?} phys_dmg : {:?}", self.name, modified_phys_dmg);
return modified_phys_dmg; return modified_phys_dmg;
} }
@ -277,9 +277,9 @@ impl Cryp {
.filter(|e| e.effect.modifications().contains(&Stat::SpellDmg)) .filter(|e| e.effect.modifications().contains(&Stat::SpellDmg))
.map(|cryp_effect| cryp_effect.effect) .map(|cryp_effect| cryp_effect.effect)
.collect::<Vec<Effect>>(); .collect::<Vec<Effect>>();
println!("{:?} spell_dmg mods : {:?}", self.name, spell_dmg_mods); // println!("{:?} spell_dmg mods : {:?}", self.name, spell_dmg_mods);
let modified_spell_dmg = spell_dmg_mods.iter().fold(self.spell_dmg.base, |acc, m| m.apply(acc)); let modified_spell_dmg = spell_dmg_mods.iter().fold(self.spell_dmg.base, |acc, m| m.apply(acc));
println!("{:?} spell_dmg : {:?}", self.name, modified_spell_dmg); // println!("{:?} spell_dmg : {:?}", self.name, modified_spell_dmg);
return modified_spell_dmg; return modified_spell_dmg;
} }
@ -308,7 +308,7 @@ impl Cryp {
pub fn deal_phys_dmg(&mut self, amount: u64) -> (u64, u64) { pub fn deal_phys_dmg(&mut self, amount: u64) -> (u64, u64) {
self.hp.reduce(amount); self.hp.reduce(amount);
println!("{:?} dealt {:?} phys dmg", self.name, amount); // println!("{:?} dealt {:?} phys dmg", self.name, amount);
return (amount, 0); return (amount, 0);
} }

View File

@ -166,7 +166,8 @@ impl Game {
} }
fn can_start(&self) -> bool { fn can_start(&self) -> bool {
self.teams.len() == self.team_num return self.teams.len() == self.team_num
&& self.teams.iter().all(|t| t.cryps.len() == self.team_size)
} }
fn start(&mut self) -> &mut Game { fn start(&mut self) -> &mut Game {
@ -299,7 +300,7 @@ impl Game {
let mob_team_id = Uuid::nil(); let mob_team_id = Uuid::nil();
let mobs = self.team_by_id(mob_team_id).clone(); let mobs = self.team_by_id(mob_team_id).clone();
let target_id = mobs.cryps.iter().find(|c| !c.is_ko()).map(|c| c.id).unwrap(); let target_id = mobs.cryps.iter().find(|c| !c.is_ko()).map(|c| c.id).unwrap();
println!("targeting {:?}", target_id);
// TODO attack multiple players based on some criteria // TODO attack multiple players based on some criteria
for incoming_skill_id in self.stack.clone().iter() for incoming_skill_id in self.stack.clone().iter()
.filter(|s| s.target_cryp_id.is_none() && s.target_team_id == mob_team_id) .filter(|s| s.target_cryp_id.is_none() && s.target_team_id == mob_team_id)
@ -311,23 +312,56 @@ impl Game {
self self
} }
// each cryp can be the target of
// incomingSkills / activeCryps rounded up
// maybe a problem with friendly / self targeting skills
fn cryp_targetable(&mut self, team_id: Uuid, cryp_id: Uuid) -> Result<(), Error> {
// whose team is this?
let team = self.teams.iter()
.find(|t| t.id == team_id)
.ok_or(err_msg("team not found"))?;
// is the target in the team?
let cryp = team.cryps.iter()
.find(|c| c.id == cryp_id)
.ok_or(err_msg("cryp not in team"))?;
if cryp.is_ko() {
return Err(err_msg("you cannot target ko cryps"));
}
let incoming = self.stack.iter()
.filter(|i| i.target_team_id == team.id)
.count();
let incoming = incoming as u32 as f64;
let active_cryps = team.cryps.iter()
.filter(|c| !c.is_ko())
.count();
let active_cryps = active_cryps as u32 as f64;
let max_targets = (incoming / active_cryps).ceil();
let targeted = self.stack.iter()
.filter(|s| s.target_cryp_id.is_some())
.filter(|s| s.target_cryp_id.unwrap() == cryp_id)
.count();
if targeted >= max_targets as usize {
return Err(format_err!("cryp target of maximum number of skills ({:?})", max_targets));
}
return Ok(());
}
// targets can only be added by the owner of the team // targets can only be added by the owner of the team
fn add_target(&mut self, team_id: Uuid, cryp_id: Uuid, skill_id: Uuid) -> Result<&mut Cast, Error> { fn add_target(&mut self, team_id: Uuid, cryp_id: Uuid, skill_id: Uuid) -> Result<&mut Cast, Error> {
if self.phase != Phase::Target { if self.phase != Phase::Target {
return Err(err_msg("game not in target phase")); return Err(err_msg("game not in target phase"));
} }
{ self.cryp_targetable(team_id, cryp_id)?;
// whose team is this?
let team = self.team_by_id(team_id);
// is the target in the team?
let cryp = team.cryp_by_id(cryp_id).ok_or(err_msg("cryp not in team"))?;
if cryp.is_ko() {
return Err(err_msg("you cannot target ko cryps"));
}
}
// set the target // set the target
let cast = match self.stack.iter_mut().find(|s| s.id == skill_id) { let cast = match self.stack.iter_mut().find(|s| s.id == skill_id) {
@ -405,7 +439,7 @@ impl Game {
// update the stack with the resolved skills // update the stack with the resolved skills
self.stack = self.stack.clone().iter_mut().map(|skill| { self.stack = self.stack.clone().iter_mut().map(|skill| {
println!("{:?} resolving ", skill); // println!("{:?} resolving ", skill);
let mut source = self.cryp_by_id(skill.source_cryp_id).unwrap().clone(); let mut source = self.cryp_by_id(skill.source_cryp_id).unwrap().clone();
let mut target = self.cryp_by_id(skill.target_cryp_id.unwrap()).unwrap().clone(); let mut target = self.cryp_by_id(skill.target_cryp_id.unwrap()).unwrap().clone();
@ -835,235 +869,241 @@ mod tests {
return game; return game;
} }
// fn create_2v2_test_game() -> Game { fn create_2v2_test_game() -> Game {
// let mut i = Cryp::new() let mut i = Cryp::new()
// .named(&"pretaliate".to_string()) .named(&"pretaliate".to_string())
// .level(8) .level(8)
// .learn(Skill::Attack) .learn(Skill::TestTouch)
// .create(); .create();
// let mut j = Cryp::new() let mut j = Cryp::new()
// .named(&"poy sian".to_string()) .named(&"poy sian".to_string())
// .level(8) .level(8)
// .learn(Skill::Attack) .learn(Skill::TestTouch)
// .create(); .create();
// let mut x = Cryp::new() let mut x = Cryp::new()
// .named(&"pronounced \"creeep\"".to_string()) .named(&"pronounced \"creeep\"".to_string())
// .level(8) .level(8)
// .learn(Skill::Attack) .learn(Skill::TestTouch)
// .create(); .create();
// let mut y = Cryp::new() let mut y = Cryp::new()
// .named(&"lemongrass tea".to_string()) .named(&"lemongrass tea".to_string())
// .level(8) .level(8)
// .learn(Skill::Attack) .learn(Skill::TestTouch)
// .create(); .create();
// let mut game = Game::new(); let mut game = Game::new();
// game game
// .set_team_num(2) .set_team_num(2)
// .set_team_size(2) .set_team_size(2)
// .set_pve(false); .set_pve(false);
// let x_team_id = Uuid::new_v4(); let i_team_id = Uuid::new_v4();
// let mut x_team = Team::new(x_team_id); let mut i_team = Team::new(i_team_id);
// x_team i_team
// .set_cryps(vec![x]); .set_cryps(vec![i,j]);
// let y_team_id = Uuid::new_v4(); let x_team_id = Uuid::new_v4();
// let mut y_team = Team::new(y_team_id); let mut x_team = Team::new(x_team_id);
// y_team x_team
// .set_cryps(vec![y]); .set_cryps(vec![x,y]);
// game game
// .team_add(x_team).unwrap() .team_add(i_team).unwrap()
// .team_add(y_team).unwrap(); .team_add(x_team).unwrap();
// assert!(game.can_start()); assert!(game.can_start());
// game.start(); game.start();
// return game; return game;
}
// #[test]
// fn phase_test() {
// let mut game = create_test_game();
// let x_team = game.teams[0].clone();
// let y_team = game.teams[1].clone();
// let x_cryp = x_team.cryps[0].clone();
// let y_cryp = y_team.cryps[0].clone();
// let x_attack_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::Attack).unwrap();
// let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::Attack).unwrap();
// assert!(game.skill_phase_finished());
// game.target_phase_start();
// game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
// game.add_target(y_team.id, y_cryp.id, x_attack_id).unwrap();
// assert!(game.target_phase_finished());
// game.resolve_phase_start();
// assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
// return;
// }
// #[test]
// fn stun_test() {
// let mut game = create_test_game();
// let x_team = game.teams[0].clone();
// let y_team = game.teams[1].clone();
// let x_cryp = x_team.cryps[0].clone();
// let y_cryp = y_team.cryps[0].clone();
// let x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestStun).unwrap();
// let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
// assert!(game.skill_phase_finished());
// game.target_phase_start();
// game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
// game.add_target(y_team.id, y_cryp.id, x_stun_id).unwrap();
// assert!(game.target_phase_finished());
// game.resolve_phase_start();
// // should auto progress back to skill phase
// assert!(game.phase == Phase::Skill);
// assert!(game.team_by_id(y_team.id).cryps[0].is_stunned());
// assert!(game.team_by_id(y_team.id).skills_required() == 0);
// }
// #[test]
// fn cooldown_test() {
// let mut game = create_test_game();
// let x_team = game.teams[0].clone();
// let y_team = game.teams[1].clone();
// let x_cryp = x_team.cryps[0].clone();
// let y_cryp = y_team.cryps[0].clone();
// let x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestTouch).unwrap();
// let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
// game.target_phase_start();
// game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
// game.add_target(y_team.id, y_cryp.id, x_stun_id).unwrap();
// game.resolve_phase_start();
// // should auto progress back to skill phase
// assert!(game.phase == Phase::Skill);
// // after 1 turn block should be off cooldown
// assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_none());
// assert!(game.team_by_id(x_team.id).cryps[0].skill_on_cd(Skill::Block).is_none());
// // second round
// // now we block and it should go back on cd
// let _x_block_id = game.add_skill(x_team.id, x_cryp.id, None, Skill::Block).unwrap();
// let _y_block_id = game.add_skill(y_team.id, y_cryp.id, None, Skill::Block).unwrap();
// game.target_phase_start();
// assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_some());
// assert!(game.team_by_id(x_team.id).cryps[0].skill_on_cd(Skill::Block).is_some());
// }
// #[test]
// fn block_test() {
// let mut game = create_test_game();
// let x_team = game.teams[0].clone();
// let y_team = game.teams[1].clone();
// let x_cryp = x_team.cryps[0].clone();
// let y_cryp = y_team.cryps[0].clone();
// // ensure that you can't pass a target for a block
// assert!(game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestBlock).is_err());
// let x_block_id = game.add_skill(x_team.id, x_cryp.id, None, Skill::TestBlock).unwrap();
// let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestStun).unwrap();
// game.target_phase_start();
// // ensure you can't target a self targeting skill
// assert!(game.add_target(y_team.id, y_cryp.id, x_block_id).is_err());
// // ensure you can't target another team's skills
// assert!(game.add_target(x_team.id, y_cryp.id, y_attack_id).is_err());
// game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
// game.resolve_phase_start();
// // should not be stunned because of block
// assert!(game.team_by_id(x_team.id).cryps[0].is_stunned() == false);
// }
// #[test]
// fn drain_test() {
// let mut game = create_test_game();
// let x_team = game.teams[0].clone();
// let y_team = game.teams[1].clone();
// let x_cryp = x_team.cryps[0].clone();
// let y_cryp = y_team.cryps[0].clone();
// let x_drain_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestDrain).unwrap();
// let y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
// game.target_phase_start();
// game.add_target(x_team.id, x_cryp.id, y_touch_id).unwrap();
// game.add_target(y_team.id, y_cryp.id, x_drain_id).unwrap();
// game.resolve_phase_start();
// game.add_skill(x_team.id, x_cryp.id, None, Skill::TestBlock).unwrap();
// game.add_skill(y_team.id, y_cryp.id, None, Skill::TestBlock).unwrap();
// game.target_phase_start();
// assert!(game.resolved.iter().any(|r| r.skill == Skill::DrainTick));
// } // }
#[test]
fn phase_test() {
let mut game = create_test_game();
let x_team = game.teams[0].clone();
let y_team = game.teams[1].clone();
let x_cryp = x_team.cryps[0].clone();
let y_cryp = y_team.cryps[0].clone();
let x_attack_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::Attack).unwrap();
let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::Attack).unwrap();
assert!(game.skill_phase_finished());
game.target_phase_start();
game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
game.add_target(y_team.id, y_cryp.id, x_attack_id).unwrap();
assert!(game.target_phase_finished());
game.resolve_phase_start();
assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
return;
}
#[test]
fn stun_test() {
let mut game = create_test_game();
let x_team = game.teams[0].clone();
let y_team = game.teams[1].clone();
let x_cryp = x_team.cryps[0].clone();
let y_cryp = y_team.cryps[0].clone();
let x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestStun).unwrap();
let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
assert!(game.skill_phase_finished());
game.target_phase_start();
game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
game.add_target(y_team.id, y_cryp.id, x_stun_id).unwrap();
assert!(game.target_phase_finished());
game.resolve_phase_start();
// should auto progress back to skill phase
assert!(game.phase == Phase::Skill);
assert!(game.team_by_id(y_team.id).cryps[0].is_stunned());
assert!(game.team_by_id(y_team.id).skills_required() == 0);
}
#[test]
fn cooldown_test() {
let mut game = create_test_game();
let x_team = game.teams[0].clone();
let y_team = game.teams[1].clone();
let x_cryp = x_team.cryps[0].clone();
let y_cryp = y_team.cryps[0].clone();
let x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestTouch).unwrap();
let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
game.target_phase_start();
game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
game.add_target(y_team.id, y_cryp.id, x_stun_id).unwrap();
game.resolve_phase_start();
// should auto progress back to skill phase
assert!(game.phase == Phase::Skill);
// after 1 turn block should be off cooldown
assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_none());
assert!(game.team_by_id(x_team.id).cryps[0].skill_on_cd(Skill::Block).is_none());
// second round
// now we block and it should go back on cd
let _x_block_id = game.add_skill(x_team.id, x_cryp.id, None, Skill::Block).unwrap();
let _y_block_id = game.add_skill(y_team.id, y_cryp.id, None, Skill::Block).unwrap();
game.target_phase_start();
assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_some());
assert!(game.team_by_id(x_team.id).cryps[0].skill_on_cd(Skill::Block).is_some());
}
#[test]
fn block_test() {
let mut game = create_test_game();
let x_team = game.teams[0].clone();
let y_team = game.teams[1].clone();
let x_cryp = x_team.cryps[0].clone();
let y_cryp = y_team.cryps[0].clone();
// ensure that you can't pass a target for a block
assert!(game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestBlock).is_err());
let x_block_id = game.add_skill(x_team.id, x_cryp.id, None, Skill::TestBlock).unwrap();
let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestStun).unwrap();
game.target_phase_start();
// ensure you can't target a self targeting skill
assert!(game.add_target(y_team.id, y_cryp.id, x_block_id).is_err());
// ensure you can't target another team's skills
assert!(game.add_target(x_team.id, y_cryp.id, y_attack_id).is_err());
game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap();
game.resolve_phase_start();
// should not be stunned because of block
assert!(game.team_by_id(x_team.id).cryps[0].is_stunned() == false);
}
#[test]
fn drain_test() {
let mut game = create_test_game();
let x_team = game.teams[0].clone();
let y_team = game.teams[1].clone();
let x_cryp = x_team.cryps[0].clone();
let y_cryp = y_team.cryps[0].clone();
let x_drain_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestDrain).unwrap();
let y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
game.target_phase_start();
game.add_target(x_team.id, x_cryp.id, y_touch_id).unwrap();
game.add_target(y_team.id, y_cryp.id, x_drain_id).unwrap();
game.resolve_phase_start();
game.add_skill(x_team.id, x_cryp.id, None, Skill::TestBlock).unwrap();
game.add_skill(y_team.id, y_cryp.id, None, Skill::TestBlock).unwrap();
game.target_phase_start();
assert!(game.resolved.iter().any(|r| r.skill == Skill::DrainTick));
println!("{:#?}", game);
}
#[test] #[test]
fn ko_pve_test() { fn ko_pve_test() {
let mut game = create_test_game(); let mut game = create_2v2_test_game();
let x_team = game.teams[0].clone(); let i_team = game.teams[0].clone();
let y_team = game.teams[1].clone(); let x_team = game.teams[1].clone();
let i_cryp = i_team.cryps[0].clone();
let j_cryp = i_team.cryps[1].clone();
let x_cryp = x_team.cryps[0].clone(); let x_cryp = x_team.cryps[0].clone();
let y_cryp = y_team.cryps[0].clone(); let y_cryp = x_team.cryps[1].clone();
let i_attack_id = game.add_skill(i_team.id, i_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
let j_attack_id = game.add_skill(i_team.id, j_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
let x_attack_id = game.add_skill(x_team.id, x_cryp.id, Some(i_team.id), Skill::TestTouch).unwrap();
let y_attack_id = game.add_skill(x_team.id, y_cryp.id, Some(i_team.id), Skill::TestTouch).unwrap();
let x_attack_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::Attack).unwrap();
let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::Attack).unwrap();
assert!(game.skill_phase_finished()); assert!(game.skill_phase_finished());
game.target_phase_start(); game.target_phase_start();
game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap(); game.add_target(i_team.id, i_cryp.id, x_attack_id).unwrap();
game.add_target(y_team.id, y_cryp.id, x_attack_id).unwrap(); assert!(game.add_target(i_team.id, i_cryp.id, y_attack_id).is_err());
game.add_target(i_team.id, j_cryp.id, y_attack_id).unwrap();
game.add_target(x_team.id, x_cryp.id, i_attack_id).unwrap();
game.add_target(x_team.id, y_cryp.id, j_attack_id).unwrap();
assert!(game.target_phase_finished()); assert!(game.target_phase_finished());
@ -1071,8 +1111,30 @@ mod tests {
assert!([Phase::Skill, Phase::Finish].contains(&game.phase)); assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
// kill a cryp
game.team_by_id(i_team.id).cryp_by_id(i_cryp.id).unwrap().hp.reduce(u64::max_value());
// add some more skills
// let i_attack_id = game.add_skill(i_team.id, i_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
let j_attack_id = game.add_skill(i_team.id, j_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
let x_attack_id = game.add_skill(x_team.id, x_cryp.id, Some(i_team.id), Skill::TestTouch).unwrap();
let y_attack_id = game.add_skill(x_team.id, y_cryp.id, Some(i_team.id), Skill::TestTouch).unwrap();
assert!(game.skill_phase_finished());
game.target_phase_start();
assert!(game.team_by_id(i_team.id).skills_required() == 1);
assert!(game.cryp_targetable(i_team.id, i_cryp.id).is_err());
assert!(game.cryp_targetable(i_team.id, j_cryp.id).is_ok());
assert!(game.add_target(i_team.id, i_cryp.id, x_attack_id).is_err());
game.add_target(i_team.id, j_cryp.id, x_attack_id).unwrap();
game.add_target(i_team.id, j_cryp.id, y_attack_id).unwrap();
game.add_target(x_team.id, x_cryp.id, j_attack_id).unwrap();
game.add_target(x_team.id, y_cryp.id, j_attack_id).unwrap();
assert!(game.target_phase_finished());
return; return;
} }
} }

View File

@ -669,7 +669,10 @@ impl Skill {
Skill::TestBlock => 1, Skill::TestBlock => 1,
Skill::TestStun => 2, Skill::TestStun => 2,
_ => panic!("{:?} does not have a duration", self), _ => {
println!("{:?} does not have a duration", self);
return 2;
},
} }
} }