Renderer, Oberfläche, Eingabe, Sound-Modul, Simulationstest und Docker-Setup (Port 18093)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
14e481cffb
commit
db417b3af8
13 files changed
+1930
-19
No files matched your search
+80
-4
@@ -380,9 +380,6 @@ impl Game {
|
||||
pub fn worker_count(&self) -> usize {
|
||||
self.ents.iter().filter(|e| e.alive && !e.hero && e.kind == EK::Worker).count()
|
||||
}
|
||||
pub fn hero_count(&self) -> usize {
|
||||
self.ents.iter().filter(|e| e.alive && e.hero).count()
|
||||
}
|
||||
pub fn summon_cost(&self) -> f32 {
|
||||
80.0 + 20.0 * (self.worker_count() as f32 - 4.0).max(0.0)
|
||||
}
|
||||
@@ -1027,7 +1024,7 @@ impl Game {
|
||||
let fxx = (e.x + tx as f32 + 0.5) * 0.5;
|
||||
let fxy = (e.y + ty as f32 + 0.5) * 0.5;
|
||||
let tl = &mut self.map.t[t];
|
||||
let mut done = false;
|
||||
let done;
|
||||
if tl.kind == Kind::Gold {
|
||||
let take = tl.gold.min(25);
|
||||
tl.gold -= take;
|
||||
@@ -1802,3 +1799,82 @@ pub fn job_name(e: &Ent) -> &'static str {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// Simuliert ein Spiel mit einfacher "KI-Spielerin" und prüft, dass nichts abstürzt.
|
||||
#[test]
|
||||
fn simulate_long_game() {
|
||||
for seed in [1u32, 7, 12345] {
|
||||
let mut g = Game::new(seed);
|
||||
let (cx, cy) = g.map.core;
|
||||
let (px, py) = g.map.portal;
|
||||
// Weg zum Portal graben (durch Erde/Gold, um Fels herum)
|
||||
let start = idx(cx - 1, cy + 1);
|
||||
let goal = idx(px + 1, py + 1);
|
||||
let path = g
|
||||
.map
|
||||
.search(start, |i| if g.map.t[i].kind == Kind::Rock { None } else { Some(1) }, |i| i == goal, false)
|
||||
.expect("Portal erreichbar");
|
||||
for i in path {
|
||||
if g.map.t[i].diggable() {
|
||||
g.map.t[i].marked = true;
|
||||
}
|
||||
}
|
||||
g.mark_rect(cx - 6, cy - 6, cx + 9, cy + 9, true);
|
||||
let (ox, oy) = (cx - 3, cy - 3);
|
||||
g.build_rect(1, ox, oy, ox + 2, oy + 1); // Quartier 3x2
|
||||
g.build_rect(2, ox + 5, oy, ox + 7, oy + 1); // Pilzgarten 3x2
|
||||
let dt = 0.05;
|
||||
let mut built = false;
|
||||
let mut portal_logged = false;
|
||||
for step in 0..(40 * 60 * 20) {
|
||||
g.update(dt);
|
||||
g.events.clear();
|
||||
g.msgs.clear();
|
||||
if step % 200 == 0 && !built && g.gold > 1900.0 {
|
||||
g.build_rect(0, ox, oy + 6, ox + 1, oy + 8); // Schatzkammer
|
||||
g.build_rect(3, ox + 6, oy + 6, ox + 8, oy + 8); // Training
|
||||
g.build_rect(1, ox, oy + 2, ox + 2, oy + 2); // Quartier erweitern
|
||||
built = true;
|
||||
}
|
||||
// Bot nutzt den Blitz gegen Helden am Kern
|
||||
if step % 20 == 0 && g.mana >= 50.0 {
|
||||
let target = g.ents.iter().find(|e| e.alive && e.hero && (e.x - cx as f32).abs() < 4.0 && (e.y - cy as f32).abs() < 4.0).map(|e| (e.x, e.y));
|
||||
if let Some((x, y)) = target {
|
||||
g.lightning(x, y);
|
||||
}
|
||||
}
|
||||
if step == 20 * 60 * 20 {
|
||||
let (gx, gy) = g.map.gate;
|
||||
g.set_flag(gx + 1, gy + 1);
|
||||
}
|
||||
if step % 2400 == 0 {
|
||||
println!(
|
||||
"seed {} t={:>5.0}s gold={:>5.0} creatures={} workers={} wave={} core={:.0} gate={:.0} heroes={} army={:.0}",
|
||||
seed,
|
||||
g.time,
|
||||
g.gold,
|
||||
g.creature_count(),
|
||||
g.worker_count(),
|
||||
g.wave,
|
||||
g.core_hp,
|
||||
g.gate_hp,
|
||||
g.ents.iter().filter(|e| e.alive && e.hero).count(),
|
||||
g.army_value()
|
||||
);
|
||||
}
|
||||
if g.portal_owned() && step % 20 == 0 && !portal_logged {
|
||||
portal_logged = true;
|
||||
println!("seed {} Portal erobert nach {:.0}s", seed, g.time);
|
||||
}
|
||||
if g.state != 0 {
|
||||
println!("seed {} Ende nach {:.0}s, state={}", seed, g.time, g.state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user