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;
}
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.switch_to(*side);
let (cx, cy) = cores[k];
@@ -1610,6 +1612,30 @@ impl Game {
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
pub(crate) fn carve_master_area(&mut self, side: u8, core: (i32, i32)) {
let owner = Owner::of_side(side);
@@ -6831,6 +6857,27 @@ mod tests {
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]
fn a_coop_ai_seat_fights_beside_the_host_not_against_him() {
let mut g = Game::new(11, 96, 128);