Steel walls: plate earth walls next to own ground with steel

- New tool Steel (key O, orders category; campaign from mission 11): 80 gold per earth wall,
  40 for a reinforced wall; riveted iron plate texture
- Heroes dig through steel 20 times slower than through earth and avoid it (path cost 300)
- Selling turns a steel wall back into a reinforced wall and refunds half the plating
- Texts EN/DE, test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-03 13:10:04 +01:00
1 parent f298e13d6e
commit 8853d84564
10 files changed
+156 -16

No files matched your search

+81 -1
View File
@@ -418,6 +418,9 @@ pub const ROOM_NAMES: [&str; 8] = ["room.treasury", "room.lair", "room.farm", "r
// bridge cost per tile: over water, over lava
pub const BRIDGE_COST: [i32; 2] = [30, 75];
// steel wall cost per tile: from earth, from a reinforced wall
pub const STEEL_COST: [i32; 2] = [80, 40];
pub const STEEL_HP: f32 = 40.0;
pub fn room_index(k: Kind) -> Option<usize> {
ROOM_KINDS.iter().position(|&r| r == k)
@@ -1399,7 +1402,13 @@ impl Game {
EK::Dwarf => 3.0,
EK::Paladin => 2.0,
_ => 1.0,
} * if tile.reinforced { 0.2 } else { 1.0 };
} * if tile.kind == Kind::Steel {
0.05
} else if tile.reinforced {
0.2
} else {
1.0
};
self.fx(6, tx as f32 + 0.5, ty as f32 + 0.5, 0.0, 0.0, 0.4, 0xff3a5a7a);
self.sfx(Sfx::Dig, tx as f32 + 0.5, ty as f32 + 0.5);
let t = &mut self.map.t[next];
@@ -1780,6 +1789,48 @@ impl Game {
// Bridges grow from own ground into the river: every pass adds the river tiles of the
// rectangle that touch own walkable ground (including bridges built in the pass before)
// Earth walls next to own ground become steel walls
pub fn build_steel(&mut self, x0: i32, y0: i32, x1: i32, y1: i32) {
let (mut built, mut broke) = (0, false);
for y in y0.min(y1)..=y0.max(y1) {
for x in x0.min(x1)..=x0.max(x1) {
if !inb(x, y) {
continue;
}
let t = self.map.t[idx(x, y)];
if t.kind != Kind::Earth || t.owner == Owner::Hero {
continue;
}
let own = DIR4.iter().any(|&(dx, dy)| self.map.get(x + dx, y + dy).map_or(false, |n| n.owner == Owner::Player && n.walkable()));
if !own {
continue;
}
let cost = STEEL_COST[t.reinforced as usize] as f32;
if self.gold < cost {
broke = true;
continue;
}
self.gold -= cost;
let tl = &mut self.map.t[idx(x, y)];
tl.kind = Kind::Steel;
tl.reinforced = true;
tl.marked = false;
tl.hp = STEEL_HP;
built += 1;
self.fx(8, x as f32 + 0.5, y as f32 + 0.5, 0.0, 0.0, 0.5, 0xffd0d0d0);
if built == 1 {
self.sfx(Sfx::Reinforce, x as f32 + 0.5, y as f32 + 0.5);
}
}
}
if broke {
self.msg("msg.no_gold", vec![]);
self.sfx_ui(Sfx::Error);
} else if built == 0 {
self.hint(23, "hint.steel_where");
}
}
pub fn build_bridges(&mut self, x0: i32, y0: i32, x1: i32, y1: i32) {
let (mut built, mut broke, mut any_river) = (0, false, false);
loop {
@@ -3361,6 +3412,13 @@ impl Game {
continue;
}
let t = &mut self.map.t[i];
if t.kind == Kind::Steel {
t.kind = Kind::Earth;
t.reinforced = true;
t.hp = 12.0;
refund += STEEL_COST[1] as f32 * 0.5;
continue;
}
if t.owner == Owner::Player && t.bridge() {
let lava = t.kind == Kind::LavaBridge;
t.kind = if lava { Kind::Lava } else { Kind::Water };
@@ -4637,6 +4695,28 @@ mod tests {
assert!(seen.iter().all(|&k| flies(k)), "no lair: only flyers come ({:?})", seen);
}
#[test]
fn steel_walls_hold_heroes_back() {
let mut g = Game::new(3, 64, 64);
let (cx, cy) = g.map.core;
let (wx, wy) = (cx + 6, (cy - 3..=cy + 5).find(|&y| g.map.t[idx(cx + 6, y)].kind == Kind::Earth).unwrap());
g.gold = 1000.0;
g.build_steel(wx, wy, wx, wy);
assert_eq!(g.map.t[idx(wx, wy)].kind, Kind::Steel);
assert_eq!(g.gold, 1000.0 - STEEL_COST[0] as f32);
// far from own ground: nothing happens
g.build_steel(wx + 5, wy, wx + 5, wy);
assert_ne!(g.map.t[idx(wx + 5, wy)].kind, Kind::Steel);
// heroes avoid it and dig 20 times slower than through earth
assert_eq!(g.map.hero_cost()(idx(wx, wy)), Some(300));
// selling: a reinforced earth wall again, half of the plating back
let gold = g.gold;
g.sell_rect(wx, wy, wx, wy);
assert_eq!(g.map.t[idx(wx, wy)].kind, Kind::Earth);
assert!(g.map.t[idx(wx, wy)].reinforced);
assert!(g.gold > gold);
}
#[test]
fn imps_reinforce_walls() {
let mut g = Game::new(3, 64, 64);