pub struct Grid<C: Cell = Tile> { /* private fields */ }Expand description
2D grid of cells
Implementations§
Source§impl<C: Cell> Grid<C>
impl<C: Cell> Grid<C>
Sourcepub fn new(width: usize, height: usize) -> Self
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(®ion.kind).or_insert(0) += 1;
21 }
22
23 for (kind, count) in ®ion_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
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}Additional examples can be found in:
- examples/enhanced_wfc.rs
- examples/morphological_operations.rs
- examples/conditional_pipelines.rs
- examples/vertical_connectivity.rs
- examples/delaunay_connections.rs
- examples/spatial_workflow.rs
- examples/pipeline_templates.rs
- examples/advanced_prefabs.rs
- examples/complete_workflow.rs
- examples/phase4_workflow.rs
Sourcepub fn width(&self) -> usize
pub fn width(&self) -> usize
Examples found in repository?
More examples
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}Additional examples can be found in:
Sourcepub fn height(&self) -> usize
pub fn height(&self) -> usize
Examples found in repository?
More examples
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}Additional examples can be found in:
pub fn in_bounds(&self, x: i32, y: i32) -> bool
Sourcepub fn get(&self, x: i32, y: i32) -> Option<&C>
pub fn get(&self, x: i32, y: i32) -> Option<&C>
Examples found in repository?
More examples
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}Additional examples can be found in:
pub fn get_mut(&mut self, x: i32, y: i32) -> Option<&mut C>
Sourcepub fn set(&mut self, x: i32, y: i32, cell: C) -> bool
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
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}pub fn fill(&mut self, cell: C)
pub fn fill_rect(&mut self, x: i32, y: i32, w: usize, h: usize, cell: C)
Sourcepub fn count<F: Fn(&C) -> bool>(&self, predicate: F) -> usize
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
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(®ion.kind).or_insert(0) += 1;
21 }
22
23 for (kind, count) in ®ion_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(®ion.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}pub fn iter(&self) -> impl Iterator<Item = (usize, usize, &C)>
Trait Implementations§
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more