Skip to content

Commit

Permalink
Add PathfindingGrid, precompute paths for each empty tile
Browse files Browse the repository at this point in the history
  • Loading branch information
JesseEmond committed Oct 5, 2024
1 parent 8675454 commit 4563896
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
5 changes: 4 additions & 1 deletion bot/benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
use pprof::criterion::{Output, PProfProfiler};

use devnull_bot::grid::{make_grid, Pos};
use devnull_bot::pathfinding::{get_aggressive_path};
use devnull_bot::pathfinding::{get_aggressive_path, PathfindingGrid};

pub fn criterion_benchmark(c: &mut Criterion) {
let grid = make_grid(vec![
Expand Down Expand Up @@ -32,6 +32,9 @@ pub fn criterion_benchmark(c: &mut Criterion) {
black_box(&grid), black_box(&Pos { x: 5, y: 1 }),
black_box(&Pos { x: 9, y: 1 })));
});
c.bench_function("PathfindingGrid 22x15 creation", |b| {
b.iter(|| PathfindingGrid::new(black_box(grid.clone())));
});
}

criterion_group! {
Expand Down
20 changes: 20 additions & 0 deletions bot/src/pathfinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,26 @@ impl Pathfinder for FastAggressivePathfinder {
}
}

/// Grid that precomputes pathfinding information at creation time.
pub struct PathfindingGrid {
pub grid: Grid,
/// Per-empty tile precomputed pathfinding information.
pathfinding_states: Vec<PathfinderState>,
}

impl PathfindingGrid {
pub fn new(grid: Grid) -> Self {
let mut pathfinding_states = Vec::new();
for pos in &grid.empty_tiles {
// TODO: Consider using a non "aggressive" pathfinder -- can be a
// regularly optimized one not matching the JS details.
let mut pathfinder = FastAggressivePathfinder::new(&grid);
pathfinding_states.push(pathfinder.pathfind(&grid, &pos, &None));
}
Self { grid, pathfinding_states }
}
}

pub fn get_aggressive_path(grid: &Grid, from: &Pos, to: &Pos) -> Vec<Pos> {
let mut pathfinder = FastAggressivePathfinder::new(grid);
let state = pathfinder.pathfind(grid, from, &Some(*to));
Expand Down
20 changes: 10 additions & 10 deletions bot/src/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use strum_macros::EnumIter;
use once_cell::sync::Lazy;

use crate::grid::{Grid, Move, Pos};
use crate::pathfinding::get_aggressive_path;
use crate::pathfinding::{get_aggressive_path, PathfindingGrid};

const MAX_TICKS: usize = 2000;

Expand Down Expand Up @@ -74,21 +74,21 @@ impl Threat {
}

/// Returns whether we know how to simulate this threat.
fn simulate(&mut self, tick: usize, player: &Pos, grid: &Grid) -> bool {
fn simulate(&mut self, tick: usize, player: &Pos, grid: &PathfindingGrid) -> bool {
if !Self::moves_on_tick(tick) {
return false;
}
let next_move = match self.style {
Style::Goldfish => {
// See girouette.js
let directions = self.get_possible_directions(&grid);
let directions = self.get_possible_directions(&grid.grid);
let o = self._next_rand() * directions.len() as f64;
let idx = o.floor();
Some(directions[idx as usize])
},
Style::Bull => {
// See straight_ahead_threat.js
let directions = self.get_possible_directions(&grid);
let directions = self.get_possible_directions(&grid.grid);
if directions.contains(&self.dir) {
Some(self.dir)
} else {
Expand All @@ -99,7 +99,7 @@ impl Threat {
},
Style::Deer => {
// See tse_le_fantome_orange_dans_pacman.js
let directions = self.get_possible_directions(&grid);
let directions = self.get_possible_directions(&grid.grid);
if directions.len() == 1 {
Some(directions[0])
} else {
Expand All @@ -117,7 +117,7 @@ impl Threat {
},
Style::Shark => {
// See aggressive.js
let path = get_aggressive_path(&grid, &self.pos, &player);
let path = get_aggressive_path(&grid.grid, &self.pos, &player);
if !path.is_empty() {
let next = path[0];
assert!(next != self.pos);
Expand Down Expand Up @@ -192,7 +192,7 @@ pub struct Game {

#[derive(Clone)]
pub struct State {
pub grid: Arc<Grid>,
pub grid: Arc<PathfindingGrid>,
pub tick: usize,
pub pos: Pos,
prev_pos: Pos,
Expand All @@ -207,7 +207,7 @@ impl State {
// https://github.com/JesseEmond/blitz-2025-registration/blob/dbe84ed80ebc441d071d5e6eb0d6a476d580a9e2/disassembled_js/490a918d96484178d4b23d814405ac87/challenge/threats/threat.decomp.js#L467
let prev_pos = Pos { x: -1, y: -1 };
let mut state = State {
grid: Arc::new(game.grid),
grid: Arc::new(PathfindingGrid::new(game.grid)),
tick: game.tick,
pos: game.pos,
prev_pos,
Expand All @@ -222,9 +222,9 @@ impl State {
pub fn generate_moves(&self) -> Vec<Option<Move>> {
let mut moves = Vec::new();
if self.is_player_turn() {
moves.extend(self.grid.available_moves(&self.pos).iter().map(|&m| Some(m)));
moves.extend(self.grid.grid.available_moves(&self.pos).iter().map(|&m| Some(m)));
} else {
moves.extend(self.grid.available_moves(&self.threat_turn().pos).iter().map(|&m| Some(m)));
moves.extend(self.grid.grid.available_moves(&self.threat_turn().pos).iter().map(|&m| Some(m)));
}
moves.push(None);
moves
Expand Down

0 comments on commit 4563896

Please sign in to comment.