Skip to main content

advanced_pathfinding/
advanced_pathfinding.rs

1//! Advanced Pathfinding Demo
2//!
3//! Demonstrates Dijkstra maps and flow fields for AI pathfinding
4
5use terrain_forge::{
6    algorithms,
7    spatial::{dijkstra_map, flow_field_from_dijkstra, PathfindingConstraints},
8    Grid, Tile,
9};
10
11fn main() {
12    println!("=== Advanced Pathfinding Demo ===\n");
13
14    // Generate a dungeon layout
15    let mut grid = Grid::new(25, 20);
16    let algo = algorithms::get("bsp").unwrap();
17    algo.generate(&mut grid, 54321);
18
19    println!("1. Dungeon Layout (25x20):");
20    print_grid(&grid);
21
22    // Single goal pathfinding
23    println!("\n2. Single Goal Dijkstra Map:");
24    let goals = vec![(12, 10)]; // Center goal
25    let constraints = PathfindingConstraints::default();
26    let dijkstra = dijkstra_map(&grid, &goals, &constraints);
27    print_dijkstra_map(&dijkstra);
28
29    // Multiple goals pathfinding
30    println!("\n3. Multiple Goals Dijkstra Map:");
31    let goals = vec![(5, 5), (20, 15), (15, 5)]; // Three goals
32    let dijkstra_multi = dijkstra_map(&grid, &goals, &constraints);
33    print_dijkstra_map(&dijkstra_multi);
34
35    // Flow field generation
36    println!("\n4. Flow Field from Single Goal:");
37    let flow = flow_field_from_dijkstra(&dijkstra);
38    print_flow_field(&flow);
39
40    // Custom movement costs
41    println!("\n5. Custom Movement Costs (diagonal penalty):");
42    let mut custom_constraints = PathfindingConstraints::default();
43    custom_constraints.movement_cost.insert((-1, -1), 2.0);
44    custom_constraints.movement_cost.insert((-1, 1), 2.0);
45    custom_constraints.movement_cost.insert((1, -1), 2.0);
46    custom_constraints.movement_cost.insert((1, 1), 2.0);
47
48    let dijkstra_custom = dijkstra_map(&grid, &goals, &custom_constraints);
49    print_dijkstra_map(&dijkstra_custom);
50
51    // Performance analysis
52    println!("\n6. Performance Analysis:");
53    let start = std::time::Instant::now();
54    let _ = dijkstra_map(&grid, &goals, &constraints);
55    println!("   Dijkstra map generation: {:?}", start.elapsed());
56
57    let start = std::time::Instant::now();
58    let _ = flow_field_from_dijkstra(&dijkstra);
59    println!("   Flow field generation: {:?}", start.elapsed());
60}
61
62fn print_grid(grid: &Grid<Tile>) {
63    for y in 0..grid.height() {
64        for x in 0..grid.width() {
65            let tile = grid.get(x as i32, y as i32).unwrap();
66            print!("{}", if tile.is_floor() { "." } else { "#" });
67        }
68        println!();
69    }
70}
71
72fn print_dijkstra_map(dijkstra: &terrain_forge::spatial::DijkstraMap) {
73    for y in 0..dijkstra.height() {
74        for x in 0..dijkstra.width() {
75            let cost = dijkstra.get(x, y);
76            if cost == f32::INFINITY {
77                print!("### ");
78            } else if cost < 100.0 {
79                print!("{:3.0} ", cost);
80            } else {
81                print!("+++ ");
82            }
83        }
84        println!();
85    }
86}
87
88fn print_flow_field(flow: &terrain_forge::spatial::FlowField) {
89    for y in 0..flow.height() {
90        for x in 0..flow.width() {
91            let (dx, dy) = flow.get_direction(x, y);
92            let arrow = match (dx, dy) {
93                (0, 0) => "●",   // Goal
94                (-1, -1) => "↖", // Northwest
95                (0, -1) => "↑",  // North
96                (1, -1) => "↗",  // Northeast
97                (-1, 0) => "←",  // West
98                (1, 0) => "→",   // East
99                (-1, 1) => "↙",  // Southwest
100                (0, 1) => "↓",   // South
101                (1, 1) => "↘",   // Southeast
102                _ => "?",        // Unknown
103            };
104            print!("{} ", arrow);
105        }
106        println!();
107    }
108}