aboutsummaryrefslogtreecommitdiff
path: root/src/game/mod.rs
blob: f59b5d584a6758b9e7c417f9f8af21626f96cb11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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,
}

pub struct Game {
    pub heads: HashMap<u32, (Direction, IVec2, String)>,
    pub map: Map,
    pub dead: Vec<u32>,
}
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 (p, name) in players {
            let pos = IVec2::ONE * p 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<Option<u32>, ()> {
        for (_player, (dir, head, _)) in &mut self.heads {
            *head = (*head + dir.vector()).rem_euclid(self.map.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[*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(())
        }
    }
}