rdgc-dm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+ # coding: UTF-8
2
+ module RDGC
3
+ module Map
4
+ class Room < Area
5
+
6
+ def self.create(top, bottom, left, right)
7
+ room = super(top, bottom, left, right)
8
+ room.fill
9
+ room
10
+ end
11
+
12
+ def self.create_from_block(b, opt = nil)
13
+ room_w = room_size(b.width, opt)
14
+ room_h = room_size(b.height, opt)
15
+ return if (room_w <= 0 || room_h <= 0)
16
+
17
+ l_point = b.left+1 + room_point(b.width, room_w)
18
+ t_point = b.top+1 + room_point(b.height, room_h)
19
+
20
+ self.create(t_point, t_point + room_h - 1, l_point, l_point + room_w - 1)
21
+ end
22
+
23
+ def fill
24
+ fill_tile TileType::ROOM
25
+ end
26
+
27
+ private
28
+
29
+ def self.room_size(val, opt = nil)
30
+ opt ||= {}
31
+
32
+ # 部屋の最大サイズ = ブロックサイズ-壁1*2-通路1
33
+ base = val - 3
34
+ return 0 if base < Util::Config.min_room_size
35
+
36
+ # 最小値・最大値判定
37
+ min = min_size(base, opt[:min])
38
+ max = max_size(base, opt[:max])
39
+ min = max if min > max
40
+
41
+ range_rand(min, max)
42
+ end
43
+
44
+ def self.min_size(base, min)
45
+ min_room_size = Util::Config.min_room_size
46
+
47
+ return min_room_size unless min
48
+ min = min.to_i
49
+ return base if base < min
50
+ return min_room_size if min < min_room_size
51
+ min
52
+ end
53
+
54
+ def self.max_size(base, max)
55
+ return base unless max
56
+ max = max.to_i
57
+ return base if max > base
58
+ return Util::Config.min_room_size if max < Util::Config.min_room_size
59
+ max
60
+ end
61
+
62
+ def self.room_point(block_size, room_size)
63
+ # 右と下は余分に空ける => 結ぶ通路は左と上が担当
64
+ range_rand(0, block_size - 3 - room_size)
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ # coding: UTF-8
2
+ module RDGC
3
+ module Map
4
+ class Tile
5
+
6
+ def initialize(type)
7
+ @type = type
8
+ @type.freeze
9
+ end
10
+
11
+ def movable?
12
+ return false if out?
13
+ return false if wall?
14
+ true
15
+ end
16
+
17
+ def out?
18
+ @type == :out ? true : false
19
+ end
20
+
21
+ def wall?
22
+ @type == :wall ? true : false
23
+ end
24
+
25
+ def room?
26
+ @type == :room ? true : false
27
+ end
28
+
29
+ def road?
30
+ @type == :road ? true : false
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ # coding: UTF-8
2
+ module RDGC
3
+ module Map
4
+ module TileType
5
+ OUT = Tile.new(:out).freeze
6
+ WALL = Tile.new(:wall).freeze
7
+ ROOM = Tile.new(:room).freeze
8
+ ROAD = Tile.new(:road).freeze
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,74 @@
1
+ # coding: UTF-8
2
+ module RDGC
3
+ module Util
4
+ class Config
5
+
6
+ DEFAULT_CONFIG = {
7
+ :min_room_size => 4,
8
+ :act_max_count => 200
9
+ }
10
+
11
+ self.class.class_eval do
12
+ @config_hash = DEFAULT_CONFIG
13
+ end
14
+
15
+ def self.set(hash)
16
+ return if seted?
17
+
18
+ default = nil
19
+ self.class.class_eval do
20
+ default = @config_hash
21
+ end
22
+
23
+ hash = default.merge(hash)
24
+
25
+ self.class.class_eval do
26
+ @config_hash = hash
27
+ @seted = true
28
+ end
29
+
30
+ true
31
+ end
32
+
33
+ def self.min_room_size
34
+ self.get(:min_room_size)
35
+ end
36
+
37
+ def self.min_block_size
38
+ # デフォルトのblock最小値 = 最小部屋サイズ+上下空き2+接線通路分1
39
+ self.min_room_size + 3
40
+ end
41
+
42
+ def self.act_max_count
43
+ self.get(:act_max_count)
44
+ end
45
+
46
+ def self.seted?
47
+ ret = false
48
+ self.class.class_eval do
49
+ ret = @seted
50
+ end
51
+ ret
52
+ end
53
+
54
+ def self.get(key)
55
+ val = nil
56
+ self.class.class_eval do
57
+ val = @config_hash[key]
58
+ end
59
+ val
60
+ end
61
+
62
+ def self.reset!
63
+ self.class.class_eval do
64
+ @config_hash = DEFAULT_CONFIG
65
+ @seted = false
66
+ end
67
+
68
+ true
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+
@@ -0,0 +1,104 @@
1
+ # coding: UTF-8
2
+ module RDGC
3
+ module Util
4
+ module RandomUtil
5
+
6
+ def bool_rand
7
+ case rand(2)
8
+ when 1
9
+ true
10
+ when 0
11
+ false
12
+ end
13
+ end
14
+
15
+ def range_rand(s_val, e_val)
16
+ return s_val if e_val <= s_val
17
+ s_val + rand((e_val - s_val)+1)
18
+ end
19
+
20
+ def select_rand(hash)
21
+ return unless hash
22
+ return if hash.empty?
23
+
24
+ range_list = []
25
+ count = 0
26
+ hash.each do |k, v|
27
+ range = count...(count + v)
28
+ range_list << [range, k]
29
+ count += v
30
+ end
31
+ return if count <= 0
32
+
33
+ val = rand(count)
34
+
35
+ ret = nil
36
+ range_list.each do |r|
37
+ if r.first.include?(val)
38
+ ret = r.last
39
+ break
40
+ end
41
+ end
42
+
43
+ ret
44
+ end
45
+
46
+ def dice(n, max)
47
+ ret = 0
48
+ n.times{ret += range_rand(1, max)}
49
+ ret
50
+ end
51
+
52
+ module_function :bool_rand, :range_rand, :select_rand, :dice
53
+
54
+ end
55
+ end
56
+ end
57
+
58
+ class Integer
59
+
60
+ def dice(max)
61
+ RDGC::Util::RandomUtil.dice(self, max)
62
+ end
63
+ alias :d :dice
64
+
65
+ def method_missing(name, *args)
66
+ try_define_dice(name, args) ? (__send__ name) : super
67
+ end
68
+
69
+ def d4
70
+ self.dice(4)
71
+ end
72
+
73
+ def d6
74
+ self.dice(6)
75
+ end
76
+
77
+ def d10
78
+ self.dice(10)
79
+ end
80
+
81
+ private
82
+
83
+ def try_define_dice(name, args)
84
+ return false if args.size > 0
85
+
86
+ m = name.to_s.match(/^[d|D](\d+)$/)
87
+ return false unless m
88
+ return false if m[1].to_i <= 0
89
+
90
+ self.class.module_eval("def #{name};self.dice(#{m[1]});end")
91
+ true
92
+ end
93
+
94
+ end
95
+
96
+ class Array
97
+
98
+ def pickup!
99
+ ret = self.choice
100
+ self.delete(ret)
101
+ ret
102
+ end
103
+
104
+ end
data/lib/rdgc-dm.rb ADDED
@@ -0,0 +1,17 @@
1
+ # coding: UTF-8
2
+ require 'rdgc/util/config'
3
+ require 'rdgc/util/random_util'
4
+ include RDGC::Util::RandomUtil
5
+
6
+ require 'rdgc/map/tile'
7
+ require 'rdgc/map/tile_type'
8
+ require 'rdgc/map/area'
9
+ require 'rdgc/map/block'
10
+ require 'rdgc/map/room'
11
+ require 'rdgc/map/road'
12
+ require 'rdgc/map/board'
13
+
14
+ require 'rdgc/maker/temp_block'
15
+ require 'rdgc/maker/dungeon_maker'
16
+ require 'rdgc/maker/divide_temp_block'
17
+ require 'rdgc/maker/divide_dungeon_maker'
data/rdgc-dm.gemspec ADDED
@@ -0,0 +1,93 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rdgc-dm}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["parrot_studio"]
12
+ s.date = %q{2010-04-01}
13
+ s.description = %q{ This gem is part of RDGC - Ruby(Random) Dungeon Game Core.
14
+ RDGC is core of random dungeon game (like rogue), make dungeon, manage mnsters etc.
15
+ }
16
+ s.email = %q{parrot@users.sourceforge.jp}
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "lib/rdgc-dm.rb",
29
+ "lib/rdgc/maker/divide_dungeon_maker.rb",
30
+ "lib/rdgc/maker/divide_temp_block.rb",
31
+ "lib/rdgc/maker/dungeon_maker.rb",
32
+ "lib/rdgc/maker/temp_block.rb",
33
+ "lib/rdgc/map/area.rb",
34
+ "lib/rdgc/map/block.rb",
35
+ "lib/rdgc/map/board.rb",
36
+ "lib/rdgc/map/road.rb",
37
+ "lib/rdgc/map/room.rb",
38
+ "lib/rdgc/map/tile.rb",
39
+ "lib/rdgc/map/tile_type.rb",
40
+ "lib/rdgc/util/config.rb",
41
+ "lib/rdgc/util/random_util.rb",
42
+ "rdgc-dm.gemspec",
43
+ "spec/rdgc/maker/01_temp_block_spec.rb",
44
+ "spec/rdgc/maker/02_divide_temp_block_spec.rb",
45
+ "spec/rdgc/maker/03_divide_dungeon_maker_divide_spec.rb",
46
+ "spec/rdgc/maker/04_divide_dungeon_maker_create_spec.rb",
47
+ "spec/rdgc/map/01_tile_spec.rb",
48
+ "spec/rdgc/map/02_area_spec.rb",
49
+ "spec/rdgc/map/03_road_spec.rb",
50
+ "spec/rdgc/map/04_room_spec.rb",
51
+ "spec/rdgc/map/05_block_spec.rb",
52
+ "spec/rdgc/map/06_board_spec.rb",
53
+ "spec/rdgc/util/01_config_spec.rb",
54
+ "spec/rdgc/util/02_random_util_spec.rb",
55
+ "spec/spec.opts",
56
+ "spec/spec_helper.rb"
57
+ ]
58
+ s.homepage = %q{http://github.com/parrot-studio/rdgc-dm}
59
+ s.rdoc_options = ["--charset=UTF-8"]
60
+ s.require_paths = ["lib"]
61
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
62
+ s.rubygems_version = %q{1.3.6}
63
+ s.summary = %q{Random Dungeon Maker from RDGC}
64
+ s.test_files = [
65
+ "spec/spec_helper.rb",
66
+ "spec/rdgc/util/02_random_util_spec.rb",
67
+ "spec/rdgc/util/01_config_spec.rb",
68
+ "spec/rdgc/map/04_room_spec.rb",
69
+ "spec/rdgc/map/06_board_spec.rb",
70
+ "spec/rdgc/map/01_tile_spec.rb",
71
+ "spec/rdgc/map/03_road_spec.rb",
72
+ "spec/rdgc/map/05_block_spec.rb",
73
+ "spec/rdgc/map/02_area_spec.rb",
74
+ "spec/rdgc/maker/02_divide_temp_block_spec.rb",
75
+ "spec/rdgc/maker/01_temp_block_spec.rb",
76
+ "spec/rdgc/maker/04_divide_dungeon_maker_create_spec.rb",
77
+ "spec/rdgc/maker/03_divide_dungeon_maker_divide_spec.rb"
78
+ ]
79
+
80
+ if s.respond_to? :specification_version then
81
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
82
+ s.specification_version = 3
83
+
84
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
85
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
86
+ else
87
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
88
+ end
89
+ else
90
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
91
+ end
92
+ end
93
+
@@ -0,0 +1,45 @@
1
+ # coding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
3
+
4
+ include RDGC::Map
5
+ include RDGC::Maker
6
+
7
+ describe RDGC::Maker::TempBlock, 'is temp Block for Dungeon make' do
8
+
9
+ it "create_whole_block will create from width/height" do
10
+ tb = TempBlock.create_whole_block(20, 30)
11
+ tb.should be_an_instance_of(TempBlock)
12
+ tb.width.should == 20
13
+ tb.height.should == 30
14
+ tb.top.should == 0
15
+ tb.bottom.should == 29
16
+ tb.left.should == 0
17
+ tb.right.should == 19
18
+ end
19
+
20
+ it "#create_pure_block provides a pure Block instance from self" do
21
+ tb = TempBlock.create(0, 20, 0, 20)
22
+
23
+ room = Room.create(5, 15, 5, 15)
24
+ road1 = Road.create(0, 4, 10, 10)
25
+ road2 = Road.create(16, 20, 12, 12)
26
+
27
+ tb.room = room
28
+ tb.roads << road1
29
+ tb.roads << road2
30
+
31
+ b = tb.create_pure_block
32
+ b.should be_an_instance_of(Block)
33
+ b.should_not be_an_instance_of(TempBlock)
34
+ b.room.should == room
35
+ b.roads.should be_include(road1)
36
+ b.roads.should be_include(road2)
37
+ end
38
+
39
+ it "#create_pure_block will return nil, if has no room and no road" do
40
+ tb = TempBlock.create_whole_block(20, 20)
41
+ tb.should be_an_instance_of(TempBlock)
42
+ tb.create_pure_block.should be_nil
43
+ end
44
+
45
+ end
@@ -0,0 +1,241 @@
1
+ # coding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
3
+
4
+ include RDGC::Map
5
+ include RDGC::Maker
6
+
7
+ describe RDGC::Maker::DivideTempBlock, 'is TempBlock for divide maker' do
8
+
9
+ describe 'block divide' do
10
+
11
+ it "#depth default is 0" do
12
+ dtb =DivideTempBlock.create(0, 10, 0, 10)
13
+ dtb.depth.should == 0
14
+ dtb.depth = 3
15
+ dtb.depth.should == 3
16
+ end
17
+
18
+ it "#min_size default is config value, and #min_divide_size provides twice value" do
19
+ dtb =DivideTempBlock.create(0, 10, 0, 10)
20
+ dtb.min_size.should == Util::Config.min_block_size
21
+ dtb.min_divide_size.should == Util::Config.min_block_size * 2
22
+
23
+ dtb.min_size = 1
24
+ dtb.min_size.should == Util::Config.min_block_size
25
+ dtb.min_divide_size.should == Util::Config.min_block_size * 2
26
+
27
+ val = Util::Config.min_block_size + 2
28
+ dtb.min_size = val
29
+ dtb.min_size.should == val
30
+ dtb.min_divide_size.should == val * 2
31
+ end
32
+
33
+ it "#opposite_direction provides opposite of divide_direction" do
34
+ dtb =DivideTempBlock.create_whole_block(20, 20)
35
+ dtb.opposite_direction.should be_nil
36
+ dtb.divide_direction = :vertical
37
+ dtb.opposite_direction.should == :horizontal
38
+ dtb.divide_direction = :horizontal
39
+ dtb.opposite_direction.should == :vertical
40
+ end
41
+
42
+ it "#dividable_size? check self can devidable for divide_direction" do
43
+ dtb_h = DivideTempBlock.create_whole_block(5, 30)
44
+ dtb_h.dividable_size?.should be_false
45
+ dtb_h.divide_direction = :vertical
46
+ dtb_h.dividable_size?.should be_false
47
+ dtb_h.divide_direction = :horizontal
48
+ dtb_h.dividable_size?.should be_true
49
+
50
+ dtb_w = DivideTempBlock.create_whole_block(30, 5)
51
+ dtb_w.dividable_size?.should be_false
52
+ dtb_w.divide_direction = :vertical
53
+ dtb_w.dividable_size?.should be_true
54
+ dtb_w.divide_direction = :horizontal
55
+ dtb_w.dividable_size?.should be_false
56
+ end
57
+
58
+ it "#set_dividable will set dividable, but reject if enough size" do
59
+ dtb =DivideTempBlock.create_whole_block(20, 20)
60
+ dtb.divide_direction = :vertical
61
+ dtb.dividable_size?.should be_true
62
+
63
+ dtb.dividable?.should be_false
64
+ dtb.set_dividable
65
+ dtb.dividable?.should be_true
66
+
67
+ dtb.dividable(false)
68
+ dtb.min_size = 99
69
+ dtb.dividable_size?.should be_false
70
+
71
+ dtb.dividable?.should be_false
72
+ dtb.set_dividable
73
+ dtb.dividable?.should be_false
74
+
75
+ dtb.dividable
76
+ dtb.dividable?.should be_true
77
+ end
78
+
79
+ it "#divide_point provides random value for divide" do
80
+ dtb =DivideTempBlock.create_whole_block(30, 40)
81
+ dtb.min_size = 5
82
+
83
+ 10.times do
84
+ wval = dtb.divide_point(dtb.width)
85
+ wval.should >= dtb.min_size
86
+ wval.should <= (dtb.width - dtb.min_divide_size)
87
+
88
+ wval = dtb.divide_point(dtb.height)
89
+ wval.should >= dtb.min_size
90
+ wval.should <= (dtb.height - dtb.min_divide_size)
91
+ end
92
+ end
93
+
94
+ it "#divide provides new twice blocks, seted opposite direction" do
95
+ 10.times do
96
+ dtb =DivideTempBlock.create_whole_block(40, 40)
97
+ dtb.divide_direction = :vertical
98
+
99
+ ret = dtb.divide
100
+ ret.should_not be_empty
101
+ ret.size.should <= 2
102
+
103
+ ret.each do |b|
104
+ b.width.should < dtb.width
105
+ b.height == dtb.height
106
+ b.divide_direction.should == :horizontal
107
+ end
108
+
109
+ dtb =DivideTempBlock.create_whole_block(40, 40)
110
+ dtb.divide_direction = :horizontal
111
+
112
+ ret = dtb.divide
113
+ ret.should_not be_empty
114
+ ret.size.should <= 2
115
+
116
+ ret.each do |b|
117
+ b.width.should == dtb.width
118
+ b.height < dtb.height
119
+ b.divide_direction.should == :vertical
120
+ end
121
+ end
122
+ end
123
+
124
+ it "#divide will returen nil, if not enough size" do
125
+ dtb =DivideTempBlock.create_whole_block(5, 40)
126
+ dtb.divide_direction = :vertical
127
+ dtb.divide.should be_nil
128
+ end
129
+
130
+ end
131
+
132
+ describe 'for road create' do
133
+
134
+ before(:each) do
135
+ @dtb =DivideTempBlock.create_whole_block(40, 40)
136
+ end
137
+
138
+ it "#road_created is sign for main road created" do
139
+ @dtb.road_created?.should be_false
140
+ @dtb.road_created
141
+ @dtb.road_created?.should be_true
142
+ end
143
+
144
+ it "#road_point is created road's coordinate for each four direction" do
145
+ params = {
146
+ :top => 1,
147
+ :bottom => 2,
148
+ :left => 3,
149
+ :right => 4
150
+ }
151
+
152
+ @dtb.road_point.should be_empty
153
+
154
+ params.each do |d, v|
155
+ @dtb.set_road_point(d, v)
156
+ end
157
+
158
+ params.each do |d, v|
159
+ @dtb.road_point[d].should == v
160
+ end
161
+ end
162
+
163
+ it "#remain_cling_blocks is cling block, not have room, and not connect by road from self" do
164
+ @dtb.remain_cling_blocks.should be_empty
165
+ @dtb.has_remain_cling_blocks?.should be_false
166
+
167
+ b = DivideTempBlock.create_whole_block(10, 10)
168
+ room = Room.create(1, 5, 1, 5)
169
+ b.room = room
170
+
171
+ @dtb.add_remain_cling_blocks(b)
172
+ @dtb.remain_cling_blocks.should be_empty
173
+ @dtb.has_remain_cling_blocks?.should be_false
174
+
175
+ b = DivideTempBlock.create_whole_block(10, 10)
176
+
177
+ @dtb.add_remain_cling_blocks(b)
178
+ @dtb.remain_cling_blocks.size.should == 1
179
+ @dtb.remain_cling_blocks.first.should == b
180
+ @dtb.has_remain_cling_blocks?.should be_true
181
+ end
182
+
183
+ it "#dead_end is only one road block of cross point" do
184
+ @dtb.dead_end?.should be_false
185
+
186
+ @dtb.create_room
187
+ @dtb.dead_end?.should be_false
188
+ @dtb.remove_all
189
+
190
+ @dtb.create_cross_point
191
+ @dtb.dead_end?.should be_false
192
+
193
+ @dtb.set_road_point(:top, 1)
194
+ @dtb.dead_end?.should be_true
195
+
196
+ @dtb.set_road_point(:bottom, 20)
197
+ @dtb.dead_end?.should be_false
198
+ end
199
+
200
+ it "#remain_direction provieds remain direction of not road create" do
201
+ @dtb.remain_direction.size.should == 4
202
+
203
+ @dtb.set_road_point(:top, 1)
204
+ @dtb.remain_direction.size.should == 3
205
+ @dtb.remain_direction.should_not be_include(:top)
206
+
207
+ @dtb.set_road_point(:bottom, 20)
208
+ @dtb.remain_direction.size.should == 2
209
+ @dtb.remain_direction.should_not be_include(:top)
210
+ @dtb.remain_direction.should_not be_include(:bottom)
211
+ end
212
+
213
+ it "create_road to cling block" do
214
+ b1 = DivideTempBlock.create(1, 10, 1, 10)
215
+ b2 = DivideTempBlock.create(11, 20, 1, 10)
216
+ b3 = DivideTempBlock.create(1, 10 , 11, 20)
217
+ b4 = DivideTempBlock.create(11, 20 , 11, 20)
218
+
219
+ b1.create_room
220
+ b2.create_cross_point
221
+ b3.create_cross_point
222
+ b4.create_room
223
+
224
+ b1.create_road_to(b2)
225
+ b1.roads.size.should == 2
226
+ b2.roads.size.should == 1
227
+
228
+ b2.create_road_to(b4)
229
+ b2.roads.size.should == 3
230
+ b4.roads.size.should == 1
231
+
232
+ b4.create_road_to(b3)
233
+ b4.roads.size.should == 2
234
+ b3.roads.size.should == 2
235
+
236
+ b3.dead_end?.should be_true
237
+ end
238
+
239
+ end
240
+
241
+ end