rdgc-dm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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