rmaze 1.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.
@@ -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