amaze 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +110 -0
  8. data/Rakefile +6 -0
  9. data/amaze.gemspec +30 -0
  10. data/bin/console +15 -0
  11. data/bin/setup +8 -0
  12. data/exe/amaze +5 -0
  13. data/lib/amaze.rb +17 -0
  14. data/lib/amaze/algorithm.rb +44 -0
  15. data/lib/amaze/algorithm/aldous_border.rb +36 -0
  16. data/lib/amaze/algorithm/binary_tree.rb +20 -0
  17. data/lib/amaze/algorithm/growing_tree.rb +52 -0
  18. data/lib/amaze/algorithm/hunt_and_kill.rb +53 -0
  19. data/lib/amaze/algorithm/recursive_backtracker.rb +77 -0
  20. data/lib/amaze/algorithm/sidewinder.rb +42 -0
  21. data/lib/amaze/algorithm/wilson.rb +54 -0
  22. data/lib/amaze/cell.rb +63 -0
  23. data/lib/amaze/cell/hex.rb +10 -0
  24. data/lib/amaze/cell/octo.rb +10 -0
  25. data/lib/amaze/cell/polar.rb +16 -0
  26. data/lib/amaze/cell/square.rb +10 -0
  27. data/lib/amaze/distances.rb +53 -0
  28. data/lib/amaze/factory.rb +153 -0
  29. data/lib/amaze/formatter.rb +5 -0
  30. data/lib/amaze/formatter/ascii.rb +91 -0
  31. data/lib/amaze/formatter/ascii/delta.rb +180 -0
  32. data/lib/amaze/formatter/ascii/ortho.rb +105 -0
  33. data/lib/amaze/formatter/ascii/polar.rb +199 -0
  34. data/lib/amaze/formatter/ascii/sigma.rb +213 -0
  35. data/lib/amaze/formatter/ascii/upsilon.rb +281 -0
  36. data/lib/amaze/formatter/image.rb +127 -0
  37. data/lib/amaze/formatter/image/delta.rb +123 -0
  38. data/lib/amaze/formatter/image/ortho.rb +103 -0
  39. data/lib/amaze/formatter/image/polar.rb +173 -0
  40. data/lib/amaze/formatter/image/sigma.rb +122 -0
  41. data/lib/amaze/formatter/image/upsilon.rb +135 -0
  42. data/lib/amaze/grid.rb +66 -0
  43. data/lib/amaze/grid/delta.rb +87 -0
  44. data/lib/amaze/grid/ortho.rb +38 -0
  45. data/lib/amaze/grid/polar.rb +61 -0
  46. data/lib/amaze/grid/sigma.rb +61 -0
  47. data/lib/amaze/grid/upsilon.rb +74 -0
  48. data/lib/amaze/mask.rb +75 -0
  49. data/lib/amaze/masked_grid.rb +29 -0
  50. data/lib/amaze/script.rb +361 -0
  51. data/lib/amaze/shape.rb +23 -0
  52. data/lib/amaze/shape/diamond.rb +26 -0
  53. data/lib/amaze/shape/hexagon.rb +79 -0
  54. data/lib/amaze/shape/star.rb +114 -0
  55. data/lib/amaze/shape/triangle.rb +25 -0
  56. data/lib/amaze/version.rb +3 -0
  57. data/support/characters.txt +17 -0
  58. data/support/mask/mask1.txt +10 -0
  59. data/support/mask/mask2.txt +12 -0
  60. data/support/mask/mask3.txt +15 -0
  61. metadata +203 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 63c062699220d0b8d22106bb8af774b4774388cc
4
+ data.tar.gz: efcb6b4be887d1e3e5e594d01a32be10f5cbf419
5
+ SHA512:
6
+ metadata.gz: 29d670232418e604d986e226ea304be3a97c4afc4139362048ccd9ab61e9fd8cf7a908d4ed5a7aa8e8887bd3a870e2e8fc3ca1d032f98eb805d35f2d164265eb
7
+ data.tar.gz: 6a221add8de5625e38ee5001ae59dec618367903db8a0a68be30bd733b1a00bdf6e51ade1cc22ea00ef79be62c75681fcbd12df64f37e45ab893b751bae70a38
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in amaze.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Patrick Marchi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,110 @@
1
+ # Amaze
2
+
3
+ Amaze is both a ruby library and a command line tool to generate mazes.
4
+
5
+ I love mazes. The beauty of mazes have always fascinated me. Amaze is a personal project to create mazes with different tesselations, shapes and sizes. The wonderful book of Jamis Buck, [Mazes for Programmers: Code Your Own Twisty Little Passages](https://pragprog.com/book/jbmaze/mazes-for-programmers) was a great source of inspiration. To adapt the ideas, the code and add my own little twists was a lot of fun.
6
+
7
+ Visit [Think Labyrinth: Maze Algorithms](http://www.astrolog.org/labyrnth/algrithm.htm) if you want to explore more on mazes, their classification, creation and solving algorithms.
8
+
9
+
10
+ ## Installation
11
+
12
+ Amaze depends on [RMagick](https://github.com/rmagick/rmagick) to generate png images. RMagick is an interface between the Ruby programming language and the [ImageMagick](http://www.imagemagick.org) image processing library. You have to install imagemagick first before installing amaze.
13
+
14
+ On **OS X** install imagemagick with brew
15
+
16
+ $ brew install imagemagick
17
+
18
+ Then run
19
+
20
+ $ gem install amaze
21
+
22
+
23
+ ## Usage
24
+
25
+ Execute `amaze --help` for a short description of all supported options.
26
+
27
+ Generate a simple ASCII maze
28
+
29
+ $ amaze
30
+
31
+ +---+---+---+---+
32
+ | |
33
+ + +---+ +---+
34
+ | | |
35
+ + +---+---+ +
36
+ | | |
37
+ + + +---+ +
38
+ | | | |
39
+ +---+---+---+---+
40
+ Growing tree (last from list) algorithm: 0.00012327899457886815s
41
+ Dead ends: 5 of 16 (31%)
42
+ Random seed: 130944739226911434163498228124148718585
43
+
44
+ Make it a little bigger
45
+
46
+ $ amaze -g 12
47
+
48
+ How about a sigma grid
49
+
50
+ $ amaze --type sigma
51
+
52
+ ___ ___
53
+ / \___/ \___
54
+ \ ___ \
55
+ / \___/ ___/
56
+ \ / ___/ \
57
+ / \ / \ /
58
+ \ / \ \
59
+ / \___/ \ /
60
+ \___ ___/ \
61
+ \___/ \___/
62
+ Growing tree (last from list) algorithm: 0.00015847600298002362s
63
+ Dead ends: 3 of 16 (18%)
64
+ Random seed: 210159208462445383832077802753403683598
65
+
66
+ Want to visualize the longest path through the maze (it will be nicely colored in your terminal)
67
+
68
+ $ exe/amaze --longest
69
+
70
+ +---+---+---+---+
71
+ | ∙ | ∙-------∙ |
72
+ + | + | +---+ | +
73
+ | | | ∙---∙ | ∙ |
74
+ + | +---+ | +---+
75
+ | ∙---∙ | ∙---∙ |
76
+ +---+ | +---+ | +
77
+ | ∙-------∙ |
78
+ +---+---+---+---+
79
+ Growing tree (last from list) algorithm: 0.00013193400809541345s
80
+ Dead ends: 3 of 16 (18%)
81
+ Path length: 14
82
+ Random seed: 21088416182148741326253564379123099432
83
+
84
+ How about watching the algorithm doing its work?
85
+
86
+ $ amaze --visualize
87
+
88
+ You can choose between different algorithm (try Hunt and Kill next)
89
+
90
+ $ amaze --visualize --algorithm hk
91
+
92
+ Finally you can render your maze as PNG
93
+
94
+ $ amaze --format=image
95
+ Growing tree (last from list) algorithm: 0.00013603299157693982s
96
+ Dead ends: 3 of 16 (18%)
97
+ Random seed: 72618483828743227022428199116847991100
98
+ Maze 'maze.png' saved.
99
+
100
+ Amaze has a lot more options to play with. Have fun and create beautiful piece of [algorithmic art](https://en.wikipedia.org/wiki/Algorithmic_art).
101
+
102
+
103
+ ## Contributing
104
+
105
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pmarchi/amaze.
106
+
107
+
108
+ ## License
109
+
110
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ # require "rspec/core/rake_task"
3
+ #
4
+ # RSpec::Core::RakeTask.new(:spec)
5
+ #
6
+ # task :default => :spec
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'amaze/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "amaze"
8
+ spec.version = Amaze::VERSION
9
+ spec.authors = ["Patrick Marchi"]
10
+ spec.email = ["mail@patrickmarchi.ch"]
11
+
12
+ spec.summary = %q{Maze generator}
13
+ spec.description = %q{A maze generator inspired by the book of Jamis Buck, Mazes for Programmers: Code Your Own Twisty Little Passages.}
14
+ spec.homepage = "https://github.com/pmarchi/amaze"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec", "~> 3.0"
25
+
26
+ spec.add_dependency "chunky_png"
27
+ spec.add_dependency "rainbow"
28
+ spec.add_dependency "gradient"
29
+ spec.add_dependency "rmagick"
30
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #require "bundler/setup"
4
+ require "amaze"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'awesome_print'
14
+ require "irb"
15
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'amaze'
4
+
5
+ Amaze::Script.new.run ARGV
@@ -0,0 +1,17 @@
1
+ require "amaze/version"
2
+
3
+ module Amaze
4
+ autoload :Script, 'amaze/script'
5
+ autoload :Factory, 'amaze/factory'
6
+ autoload :Cell, 'amaze/cell'
7
+ autoload :Grid, 'amaze/grid'
8
+ autoload :SigmaCell, 'amaze/sigma_cell'
9
+ autoload :SigmaGrid, 'amaze/sigma_grid'
10
+ autoload :DeltaGrid, 'amaze/delta_grid'
11
+ autoload :Algorithm, 'amaze/algorithm'
12
+ autoload :Formatter, 'amaze/formatter'
13
+ autoload :Distances, 'amaze/distances'
14
+ autoload :Mask, 'amaze/mask'
15
+ autoload :MaskedGrid, 'amaze/masked_grid'
16
+ autoload :Shape, 'amaze/shape'
17
+ end
@@ -0,0 +1,44 @@
1
+
2
+ require 'benchmark'
3
+
4
+ class Amaze::Algorithm
5
+
6
+ # Helper class to report the status of the algorithm
7
+ class Stat
8
+ def initialize opts
9
+ @current = opts[:current]
10
+ @pause = opts[:pause]
11
+ @info = opts[:info]
12
+ end
13
+
14
+ attr_reader :current, :info
15
+
16
+ def pause?
17
+ @pause
18
+ end
19
+ end
20
+
21
+ # The time the algorithm takes to generate the maze
22
+ attr_reader :duration
23
+
24
+ def on grid
25
+ @duration = Benchmark.realtime do
26
+ work grid do |stat|
27
+ yield stat if block_given?
28
+ end
29
+ end
30
+ grid
31
+ end
32
+
33
+ def speed
34
+ 0.06
35
+ end
36
+
37
+ autoload :AldousBorder, 'amaze/algorithm/aldous_border'
38
+ autoload :BinaryTree, 'amaze/algorithm/binary_tree'
39
+ autoload :Sidewinder, 'amaze/algorithm/sidewinder'
40
+ autoload :GrowingTree, 'amaze/algorithm/growing_tree'
41
+ autoload :Wilson, 'amaze/algorithm/wilson'
42
+ autoload :HuntAndKill, 'amaze/algorithm/hunt_and_kill'
43
+ autoload :RecursiveBacktracker, 'amaze/algorithm/recursive_backtracker'
44
+ end
@@ -0,0 +1,36 @@
1
+
2
+ class Amaze::Algorithm::AldousBorder < Amaze::Algorithm
3
+
4
+ def work grid
5
+ cell = grid.random_cell
6
+ unvisited = grid.size - 1
7
+
8
+ @iterations = 0 # visualize
9
+ pause = true #
10
+
11
+ while unvisited > 0
12
+
13
+ yield Stat.new( # visualize
14
+ current: [cell], #
15
+ pause: pause, #
16
+ info: "Iteration: #{@iterations += 1}") if block_given? #
17
+ pause = false #
18
+
19
+ neighbor = cell.neighbors.sample
20
+
21
+ if neighbor.links.empty?
22
+ pause = true # visualize
23
+ cell.link neighbor
24
+ unvisited -= 1
25
+ end
26
+
27
+ cell = neighbor
28
+
29
+ end
30
+ grid
31
+ end
32
+
33
+ def status
34
+ "Aldous-Border algorithm: #{@iterations} iterations in #{duration}s"
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+
2
+ class Amaze::Algorithm::BinaryTree < Amaze::Algorithm
3
+
4
+ def work grid
5
+ count = 0 # visualize
6
+ grid.each_cell do |cell|
7
+ links = [cell.north, cell.east].compact
8
+ cell.link links[rand(links.size)] unless links.empty?
9
+
10
+ yield Stat.new( # visualize
11
+ current: [cell], #
12
+ info: "Cell: #{count += 1}") if block_given? #
13
+ end
14
+ grid
15
+ end
16
+
17
+ def status
18
+ "Binary tree algorithm: #{duration}s"
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+
2
+ class Amaze::Algorithm::GrowingTree < Amaze::Algorithm
3
+
4
+ # The configuration of the algorithm
5
+ # In this instance the way the next cell gets picked
6
+ # from the list of active cells.
7
+ attr_reader :config
8
+
9
+ def initialize
10
+ @description = "last from list"
11
+ @config = Proc.new {|active| active.last }
12
+ end
13
+
14
+ def configure description, block
15
+ @description = description
16
+ @config = block
17
+ end
18
+
19
+ def work grid
20
+ # true when active gets cells added
21
+ # false when active gets cells deleted
22
+ mode = true
23
+
24
+ active = [grid.random_cell]
25
+
26
+ while active.any?
27
+ cell = config.call active
28
+
29
+ neighbor = cell.neighbors.select {|neighbor| neighbor.links.empty? }.sample
30
+
31
+ yield Stat.new( # visualize
32
+ current: active, #
33
+ pause: mode ^ !!neighbor, #
34
+ info: "Active #{active.size}") if block_given? #
35
+ mode = !!neighbor #
36
+
37
+ if neighbor
38
+ cell.link neighbor
39
+ active << neighbor
40
+ else
41
+ active.delete cell
42
+ end
43
+
44
+ end
45
+
46
+ grid
47
+ end
48
+
49
+ def status
50
+ "Growing tree (#{@description}) algorithm: #{duration}s"
51
+ end
52
+ end
@@ -0,0 +1,53 @@
1
+
2
+ class Amaze::Algorithm::HuntAndKill < Amaze::Algorithm
3
+
4
+ def work grid
5
+
6
+ current = grid.random_cell
7
+ path = [] # visualize
8
+
9
+ while current
10
+ unvisited_neighbors = current.neighbors.select {|c| c.links.empty? }
11
+
12
+ path << current # visualize
13
+ yield Stat.new( #
14
+ current: path, #
15
+ pause: unvisited_neighbors.empty?, #
16
+ info: "Path: #{path.size}") if block_given? #
17
+
18
+ # kill
19
+ if unvisited_neighbors.any?
20
+ neighbor = unvisited_neighbors.sample
21
+ current.link neighbor
22
+ current = neighbor
23
+
24
+ # hunt
25
+ else
26
+ current = nil
27
+
28
+ path = [] # visualize
29
+ hunt = 0 #
30
+
31
+ grid.each_cell do |cell|
32
+ visited_neighbors = cell.neighbors.select {|c| c.links.any? }
33
+
34
+ yield Stat.new( # visualize
35
+ current: [cell], #
36
+ pause: cell.links.empty? && visited_neighbors.any?, #
37
+ info: "Hunt: #{hunt += 1}") if block_given? #
38
+
39
+ if cell.links.empty? && visited_neighbors.any?
40
+ current = cell
41
+ neighbor = visited_neighbors.sample
42
+ current.link neighbor
43
+ break
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def status
51
+ "Hunt and Kill algorithm: #{duration}s"
52
+ end
53
+ end