automaze 0.0.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.
- data/LICENSE +24 -0
- data/README.rdoc +27 -0
- data/Rakefile +30 -0
- data/VERSION +1 -0
- data/lib/algorithms/boutaoshi.rb +31 -0
- data/lib/algorithms/dug_tunnels.rb +95 -0
- data/lib/automaze.rb +112 -0
- data/lib/panel.rb +27 -0
- data/sample.rb +24 -0
- data/spec/automaze_spec.rb +46 -0
- data/spec/panel_spec.rb +39 -0
- metadata +76 -0
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
automazerb
|
2
|
+
|
3
|
+
The MIT License
|
4
|
+
|
5
|
+
Copyright (c) 2010 Toshiyuki Hirooka <toshi.hirooka@gmail.com>
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
9
|
+
in the Software without restriction, including without limitation the rights
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be included in
|
15
|
+
all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
THE SOFTWARE.
|
24
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
= automazerb
|
3
|
+
|
4
|
+
== description
|
5
|
+
automazerb is maze generator library for ruby.
|
6
|
+
|
7
|
+
== usage
|
8
|
+
|
9
|
+
require "automaze"
|
10
|
+
maze = Automaze::Automaze.new
|
11
|
+
puts maze
|
12
|
+
|
13
|
+
panel = maze.panels(3,4)
|
14
|
+
panel.wall? #=> true or false
|
15
|
+
|
16
|
+
maze.each_panels do |panel,x,y|
|
17
|
+
if panel.wall?
|
18
|
+
print "XX"
|
19
|
+
else
|
20
|
+
print " "
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
specifying generation algorithm
|
25
|
+
|
26
|
+
Automaze::Automaze.new(:algorithm=>:boutaoshi)
|
27
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
|
6
|
+
task :default => [:spec]
|
7
|
+
|
8
|
+
desc "spec all"
|
9
|
+
RSpec::Core::RakeTask.new do |t|
|
10
|
+
t.name = "spec"
|
11
|
+
t.pattern = "spec/*_spec.rb"
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "run sample"
|
15
|
+
task :run do
|
16
|
+
sh "ruby sample.rb"
|
17
|
+
end
|
18
|
+
|
19
|
+
begin
|
20
|
+
require 'jeweler'
|
21
|
+
Jeweler::Tasks.new do |gemspec|
|
22
|
+
gemspec.name = "automaze"
|
23
|
+
gemspec.summary = "maze generator"
|
24
|
+
gemspec.email = "toshi.hirooka@gmail.com"
|
25
|
+
gemspec.homepage = "http://github.com/tosik/automazerb"
|
26
|
+
gemspec.description = "maze generator"
|
27
|
+
gemspec.authors = ["Toshiyuki Hirooka"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Boutaoshi
|
4
|
+
def generate
|
5
|
+
init_panels
|
6
|
+
|
7
|
+
each_panels do |panel, x, y|
|
8
|
+
if post?(x,y) && y == 2
|
9
|
+
random_floor(four_panels(x,y)).set_kind(:wall)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
each_panels do |panel, x, y|
|
14
|
+
if post?(x,y) && y != 2
|
15
|
+
random_floor(three_panels(x,y)).set_kind(:wall)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def init_panels
|
21
|
+
each_panels do |panel, x, y|
|
22
|
+
panel.set_kind(:floor)
|
23
|
+
panel.set_kind(:wall) if post?(x,y)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def post?(x,y)
|
28
|
+
( x % 2 ) == 1 && ( y % 2 ) == 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module DugTunnels
|
4
|
+
def init_panels
|
5
|
+
each_panels do |panel, x, y|
|
6
|
+
panel.set_kind(:wall)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate
|
11
|
+
init_panels
|
12
|
+
|
13
|
+
# start point
|
14
|
+
xy = random_even_xy
|
15
|
+
panels(*xy).set_kind(:floor)
|
16
|
+
|
17
|
+
while !dug_all?
|
18
|
+
|
19
|
+
# select random floor
|
20
|
+
begin
|
21
|
+
xy = random_even_xy
|
22
|
+
end while panels(*xy).wall?
|
23
|
+
|
24
|
+
while can_dig(*xy)
|
25
|
+
dir = random_direction
|
26
|
+
next_xy = next_xy(*xy, dir)
|
27
|
+
next_panel = panels(*next_xy)
|
28
|
+
if next_panel.wall? && !out_of_map?(*next_xy)
|
29
|
+
dig(*xy, dir)
|
30
|
+
xy = next_xy
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def random_direction
|
37
|
+
return rand(4)
|
38
|
+
@dir ||= 0
|
39
|
+
@dir += 1
|
40
|
+
@dir = 0 if @dir == 4
|
41
|
+
@dir
|
42
|
+
end
|
43
|
+
|
44
|
+
def next_xy(x, y, dir)
|
45
|
+
[
|
46
|
+
[x-2,y],
|
47
|
+
[x+2,y],
|
48
|
+
[x,y-2],
|
49
|
+
[x,y+2],
|
50
|
+
].at(dir)
|
51
|
+
end
|
52
|
+
|
53
|
+
def next_panel(x, y, dir)
|
54
|
+
panels(*next_xy(x, y, dir))
|
55
|
+
end
|
56
|
+
|
57
|
+
def random_even_xy
|
58
|
+
[rand(@size_x/2 + 1) * 2, rand(@size_y/2 + 1) * 2]
|
59
|
+
end
|
60
|
+
|
61
|
+
def can_dig(x, y)
|
62
|
+
(0..3).each do |dir|
|
63
|
+
unless out_of_map?(*next_xy(x, y, dir))
|
64
|
+
return true if next_panel(x, y, dir).wall?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
|
70
|
+
def dug_all?
|
71
|
+
each_panels do |panel, x, y|
|
72
|
+
if ( x % 2 ) == 0 && ( y % 2 ) == 0
|
73
|
+
return false if panel.wall?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
|
80
|
+
def dig(x, y, dir)
|
81
|
+
xy = next_xy(x, y, dir)
|
82
|
+
panels(*xy).set_kind(:floor)
|
83
|
+
|
84
|
+
diff = [xy[0] - x, xy[1] - y]
|
85
|
+
if diff[0] == 0
|
86
|
+
panels(x, xy[1] - 1).set_kind(:floor) if diff[1] > 0
|
87
|
+
panels(x, xy[1] + 1).set_kind(:floor) if diff[1] < 0
|
88
|
+
end
|
89
|
+
if diff[1] == 0
|
90
|
+
panels(xy[0] - 1, y).set_kind(:floor) if diff[0] > 0
|
91
|
+
panels(xy[0] + 1, y).set_kind(:floor) if diff[0] < 0
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
data/lib/automaze.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# The MIT License
|
4
|
+
#
|
5
|
+
# Copyright (c) 2010 Toshiyuki Hirooka <toshi.hirooka@gmail.com>
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
25
|
+
require "active_support/inflector"
|
26
|
+
require_relative "panel"
|
27
|
+
|
28
|
+
module Automaze
|
29
|
+
class Automaze
|
30
|
+
DEFAULT_ALGORITHM = :boutaoshi
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def include_algorithm(algorithm)
|
34
|
+
raise "cannot include because algorithm is nil" if algorithm.nil?
|
35
|
+
require_relative "algorithms/#{algorithm.to_s}"
|
36
|
+
include algorithm.to_s.camelize.constantize
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(options={})
|
41
|
+
@panels = {}
|
42
|
+
|
43
|
+
@size_x = options.delete(:size_x) || 30
|
44
|
+
@size_y = options.delete(:size_y) || 20
|
45
|
+
self.class.include_algorithm options.delete(:algorithm) || DEFAULT_ALGORITHM
|
46
|
+
self.generate # included algorithm
|
47
|
+
end
|
48
|
+
attr_reader :size_x
|
49
|
+
attr_reader :size_y
|
50
|
+
|
51
|
+
# nil panel is wall
|
52
|
+
def panels(x,y)
|
53
|
+
@panels[[x,y]] ||= Panel.new(:wall)
|
54
|
+
end
|
55
|
+
|
56
|
+
def each_panels
|
57
|
+
(0..@size_y).each do |y|
|
58
|
+
(0..@size_x).each do |x|
|
59
|
+
yield(panels(x,y), x, y)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def four_panels(x,y)
|
65
|
+
[
|
66
|
+
panels(x-1,y),
|
67
|
+
panels(x+1,y),
|
68
|
+
panels(x,y-1),
|
69
|
+
panels(x,y+1),
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
def three_panels(x,y)
|
74
|
+
[
|
75
|
+
panels(x-1,y),
|
76
|
+
panels(x+1,y),
|
77
|
+
panels(x,y+1),
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
81
|
+
def random_floor(panels)
|
82
|
+
loop do
|
83
|
+
panel = panels[rand(panels.length)]
|
84
|
+
return panel if panel.floor?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def out_of_map?(x, y)
|
89
|
+
return true if x < 0
|
90
|
+
return true if x > @size_x
|
91
|
+
return true if y < 0
|
92
|
+
return true if y > @size_y
|
93
|
+
return false
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
str = ""
|
98
|
+
(-1..@size_y+1).each {|y|
|
99
|
+
(-1..@size_x+1).each {|x|
|
100
|
+
if panels(x,y).wall?
|
101
|
+
str += "XX"
|
102
|
+
else
|
103
|
+
str += " "
|
104
|
+
end
|
105
|
+
}
|
106
|
+
str += "\n"
|
107
|
+
}
|
108
|
+
return str
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
data/lib/panel.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Automaze
|
4
|
+
class Panel
|
5
|
+
def initialize(kind)
|
6
|
+
set_kind(kind)
|
7
|
+
end
|
8
|
+
|
9
|
+
PANEL_KINDS = [:floor, :wall]
|
10
|
+
|
11
|
+
def kind_valid?(kind)
|
12
|
+
PANEL_KINDS.include? kind
|
13
|
+
end
|
14
|
+
|
15
|
+
PANEL_KINDS.each do |kind|
|
16
|
+
define_method("#{kind}?") do
|
17
|
+
@kind == kind
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_kind(kind)
|
22
|
+
raise "unknown kind" unless kind_valid?(kind)
|
23
|
+
@kind = kind
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/sample.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$: << "lib"
|
2
|
+
require "automaze"
|
3
|
+
|
4
|
+
algorithm = ARGV[0] || :dug_tunnels
|
5
|
+
maze = Automaze::Automaze.new(
|
6
|
+
:algorithm=>algorithm,
|
7
|
+
:size_x=>40,
|
8
|
+
:size_y=>30)
|
9
|
+
|
10
|
+
# building rooms
|
11
|
+
5.times do
|
12
|
+
room_size_x = rand(2) * 2 + 1
|
13
|
+
room_size_y = rand(2) * 2 + 1
|
14
|
+
center_x = rand(maze.size_x/2-room_size_x)*2 + room_size_x
|
15
|
+
center_y = rand(maze.size_y/2-room_size_y)*2 + room_size_y
|
16
|
+
(-room_size_x..room_size_x).each do |x|
|
17
|
+
(-room_size_y..room_size_y).each do |y|
|
18
|
+
maze.panels(x+center_x,y+center_y).set_kind(:floor)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
puts maze
|
24
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative "../lib/automaze"
|
4
|
+
|
5
|
+
describe Automaze::Automaze do
|
6
|
+
describe "self.include_algorithm" do
|
7
|
+
it "includes algorithm module" do
|
8
|
+
lambda { Automaze::Automaze.include_algorithm(:boutaoshi) }.should_not raise_error
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "new" do
|
13
|
+
it "returns Automaze class" do
|
14
|
+
Automaze::Automaze.new.class.should == Automaze::Automaze
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "using options" do
|
18
|
+
describe ":algorithm" do
|
19
|
+
it "accepts :boutaoshi" do
|
20
|
+
lambda { Automaze::Automaze.new(:algorithm=>:boutaoshi) }.should_not raise_error
|
21
|
+
end
|
22
|
+
it "doesnt accept :invalid_algorithm" do
|
23
|
+
lambda { Automaze::Automaze.new(:algorithm=>:invalid_algorithm) }.should raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "instance" do
|
30
|
+
before :each do
|
31
|
+
@maze = Automaze::Automaze.new
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "panels" do
|
35
|
+
it "returns wall panel when panel is nil" do
|
36
|
+
@maze.panels(-123, -456).wall?.should be_true
|
37
|
+
end
|
38
|
+
it "returns wall panel when panel is floor" do
|
39
|
+
@maze.panels(-123, -456).set_kind(:floor)
|
40
|
+
@maze.panels(-123, -456).floor?.should be_true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
data/spec/panel_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative "../lib/panel"
|
4
|
+
|
5
|
+
describe Automaze::Panel do
|
6
|
+
describe "check kind of panel; exp) wall?, floor?" do
|
7
|
+
it "returns true when correct kind" do
|
8
|
+
Automaze::Panel.new(:wall).wall?.should be_true
|
9
|
+
Automaze::Panel.new(:floor).floor?.should be_true
|
10
|
+
end
|
11
|
+
it "returns true when incorrect kind" do
|
12
|
+
Automaze::Panel.new(:floor).wall?.should be_false
|
13
|
+
Automaze::Panel.new(:wall).floor?.should be_false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "new by invalid kind" do
|
18
|
+
it "raises error" do
|
19
|
+
lambda { Automaze::Panel.new(:this_is_invalid_kind) }.should raise_error
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "instance" do
|
24
|
+
before :each do
|
25
|
+
@wall = Automaze::Panel.new(:wall)
|
26
|
+
@floor = Automaze::Panel.new(:floor)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "set_kind" do
|
30
|
+
it "can set kind" do
|
31
|
+
@wall.set_kind(:floor)
|
32
|
+
@wall.floor?.should be_true
|
33
|
+
@floor.set_kind(:wall)
|
34
|
+
@floor.wall?.should be_true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: automaze
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 0.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Toshiyuki Hirooka
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-31 00:00:00 +09:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: maze generator
|
22
|
+
email: toshi.hirooka@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- LICENSE
|
32
|
+
- README.rdoc
|
33
|
+
- Rakefile
|
34
|
+
- VERSION
|
35
|
+
- lib/algorithms/boutaoshi.rb
|
36
|
+
- lib/algorithms/dug_tunnels.rb
|
37
|
+
- lib/automaze.rb
|
38
|
+
- lib/panel.rb
|
39
|
+
- sample.rb
|
40
|
+
- spec/automaze_spec.rb
|
41
|
+
- spec/panel_spec.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://github.com/tosik/automazerb
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.3.7
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: maze generator
|
74
|
+
test_files:
|
75
|
+
- spec/automaze_spec.rb
|
76
|
+
- spec/panel_spec.rb
|