Skip to main content

Grid

Struct Grid 

Source
pub struct Grid<C: Cell = Tile> { /* private fields */ }
Expand description

2D grid of cells

Implementations§

Source§

impl<C: Cell> Grid<C>

Source

pub fn new(width: usize, height: usize) -> Self

Examples found in repository?
examples/bsp_analysis.rs (line 6)
3fn main() {
4    println!("=== BSP Algorithm Analysis ===\n");
5
6    let mut grid = Grid::new(40, 30);
7    algorithms::get("bsp").unwrap().generate(&mut grid, 12345);
8
9    let extractor = SemanticExtractor::for_rooms();
10    let mut rng = Rng::new(12345);
11    let semantic = extractor.extract(&grid, &mut rng);
12
13    println!("Generated map analysis:");
14    println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
15    println!("  Total regions: {}", semantic.regions.len());
16
17    println!("\nRegion breakdown:");
18    let mut region_counts = std::collections::HashMap::new();
19    for region in &semantic.regions {
20        *region_counts.entry(&region.kind).or_insert(0) += 1;
21    }
22
23    for (kind, count) in &region_counts {
24        println!("  {}: {}", kind, count);
25    }
26
27    println!("\nMarker breakdown:");
28    let mut marker_counts = std::collections::HashMap::new();
29    for marker in &semantic.markers {
30        *marker_counts.entry(marker.tag()).or_insert(0) += 1;
31    }
32
33    for (tag, count) in &marker_counts {
34        println!("  {}: {}", tag, count);
35    }
36}
More examples
Hide additional examples
examples/distance_transforms.rs (line 15)
11fn main() {
12    println!("=== Distance Transform Demo ===\n");
13
14    // Generate a simple room layout
15    let mut grid = Grid::new(20, 15);
16    let algo = algorithms::get("rooms").unwrap();
17    algo.generate(&mut grid, 12345);
18
19    println!("1. Original Grid (20x15):");
20    print_grid(&grid);
21
22    // Generate distance fields with different metrics
23    println!("\n2. Euclidean Distance Field:");
24    let euclidean = distance_field(&grid, DistanceMetric::Euclidean);
25    print_distance_field(&euclidean);
26
27    println!("\n3. Manhattan Distance Field:");
28    let manhattan = distance_field(&grid, DistanceMetric::Manhattan);
29    print_distance_field(&manhattan);
30
31    println!("\n4. Chebyshev Distance Field:");
32    let chebyshev = distance_field(&grid, DistanceMetric::Chebyshev);
33    print_distance_field(&chebyshev);
34
35    // Performance comparison
36    println!("\n5. Performance Comparison:");
37    let start = std::time::Instant::now();
38    let _ = distance_field(&grid, DistanceMetric::Euclidean);
39    println!("   Euclidean: {:?}", start.elapsed());
40
41    let start = std::time::Instant::now();
42    let _ = distance_field(&grid, DistanceMetric::Manhattan);
43    println!("   Manhattan: {:?}", start.elapsed());
44
45    let start = std::time::Instant::now();
46    let _ = distance_field(&grid, DistanceMetric::Chebyshev);
47    println!("   Chebyshev: {:?}", start.elapsed());
48}
examples/phase1_demo.rs (line 19)
16fn demo_hierarchical_markers() {
17    println!("🎯 Demo 1: Hierarchical Marker Types");
18
19    let mut grid = Grid::new(40, 30);
20    algorithms::get("bsp").unwrap().generate(&mut grid, 12345);
21
22    let extractor = SemanticExtractor::for_rooms();
23    let mut rng = Rng::new(12345);
24    let mut semantic = extractor.extract(&grid, &mut rng);
25
26    // Add hierarchical markers manually for demo
27    if let Some(region) = semantic.regions.first() {
28        let (x, y) = region.cells[0];
29
30        // Quest markers
31        semantic.markers.push(Marker::new(
32            x,
33            y,
34            MarkerType::QuestObjective { priority: 1 },
35        ));
36        semantic
37            .markers
38            .push(Marker::new(x + 2, y, MarkerType::QuestStart));
39
40        // Loot markers
41        semantic
42            .markers
43            .push(Marker::new(x, y + 2, MarkerType::LootTier { tier: 3 }));
44        semantic
45            .markers
46            .push(Marker::new(x + 1, y + 2, MarkerType::Treasure));
47
48        // Encounter zones
49        semantic.markers.push(Marker::new(
50            x + 3,
51            y + 1,
52            MarkerType::EncounterZone { difficulty: 5 },
53        ));
54        semantic
55            .markers
56            .push(Marker::new(x + 4, y + 1, MarkerType::BossRoom));
57    }
58
59    // Show marker categories
60    let mut categories = std::collections::HashMap::new();
61    for marker in &semantic.markers {
62        *categories.entry(marker.marker_type.category()).or_insert(0) += 1;
63    }
64
65    for (category, count) in categories {
66        println!("  {} markers: {}", category, count);
67    }
68
69    println!("  Sample markers:");
70    for marker in semantic.markers.iter().take(3) {
71        println!("    {} at ({}, {})", marker.tag(), marker.x, marker.y);
72    }
73    println!();
74}
75
76fn demo_generate_with_requirements() {
77    println!("📋 Demo 2: Generate with Requirements");
78
79    let mut requirements = SemanticRequirements::basic_dungeon();
80    requirements.min_regions.insert("room".to_string(), 4);
81    requirements
82        .required_markers
83        .insert(MarkerType::LootTier { tier: 1 }, 2);
84
85    match terrain_forge::generate_with_requirements("bsp", 60, 40, requirements, Some(5), 54321) {
86        Ok((grid, semantic)) => {
87            println!("  ✅ Generated valid dungeon!");
88            println!("  Regions: {}", semantic.regions.len());
89            println!("  Markers: {}", semantic.markers.len());
90            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
91        }
92        Err(msg) => println!("  ❌ Failed: {}", msg),
93    }
94    println!();
95}
96
97fn demo_vertical_connectivity() {
98    println!("🏗️ Demo 3: Vertical Connectivity");
99
100    // Create two simple floor grids
101    let mut floor1 = Grid::new(20, 20);
102    let mut floor2 = Grid::new(20, 20);
103
104    // Add some floor areas
105    for y in 5..15 {
106        for x in 5..15 {
107            floor1.set(x, y, terrain_forge::Tile::Floor);
108            floor2.set(x, y, terrain_forge::Tile::Floor);
109        }
110    }
111
112    let floors = vec![floor1, floor2];
113    let mut connectivity = VerticalConnectivity::new();
114
115    connectivity.analyze_stair_candidates(&floors, 2);
116    connectivity.place_stairs(3);
117
118    println!(
119        "  Stair candidates found: {}",
120        connectivity.stair_candidates.len()
121    );
122    println!("  Stairs placed: {}", connectivity.stairs.len());
123
124    if let Some((x, y, from, to)) = connectivity.stairs.first() {
125        println!(
126            "  Sample stair: ({}, {}) connecting floor {} to {}",
127            x, y, from, to
128        );
129    }
130    println!();
131}
examples/advanced_pathfinding.rs (line 15)
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}
examples/phase2_demo.rs (line 19)
16fn demo_conditional_pipeline() {
17    println!("🔀 Demo 1: Conditional Pipeline Operations");
18
19    let mut grid = Grid::new(30, 20);
20    let mut context = PipelineContext::new();
21    let mut rng = Rng::new(12345);
22
23    // Create conditional pipeline
24    let mut pipeline = ConditionalPipeline::new();
25
26    // Add algorithm operation
27    pipeline.add_operation(ConditionalOperation::simple(PipelineOperation::Algorithm {
28        name: "bsp".to_string(),
29        seed: Some(12345),
30    }));
31
32    // Add conditional operation based on floor density
33    pipeline.add_operation(ConditionalOperation::conditional(
34        PipelineOperation::Log {
35            message: "Evaluating floor density".to_string(),
36        },
37        PipelineCondition::Density {
38            min: Some(0.2),
39            max: Some(0.6),
40        },
41        vec![ConditionalOperation::simple(
42            PipelineOperation::SetParameter {
43                key: "density_status".to_string(),
44                value: "acceptable".to_string(),
45            },
46        )],
47        vec![ConditionalOperation::simple(
48            PipelineOperation::SetParameter {
49                key: "density_status".to_string(),
50                value: "out_of_range".to_string(),
51            },
52        )],
53    ));
54
55    // Execute pipeline
56    let result = pipeline.execute(&mut grid, &mut context, &mut rng);
57
58    println!(
59        "  Pipeline execution: {}",
60        if result.success {
61            "✅ Success"
62        } else {
63            "❌ Failed"
64        }
65    );
66    if let Some(msg) = result.message {
67        println!("  Message: {}", msg);
68    }
69
70    println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
71    println!(
72        "  Density status: {}",
73        context
74            .get_parameter("density_status")
75            .unwrap_or(&"unknown".to_string())
76    );
77    println!("  Execution log: {:?}", context.execution_history());
78    println!();
79}
80
81fn demo_pipeline_templates() {
82    println!("📋 Demo 2: Pipeline Templates");
83
84    // Create custom template
85    let template = PipelineTemplate::new("custom_dungeon", "Customizable dungeon template")
86        .with_parameter("algorithm", "cellular")
87        .with_parameter("seed", "54321")
88        .with_parameter("type", "dungeon")
89        .with_operation(ConditionalOperation::simple(PipelineOperation::Algorithm {
90            name: "{algorithm}".to_string(),
91            seed: Some(54321),
92        }))
93        .with_operation(ConditionalOperation::simple(
94            PipelineOperation::SetParameter {
95                key: "generation_type".to_string(),
96                value: "{type}".to_string(),
97            },
98        ));
99
100    // Instantiate with custom parameters
101    let mut custom_params = std::collections::HashMap::new();
102    custom_params.insert("algorithm".to_string(), "bsp".to_string());
103    custom_params.insert("type".to_string(), "fortress".to_string());
104
105    let pipeline = template.instantiate(Some(custom_params));
106
107    let mut grid = Grid::new(25, 25);
108    let mut context = PipelineContext::new();
109    let mut rng = Rng::new(98765);
110
111    let result = pipeline.execute(&mut grid, &mut context, &mut rng);
112
113    println!("  Template: {}", template.name);
114    println!("  Description: {}", template.description);
115    println!(
116        "  Execution: {}",
117        if result.success {
118            "✅ Success"
119        } else {
120            "❌ Failed"
121        }
122    );
123    println!(
124        "  Generation type: {}",
125        context
126            .get_parameter("generation_type")
127            .unwrap_or(&"unknown".to_string())
128    );
129    println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
130    println!();
131}
132
133fn demo_template_library() {
134    println!("📚 Demo 3: Template Library");
135
136    let library = TemplateLibrary::new();
137
138    println!("  Available templates:");
139    for name in library.template_names() {
140        if let Some(template) = library.get_template(name) {
141            println!("    - {}: {}", name, template.description);
142        }
143    }
144
145    // Use built-in template
146    if let Some(template) = library.get_template("simple_dungeon") {
147        let pipeline = template.instantiate(None);
148
149        let mut grid = Grid::new(40, 30);
150        let mut context = PipelineContext::new();
151        let mut rng = Rng::new(11111);
152
153        let result = pipeline.execute(&mut grid, &mut context, &mut rng);
154
155        println!("\n  Executed 'simple_dungeon' template:");
156        println!(
157            "    Result: {}",
158            if result.success {
159                "✅ Success"
160            } else {
161                "❌ Failed"
162            }
163        );
164        println!("    Floor tiles: {}", grid.count(|t| t.is_floor()));
165        println!("    Steps executed: {}", context.execution_history().len());
166    }
167    println!();
168}
examples/hierarchical_markers.rs (line 7)
3fn main() {
4    println!("=== Hierarchical Marker Types Demo ===\n");
5
6    // Generate a basic dungeon
7    let mut grid = Grid::new(30, 20);
8    algorithms::get("bsp").unwrap().generate(&mut grid, 12345);
9
10    let extractor = SemanticExtractor::for_rooms();
11    let mut rng = Rng::new(12345);
12    let mut semantic = extractor.extract(&grid, &mut rng);
13
14    // Add hierarchical markers
15    if let Some(region) = semantic.regions.first() {
16        let (x, y) = region.cells[0];
17
18        // Quest markers with priorities
19        semantic.markers.push(Marker::new(
20            x,
21            y,
22            MarkerType::QuestObjective { priority: 1 },
23        ));
24        semantic.markers.push(Marker::new(
25            x + 2,
26            y,
27            MarkerType::QuestObjective { priority: 3 },
28        ));
29        semantic
30            .markers
31            .push(Marker::new(x + 4, y, MarkerType::QuestStart));
32
33        // Loot with different tiers
34        semantic
35            .markers
36            .push(Marker::new(x, y + 2, MarkerType::LootTier { tier: 1 }));
37        semantic
38            .markers
39            .push(Marker::new(x + 2, y + 2, MarkerType::LootTier { tier: 3 }));
40        semantic
41            .markers
42            .push(Marker::new(x + 4, y + 2, MarkerType::Treasure));
43
44        // Encounter zones
45        semantic.markers.push(Marker::new(
46            x,
47            y + 4,
48            MarkerType::EncounterZone { difficulty: 2 },
49        ));
50        semantic
51            .markers
52            .push(Marker::new(x + 2, y + 4, MarkerType::BossRoom));
53        semantic
54            .markers
55            .push(Marker::new(x + 4, y + 4, MarkerType::SafeZone));
56    }
57
58    // Show marker categories and types
59    println!("Generated {} markers:", semantic.markers.len());
60    for marker in &semantic.markers {
61        println!(
62            "  {} at ({}, {}) - Category: {}",
63            marker.tag(),
64            marker.x,
65            marker.y,
66            marker.marker_type.category()
67        );
68    }
69
70    // Group by category
71    let mut categories = std::collections::HashMap::new();
72    for marker in &semantic.markers {
73        *categories.entry(marker.marker_type.category()).or_insert(0) += 1;
74    }
75
76    println!("\nMarker distribution:");
77    for (category, count) in categories {
78        println!("  {}: {} markers", category, count);
79    }
80}
Source

pub fn width(&self) -> usize

Examples found in repository?
examples/advanced_pathfinding.rs (line 64)
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}
More examples
Hide additional examples
examples/distance_transforms.rs (line 52)
50fn print_grid(grid: &Grid<Tile>) {
51    for y in 0..grid.height() {
52        for x in 0..grid.width() {
53            let tile = grid.get(x as i32, y as i32).unwrap();
54            print!("{}", if tile.is_floor() { "." } else { "#" });
55        }
56        println!();
57    }
58}
examples/morphological_operations.rs (line 98)
96fn print_grid(grid: &Grid<Tile>) {
97    for y in 0..grid.height() {
98        for x in 0..grid.width() {
99            let tile = grid.get(x as i32, y as i32).unwrap();
100            print!("{}", if tile.is_floor() { "." } else { "#" });
101        }
102        println!();
103    }
104}
105
106fn print_grid_compact(grid: &Grid<Tile>) {
107    for y in 0..grid.height().min(8) {
108        print!("     ");
109        for x in 0..grid.width() {
110            let tile = grid.get(x as i32, y as i32).unwrap();
111            print!("{}", if tile.is_floor() { "." } else { "#" });
112        }
113        println!();
114    }
115    if grid.height() > 8 {
116        println!("     ... ({} more rows)", grid.height() - 8);
117    }
118}
examples/requirements_demo.rs (line 21)
3fn main() {
4    println!("=== Generate with Requirements Demo ===\n");
5
6    // Create simple requirements that match BSP output
7    let mut requirements = SemanticRequirements::none();
8    requirements.min_regions.insert("Hall".to_string(), 1); // BSP produces "Hall" regions
9    requirements
10        .required_markers
11        .insert(MarkerType::Custom("PlayerStart".to_string()), 1); // BSP produces "PlayerStart"
12
13    println!("Requirements:");
14    println!("  - Minimum 1 Hall region");
15    println!("  - At least 1 PlayerStart marker");
16    println!();
17
18    match generate_with_requirements("bsp", 40, 30, requirements, Some(10), 12345) {
19        Ok((grid, semantic)) => {
20            println!("✅ Successfully generated map meeting requirements!");
21            println!("  Grid size: {}x{}", grid.width(), grid.height());
22            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
23            println!("  Total regions: {}", semantic.regions.len());
24
25            // Count Hall regions
26            let hall_count = semantic.regions.iter().filter(|r| r.kind == "Hall").count();
27            println!("  Hall regions: {}", hall_count);
28
29            // Count PlayerStart markers
30            let start_count = semantic
31                .markers
32                .iter()
33                .filter(|m| m.tag() == "PlayerStart")
34                .count();
35            println!("  PlayerStart markers: {}", start_count);
36
37            println!("\nFirst few regions:");
38            for (i, region) in semantic.regions.iter().take(3).enumerate() {
39                println!("  {}: {} ({} cells)", i + 1, region.kind, region.area());
40            }
41        }
42        Err(msg) => {
43            println!("❌ Failed to generate: {}", msg);
44        }
45    }
46}
examples/enhanced_wfc.rs (line 56)
10fn main() {
11    println!("=== Enhanced Wave Function Collapse Demo ===\n");
12
13    // Step 1: Generate example map for pattern learning
14    println!("1. Generating Example Map for Pattern Learning:");
15    let mut example_grid = Grid::new(20, 15);
16    let bsp = Bsp::default();
17    bsp.generate(&mut example_grid, 54321);
18
19    print_grid(&example_grid, "Example Map");
20
21    // Step 2: Extract patterns from example
22    println!("\n2. Extracting Patterns from Example:");
23    let patterns = WfcPatternExtractor::extract_patterns(&example_grid, 3);
24    println!("   Extracted {} unique patterns", patterns.len());
25
26    // Step 3: Generate with learned patterns (no backtracking)
27    println!("\n3. WFC Generation without Backtracking:");
28    let mut grid1 = Grid::new(25, 20);
29    let wfc_no_backtrack = Wfc::new(WfcConfig {
30        floor_weight: 0.4,
31        pattern_size: 3,
32        enable_backtracking: false,
33    });
34    wfc_no_backtrack.generate_with_patterns(&mut grid1, patterns.clone(), 12345);
35    print_grid(&grid1, "Without Backtracking");
36
37    // Step 4: Generate with backtracking enabled
38    println!("\n4. WFC Generation with Backtracking:");
39    let mut grid2 = Grid::new(25, 20);
40    let wfc_backtrack = Wfc::new(WfcConfig {
41        floor_weight: 0.4,
42        pattern_size: 3,
43        enable_backtracking: true,
44    });
45    wfc_backtrack.generate_with_patterns(&mut grid2, patterns.clone(), 12345);
46    print_grid(&grid2, "With Backtracking");
47
48    // Step 5: Compare results
49    println!("\n5. Comparison:");
50    let floors1 = grid1.count(|t| t.is_floor());
51    let floors2 = grid2.count(|t| t.is_floor());
52
53    println!(
54        "   Without backtracking: {} floors ({:.1}%)",
55        floors1,
56        100.0 * floors1 as f32 / (grid1.width() * grid1.height()) as f32
57    );
58    println!(
59        "   With backtracking: {} floors ({:.1}%)",
60        floors2,
61        100.0 * floors2 as f32 / (grid2.width() * grid2.height()) as f32
62    );
63
64    // Step 6: Different pattern sizes
65    println!("\n6. Pattern Size Comparison:");
66    for size in [2, 3, 4] {
67        let patterns = WfcPatternExtractor::extract_patterns(&example_grid, size);
68        let mut grid = Grid::new(15, 12);
69        let wfc = Wfc::new(WfcConfig {
70            floor_weight: 0.4,
71            pattern_size: size,
72            enable_backtracking: true,
73        });
74        wfc.generate_with_patterns(&mut grid, patterns.clone(), 98765);
75
76        let floors = grid.count(|t| t.is_floor());
77        println!(
78            "   Pattern size {}: {} patterns, {} floors",
79            size,
80            patterns.len(),
81            floors
82        );
83    }
84
85    println!("\n✅ Enhanced WFC demo complete!");
86    println!("   - Pattern learning extracts reusable structures");
87    println!("   - Backtracking improves generation success rate");
88    println!("   - Constraint propagation ensures valid outputs");
89}
90
91fn print_grid(grid: &Grid<Tile>, title: &str) {
92    println!("   {}:", title);
93    for y in 0..grid.height().min(8) {
94        print!("     ");
95        for x in 0..grid.width() {
96            let tile = grid.get(x as i32, y as i32).unwrap();
97            print!("{}", if tile.is_floor() { "." } else { "#" });
98        }
99        println!();
100    }
101    if grid.height() > 8 {
102        println!("     ... ({} more rows)", grid.height() - 8);
103    }
104}
examples/delaunay_connections.rs (line 23)
11fn main() {
12    println!("=== Delaunay Triangulation Demo ===\n");
13
14    // Step 1: Generate base dungeon with rooms
15    println!("1. Generating Base Dungeon:");
16    let mut grid = Grid::new(40, 30);
17    let bsp = Bsp::default();
18    bsp.generate(&mut grid, 42424);
19
20    let room_count = count_rooms(&grid);
21    println!(
22        "   Generated {}x{} dungeon with ~{} rooms",
23        grid.width(),
24        grid.height(),
25        room_count
26    );
27
28    // Step 2: Find room centers
29    println!("\n2. Identifying Room Centers:");
30    let room_centers = find_room_centers(&grid);
31    println!("   Found {} room centers:", room_centers.len());
32    for (i, center) in room_centers.iter().enumerate() {
33        println!("     Room {}: ({:.1}, {:.1})", i + 1, center.x, center.y);
34    }
35
36    // Step 3: Create Delaunay triangulation
37    println!("\n3. Creating Delaunay Triangulation:");
38    let triangulation = DelaunayTriangulation::new(room_centers.clone());
39
40    println!("   Triangulation results:");
41    println!("     Vertices: {}", triangulation.points.len());
42    println!("     Triangles: {}", triangulation.triangles.len());
43    println!("     Edges: {}", triangulation.edges.len());
44
45    // Step 4: Generate minimum spanning tree
46    println!("\n4. Generating Minimum Spanning Tree:");
47    let mst_edges = triangulation.minimum_spanning_tree();
48
49    println!("   MST results:");
50    println!("     Edges: {}", mst_edges.len());
51    println!(
52        "     Expected for {} rooms: {}",
53        room_centers.len(),
54        room_centers.len().saturating_sub(1)
55    );
56
57    let total_length: f32 = mst_edges
58        .iter()
59        .map(|edge| edge.length(&triangulation.points))
60        .sum();
61    println!("     Total length: {:.1}", total_length);
62
63    // Step 5: Graph analysis
64    println!("\n5. Graph Analysis:");
65    let graph = Graph::new(triangulation.points.clone(), mst_edges.clone());
66    let analysis = GraphAnalysis::analyze(&graph);
67
68    println!("   Connectivity analysis:");
69    println!("     Connected: {}", analysis.is_connected);
70    println!("     Components: {}", analysis.component_count);
71    println!("     Diameter: {:.1}", analysis.diameter);
72    println!("     Avg clustering: {:.3}", analysis.average_clustering);
73
74    // Step 6: Compare with full triangulation
75    println!("\n6. Comparison: MST vs Full Triangulation:");
76    let full_graph = Graph::new(triangulation.points.clone(), triangulation.edges.clone());
77    let full_analysis = GraphAnalysis::analyze(&full_graph);
78
79    println!("   Full triangulation:");
80    println!("     Edges: {}", full_analysis.edge_count);
81    println!("     Diameter: {:.1}", full_analysis.diameter);
82    println!(
83        "     Avg clustering: {:.3}",
84        full_analysis.average_clustering
85    );
86
87    println!("   MST (optimized):");
88    println!("     Edges: {}", analysis.edge_count);
89    println!("     Diameter: {:.1}", analysis.diameter);
90    println!("     Avg clustering: {:.3}", analysis.average_clustering);
91
92    // Step 7: Pathfinding example
93    println!("\n7. Pathfinding Example:");
94    if room_centers.len() >= 2 {
95        let start = 0;
96        let end = room_centers.len() - 1;
97
98        if let Some(path) = graph.shortest_path(start, end) {
99            println!("   Path from room {} to room {}:", start + 1, end + 1);
100            print!("     Route: ");
101            for (i, &room) in path.iter().enumerate() {
102                if i > 0 {
103                    print!(" -> ");
104                }
105                print!("Room {}", room + 1);
106            }
107            println!();
108
109            let mut path_length = 0.0;
110            for i in 0..(path.len() - 1) {
111                path_length += room_centers[path[i]].distance_to(&room_centers[path[i + 1]]);
112            }
113            println!("     Total distance: {:.1}", path_length);
114        } else {
115            println!("   No path found between rooms");
116        }
117    }
118
119    // Step 8: Performance analysis
120    println!("\n8. Performance Analysis:");
121    let start = std::time::Instant::now();
122    let _ = DelaunayTriangulation::new(room_centers.clone());
123    println!("   Triangulation time: {:?}", start.elapsed());
124
125    let start = std::time::Instant::now();
126    let _ = triangulation.minimum_spanning_tree();
127    println!("   MST generation time: {:?}", start.elapsed());
128
129    println!("\n✅ Delaunay triangulation demo complete!");
130    println!("   - Natural room connections via triangulation");
131    println!("   - Optimal corridor networks with MST");
132    println!("   - Graph analysis for connectivity insights");
133}
134
135fn count_rooms(grid: &Grid<Tile>) -> usize {
136    // Simple room counting by finding floor clusters
137    let mut room_count = 0;
138    let mut visited = vec![vec![false; grid.width()]; grid.height()];
139
140    for y in 0..grid.height() {
141        for x in 0..grid.width() {
142            if !visited[y][x] {
143                if let Some(tile) = grid.get(x as i32, y as i32) {
144                    if tile.is_floor() {
145                        flood_fill(grid, &mut visited, x, y);
146                        room_count += 1;
147                    }
148                }
149            }
150        }
151    }
152
153    room_count
154}
155
156fn flood_fill(grid: &Grid<Tile>, visited: &mut [Vec<bool>], start_x: usize, start_y: usize) {
157    let mut stack = vec![(start_x, start_y)];
158
159    while let Some((x, y)) = stack.pop() {
160        if visited[y][x] {
161            continue;
162        }
163        visited[y][x] = true;
164
165        for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
166            let nx = x as i32 + dx;
167            let ny = y as i32 + dy;
168
169            if nx >= 0 && ny >= 0 && (nx as usize) < grid.width() && (ny as usize) < grid.height() {
170                let nx = nx as usize;
171                let ny = ny as usize;
172
173                if !visited[ny][nx] {
174                    if let Some(tile) = grid.get(nx as i32, ny as i32) {
175                        if tile.is_floor() {
176                            stack.push((nx, ny));
177                        }
178                    }
179                }
180            }
181        }
182    }
183}
184
185fn find_room_centers(grid: &Grid<Tile>) -> Vec<Point> {
186    let mut centers = Vec::new();
187    let mut visited = vec![vec![false; grid.width()]; grid.height()];
188
189    for y in 0..grid.height() {
190        for x in 0..grid.width() {
191            if !visited[y][x] {
192                if let Some(tile) = grid.get(x as i32, y as i32) {
193                    if tile.is_floor() {
194                        let center = find_room_center(grid, &mut visited, x, y);
195                        centers.push(center);
196                    }
197                }
198            }
199        }
200    }
201
202    centers
203}
204
205fn find_room_center(
206    grid: &Grid<Tile>,
207    visited: &mut [Vec<bool>],
208    start_x: usize,
209    start_y: usize,
210) -> Point {
211    let mut room_cells = Vec::new();
212    let mut stack = vec![(start_x, start_y)];
213
214    while let Some((x, y)) = stack.pop() {
215        if visited[y][x] {
216            continue;
217        }
218        visited[y][x] = true;
219        room_cells.push((x, y));
220
221        for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
222            let nx = x as i32 + dx;
223            let ny = y as i32 + dy;
224
225            if nx >= 0 && ny >= 0 && (nx as usize) < grid.width() && (ny as usize) < grid.height() {
226                let nx = nx as usize;
227                let ny = ny as usize;
228
229                if !visited[ny][nx] {
230                    if let Some(tile) = grid.get(nx as i32, ny as i32) {
231                        if tile.is_floor() {
232                            stack.push((nx, ny));
233                        }
234                    }
235                }
236            }
237        }
238    }
239
240    // Calculate centroid
241    let sum_x: usize = room_cells.iter().map(|(x, _)| x).sum();
242    let sum_y: usize = room_cells.iter().map(|(_, y)| y).sum();
243    let count = room_cells.len();
244
245    Point::new(sum_x as f32 / count as f32, sum_y as f32 / count as f32)
246}
Source

pub fn height(&self) -> usize

Examples found in repository?
examples/advanced_pathfinding.rs (line 63)
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}
More examples
Hide additional examples
examples/distance_transforms.rs (line 51)
50fn print_grid(grid: &Grid<Tile>) {
51    for y in 0..grid.height() {
52        for x in 0..grid.width() {
53            let tile = grid.get(x as i32, y as i32).unwrap();
54            print!("{}", if tile.is_floor() { "." } else { "#" });
55        }
56        println!();
57    }
58}
examples/morphological_operations.rs (line 97)
96fn print_grid(grid: &Grid<Tile>) {
97    for y in 0..grid.height() {
98        for x in 0..grid.width() {
99            let tile = grid.get(x as i32, y as i32).unwrap();
100            print!("{}", if tile.is_floor() { "." } else { "#" });
101        }
102        println!();
103    }
104}
105
106fn print_grid_compact(grid: &Grid<Tile>) {
107    for y in 0..grid.height().min(8) {
108        print!("     ");
109        for x in 0..grid.width() {
110            let tile = grid.get(x as i32, y as i32).unwrap();
111            print!("{}", if tile.is_floor() { "." } else { "#" });
112        }
113        println!();
114    }
115    if grid.height() > 8 {
116        println!("     ... ({} more rows)", grid.height() - 8);
117    }
118}
examples/requirements_demo.rs (line 21)
3fn main() {
4    println!("=== Generate with Requirements Demo ===\n");
5
6    // Create simple requirements that match BSP output
7    let mut requirements = SemanticRequirements::none();
8    requirements.min_regions.insert("Hall".to_string(), 1); // BSP produces "Hall" regions
9    requirements
10        .required_markers
11        .insert(MarkerType::Custom("PlayerStart".to_string()), 1); // BSP produces "PlayerStart"
12
13    println!("Requirements:");
14    println!("  - Minimum 1 Hall region");
15    println!("  - At least 1 PlayerStart marker");
16    println!();
17
18    match generate_with_requirements("bsp", 40, 30, requirements, Some(10), 12345) {
19        Ok((grid, semantic)) => {
20            println!("✅ Successfully generated map meeting requirements!");
21            println!("  Grid size: {}x{}", grid.width(), grid.height());
22            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
23            println!("  Total regions: {}", semantic.regions.len());
24
25            // Count Hall regions
26            let hall_count = semantic.regions.iter().filter(|r| r.kind == "Hall").count();
27            println!("  Hall regions: {}", hall_count);
28
29            // Count PlayerStart markers
30            let start_count = semantic
31                .markers
32                .iter()
33                .filter(|m| m.tag() == "PlayerStart")
34                .count();
35            println!("  PlayerStart markers: {}", start_count);
36
37            println!("\nFirst few regions:");
38            for (i, region) in semantic.regions.iter().take(3).enumerate() {
39                println!("  {}: {} ({} cells)", i + 1, region.kind, region.area());
40            }
41        }
42        Err(msg) => {
43            println!("❌ Failed to generate: {}", msg);
44        }
45    }
46}
examples/enhanced_wfc.rs (line 56)
10fn main() {
11    println!("=== Enhanced Wave Function Collapse Demo ===\n");
12
13    // Step 1: Generate example map for pattern learning
14    println!("1. Generating Example Map for Pattern Learning:");
15    let mut example_grid = Grid::new(20, 15);
16    let bsp = Bsp::default();
17    bsp.generate(&mut example_grid, 54321);
18
19    print_grid(&example_grid, "Example Map");
20
21    // Step 2: Extract patterns from example
22    println!("\n2. Extracting Patterns from Example:");
23    let patterns = WfcPatternExtractor::extract_patterns(&example_grid, 3);
24    println!("   Extracted {} unique patterns", patterns.len());
25
26    // Step 3: Generate with learned patterns (no backtracking)
27    println!("\n3. WFC Generation without Backtracking:");
28    let mut grid1 = Grid::new(25, 20);
29    let wfc_no_backtrack = Wfc::new(WfcConfig {
30        floor_weight: 0.4,
31        pattern_size: 3,
32        enable_backtracking: false,
33    });
34    wfc_no_backtrack.generate_with_patterns(&mut grid1, patterns.clone(), 12345);
35    print_grid(&grid1, "Without Backtracking");
36
37    // Step 4: Generate with backtracking enabled
38    println!("\n4. WFC Generation with Backtracking:");
39    let mut grid2 = Grid::new(25, 20);
40    let wfc_backtrack = Wfc::new(WfcConfig {
41        floor_weight: 0.4,
42        pattern_size: 3,
43        enable_backtracking: true,
44    });
45    wfc_backtrack.generate_with_patterns(&mut grid2, patterns.clone(), 12345);
46    print_grid(&grid2, "With Backtracking");
47
48    // Step 5: Compare results
49    println!("\n5. Comparison:");
50    let floors1 = grid1.count(|t| t.is_floor());
51    let floors2 = grid2.count(|t| t.is_floor());
52
53    println!(
54        "   Without backtracking: {} floors ({:.1}%)",
55        floors1,
56        100.0 * floors1 as f32 / (grid1.width() * grid1.height()) as f32
57    );
58    println!(
59        "   With backtracking: {} floors ({:.1}%)",
60        floors2,
61        100.0 * floors2 as f32 / (grid2.width() * grid2.height()) as f32
62    );
63
64    // Step 6: Different pattern sizes
65    println!("\n6. Pattern Size Comparison:");
66    for size in [2, 3, 4] {
67        let patterns = WfcPatternExtractor::extract_patterns(&example_grid, size);
68        let mut grid = Grid::new(15, 12);
69        let wfc = Wfc::new(WfcConfig {
70            floor_weight: 0.4,
71            pattern_size: size,
72            enable_backtracking: true,
73        });
74        wfc.generate_with_patterns(&mut grid, patterns.clone(), 98765);
75
76        let floors = grid.count(|t| t.is_floor());
77        println!(
78            "   Pattern size {}: {} patterns, {} floors",
79            size,
80            patterns.len(),
81            floors
82        );
83    }
84
85    println!("\n✅ Enhanced WFC demo complete!");
86    println!("   - Pattern learning extracts reusable structures");
87    println!("   - Backtracking improves generation success rate");
88    println!("   - Constraint propagation ensures valid outputs");
89}
90
91fn print_grid(grid: &Grid<Tile>, title: &str) {
92    println!("   {}:", title);
93    for y in 0..grid.height().min(8) {
94        print!("     ");
95        for x in 0..grid.width() {
96            let tile = grid.get(x as i32, y as i32).unwrap();
97            print!("{}", if tile.is_floor() { "." } else { "#" });
98        }
99        println!();
100    }
101    if grid.height() > 8 {
102        println!("     ... ({} more rows)", grid.height() - 8);
103    }
104}
examples/delaunay_connections.rs (line 24)
11fn main() {
12    println!("=== Delaunay Triangulation Demo ===\n");
13
14    // Step 1: Generate base dungeon with rooms
15    println!("1. Generating Base Dungeon:");
16    let mut grid = Grid::new(40, 30);
17    let bsp = Bsp::default();
18    bsp.generate(&mut grid, 42424);
19
20    let room_count = count_rooms(&grid);
21    println!(
22        "   Generated {}x{} dungeon with ~{} rooms",
23        grid.width(),
24        grid.height(),
25        room_count
26    );
27
28    // Step 2: Find room centers
29    println!("\n2. Identifying Room Centers:");
30    let room_centers = find_room_centers(&grid);
31    println!("   Found {} room centers:", room_centers.len());
32    for (i, center) in room_centers.iter().enumerate() {
33        println!("     Room {}: ({:.1}, {:.1})", i + 1, center.x, center.y);
34    }
35
36    // Step 3: Create Delaunay triangulation
37    println!("\n3. Creating Delaunay Triangulation:");
38    let triangulation = DelaunayTriangulation::new(room_centers.clone());
39
40    println!("   Triangulation results:");
41    println!("     Vertices: {}", triangulation.points.len());
42    println!("     Triangles: {}", triangulation.triangles.len());
43    println!("     Edges: {}", triangulation.edges.len());
44
45    // Step 4: Generate minimum spanning tree
46    println!("\n4. Generating Minimum Spanning Tree:");
47    let mst_edges = triangulation.minimum_spanning_tree();
48
49    println!("   MST results:");
50    println!("     Edges: {}", mst_edges.len());
51    println!(
52        "     Expected for {} rooms: {}",
53        room_centers.len(),
54        room_centers.len().saturating_sub(1)
55    );
56
57    let total_length: f32 = mst_edges
58        .iter()
59        .map(|edge| edge.length(&triangulation.points))
60        .sum();
61    println!("     Total length: {:.1}", total_length);
62
63    // Step 5: Graph analysis
64    println!("\n5. Graph Analysis:");
65    let graph = Graph::new(triangulation.points.clone(), mst_edges.clone());
66    let analysis = GraphAnalysis::analyze(&graph);
67
68    println!("   Connectivity analysis:");
69    println!("     Connected: {}", analysis.is_connected);
70    println!("     Components: {}", analysis.component_count);
71    println!("     Diameter: {:.1}", analysis.diameter);
72    println!("     Avg clustering: {:.3}", analysis.average_clustering);
73
74    // Step 6: Compare with full triangulation
75    println!("\n6. Comparison: MST vs Full Triangulation:");
76    let full_graph = Graph::new(triangulation.points.clone(), triangulation.edges.clone());
77    let full_analysis = GraphAnalysis::analyze(&full_graph);
78
79    println!("   Full triangulation:");
80    println!("     Edges: {}", full_analysis.edge_count);
81    println!("     Diameter: {:.1}", full_analysis.diameter);
82    println!(
83        "     Avg clustering: {:.3}",
84        full_analysis.average_clustering
85    );
86
87    println!("   MST (optimized):");
88    println!("     Edges: {}", analysis.edge_count);
89    println!("     Diameter: {:.1}", analysis.diameter);
90    println!("     Avg clustering: {:.3}", analysis.average_clustering);
91
92    // Step 7: Pathfinding example
93    println!("\n7. Pathfinding Example:");
94    if room_centers.len() >= 2 {
95        let start = 0;
96        let end = room_centers.len() - 1;
97
98        if let Some(path) = graph.shortest_path(start, end) {
99            println!("   Path from room {} to room {}:", start + 1, end + 1);
100            print!("     Route: ");
101            for (i, &room) in path.iter().enumerate() {
102                if i > 0 {
103                    print!(" -> ");
104                }
105                print!("Room {}", room + 1);
106            }
107            println!();
108
109            let mut path_length = 0.0;
110            for i in 0..(path.len() - 1) {
111                path_length += room_centers[path[i]].distance_to(&room_centers[path[i + 1]]);
112            }
113            println!("     Total distance: {:.1}", path_length);
114        } else {
115            println!("   No path found between rooms");
116        }
117    }
118
119    // Step 8: Performance analysis
120    println!("\n8. Performance Analysis:");
121    let start = std::time::Instant::now();
122    let _ = DelaunayTriangulation::new(room_centers.clone());
123    println!("   Triangulation time: {:?}", start.elapsed());
124
125    let start = std::time::Instant::now();
126    let _ = triangulation.minimum_spanning_tree();
127    println!("   MST generation time: {:?}", start.elapsed());
128
129    println!("\n✅ Delaunay triangulation demo complete!");
130    println!("   - Natural room connections via triangulation");
131    println!("   - Optimal corridor networks with MST");
132    println!("   - Graph analysis for connectivity insights");
133}
134
135fn count_rooms(grid: &Grid<Tile>) -> usize {
136    // Simple room counting by finding floor clusters
137    let mut room_count = 0;
138    let mut visited = vec![vec![false; grid.width()]; grid.height()];
139
140    for y in 0..grid.height() {
141        for x in 0..grid.width() {
142            if !visited[y][x] {
143                if let Some(tile) = grid.get(x as i32, y as i32) {
144                    if tile.is_floor() {
145                        flood_fill(grid, &mut visited, x, y);
146                        room_count += 1;
147                    }
148                }
149            }
150        }
151    }
152
153    room_count
154}
155
156fn flood_fill(grid: &Grid<Tile>, visited: &mut [Vec<bool>], start_x: usize, start_y: usize) {
157    let mut stack = vec![(start_x, start_y)];
158
159    while let Some((x, y)) = stack.pop() {
160        if visited[y][x] {
161            continue;
162        }
163        visited[y][x] = true;
164
165        for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
166            let nx = x as i32 + dx;
167            let ny = y as i32 + dy;
168
169            if nx >= 0 && ny >= 0 && (nx as usize) < grid.width() && (ny as usize) < grid.height() {
170                let nx = nx as usize;
171                let ny = ny as usize;
172
173                if !visited[ny][nx] {
174                    if let Some(tile) = grid.get(nx as i32, ny as i32) {
175                        if tile.is_floor() {
176                            stack.push((nx, ny));
177                        }
178                    }
179                }
180            }
181        }
182    }
183}
184
185fn find_room_centers(grid: &Grid<Tile>) -> Vec<Point> {
186    let mut centers = Vec::new();
187    let mut visited = vec![vec![false; grid.width()]; grid.height()];
188
189    for y in 0..grid.height() {
190        for x in 0..grid.width() {
191            if !visited[y][x] {
192                if let Some(tile) = grid.get(x as i32, y as i32) {
193                    if tile.is_floor() {
194                        let center = find_room_center(grid, &mut visited, x, y);
195                        centers.push(center);
196                    }
197                }
198            }
199        }
200    }
201
202    centers
203}
204
205fn find_room_center(
206    grid: &Grid<Tile>,
207    visited: &mut [Vec<bool>],
208    start_x: usize,
209    start_y: usize,
210) -> Point {
211    let mut room_cells = Vec::new();
212    let mut stack = vec![(start_x, start_y)];
213
214    while let Some((x, y)) = stack.pop() {
215        if visited[y][x] {
216            continue;
217        }
218        visited[y][x] = true;
219        room_cells.push((x, y));
220
221        for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
222            let nx = x as i32 + dx;
223            let ny = y as i32 + dy;
224
225            if nx >= 0 && ny >= 0 && (nx as usize) < grid.width() && (ny as usize) < grid.height() {
226                let nx = nx as usize;
227                let ny = ny as usize;
228
229                if !visited[ny][nx] {
230                    if let Some(tile) = grid.get(nx as i32, ny as i32) {
231                        if tile.is_floor() {
232                            stack.push((nx, ny));
233                        }
234                    }
235                }
236            }
237        }
238    }
239
240    // Calculate centroid
241    let sum_x: usize = room_cells.iter().map(|(x, _)| x).sum();
242    let sum_y: usize = room_cells.iter().map(|(_, y)| y).sum();
243    let count = room_cells.len();
244
245    Point::new(sum_x as f32 / count as f32, sum_y as f32 / count as f32)
246}
Source

pub fn in_bounds(&self, x: i32, y: i32) -> bool

Source

pub fn get(&self, x: i32, y: i32) -> Option<&C>

Examples found in repository?
examples/advanced_pathfinding.rs (line 65)
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}
More examples
Hide additional examples
examples/distance_transforms.rs (line 53)
50fn print_grid(grid: &Grid<Tile>) {
51    for y in 0..grid.height() {
52        for x in 0..grid.width() {
53            let tile = grid.get(x as i32, y as i32).unwrap();
54            print!("{}", if tile.is_floor() { "." } else { "#" });
55        }
56        println!();
57    }
58}
examples/morphological_operations.rs (line 99)
96fn print_grid(grid: &Grid<Tile>) {
97    for y in 0..grid.height() {
98        for x in 0..grid.width() {
99            let tile = grid.get(x as i32, y as i32).unwrap();
100            print!("{}", if tile.is_floor() { "." } else { "#" });
101        }
102        println!();
103    }
104}
105
106fn print_grid_compact(grid: &Grid<Tile>) {
107    for y in 0..grid.height().min(8) {
108        print!("     ");
109        for x in 0..grid.width() {
110            let tile = grid.get(x as i32, y as i32).unwrap();
111            print!("{}", if tile.is_floor() { "." } else { "#" });
112        }
113        println!();
114    }
115    if grid.height() > 8 {
116        println!("     ... ({} more rows)", grid.height() - 8);
117    }
118}
examples/advanced_prefabs.rs (line 299)
294fn print_grid(grid: &Grid<Tile>) {
295    println!("   Generated layout:");
296    for y in 0..grid.height().min(12) {
297        print!("     ");
298        for x in 0..grid.width() {
299            let tile = grid.get(x as i32, y as i32).unwrap();
300            print!("{}", if tile.is_floor() { "." } else { "#" });
301        }
302        println!();
303    }
304    if grid.height() > 12 {
305        println!("     ... ({} more rows)", grid.height() - 12);
306    }
307}
examples/enhanced_wfc.rs (line 96)
91fn print_grid(grid: &Grid<Tile>, title: &str) {
92    println!("   {}:", title);
93    for y in 0..grid.height().min(8) {
94        print!("     ");
95        for x in 0..grid.width() {
96            let tile = grid.get(x as i32, y as i32).unwrap();
97            print!("{}", if tile.is_floor() { "." } else { "#" });
98        }
99        println!();
100    }
101    if grid.height() > 8 {
102        println!("     ... ({} more rows)", grid.height() - 8);
103    }
104}
examples/phase4_workflow.rs (line 225)
218fn find_room_centers(grid: &Grid<Tile>) -> Vec<Point> {
219    let mut centers = Vec::new();
220    let mut visited = vec![vec![false; grid.width()]; grid.height()];
221
222    for y in 0..grid.height() {
223        for x in 0..grid.width() {
224            if !visited[y][x] {
225                if let Some(tile) = grid.get(x as i32, y as i32) {
226                    if tile.is_floor() {
227                        let center = find_room_center(grid, &mut visited, x, y);
228                        centers.push(center);
229                    }
230                }
231            }
232        }
233    }
234
235    centers
236}
237
238fn find_room_center(
239    grid: &Grid<Tile>,
240    visited: &mut [Vec<bool>],
241    start_x: usize,
242    start_y: usize,
243) -> Point {
244    let mut room_cells = Vec::new();
245    let mut stack = vec![(start_x, start_y)];
246
247    while let Some((x, y)) = stack.pop() {
248        if visited[y][x] {
249            continue;
250        }
251        visited[y][x] = true;
252        room_cells.push((x, y));
253
254        for (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
255            let nx = x as i32 + dx;
256            let ny = y as i32 + dy;
257
258            if nx >= 0 && ny >= 0 && (nx as usize) < grid.width() && (ny as usize) < grid.height() {
259                let nx = nx as usize;
260                let ny = ny as usize;
261
262                if !visited[ny][nx] {
263                    if let Some(tile) = grid.get(nx as i32, ny as i32) {
264                        if tile.is_floor() {
265                            stack.push((nx, ny));
266                        }
267                    }
268                }
269            }
270        }
271    }
272
273    // Calculate centroid
274    let sum_x: usize = room_cells.iter().map(|(x, _)| x).sum();
275    let sum_y: usize = room_cells.iter().map(|(_, y)| y).sum();
276    let count = room_cells.len();
277
278    Point::new(sum_x as f32 / count as f32, sum_y as f32 / count as f32)
279}
Source

pub fn get_mut(&mut self, x: i32, y: i32) -> Option<&mut C>

Source

pub fn set(&mut self, x: i32, y: i32, cell: C) -> bool

Examples found in repository?
examples/phase1_demo.rs (line 107)
97fn demo_vertical_connectivity() {
98    println!("🏗️ Demo 3: Vertical Connectivity");
99
100    // Create two simple floor grids
101    let mut floor1 = Grid::new(20, 20);
102    let mut floor2 = Grid::new(20, 20);
103
104    // Add some floor areas
105    for y in 5..15 {
106        for x in 5..15 {
107            floor1.set(x, y, terrain_forge::Tile::Floor);
108            floor2.set(x, y, terrain_forge::Tile::Floor);
109        }
110    }
111
112    let floors = vec![floor1, floor2];
113    let mut connectivity = VerticalConnectivity::new();
114
115    connectivity.analyze_stair_candidates(&floors, 2);
116    connectivity.place_stairs(3);
117
118    println!(
119        "  Stair candidates found: {}",
120        connectivity.stair_candidates.len()
121    );
122    println!("  Stairs placed: {}", connectivity.stairs.len());
123
124    if let Some((x, y, from, to)) = connectivity.stairs.first() {
125        println!(
126            "  Sample stair: ({}, {}) connecting floor {} to {}",
127            x, y, from, to
128        );
129    }
130    println!();
131}
More examples
Hide additional examples
examples/vertical_connectivity.rs (line 13)
3fn main() {
4    println!("=== Vertical Connectivity Demo ===\n");
5
6    // Create two floors for a multi-level dungeon
7    let mut floor1 = Grid::new(25, 20);
8    let mut floor2 = Grid::new(25, 20);
9
10    // Floor 1: Large central room with corridors
11    for y in 5..15 {
12        for x in 5..20 {
13            floor1.set(x, y, Tile::Floor);
14        }
15    }
16    // Add some corridors
17    for x in 2..5 {
18        for y in 8..12 {
19            floor1.set(x, y, Tile::Floor);
20        }
21    }
22
23    // Floor 2: Multiple smaller rooms
24    // Room 1
25    for y in 3..8 {
26        for x in 3..10 {
27            floor2.set(x, y, Tile::Floor);
28        }
29    }
30    // Room 2
31    for y in 12..17 {
32        for x in 8..18 {
33            floor2.set(x, y, Tile::Floor);
34        }
35    }
36    // Room 3
37    for y in 6..12 {
38        for x in 15..22 {
39            floor2.set(x, y, Tile::Floor);
40        }
41    }
42
43    let floors = vec![floor1, floor2];
44
45    println!("Created 2-floor dungeon:");
46    println!(
47        "  Floor 1: {} floor tiles",
48        floors[0].count(|t| t.is_floor())
49    );
50    println!(
51        "  Floor 2: {} floor tiles",
52        floors[1].count(|t| t.is_floor())
53    );
54
55    // Analyze vertical connectivity
56    let mut connectivity = VerticalConnectivity::new();
57
58    // Find stair candidates with different clearance requirements
59    println!("\n1. Stair Candidate Analysis:");
60
61    connectivity.analyze_stair_candidates(&floors, 1); // Minimal clearance
62    println!(
63        "  With 1-tile clearance: {} candidates",
64        connectivity.stair_candidates.len()
65    );
66
67    connectivity.analyze_stair_candidates(&floors, 2); // More clearance
68    println!(
69        "  With 2-tile clearance: {} candidates",
70        connectivity.stair_candidates.len()
71    );
72
73    connectivity.analyze_stair_candidates(&floors, 3); // Maximum clearance
74    println!(
75        "  With 3-tile clearance: {} candidates",
76        connectivity.stair_candidates.len()
77    );
78
79    // Place stairs with different limits
80    println!("\n2. Stair Placement:");
81
82    connectivity.place_stairs(1);
83    println!("  Placed {} stairs (max 1)", connectivity.stairs.len());
84
85    connectivity.place_stairs(3);
86    println!("  Placed {} stairs (max 3)", connectivity.stairs.len());
87
88    connectivity.place_stairs(5);
89    println!("  Placed {} stairs (max 5)", connectivity.stairs.len());
90
91    // Show stair locations
92    println!("\n3. Stair Locations:");
93    for (i, &(x, y, from_floor, to_floor)) in connectivity.stairs.iter().enumerate() {
94        println!(
95            "  Stair {}: ({}, {}) connecting floor {} to floor {}",
96            i + 1,
97            x,
98            y,
99            from_floor,
100            to_floor
101        );
102    }
103
104    // Demonstrate with 3 floors
105    println!("\n4. Three-Floor Example:");
106
107    let mut floor3 = Grid::new(25, 20);
108    // Floor 3: Single large room
109    for y in 6..14 {
110        for x in 6..19 {
111            floor3.set(x, y, Tile::Floor);
112        }
113    }
114
115    let three_floors = vec![floors[0].clone(), floors[1].clone(), floor3];
116    let mut connectivity3 = VerticalConnectivity::new();
117
118    connectivity3.analyze_stair_candidates(&three_floors, 2);
119    connectivity3.place_stairs(2);
120
121    println!(
122        "  Floor 3: {} floor tiles",
123        three_floors[2].count(|t| t.is_floor())
124    );
125    println!(
126        "  Total stair candidates: {}",
127        connectivity3.stair_candidates.len()
128    );
129    println!("  Stairs placed: {}", connectivity3.stairs.len());
130
131    // Group stairs by floor connection
132    let mut connections = std::collections::HashMap::new();
133    for &(_, _, from, to) in &connectivity3.stairs {
134        *connections.entry((from, to)).or_insert(0) += 1;
135    }
136
137    println!("  Floor connections:");
138    for ((from, to), count) in connections {
139        println!("    Floor {} ↔ Floor {}: {} stairs", from, to, count);
140    }
141}
examples/complete_workflow.rs (line 153)
3fn main() {
4    println!("=== Complete Phase 1 & 2 Feature Demo ===\n");
5
6    // Demo: Complete workflow using all new features
7    println!("🏰 Generating Advanced Multi-Feature Dungeon\n");
8
9    // Step 1: Use pipeline template with custom parameters
10    println!("1. Pipeline Template Generation:");
11    let library = TemplateLibrary::new();
12    let template = library.get_template("simple_dungeon").unwrap();
13
14    let mut custom_params = std::collections::HashMap::new();
15    custom_params.insert("seed".to_string(), "12345".to_string());
16
17    let pipeline = template.instantiate(Some(custom_params));
18
19    let mut grid = Grid::new(40, 30);
20    let mut context = PipelineContext::new();
21    let mut rng = Rng::new(12345);
22
23    let result = pipeline.execute(&mut grid, &mut context, &mut rng);
24    println!(
25        "   Template execution: {}",
26        if result.success {
27            "✅ Success"
28        } else {
29            "❌ Failed"
30        }
31    );
32    println!("   Floor tiles: {}", grid.count(|t| t.is_floor()));
33
34    // Step 2: Extract semantic information
35    println!("\n2. Semantic Analysis:");
36    let extractor = SemanticExtractor::for_rooms();
37    let mut semantic = extractor.extract(&grid, &mut rng);
38
39    println!("   Regions found: {}", semantic.regions.len());
40    println!("   Original markers: {}", semantic.markers.len());
41
42    // Step 3: Add hierarchical markers based on regions
43    println!("\n3. Hierarchical Marker Placement:");
44    let mut quest_count = 0;
45    let mut loot_count = 0;
46    let mut encounter_count = 0;
47
48    for (i, region) in semantic.regions.iter().enumerate() {
49        if !region.cells.is_empty() {
50            let (x, y) = region.cells[region.cells.len() / 2]; // Middle of region
51
52            match i % 3 {
53                0 => {
54                    // Quest area
55                    semantic.markers.push(Marker::new(
56                        x,
57                        y,
58                        MarkerType::QuestObjective {
59                            priority: (i % 3 + 1) as u8,
60                        },
61                    ));
62                    quest_count += 1;
63                }
64                1 => {
65                    // Loot area
66                    semantic.markers.push(Marker::new(
67                        x,
68                        y,
69                        MarkerType::LootTier {
70                            tier: (i % 3 + 1) as u8,
71                        },
72                    ));
73                    loot_count += 1;
74                }
75                2 => {
76                    // Encounter area
77                    if i == 2 {
78                        semantic
79                            .markers
80                            .push(Marker::new(x, y, MarkerType::BossRoom));
81                    } else {
82                        semantic.markers.push(Marker::new(
83                            x,
84                            y,
85                            MarkerType::EncounterZone {
86                                difficulty: (i % 5 + 1) as u8,
87                            },
88                        ));
89                    }
90                    encounter_count += 1;
91                }
92                _ => {}
93            }
94        }
95    }
96
97    println!("   Added {} quest markers", quest_count);
98    println!("   Added {} loot markers", loot_count);
99    println!("   Added {} encounter markers", encounter_count);
100
101    // Step 4: Validate with requirements
102    println!("\n4. Requirement Validation:");
103    let mut requirements = SemanticRequirements::none();
104    requirements.min_regions.insert("Hall".to_string(), 1);
105    requirements
106        .required_markers
107        .insert(MarkerType::Custom("PlayerStart".to_string()), 1);
108
109    let validation_result = requirements.validate(&semantic);
110    println!(
111        "   Requirements met: {}",
112        if validation_result {
113            "✅ Yes"
114        } else {
115            "❌ No"
116        }
117    );
118
119    // Step 5: Marker constraints analysis
120    println!("\n5. Marker Constraint Analysis:");
121    let quest_constraints = MarkerConstraints::quest_objective();
122    let loot_constraints = MarkerConstraints::loot();
123
124    println!("   Quest marker constraints:");
125    println!(
126        "     Min distance (same type): {:?}",
127        quest_constraints.min_distance_same
128    );
129    println!(
130        "     Excluded types: {} types",
131        quest_constraints.exclude_types.len()
132    );
133
134    println!("   Loot marker constraints:");
135    println!(
136        "     Min distance (same type): {:?}",
137        loot_constraints.min_distance_same
138    );
139    println!(
140        "     Min distance (any): {:?}",
141        loot_constraints.min_distance_any
142    );
143
144    // Step 6: Multi-floor connectivity simulation
145    println!("\n6. Multi-Floor Connectivity:");
146
147    // Create a second floor based on the first
148    let mut floor2 = Grid::new(40, 30);
149    // Copy some areas from floor 1 to create overlapping regions
150    for y in 5..25 {
151        for x in 5..35 {
152            if grid.get(x, y).is_some_and(|t| t.is_floor()) && rng.random() < 0.6 {
153                floor2.set(x, y, terrain_forge::Tile::Floor);
154            }
155        }
156    }
157
158    let floors = vec![grid.clone(), floor2];
159    let mut connectivity = VerticalConnectivity::new();
160
161    connectivity.analyze_stair_candidates(&floors, 2);
162    connectivity.place_stairs(3);
163
164    println!("   Floor 1 tiles: {}", floors[0].count(|t| t.is_floor()));
165    println!("   Floor 2 tiles: {}", floors[1].count(|t| t.is_floor()));
166    println!(
167        "   Stair candidates: {}",
168        connectivity.stair_candidates.len()
169    );
170    println!("   Stairs placed: {}", connectivity.stairs.len());
171
172    // Step 7: Final summary
173    println!("\n🎯 Generation Summary:");
174    println!("   Grid size: {}x{}", grid.width(), grid.height());
175    println!("   Total floor area: {}", grid.count(|t| t.is_floor()));
176    println!(
177        "   Density: {:.1}%",
178        (grid.count(|t| t.is_floor()) as f32 / (grid.width() * grid.height()) as f32) * 100.0
179    );
180    println!("   Regions: {}", semantic.regions.len());
181    println!("   Total markers: {}", semantic.markers.len());
182
183    // Group markers by category
184    let mut categories = std::collections::HashMap::new();
185    for marker in &semantic.markers {
186        *categories.entry(marker.marker_type.category()).or_insert(0) += 1;
187    }
188
189    println!("   Marker distribution:");
190    for (category, count) in categories {
191        println!("     {}: {}", category, count);
192    }
193
194    println!(
195        "   Pipeline steps executed: {}",
196        context.execution_history().len()
197    );
198    println!("   Multi-floor stairs: {}", connectivity.stairs.len());
199
200    println!("\n✨ Advanced dungeon generation complete!");
201}
Source

pub fn fill(&mut self, cell: C)

Source

pub fn fill_rect(&mut self, x: i32, y: i32, w: usize, h: usize, cell: C)

Source

pub fn count<F: Fn(&C) -> bool>(&self, predicate: F) -> usize

Examples found in repository?
examples/phase1_demo.rs (line 90)
76fn demo_generate_with_requirements() {
77    println!("📋 Demo 2: Generate with Requirements");
78
79    let mut requirements = SemanticRequirements::basic_dungeon();
80    requirements.min_regions.insert("room".to_string(), 4);
81    requirements
82        .required_markers
83        .insert(MarkerType::LootTier { tier: 1 }, 2);
84
85    match terrain_forge::generate_with_requirements("bsp", 60, 40, requirements, Some(5), 54321) {
86        Ok((grid, semantic)) => {
87            println!("  ✅ Generated valid dungeon!");
88            println!("  Regions: {}", semantic.regions.len());
89            println!("  Markers: {}", semantic.markers.len());
90            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
91        }
92        Err(msg) => println!("  ❌ Failed: {}", msg),
93    }
94    println!();
95}
More examples
Hide additional examples
examples/bsp_analysis.rs (line 14)
3fn main() {
4    println!("=== BSP Algorithm Analysis ===\n");
5
6    let mut grid = Grid::new(40, 30);
7    algorithms::get("bsp").unwrap().generate(&mut grid, 12345);
8
9    let extractor = SemanticExtractor::for_rooms();
10    let mut rng = Rng::new(12345);
11    let semantic = extractor.extract(&grid, &mut rng);
12
13    println!("Generated map analysis:");
14    println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
15    println!("  Total regions: {}", semantic.regions.len());
16
17    println!("\nRegion breakdown:");
18    let mut region_counts = std::collections::HashMap::new();
19    for region in &semantic.regions {
20        *region_counts.entry(&region.kind).or_insert(0) += 1;
21    }
22
23    for (kind, count) in &region_counts {
24        println!("  {}: {}", kind, count);
25    }
26
27    println!("\nMarker breakdown:");
28    let mut marker_counts = std::collections::HashMap::new();
29    for marker in &semantic.markers {
30        *marker_counts.entry(marker.tag()).or_insert(0) += 1;
31    }
32
33    for (tag, count) in &marker_counts {
34        println!("  {}: {}", tag, count);
35    }
36}
examples/requirements_demo.rs (line 22)
3fn main() {
4    println!("=== Generate with Requirements Demo ===\n");
5
6    // Create simple requirements that match BSP output
7    let mut requirements = SemanticRequirements::none();
8    requirements.min_regions.insert("Hall".to_string(), 1); // BSP produces "Hall" regions
9    requirements
10        .required_markers
11        .insert(MarkerType::Custom("PlayerStart".to_string()), 1); // BSP produces "PlayerStart"
12
13    println!("Requirements:");
14    println!("  - Minimum 1 Hall region");
15    println!("  - At least 1 PlayerStart marker");
16    println!();
17
18    match generate_with_requirements("bsp", 40, 30, requirements, Some(10), 12345) {
19        Ok((grid, semantic)) => {
20            println!("✅ Successfully generated map meeting requirements!");
21            println!("  Grid size: {}x{}", grid.width(), grid.height());
22            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
23            println!("  Total regions: {}", semantic.regions.len());
24
25            // Count Hall regions
26            let hall_count = semantic.regions.iter().filter(|r| r.kind == "Hall").count();
27            println!("  Hall regions: {}", hall_count);
28
29            // Count PlayerStart markers
30            let start_count = semantic
31                .markers
32                .iter()
33                .filter(|m| m.tag() == "PlayerStart")
34                .count();
35            println!("  PlayerStart markers: {}", start_count);
36
37            println!("\nFirst few regions:");
38            for (i, region) in semantic.regions.iter().take(3).enumerate() {
39                println!("  {}: {} ({} cells)", i + 1, region.kind, region.area());
40            }
41        }
42        Err(msg) => {
43            println!("❌ Failed to generate: {}", msg);
44        }
45    }
46}
examples/phase2_demo.rs (line 70)
16fn demo_conditional_pipeline() {
17    println!("🔀 Demo 1: Conditional Pipeline Operations");
18
19    let mut grid = Grid::new(30, 20);
20    let mut context = PipelineContext::new();
21    let mut rng = Rng::new(12345);
22
23    // Create conditional pipeline
24    let mut pipeline = ConditionalPipeline::new();
25
26    // Add algorithm operation
27    pipeline.add_operation(ConditionalOperation::simple(PipelineOperation::Algorithm {
28        name: "bsp".to_string(),
29        seed: Some(12345),
30    }));
31
32    // Add conditional operation based on floor density
33    pipeline.add_operation(ConditionalOperation::conditional(
34        PipelineOperation::Log {
35            message: "Evaluating floor density".to_string(),
36        },
37        PipelineCondition::Density {
38            min: Some(0.2),
39            max: Some(0.6),
40        },
41        vec![ConditionalOperation::simple(
42            PipelineOperation::SetParameter {
43                key: "density_status".to_string(),
44                value: "acceptable".to_string(),
45            },
46        )],
47        vec![ConditionalOperation::simple(
48            PipelineOperation::SetParameter {
49                key: "density_status".to_string(),
50                value: "out_of_range".to_string(),
51            },
52        )],
53    ));
54
55    // Execute pipeline
56    let result = pipeline.execute(&mut grid, &mut context, &mut rng);
57
58    println!(
59        "  Pipeline execution: {}",
60        if result.success {
61            "✅ Success"
62        } else {
63            "❌ Failed"
64        }
65    );
66    if let Some(msg) = result.message {
67        println!("  Message: {}", msg);
68    }
69
70    println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
71    println!(
72        "  Density status: {}",
73        context
74            .get_parameter("density_status")
75            .unwrap_or(&"unknown".to_string())
76    );
77    println!("  Execution log: {:?}", context.execution_history());
78    println!();
79}
80
81fn demo_pipeline_templates() {
82    println!("📋 Demo 2: Pipeline Templates");
83
84    // Create custom template
85    let template = PipelineTemplate::new("custom_dungeon", "Customizable dungeon template")
86        .with_parameter("algorithm", "cellular")
87        .with_parameter("seed", "54321")
88        .with_parameter("type", "dungeon")
89        .with_operation(ConditionalOperation::simple(PipelineOperation::Algorithm {
90            name: "{algorithm}".to_string(),
91            seed: Some(54321),
92        }))
93        .with_operation(ConditionalOperation::simple(
94            PipelineOperation::SetParameter {
95                key: "generation_type".to_string(),
96                value: "{type}".to_string(),
97            },
98        ));
99
100    // Instantiate with custom parameters
101    let mut custom_params = std::collections::HashMap::new();
102    custom_params.insert("algorithm".to_string(), "bsp".to_string());
103    custom_params.insert("type".to_string(), "fortress".to_string());
104
105    let pipeline = template.instantiate(Some(custom_params));
106
107    let mut grid = Grid::new(25, 25);
108    let mut context = PipelineContext::new();
109    let mut rng = Rng::new(98765);
110
111    let result = pipeline.execute(&mut grid, &mut context, &mut rng);
112
113    println!("  Template: {}", template.name);
114    println!("  Description: {}", template.description);
115    println!(
116        "  Execution: {}",
117        if result.success {
118            "✅ Success"
119        } else {
120            "❌ Failed"
121        }
122    );
123    println!(
124        "  Generation type: {}",
125        context
126            .get_parameter("generation_type")
127            .unwrap_or(&"unknown".to_string())
128    );
129    println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
130    println!();
131}
132
133fn demo_template_library() {
134    println!("📚 Demo 3: Template Library");
135
136    let library = TemplateLibrary::new();
137
138    println!("  Available templates:");
139    for name in library.template_names() {
140        if let Some(template) = library.get_template(name) {
141            println!("    - {}: {}", name, template.description);
142        }
143    }
144
145    // Use built-in template
146    if let Some(template) = library.get_template("simple_dungeon") {
147        let pipeline = template.instantiate(None);
148
149        let mut grid = Grid::new(40, 30);
150        let mut context = PipelineContext::new();
151        let mut rng = Rng::new(11111);
152
153        let result = pipeline.execute(&mut grid, &mut context, &mut rng);
154
155        println!("\n  Executed 'simple_dungeon' template:");
156        println!(
157            "    Result: {}",
158            if result.success {
159                "✅ Success"
160            } else {
161                "❌ Failed"
162            }
163        );
164        println!("    Floor tiles: {}", grid.count(|t| t.is_floor()));
165        println!("    Steps executed: {}", context.execution_history().len());
166    }
167    println!();
168}
examples/requirement_generation.rs (line 13)
3fn main() {
4    println!("=== Requirement-Driven Generation Demo ===\n");
5
6    // Demo 1: Basic dungeon requirements
7    println!("1. Basic Dungeon Requirements:");
8    let basic_req = SemanticRequirements::basic_dungeon();
9
10    match generate_with_requirements("bsp", 40, 30, basic_req, Some(5), 12345) {
11        Ok((grid, semantic)) => {
12            println!("  ✅ Generated valid dungeon!");
13            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
14            println!("  Regions: {}", semantic.regions.len());
15            println!("  Markers: {}", semantic.markers.len());
16        }
17        Err(msg) => println!("  ❌ Failed: {}", msg),
18    }
19
20    // Demo 2: Custom requirements
21    println!("\n2. Custom Cave Requirements:");
22    let mut cave_req = SemanticRequirements::none();
23    cave_req.min_regions.insert("cavern".to_string(), 2);
24    cave_req.min_walkable_area = Some(200);
25    cave_req
26        .required_markers
27        .insert(MarkerType::Custom("entrance".to_string()), 1);
28    cave_req
29        .required_markers
30        .insert(MarkerType::Custom("treasure".to_string()), 1);
31
32    match generate_with_requirements("cellular", 50, 40, cave_req, Some(10), 54321) {
33        Ok((grid, semantic)) => {
34            println!("  ✅ Generated valid cave system!");
35            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
36            println!("  Regions: {}", semantic.regions.len());
37
38            // Show region types
39            let mut region_types = std::collections::HashMap::new();
40            for region in &semantic.regions {
41                *region_types.entry(&region.kind).or_insert(0) += 1;
42            }
43            for (kind, count) in region_types {
44                println!("    {}: {}", kind, count);
45            }
46        }
47        Err(msg) => println!("  ❌ Failed: {}", msg),
48    }
49
50    // Demo 3: Strict requirements (likely to fail)
51    println!("\n3. Strict Requirements (demonstration of failure):");
52    let mut strict_req = SemanticRequirements::none();
53    strict_req.min_regions.insert("room".to_string(), 10); // Very strict
54    strict_req
55        .required_markers
56        .insert(MarkerType::QuestObjective { priority: 1 }, 5);
57    strict_req.min_walkable_area = Some(800);
58
59    match generate_with_requirements("bsp", 30, 20, strict_req, Some(3), 98765) {
60        Ok((grid, _semantic)) => {
61            println!("  ✅ Unexpectedly succeeded!");
62            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
63        }
64        Err(msg) => println!("  ❌ Expected failure: {}", msg),
65    }
66}
examples/enhanced_wfc.rs (line 50)
10fn main() {
11    println!("=== Enhanced Wave Function Collapse Demo ===\n");
12
13    // Step 1: Generate example map for pattern learning
14    println!("1. Generating Example Map for Pattern Learning:");
15    let mut example_grid = Grid::new(20, 15);
16    let bsp = Bsp::default();
17    bsp.generate(&mut example_grid, 54321);
18
19    print_grid(&example_grid, "Example Map");
20
21    // Step 2: Extract patterns from example
22    println!("\n2. Extracting Patterns from Example:");
23    let patterns = WfcPatternExtractor::extract_patterns(&example_grid, 3);
24    println!("   Extracted {} unique patterns", patterns.len());
25
26    // Step 3: Generate with learned patterns (no backtracking)
27    println!("\n3. WFC Generation without Backtracking:");
28    let mut grid1 = Grid::new(25, 20);
29    let wfc_no_backtrack = Wfc::new(WfcConfig {
30        floor_weight: 0.4,
31        pattern_size: 3,
32        enable_backtracking: false,
33    });
34    wfc_no_backtrack.generate_with_patterns(&mut grid1, patterns.clone(), 12345);
35    print_grid(&grid1, "Without Backtracking");
36
37    // Step 4: Generate with backtracking enabled
38    println!("\n4. WFC Generation with Backtracking:");
39    let mut grid2 = Grid::new(25, 20);
40    let wfc_backtrack = Wfc::new(WfcConfig {
41        floor_weight: 0.4,
42        pattern_size: 3,
43        enable_backtracking: true,
44    });
45    wfc_backtrack.generate_with_patterns(&mut grid2, patterns.clone(), 12345);
46    print_grid(&grid2, "With Backtracking");
47
48    // Step 5: Compare results
49    println!("\n5. Comparison:");
50    let floors1 = grid1.count(|t| t.is_floor());
51    let floors2 = grid2.count(|t| t.is_floor());
52
53    println!(
54        "   Without backtracking: {} floors ({:.1}%)",
55        floors1,
56        100.0 * floors1 as f32 / (grid1.width() * grid1.height()) as f32
57    );
58    println!(
59        "   With backtracking: {} floors ({:.1}%)",
60        floors2,
61        100.0 * floors2 as f32 / (grid2.width() * grid2.height()) as f32
62    );
63
64    // Step 6: Different pattern sizes
65    println!("\n6. Pattern Size Comparison:");
66    for size in [2, 3, 4] {
67        let patterns = WfcPatternExtractor::extract_patterns(&example_grid, size);
68        let mut grid = Grid::new(15, 12);
69        let wfc = Wfc::new(WfcConfig {
70            floor_weight: 0.4,
71            pattern_size: size,
72            enable_backtracking: true,
73        });
74        wfc.generate_with_patterns(&mut grid, patterns.clone(), 98765);
75
76        let floors = grid.count(|t| t.is_floor());
77        println!(
78            "   Pattern size {}: {} patterns, {} floors",
79            size,
80            patterns.len(),
81            floors
82        );
83    }
84
85    println!("\n✅ Enhanced WFC demo complete!");
86    println!("   - Pattern learning extracts reusable structures");
87    println!("   - Backtracking improves generation success rate");
88    println!("   - Constraint propagation ensures valid outputs");
89}
Source

pub fn iter(&self) -> impl Iterator<Item = (usize, usize, &C)>

Trait Implementations§

Source§

impl<C: Clone + Cell> Clone for Grid<C>

Source§

fn clone(&self) -> Grid<C>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<C: Debug + Cell> Debug for Grid<C>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<C: Cell> Index<(usize, usize)> for Grid<C>

Source§

type Output = C

The returned type after indexing.
Source§

fn index(&self, (x, y): (usize, usize)) -> &Self::Output

Performs the indexing (container[index]) operation. Read more
Source§

impl<C: Cell> IndexMut<(usize, usize)> for Grid<C>

Source§

fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl<C: Cell + PartialEq> PartialEq for Grid<C>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<C: Cell + Eq> Eq for Grid<C>

Auto Trait Implementations§

§

impl<C> Freeze for Grid<C>

§

impl<C> RefUnwindSafe for Grid<C>
where C: RefUnwindSafe,

§

impl<C> Send for Grid<C>
where C: Send,

§

impl<C> Sync for Grid<C>
where C: Sync,

§

impl<C> Unpin for Grid<C>
where C: Unpin,

§

impl<C> UnwindSafe for Grid<C>
where C: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V