summaryrefslogtreecommitdiffhomepage
path: root/samples/13_path_finding_algorithms/08_a_star
diff options
context:
space:
mode:
Diffstat (limited to 'samples/13_path_finding_algorithms/08_a_star')
-rw-r--r--samples/13_path_finding_algorithms/08_a_star/app/main.rb258
-rw-r--r--samples/13_path_finding_algorithms/08_a_star/replay.txt434
2 files changed, 563 insertions, 129 deletions
diff --git a/samples/13_path_finding_algorithms/08_a_star/app/main.rb b/samples/13_path_finding_algorithms/08_a_star/app/main.rb
index e9fcb8c..eaf7e09 100644
--- a/samples/13_path_finding_algorithms/08_a_star/app/main.rb
+++ b/samples/13_path_finding_algorithms/08_a_star/app/main.rb
@@ -11,8 +11,8 @@ class A_Star_Algorithm
def tick
defaults
- render
- input
+ render
+ input
if dijkstra.came_from.empty?
calc_searches
@@ -65,7 +65,7 @@ class A_Star_Algorithm
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- state.user_input ||= :none
+ state.user_input ||= :none
# These variables allow the breadth first search to take place
# Came_from is a hash with a key of a cell and a value of the cell that was expanded from to find the key.
@@ -143,7 +143,7 @@ class A_Star_Algorithm
# If the mouse was clicked this tick
if inputs.mouse.down
# Determine what the user is editing and appropriately edit the state.user_input variable
- determine_input
+ determine_input
end
# Process user input based on user_input variable and current mouse position
@@ -154,51 +154,51 @@ class A_Star_Algorithm
# This method is called when the mouse is clicked down
def determine_input
# If the mouse is over the star in the first grid
- if dijkstra_mouse_over_star?
+ if dijkstra_mouse_over_star?
# The user is editing the star from the first grid
- state.user_input = :dijkstra_star
+ state.user_input = :dijkstra_star
# If the mouse is over the star in the second grid
- elsif greedy_mouse_over_star?
+ elsif greedy_mouse_over_star?
# The user is editing the star from the second grid
- state.user_input = :greedy_star
+ state.user_input = :greedy_star
# If the mouse is over the star in the third grid
- elsif a_star_mouse_over_star?
+ elsif a_star_mouse_over_star?
# The user is editing the star from the third grid
- state.user_input = :a_star_star
+ state.user_input = :a_star_star
# If the mouse is over the target in the first grid
- elsif dijkstra_mouse_over_target?
+ elsif dijkstra_mouse_over_target?
# The user is editing the target from the first grid
- state.user_input = :dijkstra_target
+ state.user_input = :dijkstra_target
# If the mouse is over the target in the second grid
- elsif greedy_mouse_over_target?
+ elsif greedy_mouse_over_target?
# The user is editing the target from the second grid
- state.user_input = :greedy_target
+ state.user_input = :greedy_target
# If the mouse is over the target in the third grid
- elsif a_star_mouse_over_target?
+ elsif a_star_mouse_over_target?
# The user is editing the target from the third grid
- state.user_input = :a_star_target
+ state.user_input = :a_star_target
# If the mouse is over a wall in the first grid
- elsif dijkstra_mouse_over_wall?
+ elsif dijkstra_mouse_over_wall?
# The user is removing a wall from the first grid
- state.user_input = :dijkstra_remove_wall
+ state.user_input = :dijkstra_remove_wall
# If the mouse is over a wall in the second grid
- elsif greedy_mouse_over_wall?
+ elsif greedy_mouse_over_wall?
# The user is removing a wall from the second grid
state.user_input = :greedy_remove_wall
# If the mouse is over a wall in the third grid
- elsif a_star_mouse_over_wall?
+ elsif a_star_mouse_over_wall?
# The user is removing a wall from the third grid
state.user_input = :a_star_remove_wall
# If the mouse is over the first grid
- elsif dijkstra_mouse_over_grid?
+ elsif dijkstra_mouse_over_grid?
# The user is adding a wall from the first grid
state.user_input = :dijkstra_add_wall
# If the mouse is over the second grid
- elsif greedy_mouse_over_grid?
+ elsif greedy_mouse_over_grid?
# The user is adding a wall from the second grid
state.user_input = :greedy_add_wall
# If the mouse is over the third grid
- elsif a_star_mouse_over_grid?
+ elsif a_star_mouse_over_grid?
# The user is adding a wall from the third grid
state.user_input = :a_star_add_wall
end
@@ -206,30 +206,30 @@ class A_Star_Algorithm
# Processes click and drag based on what the user is currently dragging
def process_input
- if state.user_input == :dijkstra_star
- process_input_dijkstra_star
+ if state.user_input == :dijkstra_star
+ process_input_dijkstra_star
elsif state.user_input == :greedy_star
- process_input_greedy_star
+ process_input_greedy_star
elsif state.user_input == :a_star_star
- process_input_a_star_star
- elsif state.user_input == :dijkstra_target
- process_input_dijkstra_target
- elsif state.user_input == :greedy_target
- process_input_greedy_target
- elsif state.user_input == :a_star_target
- process_input_a_star_target
- elsif state.user_input == :dijkstra_remove_wall
- process_input_dijkstra_remove_wall
+ process_input_a_star_star
+ elsif state.user_input == :dijkstra_target
+ process_input_dijkstra_target
+ elsif state.user_input == :greedy_target
+ process_input_greedy_target
+ elsif state.user_input == :a_star_target
+ process_input_a_star_target
+ elsif state.user_input == :dijkstra_remove_wall
+ process_input_dijkstra_remove_wall
elsif state.user_input == :greedy_remove_wall
- process_input_greedy_remove_wall
+ process_input_greedy_remove_wall
elsif state.user_input == :a_star_remove_wall
- process_input_a_star_remove_wall
- elsif state.user_input == :dijkstra_add_wall
- process_input_dijkstra_add_wall
- elsif state.user_input == :greedy_add_wall
- process_input_greedy_add_wall
- elsif state.user_input == :a_star_add_wall
- process_input_a_star_add_wall
+ process_input_a_star_remove_wall
+ elsif state.user_input == :dijkstra_add_wall
+ process_input_dijkstra_add_wall
+ elsif state.user_input == :greedy_add_wall
+ process_input_greedy_add_wall
+ elsif state.user_input == :a_star_add_wall
+ process_input_a_star_add_wall
end
end
@@ -244,7 +244,7 @@ class A_Star_Algorithm
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << dijkstra_horizontal_line(y)
+ outputs.lines << dijkstra_horizontal_line(y)
end
end
@@ -259,7 +259,7 @@ class A_Star_Algorithm
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << greedy_horizontal_line(y)
+ outputs.lines << greedy_horizontal_line(y)
end
end
@@ -274,10 +274,10 @@ class A_Star_Algorithm
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << a_star_horizontal_line(y)
+ outputs.lines << a_star_horizontal_line(y)
end
end
-
+
# Returns a vertical line for a column of the first grid
def dijkstra_vertical_line column
dijkstra_scale_up([column, 0, column, grid.height])
@@ -327,7 +327,7 @@ class A_Star_Algorithm
def render_dijkstra_target
outputs.sprites << [dijkstra_scale_up(grid.target), 'target.png']
end
-
+
# Renders the target on the second grid
def render_greedy_target
outputs.sprites << [greedy_scale_up(grid.target), 'target.png']
@@ -340,21 +340,21 @@ class A_Star_Algorithm
# Renders the walls on the first grid
def render_dijkstra_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [dijkstra_scale_up(wall), wall_color]
end
end
# Renders the walls on the second grid
def render_greedy_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [greedy_scale_up(wall), wall_color]
end
end
# Renders the walls on the third grid
def render_a_star_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [a_star_scale_up(wall), wall_color]
end
end
@@ -554,12 +554,12 @@ class A_Star_Algorithm
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_dijkstra_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless dijkstra_cell_closest_to_mouse == grid.target
- grid.star = dijkstra_cell_closest_to_mouse
+ grid.star = dijkstra_cell_closest_to_mouse
end
- unless old_star == grid.star
- reset_searches
+ unless old_star == grid.star
+ reset_searches
end
end
@@ -567,12 +567,12 @@ class A_Star_Algorithm
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_greedy_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless greedy_cell_closest_to_mouse == grid.target
grid.star = greedy_cell_closest_to_mouse
end
- unless old_star == grid.star
- reset_searches
+ unless old_star == grid.star
+ reset_searches
end
end
@@ -580,12 +580,12 @@ class A_Star_Algorithm
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_a_star_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless a_star_cell_closest_to_mouse == grid.target
grid.star = a_star_cell_closest_to_mouse
end
- unless old_star == grid.star
- reset_searches
+ unless old_star == grid.star
+ reset_searches
end
end
@@ -593,12 +593,12 @@ class A_Star_Algorithm
# Only reset_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_dijkstra_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless dijkstra_cell_closest_to_mouse == grid.star
grid.target = dijkstra_cell_closest_to_mouse
end
- unless old_target == grid.target
- reset_searches
+ unless old_target == grid.target
+ reset_searches
end
end
@@ -606,12 +606,12 @@ class A_Star_Algorithm
# Only reset_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_greedy_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless greedy_cell_closest_to_mouse == grid.star
grid.target = greedy_cell_closest_to_mouse
end
- unless old_target == grid.target
- reset_searches
+ unless old_target == grid.target
+ reset_searches
end
end
@@ -619,12 +619,12 @@ class A_Star_Algorithm
# Only reset_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_a_star_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless a_star_cell_closest_to_mouse == grid.star
grid.target = a_star_cell_closest_to_mouse
end
- unless old_target == grid.target
- reset_searches
+ unless old_target == grid.target
+ reset_searches
end
end
@@ -633,10 +633,10 @@ class A_Star_Algorithm
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if dijkstra_mouse_over_grid?
+ if dijkstra_mouse_over_grid?
if grid.walls.has_key?(dijkstra_cell_closest_to_mouse)
- grid.walls.delete(dijkstra_cell_closest_to_mouse)
- reset_searches
+ grid.walls.delete(dijkstra_cell_closest_to_mouse)
+ reset_searches
end
end
end
@@ -646,10 +646,10 @@ class A_Star_Algorithm
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if greedy_mouse_over_grid?
+ if greedy_mouse_over_grid?
if grid.walls.has_key?(greedy_cell_closest_to_mouse)
- grid.walls.delete(greedy_cell_closest_to_mouse)
- reset_searches
+ grid.walls.delete(greedy_cell_closest_to_mouse)
+ reset_searches
end
end
end
@@ -659,40 +659,40 @@ class A_Star_Algorithm
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if a_star_mouse_over_grid?
+ if a_star_mouse_over_grid?
if grid.walls.has_key?(a_star_cell_closest_to_mouse)
- grid.walls.delete(a_star_cell_closest_to_mouse)
- reset_searches
+ grid.walls.delete(a_star_cell_closest_to_mouse)
+ reset_searches
end
end
end
# Adds a wall in the first grid in the cell the mouse is over
def process_input_dijkstra_add_wall
- if dijkstra_mouse_over_grid?
+ if dijkstra_mouse_over_grid?
unless grid.walls.has_key?(dijkstra_cell_closest_to_mouse)
- grid.walls[dijkstra_cell_closest_to_mouse] = true
- reset_searches
+ grid.walls[dijkstra_cell_closest_to_mouse] = true
+ reset_searches
end
end
end
# Adds a wall in the second grid in the cell the mouse is over
def process_input_greedy_add_wall
- if greedy_mouse_over_grid?
+ if greedy_mouse_over_grid?
unless grid.walls.has_key?(greedy_cell_closest_to_mouse)
- grid.walls[greedy_cell_closest_to_mouse] = true
- reset_searches
+ grid.walls[greedy_cell_closest_to_mouse] = true
+ reset_searches
end
end
end
# Adds a wall in the third grid in the cell the mouse is over
def process_input_a_star_add_wall
- if a_star_mouse_over_grid?
+ if a_star_mouse_over_grid?
unless grid.walls.has_key?(a_star_cell_closest_to_mouse)
- grid.walls[a_star_cell_closest_to_mouse] = true
- reset_searches
+ grid.walls[a_star_cell_closest_to_mouse] = true
+ reset_searches
end
end
end
@@ -702,13 +702,13 @@ class A_Star_Algorithm
# Finding the cell closest to the mouse helps with this
def dijkstra_cell_closest_to_mouse
# Closest cell to the mouse in the first grid
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -716,17 +716,17 @@ class A_Star_Algorithm
# Finding the cell closest to the mouse in the second grid helps with this
def greedy_cell_closest_to_mouse
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= grid.width + 1
# Bound x and y to the first grid
x = 0 if x < 0
y = 0 if y < 0
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -734,17 +734,17 @@ class A_Star_Algorithm
# Finding the cell closest to the mouse in the third grid helps with this
def a_star_cell_closest_to_mouse
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= (grid.width + 1) * 2
# Bound x and y to the first grid
x = 0 if x < 0
y = 0 if y < 0
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
def reset_searches
@@ -772,21 +772,21 @@ class A_Star_Algorithm
def calc_dijkstra
# Sets up the search to begin from the star
- dijkstra.frontier << grid.star
- dijkstra.came_from[grid.star] = nil
- dijkstra.cost_so_far[grid.star] = 0
+ dijkstra.frontier << grid.star
+ dijkstra.came_from[grid.star] = nil
+ dijkstra.cost_so_far[grid.star] = 0
# Until the target is found or there are no more cells to explore from
until dijkstra.came_from.has_key?(grid.target) or dijkstra.frontier.empty?
# Take the next frontier cell. The first element is the cell, the second is the priority.
new_frontier = dijkstra.frontier.shift#[0]
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do | neighbor |
+ adjacent_neighbors(new_frontier).each do | neighbor |
# That have not been visited and are not walls
- unless dijkstra.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
+ unless dijkstra.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
dijkstra.frontier << neighbor
- dijkstra.came_from[neighbor] = new_frontier
+ dijkstra.came_from[neighbor] = new_frontier
dijkstra.cost_so_far[neighbor] = dijkstra.cost_so_far[new_frontier] + 1
end
end
@@ -807,20 +807,20 @@ class A_Star_Algorithm
def calc_greedy
# Sets up the search to begin from the star
- greedy.frontier << grid.star
- greedy.came_from[grid.star] = nil
+ greedy.frontier << grid.star
+ greedy.came_from[grid.star] = nil
# Until the target is found or there are no more cells to explore from
until greedy.came_from.has_key?(grid.target) or greedy.frontier.empty?
# Take the next frontier cell
- new_frontier = greedy.frontier.shift
+ new_frontier = greedy.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do | neighbor |
+ adjacent_neighbors(new_frontier).each do | neighbor |
# That have not been visited and are not walls
- unless greedy.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
+ unless greedy.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- greedy.frontier << neighbor
- greedy.came_from[neighbor] = new_frontier
+ greedy.frontier << neighbor
+ greedy.came_from[neighbor] = new_frontier
end
end
# Sort the frontier so that cells that are in a zigzag pattern are prioritized over those in an line
@@ -850,12 +850,12 @@ class A_Star_Algorithm
current_frontier = a_star.frontier.shift
# For each of that cells neighbors
- adjacent_neighbors(current_frontier).each do | neighbor |
+ adjacent_neighbors(current_frontier).each do | neighbor |
# That have not been visited and are not walls
- unless a_star.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
+ unless a_star.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- a_star.frontier << neighbor
- a_star.came_from[neighbor] = current_frontier
+ a_star.frontier << neighbor
+ a_star.came_from[neighbor] = current_frontier
a_star.cost_so_far[neighbor] = a_star.cost_so_far[current_frontier] + 1
end
end
@@ -937,16 +937,16 @@ class A_Star_Algorithm
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
# Gets all the valid neighbors into the array
# From southern neighbor, clockwise
- neighbors << [cell.x , cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
- neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
+ neighbors << [cell.x , cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
+ neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
- neighbors
+ neighbors
end
# Finds the vertical and horizontal distance of a cell from the star
@@ -991,11 +991,11 @@ class A_Star_Algorithm
def wall_color
[134, 134, 120] # Camo Green
end
-
+
def visited_color
[204, 191, 179] # Dark Brown
end
-
+
def path_color
[231, 230, 228] # Pastel White
end
@@ -1018,7 +1018,7 @@ def tick args
end
# Every tick, new args are passed, and the Breadth First Search tick is called
- $a_star_algorithm ||= A_Star_Algorithm.new(args)
+ $a_star_algorithm ||= A_Star_Algorithm.new
$a_star_algorithm.args = args
$a_star_algorithm.tick
end
diff --git a/samples/13_path_finding_algorithms/08_a_star/replay.txt b/samples/13_path_finding_algorithms/08_a_star/replay.txt
new file mode 100644
index 0000000..001a564
--- /dev/null
+++ b/samples/13_path_finding_algorithms/08_a_star/replay.txt
@@ -0,0 +1,434 @@
+replay_version 2.0
+stopped_at 341
+seed 100
+recorded_at 2021-11-20 11:24:45 -0600
+[:mouse_button_up, 1, 0, 1, 1, 1]
+[:mouse_move, 769, 97, 2, 2, 8]
+[:mouse_move, 763, 101, 2, 3, 8]
+[:mouse_move, 755, 109, 2, 4, 8]
+[:mouse_move, 748, 123, 2, 5, 8]
+[:mouse_move, 746, 148, 2, 6, 9]
+[:mouse_move, 742, 180, 2, 7, 9]
+[:mouse_move, 733, 215, 2, 8, 9]
+[:mouse_move, 719, 278, 2, 9, 9]
+[:mouse_move, 712, 336, 2, 10, 9]
+[:mouse_move, 701, 397, 2, 11, 10]
+[:mouse_move, 685, 440, 2, 12, 10]
+[:mouse_move, 667, 472, 2, 13, 10]
+[:mouse_move, 654, 493, 2, 14, 10]
+[:mouse_move, 644, 506, 2, 15, 11]
+[:mouse_move, 637, 514, 2, 16, 11]
+[:mouse_move, 635, 516, 2, 17, 11]
+[:mouse_move, 634, 517, 2, 18, 11]
+[:mouse_move, 630, 518, 2, 19, 12]
+[:mouse_move, 624, 524, 2, 20, 12]
+[:mouse_move, 619, 537, 2, 21, 12]
+[:mouse_move, 612, 553, 2, 22, 13]
+[:mouse_move, 609, 561, 2, 23, 13]
+[:mouse_move, 608, 565, 2, 24, 13]
+[:mouse_move, 613, 565, 2, 25, 14]
+[:mouse_move, 627, 565, 2, 26, 14]
+[:mouse_move, 641, 565, 2, 27, 14]
+[:mouse_move, 654, 565, 2, 28, 14]
+[:mouse_move, 658, 565, 2, 29, 15]
+[:mouse_move, 659, 565, 2, 30, 15]
+[:mouse_move, 662, 565, 2, 31, 15]
+[:mouse_move, 667, 566, 2, 32, 15]
+[:mouse_move, 671, 566, 2, 33, 16]
+[:mouse_move, 676, 566, 2, 34, 16]
+[:mouse_move, 685, 566, 2, 35, 16]
+[:mouse_move, 701, 565, 2, 36, 16]
+[:mouse_move, 719, 562, 2, 37, 17]
+[:mouse_move, 731, 560, 2, 38, 17]
+[:mouse_move, 744, 559, 2, 39, 17]
+[:mouse_move, 750, 559, 2, 40, 17]
+[:mouse_move, 757, 559, 2, 41, 17]
+[:mouse_move, 763, 559, 2, 42, 17]
+[:mouse_move, 767, 559, 2, 43, 18]
+[:mouse_move, 769, 559, 2, 44, 18]
+[:mouse_move, 770, 558, 2, 45, 18]
+[:mouse_move, 774, 557, 2, 46, 18]
+[:mouse_move, 784, 555, 2, 47, 18]
+[:mouse_move, 796, 551, 2, 48, 19]
+[:mouse_move, 804, 550, 2, 49, 19]
+[:mouse_move, 810, 548, 2, 50, 19]
+[:mouse_move, 814, 547, 2, 51, 20]
+[:mouse_move, 817, 547, 2, 52, 20]
+[:mouse_move, 818, 547, 2, 53, 20]
+[:mouse_move, 819, 547, 2, 54, 20]
+[:mouse_move, 819, 546, 2, 55, 20]
+[:mouse_move, 819, 545, 2, 56, 20]
+[:mouse_move, 820, 545, 2, 57, 21]
+[:mouse_move, 820, 544, 2, 58, 21]
+[:mouse_move, 820, 543, 2, 59, 21]
+[:mouse_move, 820, 542, 2, 60, 22]
+[:mouse_move, 820, 541, 2, 61, 22]
+[:mouse_move, 820, 540, 2, 62, 23]
+[:mouse_move, 819, 540, 2, 63, 23]
+[:mouse_button_pressed, 1, 0, 1, 64, 24]
+[:mouse_button_up, 1, 0, 1, 65, 25]
+[:mouse_move, 820, 540, 2, 66, 29]
+[:mouse_move, 820, 541, 2, 67, 29]
+[:mouse_move, 820, 542, 2, 68, 29]
+[:mouse_move, 820, 543, 2, 69, 30]
+[:mouse_move, 819, 543, 2, 70, 31]
+[:mouse_move, 818, 543, 2, 71, 31]
+[:mouse_move, 817, 542, 2, 72, 31]
+[:mouse_move, 816, 542, 2, 73, 32]
+[:mouse_move, 812, 542, 2, 74, 32]
+[:mouse_move, 808, 542, 2, 75, 32]
+[:mouse_move, 802, 542, 2, 76, 33]
+[:mouse_move, 796, 542, 2, 77, 33]
+[:mouse_move, 790, 542, 2, 78, 33]
+[:mouse_move, 784, 540, 2, 79, 33]
+[:mouse_move, 783, 540, 2, 80, 34]
+[:mouse_move, 782, 538, 2, 81, 34]
+[:mouse_move, 782, 533, 2, 82, 34]
+[:mouse_move, 785, 525, 2, 83, 34]
+[:mouse_move, 788, 512, 2, 84, 34]
+[:mouse_move, 791, 494, 2, 85, 35]
+[:mouse_move, 791, 469, 2, 86, 35]
+[:mouse_move, 785, 442, 2, 87, 35]
+[:mouse_move, 776, 417, 2, 88, 35]
+[:mouse_move, 767, 398, 2, 89, 36]
+[:mouse_move, 759, 381, 2, 90, 36]
+[:mouse_move, 747, 365, 2, 91, 36]
+[:mouse_move, 737, 356, 2, 92, 36]
+[:mouse_move, 718, 345, 2, 93, 36]
+[:mouse_move, 702, 337, 2, 94, 37]
+[:mouse_move, 693, 333, 2, 95, 37]
+[:mouse_move, 689, 331, 2, 96, 37]
+[:mouse_move, 688, 331, 2, 97, 38]
+[:mouse_move, 687, 331, 2, 98, 38]
+[:mouse_move, 686, 342, 2, 99, 38]
+[:mouse_move, 684, 352, 2, 100, 39]
+[:mouse_move, 682, 359, 2, 101, 39]
+[:mouse_move, 682, 362, 2, 102, 39]
+[:mouse_move, 682, 364, 2, 103, 40]
+[:mouse_move, 683, 364, 2, 104, 40]
+[:mouse_move, 686, 364, 2, 105, 40]
+[:mouse_move, 688, 363, 2, 106, 40]
+[:mouse_move, 692, 362, 2, 107, 40]
+[:mouse_move, 698, 362, 2, 108, 41]
+[:mouse_move, 702, 362, 2, 109, 41]
+[:mouse_move, 705, 362, 2, 110, 41]
+[:mouse_move, 706, 362, 2, 111, 42]
+[:mouse_move, 706, 361, 2, 112, 42]
+[:mouse_move, 707, 361, 2, 113, 42]
+[:mouse_move, 708, 360, 2, 114, 42]
+[:mouse_move, 709, 359, 2, 115, 43]
+[:mouse_move, 709, 358, 2, 116, 43]
+[:mouse_move, 710, 358, 2, 117, 43]
+[:mouse_button_pressed, 1, 0, 1, 118, 44]
+[:mouse_button_up, 1, 0, 1, 119, 45]
+[:mouse_move, 710, 357, 2, 120, 56]
+[:mouse_move, 713, 357, 2, 121, 56]
+[:mouse_move, 715, 357, 2, 122, 57]
+[:mouse_move, 716, 357, 2, 123, 57]
+[:mouse_move, 717, 357, 2, 124, 57]
+[:mouse_move, 719, 357, 2, 125, 58]
+[:mouse_move, 720, 357, 2, 126, 58]
+[:mouse_move, 720, 356, 2, 127, 59]
+[:mouse_move, 721, 356, 2, 128, 59]
+[:mouse_move, 723, 356, 2, 129, 59]
+[:mouse_move, 724, 356, 2, 130, 59]
+[:mouse_move, 727, 356, 2, 131, 59]
+[:mouse_move, 728, 356, 2, 132, 59]
+[:mouse_move, 730, 356, 2, 133, 60]
+[:mouse_move, 731, 355, 2, 134, 60]
+[:mouse_move, 732, 355, 2, 135, 60]
+[:mouse_move, 734, 355, 2, 136, 60]
+[:mouse_move, 735, 355, 2, 137, 60]
+[:mouse_button_pressed, 1, 0, 1, 138, 62]
+[:mouse_move, 737, 358, 2, 139, 63]
+[:mouse_move, 739, 364, 2, 140, 63]
+[:mouse_move, 739, 372, 2, 141, 63]
+[:mouse_move, 739, 381, 2, 142, 64]
+[:mouse_move, 740, 390, 2, 143, 64]
+[:mouse_move, 742, 403, 2, 144, 64]
+[:mouse_move, 744, 415, 2, 145, 64]
+[:mouse_move, 744, 426, 2, 146, 64]
+[:mouse_move, 745, 438, 2, 147, 64]
+[:mouse_move, 746, 445, 2, 148, 64]
+[:mouse_move, 747, 449, 2, 149, 64]
+[:mouse_move, 747, 450, 2, 150, 64]
+[:mouse_move, 747, 451, 2, 151, 64]
+[:mouse_move, 748, 452, 2, 152, 64]
+[:mouse_move, 749, 452, 2, 153, 64]
+[:mouse_move, 750, 452, 2, 154, 64]
+[:mouse_move, 751, 452, 2, 155, 64]
+[:mouse_move, 753, 454, 2, 156, 64]
+[:mouse_move, 754, 455, 2, 157, 64]
+[:mouse_move, 756, 456, 2, 158, 64]
+[:mouse_move, 759, 459, 2, 159, 64]
+[:mouse_move, 765, 465, 2, 160, 64]
+[:mouse_move, 769, 469, 2, 161, 64]
+[:mouse_move, 773, 474, 2, 162, 64]
+[:mouse_move, 776, 479, 2, 163, 64]
+[:mouse_move, 781, 486, 2, 164, 64]
+[:mouse_move, 782, 490, 2, 165, 65]
+[:mouse_move, 783, 494, 2, 166, 65]
+[:mouse_move, 783, 498, 2, 167, 65]
+[:mouse_move, 784, 506, 2, 168, 65]
+[:mouse_move, 786, 515, 2, 169, 65]
+[:mouse_move, 789, 526, 2, 170, 65]
+[:mouse_move, 791, 534, 2, 171, 65]
+[:mouse_move, 795, 549, 2, 172, 65]
+[:mouse_move, 798, 556, 2, 173, 65]
+[:mouse_move, 799, 561, 2, 174, 65]
+[:mouse_move, 799, 564, 2, 175, 65]
+[:mouse_move, 801, 570, 2, 176, 65]
+[:mouse_move, 802, 577, 2, 177, 65]
+[:mouse_move, 804, 583, 2, 178, 65]
+[:mouse_move, 804, 587, 2, 179, 65]
+[:mouse_move, 805, 590, 2, 180, 65]
+[:mouse_move, 807, 594, 2, 181, 65]
+[:mouse_move, 809, 598, 2, 182, 65]
+[:mouse_move, 811, 601, 2, 183, 65]
+[:mouse_move, 812, 602, 2, 184, 65]
+[:mouse_move, 812, 603, 2, 185, 65]
+[:mouse_move, 813, 604, 2, 186, 65]
+[:mouse_move, 814, 604, 2, 187, 65]
+[:mouse_move, 817, 599, 2, 188, 65]
+[:mouse_move, 819, 595, 2, 189, 65]
+[:mouse_move, 820, 594, 2, 190, 65]
+[:mouse_move, 819, 594, 2, 191, 77]
+[:mouse_button_up, 1, 0, 1, 192, 77]
+[:mouse_move, 818, 594, 2, 193, 77]
+[:mouse_move, 817, 594, 2, 194, 78]
+[:mouse_move, 816, 594, 2, 195, 79]
+[:mouse_move, 815, 593, 2, 196, 109]
+[:mouse_move, 812, 592, 2, 197, 109]
+[:mouse_move, 808, 592, 2, 198, 109]
+[:mouse_move, 799, 591, 2, 199, 109]
+[:mouse_move, 780, 588, 2, 200, 110]
+[:mouse_move, 758, 584, 2, 201, 110]
+[:mouse_move, 738, 584, 2, 202, 110]
+[:mouse_move, 724, 584, 2, 203, 110]
+[:mouse_move, 710, 584, 2, 204, 110]
+[:mouse_move, 691, 583, 2, 205, 111]
+[:mouse_move, 668, 579, 2, 206, 111]
+[:mouse_move, 647, 577, 2, 207, 111]
+[:mouse_move, 630, 577, 2, 208, 111]
+[:mouse_move, 610, 577, 2, 209, 112]
+[:mouse_move, 602, 577, 2, 210, 112]
+[:mouse_move, 597, 576, 2, 211, 112]
+[:mouse_move, 595, 575, 2, 212, 112]
+[:mouse_move, 603, 575, 2, 213, 114]
+[:mouse_move, 626, 575, 2, 214, 114]
+[:mouse_move, 651, 575, 2, 215, 114]
+[:mouse_move, 680, 579, 2, 216, 114]
+[:mouse_move, 723, 583, 2, 217, 114]
+[:mouse_move, 745, 585, 2, 218, 114]
+[:mouse_move, 756, 585, 2, 219, 115]
+[:mouse_move, 758, 585, 2, 220, 115]
+[:mouse_move, 759, 585, 2, 221, 115]
+[:mouse_move, 760, 584, 2, 222, 115]
+[:mouse_move, 761, 584, 2, 223, 116]
+[:mouse_move, 764, 584, 2, 224, 116]
+[:mouse_move, 767, 584, 2, 225, 116]
+[:mouse_move, 769, 584, 2, 226, 116]
+[:mouse_move, 773, 584, 2, 227, 117]
+[:mouse_move, 791, 588, 2, 228, 117]
+[:mouse_move, 803, 596, 2, 229, 117]
+[:mouse_move, 807, 599, 2, 230, 118]
+[:mouse_move, 808, 599, 2, 231, 118]
+[:mouse_move, 809, 599, 2, 232, 119]
+[:mouse_move, 812, 599, 2, 233, 120]
+[:mouse_move, 813, 599, 2, 234, 120]
+[:mouse_move, 814, 599, 2, 235, 120]
+[:mouse_move, 815, 599, 2, 236, 122]
+[:mouse_move, 816, 598, 2, 237, 122]
+[:mouse_move, 817, 598, 2, 238, 123]
+[:mouse_button_pressed, 1, 0, 1, 239, 123]
+[:mouse_move, 805, 598, 2, 240, 124]
+[:mouse_move, 777, 598, 2, 241, 124]
+[:mouse_move, 748, 598, 2, 242, 124]
+[:mouse_move, 722, 598, 2, 243, 124]
+[:mouse_move, 692, 598, 2, 244, 124]
+[:mouse_move, 668, 598, 2, 245, 124]
+[:mouse_move, 648, 598, 2, 246, 125]
+[:mouse_move, 624, 598, 2, 247, 125]
+[:mouse_move, 615, 598, 2, 248, 125]
+[:mouse_move, 610, 598, 2, 249, 125]
+[:mouse_move, 609, 598, 2, 250, 125]
+[:mouse_move, 607, 598, 2, 251, 125]
+[:mouse_move, 606, 598, 2, 252, 125]
+[:mouse_move, 604, 595, 2, 253, 127]
+[:mouse_move, 598, 590, 2, 254, 128]
+[:mouse_move, 592, 584, 2, 255, 128]
+[:mouse_move, 588, 581, 2, 256, 129]
+[:mouse_move, 588, 580, 2, 257, 129]
+[:mouse_move, 587, 580, 2, 258, 129]
+[:mouse_move, 586, 579, 2, 259, 130]
+[:mouse_move, 585, 579, 2, 260, 130]
+[:mouse_move, 584, 578, 2, 261, 131]
+[:mouse_move, 584, 577, 2, 262, 131]
+[:mouse_move, 584, 576, 2, 263, 132]
+[:mouse_move, 583, 576, 2, 264, 133]
+[:mouse_move, 584, 576, 2, 265, 135]
+[:mouse_button_up, 1, 0, 1, 266, 147]
+[:mouse_move, 585, 575, 2, 267, 153]
+[:mouse_move, 585, 571, 2, 268, 196]
+[:mouse_move, 585, 568, 2, 269, 197]
+[:mouse_move, 586, 563, 2, 270, 197]
+[:mouse_move, 587, 558, 2, 271, 197]
+[:mouse_move, 587, 557, 2, 272, 198]
+[:mouse_move, 587, 555, 2, 273, 199]
+[:mouse_move, 588, 555, 2, 274, 200]
+[:mouse_move, 588, 554, 2, 275, 200]
+[:mouse_move, 588, 550, 2, 276, 235]
+[:mouse_move, 594, 541, 2, 277, 236]
+[:mouse_move, 605, 525, 2, 278, 236]
+[:mouse_move, 622, 502, 2, 279, 236]
+[:mouse_move, 654, 458, 2, 280, 237]
+[:mouse_move, 672, 425, 2, 281, 237]
+[:mouse_move, 682, 391, 2, 282, 238]
+[:mouse_move, 688, 358, 2, 283, 239]
+[:mouse_move, 692, 333, 2, 284, 239]
+[:mouse_move, 694, 319, 2, 285, 239]
+[:mouse_move, 697, 308, 2, 286, 240]
+[:mouse_move, 698, 303, 2, 287, 240]
+[:mouse_move, 700, 299, 2, 288, 241]
+[:mouse_move, 702, 295, 2, 289, 241]
+[:mouse_move, 703, 291, 2, 290, 242]
+[:mouse_move, 704, 289, 2, 291, 242]
+[:mouse_move, 705, 288, 2, 292, 243]
+[:mouse_move, 706, 288, 2, 293, 245]
+[:mouse_move, 706, 291, 2, 294, 246]
+[:mouse_move, 706, 294, 2, 295, 246]
+[:mouse_move, 706, 298, 2, 296, 247]
+[:mouse_move, 706, 303, 2, 297, 247]
+[:mouse_move, 707, 308, 2, 298, 247]
+[:mouse_move, 709, 315, 2, 299, 248]
+[:mouse_move, 710, 321, 2, 300, 248]
+[:mouse_move, 711, 324, 2, 301, 249]
+[:mouse_move, 711, 325, 2, 302, 249]
+[:mouse_move, 712, 325, 2, 303, 250]
+[:mouse_move, 713, 325, 2, 304, 252]
+[:mouse_move, 713, 324, 2, 305, 252]
+[:mouse_move, 714, 324, 2, 306, 253]
+[:mouse_button_pressed, 1, 0, 1, 307, 254]
+[:mouse_button_up, 1, 0, 1, 308, 255]
+[:mouse_move, 714, 325, 2, 309, 263]
+[:mouse_move, 714, 331, 2, 310, 263]
+[:mouse_move, 714, 344, 2, 311, 264]
+[:mouse_move, 714, 365, 2, 312, 264]
+[:mouse_move, 710, 394, 2, 313, 264]
+[:mouse_move, 696, 432, 2, 314, 265]
+[:mouse_move, 678, 472, 2, 315, 265]
+[:mouse_move, 654, 506, 2, 316, 266]
+[:mouse_move, 637, 532, 2, 317, 267]
+[:mouse_move, 624, 549, 2, 318, 267]
+[:mouse_move, 615, 559, 2, 319, 267]
+[:mouse_move, 612, 562, 2, 320, 268]
+[:mouse_move, 609, 563, 2, 321, 268]
+[:mouse_move, 608, 564, 2, 322, 269]
+[:mouse_move, 606, 566, 2, 323, 269]
+[:mouse_move, 606, 568, 2, 324, 270]
+[:mouse_move, 606, 572, 2, 325, 270]
+[:mouse_move, 606, 573, 2, 326, 271]
+[:mouse_move, 606, 574, 2, 327, 271]
+[:mouse_move, 605, 573, 2, 328, 273]
+[:mouse_move, 606, 571, 2, 329, 273]
+[:mouse_move, 606, 566, 2, 330, 274]
+[:mouse_move, 606, 565, 2, 331, 274]
+[:mouse_move, 605, 565, 2, 332, 275]
+[:mouse_move, 601, 565, 2, 333, 275]
+[:mouse_move, 593, 565, 2, 334, 276]
+[:mouse_move, 583, 565, 2, 335, 276]
+[:mouse_move, 573, 567, 2, 336, 277]
+[:mouse_move, 570, 567, 2, 337, 278]
+[:mouse_move, 569, 567, 2, 338, 278]
+[:mouse_move, 570, 568, 2, 339, 284]
+[:mouse_move, 572, 568, 2, 340, 284]
+[:mouse_move, 573, 568, 2, 341, 286]
+[:mouse_button_pressed, 1, 0, 1, 342, 290]
+[:mouse_move, 574, 568, 2, 343, 290]
+[:mouse_move, 576, 568, 2, 344, 291]
+[:mouse_move, 586, 564, 2, 345, 292]
+[:mouse_move, 601, 560, 2, 346, 292]
+[:mouse_move, 622, 552, 2, 347, 292]
+[:mouse_move, 648, 544, 2, 348, 293]
+[:mouse_move, 675, 537, 2, 349, 293]
+[:mouse_move, 702, 533, 2, 350, 293]
+[:mouse_move, 726, 530, 2, 351, 293]
+[:mouse_move, 747, 526, 2, 352, 293]
+[:mouse_move, 771, 518, 2, 353, 293]
+[:mouse_move, 786, 514, 2, 354, 293]
+[:mouse_move, 802, 511, 2, 355, 294]
+[:mouse_move, 815, 508, 2, 356, 294]
+[:mouse_move, 827, 505, 2, 357, 294]
+[:mouse_move, 833, 504, 2, 358, 294]
+[:mouse_move, 835, 503, 2, 359, 294]
+[:mouse_move, 832, 503, 2, 360, 294]
+[:mouse_move, 830, 504, 2, 361, 294]
+[:mouse_move, 826, 506, 2, 362, 294]
+[:mouse_move, 822, 508, 2, 363, 294]
+[:mouse_move, 818, 511, 2, 364, 294]
+[:mouse_move, 816, 511, 2, 365, 294]
+[:mouse_move, 813, 513, 2, 366, 294]
+[:mouse_move, 813, 514, 2, 367, 294]
+[:mouse_move, 812, 515, 2, 368, 294]
+[:mouse_move, 812, 516, 2, 369, 294]
+[:mouse_move, 812, 517, 2, 370, 294]
+[:mouse_move, 813, 518, 2, 371, 295]
+[:mouse_move, 814, 518, 2, 372, 295]
+[:mouse_move, 815, 518, 2, 373, 295]
+[:mouse_move, 816, 518, 2, 374, 295]
+[:mouse_move, 817, 518, 2, 375, 295]
+[:mouse_button_up, 1, 0, 1, 376, 302]
+[:mouse_move, 817, 517, 2, 377, 313]
+[:key_down_raw, 96, 0, 2, 378, 320]
+[:key_up_raw, 96, 0, 2, 379, 321]
+[:mouse_move, 817, 518, 2, 380, 323]
+[:mouse_move, 819, 515, 2, 381, 324]
+[:mouse_move, 819, 510, 2, 382, 324]
+[:mouse_move, 811, 498, 2, 383, 324]
+[:mouse_move, 797, 486, 2, 384, 324]
+[:mouse_move, 786, 482, 2, 385, 324]
+[:mouse_move, 780, 479, 2, 386, 324]
+[:mouse_move, 779, 478, 2, 387, 324]
+[:mouse_move, 778, 479, 2, 388, 327]
+[:mouse_move, 779, 484, 2, 389, 327]
+[:mouse_move, 780, 487, 2, 390, 327]
+[:mouse_move, 781, 488, 2, 391, 327]
+[:mouse_move, 782, 488, 2, 392, 327]
+[:mouse_move, 782, 487, 2, 393, 328]
+[:mouse_move, 789, 485, 2, 394, 328]
+[:mouse_move, 800, 481, 2, 395, 328]
+[:mouse_move, 816, 472, 2, 396, 328]
+[:mouse_move, 839, 456, 2, 397, 328]
+[:mouse_move, 870, 434, 2, 398, 329]
+[:mouse_move, 904, 409, 2, 399, 329]
+[:mouse_move, 944, 380, 2, 400, 329]
+[:mouse_move, 996, 331, 2, 401, 329]
+[:mouse_move, 1011, 312, 2, 402, 329]
+[:mouse_move, 1042, 278, 2, 403, 329]
+[:mouse_move, 1081, 231, 2, 404, 329]
+[:mouse_move, 1101, 213, 2, 405, 330]
+[:mouse_move, 1114, 202, 2, 406, 330]
+[:mouse_move, 1118, 196, 2, 407, 330]
+[:mouse_move, 1118, 195, 2, 408, 330]
+[:mouse_move, 1117, 194, 2, 409, 331]
+[:mouse_move, 1115, 194, 2, 410, 331]
+[:mouse_move, 1110, 193, 2, 411, 331]
+[:mouse_move, 1102, 189, 2, 412, 331]
+[:mouse_move, 1084, 184, 2, 413, 331]
+[:mouse_move, 1052, 175, 2, 414, 332]
+[:mouse_move, 1005, 162, 2, 415, 332]
+[:mouse_move, 938, 144, 2, 416, 332]
+[:mouse_move, 892, 138, 2, 417, 332]
+[:mouse_move, 860, 134, 2, 418, 332]
+[:mouse_move, 833, 128, 2, 419, 333]
+[:mouse_move, 809, 120, 2, 420, 333]
+[:mouse_move, 782, 108, 2, 421, 333]
+[:mouse_move, 772, 104, 2, 422, 333]
+[:mouse_move, 770, 103, 2, 423, 333]
+[:mouse_move, 769, 103, 2, 424, 333]
+[:mouse_move, 766, 101, 2, 425, 334]
+[:mouse_move, 764, 100, 2, 426, 334]
+[:mouse_move, 763, 100, 2, 427, 334]
+[:mouse_move, 761, 99, 2, 428, 334]
+[:mouse_move, 760, 98, 2, 429, 334]
+[:key_down_raw, 13, 0, 2, 430, 341]