aboutsummaryrefslogtreecommitdiff
path: root/src/game/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/mod.rs')
-rw-r--r--src/game/mod.rs71
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(())
+ }
+ }
+}