This commit is contained in:
ntr
2018-08-27 22:16:49 +10:00
parent 8de7d1be20
commit cb369e4683
8 changed files with 3 additions and 3 deletions
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "cryps"
version = "0.1.0"
authors = ["ntr <ntr@smokestack.io>"]
[dependencies]
rand = "0.5.4"
uuid = { version = "0.6", features = ["serde", "v4"] }
serde_json = "1.0.24"
+91
View File
@@ -0,0 +1,91 @@
# Cryps ("creeps") // Creeptography
## Items
## Rolling
stat & rng
block hash or totally random
roll server that prints a roll every second?
friendship on ties?
Def
0001011011001100110101000000101111100110101111110100100001000001 - roll
0000000000000000000000000000000000000000000000000000000000001111 ^ steel armour
0000000000000000000000000000000000000000000000000000001111000000 ^ stoney trait
0001011011001100110101000000101111100110101111110100101111001111 = modified roll
0000000000000000000000000000000000000000000000000000000111000010 & def attribute
0000000000000000000000000000000000000000000000000000000111000010 = roll w/ stats
0000000000000000000000000000000000000000000000000000000001000000 = roll w/out stats
## missions
also the idea is like
the currency is kinda like path right
you're trying to get like chaos
to reroll some stat
or some item
so maybe like a sword
has 5 bits of damage it can guarantee
but a badman-sabre has 16 bits
and you keep blowing chaos on it til it gets 1111111111
MashyToday at 9:04 PM
yeah that would be cool
natureToday at 9:05 PM
i feel like that would make it kinda p2w
so probably needs limits
MashyToday at 9:05 PM
I was thinking the p2w more just like making the needs and missions quicker right
so like instead of feeding your dude you get some item where hes fed for 2 days or something
or you could reduce the mission time which is like kinda pay to win but not really
natureToday at 9:06 PM
well what do the missions give you
MashyToday at 9:06 PM
well thats what i was thinking you'd do to get items
so instead of doing a zone in an rpg and getting all this loot
you send your dude out and you got a notification 4 hours later like success / failure this is what you got back
natureToday at 9:07 PM
i was thinking aobut that
i don't really like the possibility of failure on a mission
imagine sending your dude out on a mission for 2 days and it ceoms back like "nope wrong"
i'd just fucken rq
MashyToday at 9:08 PM
Yeah
natureToday at 9:08 PM
BUT
a better thing is like
playing off crypto
MashyToday at 9:08 PM
its something like this https://www.youtube.com/watch?v=bXLW9dF7LN8
YouTube
Tommy J
WoW: Garrison Mission Chance - How it Works
natureToday at 9:08 PM
missions are like
MashyToday at 9:08 PM
so you get told before hand the % chance for success
natureToday at 9:08 PM
go and do 2000 overkill damage to some monster
and your dude is out there using his items and rolling
so it can happen quick if you're lucky
or slow if you're not
but still will eventually happen
and then you get like easy limits for missions right
MashyToday at 9:09 PM
yeah that would be better actually
natureToday at 9:09 PM
like a creep that onl deals 100 dmg can't finish that mission
i feel like that would be good
cause then if you have like a defensive cryp
it could have a defensive kinda mission
like go and block 40000 damage in pve
and then it gets some baller shield
and is like speccing into defense
MashyToday at 9:10 PM
sounds better
natureToday at 9:10 PM
and like an offensive cryp could do that too
but it might keep getting KOd
and you hvae to pay to revive it
+57
View File
@@ -0,0 +1,57 @@
// use uuid::Uuid;
use rand::prelude::*;
use cryp::Cryp;
// impl Attribute {
// pub fn as_str(&self) -> &'static str {
// match self {
// Dmg => "dmg",
// Def => "def",
// }
// }
// }
#[derive(Debug)]
pub struct Battle {
a: Cryp,
b: Cryp,
}
impl Battle {
pub fn new(a: &Cryp, b: &Cryp) -> Battle {
return Battle {
a: a.clone(),
b: b.clone(),
};
}
pub fn cryps(&self) -> Vec<&Cryp> {
vec![&self.a, &self.b]
}
pub fn next(&mut self) -> &mut Battle {
let a_turn = self.a.turn();
let b_turn = self.b.turn();
self.a.assign_dmg(&self.b, &a_turn, &b_turn);
self.b.assign_dmg(&self.a, &b_turn, &a_turn);
self
}
pub fn finished(&self) -> bool {
self.cryps().iter().any(|c| c.is_ko())
}
pub fn winner(&self) -> Option<&Cryp> {
if self.cryps().iter().all(|c| c.is_ko()) {
return None
}
match self.cryps().iter().find(|c| !c.is_ko()) {
Some(w) => Some(w),
None => panic!("no winner found {:?}", self),
}
}
}
+83
View File
@@ -0,0 +1,83 @@
use rand::prelude::*;
use cryp::Cryp;
use battle::Battle;
struct Encounter {
mob: Cryp,
success: bool,
player: Cryp,
}
pub fn battle(a: &Cryp, b: &Cryp) -> Battle {
let mut battle = Battle::new(a, b);
loop {
battle.next();
if battle.finished() {
break battle
}
}
}
fn pve(plr: Cryp) -> Encounter {
let mut rng = thread_rng();
let mob_lvl: u8 = rng.gen_range(1, plr.lvl);
let mob = Cryp::new()
.named("bamboo basher".to_string())
.level(mob_lvl)
.create();
let outcome = battle(&plr, &mob);
let success = match outcome.winner() {
Some(c) => c.id == plr.id,
None => false,
};
return Encounter {
mob: mob,
success,
player: plr,
};
}
pub fn levelling(mut c: Cryp) -> Cryp {
loop {
let enc = pve(c);
c = enc.player;
if !enc.success {
println!("{:?} has been KO'd", c.name);
break c;
}
println!("{:?} rekt {:?}", c.name, enc.mob.name);
c = c.add_xp();
println!("{:?} now has {:?} xp and is lvl {:?}", c.name, c.xp, c.lvl);
// LEVEL CAP
if c.lvl == 12 {
break c;
}
continue;
}
}
#[cfg(test)]
mod tests {
use *;
#[test]
fn pve_test() {
// let player = Cryp::new()
// .named("ca phe sua da".to_string())
// .level(2)
// .create();
// levelling(player);
return;
}
}
+198
View File
@@ -0,0 +1,198 @@
use uuid::Uuid;
use rand::prelude::*;
use skill::Skill;
#[derive(Debug,Clone,Copy,PartialEq)]
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)]
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)]
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 lvl_as_two_pwr = 2_u64.pow(self.lvl.into());
let max = match self.lvl == 64 {
true => u64::max_value(),
false => lvl_as_two_pwr,
};
self.xp = lvl_as_two_pwr;
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
}
}
#[cfg(test)]
mod tests {
use cryp::{StatKind,Skill};
use *;
#[test]
fn create_cryp_test() {
let mut level_two = Cryp::new()
.named("hatchling".to_string())
.level(2)
.learn(Skill::Stoney)
.create();
// assert!(level_two.dmg <= 2_u64.pow(2));
// assert!(level_two.def <= 2_u64.pow(2));
assert_eq!(level_two.skills.len(), 1);
println!("{:?}", level_two);
return;
}
}
+46
View File
@@ -0,0 +1,46 @@
extern crate rand;
extern crate uuid;
mod cryp;
mod combat;
mod battle;
mod skill;
use combat::{battle, levelling};
use battle::{Battle};
use cryp::{Cryp, StatKind};
use skill::{Skill};
pub fn main() {
let mut a = Cryp::new()
.named("pronounced \"creeep\"".to_string())
.level(8)
.learn(Skill::Stoney)
.create();
let b = Cryp::new()
.named("lemongrass tea".to_string())
.level(8)
.create();
let outcome = battle(&a, &b);
match outcome.winner() {
Some(w) => println!("{:?} is the winner with {:?} hp remaining", w.name, w.hp),
None => println!("{:?} was a draw", outcome),
};
return
}
#[cfg(test)]
mod tests {
use *;
#[test]
fn battle_test() {
main();
return;
}
}
+41
View File
@@ -0,0 +1,41 @@
use cryp::{StatKind, Roll};
#[derive(Debug,Clone,Copy,PartialEq)]
pub enum Skill {
Stoney,
Evasive,
}
impl Skill {
pub fn apply(&self, mut roll: Roll) -> Roll {
match self {
Skill::Stoney => stoney(self, roll),
Skill::Evasive => evasive(self, roll),
_ => panic!("missing skill"),
}
}
}
fn stoney(s: &Skill, mut roll: Roll) -> Roll {
let effect = 0b11110000;
match roll.kind {
StatKind::Def => {
println!("{:064b} | <- {:?}", effect, s);
roll.result = roll.result | effect;
roll
},
_ => roll,
}
}
fn evasive(s: &Skill, mut roll: Roll) -> Roll {
match roll.kind {
StatKind::Def => {
if roll.result.is_power_of_two() {
roll.result = u64::max_value()
}
roll
},
_ => roll,
}
}