diff options
Diffstat (limited to 'src/game/mod.rs')
-rw-r--r-- | src/game/mod.rs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/game/mod.rs b/src/game/mod.rs new file mode 100644 index 0000000..27faa27 --- /dev/null +++ b/src/game/mod.rs @@ -0,0 +1,71 @@ +use glam::IVec2; +use protocol::Direction; +use serde::Deserialize; +use std::{collections::HashMap, net::SocketAddr, ops::ControlFlow}; + +pub mod protocol; +pub mod server; + +#[derive(Deserialize)] +pub struct Config { + bind: SocketAddr, +} + +pub struct Game { + pub heads: HashMap<u32, (Direction, IVec2, String)>, + pub map: HashMap<IVec2, u32>, + pub size: IVec2, + pub dead: Vec<u32>, +} +impl Game { + pub fn new(players: Vec<String>) -> Self { + let mut map = HashMap::new(); + let mut heads = HashMap::new(); + let plen = players.len(); + for (p, name) in players.into_iter().enumerate() { + let pos = IVec2::ONE * p as i32 * 2; + map.insert(pos, p as u32); + heads.insert(p as u32, (Direction::Up, pos, name)); + } + Self { + size: IVec2::ONE * plen as i32 * 2, + heads, + map, + dead: Vec::new(), + } + } + pub fn tick(&mut self) -> ControlFlow<Option<u32>, ()> { + for (_player, (dir, head, _)) in &mut self.heads { + *head = (*head + dir.vector()).rem_euclid(self.size) + } + + self.dead.clear(); + let mut h = HashMap::<IVec2, Vec<u32>>::new(); + for (player, (_, head, _)) in &self.heads { + h.entry(*head).or_default().push(*player); + if self.map.contains_key(head) { + self.dead.push(*player); + } + } + for (_, hp) in h { + if hp.len() > 1 { + self.dead.extend(hp) + } + } + + for (player, (_, head, _)) in &mut self.heads { + self.map.insert(*head, *player); + } + + for d in &self.dead { + self.map.retain(|_, p| *d != *p); + self.heads.remove(&d); + } + + if self.heads.len() <= 1 { + ControlFlow::Break(self.heads.keys().next().cloned()) + } else { + ControlFlow::Continue(()) + } + } +} |