@@ -29,11 +29,6 @@ def initialize(tiles, width, height)
2929 @height . times { |y | @width . times { |x | @cells << Cell . new ( x , y , @tiles . shuffle ) } }
3030 @uncollapsed_cells = Set . new ( @cells . reject ( &:collapsed ) )
3131 @max_entropy = @tiles . length
32-
33- # Initialize entropy buckets for O(1) minimum entropy lookup
34- @entropy_buckets = Hash . new { |h , k | h [ k ] = Set . new }
35- @min_entropy = @max_entropy
36- @uncollapsed_cells . each { |cell | @entropy_buckets [ cell . entropy ] . add ( cell ) }
3732 end
3833
3934 def build_tile_adjacencies
@@ -62,45 +57,6 @@ def build_tile_adjacencies
6257 end
6358 end
6459
65- # Update entropy bucket when a cell's entropy changes
66- def update_cell_entropy ( cell , old_entropy , new_entropy )
67- return if old_entropy == new_entropy
68-
69- # Remove from old bucket
70- @entropy_buckets [ old_entropy ] . delete ( cell )
71- @entropy_buckets . delete ( old_entropy ) if @entropy_buckets [ old_entropy ] . empty?
72-
73- # Add to new bucket (unless collapsed)
74- if new_entropy > 1
75- @entropy_buckets [ new_entropy ] . add ( cell )
76- end
77-
78- # Update minimum entropy if needed
79- update_min_entropy
80- end
81-
82- # Remove cell from entropy tracking (when collapsed or removed)
83- def remove_from_entropy_buckets ( cell )
84- # Cell might be in any bucket, so search all buckets to remove it
85- # This is still O(1) amortized since we only check a few entropy levels
86- @entropy_buckets . each do |entropy , bucket |
87- if bucket . delete ( cell )
88- @entropy_buckets . delete ( entropy ) if bucket . empty?
89- break
90- end
91- end
92- update_min_entropy
93- end
94-
95- # Find the current minimum entropy value
96- def update_min_entropy
97- if @entropy_buckets . empty?
98- @min_entropy = nil
99- else
100- @min_entropy = @entropy_buckets . keys . min
101- end
102- end
103-
10460 def cell_at ( x , y )
10561 @cells [ @width * y + x ]
10662 end
@@ -137,10 +93,8 @@ def prepend_empty_row
13793 new_cell = Cell . new ( x , @height - 1 , @tiles )
13894 @cells << new_cell
13995 @uncollapsed_cells . add ( new_cell )
140- @entropy_buckets [ new_cell . entropy ] . add ( new_cell )
14196 x = x . succ
14297 end
143- update_min_entropy
14498 @width . times { |x |
14599 evaluate_neighbor ( cell_at ( x , @height - 2 ) , :up )
146100 }
@@ -169,13 +123,8 @@ def generate_grid
169123 end
170124
171125 def process_cell ( cell )
172- old_entropy = cell . entropy
173126 cell . collapse
174127 @uncollapsed_cells . delete ( cell )
175- # Remove from the bucket it was in before collapsing
176- @entropy_buckets [ old_entropy ] &.delete ( cell )
177- @entropy_buckets . delete ( old_entropy ) if @entropy_buckets [ old_entropy ] &.empty?
178- update_min_entropy
179128 return if @uncollapsed_cells . empty?
180129
181130 propagate ( cell )
@@ -222,32 +171,32 @@ def evaluate_neighbor(source_cell, evaluation_direction)
222171 new_tiles << neighbor_tile if valid_tile_ids [ neighbor_tile . __id__ ]
223172 end
224173
225- unless new_tiles . empty?
226- old_entropy = neighbor_cell . entropy
227- neighbor_cell . tiles = new_tiles
228- new_entropy = neighbor_cell . entropy
229-
230- # Update entropy buckets if entropy changed
231- # update_cell_entropy handles removal from buckets when cell collapses (entropy=1)
232- update_cell_entropy ( neighbor_cell , old_entropy , new_entropy ) if old_entropy != new_entropy
233-
234- # Remove from uncollapsed set if collapsed
235- @uncollapsed_cells . delete ( neighbor_cell ) if neighbor_cell . collapsed
236- end
174+ neighbor_cell . tiles = new_tiles unless new_tiles . empty?
175+ @uncollapsed_cells . delete ( neighbor_cell ) if neighbor_cell . collapsed
237176
238177 # if the number of tiles changed, we need to evaluate current cell's neighbors now
239178 propagate ( neighbor_cell ) if neighbor_cell . tiles . length != original_tile_count
240179 end
241180
242181 def find_lowest_entropy
243- return nil if @min_entropy . nil?
182+ return nil if @uncollapsed_cells . empty?
183+
184+ min_e = nil
185+ acc = [ ]
186+
187+ @uncollapsed_cells . each do |cell |
188+ ce = cell . entropy
244189
245- # Get cells with minimum entropy from bucket (O(1) instead of O(n))
246- min_entropy_cells = @entropy_buckets [ @min_entropy ]
247- return nil if min_entropy_cells . nil? || min_entropy_cells . empty?
190+ if min_e . nil? || ce < min_e
191+ min_e = ce
192+ acc . clear
193+ acc << cell
194+ elsif ce == min_e
195+ acc << cell
196+ end
197+ end
248198
249- # Sample randomly from cells with same minimum entropy
250- min_entropy_cells . to_a . sample
199+ acc . sample
251200 end
252201 end
253202end
0 commit comments