Class: RDGC::Maker::DivideDungeonMaker
- Inherits:
-
Object
- Object
- RDGC::Maker::DivideDungeonMaker
show all
- Includes:
- DungeonMaker
- Defined in:
- lib/rdgc/maker/divide_dungeon_maker.rb
Constant Summary
collapse
- DEFAULT_CROSS_ROAD_RATIO =
2
Class Method Summary
collapse
Instance Method Summary
collapse
#blocks, #clear_block, #create_pure_blocks, #make, #params
Class Method Details
.create(width, height, params = nil) ⇒ Object
7
8
9
10
11
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 7
def self.create(width, height, params = nil)
dm = self.new
list = dm.make(width, height, params)
Map::Board.create_from_blocks(list)
end
|
Instance Method Details
#add_road_for_dead_end ⇒ Object
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 384
def add_road_for_dead_end
deadends = blocks.select{|b| b.dead_end?}
return if deadends.empty?
deadends.each do |target|
c_list = []
block_list = blocks.select{|b| b.has_road?}
target.remain_direction.each do |d|
ret = collect_cling_block(target, block_list, d)
c_list += ret.flatten
end
next if c_list.empty?
target.create_road_to(c_list.pickup!)
end
end
|
#collect_cling_block(block, list, direction) ⇒ Object
346
347
348
349
350
351
352
353
354
355
356
357
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 346
def collect_cling_block(block, list, direction)
case direction
when :top
list.select{|b| block.cling_to_top?(b)}
when :bottom
list.select{|b| block.cling_to_bottom?(b)}
when :left
list.select{|b| block.cling_to_left?(b)}
when :right
list.select{|b| block.cling_to_right?(b)}
end
end
|
#connect_cling_block_has_road ⇒ Object
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 285
def connect_cling_block_has_road
remains = blocks.select{|b| b.has_room? && ! b.has_road?}
return if remains.empty?
done_count = blocks.select{|b| b.has_room? && b.has_road?}.size
remains.each do |target|
if done_count >= min_room_count
next unless bool_rand
end
c_list = create_cling_list(target, blocks.select{|b| b.has_road?}).flatten
return if c_list.empty?
target.create_road_to(c_list.pickup!)
c_list.each{|b| target.add_remain_cling_blocks(b)}
done_count += 1
end
end
|
#connect_cling_blocks(target, cling_list) ⇒ Object
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 359
def connect_cling_blocks(target, cling_list)
return unless cling_list
return if cling_list.size <= 0
direction_list = cling_list.pickup!
next_block = direction_list.pickup!
target.create_road_to(next_block)
direction_list.each{|b| target.add_remain_cling_blocks(b)}
cling_list.each do |d_list|
bl = d_list.pickup! if bool_rand
target.create_road_to(bl) if bl
d_list.each{|b| target.add_remain_cling_blocks(b)}
end
next_block
end
|
#create_cling_list(block, list) ⇒ Object
337
338
339
340
341
342
343
344
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 337
def create_cling_list(block, list)
top_list = collect_cling_block(block, list,:top)
bottom_list = collect_cling_block(block, list, :bottom)
left_list = collect_cling_block(block, list, :left)
right_list = collect_cling_block(block, list, :right)
[top_list, bottom_list, left_list, right_list].select{|a| a.size > 0}
end
|
#create_road ⇒ Object
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 40
def create_road
return if blocks.size <= 1
recursive_road_create(blocks.choice)
connect_cling_block_has_road
move_room_and_connect
add_road_for_dead_end
end
|
#create_room ⇒ Object
35
36
37
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 35
def create_room
force_room_count ? create_room_force : create_room_normal
end
|
#create_room_force ⇒ Object
252
253
254
255
256
257
258
259
260
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 252
def create_room_force
blocks.shuffle.each.with_index do |b, i|
if (i+1) <= force_room_count.to_i
b.create_room(:min => min_room_size, :max => max_room_size)
else
b.create_cross_point
end
end
end
|
#create_room_normal ⇒ Object
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 197
def create_room_normal
room_blocks = []
cross_blocks = []
force_room_blocks = []
param = {
:room => (10 - cross_road_ratio),
:cross => cross_road_ratio
}
blocks.each do |b|
if b.depth < 2
force_room_blocks << b
next
end
r = select_rand(param)
case r
when :room
room_blocks << b
when :cross
cross_blocks << b
end
end
room_count = room_blocks.size + force_room_blocks.size
if max_room_count > 0 && room_count > max_room_count
(room_count - max_room_count).times do
break if room_blocks.size + force_room_blocks.size <= 1
break if room_blocks.empty?
b = room_blocks.pickup!
cross_blocks << b if b
end
end
room_count = room_blocks.size + force_room_blocks.size
if room_count < min_room_count
(min_room_count - room_count).times do
break if cross_blocks.empty?
b = cross_blocks.pickup!
room_blocks << b if b
end
end
[room_blocks, force_room_blocks].flatten.each do |b|
b.create_room(:min => min_room_size, :max => max_room_size)
end
cross_blocks.each{|b| b.create_cross_point}
end
|
#create_whole_block(width, height) ⇒ Object
16
17
18
19
20
21
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 16
def create_whole_block(width, height)
tb = DivideTempBlock.create_whole_block(width, height)
tb.min_size = min_block_size
tb.dividable
tb
end
|
#cross_road_ratio ⇒ Object
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 108
def cross_road_ratio
unless @cross_road_ratio
val = params[:cross_road_ratio]
if val
val = val.to_i
val = DEFAULT_CROSS_ROAD_RATIO if (val < 0 || val > 9)
else
val = DEFAULT_CROSS_ROAD_RATIO
end
@cross_road_ratio = val
end
@cross_road_ratio
end
|
#dividable_block?(b) ⇒ Boolean
148
149
150
151
152
153
154
155
156
157
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 148
def dividable_block?(b)
return false unless b.dividable?
return true if max_depth <= 0
b.depth >= max_depth ? false : true
end
|
#divide ⇒ Object
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 159
def divide
loop do
break if finish?
tb = divide_queue.shift
break unless tb
list = tb.divide
unless list
done_queue << tb
break
end
list.each do |b|
if dividable_block?(b)
divide_queue << b
else
done_queue << b
end
end
end
divide_queue.each{|b| done_queue << b}
if min_block_count > 0 && done_queue.size < min_block_count
(min_block_count - queue_size).times do
tb = done_queue.select{|b| b.dividable_size?}.shuffle.shift
break unless tb
done_queue.delete(tb)
tb.divide.each{|b| done_queue << b}
end
end
end
|
#divide_queue ⇒ Object
128
129
130
131
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 128
def divide_queue
@divide_queue ||= []
@divide_queue
end
|
#done_queue ⇒ Object
133
134
135
136
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 133
def done_queue
@done_queue ||= []
@done_queue
end
|
#finish? ⇒ Boolean
142
143
144
145
146
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 142
def finish?
return true if divide_queue.empty?
return true if (max_block_count > 0 && queue_size >= max_block_count)
false
end
|
#force_room_count ⇒ Object
124
125
126
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 124
def force_room_count
params[:force_room_count]
end
|
#make_blocks(tb) ⇒ Object
23
24
25
26
27
28
29
30
31
32
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 23
def make_blocks(tb)
divide_queue << tb
divide
done_queue
end
|
#max_block_count ⇒ Object
86
87
88
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 86
def max_block_count
params[:max_block_count].to_i
end
|
#max_depth ⇒ Object
104
105
106
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 104
def max_depth
params[:max_depth].to_i
end
|
#max_room_count ⇒ Object
100
101
102
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 100
def max_room_count
params[:max_room_count].to_i
end
|
#max_room_size ⇒ Object
78
79
80
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 78
def max_room_size
params[:max_room_size]
end
|
#min_block_count ⇒ Object
82
83
84
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 82
def min_block_count
params[:min_block_count].to_i
end
|
#min_block_size ⇒ Object
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 58
def min_block_size
unless @min_block_size
val = params[:min_block_size]
if val
val = val.to_i
else
val = (min_room_size ? min_room_size + 3 : 0)
end
val = Util::Config.min_block_size if val < Util::Config.min_block_size
@min_block_size = val
end
@min_block_size
end
|
#min_room_count ⇒ Object
90
91
92
93
94
95
96
97
98
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 90
def min_room_count
return force_room_count if force_room_count
unless @min_room_count
val = params[:min_room_count].to_i
@min_room_count = (val > 2 ? val : 2)
end
@min_room_count
end
|
#min_room_size ⇒ Object
74
75
76
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 74
def min_room_size
params[:min_room_size]
end
|
#move_room_and_connect ⇒ Object
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 309
def move_room_and_connect
done_count = blocks.select{|b| b.has_room? && b.has_road?}.size
return if done_count >= min_room_count
remains = blocks.select{|b| b.has_room? && ! b.has_road?}
return if remains.empty?
remains.each do |target|
target.remove_all
enable_blocks = blocks.select{|b| b.has_remain_cling_blocks?}
next if enable_blocks.empty?
org_block = enable_blocks.choice
room_block = org_block.remain_cling_blocks.pickup!
room_block.create_room(:min => min_room_size, :max => max_room_size)
room_block.create_road_to(org_block)
end
end
|
#queue_size ⇒ Object
138
139
140
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 138
def queue_size
divide_queue.size + done_queue.size
end
|
#recursive_road_create(target) ⇒ Object
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
|
# File 'lib/rdgc/maker/divide_dungeon_maker.rb', line 264
def recursive_road_create(target)
return if blocks.all?{|b| b.has_road?}
yet_block = blocks.reject{|b| b.road_created?}
cling_list = create_cling_list(target, yet_block)
return if cling_list.size <= 0
next_block = connect_cling_blocks(target, cling_list)
target.road_created
recursive_road_create(next_block)
end
|