deploy the bot in front of its own towers, nothing else
read the client's memory during a live battle and the board told the story at a glance - a column of the bot's objects down one lane, x fixed at 3500, y stepping by exactly two thousand: 23500, 21500, 19500, ... 3500, 1500, -500, -2500 two thousand is BOT_DEPLOY_AHEAD. the landmark was any building the bot owned, so a hut it had just played became the reference for the next card, that card became the reference for the one after, and they walked up the lane and off the top of the map. every one of them had a movie clip and sat exactly where its sprite said - they were never invisible, they were marching into nowhere. the huts spawning from out there are the 177688 addLogicGameObject calls the hook counted. the landmark is now one of the two tower refs the battle already keeps in leader_towers, and nothing else can become one. the harness missed this because the bot had been given the player's deck, which has no buildings in it. it now plays a cannon and a hut, and asserts each deploy lands in front of a tower on the bot's own half - the old code deploys on top of the king tower and fails.
This commit is contained in:
parent
14786cbc92
commit
d13e8458ba
2 changed files with 30 additions and 34 deletions
|
|
@ -102,38 +102,23 @@ impl BattleSession {
|
|||
let card = filled
|
||||
.get(self.random.next(filled.len() as i32).max(0) as usize)?
|
||||
.clone();
|
||||
let towers: Vec<(i32, i32)> = self
|
||||
.mode
|
||||
let leader = self.mode.battle.leader(crate::bot::BOT_OWNER_INDEX as usize)?;
|
||||
let (king_x, king_y) = leader.position();
|
||||
let towers: Vec<(i32, i32)> = self.mode.battle.leader_towers
|
||||
[crate::bot::BOT_OWNER_INDEX as usize]
|
||||
.iter()
|
||||
.filter_map(|tower| {
|
||||
self.mode
|
||||
.battle
|
||||
.objects
|
||||
.objects
|
||||
.iter()
|
||||
.filter(|entry| {
|
||||
entry.owner_index() == crate::bot::BOT_OWNER_INDEX
|
||||
&& entry.stats().is_building()
|
||||
&& entry.is_alive()
|
||||
.find(|entry| entry.global_id == *tower && entry.is_alive())
|
||||
})
|
||||
.map(|entry| entry.position())
|
||||
.collect();
|
||||
let leader = self.mode.battle.leader(crate::bot::BOT_OWNER_INDEX as usize)?;
|
||||
let (king_x, king_y) = leader.position();
|
||||
let front = towers
|
||||
.iter()
|
||||
.copied()
|
||||
.fold((king_x, king_y), |best, tower| {
|
||||
if (tower.1 - king_y).abs() > (best.1 - king_y).abs() {
|
||||
tower
|
||||
} else {
|
||||
best
|
||||
}
|
||||
});
|
||||
let lane: Vec<(i32, i32)> = towers
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|(_, y)| *y == front.1)
|
||||
.collect();
|
||||
let (x, tower_y) = lane
|
||||
.get(self.random.next(lane.len().max(1) as i32).max(0) as usize)
|
||||
let (x, tower_y) = towers
|
||||
.get(self.random.next(towers.len().max(1) as i32).max(0) as usize)
|
||||
.copied()
|
||||
.unwrap_or((king_x, king_y));
|
||||
let ahead = tower_y + (tower_y - king_y).signum() * BOT_DEPLOY_AHEAD;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ fn the_bot_deploys_in_front_of_its_own_towers() {
|
|||
}
|
||||
let builder = BattleBuilder::new(&root);
|
||||
let mut deck = logic::model::LogicSpellDeck::default();
|
||||
for (slot, name) in ["Knight", "Archers", "Goblins", "Giant"].iter().enumerate() {
|
||||
for (slot, name) in ["Knight", "Cannon", "GoblinHut", "Giant"].iter().enumerate() {
|
||||
deck.slots[slot] = Some(logic::model::LogicSpell {
|
||||
data: LogicDataRef::spell(name),
|
||||
..logic::model::LogicSpell::default()
|
||||
|
|
@ -113,12 +113,26 @@ fn the_bot_deploys_in_front_of_its_own_towers() {
|
|||
if tick % 20 == 0 {
|
||||
if let Some((card, at, instance)) = session.bot_play() {
|
||||
let entries = builder.summon(&card, at, 1, 0, instance);
|
||||
let entries_debug = entries.clone();
|
||||
session.reserve_instances(entries.len());
|
||||
for entry in entries {
|
||||
session.push(entry);
|
||||
}
|
||||
assert!(
|
||||
(17000..25000).contains(&at.y) && (at.x == 3500 || at.x == 14500),
|
||||
"the bot deployed at {:?}, which is not in front of one of its towers",
|
||||
(at.x, at.y)
|
||||
);
|
||||
plays += 1;
|
||||
if plays <= 6 { println!("bot played at {:?}", (at.x, at.y)); }
|
||||
if plays <= 8 {
|
||||
println!(
|
||||
"bot played {:?} at {:?}, {} entries, speeds {:?}",
|
||||
card,
|
||||
(at.x, at.y),
|
||||
entries_debug.len(),
|
||||
entries_debug.iter().map(|e| e.stats().speed).collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
session.advance_to(tick);
|
||||
|
|
@ -140,13 +154,10 @@ fn the_bot_deploys_in_front_of_its_own_towers() {
|
|||
break;
|
||||
}
|
||||
for entry in session.mode().battle.objects.objects.iter() {
|
||||
if entry.stats().speed < 1 {
|
||||
continue;
|
||||
}
|
||||
let (x, y) = entry.position();
|
||||
if !((500..=17500).contains(&x) && (1000..=31000).contains(&y)) {
|
||||
println!(
|
||||
"t={tick}: troop owner={} speed={} alive={} at ({x}, {y})",
|
||||
"t={tick}: object owner={} speed={} alive={} at ({x}, {y})",
|
||||
entry.owner_index(),
|
||||
entry.stats().speed,
|
||||
entry.is_alive()
|
||||
|
|
|
|||
Loading…
Reference in a new issue