use glam::IVec2; use map::Map; use protocol::Direction; use serde::Deserialize; use std::{collections::HashMap, net::SocketAddr, ops::ControlFlow}; pub mod map; pub mod protocol; pub mod server; #[derive(Deserialize, Clone)] pub struct Config { bind: SocketAddr, tickrate: f32, tickrate_speedup: f32, tickrate_max: f32, } pub struct Game { pub heads: HashMap, pub map: Map, pub dead: Vec, } impl Game { pub fn new(players: Vec<(u32, String)>) -> Self { let mut map = Map::new(players.len() * 2, players.len() * 2); let mut heads = HashMap::new(); for (i, (p, name)) in players.into_iter().enumerate() { let pos = IVec2::ONE * i as i32 * 2; map[pos] = Some(p); heads.insert(p, (Direction::Up, pos, name)); } Self { heads, map, dead: Vec::new(), } } pub fn tick(&mut self) -> ControlFlow, ()> { for (_player, (dir, head, _)) in &mut self.heads { *head = (*head + dir.vector()).rem_euclid(self.map.size) } self.dead.clear(); let mut h = HashMap::>::new(); for (player, (_, head, _)) in &self.heads { h.entry(*head).or_default().push(*player); if self.map[*head].is_some() { 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[*head] = Some(*player); } for d in &self.dead { self.map.clear_player(*d); self.heads.remove(&d); } if self.heads.len() <= 1 { ControlFlow::Break(self.heads.keys().next().cloned()) } else { ControlFlow::Continue(()) } } }