mnml/server/src/cryp.rs
2018-09-14 18:46:28 +10:00

205 lines
4.0 KiB
Rust
Executable File

use uuid::Uuid;
use rand::prelude::*;
use serde_cbor::*;
use rpc::{GenerateParams};
use skill::{Skill};
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum StatKind {
Dmg,
Def,
Hp,
Stam,
}
#[derive(Debug,Clone)]
pub struct Roll {
pub base: u64,
pub result: u64,
pub kind: StatKind,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Stat {
pub value: u64,
pub kind: StatKind,
}
impl Stat {
fn set(&mut self, v: u64) -> &Stat {
self.value = v;
self
}
fn roll(&self, c: &Cryp) -> Roll {
let mut rng = thread_rng();
let base: u64 = rng.gen();
let mut roll = Roll { kind: self.kind, base, result: base };
println!("{:?}", self.kind);
println!("{:064b} <- base roll", base);
// apply skills
roll = c.skills.iter().fold(roll, |roll, s| s.apply(roll));
// finally combine with stat
println!("{:064b} <- finalised", roll.result);
roll.result = roll.result & self.value;
println!("{:064b} & <- attribute roll", self.value);
println!("{:064b} = {:?}", roll.result, roll.result);
println!("");
return roll;
}
fn reduce(&mut self, dmg: u64) -> &mut Stat {
self.value = self.value.saturating_sub(dmg);
self
}
}
pub struct Turn {
pub dmg: Roll,
pub def: Roll,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Cryp {
pub id: Uuid,
// todo
// make attributes hold this value
pub dmg: Stat,
pub def: Stat,
pub stam: Stat,
pub hp: Stat,
pub xp: u64,
pub lvl: u8,
pub skills: Vec<Skill>,
pub name: String,
}
fn check_lvl(lvl: u8) -> u8 {
if lvl > 64 { return 64; }
return lvl;
}
impl Cryp {
pub fn new() -> Cryp {
let id = Uuid::new_v4();
return Cryp {
id,
dmg: Stat { value: 0, kind: StatKind::Dmg },
def: Stat { value: 0, kind: StatKind::Def },
stam: Stat { value: 0, kind: StatKind::Stam },
hp: Stat { value: 0, kind: StatKind::Hp },
lvl: 0,
xp: 0,
skills: vec![],
name: String::new()
};
}
pub fn named(mut self, name: String) -> Cryp {
self.name = name.clone();
self
}
pub fn level(mut self, lvl: u8) -> Cryp {
self.lvl = check_lvl(lvl);
self
}
pub fn learn(mut self, s: Skill) -> Cryp {
self.skills.push(s);
self
}
pub fn add_xp(mut self) -> Cryp {
self.xp = self.xp.saturating_add(1);
if self.xp.is_power_of_two() {
return self.level_up();
}
self
}
pub fn level_up(mut self) -> Cryp {
self.lvl = self.lvl.saturating_add(1);
self.create()
}
pub fn turn(&self) -> Turn {
// println!("{:?}'s turn:", c.name);
let dmg = self.dmg.roll(self);
let def = self.def.roll(self);
return Turn { dmg, def }
}
pub fn create(mut self) -> Cryp {
let mut rng = thread_rng();
let max = match self.lvl == 64 {
true => u64::max_value(),
false => 2_u64.pow(self.lvl.into()),
};
self.xp = max;
self.dmg.set(rng.gen_range(1, max));
self.def.set(rng.gen_range(1, max));
self.stam.set(rng.gen_range(1, max));
self.hp.set(self.stam.value);
self
}
pub fn assign_dmg(&mut self, opp: &Cryp, plr_t: &Turn, opp_t: &Turn) -> &mut Cryp {
let final_dmg = opp_t.dmg.result.saturating_sub(plr_t.def.result);
let blocked = opp_t.dmg.result.saturating_sub(final_dmg);
self.hp.reduce(final_dmg);
println!("{:?} deals {:?} dmg to {:?} ({:?} blocked / {:?} hp remaining)"
,opp.name
,final_dmg
,self.name
,blocked
,self.hp.value);
self
}
pub fn is_ko(&self) -> bool {
self.hp.value == 0
}
}
pub fn generate(params: GenerateParams) -> Cryp {
Cryp::new()
.named("hatchling".to_string())
.level(params.level)
.learn(Skill::Stoney)
.create()
}
#[cfg(test)]
mod tests {
use cryp::*;
use skill::*;
#[test]
fn create_cryp_test() {
let max_level = Cryp::new()
.named("hatchling".to_string())
.level(64)
.learn(Skill::Stoney)
.create();
assert_eq!(max_level.lvl, 64);
return;
}
}