rmaze 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8de1761ea1c434699b107bfd7ac8f67066ccbb72
4
+ data.tar.gz: 5a00adebfa0161e2bc9da4c708d35080f687e385
5
+ SHA512:
6
+ metadata.gz: ee50ce8778253e1915c1c4591ebb4e2ed6c08a68ef834cfd77116b88d68a18533c7f29ebe57a7f59b2b3b6434d98593d49fa3f6d1bc188723d71f35dfa9786cf
7
+ data.tar.gz: f225f4e02d3955852991b646319cbb9dcee0e713df7f55c544bd293a8325b0366805fa055799396c0fc18a7b87c88ffd217db3189fe0f7296ed1943b18f1f186
@@ -0,0 +1,2 @@
1
+ *.swp
2
+ coverage/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -c -r ./spec/spec_helper.rb -r ./lib/rmaze.rb
@@ -0,0 +1 @@
1
+ maze
@@ -0,0 +1 @@
1
+ ruby-2.1.3
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'OptionParser', '~> 0.5.1'
4
+ gem 'rubytree', '~> 0.9.4'
5
+
6
+ group :test do
7
+ gem 'rspec', '~> 3.1.0'
8
+ gem 'simplecov', :require => false
9
+ end
@@ -0,0 +1,38 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ OptionParser (0.5.1)
5
+ diff-lcs (1.2.5)
6
+ docile (1.1.5)
7
+ json (1.8.1)
8
+ multi_json (1.10.1)
9
+ rspec (3.1.0)
10
+ rspec-core (~> 3.1.0)
11
+ rspec-expectations (~> 3.1.0)
12
+ rspec-mocks (~> 3.1.0)
13
+ rspec-core (3.1.5)
14
+ rspec-support (~> 3.1.0)
15
+ rspec-expectations (3.1.2)
16
+ diff-lcs (>= 1.2.0, < 2.0)
17
+ rspec-support (~> 3.1.0)
18
+ rspec-mocks (3.1.2)
19
+ rspec-support (~> 3.1.0)
20
+ rspec-support (3.1.1)
21
+ rubytree (0.9.4)
22
+ json (~> 1.8)
23
+ structured_warnings (~> 0.1)
24
+ simplecov (0.9.1)
25
+ docile (~> 1.1.0)
26
+ multi_json (~> 1.0)
27
+ simplecov-html (~> 0.8.0)
28
+ simplecov-html (0.8.0)
29
+ structured_warnings (0.1.4)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ OptionParser (~> 0.5.1)
36
+ rspec (~> 3.1.0)
37
+ rubytree (~> 0.9.4)
38
+ simplecov
@@ -0,0 +1,4 @@
1
+ Maze
2
+ ====
3
+
4
+ Ruby library for maze generation
@@ -0,0 +1,76 @@
1
+ require 'maze/maze_cell'
2
+
3
+ class Maze
4
+ protected
5
+ attr_reader :matrix
6
+
7
+ def initialize_matrix
8
+ @matrix = []
9
+ (0...@height_full).each do
10
+ @matrix << [0]*@width_full
11
+ end
12
+ end
13
+
14
+ def make_value(value = 0)
15
+ (0...@height_full).each do |i|
16
+ (0...@width_full).each do |j|
17
+ @matrix[i][j] = value
18
+ end
19
+ end
20
+ end
21
+
22
+ def make_unconnected
23
+ make_value(1)
24
+ (0...@width).each do |x|
25
+ (0...@height).each do |y|
26
+ i, j = xy_to_ij(x, y)
27
+ @matrix[i][j] = 0
28
+ end
29
+ end
30
+ end
31
+
32
+ public
33
+ attr_reader :mirrored, :width, :height, :width_full, :height_full
34
+
35
+ def initialize(width, height)
36
+ @mirrored = false
37
+ @height, @width = height.to_i, width.to_i
38
+ @height_full, @width_full = (1 + 2*@height), (1 + 2*@width)
39
+ initialize_matrix
40
+ @hash = "#{@width}#{@height}".to_i # optimized pre-computed hash
41
+ end
42
+
43
+ def debug
44
+ @matrix.each do |row|
45
+ puts row.join(' ').gsub(/0/, ' ').gsub(/1/, '#').gsub(/2/, 'X')
46
+ end
47
+ self
48
+ end
49
+
50
+ def value(i, j)
51
+ @matrix[i][j]
52
+ end
53
+
54
+ def cell(x, y)
55
+ MazeCell.new(self, x, y)
56
+ end
57
+
58
+ def xy_to_ij(x, y)
59
+ x, y = x % @width, y % @height if @mirrored
60
+ i = 1 + (2 * y)
61
+ j = 1 + (2 * x)
62
+ [i, j]
63
+ end
64
+
65
+ def generate
66
+ self
67
+ end
68
+
69
+ def hash
70
+ @hash
71
+ end
72
+
73
+ def inspect
74
+ "#<#{self.class}: @width=#{@width}, @height=#{@height}>"
75
+ end
76
+ end
@@ -0,0 +1,57 @@
1
+ require 'maze/maze'
2
+
3
+ class MazeBTrace < Maze
4
+ protected
5
+ def initialize_matrix
6
+ super
7
+ make_unconnected
8
+ end
9
+
10
+ public
11
+ def initialize(width, height)
12
+ super(width, height)
13
+ end
14
+
15
+ def between_cells(cell_a, cell_b)
16
+ i_a, j_a = xy_to_ij(cell_a.x, cell_a.y)
17
+ i_b, j_b = xy_to_ij(cell_b.x, cell_b.y)
18
+ [(i_a + i_b).abs / 2, (j_a + j_b).abs / 2]
19
+ end
20
+
21
+ def generate
22
+ super
23
+ stack = []
24
+ visited_cells = []
25
+ all_index_cells = []
26
+ current_cell = cell(rand(@width), rand(@height))
27
+ visited_cells.push current_cell
28
+ (0...@width).each do |x|
29
+ (0...@height).each do |y|
30
+ all_index_cells << [x, y]
31
+ end
32
+ end
33
+ while visited_cells.size != @width * @height
34
+ neighbours = current_cell.neighbours
35
+ visited_cells.push current_cell
36
+ unvisited_neighbours = (neighbours - visited_cells)
37
+ if !unvisited_neighbours.empty?
38
+ stack.push current_cell
39
+ random_neighbour = unvisited_neighbours.shuffle.shift
40
+ i, j = xy_to_ij(random_neighbour.x, random_neighbour.y)
41
+ inner_i, inner_j = between_cells(current_cell, random_neighbour)
42
+ @matrix[inner_i][inner_j] = 0
43
+ current_cell = random_neighbour
44
+ visited_cells.push current_cell
45
+ elsif !stack.empty?
46
+ current_cell = stack.pop
47
+ else
48
+ unvisited_index_cells = all_index_cells - visited_cells.map { |c| [c.x, c.y] }
49
+ unvisited_index_cell = unvisited_index_cells.shuffle.shift
50
+ current_cell = cell(unvisited_index_cell[0], unvisited_index_cell[0])
51
+ visited_cells.push current_cell
52
+ end
53
+ visited_cells.uniq!
54
+ end
55
+ self
56
+ end
57
+ end
@@ -0,0 +1,94 @@
1
+ class MazeCell
2
+ attr_reader :maze, :x, :y
3
+
4
+ def initialize(maze, x, y)
5
+ @maze = maze
6
+ @x, @y = x.to_i, y.to_i
7
+ @x, @y = x % @maze.width, y % @maze.height if @maze.mirrored
8
+ @hash = "#{@maze.hash}#{@x}#{@y}".to_i
9
+ end
10
+
11
+ def debug
12
+ i, j = @maze.xy_to_ij(@x, @y)
13
+ puts " #{@maze.value(i - 1, j)} "
14
+ puts "#{@maze.value(i, j - 1)} #{@maze.value(i, j)} #{@maze.value(i, j + 1)}"
15
+ puts " #{@maze.value(i + 1, j)} "
16
+ end
17
+
18
+ def left
19
+ MazeCell.new(@maze, @x - 1, @y) if @maze.mirrored || @x > 0
20
+ end
21
+
22
+ def up
23
+ MazeCell.new(@maze, @x, @y - 1) if @maze.mirrored || @y > 0
24
+ end
25
+
26
+ def right
27
+ MazeCell.new(@maze, @x + 1, @y) if @maze.mirrored || @x < (@maze.width - 1)
28
+ end
29
+
30
+ def down
31
+ MazeCell.new(@maze, @x, @y + 1) if @maze.mirrored || @y < (@maze.height - 1)
32
+ end
33
+
34
+ def has_wall_left?
35
+ i, j = @maze.xy_to_ij(@x, @y)
36
+ @maze.value(i, j - 1) != 0
37
+ end
38
+
39
+ def has_wall_up?
40
+ i, j = @maze.xy_to_ij(@x, @y)
41
+ @maze.value(i - 1, j) != 0
42
+ end
43
+
44
+ def has_wall_right?
45
+ i, j = @maze.xy_to_ij(@x, @y)
46
+ @maze.value(i, j + 1) != 0
47
+ end
48
+
49
+ def has_wall_down?
50
+ i, j = @maze.xy_to_ij(@x, @y)
51
+ @maze.value(i + 1, j) != 0
52
+ end
53
+
54
+ def connected?
55
+ !(has_wall_left? && has_wall_up? && has_wall_right? && has_wall_down?)
56
+ end
57
+
58
+ def neighbours
59
+ [left, up, right, down].compact
60
+ end
61
+
62
+ def connected_neighbours
63
+ neighbours = []
64
+ neighbours << left unless has_wall_left?
65
+ neighbours << up unless has_wall_up?
66
+ neighbours << right unless has_wall_right?
67
+ neighbours << down unless has_wall_down?
68
+ neighbours
69
+ end
70
+
71
+ def hash
72
+ @hash
73
+ end
74
+
75
+ def eql?(object)
76
+ if (object.class == self.class)
77
+ @x == object.x && @y == object.y && @maze == object.maze
78
+ elsif
79
+ super(object)
80
+ end
81
+ end
82
+
83
+ def ==(object)
84
+ self.eql? object
85
+ end
86
+
87
+ def !=(object)
88
+ !(self.eql? object)
89
+ end
90
+
91
+ def inspect
92
+ "#<#{self.class}: @maze=#{@maze.inspect}, @x=#{@x}, @y=#{@y}>"
93
+ end
94
+ end
@@ -0,0 +1,7 @@
1
+ expand_path = File.expand_path('..', __FILE__)
2
+
3
+ $LOAD_PATH.unshift expand_path
4
+
5
+ Dir.glob(File.join(expand_path, "**/*.rb")) do |file|
6
+ require file
7
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require './lib/rmaze.rb'
4
+ require 'optparse'
5
+
6
+ options = {
7
+ :width => 10,
8
+ :height => 10,
9
+ :algorithm => :backtrace
10
+ }
11
+ OptionParser.new do |opts|
12
+ opts.banner = "Usage: maze_gen.rb [options]"
13
+
14
+ opts.separator ""
15
+ opts.separator "Basic options:"
16
+ opts.on("-w", "--width width", "Specify the maze width (default: #{options[:width]})") do |width|
17
+ options[:width] = width
18
+ end
19
+ opts.on("-h", "--height height", "Specify the maze height (default: #{options[:height]})") do |height|
20
+ options[:height] = height
21
+ end
22
+
23
+ opts.separator ""
24
+ opts.separator "Algorithms:"
25
+ opts.on("-b", "--backtrace", "Choose backtrace algorithm (default)") do |bt|
26
+ options[:algorithm] = bt ? :backtrace : nil
27
+ end
28
+ end.parse!
29
+
30
+ maze = nil
31
+ case options[:algorithm]
32
+ when :backtrace
33
+ maze = MazeBTrace.new(options[:width], options[:height])
34
+ else
35
+ $stderr.puts "Error: the algorithm must be set."
36
+ exit(-1)
37
+ end
38
+
39
+ maze.generate
40
+ maze.debug
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'rmaze'
3
+ s.version = '1.0.0'
4
+ s.date = '2014-10-01'
5
+ s.licenses = ["MIT"]
6
+ s.platform = Gem::Platform::RUBY
7
+ s.summary = "RMaze"
8
+ s.description = "Ruby library for maze generation"
9
+ s.authors = ["Pedro Lira"]
10
+ s.email = 'pedrohml@gmail.com'
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files -- spec/*`.split("\n")
13
+ s.homepage = 'https://github.com/pedrohml/rmaze'
14
+ s.require_paths = ["lib"]
15
+ end
@@ -0,0 +1,11 @@
1
+ describe MazeBTrace do
2
+ before do
3
+ @width = rand(10) + 15
4
+ @height = rand(10) + 15
5
+ @maze = MazeBTrace.new(@width, @height)
6
+ end
7
+
8
+ it '#generate' do
9
+ expect { @maze.generate }.not_to raise_error
10
+ end
11
+ end
@@ -0,0 +1,95 @@
1
+ describe MazeCell do
2
+ before do
3
+ @width = 4
4
+ @height = 4
5
+ @maze = MazeBTrace.new(@width, @height)
6
+ @maze_zero = Maze.new(@width, @height)
7
+ end
8
+
9
+ it '#initialize' do
10
+ maze_cell = MazeCell.new(@maze, 1, 0)
11
+ expect(maze_cell.maze).to eq(@maze)
12
+ expect(maze_cell.x).to eq(1)
13
+ expect(maze_cell.y).to eq(0)
14
+ end
15
+
16
+ it 'gets directions' do
17
+ maze_cell = @maze.cell(0, 0)
18
+ expect(maze_cell.left).to be_nil
19
+ expect(maze_cell.up).to be_nil
20
+ expect(maze_cell.right).to eq(@maze.cell(1, 0))
21
+ expect(maze_cell.down).to eq(@maze.cell(0, 1))
22
+ end
23
+
24
+ it 'checks wall' do
25
+ maze_cell = @maze.cell(0, 0)
26
+ expect(maze_cell).to have_wall_left
27
+ expect(maze_cell).to have_wall_up
28
+ expect(maze_cell).to have_wall_right
29
+ expect(maze_cell).to have_wall_down
30
+ maze_zero_cell = @maze_zero.cell(1, 1)
31
+ expect(maze_zero_cell).not_to have_wall_left
32
+ expect(maze_zero_cell).not_to have_wall_up
33
+ expect(maze_zero_cell).not_to have_wall_right
34
+ expect(maze_zero_cell).not_to have_wall_down
35
+ end
36
+
37
+ it '#connected?' do
38
+ expect(@maze.cell(0, 0)).not_to be_connected
39
+ expect(@maze_zero.cell(1, 0)).to be_connected
40
+ end
41
+
42
+ it '#connected_neighbours' do
43
+ expect(@maze.cell(0, 0).connected_neighbours).to be_empty
44
+ expect(@maze_zero.cell(1, 1).connected_neighbours.size).to eq(4)
45
+ end
46
+
47
+ it '#neighbours' do
48
+ maze_cell = @maze.cell(0, 0)
49
+ neighbours = maze_cell.neighbours
50
+ expect(neighbours.size).to eq(2)
51
+ expect(neighbours).to include(@maze.cell(1, 0))
52
+ expect(neighbours).to include(@maze.cell(0, 1))
53
+ expect(neighbours).not_to include(@maze.cell(0, 0))
54
+ end
55
+
56
+ it '#hash' do
57
+ allow_any_instance_of(MazeCell).to receive(:eql?).and_return(true) # remove elements only based on hash
58
+ cells = [@maze.cell(0, 0), @maze.cell(1, 0), @maze.cell(0, 1)]
59
+ cells -= [@maze.cell(0, 0)]
60
+ expect(cells).to contain_exactly(@maze.cell(1, 0), @maze.cell(0, 1))
61
+ end
62
+
63
+ it '#eql?' do
64
+ maze_cell = @maze.cell(0, 0)
65
+ expect(maze_cell).to eql(maze_cell)
66
+ expect(maze_cell).to eql(@maze.cell(0, 0))
67
+ expect(maze_cell).not_to eql(@maze.cell(1, 0))
68
+ expect(maze_cell).not_to eql(nil)
69
+ end
70
+
71
+ it '#==' do
72
+ maze_cell = @maze.cell(0, 0)
73
+ expect(maze_cell).to eq(maze_cell)
74
+ expect(maze_cell).to eq(@maze.cell(0, 0))
75
+ expect(maze_cell).not_to eq(@maze.cell(1, 0))
76
+ expect(maze_cell).not_to eq(nil)
77
+ end
78
+
79
+ it '#!=' do
80
+ maze_cell = @maze.cell(0, 0)
81
+ expect(maze_cell != @maze.cell(1, 0)).to be_truthy
82
+ expect(maze_cell != nil).to be_truthy
83
+ end
84
+
85
+ it '#debug' do
86
+ allow($stdout).to receive(:puts).exactly(3).times
87
+ maze_cell = @maze.cell(0, 0)
88
+ maze_cell.debug
89
+ end
90
+
91
+ it '#inspect' do
92
+ maze_cell = @maze.cell(1, 0)
93
+ expect(maze_cell.inspect).to eq("#<MazeCell: @maze=#{@maze.inspect}, @x=#{1}, @y=#{0}>")
94
+ end
95
+ end
@@ -0,0 +1,47 @@
1
+ describe Maze do
2
+ before do
3
+ @width = rand(10) + 15
4
+ @height = rand(10) + 15
5
+ @maze = Maze.new(@width, @height)
6
+ end
7
+
8
+ it '#initialize' do
9
+ expect(@maze.width).to eq(@width)
10
+ expect(@maze.height).to eq(@height)
11
+ end
12
+
13
+ it '#value' do
14
+ expect(@maze.value(0, 0)).to eq(0)
15
+ end
16
+
17
+ it '#cell' do
18
+ cell = @maze.cell(3, 8)
19
+ expect(cell).to be_a_kind_of(MazeCell)
20
+ expect(cell.maze).to eq(@maze)
21
+ expect(cell.x).to eq(3)
22
+ expect(cell.y).to eq(8)
23
+ end
24
+
25
+ it '#xy_to_ij' do
26
+ x, y = 0, 0
27
+ i, j = @maze.xy_to_ij(x, y)
28
+ expect([i, j]).to eq([1, 1])
29
+ end
30
+
31
+ it '#generate' do
32
+ expect(@maze.generate).to eq(@maze)
33
+ end
34
+
35
+ it '#hash' do
36
+ expect(@maze.hash).to eq("#{@width}#{@height}".to_i)
37
+ end
38
+
39
+ it '#inspect' do
40
+ expect(@maze.inspect).to eq("#<Maze: @width=#{@width}, @height=#{@height}>")
41
+ end
42
+
43
+ it '#debug' do
44
+ allow($stdout).to receive(:puts).exactly(@maze.height_full).times
45
+ @maze.debug
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmaze
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Pedro Lira
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby library for maze generation
14
+ email: pedrohml@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - ".gitignore"
20
+ - ".rspec"
21
+ - ".ruby-gemset"
22
+ - ".ruby-version"
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - README.md
26
+ - lib/maze/maze.rb
27
+ - lib/maze/maze_btrace.rb
28
+ - lib/maze/maze_cell.rb
29
+ - lib/rmaze.rb
30
+ - maze_gen.rb
31
+ - rmaze.gemspec
32
+ - spec/maze/maze_btrace_spec.rb
33
+ - spec/maze/maze_cell_spec.rb
34
+ - spec/maze/maze_spec.rb
35
+ - spec/spec_helper.rb
36
+ homepage: https://github.com/pedrohml/rmaze
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 2.2.2
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: RMaze
60
+ test_files:
61
+ - spec/maze/maze_btrace_spec.rb
62
+ - spec/maze/maze_cell_spec.rb
63
+ - spec/maze/maze_spec.rb
64
+ - spec/spec_helper.rb