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,5 @@
1
+
2
+ module Amaze::Formatter
3
+ autoload :ASCII, 'amaze/formatter/ascii'
4
+ autoload :Image, 'amaze/formatter/image'
5
+ end
@@ -0,0 +1,91 @@
1
+
2
+ # all rainbow colors: Rainbow::X11ColorNames::NAMES.keys
3
+ require 'rainbow/ext/string'
4
+
5
+ class Amaze::Formatter::ASCII
6
+ autoload :Delta, 'amaze/formatter/ascii/delta'
7
+ autoload :Ortho, 'amaze/formatter/ascii/ortho'
8
+ autoload :Sigma, 'amaze/formatter/ascii/sigma'
9
+ autoload :Upsilon, 'amaze/formatter/ascii/upsilon'
10
+ autoload :Polar, 'amaze/formatter/ascii/polar'
11
+
12
+ # The grid
13
+ attr_reader :grid
14
+
15
+ # Options for the ASCII renderer
16
+ attr_reader :options
17
+
18
+ def initialize grid, options={}
19
+ @grid = grid
20
+ @options = options
21
+ end
22
+
23
+ def char
24
+ @char ||= Array.new(char_array_height) do |x|
25
+ Array.new(char_array_width) do |y|
26
+ clear
27
+ end
28
+ end
29
+ end
30
+
31
+ def render
32
+ grid.each_cell do |cell|
33
+ draw_cell cell
34
+ draw_content cell if distances
35
+ draw_path cell if path_cell? cell
36
+ end
37
+
38
+ ansi_clear + char.map{|l| l.join }.join("\n")
39
+ end
40
+
41
+ def path? direction, cell
42
+ cell.linked?(cell.send(direction)) && path_cell?(cell.send(direction))
43
+ end
44
+
45
+ def ansi_clear
46
+ "\e[H\e[2J"
47
+ end
48
+
49
+ def clear
50
+ ' '
51
+ end
52
+
53
+ # The size of the cell
54
+ def cell_size
55
+ options[:cell_size] || 1
56
+ end
57
+
58
+ # The color of the grid
59
+ def grid_color
60
+ options[:grid_color] || :white
61
+ end
62
+
63
+ # The color used to draw the solution or the longest path
64
+ def path_color
65
+ options[:path_color] || :blue
66
+ end
67
+
68
+ def path_cell? cell
69
+ Array(options[:path_cells]).include? cell
70
+ end
71
+
72
+ # Distances
73
+ def distances
74
+ options[:distances]
75
+ end
76
+
77
+ def distance cell
78
+ # .to_s(36) => 0..9a..z
79
+ distances && distances[cell] ? distances[cell].to_s(36).upcase : ' '
80
+ end
81
+
82
+ def distance_color cell
83
+ return @options[:distances_color] if @options[:distances_color]
84
+ _, max = distances.max
85
+ high = (255-47).to_f / max * distances[cell] + 47
86
+ low = high / 4
87
+ p [:low, low] unless (0..255).include? low
88
+ p [:high, high] unless (0..255).include? high
89
+ [0,low,high]
90
+ end
91
+ end
@@ -0,0 +1,180 @@
1
+
2
+ class Amaze::Formatter::ASCII::Delta < Amaze::Formatter::ASCII
3
+
4
+ def draw_cell cell
5
+ x0, y0 = coord cell
6
+
7
+ # reverse triangle
8
+ if (cell.column + cell.row).even?
9
+ # corner
10
+ char[y0][x0] = corner.color(grid_color)
11
+ char[y0][x0+(cell_size+1)*2] = corner.color(grid_color)
12
+ char[y0+cell_size+1][x0+cell_size+1] = corner.color(grid_color)
13
+
14
+ 0.upto(cell_size*2) do |i|
15
+ # north
16
+ char[y0][x0+1+i] = h.color(grid_color)
17
+ end unless cell.linked_to?(:north)
18
+ 1.upto(cell_size) do |i|
19
+ # west
20
+ char[y0+i][x0+i] = rw.color(grid_color) unless cell.linked_to?(:west)
21
+ # east
22
+ char[y0+i][x0+(cell_size+1)*2-i] = re.color(grid_color) unless cell.linked_to?(:east)
23
+ end
24
+
25
+ # normal triangle
26
+ else
27
+ # corner
28
+ char[y0+cell_size+1][x0] = corner.color(grid_color)
29
+ char[y0+cell_size+1][x0+(cell_size+1)*2] = corner.color(grid_color)
30
+ char[y0][x0+cell_size+1] = corner.color(grid_color)
31
+
32
+ 0.upto(cell_size*2) do |i|
33
+ # south
34
+ char[y0+cell_size+1][x0+1+i] = h.color(grid_color)
35
+ end unless cell.linked_to?(:south)
36
+ 1.upto(cell_size) do |i|
37
+ # west
38
+ char[y0+i][x0+cell_size+1-i] = nw.color(grid_color) unless cell.linked_to?(:west)
39
+ # east
40
+ char[y0+i][x0+cell_size+1+i] = ne.color(grid_color) unless cell.linked_to?(:east)
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ def draw_content cell
47
+ x0, y0 = coord cell
48
+
49
+ if cell_size == 1
50
+ my = y0 + 1
51
+ mx = x0 + 2
52
+ w = 1
53
+ else
54
+ mx = x0 + cell_size / 2 + 1
55
+ w = (cell_size+1) / 2 * 2 + 1
56
+ if (cell.column+cell.row).even?
57
+ my = y0 + cell_size / 2
58
+ else
59
+ my = y0 + (cell_size+3) / 2
60
+ end
61
+ end
62
+
63
+ distance(cell).center(w).chars.each_with_index do |c,i|
64
+ char[my][mx+i] = c.color(*distance_color(cell))
65
+ end
66
+ end
67
+
68
+ def draw_path cell
69
+ x0, y0 = coord cell
70
+
71
+ mx = x0 + cell_size + 1
72
+ my = y0 + (cell_size + 1) / 2
73
+
74
+ # center
75
+ char[my][mx] = center.color(path_color)
76
+ 1.upto(cell_size) do |i|
77
+ # east-west
78
+ char[my][mx+i] = h.color(path_color) if path?(:east, cell)
79
+ # north-south
80
+ char[my+i][mx] = v.color(path_color) if path?(:south, cell)
81
+ end
82
+ end
83
+
84
+ def coord cell
85
+ [xpos(cell.column), ypos(cell.row)]
86
+ end
87
+
88
+ def xpos column
89
+ (cell_size + 1) * column
90
+ end
91
+
92
+ def ypos row
93
+ (cell_size + 1) * row
94
+ end
95
+
96
+ def char_array_width
97
+ xpos(grid.columns + 1) + 1
98
+ end
99
+
100
+ def char_array_height
101
+ ypos(grid.rows) + 1
102
+ end
103
+
104
+ def h
105
+ '-'
106
+ end
107
+
108
+ def v
109
+ '|'
110
+ end
111
+
112
+ def rw
113
+ '\\'
114
+ end
115
+
116
+ def re
117
+ '/'
118
+ end
119
+
120
+ def corner
121
+ '∙'
122
+ end
123
+
124
+ alias_method :center, :corner
125
+ alias_method :nw, :re
126
+ alias_method :ne, :rw
127
+
128
+ end
129
+
130
+ __END__
131
+
132
+ ∙---∙---∙
133
+ \...\ / \
134
+ ∙ . ∙---∙
135
+ / \./ \ /
136
+ ∙---∙---∙
137
+ \ / \ / \
138
+ ∙---∙---∙
139
+
140
+ ∙-----∙-----∙
141
+ \ ....\ * / \
142
+ \ . \ / \
143
+ ∙ . ∙-----∙
144
+ /.... / \ /
145
+ / . / \ /
146
+ ∙ . ∙-----∙
147
+ \ . / \ / \
148
+ \ / \ / \
149
+ ∙-----∙-----∙
150
+
151
+ ∙-------∙-------∙
152
+ \ \ / \
153
+ \ ..... \ / \
154
+ \ . \ / \
155
+ ∙ . ∙-------∙
156
+ / \ . / \ /
157
+ / \ / \ /
158
+ / \ / \ /
159
+ ∙-------∙-------∙
160
+ \ / \ / \
161
+ \ / \ / \
162
+ \ / \ / \
163
+ ∙-------∙-------∙
164
+
165
+ ∙---------∙---------∙
166
+ \ / \ / \
167
+ \ . \ / \
168
+ \ ` . \ / \
169
+ \ / \ / \
170
+ ∙---------∙---------∙
171
+ / \ / \ /
172
+ / \ / \ /
173
+ / \ / \ /
174
+ / \ / \ /
175
+ ∙---------∙---------∙
176
+ \ / \ / \
177
+ \ / \ / \
178
+ \ / \ / \
179
+ \ / \ / \
180
+ ∙---------∙---------∙
@@ -0,0 +1,105 @@
1
+
2
+ class Amaze::Formatter::ASCII::Ortho < Amaze::Formatter::ASCII
3
+
4
+ def draw_cell cell
5
+ left, right, top, bottom = coord cell
6
+
7
+ # corners
8
+ char[top][left] = corner.color(grid_color)
9
+ char[top][right] = corner.color(grid_color)
10
+ char[bottom][left] = corner.color(grid_color)
11
+ char[bottom][right] = corner.color(grid_color)
12
+ # top & bottom
13
+ (left+1).upto(right-1) do |i|
14
+ # top
15
+ char[top][i] = h.color(grid_color) unless cell.linked_to?(:north)
16
+ # bottom
17
+ char[bottom][i] = h.color(grid_color) unless cell.linked_to?(:south)
18
+ end
19
+ # left & right
20
+ (top+1).upto(bottom-1) do |i|
21
+ # left
22
+ char[i][left] = v.color(grid_color) unless cell.linked_to?(:west)
23
+ # right
24
+ char[i][right] = v.color(grid_color) unless cell.linked_to?(:east)
25
+ end
26
+ end
27
+
28
+ def draw_content cell
29
+ left, right, top, bottom = coord cell
30
+
31
+ my = top + cell_size / 2 + 1
32
+ distance(cell).center(cell_size * 3).chars.each_with_index do |c,i|
33
+ char[my][left+1+i] = c.color(*distance_color(cell))
34
+ end
35
+ end
36
+
37
+ def draw_path cell
38
+ left, right, top, bottom = coord cell
39
+
40
+ mx = left + (cell_size * 3 + 1) / 2
41
+ my = top + cell_size / 2 + 1
42
+
43
+ # TODO: simplify paths, draw only north-south and east-west
44
+
45
+ # to north
46
+ top.upto(my-1) do |i|
47
+ char[i][mx] = v.color(path_color) if path?(:north, cell)
48
+ end if top <= my-1
49
+ # to east
50
+ (mx+1).upto(right) do |i|
51
+ char[my][i] = h.color(path_color) if path?(:east, cell)
52
+ end if mx+1 <= right
53
+ # to south
54
+ (my+1).upto(bottom) do |i|
55
+ char[i][mx] = v.color(path_color) if path?(:south, cell)
56
+ end if my+1 <= bottom
57
+ # to west
58
+ left.upto(mx-1) do |i|
59
+ char[my][i] = h.color(path_color) if path?(:west, cell)
60
+ end if left <= mx-1
61
+ # center, select the char depeding on how many paths cross the cell
62
+ center_char = center
63
+ center_char = v if path?(:north, cell) && path?(:south, cell)
64
+ center_char = h if path?(:east, cell) && path?(:west, cell)
65
+ center_char = corner if [:north, :east, :south, :west].select{|d| path?(d, cell) }.size >= 3
66
+ char[my][mx] = center_char.color(path_color)
67
+ end
68
+
69
+ # left, right, top, bottom
70
+ def coord cell
71
+ [x(cell.column), x(cell.column+1), y(cell.row), y(cell.row+1)]
72
+ end
73
+
74
+ def x column
75
+ (cell_size * 3 + 1) * column
76
+ end
77
+
78
+ def y row
79
+ (cell_size + 1) * row
80
+ end
81
+
82
+ def char_array_width
83
+ x(grid.columns) + 1
84
+ end
85
+
86
+ def char_array_height
87
+ y(grid.rows) + 1
88
+ end
89
+
90
+ def h
91
+ '-'
92
+ end
93
+
94
+ def v
95
+ '|'
96
+ end
97
+
98
+ def center
99
+ '∙'
100
+ end
101
+
102
+ def corner
103
+ '+'
104
+ end
105
+ end
@@ -0,0 +1,199 @@
1
+
2
+ class Amaze::Formatter::ASCII::Polar < Amaze::Formatter::ASCII
3
+
4
+ def draw_cell cell
5
+ x1, x2, y1, y2 = coord cell
6
+
7
+ # corners
8
+ char[y1][x1] = corner.color(grid_color)
9
+ char[y1][x2] = corner.color(grid_color)
10
+ char[y2][x1] = corner.color(grid_color)
11
+ char[y2][x2] = corner.color(grid_color)
12
+ # top & bottom
13
+ (x1+1).upto(x2-1) do |i|
14
+ # top (inward)
15
+ char[y1][i] = h.color(grid_color) unless cell.linked_to?(:inward)
16
+ # bottom (outward)
17
+ char[y2][i] = h.color(grid_color) if cell.row == grid.rows-1
18
+ end
19
+ # left & right
20
+ (y1+1).upto(y2-1) do |i|
21
+ # left (cw)
22
+ char[i][x1] = v.color(grid_color) unless cell.linked_to?(:cw)
23
+ # right (ccw)
24
+ char[i][x2] = v.color(grid_color) unless cell.linked_to?(:ccw)
25
+ end
26
+ end
27
+
28
+ def draw_content cell
29
+ x1, x2, y1, y2 = coord cell
30
+ _, my = center_coord cell
31
+ dx = x2 - x1 - 1
32
+
33
+ distance(cell).center(dx).chars.each_with_index do |c,i|
34
+ char[my][x1+1+i] = c.color(*distance_color(cell))
35
+ end
36
+ end
37
+
38
+ def draw_path cell
39
+ # draw horizontal connections in cells with more than one outward path
40
+ if outward_subdivided?(cell) && ! path?(:cw, cell) && ! path?(:ccw, cell)
41
+ outward_cells = path_outward(cell)
42
+ if outward_cells.any?
43
+ mx, my = center_coord cell
44
+ x_outward_cells = outward_cells.map{|c| x,_ = center_coord c; x}
45
+ mx = x_outward_cells.first if cell.row.zero?
46
+ mx_min = [mx, *x_outward_cells].min
47
+ mx_max = [mx, *x_outward_cells].max
48
+ char[my][mx_min] = center.color(path_color)
49
+ char[my][mx_max] = center.color(path_color)
50
+ (mx_min+1).upto(mx_max-1) do |i|
51
+ char[my][i] = h.color(path_color)
52
+ end
53
+ end
54
+ end
55
+
56
+ # to cw
57
+ if path?(:cw, cell)
58
+ mx1, my1 = center_coord cell.cw
59
+ mx2, my2 = center_coord cell
60
+ if outward_subdivided? cell
61
+ outward_cells_cw = path_outward cell.cw
62
+ mx1, _ = center_coord(outward_cells_cw.first) if outward_cells_cw.any?
63
+ outward_cells = path_outward cell
64
+ mx2, _ = center_coord(outward_cells.first) if outward_cells.any?
65
+ end
66
+ mx1 = -1 if mx1 > mx2
67
+ (mx1+1).upto(mx2-1) do |i|
68
+ char[my1][i] = h.color(path_color)
69
+ end
70
+ char[my1][mx2] = center.color(path_color)
71
+ end
72
+
73
+ # to ccw
74
+ if path?(:ccw, cell)
75
+ mx1, my1 = center_coord cell
76
+ mx2, my2 = center_coord cell.ccw
77
+ if outward_subdivided? cell
78
+ outward_cells = path_outward cell
79
+ mx1, _ = center_coord(outward_cells.first) if outward_cells.any?
80
+ outward_cells_ccw = path_outward cell.ccw
81
+ mx2, _ = center_coord(outward_cells_ccw.first) if outward_cells_ccw.any?
82
+ end
83
+ mx2 = char_array_width if mx1 > mx2
84
+ (mx1+1).upto(mx2-1) do |i|
85
+ char[my1][i] = h.color(path_color)
86
+ end
87
+ char[my1][mx1] = center.color(path_color)
88
+ end
89
+
90
+ # to inward
91
+ if path?(:inward, cell)
92
+ mx, my = center_coord cell
93
+ v1, v2, w1, w2 = coord cell.inward
94
+ mw = (w1 + w2) / 2
95
+ (mw+1).upto(my-1) do |i|
96
+ char[i][mx] = v.color(path_color)
97
+ end
98
+ end
99
+
100
+ # center
101
+ mx, my = center_coord cell
102
+ if outward_subdivided? cell
103
+ char[my][mx] = h.color(path_color) if path?(:ccw, cell) && path?(:cw, cell)
104
+ char[my][mx] = center.color(path_color) if path?(:inward, cell) && path_outward(cell).empty?
105
+ else
106
+ center_char = center
107
+ center_char = h if path?(:ccw, cell) && path?(:cw, cell)
108
+ center_char = v if path?(:inward, cell) && path_outward(cell).any?
109
+ char[my][mx] = center_char.color(path_color)
110
+ end
111
+ end
112
+
113
+ def outward_subdivided? cell
114
+ return false if grid.rows == cell.row + 1
115
+ grid.columns(cell.row).size != grid.columns(cell.row+1).size
116
+ end
117
+
118
+ def path_outward cell
119
+ cell.outward.select {|o| cell.linked?(o) && path_cell?(o) }
120
+ end
121
+
122
+ def coord cell
123
+ columns = grid.columns(cell.row).size
124
+ x2 = char_array_width - 1 - x(cell.column, columns)
125
+ x1 = char_array_width - 1 - x(cell.column+1, columns)
126
+ y1 = y(cell.row)
127
+ y2 = y(cell.row+1)
128
+
129
+ [x1, x2, y1, y2]
130
+ end
131
+
132
+ def center_coord cell
133
+ x1, x2, y1, y2 = coord cell
134
+ [(x1 + x2) / 2, (y1 + y2) / 2]
135
+ end
136
+
137
+ def x column, columns=max_columns
138
+ factor = max_columns / columns
139
+ (cell_size * 4 * factor) * column
140
+ end
141
+
142
+ def y row
143
+ (cell_size + 1) * row
144
+ end
145
+
146
+ def max_columns
147
+ grid.columns(grid.rows-1).size
148
+ end
149
+
150
+ def char_array_width
151
+ x(max_columns) + 1
152
+ end
153
+
154
+ def char_array_height
155
+ y(grid.rows) + 1
156
+ end
157
+
158
+ def h
159
+ '-'
160
+ end
161
+
162
+ def v
163
+ '|'
164
+ end
165
+
166
+ def center
167
+ '∙'
168
+ end
169
+
170
+ def corner
171
+ '+'
172
+ end
173
+ end
174
+
175
+ __END__
176
+
177
+ +-----------------------------------------------+ 47 f=12 columns/column * 3 + columns/column-1
178
+ | |
179
+ +---------------+---------------+---------------+ 15 f=4
180
+ | | | |
181
+ +-------+-------+-------+-------+-------+-------+ 7 f=2
182
+ | | | | | | |
183
+ +---+---+---+---+---+---+---+---+---+---+---+---+ 3 f=1
184
+ | | | | | | | | | | | | |
185
+ +---+---+---+---+---+---+---+---+---+---+---+---+
186
+
187
+ +-----------------------------------------------------------------------------------+
188
+ | |
189
+ | |
190
+ +---------------------------+---------------------------+---------------------------+
191
+ | | | |
192
+ | | | |
193
+ +-------------+-------------+-------------+-------------+-------------+-------------+
194
+ | | | | | | |
195
+ | | | | | | |
196
+ +------+------+------+------+------+------+------+------+------+------+------+------+
197
+ | | | | | | | | | | | | |
198
+ | | | | | | | | | | | | |
199
+ +------+------+------+------+------+------+------+------+------+------+------+------+