pub struct VerticalConnectivity {
pub stair_candidates: Vec<(u32, u32, u32, u32)>,
pub stairs: Vec<(u32, u32, u32, u32)>,
pub floor_accessibility: HashMap<u32, Vec<u32>>,
}Expand description
Vertical connectivity analysis for multi-floor support
Fields§
§stair_candidates: Vec<(u32, u32, u32, u32)>Potential stair locations (x, y, floor_from, floor_to)
stairs: Vec<(u32, u32, u32, u32)>Confirmed stair placements
floor_accessibility: HashMap<u32, Vec<u32>>Regions accessible from each floor
Implementations§
Source§impl VerticalConnectivity
impl VerticalConnectivity
Sourcepub fn new() -> Self
pub fn new() -> Self
Create empty vertical connectivity analysis
Examples found in repository?
examples/phase1_demo.rs (line 113)
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 56)
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 159)
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}Sourcepub fn analyze_stair_candidates(
&mut self,
floor_grids: &[Grid<Tile>],
min_clearance: usize,
)
pub fn analyze_stair_candidates( &mut self, floor_grids: &[Grid<Tile>], min_clearance: usize, )
Analyze potential stair placements between floors This is a basic implementation that looks for suitable floor tiles adjacent to walls that could support stairs
Examples found in repository?
examples/phase1_demo.rs (line 115)
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 61)
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 161)
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}Sourcepub fn place_stairs(&mut self, max_stairs_per_floor: usize)
pub fn place_stairs(&mut self, max_stairs_per_floor: usize)
Place stairs at the best candidate locations
Examples found in repository?
examples/phase1_demo.rs (line 116)
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 82)
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 162)
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}Trait Implementations§
Source§impl Clone for VerticalConnectivity
impl Clone for VerticalConnectivity
Source§fn clone(&self) -> VerticalConnectivity
fn clone(&self) -> VerticalConnectivity
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for VerticalConnectivity
impl Debug for VerticalConnectivity
Auto Trait Implementations§
impl Freeze for VerticalConnectivity
impl RefUnwindSafe for VerticalConnectivity
impl Send for VerticalConnectivity
impl Sync for VerticalConnectivity
impl Unpin for VerticalConnectivity
impl UnwindSafe for VerticalConnectivity
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