graphics 1.0.0b1 → 1.0.0b4

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/History.rdoc +30 -0
  5. data/Manifest.txt +39 -7
  6. data/README.rdoc +48 -4
  7. data/Rakefile +8 -2
  8. data/examples/boid.rb +9 -18
  9. data/examples/bounce.rb +15 -23
  10. data/examples/canvas.rb +75 -0
  11. data/examples/collision.rb +6 -6
  12. data/examples/demo.rb +5 -7
  13. data/examples/editor.rb +12 -9
  14. data/examples/fluid.rb +2 -3
  15. data/examples/fluid2.rb +1 -1
  16. data/examples/{lito2.rb → gol.rb} +0 -0
  17. data/examples/{zenspider4.rb → gol2.rb} +0 -0
  18. data/examples/logo.rb +4 -7
  19. data/examples/maze.rb +136 -0
  20. data/examples/tank.rb +10 -11
  21. data/examples/tank2.rb +12 -17
  22. data/examples/targeting.rb +1 -1
  23. data/examples/vants.rb +1 -1
  24. data/examples/walker.rb +3 -12
  25. data/examples/walker2.rb +197 -0
  26. data/examples/zombies.rb +31 -35
  27. data/ext/sdl/extconf.rb +31 -0
  28. data/ext/sdl/sdl.c +1067 -0
  29. data/ext/sdl/sge/INSTALL +72 -0
  30. data/ext/sdl/sge/LICENSE +504 -0
  31. data/ext/sdl/sge/Makefile +83 -0
  32. data/ext/sdl/sge/Makefile.conf +63 -0
  33. data/ext/sdl/sge/README +219 -0
  34. data/ext/sdl/sge/Todo +7 -0
  35. data/ext/sdl/sge/WhatsNew +224 -0
  36. data/ext/sdl/sge/sge.h +31 -0
  37. data/ext/sdl/sge/sge_blib.cpp +1939 -0
  38. data/ext/sdl/sge/sge_blib.h +68 -0
  39. data/ext/sdl/sge/sge_bm_text.cpp +451 -0
  40. data/ext/sdl/sge/sge_bm_text.h +71 -0
  41. data/ext/sdl/sge/sge_collision.cpp +388 -0
  42. data/ext/sdl/sge/sge_collision.h +54 -0
  43. data/ext/sdl/sge/sge_config.h +6 -0
  44. data/ext/sdl/sge/sge_internal.h +152 -0
  45. data/ext/sdl/sge/sge_misc.cpp +92 -0
  46. data/ext/sdl/sge/sge_misc.h +37 -0
  47. data/ext/sdl/sge/sge_primitives.cpp +2516 -0
  48. data/ext/sdl/sge/sge_primitives.h +111 -0
  49. data/ext/sdl/sge/sge_rotation.cpp +683 -0
  50. data/ext/sdl/sge/sge_rotation.h +46 -0
  51. data/ext/sdl/sge/sge_shape.cpp +762 -0
  52. data/ext/sdl/sge/sge_shape.h +365 -0
  53. data/ext/sdl/sge/sge_surface.cpp +1090 -0
  54. data/ext/sdl/sge/sge_surface.h +100 -0
  55. data/ext/sdl/sge/sge_textpp.cpp +785 -0
  56. data/ext/sdl/sge/sge_textpp.h +270 -0
  57. data/ext/sdl/sge/sge_tt_text.cpp +1456 -0
  58. data/ext/sdl/sge/sge_tt_text.h +114 -0
  59. data/graphics_setup.sh +26 -0
  60. data/lib/graphics.rb +1 -1
  61. data/lib/graphics/body.rb +50 -3
  62. data/lib/graphics/extensions.rb +13 -7
  63. data/lib/graphics/simulation.rb +126 -46
  64. data/test/test_graphics.rb +52 -12
  65. data/test/test_sdl.rb +1 -0
  66. metadata +54 -23
  67. metadata.gz.sig +0 -0
  68. data/.gemtest +0 -0
  69. data/examples/lito.rb +0 -108
  70. data/examples/zenspider1.rb +0 -93
  71. data/examples/zenspider2.rb +0 -123
  72. data/examples/zenspider3.rb +0 -104
  73. data/rubysdl_setup.sh +0 -34
@@ -34,8 +34,6 @@ class Demo < Graphics::Simulation
34
34
  super 800, 800, 16, "Boid"
35
35
  self.ball = Ball.new self
36
36
 
37
- r = color[:red]
38
-
39
37
  self.img = sprite 10, 10 do
40
38
  circle 5, 5, 5, :white, :filled
41
39
  end
@@ -64,12 +62,14 @@ class Demo < Graphics::Simulation
64
62
 
65
63
  circle 225, 50, 10, :white
66
64
 
67
- ellipse 250, 50, 10, 10, :white
65
+ ellipse 250, 50, 10, 20, :white
68
66
 
69
67
  bezier 275, 50, 275, 100, 285, 0, 300, 50, :white
70
68
 
71
69
  rect 300, 25, 50, 50, :white
72
- blit img, 325, 50, 0
70
+
71
+ blit img, 325, 50 # centered
72
+ put img, 335, 50 # cornered
73
73
 
74
74
  text "blah", 350, 50, :white
75
75
 
@@ -85,6 +85,4 @@ class Demo < Graphics::Simulation
85
85
  end
86
86
  end
87
87
 
88
- if $0 == __FILE__
89
- Demo.new.run
90
- end
88
+ Demo.new.run if $0 == __FILE__
@@ -16,9 +16,14 @@ class Editor < Graphics::Simulation
16
16
  self.lines = []
17
17
  end
18
18
 
19
+ def initialize_keys
20
+ # no super
21
+ add_key_handler(:ESCAPE) { exit }
22
+ end
23
+
19
24
  def handle_event e, n
20
25
  case e
21
- when SDL::Event::KeyDown then
26
+ when SDL::Event::Keydown then
22
27
  if e.mod & (SDL::Key::MOD_LCTRL | SDL::Key::MOD_RCTRL) != 0 then
23
28
  case e.sym.chr
24
29
  when "t" then
@@ -55,16 +60,14 @@ class Editor < Graphics::Simulation
55
60
  end
56
61
 
57
62
  def draw_overlay
58
- if overlay? then
59
- lines.each_with_index do |l, i|
60
- text l, 10, ((lines.size-i)*font.height), :gray
61
- end
63
+ return unless overlay?
62
64
 
63
- text "> #{s}_", 10, 0, :white
65
+ lines.each_with_index do |l, i|
66
+ text l, 10, ((lines.size-i)*font.height), :gray
64
67
  end
68
+
69
+ text "> #{s}_", 10, 0, :white
65
70
  end
66
71
  end
67
72
 
68
- if $0 == __FILE__
69
- Editor.new.run
70
- end
73
+ Editor.new.run if $0 == __FILE__
@@ -111,15 +111,14 @@ class SPH
111
111
  # Calculate fluid density around each particle
112
112
  particles.each do |particle|
113
113
  particles.each do |neighbor|
114
-
115
114
  # If particles are close together, density increases
116
115
  distance = particle.position - neighbor.position
117
116
 
118
- if distance.magnitude < H # Particles are close enough to matter
117
+ if distance.magnitude < H then
118
+ # Particles are close enough to matter
119
119
  particle.density += MASS * weight(distance, H)
120
120
  end
121
121
  end
122
- # p particle.density if particle.density > 2*H
123
122
  end
124
123
  end
125
124
 
@@ -52,7 +52,7 @@ class Particle < Graphics::Body
52
52
  nearby.each do |neighbor|
53
53
  distance = (position - neighbor.position)
54
54
 
55
- self.density += MASS * weight(distance, H) # if distance.magnitude < H
55
+ self.density += MASS * weight(distance, H)
56
56
  end
57
57
  end
58
58
 
File without changes
File without changes
@@ -34,9 +34,8 @@ class Turtle < Graphics::Body
34
34
  self.a += $1.to_i
35
35
  when /f (\d+)/ then
36
36
  dist = $1.to_i
37
- if pen then
38
- w.angle x, y, a, dist, :white
39
- end
37
+
38
+ w.angle x, y, a, dist, :white if pen
40
39
  move_by a, dist
41
40
  else
42
41
  src.delete line
@@ -51,7 +50,7 @@ class Turtle < Graphics::Body
51
50
  p2 = w.project(x, y, a+90, 5)
52
51
  p3 = w.project(x, y, a-90, 5)
53
52
 
54
- polygon p1, p2, p3, :green
53
+ w.polygon p1, p2, p3, :green
55
54
  end
56
55
  end
57
56
 
@@ -68,6 +67,4 @@ class Logo < Editor
68
67
  end
69
68
  end
70
69
 
71
- if $0 == __FILE__
72
- Logo.new.run
73
- end
70
+ Logo.new.run if $0 == __FILE__
@@ -0,0 +1,136 @@
1
+ #!/usr/local/bin/ruby -w
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require "graphics"
5
+
6
+ ##
7
+ # All code here is adapted from Jamis Buck's Mazes for Programmers.
8
+ # Used with Permission.
9
+
10
+ class Cell
11
+ attr_reader :row, :column
12
+ attr_accessor :north, :south, :east, :west
13
+
14
+ def initialize(row, column)
15
+ @row, @column = row, column
16
+ @links = {}
17
+ end
18
+
19
+ def link(cell, bidi=true)
20
+ @links[cell] = true
21
+ cell.link(self, false) if bidi
22
+ self
23
+ end
24
+
25
+ def linked?(cell)
26
+ @links.key?(cell)
27
+ end
28
+ end
29
+
30
+ class Grid
31
+ attr_reader :rows, :columns, :w
32
+
33
+ def initialize(rows, columns, w)
34
+ @rows = rows
35
+ @columns = columns
36
+ @w = w
37
+
38
+ @grid = prepare_grid
39
+ configure_cells
40
+ end
41
+
42
+ def prepare_grid
43
+ Array.new(rows) do |row|
44
+ Array.new(columns) do |column|
45
+ Cell.new(row, column)
46
+ end
47
+ end
48
+ end
49
+
50
+ def configure_cells
51
+ each_cell do |cell|
52
+ row, col = cell.row, cell.column
53
+
54
+ cell.north = self[row - 1, col]
55
+ cell.south = self[row + 1, col]
56
+ cell.west = self[row, col - 1]
57
+ cell.east = self[row, col + 1]
58
+ end
59
+ end
60
+
61
+ def [](row, column)
62
+ return nil unless row.between?(0, @rows - 1)
63
+ return nil unless column.between?(0, @grid[row].count - 1)
64
+ @grid[row][column]
65
+ end
66
+
67
+ def each_row
68
+ @grid.each do |row|
69
+ yield row
70
+ end
71
+ end
72
+
73
+ def each_cell
74
+ each_row do |row|
75
+ row.each do |cell|
76
+ yield cell if cell
77
+ end
78
+ end
79
+ end
80
+
81
+ def draw n
82
+ cell_size = w.w / columns
83
+
84
+ each_cell do |cell|
85
+ x1 = cell_size * cell.column
86
+ y1 = cell_size * cell.row
87
+ x2 = cell_size * (cell.column + 1)
88
+ y2 = cell_size * (cell.row + 1)
89
+
90
+ w.line x1, y1, x2, y1, :white unless cell.north
91
+ w.line x1, y1, x1, y2, :white unless cell.west
92
+ w.line x2, y1, x2, y2, :white unless cell.linked? cell.east
93
+ w.line x1, y2, x2, y2, :white unless cell.linked? cell.south
94
+ end
95
+ end
96
+ end
97
+
98
+ class BinaryTree
99
+ def self.on(grid)
100
+ grid.each_cell do |cell|
101
+ neighbors = []
102
+ neighbors << cell.north if cell.north
103
+ neighbors << cell.east if cell.east
104
+
105
+ index = rand(neighbors.length)
106
+ neighbor = neighbors[index]
107
+
108
+ cell.link(neighbor) if neighbor
109
+ end
110
+
111
+ grid
112
+ end
113
+ end
114
+
115
+ class Maze < Graphics::Simulation
116
+ attr_accessor :grid
117
+
118
+ def initialize
119
+ super 800, 800
120
+
121
+ self.grid = Grid.new 50, 50, self
122
+ BinaryTree.on grid
123
+ end
124
+
125
+ def update n
126
+ # do nothing
127
+ end
128
+
129
+ def draw n
130
+ clear
131
+
132
+ grid.draw n
133
+ end
134
+ end
135
+
136
+ Maze.new.run if $0 == __FILE__
@@ -123,8 +123,6 @@ class TargetSimulation < Graphics::Simulation
123
123
  def initialize
124
124
  super 640, 640, 16, "Target Practice"
125
125
 
126
- SDL::Key.enable_key_repeat 50, 10
127
-
128
126
  self.tank = Tank.new self
129
127
  self.bullets = []
130
128
 
@@ -132,15 +130,16 @@ class TargetSimulation < Graphics::Simulation
132
130
  self.turret_img = image "resources/images/turret.png"
133
131
  end
134
132
 
135
- def handle_keys
136
- exit if SDL::Key.press? SDL::Key::ESCAPE
137
- tank.turn_right if SDL::Key.press? SDL::Key::RIGHT
138
- tank.turn_left if SDL::Key.press? SDL::Key::LEFT
139
- tank.accelerate if SDL::Key.press? SDL::Key::UP
140
- tank.decelerate if SDL::Key.press? SDL::Key::DOWN
141
- tank.aim_left if SDL::Key.press? SDL::Key::SEMICOLON
142
- tank.aim_right if SDL::Key.press? SDL::Key::Q
143
- tank.fire if SDL::Key.press? SDL::Key::SPACE
133
+ def initialize_keys
134
+ super
135
+
136
+ add_key_handler(:RIGHT) { tank.turn_right }
137
+ add_key_handler(:LEFT) { tank.turn_left }
138
+ add_key_handler(:UP) { tank.accelerate }
139
+ add_key_handler(:DOWN) { tank.decelerate }
140
+ add_key_handler(:SEMICOLON) { tank.aim_left }
141
+ add_key_handler(:Q, :remove){ tank.aim_right }
142
+ add_key_handler(:SPACE) { tank.fire }
144
143
  end
145
144
 
146
145
  def update n
@@ -97,13 +97,9 @@ class TargetSimulation < Graphics::Simulation
97
97
  def initialize
98
98
  super 640, 640, 16, "Target Practice"
99
99
 
100
- SDL::Key.enable_key_repeat 50, 10
101
-
102
100
  self.tank = Tank.new w/2, h/2
103
101
  self.bullets = []
104
102
 
105
- screen.set_alpha SDL::SRCALPHA, 128
106
-
107
103
  self.body_img = sprite 40, 30 do
108
104
  rect 0, 0, 39, 29, :white
109
105
  rect 0, 4, 39, 21, :white
@@ -120,15 +116,16 @@ class TargetSimulation < Graphics::Simulation
120
116
  end
121
117
  end
122
118
 
123
- def handle_keys
124
- exit if SDL::Key.press? SDL::Key::ESCAPE
125
- tank.turn_right if SDL::Key.press? SDL::Key::RIGHT
126
- tank.turn_left if SDL::Key.press? SDL::Key::LEFT
127
- tank.accelerate if SDL::Key.press? SDL::Key::UP
128
- tank.decelerate if SDL::Key.press? SDL::Key::DOWN
129
- tank.aim_left if SDL::Key.press? SDL::Key::SEMICOLON
130
- tank.aim_right if SDL::Key.press? SDL::Key::Q
131
- fire if SDL::Key.press? SDL::Key::SPACE
119
+ def initialize_keys
120
+ super
121
+
122
+ add_key_handler(:RIGHT) { tank.turn_right }
123
+ add_key_handler(:LEFT) { tank.turn_left }
124
+ add_key_handler(:UP) { tank.accelerate }
125
+ add_key_handler(:DOWN) { tank.decelerate }
126
+ add_key_handler(:SEMICOLON) { tank.aim_left }
127
+ add_key_handler(:Q, :remove){ tank.aim_right }
128
+ add_key_handler(:SPACE) { fire }
132
129
  end
133
130
 
134
131
  def fire
@@ -152,13 +149,11 @@ class TargetSimulation < Graphics::Simulation
152
149
  fps n
153
150
  end
154
151
 
155
- AA = SDL::Surface::TRANSFORM_AA
156
-
157
152
  def draw_tank
158
153
  x, y, a, t = tank.x, tank.y, tank.angle, tank.turret
159
154
 
160
- blit body_img, x, y, a, AA
161
- blit turret_img, x, y, t, AA
155
+ blit body_img, x, y, a
156
+ blit turret_img, x, y, t
162
157
 
163
158
  debug "%3d @ %.2f @ %d", tank.angle, tank.speed, tank.energy
164
159
  end
@@ -15,7 +15,7 @@ class TargetSimulation < Graphics::Simulation
15
15
  end
16
16
 
17
17
  def handle_event event, n
18
- bombs << [n, event.x, h-event.y] if SDL::Event::MouseButtonDown === event
18
+ bombs << [n, event.x, h-event.y] if SDL::Event::Mousedown === event
19
19
  super
20
20
  end
21
21
 
@@ -62,7 +62,7 @@ class Vants < Graphics::Simulation
62
62
  end
63
63
 
64
64
  def draw n
65
- screen.update_rect 0, 0, 0, 0
65
+ screen.update 0, 0, 0, 0
66
66
  end
67
67
  end
68
68
 
@@ -10,9 +10,7 @@ class Person < Graphics::Body
10
10
  D_M = 0.25
11
11
  M_M = 5.0
12
12
 
13
- AA = SDL::Surface::TRANSFORM_AA
14
-
15
- attr_accessor :trail, :attack
13
+ attr_accessor :trail
16
14
 
17
15
  def initialize w
18
16
  super
@@ -21,7 +19,6 @@ class Person < Graphics::Body
21
19
 
22
20
  self.a = random_angle
23
21
  self.ga = random_angle
24
- self.attack = false
25
22
  end
26
23
 
27
24
  def update
@@ -43,16 +40,10 @@ class Person < Graphics::Body
43
40
  def draw
44
41
  trail.draw
45
42
 
46
- if attack then
47
- w.angle x, y, a-45, 50, :yellow
48
- w.angle x, y, a, 60, :red
49
- w.angle x, y, a+45, 50, :yellow
50
- end
51
-
52
43
  w.angle x, y, ga, 60, :red
53
44
 
54
45
  # the blit looks HORRIBLE when rotated... dunno why
55
- w.blit w.body_img, x, y, 0, AA
46
+ w.blit w.body_img, x, y
56
47
  end
57
48
 
58
49
  def turn_towards_goal
@@ -68,7 +59,7 @@ class Person < Graphics::Body
68
59
  end
69
60
 
70
61
  def collide_with? other
71
- w.cmap.collision_check(x, y, w.cmap, other.x, other.y) != nil
62
+ w.cmap.check(x, y, w.cmap, other.x, other.y) != nil
72
63
  end
73
64
 
74
65
  def collide
@@ -0,0 +1,197 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # srand 42
4
+
5
+ require "graphics"
6
+ require "graphics/trail"
7
+
8
+ class Person < Graphics::Body
9
+ COUNT = 40
10
+
11
+ D_A = 5.0
12
+ D_M = 0.25
13
+ M_M = 5.0
14
+
15
+ VISIBILITY = 100
16
+ ATTACK_DISTANCE = 6 * 2
17
+ VISIBILITY_SQ = VISIBILITY**2
18
+ ATTACK_DISTANCE_SQ = ATTACK_DISTANCE**2
19
+
20
+ attr_accessor :attack, :debug
21
+ alias attack? attack
22
+ alias debug? debug
23
+
24
+ def initialize w
25
+ super
26
+
27
+ self.a = random_angle
28
+ self.ga = random_angle
29
+ self.attack = false
30
+ self.debug = false
31
+ end
32
+
33
+ def update
34
+ return update_attack if attack?
35
+
36
+ normal_update
37
+ end
38
+
39
+ def normal_update
40
+ turn_towards_goal
41
+ possibly_change_goal
42
+
43
+ # accelerate
44
+ # move
45
+
46
+ wrap
47
+ end
48
+
49
+ def near? p
50
+ distance_to_squared(p) < VISIBILITY_SQ
51
+ end
52
+
53
+ def visible? o
54
+ pa = self.angle_to o
55
+ da = (pa - self.a + 90).degrees
56
+ da.between?(75, 150)
57
+ end
58
+
59
+ def nearby
60
+ @nearby ||= begin
61
+ all_but_me = w.ps.reject(&:attack?)
62
+ nearby = all_but_me.find_all { |p| self.near? p }
63
+ visible = nearby.select { |p| self.visible? p }
64
+ visible.sort_by { |p| self.distance_to_squared(p) }
65
+ end
66
+ end
67
+
68
+ def update_attack
69
+ @nearby = nil
70
+
71
+ nearby.each do |p|
72
+ dist = self.distance_to_squared(p)
73
+
74
+ if dist <= ATTACK_DISTANCE_SQ then
75
+ p.kill
76
+ else
77
+ self.ga = self.angle_to(nearby.first)
78
+ end
79
+ end
80
+
81
+ normal_update
82
+ end
83
+
84
+ def kill
85
+ w.ps.delete self unless attack?
86
+ end
87
+
88
+ def accelerate
89
+ max = attack ? 1.1 * M_M : M_M
90
+ self.m += D_M unless m >= max
91
+ end
92
+
93
+ def draw
94
+ if debug? and attack? then
95
+ w.angle x, y, a-75, VISIBILITY, :yellow
96
+ w.angle x, y, a-25, VISIBILITY, :yellow
97
+ w.angle x, y, a+25, VISIBILITY, :yellow
98
+ w.angle x, y, a+75, VISIBILITY, :yellow
99
+ nearby.each do |o|
100
+ w.line x, y, o.x, o.y, :yellow
101
+ end
102
+ # sleep 0.25 unless nearby.empty?
103
+ end
104
+
105
+ w.angle x, y, a, 20, :green
106
+ w.angle x, y, ga, 10, :red
107
+
108
+ # the blit looks HORRIBLE when rotated... dunno why
109
+ w.blit w.body_img, x, y
110
+ w.circle x, y, 5, :red, :filled if attack?
111
+ end
112
+
113
+ def turn_towards_goal
114
+ turn a.relative_angle(ga, D_A)
115
+ end
116
+
117
+ def change_goal
118
+ self.ga = (a + random_turn(180)).degrees
119
+ end
120
+
121
+ def possibly_change_goal
122
+ close = ga.close_to?(a)
123
+ change = close && 1 =~ 25
124
+ change_goal if change
125
+ end
126
+
127
+ def collide_with? other
128
+ w.cmap.check(x, y, w.cmap, other.x, other.y) != nil
129
+ end
130
+
131
+ def collide b
132
+ return b.kill if self.attack?
133
+ self.a = (a + 180).degrees
134
+ change_goal
135
+ end
136
+ end
137
+
138
+ class WalkerSimulation < Graphics::Simulation
139
+ attr_accessor :ps, :body_img, :cmap
140
+
141
+ def initialize
142
+ super 850, 850, 16, "Walker"
143
+
144
+ self.ps = populate Person, 2
145
+
146
+ # 5.times do |n|
147
+ # ps[n].attack = true
148
+ # end
149
+
150
+ ps[0].debug = true
151
+ ps[0].attack = true
152
+
153
+ ps.first.x = w/2
154
+ ps.first.y = h/2
155
+ ps.first.a = 90
156
+ ps.first.ga = 90
157
+
158
+ ps.last.x = w/2 + 50
159
+ ps.last.y = h/2 + 50
160
+ ps.last.a = 0
161
+ ps.last.ga = 0
162
+
163
+ self.body_img = sprite 20, 20 do
164
+ circle 10, 10, 5, :white, :filled
165
+ end
166
+
167
+ self.cmap = body_img.make_collision_map
168
+ end
169
+
170
+ def update n
171
+ ps.each(&:update)
172
+ detect_collisions(ps).each do |a, b|
173
+ a.collide b
174
+ end
175
+
176
+ exit if ps.all?(&:attack?)
177
+ end
178
+
179
+ def draw n
180
+ clear
181
+
182
+ ps.each(&:draw)
183
+
184
+ debug "#{ps.size}"
185
+ fps n
186
+ end
187
+
188
+ def detect_collisions sprites
189
+ collisions = []
190
+ sprites.combination(2).each do |a, b|
191
+ collisions << [a, b] if a.collide_with? b
192
+ end
193
+ collisions
194
+ end
195
+ end
196
+
197
+ WalkerSimulation.new.run