impl Battle::Engine::exec()
parent
262c962d5d
commit
9edb4a224c
|
|
@ -5,6 +5,7 @@ pub mod mon {
|
||||||
pub hp: i32,
|
pub hp: i32,
|
||||||
pub atk: i32,
|
pub atk: i32,
|
||||||
pub def: i32,
|
pub def: i32,
|
||||||
|
pub spd: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
@ -18,6 +19,7 @@ pub mod mon {
|
||||||
hp: 1,
|
hp: 1,
|
||||||
atk: 2,
|
atk: 2,
|
||||||
def: 3,
|
def: 3,
|
||||||
|
spd: 4,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,12 +44,14 @@ pub mod mon {
|
||||||
hp: 10,
|
hp: 10,
|
||||||
atk: 11,
|
atk: 11,
|
||||||
def: 9,
|
def: 9,
|
||||||
|
spd: 11,
|
||||||
},
|
},
|
||||||
Dex::Mari => Species{
|
Dex::Mari => Species{
|
||||||
name: "Mari".to_string(),
|
name: "Mari".to_string(),
|
||||||
hp: 10,
|
hp: 10,
|
||||||
atk: 8,
|
atk: 8,
|
||||||
def: 12,
|
def: 12,
|
||||||
|
spd: 9,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,6 +71,7 @@ pub mod mon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
pub species: Species,
|
pub species: Species,
|
||||||
pub damage: i32,
|
pub damage: i32,
|
||||||
|
|
@ -94,10 +99,69 @@ pub mod mon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod battler {
|
pub mod battle {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn attack(w: &mut mon::Instance, r: &mut mon::Instance) {
|
pub struct Engine {
|
||||||
|
teams: Vec<Team>,
|
||||||
|
q: Vec<Move>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Engine {
|
||||||
|
pub fn new(first: Vec<mon::Instance>, second: Vec<mon::Instance>) -> Engine {
|
||||||
|
let mut result = Self{
|
||||||
|
teams: vec![],
|
||||||
|
q: vec![],
|
||||||
|
};
|
||||||
|
result.join(first);
|
||||||
|
result.join(second);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join(&mut self, third: Vec<mon::Instance>) {
|
||||||
|
self.teams.push(Team::new(third));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enqueue(&mut self, m: Move) {
|
||||||
|
self.q.push(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exec(&mut self) {
|
||||||
|
self.turn_order().iter().for_each(|idx| {
|
||||||
|
match self.q[*idx].clone() {
|
||||||
|
Move::Pass(_) => {},
|
||||||
|
Move::Attack(rIdx, wIdx) => {
|
||||||
|
let r = self.teams[rIdx.team].mons[rIdx.mon].clone();
|
||||||
|
if r.can_attack() {
|
||||||
|
let w = self.teams[wIdx.team].mons[wIdx.mon].clone();
|
||||||
|
if w.can_be_attacked() {
|
||||||
|
self.teams[wIdx.team].mons[wIdx.mon].mon = Engine::attack(&w.mon, &r.mon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
self.new_turn();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_turn(&mut self) {
|
||||||
|
self.q = vec![];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn turn_order(&self) -> Vec<usize> {
|
||||||
|
let mut order = vec![];
|
||||||
|
for i in 0..self.q.len() {
|
||||||
|
order.push((i, match &self.q[i] {
|
||||||
|
Move::Pass(_) => 0,
|
||||||
|
Move::Attack(w, _) => self.teams[w.team].mons[w.mon].mon.species.spd,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
order.sort_unstable_by(|a, b| a.1.cmp(&b.1));
|
||||||
|
order.iter().map(|x| x.0).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attack(w: &mon::Instance, r: &mon::Instance) -> mon::Instance {
|
||||||
|
let mut w = w.clone();
|
||||||
let atk_delta = r.species.atk - 10;
|
let atk_delta = r.species.atk - 10;
|
||||||
let def_delta = w.species.def - 10;
|
let def_delta = w.species.def - 10;
|
||||||
|
|
||||||
|
|
@ -110,28 +174,128 @@ pub mod battler {
|
||||||
v if v < w.species.hp => v,
|
v if v < w.species.hp => v,
|
||||||
_ => w.species.hp,
|
_ => w.species.hp,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
w
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod species_tests {
|
mod engine_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new() {
|
||||||
|
let mut engine = Engine::new(team_a(), team_b());
|
||||||
|
engine.join(team_b());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_attack() {
|
fn test_attack() {
|
||||||
let mut pika = mon::Instance::roll(mon::Dex::Pika);
|
let mut pika = mon::Instance::roll(mon::Dex::Pika);
|
||||||
let mut mari = mon::Instance::roll(mon::Dex::Mari);
|
let mut mari = mon::Instance::roll(mon::Dex::Mari);
|
||||||
|
|
||||||
attack(&mut pika, &mut mari);
|
pika = Engine::attack(&mut pika, &mut mari);
|
||||||
assert_eq!(1, pika.damage);
|
assert_eq!(1, pika.damage);
|
||||||
|
|
||||||
attack(&mut mari, &mut pika);
|
mari = Engine::attack(&mut mari, &mut pika);
|
||||||
assert_eq!(1, mari.damage);
|
assert_eq!(1, mari.damage);
|
||||||
|
|
||||||
for _ in 0..pika.species.hp+5 {
|
for _ in 0..pika.species.hp+5 {
|
||||||
attack(&mut pika, &mut mari);
|
pika = Engine::attack(&mut pika, &mut mari);
|
||||||
}
|
}
|
||||||
assert_eq!(pika.species.hp, pika.damage);
|
assert_eq!(pika.species.hp, pika.damage);
|
||||||
assert_eq!(1, mari.damage);
|
assert_eq!(1, mari.damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_turn() {
|
||||||
|
let mut engine = Engine::new(team_a(), team_b());
|
||||||
|
engine.join(team_b());
|
||||||
|
|
||||||
|
// player 0 mon 0 attacks team 1 mon 0
|
||||||
|
engine.enqueue(Move::Attack(Idx{team: 0, mon: 0}, Idx{team: 1, mon: 0}));
|
||||||
|
// player 1 mon 0 passes
|
||||||
|
engine.enqueue(Move::Pass(Idx{team: 1, mon: 0}));
|
||||||
|
// player 1 mon 1 not out
|
||||||
|
engine.exec();
|
||||||
|
|
||||||
|
assert_eq!(0, engine.teams[0].mons[0].mon.damage);
|
||||||
|
assert_eq!(1, engine.teams[1].mons[0].mon.damage);
|
||||||
|
assert_eq!(0, engine.teams[1].mons[1].mon.damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn team_a() -> Vec<mon::Instance> {
|
||||||
|
vec![mon::Instance::roll(mon::Dex::Pika)]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn team_b() -> Vec<mon::Instance> {
|
||||||
|
vec![mon::Instance::roll(mon::Dex::Mari), mon::Instance::roll(mon::Dex::Pika)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Team {
|
||||||
|
mons: Vec<Instance>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Team {
|
||||||
|
fn new(mons: Vec<mon::Instance>) -> Self {
|
||||||
|
assert!(mons.len() > 0);
|
||||||
|
let mut mons: Vec<_> = mons.iter().map(|m| Instance{mon: m.clone(), out: false}).collect();
|
||||||
|
mons[0].out = true;
|
||||||
|
Self{mons: mons}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct Instance {
|
||||||
|
mon: mon::Instance,
|
||||||
|
out: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance {
|
||||||
|
fn alive(&self) -> bool {
|
||||||
|
self.mon.damage < self.mon.species.hp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_attack(&self) -> bool {
|
||||||
|
self.out && self.alive()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_be_attacked(&self) -> bool {
|
||||||
|
self.out && self.alive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod instance_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_checks() {
|
||||||
|
let mut i = Instance{
|
||||||
|
mon: mon::Instance::roll(mon::Dex::Pika),
|
||||||
|
out: true,
|
||||||
|
};
|
||||||
|
assert_eq!(true, i.alive());
|
||||||
|
assert_eq!(true, i.can_attack());
|
||||||
|
assert_eq!(true, i.can_be_attacked());
|
||||||
|
i.mon.damage = i.mon.species.hp;
|
||||||
|
assert_eq!(false, i.alive());
|
||||||
|
assert_eq!(false, i.can_attack());
|
||||||
|
assert_eq!(false, i.can_be_attacked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct Idx {
|
||||||
|
pub team: usize,
|
||||||
|
pub mon: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum Move {
|
||||||
|
Pass(Idx),
|
||||||
|
Attack(Idx, Idx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue