//! Helpers to determine if a node can send a particular packet. /// These functions are unfortunately all a bit stringly typed atm pub mod can_send { use crate::data::{Level, PacketType, Upgrade}; use Level::*; #[inline] pub fn base() -> Vec<&'static str> { vec!["ping", "capture"] } /// Guard nodes are the most versatile #[inline] pub fn guard(lvl: Level) -> Vec<&'static str> { match lvl { // This is just kinda gross One => { let mut p = base(); p.append(&mut vec!["payload", "cns", "reset"]); p } Two => { let mut p = guard(One); p.append(&mut vec!["nitm", "virus"]); p } Three => { let mut p = guard(Two); p.append(&mut vec!["takeover"]); p } } } /// Compute nodes can ping and compute but not capture pub fn compute() -> Vec<&'static str> { vec!["ping", "compute"] } /// Relays only relay! pub fn relay() -> Vec<&'static str> { vec![] } } pub mod send { use crate::{ data::{ Level::*, PacketType as Pkt, Upgrade::{self, *}, }, stats::strengths, }; /// Turn the string type identifier into a packet /// /// This function makes heavy use of the stats module, which is /// responsible for balancing all of these values. pub fn build_packet(node: Upgrade, type_: &'static str, prev: Option) -> Pkt { match (prev, node, type_) { // All pings are the same (None, _, "ping") => Pkt::Ping, // TODO: captures should improve (None, Base, "capture") | (None, Guard(_), "capture") => Pkt::Capture, (None, Compute(lvl), "compute") => Pkt::Compute { curr: Default::default(), max: strengths::compute_max(lvl), step: strengths::compute_step(lvl), }, (Some(prev), Guard(lvl), "payload") => Pkt::Payload { inner: Box::new(prev), reward: strengths::payload_reward(lvl), }, (None, Guard(_), "cns") => Pkt::CNS, (None, Guard(_), "reset") => Pkt::Reset, (None, Guard(_), "nitm") => Pkt::Nitm, (None, Guard(_), "virus") => Pkt::Virus, // Only level 3 guards can send takeovers (None, Guard(Three), "takeover") => Pkt::TakeOver, // Can't touch this (_, _, _) => unreachable!(), } } }