Masters for a match: the four sides red, green, blue and yellow (side 4 gets its own owner), and start_masters gives every master his core and his starting area
This commit is contained in:
1 parent
35ddfa134c
commit
87890adc53
10 files changed
+132
-9
No files matched your search
+88
-3
@@ -1287,9 +1287,9 @@ impl Game {
|
||||
self.put_active(target);
|
||||
}
|
||||
|
||||
// a new master on `side` with its core at (cx, cy) (top-left of the 3x3 core). Used by the
|
||||
// multiplayer lobby (and its tests); single player games have no stored masters.
|
||||
#[allow(dead_code)]
|
||||
// a new master on `side` with his core at (cx, cy) (top-left of the 3x3 core); single player
|
||||
// games have no stored masters
|
||||
#[allow(dead_code)] // used by the tests; the *Multiplayer* menu (step D) will call it
|
||||
pub fn add_master(&mut self, side: u8, core: (i32, i32)) {
|
||||
let mut m = self.take_active();
|
||||
let me = std::mem::replace(&mut m, MasterState::default());
|
||||
@@ -1311,6 +1311,62 @@ impl Game {
|
||||
self.masters.push(fresh);
|
||||
}
|
||||
|
||||
// A match: `sides` (out of 0, 2, 3, 4 - side 1 is the heroes') play against each other and
|
||||
// `local` is the master who plays at this computer. Side 0 keeps the core of the generated map
|
||||
// (that is where the hero gate path leads); the other masters get their cores at fixed places
|
||||
// worked out from the map size alone, so every client of a match puts them in the same spots.
|
||||
#[allow(dead_code)] // used by the tests; the *Multiplayer* menu (step D) will call it
|
||||
pub fn start_masters(&mut self, sides: &[u8], local: u8) -> bool {
|
||||
let sides: Vec<u8> = sides.iter().copied().filter(|s| Owner::MASTER_SIDES.contains(s)).collect();
|
||||
if sides.len() < 2 || !sides.contains(&0) || !sides.contains(&local) {
|
||||
return false;
|
||||
}
|
||||
let (w, h) = (mw() as i32, mh() as i32);
|
||||
if w < 72 || h < 72 {
|
||||
return false; // the master areas need room
|
||||
}
|
||||
let cores: Vec<(i32, i32)> = sides.iter().map(|&s| match s { 0 => self.map.core, 2 => (w - 30, 12), 3 => (w - 30, h - 16), _ => (14, h - 16) }).collect();
|
||||
for (k, side) in sides.iter().enumerate() {
|
||||
if *side == self.me_side {
|
||||
continue;
|
||||
}
|
||||
self.carve_master_area(*side, cores[k]);
|
||||
self.add_master(*side, cores[k]);
|
||||
}
|
||||
self.local_side = local;
|
||||
self.switch_to(local);
|
||||
true
|
||||
}
|
||||
|
||||
// the starting area of a master: a 9x9 room of his own floor and his 3x3 soul core
|
||||
#[allow(dead_code)] // called by start_masters only
|
||||
fn carve_master_area(&mut self, side: u8, core: (i32, i32)) {
|
||||
let owner = Owner::of_side(side);
|
||||
for y in core.1 - 3..core.1 + 6 {
|
||||
for x in core.0 - 3..core.0 + 6 {
|
||||
if x < 2 || y < 2 || x >= mw() as i32 - 2 || y >= mh() as i32 - 2 {
|
||||
continue;
|
||||
}
|
||||
let t = &mut self.map.t[idx(x, y)];
|
||||
if matches!(t.kind, Kind::Portal | Kind::Gate | Kind::Core) {
|
||||
continue;
|
||||
}
|
||||
t.kind = Kind::Floor;
|
||||
t.owner = owner;
|
||||
t.gold = 0;
|
||||
t.marked = false;
|
||||
t.reinforced = false;
|
||||
}
|
||||
}
|
||||
for y in 0..3 {
|
||||
for x in 0..3 {
|
||||
let t = &mut self.map.t[idx(core.0 + x, core.1 + y)];
|
||||
t.kind = Kind::Core;
|
||||
t.owner = owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_units(&mut self, dt: f32) {
|
||||
for i in 0..self.ents.len() {
|
||||
if !self.ents[i].alive || self.ents[i].held {
|
||||
@@ -5341,6 +5397,35 @@ mod tests {
|
||||
assert!(e.alive && g.map.walk(e.x as i32, e.y as i32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_match_gives_every_master_his_core_and_his_ground() {
|
||||
let mut g = Game::new(7, 96, 128);
|
||||
g.init_fog();
|
||||
assert!(g.start_masters(&[0, 2, 3, 4], 2), "four masters, and I am the green one");
|
||||
assert_eq!(g.local_side, 2);
|
||||
assert_eq!(g.masters.len(), 3);
|
||||
for side in Owner::MASTER_SIDES {
|
||||
let owner = Owner::of_side(side);
|
||||
assert!(g.is_master(side));
|
||||
let cores = g.map.t.iter().filter(|t| t.kind == Kind::Core && t.owner == owner).count();
|
||||
assert_eq!(cores, 9, "master {side} has his soul core");
|
||||
let ground = g.map.t.iter().filter(|t| t.kind == Kind::Floor && t.owner == owner).count();
|
||||
assert!(ground >= 40, "master {side} has a starting area of his own");
|
||||
g.switch_to(side);
|
||||
assert_eq!(g.core_hp, CORE_HP, "every core starts intact");
|
||||
assert_eq!(g.gold, 1500.0, "and every master with the same gold");
|
||||
}
|
||||
g.switch_to(2);
|
||||
let green = g.map.core;
|
||||
g.switch_to(4);
|
||||
assert_ne!(g.map.core, green, "the masters live apart");
|
||||
for _ in 0..50 {
|
||||
g.update(STEP);
|
||||
}
|
||||
assert_eq!(g.sim_steps, 50, "every master is simulated");
|
||||
assert_eq!(g.me_side, 2, "the saddle goes back to the master who plays here");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lava_burns_and_needs_stone_bridges() {
|
||||
let (mut g, rx) = river_game(true);
|
||||
|
||||
Reference in new issue
Block a user