Every master of a match gets an own portal beside the dungeon

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-06 09:32:40 +01:00
1 parent aeaa1eba36
commit 7b927b0df7
2 files changed
+48 -19

No files matched your search

+47
View File
@@ -1597,6 +1597,8 @@ impl Game {
continue; continue;
} }
self.carve_master_area(*side, cores[k]); self.carve_master_area(*side, cores[k]);
// every master gets a portal of his own (side 0 has the map's portal)
self.add_master_portal(*side, cores[k]);
self.add_master(*side, cores[k]); self.add_master(*side, cores[k]);
self.switch_to(*side); self.switch_to(*side);
let (cx, cy) = cores[k]; let (cx, cy) = cores[k];
@@ -1610,6 +1612,30 @@ impl Game {
true true
} }
// a master's own portal right beside his starting area (if there is room)
pub(crate) fn add_master_portal(&mut self, side: u8, core: (i32, i32)) {
let owner = Owner::of_side(side);
let (px, py) = (core.0 + 6, core.1);
if px + 3 >= mw() as i32 - 2 || py < 2 || py + 3 >= mh() as i32 - 2 {
return;
}
for y in py..py + 3 {
for x in px..px + 3 {
let t = &mut self.map.t[idx(x, y)];
if !matches!(t.kind, Kind::Core | Kind::Gate) {
t.kind = Kind::Portal;
t.owner = owner;
t.gold = 0;
t.marked = false;
t.reinforced = false;
}
}
}
if !self.map.portals.contains(&(px, py)) {
self.map.portals.push((px, py));
}
}
// the starting area of a master: a 9x9 room of his own floor and his 3x3 soul core // the starting area of a master: a 9x9 room of his own floor and his 3x3 soul core
pub(crate) fn carve_master_area(&mut self, side: u8, core: (i32, i32)) { pub(crate) fn carve_master_area(&mut self, side: u8, core: (i32, i32)) {
let owner = Owner::of_side(side); let owner = Owner::of_side(side);
@@ -6831,6 +6857,27 @@ mod tests {
assert!(g.ents.iter().filter(|e| e.kind == EK::Chainbreaker).count() <= 1); assert!(g.ents.iter().filter(|e| e.kind == EK::Chainbreaker).count() <= 1);
} }
#[test]
fn every_master_of_a_coop_mission_has_an_own_portal() {
let m = crate::campaign::coop_mission_indexes()[2];
let mut g = crate::campaign::start_mission(m, None);
g.coop = true;
assert!(g.start_masters(&[0, 2, 3], 0));
for side in [2u8, 3] {
let owner = Owner::of_side(side);
let core = g.masters.iter().find(|m| m.side == side).unwrap().core;
let k = (0..g.map.portals.len()).find(|&k| g.map.portal_owner(k) == owner && g.map.portals[k] == (core.0 + 6, core.1)).expect("a portal of his own");
let (px, py) = g.map.portals[k];
let from = idx(core.0 + 1, core.1 + 4);
assert!(g.map.creature_path(false, from, idx(px, py + 1)).is_some(), "reachable from his dungeon");
}
for n in crate::lobby::MATCH_SIZES {
let seats = crate::lobby::seats_for(n);
let mut m = Game::new(3, n, n);
assert!(m.start_masters(seats, 0), "a {}x{} match with {} seats", n, n, seats.len());
}
}
#[test] #[test]
fn a_coop_ai_seat_fights_beside_the_host_not_against_him() { fn a_coop_ai_seat_fights_beside_the_host_not_against_him() {
let mut g = Game::new(11, 96, 128); let mut g = Game::new(11, 96, 128);
+1 -19
View File
@@ -97,25 +97,7 @@ impl Game {
pub fn add_rival(&mut self, side: u8, cx: i32, cy: i32, difficulty: u8) { pub fn add_rival(&mut self, side: u8, cx: i32, cy: i32, difficulty: u8) {
let core = (cx - 1, cy - 1); let core = (cx - 1, cy - 1);
self.carve_master_area(side, core); self.carve_master_area(side, core);
// his own portal beside the dungeon (if there is room) self.add_master_portal(side, core);
let owner = Owner::of_side(side);
let (px, py) = (core.0 + 6, core.1);
if px + 3 < mw() as i32 - 2 && py >= 2 && py + 3 < mh() as i32 - 2 {
for y in py..py + 3 {
for x in px..px + 3 {
let t = &mut self.map.t[idx(x, y)];
if !matches!(t.kind, Kind::Core | Kind::Gate) {
t.kind = Kind::Portal;
t.owner = owner;
t.gold = 0;
t.reinforced = false;
}
}
}
if !self.map.portals.contains(&(px, py)) {
self.map.portals.push((px, py));
}
}
self.rivals.push(Rival { side, core, hp: RIVAL_CORE_HP, alive: true, radius: 5, grow_t: 20.0, spawn_t: 5.0, attack_t: 0.0, difficulty, power: 0.0, gift_t: PARTNER_GIFT_EVERY, think_t: 2.0, attacking: false, army0: 0.0 }); self.rivals.push(Rival { side, core, hp: RIVAL_CORE_HP, alive: true, radius: 5, grow_t: 20.0, spawn_t: 5.0, attack_t: 0.0, difficulty, power: 0.0, gift_t: PARTNER_GIFT_EVERY, think_t: 2.0, attacking: false, army0: 0.0 });
self.adopt_master(side, core, difficulty, true); self.adopt_master(side, core, difficulty, true);
} }