diff --git a/GenerateCases/GenerateCases.sln b/GenerateCases/GenerateCases.sln
new file mode 100644
index 0000000..4c9e47a
--- /dev/null
+++ b/GenerateCases/GenerateCases.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenerateCases", "GenerateCases\GenerateCases.csproj", "{9DFB7EEF-7262-4F0E-9812-E9283CA9C9A3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9DFB7EEF-7262-4F0E-9812-E9283CA9C9A3}.Debug|x86.ActiveCfg = Debug|x86
+ {9DFB7EEF-7262-4F0E-9812-E9283CA9C9A3}.Debug|x86.Build.0 = Debug|x86
+ {9DFB7EEF-7262-4F0E-9812-E9283CA9C9A3}.Release|x86.ActiveCfg = Release|x86
+ {9DFB7EEF-7262-4F0E-9812-E9283CA9C9A3}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/GenerateCases/GenerateCases.suo b/GenerateCases/GenerateCases.suo
new file mode 100644
index 0000000..62e0e84
Binary files /dev/null and b/GenerateCases/GenerateCases.suo differ
diff --git a/GenerateCases/GenerateCases/GenerateCases.csproj b/GenerateCases/GenerateCases/GenerateCases.csproj
new file mode 100644
index 0000000..19a9724
--- /dev/null
+++ b/GenerateCases/GenerateCases/GenerateCases.csproj
@@ -0,0 +1,57 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {9DFB7EEF-7262-4F0E-9812-E9283CA9C9A3}
+ Exe
+ Properties
+ GenerateCases
+ GenerateCases
+ v4.0
+ Client
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GenerateCases/GenerateCases/Program.cs b/GenerateCases/GenerateCases/Program.cs
new file mode 100644
index 0000000..f5e2c4e
--- /dev/null
+++ b/GenerateCases/GenerateCases/Program.cs
@@ -0,0 +1,392 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace GenerateCases
+{
+ public enum Dir
+ {
+ Down = 0,
+ DownRight = 1,
+ Right = 2,
+ UpRight = 3,
+ Up = 4,
+ UpLeft = 5,
+ Left = 6,
+ DownLeft = 7,
+ All = 8
+ };
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"Cases.h"))
+
+ for (int bits = 0; bits < 256; ++bits)
+ {
+ file.WriteLine("CASE(" + TranslateDown(Down(bits)) + ")");
+ file.WriteLine("CASE(" + TranslateDownRight(DownRight(bits)) + ")");
+ file.WriteLine("CASE(" + TranslateRight(Right(bits)) + ")");
+ file.WriteLine("CASE(" + TranslateUpRight(UpRight(bits)) + ")");
+ file.WriteLine("CASE(" + TranslateUp(Up(bits)) + ")");
+ file.WriteLine("CASE(" + TranslateUpLeft(UpLeft(bits)) + ")");
+ file.WriteLine("CASE(" + TranslateLeft(Left(bits)) + ")");
+ file.WriteLine("CASE(" + TranslateDownLeft(DownLeft(bits)) + ")");
+ }
+
+ }
+
+ static bool Blocked(int bits, Dir dir)
+ {
+ return (((bits) & (1 << (int)dir)) > 0);
+ }
+
+ static bool Empty(int bits, Dir dir)
+ {
+ return !Blocked(bits, dir);
+ }
+
+ static string Down(int bits)
+ {
+ Dir primaryDir = Dir.Down;
+ bool straight = Empty(bits, Dir.Down);
+ bool leftForcedNeighbor = Blocked(bits, Dir.UpRight) && Empty(bits, Dir.Right);
+ bool rightForcedNeighbor = Blocked(bits, Dir.UpLeft) && Empty(bits, Dir.Left);
+ bool leftForcedDiagonal = leftForcedNeighbor && straight && Empty(bits, Dir.DownRight);
+ bool rightForcedDiagonal = rightForcedNeighbor && straight && Empty(bits, Dir.DownLeft);
+
+ return GetCardinalVariation(
+ bits,
+ primaryDir,
+ straight,
+ leftForcedNeighbor,
+ rightForcedNeighbor,
+ leftForcedDiagonal,
+ rightForcedDiagonal);
+ }
+
+ static string Right(int bits)
+ {
+ Dir primaryDir = Dir.Right;
+ bool straight = Empty(bits, Dir.Right);
+ bool leftForcedNeighbor = Blocked(bits, Dir.UpLeft) && Empty(bits, Dir.Up);
+ bool rightForcedNeighbor = Blocked(bits, Dir.DownLeft) && Empty(bits, Dir.Down);
+ bool leftForcedDiagonal = leftForcedNeighbor && straight && Empty(bits, Dir.UpRight);
+ bool rightForcedDiagonal = rightForcedNeighbor && straight && Empty(bits, Dir.DownRight);
+
+ return GetCardinalVariation(
+ bits,
+ primaryDir,
+ straight,
+ leftForcedNeighbor,
+ rightForcedNeighbor,
+ leftForcedDiagonal,
+ rightForcedDiagonal);
+ }
+
+ static string Up(int bits)
+ {
+ Dir primaryDir = Dir.Up;
+ bool straight = Empty(bits, Dir.Up);
+ bool leftForcedNeighbor = Blocked(bits, Dir.DownLeft) && Empty(bits, Dir.Left);
+ bool rightForcedNeighbor = Blocked(bits, Dir.DownRight) && Empty(bits, Dir.Right);
+ bool leftForcedDiagonal = leftForcedNeighbor && straight && Empty(bits, Dir.UpLeft);
+ bool rightForcedDiagonal = rightForcedNeighbor && straight && Empty(bits, Dir.UpRight);
+
+ return GetCardinalVariation(
+ bits,
+ primaryDir,
+ straight,
+ leftForcedNeighbor,
+ rightForcedNeighbor,
+ leftForcedDiagonal,
+ rightForcedDiagonal);
+ }
+
+ static string Left(int bits)
+ {
+ Dir primaryDir = Dir.Left;
+ bool straight = Empty(bits, Dir.Left);
+ bool leftForcedNeighbor = Blocked(bits, Dir.DownRight) && Empty(bits, Dir.Down);
+ bool rightForcedNeighbor = Blocked(bits, Dir.UpRight) && Empty(bits, Dir.Up);
+ bool leftForcedDiagonal = leftForcedNeighbor && straight && Empty(bits, Dir.DownLeft);
+ bool rightForcedDiagonal = rightForcedNeighbor && straight && Empty(bits, Dir.UpLeft);
+
+ return GetCardinalVariation(
+ bits,
+ primaryDir,
+ straight,
+ leftForcedNeighbor,
+ rightForcedNeighbor,
+ leftForcedDiagonal,
+ rightForcedDiagonal);
+ }
+
+ static string GetCardinalVariation(
+ int bits,
+ Dir dir,
+ bool straight,
+ bool leftForcedNeighbor,
+ bool rightForcedNeighbor,
+ bool leftForcedDiagonal,
+ bool rightForcedDiagonal)
+ {
+ string pre = "";
+
+ if (straight && !leftForcedNeighbor && !rightForcedNeighbor)
+ {
+ return pre + "XX2XX";
+ }
+ else if (!straight && leftForcedNeighbor && !rightForcedNeighbor)
+ {
+ return pre + "0XXXX";
+ }
+ else if (!straight && !leftForcedNeighbor && rightForcedNeighbor)
+ {
+ return pre + "XXXX4";
+ }
+ else if (leftForcedDiagonal && !rightForcedNeighbor)
+ {
+ return pre + "012XX";
+ }
+ else if (rightForcedDiagonal && !leftForcedNeighbor)
+ {
+ return pre + "XX234";
+ }
+ else if (leftForcedDiagonal && rightForcedDiagonal)
+ {
+ return pre + "01234";
+ }
+ else if (straight && leftForcedNeighbor && !rightForcedNeighbor && !leftForcedDiagonal)
+ {
+ return pre + "0X2XX";
+ }
+ else if (straight && !leftForcedNeighbor && rightForcedNeighbor && !rightForcedDiagonal)
+ {
+ return pre + "XX2X4";
+ }
+ else if (!straight && leftForcedNeighbor && rightForcedNeighbor)
+ {
+ return pre + "0XXX4";
+ }
+ else if (straight && leftForcedNeighbor && rightForcedNeighbor && !leftForcedDiagonal && !rightForcedDiagonal)
+ {
+ return pre + "0X2X4";
+ }
+ else if (straight && leftForcedNeighbor && rightForcedNeighbor && leftForcedDiagonal && !rightForcedDiagonal)
+ {
+ return pre + "012X4";
+ }
+ else if (straight && leftForcedNeighbor && rightForcedNeighbor && !leftForcedDiagonal && rightForcedDiagonal)
+ {
+ return pre + "0X234";
+ }
+ else
+ {
+ return pre + "XXXXX";
+ }
+ }
+
+ static string DownRight(int bits)
+ {
+ Dir primaryDir = Dir.DownRight;
+ bool leftish = Empty(bits, Dir.Right);
+ bool rightish = Empty(bits, Dir.Down);
+ bool straight = leftish && rightish && Empty(bits, Dir.DownRight);
+
+ return GetDiagonalVariation(
+ primaryDir,
+ straight,
+ leftish,
+ rightish);
+ }
+
+ static string UpRight(int bits)
+ {
+ Dir primaryDir = Dir.UpRight;
+ bool leftish = Empty(bits, Dir.Up);
+ bool rightish = Empty(bits, Dir.Right);
+ bool straight = leftish && rightish && Empty(bits, Dir.UpRight);
+
+ return GetDiagonalVariation(
+ primaryDir,
+ straight,
+ leftish,
+ rightish);
+ }
+
+ static string UpLeft(int bits)
+ {
+ Dir primaryDir = Dir.UpLeft;
+ bool leftish = Empty(bits, Dir.Left);
+ bool rightish = Empty(bits, Dir.Up);
+ bool straight = leftish && rightish && Empty(bits, Dir.UpLeft);
+
+ return GetDiagonalVariation(
+ primaryDir,
+ straight,
+ leftish,
+ rightish);
+ }
+
+ static string DownLeft(int bits)
+ {
+ Dir primaryDir = Dir.DownLeft;
+ bool leftish = Empty(bits, Dir.Down);
+ bool rightish = Empty(bits, Dir.Left);
+ bool straight = leftish && rightish && Empty(bits, Dir.DownLeft);
+
+ return GetDiagonalVariation(
+ primaryDir,
+ straight,
+ leftish,
+ rightish);
+ }
+
+ static string GetDiagonalVariation(
+ Dir dir,
+ bool straight,
+ bool leftish,
+ bool rightish)
+ {
+ string pre = "";
+
+ if (leftish && !rightish)
+ {
+ return pre + "0XX";
+ }
+ else if (!leftish && rightish)
+ {
+ return pre + "XX2";
+ }
+ else if (straight)
+ {
+ return pre + "012";
+ }
+ else if (leftish && rightish && !straight)
+ {
+ return pre + "0X2";
+ }
+ else
+ {
+ return pre + "XXX";
+ }
+ }
+
+ static string TranslateDown(string input)
+ {
+ if (input == "XX2XX") return "D";
+ if (input == "0XXXX") return "R";
+ if (input == "XXXX4") return "L";
+ if (input == "0X2XX") return "D_R";
+ if (input == "XX2X4") return "L_D";
+ if (input == "0XXX4") return "R_L";
+ if (input == "012XX") return "D_DR_R";
+ if (input == "XX234") return "L_DL_D";
+ if (input == "0X2X4") return "L_D_R";
+ if (input == "012X4") return "R_DR_D_L";
+ if (input == "0X234") return "R_D_DL_L";
+ if (input == "01234") return "R_DR_D_DL_L";
+ if (input == "XXXXX") return "Null";
+ return "Null";
+ }
+
+ static string TranslateDownRight(string input)
+ {
+ if (input == "0XX") return "R";
+ if (input == "XX2") return "D";
+ if (input == "0X2") return "D_R";
+ if (input == "012") return "D_DR_R";
+ if (input == "XXX") return "Null";
+ return "Null";
+ }
+
+ static string TranslateRight(string input)
+ {
+ if (input == "XX2XX") return "R";
+ if (input == "0XXXX") return "U";
+ if (input == "XXXX4") return "D";
+ if (input == "0X2XX") return "R_U";
+ if (input == "XX2X4") return "D_R";
+ if (input == "0XXX4") return "D_U";
+ if (input == "012XX") return "R_UR_U";
+ if (input == "XX234") return "D_DR_R";
+ if (input == "0X2X4") return "D_R_U";
+ if (input == "012X4") return "U_UR_R_D";
+ if (input == "0X234") return "U_R_DR_D";
+ if (input == "01234") return "U_UR_R_DR_D";
+ if (input == "XXXXX") return "Null";
+ return "Null";
+ }
+
+ static string TranslateUpRight(string input)
+ {
+ if (input == "0XX") return "U";
+ if (input == "XX2") return "R";
+ if (input == "0X2") return "R_U";
+ if (input == "012") return "R_UR_U";
+ if (input == "XXX") return "Null";
+ return "Null";
+ }
+
+ static string TranslateUp(string input)
+ {
+ if (input == "XX2XX") return "U";
+ if (input == "0XXXX") return "L";
+ if (input == "XXXX4") return "R";
+ if (input == "0X2XX") return "U_L";
+ if (input == "XX2X4") return "R_U";
+ if (input == "0XXX4") return "R_L";
+ if (input == "012XX") return "U_UL_L";
+ if (input == "XX234") return "R_UR_U";
+ if (input == "0X2X4") return "R_U_L";
+ if (input == "012X4") return "L_UL_U_R";
+ if (input == "0X234") return "L_U_UR_R";
+ if (input == "01234") return "L_UL_U_UR_R";
+ if (input == "XXXXX") return "Null";
+ return "Null";
+ }
+
+ static string TranslateUpLeft(string input)
+ {
+ if (input == "0XX") return "L";
+ if (input == "XX2") return "U";
+ if (input == "0X2") return "U_L";
+ if (input == "012") return "U_UL_L";
+ if (input == "XXX") return "Null";
+ return "Null";
+ }
+
+ static string TranslateLeft(string input)
+ {
+ if (input == "XX2XX") return "L";
+ if (input == "0XXXX") return "D";
+ if (input == "XXXX4") return "U";
+ if (input == "0X2XX") return "L_D";
+ if (input == "XX2X4") return "U_L";
+ if (input == "0XXX4") return "D_U";
+ if (input == "012XX") return "L_DL_D";
+ if (input == "XX234") return "U_UL_L";
+ if (input == "0X2X4") return "U_L_D";
+ if (input == "012X4") return "D_DL_L_U";
+ if (input == "0X234") return "D_L_UL_U";
+ if (input == "01234") return "D_DL_L_UL_U";
+ if (input == "XXXXX") return "Null";
+ return "Null";
+ }
+
+ static string TranslateDownLeft(string input)
+ {
+ if (input == "0XX") return "D";
+ if (input == "XX2") return "L";
+ if (input == "0X2") return "L_D";
+ if (input == "012") return "L_DL_D";
+ if (input == "XXX") return "Null";
+ return "Null";
+ }
+
+
+ }
+}
diff --git a/GenerateCases/GenerateCases/Properties/AssemblyInfo.cs b/GenerateCases/GenerateCases/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..fdf06b4
--- /dev/null
+++ b/GenerateCases/GenerateCases/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GenerateCases")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GenerateCases")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("520a70d7-e42b-4bd5-9757-db6184c3a683")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/JPSPlusGoalBounding/BucketPriorityQueue.cpp b/JPSPlusGoalBounding/BucketPriorityQueue.cpp
new file mode 100644
index 0000000..7be585e
--- /dev/null
+++ b/JPSPlusGoalBounding/BucketPriorityQueue.cpp
@@ -0,0 +1,166 @@
+/*
+ * BucketPriorityQueue.cpp
+ *
+ * Copyright (c) 2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "BucketPriorityQueue.h"
+#include "UnsortedPriorityQueue.h"
+
+BucketPriorityQueue::BucketPriorityQueue(int buckets, int arraySize, unsigned int division)
+{
+ m_numBuckets = buckets;
+ m_division = division;
+
+ Reset();
+
+ // Allocate a bunch of free buckets
+ m_maxFreeBuckets = 200;
+ m_nextFreeBucket = 0;
+ m_freeBuckets = new UnsortedPriorityQueue*[m_maxFreeBuckets];
+ for (int m = 0; m < m_maxFreeBuckets; m++)
+ {
+ m_freeBuckets[m] = new UnsortedPriorityQueue(arraySize);
+ }
+
+ // Allocate bucket slots
+ m_bin = new UnsortedPriorityQueue*[m_numBuckets];
+ for (int m = 0; m < m_numBuckets; m++)
+ {
+ m_bin[m] = 0;
+ }
+}
+
+BucketPriorityQueue::~BucketPriorityQueue()
+{
+ for (int m = 0; m < m_maxFreeBuckets; m++)
+ {
+ if(m_freeBuckets[m] != 0)
+ {
+ delete m_freeBuckets[m];
+ }
+ }
+
+ delete[] m_freeBuckets;
+
+ for (int m = 0; m < m_numBuckets; m++)
+ {
+ if(m_bin[m] != 0)
+ {
+ delete m_bin[m];
+ }
+ }
+
+ delete[] m_bin;
+}
+
+void BucketPriorityQueue::Push(DijkstraPathfindingNode* node)
+{
+ m_numNodesTracked++;
+ int index = GetBinIndex(node->m_givenCost);
+
+ if(m_bin[index] == 0)
+ {
+ m_bin[index] = m_freeBuckets[m_nextFreeBucket++];
+ }
+
+ m_bin[index]->Push(node);
+
+ if (index < m_lowestNonEmptyBin)
+ {
+ m_lowestNonEmptyBin = index;
+ }
+}
+
+DijkstraPathfindingNode* BucketPriorityQueue::Pop(void)
+{
+ DijkstraPathfindingNode* node = m_bin[m_lowestNonEmptyBin]->Pop();
+ m_numNodesTracked--;
+
+ if(m_bin[m_lowestNonEmptyBin]->Empty(node->m_iteration))
+ {
+ m_freeBuckets[--m_nextFreeBucket] = m_bin[m_lowestNonEmptyBin];
+ m_bin[m_lowestNonEmptyBin] = 0;
+ }
+
+ if (m_numNodesTracked > 0)
+ {
+ // Find the next non-empty bin
+ for (m_lowestNonEmptyBin; m_lowestNonEmptyBin < m_numBuckets; m_lowestNonEmptyBin++)
+ {
+ if (m_bin[m_lowestNonEmptyBin] != 0 &&
+ !m_bin[m_lowestNonEmptyBin]->Empty(node->m_iteration))
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ m_lowestNonEmptyBin = m_numBuckets;
+ }
+
+ return node;
+}
+
+void BucketPriorityQueue::DecreaseKey(DijkstraPathfindingNode* node, unsigned int lastCost)
+{
+ // Remove node
+ int index = GetBinIndex(lastCost);
+ m_bin[index]->Remove(node);
+
+ if(m_bin[index]->Empty(node->m_iteration))
+ {
+ m_freeBuckets[--m_nextFreeBucket] = m_bin[index];
+ m_bin[index] = 0;
+ }
+
+ // Push node
+ index = GetBinIndex(node->m_givenCost);
+
+ if(m_bin[index] == 0)
+ {
+ m_bin[index] = m_freeBuckets[m_nextFreeBucket++];
+ }
+
+ m_bin[index]->Push(node);
+
+ if (index < m_lowestNonEmptyBin)
+ {
+ m_lowestNonEmptyBin = index;
+ }
+}
diff --git a/JPSPlusGoalBounding/BucketPriorityQueue.h b/JPSPlusGoalBounding/BucketPriorityQueue.h
new file mode 100644
index 0000000..1454f2b
--- /dev/null
+++ b/JPSPlusGoalBounding/BucketPriorityQueue.h
@@ -0,0 +1,75 @@
+/*
+ * BucketPriorityQueue.h
+ *
+ * Copyright (c) 2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "UnsortedPriorityQueue.h"
+
+// This data structure is dangerous since there are no safeguards if the max size is exceeded.
+// However, any method to detect a problem and deal with it gracefully will sacrifice speed.
+// The number of buckets can be reduced if the maximum final cost is known to be lower (significant memory savings)
+// In this code base, this is only used by the Dijkstra floodfill for Goal Bounding preprocessing.
+
+class BucketPriorityQueue
+{
+public:
+ BucketPriorityQueue(int buckets, int arraySize, unsigned int division);
+ ~BucketPriorityQueue();
+
+ inline void SetBaseCost(unsigned int baseCost) { m_baseCost = baseCost; }
+ inline void Reset() { m_lowestNonEmptyBin = m_numBuckets; m_numNodesTracked = 0; m_baseCost = 0; }
+ inline bool Empty() { return m_numNodesTracked == 0; }
+ void Push(DijkstraPathfindingNode* node);
+ DijkstraPathfindingNode* Pop(void);
+ void DecreaseKey(DijkstraPathfindingNode* node, unsigned int lastCost);
+
+private:
+ int m_numBuckets;
+ int m_lowestNonEmptyBin;
+ int m_numNodesTracked;
+ unsigned int m_division;
+ unsigned int m_baseCost;
+ UnsortedPriorityQueue** m_bin;
+
+ int m_maxFreeBuckets;
+ int m_nextFreeBucket;
+ UnsortedPriorityQueue** m_freeBuckets;
+
+ inline int GetBinIndex(unsigned int cost) { return ((cost - m_baseCost) / m_division); }
+};
+
diff --git a/JPSPlusGoalBounding/Cases.h b/JPSPlusGoalBounding/Cases.h
new file mode 100644
index 0000000..2dec775
--- /dev/null
+++ b/JPSPlusGoalBounding/Cases.h
@@ -0,0 +1,2048 @@
+CASE(D)
+CASE(D_DR_R)
+CASE(R)
+CASE(R_UR_U)
+CASE(U)
+CASE(U_UL_L)
+CASE(L)
+CASE(L_DL_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(U)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D_R)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U_UL_L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(L)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(R_U)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L_DL_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U_UL_L)
+CASE(D_DL_L_UL_U)
+CASE(L_DL_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(D_DL_L_UL_U)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D_DR_R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(U_L)
+CASE(L)
+CASE(L_DL_D)
+CASE(L)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D_R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U_L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(L)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(L)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(R_DR_D_DL_L)
+CASE(D_DR_R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L_DL_D)
+CASE(R_L)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(R_D_DL_L)
+CASE(D_R)
+CASE(R_U)
+CASE(R_U)
+CASE(R_U)
+CASE(U_L)
+CASE(D_DL_L_U)
+CASE(L_DL_D)
+CASE(R_L)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(R_U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(D_DL_L_U)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(R_DR_D_DL_L)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(R_L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(R_D_DL_L)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(R_L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_DL_D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L_DL_D)
+CASE(L_DL_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D_DR_R)
+CASE(R)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_DR_R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(R_U)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R_UR_U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(L_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D_R)
+CASE(D_R)
+CASE(R_UR_U)
+CASE(L_UL_U_UR_R)
+CASE(U_UL_L)
+CASE(L_D)
+CASE(L_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(L_UL_U_UR_R)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L_D)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(L)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R_U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D_R)
+CASE(D_R)
+CASE(D_R)
+CASE(R_U)
+CASE(L_UL_U_R)
+CASE(U_UL_L)
+CASE(D_L_UL_U)
+CASE(L_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(L_UL_U_R)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(D_L_UL_U)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(U_UL_L)
+CASE(L)
+CASE(D)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D_R)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D_DR_R)
+CASE(U_UR_R_DR_D)
+CASE(R_UR_U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_D)
+CASE(L)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D_R)
+CASE(U_UR_R_D)
+CASE(R_UR_U)
+CASE(L_U_UR_R)
+CASE(U_L)
+CASE(L_D)
+CASE(L_D)
+CASE(L)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(L_U_UR_R)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L_D)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L)
+CASE(R_DR_D_L)
+CASE(D_DR_R)
+CASE(U_R_DR_D)
+CASE(R_U)
+CASE(U_L)
+CASE(U_L)
+CASE(U_L)
+CASE(L_D)
+CASE(R_L)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U_L)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_D_R)
+CASE(D_R)
+CASE(D_R_U)
+CASE(R_U)
+CASE(R_U_L)
+CASE(U_L)
+CASE(U_L_D)
+CASE(L_D)
+CASE(R_L)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(R_U_L)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(U_L)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(U_L_D)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U_L)
+CASE(U_L)
+CASE(U_L)
+CASE(L)
+CASE(L_D)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(R_DR_D_L)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(R_L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D_R)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(R_L)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L_D)
+CASE(L_D)
+CASE(L)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(L)
+CASE(D)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(D_R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(D_R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_DR_R)
+CASE(U_UR_R_DR_D)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(U_UR_R_D)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(R_UR_U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(U_R_DR_D)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(D_R_U)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R_U)
+CASE(R_U)
+CASE(R_U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D_U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(D_U)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(U)
+CASE(Null)
+CASE(D)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(D_DR_R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D_R)
+CASE(D_R)
+CASE(D_R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(R)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(D)
+CASE(D)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
+CASE(Null)
diff --git a/JPSPlusGoalBounding/DijkstraFloodfill.cpp b/JPSPlusGoalBounding/DijkstraFloodfill.cpp
new file mode 100644
index 0000000..3f71945
--- /dev/null
+++ b/JPSPlusGoalBounding/DijkstraFloodfill.cpp
@@ -0,0 +1,687 @@
+/*
+ * DijkstraFloodfill.cpp
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "DijkstraFloodfill.h"
+
+#define ONLY_VISIT_REASONABLE_NEIGHBORS // 3% to 17% speed-up
+
+#define FIXED_POINT_MULTIPLIER 100000
+#define FIXED_POINT_SHIFT(x) ((x) * FIXED_POINT_MULTIPLIER)
+#define FIXED_POINT_ONE FIXED_POINT_MULTIPLIER
+#define FIXED_POINT_SQRT_2 141421
+
+typedef const void (DijkstraFloodfill::*DijkstraFloodFunctionPointer)(DijkstraPathfindingNode * currentNode);
+
+DijkstraFloodfill::DijkstraFloodfill(int width, int height, std::vector map, DistantJumpPoints** distantJumpPointMap)
+: m_width(width), m_height(height), m_map(map)
+{
+ m_currentIteration = 1;
+
+#ifdef USE_FAST_OPEN_LIST
+ // Number of buckets
+ const int numberOfBuckets = 300000; // Must be no smaller than longest path divided by "division"
+ const int nodesInEachBucket = 1000;
+ const int division = 10000;
+ m_fastOpenList = new BucketPriorityQueue(numberOfBuckets, nodesInEachBucket, division);
+#endif
+
+ // Initialize nodes
+ InitArray(m_mapNodes, m_width, m_height);
+ for (int r = 0; rReset();
+#else
+ m_openList.reset();
+ m_openList.reserve(3000);
+#endif
+
+ if (IsEmpty(r, c))
+ {
+ // Begin with starting node
+ DijkstraPathfindingNode* node = &m_mapNodes[r][c];
+ node->m_parent = NULL;
+ node->m_directionFromStart = 255;
+ node->m_directionFromParent = 255;
+ node->m_givenCost = 0;
+ node->m_iteration = m_currentIteration;
+ node->m_listStatus = PathfindingNode::OnOpen;
+
+ // Explore outward in all directions on the starting node
+ Explore_AllDirectionsWithChecks(node);
+
+ node->m_listStatus = PathfindingNode::OnClosed;
+ }
+
+#ifdef USE_FAST_OPEN_LIST
+ while (!m_fastOpenList->Empty())
+#else
+ while (!m_openList.empty())
+#endif
+ {
+
+#ifdef USE_FAST_OPEN_LIST
+ DijkstraPathfindingNode* currentNode = m_fastOpenList->Pop();
+#else
+ DijkstraPathfindingNode* currentNode = m_openList.remove();
+#endif
+
+ // Explore nodes based on the parent and surrounding walls.
+ // This must be in the search style of JPS+ in order to produce
+ // the correct data for JPS+. If goal bounding is used for regular
+ // A*, then this search would need to mimic regular A*.
+ (this->*exploreDirectionsDijkstraFlood[(currentNode->m_blockedDirectionBitfield * 8) +
+ currentNode->m_directionFromParent])(currentNode);
+
+ currentNode->m_listStatus = PathfindingNode::OnClosed;
+ }
+}
+
+const void DijkstraFloodfill::Explore_AllDirectionsWithChecks(DijkstraPathfindingNode * currentNode)
+{
+ //DOWN, DOWNRIGHT, RIGHT, UPRIGHT, UP, UPLEFT, LEFT, DOWNLEFT
+ static const int offsetRow[] = { 1, 1, 0, -1, -1, -1, 0, 1 };
+ static const int offsetCol[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
+
+ for (int i = 0; i < 8; ++i)
+ {
+ unsigned int neighborRow = currentNode->m_row + offsetRow[i];
+
+ // Out of grid bounds?
+ if (neighborRow >= m_height)
+ continue;
+
+ unsigned int neighborCol = currentNode->m_col + offsetCol[i];
+
+ // Out of grid bounds?
+ if (neighborCol >= m_width)
+ continue;
+
+ // Valid tile - get the node
+ DijkstraPathfindingNode* newSuccessor = &m_mapNodes[neighborRow][neighborCol];
+
+ // Blocked?
+ if (!m_map[neighborCol + (neighborRow * m_width)])
+ continue;
+
+ // Diagonal blocked?
+ bool isDiagonal = (i & 0x1) == 1;
+ if (isDiagonal && (!m_map[currentNode->m_col + ((currentNode->m_row + offsetRow[i]) * m_width)] ||
+ !m_map[currentNode->m_col + offsetCol[i] + (currentNode->m_row * m_width)]))
+ {
+ continue;
+ }
+
+ unsigned int costToNextNode = isDiagonal ? FIXED_POINT_SQRT_2 : FIXED_POINT_ONE;
+ ArrayDirections dir = (ArrayDirections)i;
+
+ PushNewNode(newSuccessor, currentNode, dir, dir, costToNextNode);
+ }
+}
+
+inline const void DijkstraFloodfill::Explore_Null(DijkstraPathfindingNode * currentNode)
+{
+ // Purposely does nothing
+}
+
+inline const void DijkstraFloodfill::Explore_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_DR(DijkstraPathfindingNode * currentNode)
+{
+ SearchDownRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_UR(DijkstraPathfindingNode * currentNode)
+{
+ SearchUpRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_UL(DijkstraPathfindingNode * currentNode)
+{
+ SearchUpLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_DL(DijkstraPathfindingNode * currentNode)
+{
+ SearchDownLeft(currentNode);
+}
+
+// Adjacent Doubles
+
+inline const void DijkstraFloodfill::Explore_D_DR(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchDownRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_DR_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchDownRight(currentNode);
+ SearchRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_R_UR(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchUpRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_UR_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchUpRight(currentNode);
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U_UL(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+ SearchUpLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_UL_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchUpLeft(currentNode);
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L_DL(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+ SearchDownLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_DL_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchDownLeft(currentNode);
+ SearchDown(currentNode);
+}
+
+// Non-Adjacent Cardinal Doubles
+
+inline const void DijkstraFloodfill::Explore_D_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_R_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+ SearchDown(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_D_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_R_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchLeft(currentNode);
+}
+
+// Adjacent Triples
+
+inline const void DijkstraFloodfill::Explore_D_DR_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchDownRight(currentNode);
+ SearchRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_DR_R_UR(DijkstraPathfindingNode * currentNode)
+{
+ SearchDownRight(currentNode);
+ SearchRight(currentNode);
+ SearchUpRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_R_UR_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchUpRight(currentNode);
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_UR_U_UL(DijkstraPathfindingNode * currentNode)
+{
+ SearchUpRight(currentNode);
+ SearchUp(currentNode);
+ SearchUpLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U_UL_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+ SearchUpLeft(currentNode);
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_UL_L_DL(DijkstraPathfindingNode * currentNode)
+{
+ SearchUpLeft(currentNode);
+ SearchLeft(currentNode);
+ SearchDownLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L_DL_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+ SearchDownLeft(currentNode);
+ SearchDown(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_DL_D_DR(DijkstraPathfindingNode * currentNode)
+{
+ SearchDownLeft(currentNode);
+ SearchDown(currentNode);
+ SearchDownRight(currentNode);
+}
+
+// Non-Adjacent Cardinal Triples
+
+inline const void DijkstraFloodfill::Explore_D_R_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchRight(currentNode);
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_R_U_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchUp(currentNode);
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U_L_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+ SearchLeft(currentNode);
+ SearchDown(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L_D_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+ SearchDown(currentNode);
+ SearchRight(currentNode);
+}
+
+// Quads
+
+inline const void DijkstraFloodfill::Explore_R_DR_D_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchDownRight(currentNode);
+ SearchDown(currentNode);
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_R_D_DL_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchDown(currentNode);
+ SearchDownLeft(currentNode);
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U_UR_R_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+ SearchUpRight(currentNode);
+ SearchRight(currentNode);
+ SearchDown(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U_R_DR_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+ SearchRight(currentNode);
+ SearchDownRight(currentNode);
+ SearchDown(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L_UL_U_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+ SearchUpLeft(currentNode);
+ SearchUp(currentNode);
+ SearchRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L_U_UR_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+ SearchUp(currentNode);
+ SearchUpRight(currentNode);
+ SearchRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_D_DL_L_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchDownLeft(currentNode);
+ SearchLeft(currentNode);
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_D_L_UL_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchLeft(currentNode);
+ SearchUpLeft(currentNode);
+ SearchUp(currentNode);
+}
+
+// Quints
+
+inline const void DijkstraFloodfill::Explore_R_DR_D_DL_L(DijkstraPathfindingNode * currentNode)
+{
+ SearchRight(currentNode);
+ SearchDownRight(currentNode);
+ SearchDown(currentNode);
+ SearchDownLeft(currentNode);
+ SearchLeft(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_U_UR_R_DR_D(DijkstraPathfindingNode * currentNode)
+{
+ SearchUp(currentNode);
+ SearchUpRight(currentNode);
+ SearchRight(currentNode);
+ SearchDownRight(currentNode);
+ SearchDown(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_L_UL_U_UR_R(DijkstraPathfindingNode * currentNode)
+{
+ SearchLeft(currentNode);
+ SearchUpLeft(currentNode);
+ SearchUp(currentNode);
+ SearchUpRight(currentNode);
+ SearchRight(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_D_DL_L_UL_U(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchDownLeft(currentNode);
+ SearchLeft(currentNode);
+ SearchUpLeft(currentNode);
+ SearchUp(currentNode);
+}
+
+inline const void DijkstraFloodfill::Explore_AllDirections(DijkstraPathfindingNode * currentNode)
+{
+ SearchDown(currentNode);
+ SearchDownLeft(currentNode);
+ SearchLeft(currentNode);
+ SearchUpLeft(currentNode);
+ SearchUp(currentNode);
+ SearchUpRight(currentNode);
+ SearchRight(currentNode);
+ SearchDownRight(currentNode);
+}
+
+void DijkstraFloodfill::SearchDown(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row + 1;
+ int newCol = currentNode->m_col;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_ONE;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, Down, givenCost);
+}
+
+void DijkstraFloodfill::SearchDownRight(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row + 1;
+ int newCol = currentNode->m_col + 1;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SQRT_2;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, DownRight, givenCost);
+}
+
+void DijkstraFloodfill::SearchRight(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row;
+ int newCol = currentNode->m_col + 1;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_ONE;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, Right, givenCost);
+}
+
+void DijkstraFloodfill::SearchUpRight(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row - 1;
+ int newCol = currentNode->m_col + 1;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SQRT_2;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, UpRight, givenCost);
+}
+
+void DijkstraFloodfill::SearchUp(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row - 1;
+ int newCol = currentNode->m_col;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_ONE;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, Up, givenCost);
+}
+
+void DijkstraFloodfill::SearchUpLeft(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row - 1;
+ int newCol = currentNode->m_col - 1;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SQRT_2;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, UpLeft, givenCost);
+}
+
+void DijkstraFloodfill::SearchLeft(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row;
+ int newCol = currentNode->m_col - 1;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_ONE;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, Left, givenCost);
+}
+
+void DijkstraFloodfill::SearchDownLeft(DijkstraPathfindingNode * currentNode)
+{
+ int newRow = currentNode->m_row + 1;
+ int newCol = currentNode->m_col - 1;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SQRT_2;
+ DijkstraPathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, (ArrayDirections)currentNode->m_directionFromStart, DownLeft, givenCost);
+}
+
+void DijkstraFloodfill::PushNewNode(
+ DijkstraPathfindingNode * newSuccessor,
+ DijkstraPathfindingNode * currentNode,
+ ArrayDirections startDirection,
+ ArrayDirections parentDirection,
+ unsigned int givenCost)
+{
+ if (newSuccessor->m_iteration != m_currentIteration)
+ {
+ // Place node on the Open list (we've never seen it before)
+ newSuccessor->m_parent = currentNode;
+ newSuccessor->m_directionFromStart = startDirection;
+ newSuccessor->m_directionFromParent = parentDirection;
+ newSuccessor->m_givenCost = givenCost;
+ newSuccessor->m_listStatus = PathfindingNode::OnOpen;
+ newSuccessor->m_iteration = m_currentIteration;
+
+#ifdef USE_FAST_OPEN_LIST
+ m_fastOpenList->Push(newSuccessor);
+#else
+ m_openList.add(newSuccessor);
+#endif
+ }
+ else if (givenCost < newSuccessor->m_givenCost &&
+ newSuccessor->m_listStatus == PathfindingNode::OnOpen)
+ {
+ // We found a cheaper way to this node - update it
+ unsigned int lastCost = newSuccessor->m_givenCost;
+ newSuccessor->m_parent = currentNode;
+ newSuccessor->m_directionFromStart = startDirection;
+ newSuccessor->m_directionFromParent = parentDirection;
+ newSuccessor->m_givenCost = givenCost;
+
+#ifdef USE_FAST_OPEN_LIST
+ m_fastOpenList->DecreaseKey(newSuccessor, lastCost);
+#else
+ m_openList.decreaseKey(newSuccessor);
+#endif
+ }
+}
+
+inline bool DijkstraFloodfill::IsEmpty(int r, int c)
+{
+ unsigned int colBoundsCheck = c;
+ unsigned int rowBoundsCheck = r;
+ if (colBoundsCheck < (unsigned int)m_width && rowBoundsCheck < (unsigned int)m_height)
+ {
+ return m_map[c + (r * m_width)];
+ }
+ else
+ {
+ return false;
+ }
+}
+
+template
+void DijkstraFloodfill::InitArray(T**& t, int width, int height)
+{
+ t = new T*[height];
+ for (int i = 0; i < height; ++i)
+ {
+ t[i] = new T[width];
+ memset(t[i], 0, sizeof(T)*width);
+ }
+}
+
+template
+void DijkstraFloodfill::DestroyArray(T**& t)
+{
+ for (int i = 0; i < m_height; ++i)
+ delete[] t[i];
+ delete[] t;
+
+ t = 0;
+}
+
diff --git a/JPSPlusGoalBounding/DijkstraFloodfill.h b/JPSPlusGoalBounding/DijkstraFloodfill.h
new file mode 100644
index 0000000..39158d6
--- /dev/null
+++ b/JPSPlusGoalBounding/DijkstraFloodfill.h
@@ -0,0 +1,181 @@
+/*
+ * DijkstraFloodfill.h
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include
+#include "PathfindingNode.h"
+#include "GenericHeap.h"
+#include "BucketPriorityQueue.h"
+#include "PrecomputeMap.h"
+
+#define MAX_WIDTH 2048
+#define MAX_HEIGHT 2048
+
+#define USE_FAST_OPEN_LIST // Significantly faster, but preallocated memory might not be large enough. Verify in cpp file.
+
+// A Dijkstra floodfill has no goal. It floods the map from the starting node until all connected nodes are exhausted.
+// This Dijkstra floodfill propagate to all explored nodes the original direction it left the staring node. This is
+// needed to determine the Goal Bounds for each neighboring edge of the starting node.
+
+class DijkstraFloodfill
+{
+public:
+ DijkstraFloodfill(int width, int height, std::vector map, DistantJumpPoints** distantJumpPointMap);
+ ~DijkstraFloodfill();
+
+ void Flood(int r, int c);
+ inline int GetCurrentInteration() { return m_currentIteration; }
+
+ DijkstraPathfindingNode ** m_mapNodes;
+
+private:
+
+ // 48 function variations of exploring (used in 2048 entry look-up table)
+ // D = Down, U = Up, R = Right, L = Left, DR = Down Right, DL = Down Left, UR = Up Right, UL = Up Left
+ const void Explore_Null(DijkstraPathfindingNode * currentNode);
+ const void Explore_D(DijkstraPathfindingNode * currentNode);
+ const void Explore_DR(DijkstraPathfindingNode * currentNode);
+ const void Explore_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_UR(DijkstraPathfindingNode * currentNode);
+ const void Explore_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_UL(DijkstraPathfindingNode * currentNode);
+ const void Explore_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_DL(DijkstraPathfindingNode * currentNode);
+ const void Explore_D_DR(DijkstraPathfindingNode * currentNode);
+ const void Explore_DR_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_UR(DijkstraPathfindingNode * currentNode);
+ const void Explore_UR_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_U_UL(DijkstraPathfindingNode * currentNode);
+ const void Explore_UL_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_L_DL(DijkstraPathfindingNode * currentNode);
+ const void Explore_DL_D(DijkstraPathfindingNode * currentNod);
+ const void Explore_D_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_U_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_L_D(DijkstraPathfindingNode * currentNode);
+ const void Explore_D_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_D_DR_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_DR_R_UR(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_UR_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_UR_U_UL(DijkstraPathfindingNode * currentNode);
+ const void Explore_U_UL_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_UL_L_DL(DijkstraPathfindingNode * currentNode);
+ const void Explore_L_DL_D(DijkstraPathfindingNode * currentNode);
+ const void Explore_DL_D_DR(DijkstraPathfindingNode * currentNode);
+ const void Explore_D_R_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_U_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_U_L_D(DijkstraPathfindingNode * currentNode);
+ const void Explore_L_D_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_DR_D_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_D_DL_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_U_UR_R_D(DijkstraPathfindingNode * currentNode);
+ const void Explore_U_R_DR_D(DijkstraPathfindingNode * currentNode);
+ const void Explore_L_UL_U_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_L_U_UR_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_D_DL_L_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_D_L_UL_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_R_DR_D_DL_L(DijkstraPathfindingNode * currentNode);
+ const void Explore_U_UR_R_DR_D(DijkstraPathfindingNode * currentNode);
+ const void Explore_L_UL_U_UR_R(DijkstraPathfindingNode * currentNode);
+ const void Explore_D_DL_L_UL_U(DijkstraPathfindingNode * currentNode);
+ const void Explore_AllDirections(DijkstraPathfindingNode * currentNode);
+
+ const void Explore_AllDirectionsWithChecks(DijkstraPathfindingNode * currentNode);
+
+ void SearchDown(DijkstraPathfindingNode * currentNode);
+ void SearchDownRight(DijkstraPathfindingNode * currentNode);
+ void SearchRight(DijkstraPathfindingNode * currentNode);
+ void SearchUpRight(DijkstraPathfindingNode * currentNode);
+ void SearchUp(DijkstraPathfindingNode * currentNode);
+ void SearchUpLeft(DijkstraPathfindingNode * currentNode);
+ void SearchLeft(DijkstraPathfindingNode * currentNode);
+ void SearchDownLeft(DijkstraPathfindingNode * currentNode);
+
+ void PushNewNode(
+ DijkstraPathfindingNode * newSuccessor,
+ DijkstraPathfindingNode * currentNode,
+ ArrayDirections startDirection,
+ ArrayDirections parentDirection,
+ unsigned int givenCost);
+
+ // Helper functions for heap open list
+ struct PathfindingNodeEqual {
+ bool operator()(const DijkstraPathfindingNode* i1, const DijkstraPathfindingNode* i2)
+ {
+ return (i1 == i2);
+ }
+ };
+
+ struct PathfindingNodeCmp : std::binary_function {
+ bool operator()(DijkstraPathfindingNode* const lhs, DijkstraPathfindingNode* const rhs) const {
+ return lhs->m_givenCost > rhs->m_givenCost;
+ }
+ };
+
+ struct SearchNodeHash {
+ size_t operator()(const DijkstraPathfindingNode* x) const
+ {
+ return (size_t)(x->m_col + (x->m_row * MAX_WIDTH));
+ }
+ };
+
+ typedef GenericHeap PQueue;
+
+ // Open list
+ PQueue m_openList;
+#ifdef USE_FAST_OPEN_LIST
+ BucketPriorityQueue* m_fastOpenList;
+#endif
+
+ // Map properties
+ int m_width, m_height;
+ std::vector m_map;
+
+ // Search specific info
+ int m_currentIteration; // This allows us to know if a node has been touched this iteration (faster than clearing all the nodes before each search)
+
+ // Wall queries
+ bool IsEmpty(int r, int c);
+
+ // 2D array initialization and destruction
+ template void InitArray(T**& t, int width, int height);
+ template void DestroyArray(T**& t);
+};
diff --git a/JPSPlusGoalBounding/Entry.cpp b/JPSPlusGoalBounding/Entry.cpp
new file mode 100644
index 0000000..31a5f52
--- /dev/null
+++ b/JPSPlusGoalBounding/Entry.cpp
@@ -0,0 +1,74 @@
+/*
+ * Entry.cpp
+ *
+ * Copyright (c) 2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include
+#include "Entry.h"
+#include "PrecomputeMap.h"
+#include "JPSPlus.h"
+
+const char *GetName()
+{
+ return "JPS+";
+}
+
+void PreprocessMap(std::vector &bits, int w, int h, const char *filename)
+{
+ printf("Writing to file '%s'\n", filename);
+
+ PrecomputeMap precomputeMap(w, h, bits);
+ precomputeMap.CalculateMap();
+ precomputeMap.SaveMap(filename);
+}
+
+void *PrepareForSearch(std::vector &bits, int w, int h, const char *filename)
+{
+ //printf("Reading from file '%s'\n", filename);
+
+ PrecomputeMap precomputeMap(w, h, bits);
+ precomputeMap.LoadMap(filename);
+ JumpDistancesAndGoalBounds** preprocessedMap = precomputeMap.GetPreprocessedMap();
+ return (void*)new JPSPlus(preprocessedMap, bits, w, h);
+}
+
+bool GetPath(void *data, xyLoc s, xyLoc g, std::vector &path)
+{
+ JPSPlus* search = (JPSPlus*)data;
+ return search->GetPath((xyLocJPS&)s, (xyLocJPS&)g, (std::vector&)path);
+}
diff --git a/JPSPlusGoalBounding/Entry.h b/JPSPlusGoalBounding/Entry.h
new file mode 100644
index 0000000..6af1b10
--- /dev/null
+++ b/JPSPlusGoalBounding/Entry.h
@@ -0,0 +1,50 @@
+/*
+ * Entry.h
+ *
+ * Copyright (c) 2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+
+struct xyLoc {
+ int16_t x;
+ int16_t y;
+};
+
+void PreprocessMap(std::vector &bits, int width, int height, const char *filename);
+void *PrepareForSearch(std::vector &bits, int width, int height, const char *filename);
+bool GetPath(void *data, xyLoc s, xyLoc g, std::vector &path);
+const char *GetName();
diff --git a/JPSPlusGoalBounding/FPUtil.cpp b/JPSPlusGoalBounding/FPUtil.cpp
new file mode 100644
index 0000000..dea50b0
--- /dev/null
+++ b/JPSPlusGoalBounding/FPUtil.cpp
@@ -0,0 +1,31 @@
+#include "stdafx.h"
+#include "FPUtil.h"
+
+/*
+ * FPUtil.cpp
+ *
+ * Copyright (c) 2007, Nathan Sturtevant
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of Alberta nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NATHAN STURTEVANT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/JPSPlusGoalBounding/FPUtil.h b/JPSPlusGoalBounding/FPUtil.h
new file mode 100644
index 0000000..9336c44
--- /dev/null
+++ b/JPSPlusGoalBounding/FPUtil.h
@@ -0,0 +1,61 @@
+/*
+ * FPUtil.h
+ *
+ * Copyright (c) 2007, Nathan Sturtevant
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of Alberta nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NATHAN STURTEVANT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef _MSC_VER
+#include "stdafx.h"
+#endif
+
+#ifndef FPUTIL_H
+#define FPUTIL_H
+
+/**
+ * FPUtil.h
+ *
+ * This file defines floating point compare functions with tolerances.
+ *
+ */
+
+// Floating point comparisons
+static const double TOLERANCE = 0.000001; // floating point tolerance
+
+/**
+* Compare two doubles using a floating-point tolerance
+*/
+inline bool fless(double a, double b) { return (a < b - TOLERANCE); }
+/**
+* Compare two doubles using a floating-point tolerance
+*/
+inline bool fgreater(double a, double b) { return (a > b + TOLERANCE); }
+/**
+* Compare two doubles using a floating-point tolerance
+*/
+inline bool fequal(double a, double b)
+{ return (a > b - TOLERANCE) && (a < b+TOLERANCE); }
+
+#endif
diff --git a/JPSPlusGoalBounding/FastStack.cpp b/JPSPlusGoalBounding/FastStack.cpp
new file mode 100644
index 0000000..ca457d0
--- /dev/null
+++ b/JPSPlusGoalBounding/FastStack.cpp
@@ -0,0 +1,42 @@
+/*
+ * FastStack.cpp
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "StdAfx.h"
+#include "FastStack.h"
+
diff --git a/JPSPlusGoalBounding/FastStack.h b/JPSPlusGoalBounding/FastStack.h
new file mode 100644
index 0000000..39eaa9f
--- /dev/null
+++ b/JPSPlusGoalBounding/FastStack.h
@@ -0,0 +1,63 @@
+/*
+ * FastStack.h
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "PathfindingNode.h"
+
+// This class is designed to be used only for grid searches that use the Octile heuristic.
+// In this specific use case, a stack can be used instead of a traditional open list to
+// hold neighboring all nodes that have a final cost equal to the parent node. When the
+// cheapest node is needed, exhaust this stack first before pulling off of the open list.
+
+class FastStack
+{
+public:
+ FastStack(int size) : m_nextFreeNode(0) { m_nodeArray = new PathfindingNode*[size]; }
+ ~FastStack(void) { delete[] m_nodeArray; }
+
+ inline void Reset(void) { m_nextFreeNode = 0; }
+ inline bool Empty(void) { return m_nextFreeNode == 0; }
+ inline void Push(PathfindingNode* node) { m_nodeArray[m_nextFreeNode++] = node; }
+ PathfindingNode* Pop(void) { return m_nodeArray[--m_nextFreeNode]; }
+
+private:
+ int m_nextFreeNode;
+ PathfindingNode** m_nodeArray;
+};
+
diff --git a/JPSPlusGoalBounding/GenericHeap.cpp b/JPSPlusGoalBounding/GenericHeap.cpp
new file mode 100644
index 0000000..509d619
--- /dev/null
+++ b/JPSPlusGoalBounding/GenericHeap.cpp
@@ -0,0 +1,31 @@
+/*
+ * GenericHeap.cpp
+ *
+ * Copyright (c) 2007, Nathan Sturtevant
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of Alberta nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NATHAN STURTEVANT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "GenericHeap.h"
diff --git a/JPSPlusGoalBounding/GenericHeap.h b/JPSPlusGoalBounding/GenericHeap.h
new file mode 100644
index 0000000..4cf858b
--- /dev/null
+++ b/JPSPlusGoalBounding/GenericHeap.h
@@ -0,0 +1,312 @@
+/*
+ * GenericHeap.h
+ *
+ * Copyright (c) 2007, Nathan Sturtevant
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of Alberta nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NATHAN STURTEVANT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef _MSC_VER
+#include "stdafx.h"
+#include
+#else
+#include
+#endif
+
+#ifndef HEAP2_H
+#define HEAP2_H
+
+#include
+#include
+#include
+
+/**
+ * Generic Heap
+ *
+* A relatively simple heap class. Uses a second hash table so that
+ * keys can be looked up and re-heaped in constant time instead of
+ * linear time.
+ *
+ * The EqKey and CmpKey functions were required for the gnu hash_map, but
+ * aren't compatible with the windows hash_map. So, there is some
+ * unnecessary code here which I just haven't re-written.
+ */
+template
+class GenericHeap {
+public:
+ GenericHeap();
+ ~GenericHeap();
+ void reset();
+ void add(Obj val);
+ void decreaseKey(Obj val);
+ bool isIn(Obj val);
+ Obj remove();
+ void pop() { remove(); }
+ Obj top() { return _elts[0]; }
+ Obj find(Obj val);
+ bool empty();
+ uint32_t size() { return (uint32_t)_elts.size(); }
+ void reserve(unsigned int c) { _elts.reserve(c); }
+private:
+ std::vector _elts;
+ void heapifyUp(unsigned int index);
+ void heapifyDown(unsigned int index);
+#ifdef _MSC_VER
+ typedef stdext::hash_map IndexTable;
+#else
+// // this was my original definition, but to maintain compatibility with
+// // microsoft's hash_map, we now have to require a perfect hash function
+// typedef __gnu_cxx::hash_map IndexTable;
+ typedef __gnu_cxx::hash_map IndexTable;
+#endif
+ IndexTable table;
+};
+
+
+template
+GenericHeap::GenericHeap()
+{
+}
+
+template
+GenericHeap::~GenericHeap()
+{
+}
+
+/**
+ * GenericHeap::reset()
+ *
+ * \brief Remove all objects from queue.
+ *
+ * \return none
+ */
+template
+void GenericHeap::reset()
+{
+ table.clear();
+ _elts.resize(0);
+}
+
+/**
+* GenericHeap::add()
+ *
+ * \brief Add object into GenericHeap.
+ *
+ * \param val Object to be added
+ * \return none
+ */
+template
+void GenericHeap::add(Obj val)
+{
+ HashKey hk;
+
+ assert(table.find(hk(val)) == table.end());
+ table[hk(val)] = (unsigned int)_elts.size();
+ _elts.push_back(val);
+ heapifyUp(table[hk(val)]);
+}
+
+/**
+* GenericHeap::decreaseKey()
+ *
+ * \brief Indicate that the key for a particular object has decreased.
+ *
+ * \param val Object which has had its key decreased
+ * \return none
+ */
+template
+void GenericHeap::decreaseKey(Obj val)
+{
+
+// otherwise we get an unused variable warning when compiling in release mode
+#ifndef NDEBUG
+ EqKey eq;
+#endif
+ HashKey hk;
+
+ assert(eq(_elts[table[hk(val)]], val));
+ _elts[table[hk(val)]] = val;
+ heapifyUp(table[hk(val)]);
+}
+
+/**
+* GenericHeap::isIn()
+ *
+ * \brief Returns true if the object is in the GenericHeap.
+ *
+ * \param val Object to be tested
+ * \return true if the object is in the heap
+ */
+template
+bool GenericHeap::isIn(Obj val)
+{
+ EqKey eq;
+ HashKey hk;
+
+ if ((table.find(hk(val)) != table.end()) && (table[hk(val)] < _elts.size()) &&
+ (eq(_elts[table[hk(val)]], val)))
+ return true;
+ return false;
+}
+
+/**
+* GenericHeap::remove()
+ *
+ * \brief Remove the item with the lowest key from the heap & re-heapify.
+ *
+ * \return Object with lowest key
+ */
+template
+Obj GenericHeap::remove()
+{
+ HashKey hk;
+
+ if (empty())
+ return Obj();
+ Obj ans = _elts[0];
+ _elts[0] = _elts[_elts.size()-1];
+ table[hk(_elts[0])] = 0;
+ _elts.pop_back();
+ table.erase(hk(ans));
+ heapifyDown(0);
+
+ return ans;
+}
+
+/**
+* GenericHeap::find()
+ *
+ * \brief Find this object in the heap and return
+ *
+ * The object passed in only needs enough fields filled in to find
+ * the hash key of the object. All fields will be filled in when returned.
+ *
+ * \param val Object to find
+ * \return The same object from the heap.
+ */
+template
+Obj GenericHeap::find(Obj val)
+{
+ HashKey hk;
+
+ if (!isIn(val))
+ return Obj();
+ return _elts[table[hk(val)]];
+}
+
+/**
+ * GenericHeap::empty()
+ *
+ * \brief Returns true if no items are in the heap.
+ *
+ * \return true if no items are in the heap.
+ */
+/**
+* Returns true if no items are in the GenericHeap.
+ */
+template
+bool GenericHeap::empty()
+{
+ return _elts.size() == 0;
+}
+
+/**
+* GenericHeap::heapifyUp()
+ *
+ * \brief Check the object at the current index and see if it needs to move up the heap.
+ *
+ * An object moves up if it has a lower key than its parent.
+ *
+ * \param index Current index
+ * \return none
+ */
+template
+void GenericHeap::heapifyUp(unsigned int index)
+{
+ if (index == 0) return;
+ int parent = (index-1)/2;
+ CmpKey compare;
+ HashKey hk;
+
+ if (compare(_elts[parent], _elts[index]))
+ {
+ Obj tmp = _elts[parent];
+ _elts[parent] = _elts[index];
+ _elts[index] = tmp;
+ table[hk(_elts[parent])] = parent;
+ table[hk(_elts[index])] = index;
+#ifndef NDEBUG
+ EqKey eq;
+#endif
+ assert(!eq(_elts[parent], _elts[index]));
+ heapifyUp(parent);
+ }
+}
+
+/**
+* GenericHeap::heapifyDown()
+ *
+ * \brief Check the object at the current index and see if it needs to move down the heap.
+ *
+ * If an object has a higher key than one or more of its children, it is swapped
+ * with its lowest-valued child.
+ *
+ * \param index Current index
+ * \return none
+ */
+template
+void GenericHeap::heapifyDown(unsigned int index)
+{
+ HashKey hk;
+ CmpKey compare;
+ unsigned int child1 = index*2+1;
+ unsigned int child2 = index*2+2;
+ int which;
+ unsigned int count = (unsigned int)_elts.size();
+ // find smallest child
+ if (child1 >= count)
+ return;
+ else if (child2 >= count)
+ which = child1;
+ //else if (fless(_elts[child1]->getKey(), _elts[child2]->getKey()))
+ else if (!(compare(_elts[child1], _elts[child2])))
+ which = child1;
+ else
+ which = child2;
+
+ //if (fless(_elts[which]->getKey(), _elts[index]->getKey()))
+ if (!(compare(_elts[which], _elts[index])))
+ {
+ Obj tmp = _elts[which];
+ _elts[which] = _elts[index];
+ table[hk(_elts[which])] = which;
+ _elts[index] = tmp;
+ table[hk(_elts[index])] = index;
+ // _elts[which]->key = which;
+ // _elts[index]->key = index;
+ heapifyDown(which);
+ }
+}
+
+#endif
diff --git a/JPSPlusGoalBounding/JPSPlus.cpp b/JPSPlusGoalBounding/JPSPlus.cpp
new file mode 100644
index 0000000..367b173
--- /dev/null
+++ b/JPSPlusGoalBounding/JPSPlus.cpp
@@ -0,0 +1,985 @@
+/*
+ * JPSPlus.cpp
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "JPSPlus.h"
+
+// Ideal choice of fixed-point equivalent to 1.0 that can almost perfectly represent sqrt(2) and (sqrt(2) - 1) in whole numbers
+// 1.000000000 = 2378
+// 0.414213624 = 985 / 2378
+// 1.414213625 = 3363 / 2378
+// 1.414213562 = Actual sqrt(2)
+// 0.00000006252 = Difference between actual sqrt(2) and fixed-point sqrt(2)
+#define FIXED_POINT_MULTIPLIER 2378
+#define FIXED_POINT_SHIFT(x) ((x) * FIXED_POINT_MULTIPLIER)
+#define SQRT_2 3363
+#define SQRT_2_MINUS_ONE 985
+
+typedef const void (JPSPlus::*FunctionPointer)(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+
+JPSPlus::JPSPlus(JumpDistancesAndGoalBounds** jumpDistancesAndGoalBoundsMap, std::vector &rawMap, int w, int h)
+{
+ // Map properties
+ m_width = w;
+ m_height = h;
+
+ // Adjust preallocation for worst-case
+ m_simpleUnsortedPriorityQueue = new SimpleUnsortedPriorityQueue(10000);
+ m_fastStack = new FastStack(1000);
+
+ m_jumpDistancesAndGoalBounds = jumpDistancesAndGoalBoundsMap;
+ m_currentIteration = 1; // This gets incremented on each search
+
+ // Initialize nodes
+ InitArray(m_mapNodes, m_width, m_height);
+ for (int r = 0; r
+void JPSPlus::InitArray(T**& t, int width, int height)
+{
+ t = new T*[height];
+ for (int i = 0; i < height; ++i)
+ {
+ t[i] = new T[width];
+ memset(t[i], 0, sizeof(T)*width);
+ }
+}
+
+template
+void JPSPlus::DestroyArray(T**& t)
+{
+ for (int i = 0; i < m_height; ++i)
+ delete[] t[i];
+ delete[] t;
+
+ t = 0;
+}
+
+bool JPSPlus::GetPath(xyLocJPS& s, xyLocJPS& g, std::vector &path)
+{
+ if (path.size() > 0)
+ {
+ path.push_back(g);
+ return true;
+ }
+
+ int startRow = s.y;
+ int startCol = s.x;
+ m_goalRow = g.y;
+ m_goalCol = g.x;
+
+ {
+ // Initialize map
+ path.clear();
+
+ m_goalNode = &m_mapNodes[m_goalRow][m_goalCol];
+ m_currentIteration++;
+
+ m_fastStack->Reset();
+ m_simpleUnsortedPriorityQueue->Reset();
+ }
+
+ // Create starting node
+ PathfindingNode* startNode = &m_mapNodes[startRow][startCol];
+ startNode->m_parent = NULL;
+ startNode->m_givenCost = 0;
+ startNode->m_finalCost = 0;
+ startNode->m_listStatus = PathfindingNode::OnOpen;
+ startNode->m_iteration = m_currentIteration;
+
+ // Actual search
+ PathStatus status = SearchLoop(startNode);
+
+ if (status == PathFound)
+ {
+ FinalizePath(path);
+ if (path.size() > 0)
+ {
+ path.pop_back();
+ return false;
+ }
+ return true;
+ }
+ else
+ {
+ // No path
+ return true;
+ }
+}
+
+PathStatus JPSPlus::SearchLoop(PathfindingNode* startNode)
+{
+ // Create 2048 entry function pointer lookup table
+ #define CASE(x) &JPSPlus::Explore_ ## x ## ,
+ static const FunctionPointer exploreDirections[2048] =
+ {
+ #include "cases.h"
+ };
+ #undef CASE(x)
+
+ {
+ // Special case for the starting node
+
+ if (startNode == m_goalNode)
+ {
+ return PathFound;
+ }
+
+ JumpDistancesAndGoalBounds* jumpDistancesAndGoalBounds = &m_jumpDistancesAndGoalBounds[startNode->m_row][startNode->m_col];
+ Explore_AllDirections(startNode, jumpDistancesAndGoalBounds);
+ startNode->m_listStatus = PathfindingNode::OnClosed;
+ }
+
+ while (!m_simpleUnsortedPriorityQueue->Empty() || !m_fastStack->Empty())
+ {
+ PathfindingNode* currentNode;
+
+ if(!m_fastStack->Empty())
+ {
+ currentNode = m_fastStack->Pop();
+ }
+ else
+ {
+ currentNode = m_simpleUnsortedPriorityQueue->Pop();
+ }
+
+ if (currentNode == m_goalNode)
+ {
+ return PathFound;
+ }
+
+ // Explore nodes based on parent
+ JumpDistancesAndGoalBounds* jumpDistancesAndGoalBounds =
+ &m_jumpDistancesAndGoalBounds[currentNode->m_row][currentNode->m_col];
+
+ (this->*exploreDirections[(jumpDistancesAndGoalBounds->blockedDirectionBitfield * 8) +
+ currentNode->m_directionFromParent])(currentNode, jumpDistancesAndGoalBounds);
+
+ currentNode->m_listStatus = PathfindingNode::OnClosed;
+ }
+ return NoPathExists;
+}
+
+void JPSPlus::FinalizePath(std::vector &finalPath)
+{
+ PathfindingNode* prevNode = NULL;
+ PathfindingNode* curNode = m_goalNode;
+
+ while (curNode != NULL)
+ {
+ xyLocJPS loc;
+ loc.x = curNode->m_col;
+ loc.y = curNode->m_row;
+
+ if (prevNode != NULL)
+ {
+ // Insert extra nodes if needed (may not be neccessary depending on final path use)
+ int xDiff = curNode->m_col - prevNode->m_col;
+ int yDiff = curNode->m_row - prevNode->m_row;
+
+ int xInc = 0;
+ int yInc = 0;
+
+ if (xDiff > 0) { xInc = 1; }
+ else if (xDiff < 0) { xInc = -1; xDiff = -xDiff; }
+
+ if (yDiff > 0) { yInc = 1; }
+ else if (yDiff < 0) { yInc = -1; yDiff = -yDiff; }
+
+ int x = prevNode->m_col;
+ int y = prevNode->m_row;
+ int steps = xDiff - 1;
+ if (yDiff > xDiff) { steps = yDiff - 1; }
+
+ for (int i = 0; i < steps; i++)
+ {
+ x += xInc;
+ y += yInc;
+
+ xyLocJPS locNew;
+ locNew.x = x;
+ locNew.y = y;
+
+ finalPath.push_back(locNew);
+ }
+ }
+
+ finalPath.push_back(loc);
+ prevNode = curNode;
+ curNode = curNode->m_parent;
+ }
+ std::reverse(finalPath.begin(), finalPath.end());
+}
+
+// Macro definitions for exploring in a particular direction
+#define MacroExploreDown \
+ if (m_goalRow >= map->bounds[Down][MinRow] && \
+ m_goalRow <= map->bounds[Down][MaxRow] && \
+ m_goalCol >= map->bounds[Down][MinCol] && \
+ m_goalCol <= map->bounds[Down][MaxCol]) SearchDown(currentNode, map->jumpDistance[Down]);
+
+#define MacroExploreDownRight \
+ if (m_goalRow >= map->bounds[DownRight][MinRow] && \
+ m_goalRow <= map->bounds[DownRight][MaxRow] && \
+ m_goalCol >= map->bounds[DownRight][MinCol] && \
+ m_goalCol <= map->bounds[DownRight][MaxCol]) SearchDownRight(currentNode, map->jumpDistance[DownRight]);
+
+#define MacroExploreRight \
+ if (m_goalRow >= map->bounds[Right][MinRow] && \
+ m_goalRow <= map->bounds[Right][MaxRow] && \
+ m_goalCol >= map->bounds[Right][MinCol] && \
+ m_goalCol <= map->bounds[Right][MaxCol]) SearchRight(currentNode, map->jumpDistance[Right]);
+
+#define MacroExploreUpRight \
+ if (m_goalRow >= map->bounds[UpRight][MinRow] && \
+ m_goalRow <= map->bounds[UpRight][MaxRow] && \
+ m_goalCol >= map->bounds[UpRight][MinCol] && \
+ m_goalCol <= map->bounds[UpRight][MaxCol]) SearchUpRight(currentNode, map->jumpDistance[UpRight]);
+
+#define MacroExploreUp \
+ if (m_goalRow >= map->bounds[Up][MinRow] && \
+ m_goalRow <= map->bounds[Up][MaxRow] && \
+ m_goalCol >= map->bounds[Up][MinCol] && \
+ m_goalCol <= map->bounds[Up][MaxCol]) SearchUp(currentNode, map->jumpDistance[Up]);
+
+#define MacroExploreUpLeft \
+ if (m_goalRow >= map->bounds[UpLeft][MinRow] && \
+ m_goalRow <= map->bounds[UpLeft][MaxRow] && \
+ m_goalCol >= map->bounds[UpLeft][MinCol] && \
+ m_goalCol <= map->bounds[UpLeft][MaxCol]) SearchUpLeft(currentNode, map->jumpDistance[UpLeft]);
+
+#define MacroExploreLeft \
+ if (m_goalRow >= map->bounds[Left][MinRow] && \
+ m_goalRow <= map->bounds[Left][MaxRow] && \
+ m_goalCol >= map->bounds[Left][MinCol] && \
+ m_goalCol <= map->bounds[Left][MaxCol]) SearchLeft(currentNode, map->jumpDistance[Left]);
+
+#define MacroExploreDownLeft \
+ if (m_goalRow >= map->bounds[DownLeft][MinRow] && \
+ m_goalRow <= map->bounds[DownLeft][MaxRow] && \
+ m_goalCol >= map->bounds[DownLeft][MinCol] && \
+ m_goalCol <= map->bounds[DownLeft][MaxCol]) SearchDownLeft(currentNode, map->jumpDistance[DownLeft]);
+
+inline const void JPSPlus::Explore_Null(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ // Purposely does nothing
+}
+
+inline const void JPSPlus::Explore_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+}
+
+inline const void JPSPlus::Explore_DR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDownRight;
+}
+
+inline const void JPSPlus::Explore_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+}
+
+inline const void JPSPlus::Explore_UR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUpRight;
+}
+
+inline const void JPSPlus::Explore_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_UL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUpLeft;
+}
+
+inline const void JPSPlus::Explore_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_DL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDownLeft;
+}
+
+// Adjacent Doubles
+
+inline const void JPSPlus::Explore_D_DR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreDownRight;
+}
+
+inline const void JPSPlus::Explore_DR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDownRight;
+ MacroExploreRight;
+}
+
+inline const void JPSPlus::Explore_R_UR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreUpRight;
+}
+
+inline const void JPSPlus::Explore_UR_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUpRight;
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_U_UL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+ MacroExploreUpLeft;
+}
+
+inline const void JPSPlus::Explore_UL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUpLeft;
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_L_DL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+ MacroExploreDownLeft;
+}
+
+inline const void JPSPlus::Explore_DL_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDownLeft;
+ MacroExploreDown;
+}
+
+// Non-Adjacent Cardinal Doubles
+
+inline const void JPSPlus::Explore_D_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreRight;
+}
+
+inline const void JPSPlus::Explore_R_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_U_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_L_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+ MacroExploreDown;
+}
+
+inline const void JPSPlus::Explore_D_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_R_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreLeft;
+}
+
+// Adjacent Triples
+
+inline const void JPSPlus::Explore_D_DR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreDownRight;
+ MacroExploreRight;
+}
+
+inline const void JPSPlus::Explore_DR_R_UR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDownRight;
+ MacroExploreRight;
+ MacroExploreUpRight;
+}
+
+inline const void JPSPlus::Explore_R_UR_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreUpRight;
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_UR_U_UL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUpRight;
+ MacroExploreUp;
+ MacroExploreUpLeft;
+}
+
+inline const void JPSPlus::Explore_U_UL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+ MacroExploreUpLeft;
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_UL_L_DL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUpLeft;
+ MacroExploreLeft;
+ MacroExploreDownLeft;
+}
+
+inline const void JPSPlus::Explore_L_DL_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+ MacroExploreDownLeft;
+ MacroExploreDown;
+}
+
+inline const void JPSPlus::Explore_DL_D_DR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDownLeft;
+ MacroExploreDown;
+ MacroExploreDownRight;
+}
+
+// Non-Adjacent Cardinal Triples
+
+inline const void JPSPlus::Explore_D_R_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreRight;
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_R_U_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreUp;
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_U_L_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+ MacroExploreLeft;
+ MacroExploreDown;
+}
+
+inline const void JPSPlus::Explore_L_D_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+ MacroExploreDown;
+ MacroExploreRight;
+}
+
+// Quads
+
+inline const void JPSPlus::Explore_R_DR_D_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreDownRight;
+ MacroExploreDown;
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_R_D_DL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreDown;
+ MacroExploreDownLeft;
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_U_UR_R_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+ MacroExploreUpRight;
+ MacroExploreRight;
+ MacroExploreDown;
+}
+
+inline const void JPSPlus::Explore_U_R_DR_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+ MacroExploreRight;
+ MacroExploreDownRight;
+ MacroExploreDown;
+}
+
+inline const void JPSPlus::Explore_L_UL_U_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+ MacroExploreUpLeft;
+ MacroExploreUp;
+ MacroExploreRight;
+}
+
+inline const void JPSPlus::Explore_L_U_UR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+ MacroExploreUp;
+ MacroExploreUpRight;
+ MacroExploreRight;
+}
+
+inline const void JPSPlus::Explore_D_DL_L_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreDownLeft;
+ MacroExploreLeft;
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_D_L_UL_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreLeft;
+ MacroExploreUpLeft;
+ MacroExploreUp;
+}
+
+// Quints
+
+inline const void JPSPlus::Explore_R_DR_D_DL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreRight;
+ MacroExploreDownRight;
+ MacroExploreDown;
+ MacroExploreDownLeft;
+ MacroExploreLeft;
+}
+
+inline const void JPSPlus::Explore_U_UR_R_DR_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreUp;
+ MacroExploreUpRight;
+ MacroExploreRight;
+ MacroExploreDownRight;
+ MacroExploreDown;
+}
+
+inline const void JPSPlus::Explore_L_UL_U_UR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreLeft;
+ MacroExploreUpLeft;
+ MacroExploreUp;
+ MacroExploreUpRight;
+ MacroExploreRight;
+}
+
+inline const void JPSPlus::Explore_D_DL_L_UL_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreDownLeft;
+ MacroExploreLeft;
+ MacroExploreUpLeft;
+ MacroExploreUp;
+}
+
+inline const void JPSPlus::Explore_AllDirections(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map)
+{
+ MacroExploreDown;
+ MacroExploreDownLeft;
+ MacroExploreLeft;
+ MacroExploreUpLeft;
+ MacroExploreUp;
+ MacroExploreUpRight;
+ MacroExploreRight;
+ MacroExploreDownRight;
+}
+
+void JPSPlus::SearchDown(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Consider straight line to Goal
+ if (col == m_goalCol && row < m_goalRow)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ if ((row + absJumpDistance) >= m_goalRow)
+ {
+ unsigned int diff = m_goalRow - row;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(diff);
+ PathfindingNode * newSuccessor = m_goalNode;
+ PushNewNode(newSuccessor, currentNode, Down, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newRow = row + jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][col];
+ PushNewNode(newSuccessor, currentNode, Down, givenCost);
+ }
+}
+
+void JPSPlus::SearchDownRight(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Check for goal in general direction (straight line to Goal or Target Jump Point)
+ if (row < m_goalRow && col < m_goalCol)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ int diffRow = m_goalRow - row;
+ int diffCol = m_goalCol - col;
+ int smallerDiff = diffRow;
+ if (diffCol < smallerDiff) { smallerDiff = diffCol; }
+
+ if (smallerDiff <= absJumpDistance)
+ {
+ int newRow = row + smallerDiff;
+ int newCol = col + smallerDiff;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * smallerDiff);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, DownRight, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newRow = row + jumpDistance;
+ int newCol = col + jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, DownRight, givenCost);
+ }
+}
+
+void JPSPlus::SearchRight(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Consider straight line to Goal
+ if (row == m_goalRow && col < m_goalCol)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ if ((col + absJumpDistance) >= m_goalCol)
+ {
+ unsigned int diff = m_goalCol - col;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(diff);
+ PathfindingNode * newSuccessor = m_goalNode;
+ PushNewNode(newSuccessor, currentNode, Right, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newCol = col + jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[row][newCol];
+ PushNewNode(newSuccessor, currentNode, Right, givenCost);
+ }
+}
+
+void JPSPlus::SearchUpRight(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Check for goal in general direction (straight line to Goal or Target Jump Point)
+ if (row > m_goalRow && col < m_goalCol)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ int diffRow = row - m_goalRow;
+ int diffCol = m_goalCol - col;
+ int smallerDiff = diffRow;
+ if (diffCol < smallerDiff) { smallerDiff = diffCol; }
+
+ if (smallerDiff <= absJumpDistance)
+ {
+ int newRow = row - smallerDiff;
+ int newCol = col + smallerDiff;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * smallerDiff);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, UpRight, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newRow = row - jumpDistance;
+ int newCol = col + jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, UpRight, givenCost);
+ }
+}
+
+void JPSPlus::SearchUp(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Consider straight line to Goal
+ if (col == m_goalCol && row > m_goalRow)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ if ((row - absJumpDistance) <= m_goalRow)
+ {
+ unsigned int diff = row - m_goalRow;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(diff);
+ PathfindingNode * newSuccessor = m_goalNode;
+ PushNewNode(newSuccessor, currentNode, Up, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newRow = row - jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][col];
+ PushNewNode(newSuccessor, currentNode, Up, givenCost);
+ }
+}
+
+void JPSPlus::SearchUpLeft(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Check for goal in general direction (straight line to Goal or Target Jump Point)
+ if (row > m_goalRow && col > m_goalCol)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ int diffRow = row - m_goalRow;
+ int diffCol = col - m_goalCol;
+ int smallerDiff = diffRow;
+ if (diffCol < smallerDiff) { smallerDiff = diffCol; }
+
+ if (smallerDiff <= absJumpDistance)
+ {
+ int newRow = row - smallerDiff;
+ int newCol = col - smallerDiff;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * smallerDiff);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, UpLeft, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newRow = row - jumpDistance;
+ int newCol = col - jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, UpLeft, givenCost);
+ }
+}
+
+void JPSPlus::SearchLeft(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Consider straight line to Goal
+ if (row == m_goalRow && col > m_goalCol)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ if ((col - absJumpDistance) <= m_goalCol)
+ {
+ unsigned int diff = col - m_goalCol;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(diff);
+ PathfindingNode * newSuccessor = m_goalNode;
+ PushNewNode(newSuccessor, currentNode, Left, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newCol = col - jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + FIXED_POINT_SHIFT(jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[row][newCol];
+ PushNewNode(newSuccessor, currentNode, Left, givenCost);
+ }
+}
+
+void JPSPlus::SearchDownLeft(PathfindingNode * currentNode, int jumpDistance)
+{
+ int row = currentNode->m_row;
+ int col = currentNode->m_col;
+
+ // Check for goal in general direction (straight line to Goal or Target Jump Point)
+ if (row < m_goalRow && col > m_goalCol)
+ {
+ int absJumpDistance = jumpDistance;
+ if (absJumpDistance < 0) { absJumpDistance = -absJumpDistance; }
+
+ int diffRow = m_goalRow - row;
+ int diffCol = col - m_goalCol;
+ int smallerDiff = diffRow;
+ if (diffCol < smallerDiff) { smallerDiff = diffCol; }
+
+ if (smallerDiff <= absJumpDistance)
+ {
+ int newRow = row + smallerDiff;
+ int newCol = col - smallerDiff;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * smallerDiff);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, DownLeft, givenCost);
+ return;
+ }
+ }
+
+ if (jumpDistance > 0)
+ {
+ // Directly jump
+ int newRow = row + jumpDistance;
+ int newCol = col - jumpDistance;
+ unsigned int givenCost = currentNode->m_givenCost + (SQRT_2 * jumpDistance);
+ PathfindingNode * newSuccessor = &m_mapNodes[newRow][newCol];
+ PushNewNode(newSuccessor, currentNode, DownLeft, givenCost);
+ }
+}
+
+void JPSPlus::PushNewNode(
+ PathfindingNode * newSuccessor,
+ PathfindingNode * currentNode,
+ ArrayDirections parentDirection,
+ unsigned int givenCost)
+{
+ if (newSuccessor->m_iteration != m_currentIteration)
+ {
+ // Place node on the Open list (we've never seen it before)
+
+ // Compute heuristic using octile calculation (optimized: minDiff * SQRT_2_MINUS_ONE + maxDiff)
+ unsigned int diffrow = abs(m_goalRow - newSuccessor->m_row);
+ unsigned int diffcolumn = abs(m_goalCol - newSuccessor->m_col);
+ unsigned int heuristicCost;
+ if (diffrow <= diffcolumn)
+ {
+ heuristicCost = (diffrow * SQRT_2_MINUS_ONE) + FIXED_POINT_SHIFT(diffcolumn);
+ }
+ else
+ {
+ heuristicCost = (diffcolumn * SQRT_2_MINUS_ONE) + FIXED_POINT_SHIFT(diffrow);
+ }
+
+ newSuccessor->m_parent = currentNode;
+ newSuccessor->m_directionFromParent = parentDirection;
+ newSuccessor->m_givenCost = givenCost;
+ newSuccessor->m_finalCost = givenCost + heuristicCost;
+ newSuccessor->m_listStatus = PathfindingNode::OnOpen;
+ newSuccessor->m_iteration = m_currentIteration;
+
+ if(newSuccessor->m_finalCost <= currentNode->m_finalCost)
+ {
+ m_fastStack->Push(newSuccessor);
+ }
+ else
+ {
+ m_simpleUnsortedPriorityQueue->Add(newSuccessor);
+ }
+ }
+ else if (givenCost < newSuccessor->m_givenCost &&
+ newSuccessor->m_listStatus == PathfindingNode::OnOpen) // Might be valid to remove this 2nd condition for extra speed (a node on the closed list wouldn't be cheaper)
+ {
+ // We found a cheaper way to this node - update node
+
+ // Extract heuristic cost (was previously calculated)
+ unsigned int heuristicCost = newSuccessor->m_finalCost - newSuccessor->m_givenCost;
+
+ newSuccessor->m_parent = currentNode;
+ newSuccessor->m_directionFromParent = parentDirection;
+ newSuccessor->m_givenCost = givenCost;
+ newSuccessor->m_finalCost = givenCost + heuristicCost;
+
+ // No decrease key operation necessary (already in unsorted open list)
+ }
+}
\ No newline at end of file
diff --git a/JPSPlusGoalBounding/JPSPlus.h b/JPSPlusGoalBounding/JPSPlus.h
new file mode 100644
index 0000000..f3ed652
--- /dev/null
+++ b/JPSPlusGoalBounding/JPSPlus.h
@@ -0,0 +1,160 @@
+/*
+ * JPSPlus.h
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "PathfindingNode.h"
+#include "PrecomputeMap.h"
+#include "FastStack.h"
+#include "SimpleUnsortedPriorityQueue.h"
+#include
+
+struct xyLocJPS {
+ int16_t x;
+ int16_t y;
+};
+
+enum PathStatus
+{
+ Working,
+ PathFound,
+ NoPathExists
+};
+
+// This version of JPS+ is intimately tied with Goal Bounding.
+// Every effort has been made to maximize speed.
+// If you develop a way to improve this code or make it faster, contact steve.rabin@gmail.com
+
+class JPSPlus
+{
+public:
+ JPSPlus(JumpDistancesAndGoalBounds** jumpDistancesAndGoalBoundsMap, std::vector &rawMap, int w, int h);
+ ~JPSPlus();
+
+ bool GetPath(xyLocJPS& s, xyLocJPS& g, std::vector &path);
+
+protected:
+
+ PathStatus SearchLoop(PathfindingNode* startNode);
+ void FinalizePath(std::vector &finalPath);
+
+ // 48 function variations of exploring (used in 2048 entry look-up table)
+ // D = Down, U = Up, R = Right, L = Left, DR = Down Right, DL = Down Left, UR = Up Right, UL = Up Left
+ const void Explore_Null(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_DR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_UR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_UL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_DL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_DR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_DR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_UR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_UR_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U_UL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_UL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L_DL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_DL_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_DR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_DR_R_UR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_UR_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_UR_U_UL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U_UL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_UL_L_DL(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L_DL_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_DL_D_DR(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_R_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_U_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U_L_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L_D_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_DR_D_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_D_DL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U_UR_R_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U_R_DR_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L_UL_U_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L_U_UR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_DL_L_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_L_UL_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_R_DR_D_DL_L(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_U_UR_R_DR_D(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_L_UL_U_UR_R(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_D_DL_L_UL_U(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+ const void Explore_AllDirections(PathfindingNode * currentNode, JumpDistancesAndGoalBounds * map);
+
+ void SearchDown(PathfindingNode * currentNode, int jumpDistance);
+ void SearchDownRight(PathfindingNode * currentNode, int jumpDistance);
+ void SearchRight(PathfindingNode * currentNode, int jumpDistance);
+ void SearchUpRight(PathfindingNode * currentNode, int jumpDistance);
+ void SearchUp(PathfindingNode * currentNode, int jumpDistance);
+ void SearchUpLeft(PathfindingNode * currentNode, int jumpDistance);
+ void SearchLeft(PathfindingNode * currentNode, int jumpDistance);
+ void SearchDownLeft(PathfindingNode * currentNode, int jumpDistance);
+
+ void PushNewNode(PathfindingNode * newSuccessor, PathfindingNode * currentNode, ArrayDirections parentDirection, unsigned int givenCost);
+
+ // 2D array initialization and destruction
+ template void InitArray(T**& t, int width, int height);
+ template void DestroyArray(T**& t);
+
+ // Map properties
+ int m_width, m_height;
+
+ // Open list structures
+ FastStack* m_fastStack;
+ SimpleUnsortedPriorityQueue* m_simpleUnsortedPriorityQueue;
+
+ // Precomputed data
+ JumpDistancesAndGoalBounds** m_jumpDistancesAndGoalBounds;
+
+ // Preallocated nodes
+ PathfindingNode** m_mapNodes;
+
+ // Search specific info
+ unsigned short m_currentIteration; // This allows us to know if a node has been touched this iteration (faster than clearing all the nodes before each search)
+ PathfindingNode* m_goalNode;
+ int m_goalRow, m_goalCol;
+};
+
diff --git a/JPSPlusGoalBounding/JPSPlusGoalBounding.sln b/JPSPlusGoalBounding/JPSPlusGoalBounding.sln
new file mode 100644
index 0000000..9242058
--- /dev/null
+++ b/JPSPlusGoalBounding/JPSPlusGoalBounding.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JPSPlusGoalBounding", "JPSPlusGoalBounding.vcxproj", "{32176719-9104-4AF2-841F-EFCCA868B47A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {32176719-9104-4AF2-841F-EFCCA868B47A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {32176719-9104-4AF2-841F-EFCCA868B47A}.Debug|Win32.Build.0 = Debug|Win32
+ {32176719-9104-4AF2-841F-EFCCA868B47A}.Release|Win32.ActiveCfg = Release|Win32
+ {32176719-9104-4AF2-841F-EFCCA868B47A}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/JPSPlusGoalBounding/JPSPlusGoalBounding.sln.docstates.suo b/JPSPlusGoalBounding/JPSPlusGoalBounding.sln.docstates.suo
new file mode 100644
index 0000000..d4331fc
Binary files /dev/null and b/JPSPlusGoalBounding/JPSPlusGoalBounding.sln.docstates.suo differ
diff --git a/JPSPlusGoalBounding/JPSPlusGoalBounding.suo b/JPSPlusGoalBounding/JPSPlusGoalBounding.suo
new file mode 100644
index 0000000..1e46a5f
Binary files /dev/null and b/JPSPlusGoalBounding/JPSPlusGoalBounding.suo differ
diff --git a/JPSPlusGoalBounding/JPSPlusGoalBounding.vcxproj b/JPSPlusGoalBounding/JPSPlusGoalBounding.vcxproj
new file mode 100644
index 0000000..f9340a8
--- /dev/null
+++ b/JPSPlusGoalBounding/JPSPlusGoalBounding.vcxproj
@@ -0,0 +1,123 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {32176719-9104-4AF2-841F-EFCCA868B47A}
+ Win32Proj
+ JPSPlusGoalBounding
+
+
+
+ Application
+ true
+ Unicode
+
+
+ Application
+ false
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ AnySuitable
+ Speed
+ false
+ false
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JPSPlusGoalBounding/Map.cpp b/JPSPlusGoalBounding/Map.cpp
new file mode 100644
index 0000000..82359fd
--- /dev/null
+++ b/JPSPlusGoalBounding/Map.cpp
@@ -0,0 +1,403 @@
+/*
+ * Map.cpp
+ *
+ * Copyright (c) 2007, Nathan Sturtevant
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of Alberta nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NATHAN STURTEVANT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "Map.h"
+#include
+#include
+
+using namespace std;
+
+static const bool verbose = false;
+
+/**
+* Map::Map()
+*
+* \brief Create a new map of a particular size.
+*
+* A map is an array of tiles according to the height and width of the map.
+*
+* \param wide The new map width
+* \param high The new map height
+* \return none
+*/
+Map::Map(uint32_t wide, uint32_t high)
+:width(wide), height(high)
+{
+ map_name[0] = 0;
+ land.resize(height*width);
+ for (uint32_t x = 0; x < land.size(); x++)
+ land[x] = 1;
+
+}
+
+/**
+* Map::Map()
+*
+* \brief Create a new map by loading it from a file.
+*
+* Creates a new map and initializes it with the file passed to it.
+*
+* \param filename The path of a file containing a map.
+* \return none
+*/
+Map::Map(const char *filename)
+{
+ Load(filename);
+}
+
+/**
+* Map::Map()
+*
+* \brief Create a new map by loading it from a file pointer.
+*
+* Creates a new map and initializes it with the file pointer passed to it.
+*
+* \param f A file pointer ready to read the beginning of a map within a file
+*/
+Map::Map(FILE *f)
+{
+ map_name[0] = 0;
+ land.resize(0);
+ Load(f);
+}
+
+Map::~Map()
+{
+}
+
+/**
+* Map::Scale()
+ *
+ * \brief Scale a map to the new size
+ *
+ * \param newWidth The new width of the map
+ * \param newHeight The new height of the map
+ */
+void Map::Scale(uint32_t newWidth, uint32_t newHeight)
+{
+ std::vector newLand;
+ newLand.resize(newWidth*newHeight);
+ for (uint32_t x = 0; x < newWidth; x++)
+ {
+ for (uint32_t y = 0; y < newHeight; y++)
+ {
+ newLand[GetIndex(x, y)] = land[GetIndex((x*width)/newWidth,
+ (y*height)/newHeight)];
+ }
+ }
+ land = newLand;
+ width = newWidth;
+ height = newHeight;
+ updated = true;
+ map_name[0] = 0;
+}
+
+/**
+* Map::Load()
+*
+* \brief Resets the current map by loading the file passed in.
+*
+* Resets the current map by loading the file passed in.
+*
+* \param filename The file to load
+* \return none
+*/
+void Map::Load(const char *filename)
+{
+ land.resize(0);
+ FILE *f = fopen(filename, "r");
+ if (f)
+ {
+ Load(f);
+ fclose(f);
+ strncpy(map_name, filename, 128);
+ }
+ else {
+ printf("Error! Can't open file %s\n", filename);
+ width = height = 64;
+ land.resize(height*width);
+
+ updated = true;
+ map_name[0] = 0;
+ }
+}
+
+/**
+* Map::Load()
+*
+* \brief Resets the current map by loading the file from the pointer passed in.
+*
+* Resets the current map by loading the file from the pointer passed in.
+*
+* Loads an octile map according to the following format.
+* The header includes 4 lines:
+* type octile\n
+* height \n
+* width \n
+* map\n
+*
+* \param f A (open) file pointer read to read from the file.
+* \return none
+*/
+void Map::Load(FILE *f)
+{
+ land.resize(0);
+
+ char format[32];
+ // ADD ERROR HANDLING HERE
+ int num = fscanf(f, "type %s\nheight %u\nwidth %u\nmap\n", format, &height, &width);
+ if (num == 3)
+ {
+ if (strcmp(format, "octile") == 0)
+ {
+ printf("Loading octile %ux%u\n", width, height);
+ LoadOctile(f, height, width);
+ }
+ }
+}
+
+/**
+* Map::LoadOctile()
+ *
+ * \brief Helper function for loading an octile map
+ *
+ * After the header has been ready,
+ * following header lines there is a "@" or an "O" for blocked land
+ * and any other character for unblocked land.
+ *
+ * \param f and open file pointer
+ * \param high The height of the map being loaded (number of lines)
+ * \param wide The width of the map being loaded (column width)
+ * \return none
+ */
+void Map::LoadOctile(FILE *f, int high, int wide)
+{
+ height = high;
+ width = wide;
+ updated = true;
+ land.resize(high*wide);
+ for (int y = 0; y < high; y++)
+ {
+ for (int x = 0; x < wide; x++)
+ {
+ char what;
+ fscanf(f, "%c", &what);
+ switch (toupper(what))
+ {
+ case '@':
+ case 'O':
+ land[GetIndex(x, y)] = 0;
+ break;
+ default:
+ land[GetIndex(x, y)] = 1;
+ break;
+ }
+ fscanf(f, "\n");
+ }
+ }
+}
+
+/**
+* Map::Save()
+*
+* \brief Saves the current map out to the designated file.
+*
+* \param filename The filename to save the map in.
+* \return none
+*/
+void Map::Save(const char *filename)
+{
+ FILE *f = fopen(filename, "w+");
+ if (f)
+ {
+ Save(f);
+ fclose(f);
+ }
+ else {
+ printf("Error! Couldn't open file to save\n");
+ }
+}
+
+/**
+* Map::Save()
+*
+* \brief Saves the current map out to the designated file.
+*
+* Saves the current map out to the designated file.
+*
+* \param f An open file pointer
+* \return none
+*/
+void Map::Save(FILE *f)
+{
+ SaveOctile(f);
+}
+
+/**
+* Map::SaveOctile()
+ *
+ * \brief Write out using the octile map format
+ *
+ * \param f An open file pointer
+ * \return none
+ */
+void Map::SaveOctile(FILE *f)
+{
+ if (f)
+ {
+ fprintf(f, "type octile\nheight %u\nwidth %u\nmap\n", height, width);
+ for (uint32_t y = 0; y < height; y++)
+ {
+ for (uint32_t x = 0; x < width; x++)
+ {
+ switch (land[GetIndex(x, y)])
+ {
+ case 0: fprintf(f, "@"); break;
+ default:
+ case 1: fprintf(f, "."); break;
+ }
+ }
+ fprintf(f, "\n");
+ }
+ }
+}
+
+/**
+* Map::GetMapName()
+ *
+ * \brief Returns the file name of the map, if available
+ *
+ * \return A pointer to a string containing the name of the map.
+ */
+
+const char *Map::GetMapName()
+{
+ if (map_name[0] == 0)
+ return "";
+ return map_name;
+}
+
+
+/**
+* Map::GetTerrainType()
+ *
+ * \brief Get the terrain at a particular coordinate.
+ *
+ * \param x The x-coordinate to query
+ * \param y The y-coordinate to query
+ * \return The terrain at that coordinate
+ */
+tTerrain Map::GetTerrainType(uint32_t x, uint32_t y)
+{
+ int index = GetIndex(x, y);
+ if (index == -1)
+ return kOutOfBounds;
+ if (land[index] == 0)
+ return kOutOfBounds;
+ return kGround;
+}
+
+/**
+* Map::SetTerrainType()
+ *
+ * \brief Set the terrain at a particular coordinate.
+ *
+ * \param x The x-coordinate to set
+ * \param y The y-coordinate to set
+ * \param terrain The terrain for that coordinate
+ * \return none
+ */
+void Map::SetTerrainType(uint32_t x, uint32_t y, tTerrain terrain)
+{
+ updated = true;
+ int index = GetIndex(x, y);
+ if (index == -1)
+ return;
+ if (terrain == kOutOfBounds)
+ land[index] = 0;
+ else
+ land[index] = 1;
+}
+
+/**
+* Map::SetTerrainType()
+ *
+ * \brief Set all the terrain between two points to be the same
+ *
+ * \param x1 The first x-coordinate to set
+ * \param y1 The first y-coordinate to set
+ * \param x2 The second x-coordinate to set
+ * \param y2 The second y-coordinate to set
+ * \param terrain The terrain for the line between the coordinates
+ * \return none
+ */
+void Map::SetTerrainType(int32_t x1, int32_t y1,
+ int32_t x2, int32_t y2, tTerrain t)
+{
+ updated = true;
+ //printf("---> (%d, %d) to (%d, %d)\n", x1, y1, x2, y2);
+ double xdiff = (int)x1-(int)x2;
+ double ydiff = (int)y1-(int)y2;
+ double dist = sqrt(xdiff*xdiff + ydiff*ydiff);
+ SetTerrainType(x1, y1, t);
+ for (double c = 0; c < dist; c += 0.5)
+ {
+ double ratio = c/dist;
+ double newx = (double)x1-xdiff*ratio;
+ double newy = (double)y1-ydiff*ratio;
+ SetTerrainType((uint32_t)newx, (uint32_t)newy, t);
+ }
+ SetTerrainType(x2, y2, t);
+}
+
+/**
+* Map::SetTerrainType()
+ *
+ * \brief Set the terrain at a radius from a point to be the same
+ *
+ * \param x The center x-coordinate
+ * \param y The center y-coordinate
+ * \param radius The radius of the circle
+ * \param terrain The terrain for the circle
+ * \return none
+ */
+void Map::SetTerrainType(int32_t x, int32_t y, int32_t radius, tTerrain t)
+{
+ updated = true;
+ for (int x2 = -radius; x2 <= radius; x2++)
+ {
+ for (int y2 = -radius; y2 <= radius; y2++)
+ {
+ if ((x+x2 >= 0) && (y+y2 >= 0))
+ if ((x2*x2+y2*y2) < radius*radius)
+ SetTerrainType(x+x2, y+y2, t);
+ }
+ }
+}
diff --git a/JPSPlusGoalBounding/Map.h b/JPSPlusGoalBounding/Map.h
new file mode 100644
index 0000000..1b5a785
--- /dev/null
+++ b/JPSPlusGoalBounding/Map.h
@@ -0,0 +1,126 @@
+/*
+ * Map.h
+ *
+ * Copyright (c) 2007, Nathan Sturtevant
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of Alberta nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NATHAN STURTEVANT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef _MSC_VER
+#include "stdafx.h"
+#else
+#include
+#endif
+
+#ifndef UINT32_MAX
+#define UINT32_MAX 4294967295U
+#endif
+
+#ifndef MAP_H
+#define MAP_H
+
+static const double ONE = 1.0f;
+static const double TWO = 2.0f;
+static const double ROOT_TWO = 1.414213562f;//or 1.5f if desired
+static const double ONE_OVER_ROOT_TWO = 1.0/ROOT_TWO;//0.707106781f;
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#define uint32_t unsigned int
+//#define int32_t int
+
+/**
+* Terrain is simple here, either out-of-bounds or passable.
+ * In reality a much more complex mode could be used for passibility,
+ * but this suffices for now.
+ */
+
+enum tTerrain {
+ kOutOfBounds,
+ kGround
+};
+
+/**
+*
+ * Map
+ *
+ * This code is simplified from a more complex map structure.
+ * This map class
+ *
+ */
+class Map {
+public:
+ Map(uint32_t width, uint32_t height);
+ Map(const char *filename);
+ Map(Map *);
+ Map(FILE *);
+ ~Map();
+ void Load(const char *filename);
+ void Load(FILE *f);
+ void Scale(uint32_t newWidth, uint32_t newHeight);
+ void Save(const char *filename);
+ void Save(FILE *f);
+ const char *GetMapName();
+
+ /** return the width of the map */
+ inline uint32_t GetMapWidth() const { return width; }
+ /** return the height of the map */
+ inline uint32_t GetMapHeight() const { return height; }
+
+ tTerrain GetTerrainType(uint32_t x, uint32_t y);
+ void SetTerrainType(uint32_t x, uint32_t y, tTerrain);
+ void SetTerrainType(int32_t x1, int32_t y1,
+ int32_t x2, int32_t y2, tTerrain);
+ void SetTerrainType(int32_t x, int32_t y, int32_t radius, tTerrain);
+private:
+ /** Given an x/y coordinate, compute the index in the land vector */
+ inline int GetIndex(uint32_t x, uint32_t y)
+ {
+ if (x >= width) return -1;
+ if (y >= height) return -1;
+ return y*width+x;
+ }
+ /** Given a location in the land vector, get the x/y coordinate */
+ inline void GetCoordinate(int loc, uint32_t &x, uint32_t &y)
+ {
+ y = loc/width;
+ x = loc%width;
+ }
+
+ void LoadOctile(FILE *f, int height, int width);
+ void SaveOctile(FILE *f);
+ void DrawLandQuickly();
+ uint32_t width, height;
+ std::vector land;
+ char map_name[128];
+ bool updated;
+};
+
+#endif
diff --git a/JPSPlusGoalBounding/Maps/maze-100-1.map b/JPSPlusGoalBounding/Maps/maze-100-1.map
new file mode 100644
index 0000000..0f85539
--- /dev/null
+++ b/JPSPlusGoalBounding/Maps/maze-100-1.map
@@ -0,0 +1,104 @@
+type octile
+height 100
+width 100
+map
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@.......@.......@.@...........@...............@...@.....@...@.@.........@.......@.......@...........
+@.@@@@@.@@@@@.@.@.@@@.@@@@@.@@@.@.@.@@@@@@@@@@@.@.@.@@@.@.@.@.@@@.@@@@@@@.@@@.@@@.@@@@@@@@@.@@@@@@@.
+@.....@.......@.....@.....@.....@.@...........@.@...@...@.@.@...@...@.....@.....@.........@.....@...
+@.@@@.@@@@@@@@@@@@@@@.@@@@@@@@@@@@@@@@@@@@@.@@@.@@@@@@@.@.@.@.@@@.@.@.@.@@@.@@@.@.@@@.@@@@@@@@@.@.@@
+@.@.@.................@.....@...@.....@...@.@...@.....@.@.@.@.....@...@.@.....@.@...@.......@...@...
+@.@.@@@@@.@@@@@@@@@@@@@.@@@.@.@.@@@.@.@.@.@.@.@@@.@.@@@.@.@.@@@@@@@@@@@.@.@@@@@.@.@@@@@.@@@@@.@@@@@.
+@.@.....@.@.........@...@.....@.@...@.@.@...@.....@...@.@.@.........@...@.@...@.@.@.....@.......@...
+@.@@@.@.@@@.@@@@@.@@@.@.@.@@@@@.@.@@@.@.@@@@@@@.@@@@@.@.@.@@@@@@@@@.@.@@@.@@@.@.@@@@@@@.@.@@@@@@@@@.
+@...@.@.........@.@...@.@.@...@...@...@.....@.@.@...@.@.....@.@.......@.@.....@.@.......@.....@...@.
+@@@.@.@@@@@@@.@@@.@.@.@@@.@@@.@@@@@@@.@@@.@@@.@.@.@@@.@@@@@@@.@.@.@@@.@.@.@@@@@@@.@@@@@@@.@@@@@.@.@.
+@...@...@...@.@.....@.@.....@.@.....@...@...@...@...@.....@...@.@...@...@.......@...@.....@.....@...
+@.@@@@@.@.@.@@@@@@@@@.@@@.@.@.@.@@@.@@@.@@@.@.@@@@@.@.@@@.@.@@@.@@@.@.@@@@@@@.@@@@@.@.@@@@@.@@@@@@@@
+@.@...@.@.@.........@...@.@...@.@...@.......@.....@.@...@.@.......@.@.......@.....@.....@.@.@.......
+@.@.@@@@@.@@@.@@@@@.@.@.@.@.@@@.@.@.@@@@@@@@@@@.@@@.@@@@@.@.@@@@@@@.@@@.@@@@@.@@@.@@@@@.@.@.@.@@@.@@
+@.@...@...@.@.@...@.@.@.@.@.@...@.@...@.........@.........@.@.....@.@.@.@...@.@.@.....@...@.....@...
+@.@@@.@.@@@.@@@.@.@.@@@.@.@@@.@@@.@@@@@.@@@@@@@@@@@@@@@.@@@.@.@@@.@.@.@@@.@.@.@.@@@@@.@@@.@@@.@.@@@.
+@.....@.@...@...@.@.@...@...@...@.@.........@.......@.@.@.@.@...@.@.....@.@...@.....@.@.....@.@.@...
+@.@@@@@.@.@@@.@.@@@.@.@.@.@@@@@@@.@.@.@.@@@@@@@.@@@@@.@.@.@@@@@@@.@@@@@.@.@@@@@.@@@.@.@@@.@@@@@.@.@@
+@.@.....@.....@...@.@.@.@.......@.@.@.@.@.........@...@.@.......@.....@.@.....@.@...@...@...@...@...
+@.@.@@@.@@@.@@@@@.@.@.@@@@@@@@@.@.@.@@@@@.@@@@@@@.@@@.@.@@@@@@@.@@@.@@@.@@@@@.@@@.@@@.@@@@@@@@@.@@@.
+@.@...@.@.....@.......@...@.......@...@.........@...@.....@.....@...@...@...@.@.@...........@.....@.
+@.@@@.@@@@@@@@@@@@@@@@@@@.@@@.@@@@@.@@@@@.@@@@@@@@@.@@@.@@@.@@@@@@@.@.@@@.@@@.@.@@@@@@@@@@@.@@@@@@@.
+@...@...........@.......@.....@...@...@...@.....@...@.....@.....@.....@.......@.....@.....@.........
+@.@@@@@@@.@.@@@@@@@.@@@.@@@@@@@.@.@@@.@.@@@.@@@.@.@@@.@@@@@@@@@.@@@@@.@.@.@@@@@@@.@.@.@@@@@.@@@@@@@@
+@.@...@...@.@.......@.....@...@.@.....@...@.@...@...@...@.......@...@.@.@.@.@.....@.@...@...@.......
+@.@@@.@.@@@@@.@@@@@@@.@.@@@.@.@.@@@@@@@@@.@.@@@.@.@@@@@.@.@@@@@@@.@.@@@.@@@.@.@.@@@.@@@.@@@.@@@@@.@@
+@.....@.....@.@.@.@...@.....@...@.........@.@...@.....@.@...@.....@.@.......@.@.@.@.@...........@...
+@@@@@@@@@@@.@.@.@.@@@.@@@.@@@@@@@.@@@@@@@@@.@.@@@@@@@.@.@@@.@.@@@@@.@.@@@@@@@.@@@.@@@.@@@@@@@@@.@@@.
+@...........@...@.......@.......@...@.......@.@.......@...@.@.@.@...@.....@...@.....@.@.........@...
+@.@@@@@@@@@@@@@.@.@@@@@@@@@@@@@.@@@.@.@@@@@.@.@.@@@@@@@.@@@.@.@.@@@@@.@.@.@.@@@.@@@.@.@@@.@@@@@@@.@@
+@.........@.....@.@...@.......@.....@.@...@.@...@.........@.@.......@.@.@.@.....@...@...@.......@...
+@.@@@@@@@.@.@@@@@.@.@@@.@@@@@.@@@@@@@.@.@.@@@@@@@@@@@@@@@.@.@@@.@@@.@.@@@.@@@@@@@.@.@@@@@.@@@@@.@@@.
+@.......@.....@.....@...@...@...@.....@.@...........@...@.@...@.@.@...@.......@...@.@.....@...@.@...
+@.@@@@@@@@@.@@@.@@@@@.@@@@@.@@@.@.@@@@@.@@@@@@@@@@@.@.@.@.@@@.@.@.@@@@@@@@@@@.@.@@@@@@@@@@@.@@@.@.@@
+@.@.......@.@...@.@...@.@.........@.....@.......@...@.@.@.@...@...@.@.....@...@.@...@.....@...@.@...
+@.@.@@@.@@@.@.@@@.@.@@@.@@@@@@@@@@@.@.@@@.@.@@@@@.@@@.@.@.@.@@@.@@@.@.@@@.@@@@@.@.@.@@@.@.@.@@@.@@@.
+@.@...@...@.@.@...@...@.............@.@...@.@.....@...@.@.....@.@.....@.@.@.....@.@.@...@...@.@...@.
+@@@@@.@@@.@@@.@.@@@@@.@.@@@@@.@.@@@@@@@.@.@@@.@@@@@.@@@.@@@@@.@@@.@.@@@.@.@.@@@@@.@@@.@@@@@.@.@@@.@.
+@...@...@.@.@.@.........@.....@.@.@...@.@...@.....@...@...@.......@.@.@.....@.............@.@...@...
+@@@.@@@.@.@.@.@@@@@@@@@@@.@@@@@@@.@.@@@@@.@@@@@@@.@@@.@.@@@@@.@@@@@@@.@@@.@@@.@@@@@@@@@@@.@@@.@@@@@.
+@.@.....@...@.......@.....@.....@.......@...@.......@.@.....@.@...@.....@.@.@.@.@.........@...@.....
+@.@@@@@@@@@.@@@.@@@.@@@.@@@.@.@@@@@@@.@@@.@.@.@.@.@@@.@@@@@.@@@.@.@.@@@@@@@.@.@.@.@@@.@@@@@.@@@.@@@@
+@...@.........@.@.@.@.....@.@.........@...@...@.@.@.....@.......@.@.....@...@.@.@...@.@.......@...@.
+@@@.@.@@@@@@@.@.@.@.@@@@@.@.@@@@@.@.@@@.@@@@@.@@@@@@@@@.@.@@@@@@@.@.@@@.@.@.@.@.@@@.@@@@@.@@@.@.@@@.
+@...@.@.....@...@...@...@.@...@.@.@.@.....@...@.........@.@.......@.@.@...@.@.....@.@.....@...@...@.
+@.@.@.@@@.@@@@@@@.@@@@@.@.@@@.@.@@@.@.@@@.@@@@@.@.@@@@@@@.@@@.@@@@@@@.@.@.@@@@@.@@@.@.@@@@@@@.@.@@@.
+@.@.@...@.....@...@.....@...@...@...@...@.@.....@...@...@.@.@.@.....@...@.@.....@...@.@...@...@.....
+@.@@@@@.@.@.@@@.@@@@@@@.@.@@@.@@@.@@@@@.@@@.@.@@@.@@@.@.@.@.@.@.@@@@@.@@@@@.@@@@@.@@@.@@@.@@@.@.@@@@
+@.....@.@.@.@...@.......@...@.@...@.......@.@...@.@...@.@...@...@.@.@...........@.@.......@.@...@...
+@@@@@.@.@.@.@.@@@.@@@@@.@@@.@.@@@.@@@.@@@@@.@@@.@@@.@@@.@@@@@@@.@.@.@@@@@@@@@@@@@.@@@@@@@@@.@.@@@@@.
+@.....@.@.@.@.@.@...@.@...@.@...@...@.......@...@...@...@.....@.@...........@.@.............@.......
+@@@@@.@.@@@.@.@.@@@.@.@.@.@.@@@@@@@.@@@@@@@@@.@@@.@@@.@@@.@@@.@@@.@@@.@@@@@.@.@@@.@@@@@@@@@.@@@@@@@.
+@.@...@.....@.@...@.@.@.@...@...............@.....@.@.@.....@...@.@.@.@.....@...@.@.......@.@...@...
+@.@@@.@@@.@@@.@.@.@.@.@.@@@@@.@@@@@@@@@@@@@@@@@@@@@.@.@@@@@.@@@.@@@.@@@@@.@@@.@@@.@.@@@@@.@.@@@.@@@.
+@.......@...@.@.@.@.@...@.......@.................@.@.@...@...@.......@...@...@...@.@.....@.......@.
+@.@@@@@.@@@.@.@@@.@.@.@@@@@@@.@.@.@@@@@@@.@.@@@.@.@.@.@.@.@.@@@@@@@@@.@.@@@@@.@.@@@.@.@@@.@@@@@@@.@.
+@...@...@...@.@...@.@.......@.@.@...@...@.@.@...@.@.@...@...@.@...@.....@.....@.@...@...@.@...@...@.
+@.@.@@@@@.@@@.@@@.@.@@@@@@@.@.@.@@@.@.@.@@@@@.@@@.@.@.@@@@@@@.@.@@@.@@@@@.@@@@@.@@@@@@@.@.@.@.@.@.@@
+@.@.......@.@.@...@.@.....@.@.@.....@.@.......@.....@.@.@.........@.@.@.................@.@.@...@...
+@.@@@@@@@@@.@.@.@@@.@.@.@@@.@@@@@.@@@.@@@@@@@@@@@@@@@.@.@@@.@@@@@.@.@.@.@@@@@@@@@@@@@@@.@@@.@@@@@@@.
+@...@.......@.@.@.@.@.@...@.....@.@.@.....@.......@.......@.@...@...@.@...@...@...........@.@.@...@.
+@.@@@@@@@@@.@.@.@.@.@@@.@.@@@@@.@.@.@@@@@.@.@@@@@.@@@@@@@.@.@@@.@@@@@.@.@@@.@@@@@@@@@@@@@@@.@.@.@@@.
+@.@.........@.@...@.....@...@.@.@.@.@...@.....@...@...@...@.....@.....@.@.....@.............@.......
+@.@.@@@@@.@@@.@.@@@@@@@.@@@.@.@.@.@.@.@.@@@@@@@.@@@.@.@@@@@.@@@@@.@@@@@.@.@@@@@.@@@@@@@@@@@@@@@.@.@@
+@...@.@.....@.@.@.....@.@.@...@.@.@...@...@...@.@...@.@.......@...@...@.@.....@.....@.....@.....@.@.
+@@@@@.@.@@@@@.@.@@@.@@@@@.@@@.@.@.@@@@@@@.@.@.@.@@@.@@@@@.@@@.@.@@@.@.@.@@@.@@@@@@@.@.@.@.@.@@@.@@@.
+@.@.......@...@...@...@.......@.@...@.....@.@...@...@.....@...@.....@.......@.......@.@.@.@...@.....
+@.@.@@@.@@@@@@@.@@@.@.@@@@@@@@@.@@@.@.@@@.@.@@@@@.@@@.@@@@@.@@@.@@@@@@@@@@@@@.@@@@@@@.@@@.@@@.@.@@@@
+@.....@...@...@.....@.............@...@...@.........@.@...@.@.@...@.....@...@.....@...@.@.@...@.@...
+@.@@@@@@@@@.@.@.@@@@@@@@@@@.@.@@@@@@@@@.@@@@@@@@@.@@@.@@@.@.@.@@@.@@@@@.@.@.@@@.@.@.@@@.@.@.@@@.@@@.
+@.@.........@...@.....@.@.@.@.@.......@...@.@.........@...@.@.@...@.....@.@.....@.@.@.....@...@.@...
+@.@@@.@@@@@@@@@@@.@@@.@.@.@@@@@@@@@.@.@@@.@.@@@.@@@@@.@.@.@.@.@@@.@.@@@@@.@@@@@@@@@.@.@@@@@@@@@.@.@@
+@.@.@.@...@.......@.....@.@.........@...@.....@...@.@.@.@.@.....@.@.@.....@.........@.........@...@.
+@.@.@.@.@@@.@@@@@@@@@@@.@.@@@.@.@.@.@@@.@.@.@@@@@.@.@.@.@@@.@@@@@.@.@.@@@.@.@.@@@@@@@@@.@@@@@@@@@.@.
+@.@.@.@...@.......@.........@.@.@.@...@.@.@.@.@.@.@.@.@...@...@.....@...@.@.@.@.@.........@...@...@.
+@.@.@@@.@.@@@@@@@.@@@@@@@@@.@@@@@.@@@.@.@@@@@.@.@.@.@@@@@.@@@.@@@@@.@@@.@@@.@.@.@.@.@@@@@.@@@.@@@.@.
+@.....@.@.....@.......@.@.....@.....@.@.......@...@.....@...@.@.......@.....@.@.@.@...@...@.....@...
+@.@@@.@@@@@@@.@@@.@@@.@.@.@@@@@@@@@@@.@@@@@@@.@.@@@@@.@.@@@.@.@@@@@@@@@@@@@@@.@.@@@@@.@@@.@.@.@@@@@@
+@.@...@.......@...@...@...@.......@...@...@.@.@.....@.@.....@.@...............@.....@...@...@.@.....
+@@@@@.@.@@@@@.@@@@@.@@@.@@@.@@@@@.@.@@@.@.@.@.@.@.@@@.@@@@@.@.@@@.@@@@@@@@@@@@@@@.@.@.@@@@@@@@@.@@@.
+@.@.@.@.@...@.......@...@...@.....@.....@.@...@.@.@...@...@.@...@.....@.........@.@.@.@.....@...@...
+@.@.@.@.@@@.@@@@@@@@@.@@@.@.@@@@@.@.@@@@@.@.@@@.@@@@@.@.@.@@@.@@@.@@@.@@@@@.@.@@@@@.@.@@@@@.@.@@@.@@
+@...@.@.@...@.......@.....@.@...@.@...@...@...@.@.....@.@.....@.....@.@.....@...@...@.@.........@...
+@@@.@.@.@.@@@.@@@@@.@@@.@@@@@@@.@.@.@@@.@@@@@@@.@.@.@@@.@@@@@@@@@@@@@.@.@@@@@.@@@.@.@.@.@@@@@@@@@.@@
+@...@...@.....@.......@.@.......@.@.@.......@...@.@...@.@...@.........@.....@.@...@.@.@.......@.....
+@@@.@@@@@.@@@@@.@@@@@@@@@@@.@@@.@.@.@@@.@@@@@.@@@@@.@.@.@.@.@.@@@@@@@@@.@@@.@@@.@.@@@.@@@@@@@.@@@@@.
+@.......@.@...@.............@.@.@.@.@...@.....@...@.@.@.@.@.@...@.....@.@.....@.@.@...@...@.@.@.....
+@.@@@@@@@.@.@.@@@@@@@@@@@.@@@.@@@.@@@.@@@.@@@@@.@.@@@.@.@.@.@@@.@@@.@@@.@@@.@.@.@@@@@.@.@.@.@.@.@@@.
+@.......@.@.@...........@...@.....@.....@.@...@.@...@.@.@.@.....@...@...@...@.@.....@...@.@...@.@...
+@@@.@@@.@.@@@.@.@@@@@.@.@@@.@.@@@@@.@@@@@.@.@@@.@@@@@.@.@.@@@.@.@.@@@.@@@.@@@.@.@@@.@@@@@.@@@.@.@@@@
+@.@.@...@...@.@...@...@...@.........@.....@.....@.......@...@.@.@.....@.@...@.@...@.....@.@...@.....
+@.@.@@@.@@@.@@@@@@@.@@@@@.@@@@@.@@@@@@@.@@@.@@@@@.@@@.@@@.@.@@@.@.@@@@@.@@@.@.@@@@@.@@@.@.@@@.@@@@@.
+@.@.@.@...@.@.........@.....@.@...@...@.@...@.......@...@.@.@.@.@.@.....@...@.....@...@.@.@.....@...
+@.@.@.@@@.@.@@@@@.@@@@@@@@@.@.@@@@@.@.@.@.@.@@@@@@@@@@@.@@@.@.@.@.@@@@@.@.@@@@@.@.@@@.@@@.@.@@@@@.@.
+@.@...@...@.@...@.......@.....@.....@.@.@.@.......@...@.....@.@.@...@...@...@.@.@.@...@...@.@.....@.
+@.@.@@@@@.@.@.@.@@@.@.@@@@@@@.@.@@@@@.@.@@@@@@@@@.@@@.@@@@@@@.@.@@@.@@@.@@@.@.@@@.@.@@@.@@@.@.@@@@@.
+@.@.@.....@.@.@...@.@.@.@.@.....@.....@.@.........@...........@.@.........@.@...@.@.@...@...@.@...@.
+@.@.@@@.@@@.@.@@@.@.@@@.@.@.@@@.@.@@@@@.@.@@@@@@@@@.@@@.@@@@@@@.@@@@@@@@@@@.@.@@@.@.@.@@@@@@@.@.@@@.
+@.....@.........@...@.........@.@...@.........@.......@.....................@.......@.........@.....
diff --git a/JPSPlusGoalBounding/Maps/maze-100-1.map.pre b/JPSPlusGoalBounding/Maps/maze-100-1.map.pre
new file mode 100644
index 0000000..4380c9e
Binary files /dev/null and b/JPSPlusGoalBounding/Maps/maze-100-1.map.pre differ
diff --git a/JPSPlusGoalBounding/Maps/maze-100-1.map.scen b/JPSPlusGoalBounding/Maps/maze-100-1.map.scen
new file mode 100644
index 0000000..fc5c8ce
--- /dev/null
+++ b/JPSPlusGoalBounding/Maps/maze-100-1.map.scen
@@ -0,0 +1,2431 @@
+version 1
+1 maze-100-1.map 100 100 35 75 36 71 5
+1 maze-100-1.map 100 100 14 99 11 96 6
+1 maze-100-1.map 100 100 1 17 1 22 5
+1 maze-100-1.map 100 100 37 6 38 11 6
+1 maze-100-1.map 100 100 31 63 27 61 6
+1 maze-100-1.map 100 100 93 86 92 89 4
+1 maze-100-1.map 100 100 39 8 42 11 6
+1 maze-100-1.map 100 100 1 78 5 78 6
+1 maze-100-1.map 100 100 91 50 85 51 7
+1 maze-100-1.map 100 100 18 69 15 71 5
+2 maze-100-1.map 100 100 71 11 71 7 8
+2 maze-100-1.map 100 100 9 55 8 59 9
+2 maze-100-1.map 100 100 41 43 45 44 9
+2 maze-100-1.map 100 100 17 20 23 17 11
+2 maze-100-1.map 100 100 56 9 59 1 11
+2 maze-100-1.map 100 100 91 29 85 33 10
+2 maze-100-1.map 100 100 1 30 6 33 8
+2 maze-100-1.map 100 100 4 29 10 27 10
+2 maze-100-1.map 100 100 71 4 71 11 11
+2 maze-100-1.map 100 100 85 99 89 93 10
+3 maze-100-1.map 100 100 93 79 87 75 14
+3 maze-100-1.map 100 100 75 67 71 59 12
+3 maze-100-1.map 100 100 1 68 3 75 13
+3 maze-100-1.map 100 100 29 81 26 81 15
+3 maze-100-1.map 100 100 39 6 42 3 12
+3 maze-100-1.map 100 100 82 9 83 3 15
+3 maze-100-1.map 100 100 3 69 3 77 12
+3 maze-100-1.map 100 100 32 89 37 89 15
+3 maze-100-1.map 100 100 93 67 99 63 14
+3 maze-100-1.map 100 100 27 49 22 55 15
+4 maze-100-1.map 100 100 93 62 96 75 18
+4 maze-100-1.map 100 100 97 59 91 66 17
+4 maze-100-1.map 100 100 99 51 95 41 18
+4 maze-100-1.map 100 100 41 13 33 7 18
+4 maze-100-1.map 100 100 19 32 23 25 17
+4 maze-100-1.map 100 100 24 79 21 72 16
+4 maze-100-1.map 100 100 98 11 93 13 19
+4 maze-100-1.map 100 100 17 89 19 96 17
+4 maze-100-1.map 100 100 36 55 47 59 19
+4 maze-100-1.map 100 100 85 21 99 23 16
+5 maze-100-1.map 100 100 17 1 4 1 21
+5 maze-100-1.map 100 100 15 75 23 72 23
+5 maze-100-1.map 100 100 29 56 37 69 23
+5 maze-100-1.map 100 100 21 9 15 9 22
+5 maze-100-1.map 100 100 97 47 93 39 20
+5 maze-100-1.map 100 100 25 88 39 85 23
+5 maze-100-1.map 100 100 43 28 28 35 22
+5 maze-100-1.map 100 100 57 33 67 35 20
+5 maze-100-1.map 100 100 82 89 79 78 22
+5 maze-100-1.map 100 100 25 49 19 47 20
+6 maze-100-1.map 100 100 71 33 77 22 25
+6 maze-100-1.map 100 100 71 29 65 27 24
+6 maze-100-1.map 100 100 62 21 59 32 26
+6 maze-100-1.map 100 100 67 88 75 88 24
+6 maze-100-1.map 100 100 65 13 76 1 27
+6 maze-100-1.map 100 100 69 17 61 11 26
+6 maze-100-1.map 100 100 43 81 35 75 26
+6 maze-100-1.map 100 100 7 68 5 82 26
+6 maze-100-1.map 100 100 5 45 3 35 24
+6 maze-100-1.map 100 100 26 77 11 74 26
+7 maze-100-1.map 100 100 76 5 75 19 31
+7 maze-100-1.map 100 100 7 15 11 29 30
+7 maze-100-1.map 100 100 85 61 77 51 30
+7 maze-100-1.map 100 100 29 25 15 29 30
+7 maze-100-1.map 100 100 29 37 28 31 29
+7 maze-100-1.map 100 100 29 89 17 83 30
+7 maze-100-1.map 100 100 29 57 39 67 28
+7 maze-100-1.map 100 100 13 26 17 32 28
+7 maze-100-1.map 100 100 77 20 77 35 31
+7 maze-100-1.map 100 100 37 7 23 7 30
+8 maze-100-1.map 100 100 25 74 15 79 35
+8 maze-100-1.map 100 100 51 2 56 11 34
+8 maze-100-1.map 100 100 61 37 59 23 32
+8 maze-100-1.map 100 100 25 25 9 33 32
+8 maze-100-1.map 100 100 41 45 49 47 34
+8 maze-100-1.map 100 100 73 91 79 97 32
+8 maze-100-1.map 100 100 85 68 65 80 32
+8 maze-100-1.map 100 100 62 85 73 95 35
+8 maze-100-1.map 100 100 47 29 41 19 32
+8 maze-100-1.map 100 100 83 82 80 99 32
+9 maze-100-1.map 100 100 61 79 49 71 36
+9 maze-100-1.map 100 100 81 13 88 29 37
+9 maze-100-1.map 100 100 31 6 25 21 39
+9 maze-100-1.map 100 100 33 51 39 67 38
+9 maze-100-1.map 100 100 25 81 21 87 38
+9 maze-100-1.map 100 100 37 31 23 39 38
+9 maze-100-1.map 100 100 81 27 67 37 36
+9 maze-100-1.map 100 100 33 53 46 57 39
+9 maze-100-1.map 100 100 24 5 13 19 37
+9 maze-100-1.map 100 100 51 98 57 88 38
+10 maze-100-1.map 100 100 88 51 98 71 42
+10 maze-100-1.map 100 100 29 89 10 83 43
+10 maze-100-1.map 100 100 57 88 69 79 41
+10 maze-100-1.map 100 100 64 83 57 91 41
+10 maze-100-1.map 100 100 85 56 77 63 43
+10 maze-100-1.map 100 100 85 41 84 61 41
+10 maze-100-1.map 100 100 63 93 77 89 42
+10 maze-100-1.map 100 100 59 54 46 53 40
+10 maze-100-1.map 100 100 29 37 18 51 43
+10 maze-100-1.map 100 100 27 60 21 41 41
+11 maze-100-1.map 100 100 19 63 31 61 46
+11 maze-100-1.map 100 100 11 93 27 85 44
+11 maze-100-1.map 100 100 78 13 75 33 47
+11 maze-100-1.map 100 100 35 18 57 11 45
+11 maze-100-1.map 100 100 76 63 83 46 46
+11 maze-100-1.map 100 100 37 7 22 17 45
+11 maze-100-1.map 100 100 36 83 24 87 44
+11 maze-100-1.map 100 100 35 41 34 67 45
+11 maze-100-1.map 100 100 9 59 1 73 46
+11 maze-100-1.map 100 100 46 51 58 53 46
+12 maze-100-1.map 100 100 24 1 39 13 51
+12 maze-100-1.map 100 100 31 61 23 62 51
+12 maze-100-1.map 100 100 81 47 97 72 51
+12 maze-100-1.map 100 100 77 57 99 59 48
+12 maze-100-1.map 100 100 73 19 68 9 51
+12 maze-100-1.map 100 100 63 95 75 81 50
+12 maze-100-1.map 100 100 18 29 39 18 50
+12 maze-100-1.map 100 100 21 26 5 33 49
+12 maze-100-1.map 100 100 81 21 92 11 49
+12 maze-100-1.map 100 100 57 35 46 7 51
+13 maze-100-1.map 100 100 33 56 49 63 53
+13 maze-100-1.map 100 100 16 39 46 37 54
+13 maze-100-1.map 100 100 11 31 15 42 55
+13 maze-100-1.map 100 100 15 17 3 6 55
+13 maze-100-1.map 100 100 75 76 93 76 54
+13 maze-100-1.map 100 100 97 82 89 89 55
+13 maze-100-1.map 100 100 84 77 71 75 55
+13 maze-100-1.map 100 100 5 59 15 34 55
+13 maze-100-1.map 100 100 27 69 23 42 55
+13 maze-100-1.map 100 100 24 69 19 54 52
+14 maze-100-1.map 100 100 49 79 46 91 57
+14 maze-100-1.map 100 100 51 91 53 96 57
+14 maze-100-1.map 100 100 15 42 12 33 58
+14 maze-100-1.map 100 100 82 65 92 69 58
+14 maze-100-1.map 100 100 5 81 5 50 59
+14 maze-100-1.map 100 100 23 8 29 17 57
+14 maze-100-1.map 100 100 32 31 9 40 58
+14 maze-100-1.map 100 100 17 98 35 99 59
+14 maze-100-1.map 100 100 89 95 95 79 58
+14 maze-100-1.map 100 100 97 58 73 71 59
+15 maze-100-1.map 100 100 17 81 11 59 60
+15 maze-100-1.map 100 100 17 56 23 54 62
+15 maze-100-1.map 100 100 58 9 77 11 63
+15 maze-100-1.map 100 100 57 15 59 23 62
+15 maze-100-1.map 100 100 1 32 20 31 60
+15 maze-100-1.map 100 100 27 86 17 98 62
+15 maze-100-1.map 100 100 46 7 71 7 63
+15 maze-100-1.map 100 100 99 49 91 23 62
+15 maze-100-1.map 100 100 66 31 85 20 60
+15 maze-100-1.map 100 100 82 83 73 95 61
+16 maze-100-1.map 100 100 83 57 65 74 67
+16 maze-100-1.map 100 100 61 67 41 97 66
+16 maze-100-1.map 100 100 11 69 19 47 66
+16 maze-100-1.map 100 100 40 43 55 40 66
+16 maze-100-1.map 100 100 97 34 97 13 67
+16 maze-100-1.map 100 100 80 69 98 67 66
+16 maze-100-1.map 100 100 75 57 79 42 67
+16 maze-100-1.map 100 100 48 61 63 81 67
+16 maze-100-1.map 100 100 57 69 59 85 66
+16 maze-100-1.map 100 100 30 89 9 96 66
+17 maze-100-1.map 100 100 61 34 49 1 71
+17 maze-100-1.map 100 100 93 33 97 58 69
+17 maze-100-1.map 100 100 53 1 68 19 69
+17 maze-100-1.map 100 100 13 23 25 25 70
+17 maze-100-1.map 100 100 99 45 83 19 70
+17 maze-100-1.map 100 100 99 77 87 59 70
+17 maze-100-1.map 100 100 40 79 11 81 69
+17 maze-100-1.map 100 100 67 60 45 53 69
+17 maze-100-1.map 100 100 23 91 1 82 71
+17 maze-100-1.map 100 100 79 81 61 93 70
+18 maze-100-1.map 100 100 99 52 98 19 74
+18 maze-100-1.map 100 100 49 31 55 1 72
+18 maze-100-1.map 100 100 25 46 44 43 72
+18 maze-100-1.map 100 100 83 30 52 19 72
+18 maze-100-1.map 100 100 89 57 91 39 72
+18 maze-100-1.map 100 100 81 20 99 52 74
+18 maze-100-1.map 100 100 69 11 99 21 72
+18 maze-100-1.map 100 100 41 71 29 45 74
+18 maze-100-1.map 100 100 79 69 97 76 73
+18 maze-100-1.map 100 100 72 81 81 81 73
+19 maze-100-1.map 100 100 71 7 87 33 78
+19 maze-100-1.map 100 100 43 1 17 3 76
+19 maze-100-1.map 100 100 93 47 78 13 77
+19 maze-100-1.map 100 100 48 69 49 85 77
+19 maze-100-1.map 100 100 31 26 57 21 79
+19 maze-100-1.map 100 100 7 55 4 41 77
+19 maze-100-1.map 100 100 45 58 59 59 79
+19 maze-100-1.map 100 100 41 26 9 39 77
+19 maze-100-1.map 100 100 59 16 49 6 76
+19 maze-100-1.map 100 100 44 55 47 76 78
+20 maze-100-1.map 100 100 65 4 99 16 82
+20 maze-100-1.map 100 100 47 31 27 39 80
+20 maze-100-1.map 100 100 34 11 9 19 83
+20 maze-100-1.map 100 100 17 49 26 35 81
+20 maze-100-1.map 100 100 77 44 83 56 80
+20 maze-100-1.map 100 100 39 39 20 37 81
+20 maze-100-1.map 100 100 98 35 93 21 81
+20 maze-100-1.map 100 100 69 37 49 13 80
+20 maze-100-1.map 100 100 8 37 5 69 81
+20 maze-100-1.map 100 100 73 29 99 17 82
+21 maze-100-1.map 100 100 81 14 94 1 86
+21 maze-100-1.map 100 100 71 10 88 33 86
+21 maze-100-1.map 100 100 9 41 2 33 85
+21 maze-100-1.map 100 100 51 97 87 65 84
+21 maze-100-1.map 100 100 83 57 99 65 84
+21 maze-100-1.map 100 100 36 49 21 39 87
+21 maze-100-1.map 100 100 62 87 53 67 87
+21 maze-100-1.map 100 100 74 49 68 65 84
+21 maze-100-1.map 100 100 83 76 95 79 87
+21 maze-100-1.map 100 100 69 95 59 85 84
+22 maze-100-1.map 100 100 87 66 55 93 89
+22 maze-100-1.map 100 100 63 68 97 76 88
+22 maze-100-1.map 100 100 62 43 46 35 90
+22 maze-100-1.map 100 100 53 7 57 17 90
+22 maze-100-1.map 100 100 21 5 26 5 91
+22 maze-100-1.map 100 100 30 97 1 93 89
+22 maze-100-1.map 100 100 21 37 37 49 88
+22 maze-100-1.map 100 100 95 32 65 5 89
+22 maze-100-1.map 100 100 5 47 39 17 88
+22 maze-100-1.map 100 100 90 1 83 18 88
+23 maze-100-1.map 100 100 54 97 77 71 93
+23 maze-100-1.map 100 100 91 60 88 71 94
+23 maze-100-1.map 100 100 49 31 59 4 95
+23 maze-100-1.map 100 100 41 5 9 18 95
+23 maze-100-1.map 100 100 9 67 14 49 93
+23 maze-100-1.map 100 100 95 11 75 21 94
+23 maze-100-1.map 100 100 61 59 49 45 94
+23 maze-100-1.map 100 100 95 11 99 29 94
+23 maze-100-1.map 100 100 73 54 57 88 92
+23 maze-100-1.map 100 100 27 57 48 41 95
+24 maze-100-1.map 100 100 38 85 3 94 98
+24 maze-100-1.map 100 100 89 11 86 27 99
+24 maze-100-1.map 100 100 49 13 4 33 99
+24 maze-100-1.map 100 100 7 48 5 29 97
+24 maze-100-1.map 100 100 63 97 85 79 96
+24 maze-100-1.map 100 100 63 1 97 37 98
+24 maze-100-1.map 100 100 79 41 69 62 97
+24 maze-100-1.map 100 100 47 90 63 58 98
+24 maze-100-1.map 100 100 45 47 23 36 97
+24 maze-100-1.map 100 100 52 15 33 31 97
+25 maze-100-1.map 100 100 49 5 79 31 100
+25 maze-100-1.map 100 100 15 75 17 83 102
+25 maze-100-1.map 100 100 55 6 79 16 100
+25 maze-100-1.map 100 100 67 15 93 14 101
+25 maze-100-1.map 100 100 42 9 7 20 102
+25 maze-100-1.map 100 100 29 48 43 61 101
+25 maze-100-1.map 100 100 65 89 55 86 101
+25 maze-100-1.map 100 100 19 33 57 15 100
+25 maze-100-1.map 100 100 97 35 99 3 102
+25 maze-100-1.map 100 100 71 89 83 72 101
+26 maze-100-1.map 100 100 17 5 25 17 104
+26 maze-100-1.map 100 100 57 55 41 63 104
+26 maze-100-1.map 100 100 44 23 19 52 106
+26 maze-100-1.map 100 100 15 42 5 19 105
+26 maze-100-1.map 100 100 61 75 77 88 105
+26 maze-100-1.map 100 100 25 39 54 45 107
+26 maze-100-1.map 100 100 33 87 17 91 104
+26 maze-100-1.map 100 100 89 44 77 21 107
+26 maze-100-1.map 100 100 65 4 37 19 105
+26 maze-100-1.map 100 100 13 65 7 66 107
+27 maze-100-1.map 100 100 47 90 61 81 109
+27 maze-100-1.map 100 100 97 14 57 9 111
+27 maze-100-1.map 100 100 47 82 33 67 109
+27 maze-100-1.map 100 100 59 95 81 84 109
+27 maze-100-1.map 100 100 19 5 17 9 110
+27 maze-100-1.map 100 100 2 61 35 27 109
+27 maze-100-1.map 100 100 99 10 70 29 110
+27 maze-100-1.map 100 100 27 59 41 41 108
+27 maze-100-1.map 100 100 1 14 34 5 108
+27 maze-100-1.map 100 100 97 11 71 31 110
+28 maze-100-1.map 100 100 2 29 37 5 115
+28 maze-100-1.map 100 100 74 59 75 74 114
+28 maze-100-1.map 100 100 55 79 43 61 114
+28 maze-100-1.map 100 100 91 73 87 81 112
+28 maze-100-1.map 100 100 82 75 48 99 112
+28 maze-100-1.map 100 100 53 37 63 58 113
+28 maze-100-1.map 100 100 63 71 73 45 112
+28 maze-100-1.map 100 100 13 23 14 49 113
+28 maze-100-1.map 100 100 2 39 43 21 115
+28 maze-100-1.map 100 100 40 69 53 74 114
+29 maze-100-1.map 100 100 76 79 95 97 117
+29 maze-100-1.map 100 100 7 81 17 46 119
+29 maze-100-1.map 100 100 81 61 72 77 119
+29 maze-100-1.map 100 100 71 17 94 11 117
+29 maze-100-1.map 100 100 45 27 39 19 118
+29 maze-100-1.map 100 100 49 92 89 75 117
+29 maze-100-1.map 100 100 59 4 70 35 116
+29 maze-100-1.map 100 100 58 83 67 96 116
+29 maze-100-1.map 100 100 54 31 34 31 116
+29 maze-100-1.map 100 100 67 49 51 38 119
+30 maze-100-1.map 100 100 45 38 18 69 120
+30 maze-100-1.map 100 100 43 62 53 49 123
+30 maze-100-1.map 100 100 27 81 6 63 123
+30 maze-100-1.map 100 100 51 23 45 33 120
+30 maze-100-1.map 100 100 86 25 86 9 120
+30 maze-100-1.map 100 100 64 79 99 65 121
+30 maze-100-1.map 100 100 27 2 7 13 123
+30 maze-100-1.map 100 100 57 76 71 73 123
+30 maze-100-1.map 100 100 7 19 40 21 121
+30 maze-100-1.map 100 100 53 56 45 99 123
+31 maze-100-1.map 100 100 42 55 45 95 127
+31 maze-100-1.map 100 100 13 65 50 25 125
+31 maze-100-1.map 100 100 33 33 17 27 126
+31 maze-100-1.map 100 100 83 69 71 94 127
+31 maze-100-1.map 100 100 53 3 19 45 124
+31 maze-100-1.map 100 100 7 56 37 18 126
+31 maze-100-1.map 100 100 29 26 27 33 127
+31 maze-100-1.map 100 100 20 23 30 35 124
+31 maze-100-1.map 100 100 21 61 43 24 127
+31 maze-100-1.map 100 100 69 49 78 69 125
+32 maze-100-1.map 100 100 60 75 84 95 128
+32 maze-100-1.map 100 100 89 63 51 99 130
+32 maze-100-1.map 100 100 63 30 99 44 128
+32 maze-100-1.map 100 100 66 89 89 70 130
+32 maze-100-1.map 100 100 86 75 95 62 130
+32 maze-100-1.map 100 100 9 97 11 74 131
+32 maze-100-1.map 100 100 2 51 2 31 130
+32 maze-100-1.map 100 100 65 59 39 67 130
+32 maze-100-1.map 100 100 55 71 73 81 128
+32 maze-100-1.map 100 100 63 83 64 55 131
+33 maze-100-1.map 100 100 54 47 43 99 133
+33 maze-100-1.map 100 100 21 45 47 45 134
+33 maze-100-1.map 100 100 37 69 61 77 132
+33 maze-100-1.map 100 100 79 13 54 25 135
+33 maze-100-1.map 100 100 19 89 27 77 132
+33 maze-100-1.map 100 100 71 83 58 59 133
+33 maze-100-1.map 100 100 73 54 73 93 135
+33 maze-100-1.map 100 100 52 45 44 65 134
+33 maze-100-1.map 100 100 32 71 21 91 133
+33 maze-100-1.map 100 100 1 92 25 79 135
+34 maze-100-1.map 100 100 47 1 99 13 136
+34 maze-100-1.map 100 100 15 75 9 96 137
+34 maze-100-1.map 100 100 16 59 36 33 136
+34 maze-100-1.map 100 100 75 92 67 54 136
+34 maze-100-1.map 100 100 4 7 9 5 139
+34 maze-100-1.map 100 100 45 19 9 11 136
+34 maze-100-1.map 100 100 65 52 48 87 136
+34 maze-100-1.map 100 100 62 85 40 61 138
+34 maze-100-1.map 100 100 2 85 39 73 137
+34 maze-100-1.map 100 100 19 32 61 40 138
+35 maze-100-1.map 100 100 61 51 31 56 141
+35 maze-100-1.map 100 100 99 63 85 87 142
+35 maze-100-1.map 100 100 59 11 89 45 140
+35 maze-100-1.map 100 100 35 71 27 93 142
+35 maze-100-1.map 100 100 23 73 1 97 142
+35 maze-100-1.map 100 100 57 65 77 98 143
+35 maze-100-1.map 100 100 29 6 25 25 143
+35 maze-100-1.map 100 100 72 79 85 37 143
+35 maze-100-1.map 100 100 48 17 5 49 143
+35 maze-100-1.map 100 100 33 11 5 5 142
+36 maze-100-1.map 100 100 65 7 9 33 146
+36 maze-100-1.map 100 100 36 25 85 16 144
+36 maze-100-1.map 100 100 49 96 33 65 145
+36 maze-100-1.map 100 100 1 64 47 10 144
+36 maze-100-1.map 100 100 77 92 85 89 147
+36 maze-100-1.map 100 100 59 59 65 44 147
+36 maze-100-1.map 100 100 5 77 16 83 147
+36 maze-100-1.map 100 100 31 74 23 93 145
+36 maze-100-1.map 100 100 11 77 21 27 144
+36 maze-100-1.map 100 100 75 17 55 29 144
+37 maze-100-1.map 100 100 58 1 90 1 150
+37 maze-100-1.map 100 100 49 23 6 57 149
+37 maze-100-1.map 100 100 53 69 83 98 149
+37 maze-100-1.map 100 100 9 41 20 21 151
+37 maze-100-1.map 100 100 31 85 3 69 148
+37 maze-100-1.map 100 100 64 45 71 51 149
+37 maze-100-1.map 100 100 41 22 19 49 151
+37 maze-100-1.map 100 100 45 39 57 67 148
+37 maze-100-1.map 100 100 69 39 76 71 149
+37 maze-100-1.map 100 100 59 83 43 53 150
+38 maze-100-1.map 100 100 39 55 55 51 152
+38 maze-100-1.map 100 100 97 51 65 16 155
+38 maze-100-1.map 100 100 7 27 43 25 154
+38 maze-100-1.map 100 100 12 3 21 20 152
+38 maze-100-1.map 100 100 22 25 68 19 152
+38 maze-100-1.map 100 100 57 75 83 82 155
+38 maze-100-1.map 100 100 4 63 8 25 152
+38 maze-100-1.map 100 100 47 99 97 57 152
+38 maze-100-1.map 100 100 44 63 61 96 154
+38 maze-100-1.map 100 100 57 73 48 97 155
+39 maze-100-1.map 100 100 78 53 69 85 157
+39 maze-100-1.map 100 100 57 2 4 37 158
+39 maze-100-1.map 100 100 13 44 61 34 156
+39 maze-100-1.map 100 100 51 85 54 45 159
+39 maze-100-1.map 100 100 33 67 55 93 156
+39 maze-100-1.map 100 100 49 29 18 69 159
+39 maze-100-1.map 100 100 87 17 93 48 159
+39 maze-100-1.map 100 100 3 14 16 11 156
+39 maze-100-1.map 100 100 10 45 55 5 159
+39 maze-100-1.map 100 100 15 29 33 11 156
+40 maze-100-1.map 100 100 69 84 86 37 160
+40 maze-100-1.map 100 100 29 29 41 31 162
+40 maze-100-1.map 100 100 30 53 43 92 160
+40 maze-100-1.map 100 100 63 11 42 21 161
+40 maze-100-1.map 100 100 47 8 11 59 163
+40 maze-100-1.map 100 100 39 48 12 69 162
+40 maze-100-1.map 100 100 7 7 1 16 163
+40 maze-100-1.map 100 100 90 37 88 65 160
+40 maze-100-1.map 100 100 49 59 56 75 161
+40 maze-100-1.map 100 100 30 43 41 99 163
+41 maze-100-1.map 100 100 99 55 63 15 164
+41 maze-100-1.map 100 100 50 17 67 7 165
+41 maze-100-1.map 100 100 75 97 57 62 167
+41 maze-100-1.map 100 100 4 79 30 73 166
+41 maze-100-1.map 100 100 55 43 39 96 165
+41 maze-100-1.map 100 100 26 7 15 41 167
+41 maze-100-1.map 100 100 41 17 21 14 165
+41 maze-100-1.map 100 100 71 31 81 10 167
+41 maze-100-1.map 100 100 50 59 49 53 167
+41 maze-100-1.map 100 100 19 35 11 33 166
+42 maze-100-1.map 100 100 1 16 31 13 169
+42 maze-100-1.map 100 100 46 19 25 62 170
+42 maze-100-1.map 100 100 76 55 84 77 170
+42 maze-100-1.map 100 100 97 58 53 79 171
+42 maze-100-1.map 100 100 51 29 16 63 171
+42 maze-100-1.map 100 100 22 49 54 61 168
+42 maze-100-1.map 100 100 99 25 90 19 169
+42 maze-100-1.map 100 100 79 3 15 41 170
+42 maze-100-1.map 100 100 7 31 71 35 168
+42 maze-100-1.map 100 100 29 61 53 36 169
+43 maze-100-1.map 100 100 2 89 12 79 174
+43 maze-100-1.map 100 100 59 43 33 35 174
+43 maze-100-1.map 100 100 99 91 73 93 172
+43 maze-100-1.map 100 100 55 93 41 47 172
+43 maze-100-1.map 100 100 30 47 70 57 172
+43 maze-100-1.map 100 100 45 71 81 70 175
+43 maze-100-1.map 100 100 53 54 77 78 174
+43 maze-100-1.map 100 100 44 63 77 90 174
+43 maze-100-1.map 100 100 17 11 41 21 174
+43 maze-100-1.map 100 100 89 91 97 76 173
+44 maze-100-1.map 100 100 20 39 37 18 176
+44 maze-100-1.map 100 100 97 71 61 94 177
+44 maze-100-1.map 100 100 95 35 55 22 179
+44 maze-100-1.map 100 100 51 85 97 94 177
+44 maze-100-1.map 100 100 35 61 57 51 176
+44 maze-100-1.map 100 100 20 63 55 33 179
+44 maze-100-1.map 100 100 14 29 62 15 178
+44 maze-100-1.map 100 100 57 8 46 23 178
+44 maze-100-1.map 100 100 79 30 76 1 178
+44 maze-100-1.map 100 100 61 61 83 85 178
+45 maze-100-1.map 100 100 80 25 63 9 181
+45 maze-100-1.map 100 100 19 35 47 13 182
+45 maze-100-1.map 100 100 46 19 37 50 182
+45 maze-100-1.map 100 100 57 21 92 15 183
+45 maze-100-1.map 100 100 79 13 15 27 182
+45 maze-100-1.map 100 100 68 99 47 50 182
+45 maze-100-1.map 100 100 43 48 41 94 182
+45 maze-100-1.map 100 100 69 60 69 84 180
+45 maze-100-1.map 100 100 99 50 47 9 183
+45 maze-100-1.map 100 100 11 95 1 67 182
+46 maze-100-1.map 100 100 77 90 95 69 187
+46 maze-100-1.map 100 100 10 99 1 67 187
+46 maze-100-1.map 100 100 11 50 69 7 187
+46 maze-100-1.map 100 100 53 11 5 69 186
+46 maze-100-1.map 100 100 33 83 6 43 185
+46 maze-100-1.map 100 100 21 47 59 48 185
+46 maze-100-1.map 100 100 57 61 77 87 186
+46 maze-100-1.map 100 100 13 39 77 15 184
+46 maze-100-1.map 100 100 49 91 47 43 186
+46 maze-100-1.map 100 100 85 56 89 87 187
+47 maze-100-1.map 100 100 5 73 50 27 189
+47 maze-100-1.map 100 100 9 59 64 9 191
+47 maze-100-1.map 100 100 62 23 5 29 189
+47 maze-100-1.map 100 100 25 44 15 31 191
+47 maze-100-1.map 100 100 13 40 62 17 188
+47 maze-100-1.map 100 100 37 83 2 65 189
+47 maze-100-1.map 100 100 51 55 53 95 190
+47 maze-100-1.map 100 100 17 10 13 58 188
+47 maze-100-1.map 100 100 37 23 99 39 190
+47 maze-100-1.map 100 100 58 25 90 21 190
+48 maze-100-1.map 100 100 80 79 82 63 194
+48 maze-100-1.map 100 100 49 92 97 85 195
+48 maze-100-1.map 100 100 81 23 17 25 194
+48 maze-100-1.map 100 100 53 54 25 69 193
+48 maze-100-1.map 100 100 74 13 6 39 192
+48 maze-100-1.map 100 100 48 99 71 63 195
+48 maze-100-1.map 100 100 98 87 47 93 193
+48 maze-100-1.map 100 100 71 13 4 41 195
+48 maze-100-1.map 100 100 45 53 74 79 195
+48 maze-100-1.map 100 100 57 36 1 53 195
+49 maze-100-1.map 100 100 7 43 81 33 196
+49 maze-100-1.map 100 100 17 46 37 5 197
+49 maze-100-1.map 100 100 53 82 48 39 198
+49 maze-100-1.map 100 100 61 9 85 3 198
+49 maze-100-1.map 100 100 27 5 9 55 196
+49 maze-100-1.map 100 100 5 84 6 87 196
+49 maze-100-1.map 100 100 53 55 29 64 199
+49 maze-100-1.map 100 100 29 71 53 60 197
+49 maze-100-1.map 100 100 6 43 31 37 199
+49 maze-100-1.map 100 100 47 63 60 45 197
+50 maze-100-1.map 100 100 83 75 42 87 201
+50 maze-100-1.map 100 100 59 15 81 5 200
+50 maze-100-1.map 100 100 28 77 25 28 202
+50 maze-100-1.map 100 100 61 52 87 79 201
+50 maze-100-1.map 100 100 44 73 59 85 201
+50 maze-100-1.map 100 100 45 53 17 53 200
+50 maze-100-1.map 100 100 43 19 17 58 203
+50 maze-100-1.map 100 100 33 60 59 97 201
+50 maze-100-1.map 100 100 65 91 55 61 200
+50 maze-100-1.map 100 100 39 23 37 9 200
+51 maze-100-1.map 100 100 50 89 75 79 205
+51 maze-100-1.map 100 100 79 86 88 99 206
+51 maze-100-1.map 100 100 65 19 4 35 205
+51 maze-100-1.map 100 100 77 26 40 25 204
+51 maze-100-1.map 100 100 51 31 92 11 205
+51 maze-100-1.map 100 100 41 23 33 19 204
+51 maze-100-1.map 100 100 55 20 30 33 204
+51 maze-100-1.map 100 100 59 87 71 49 206
+51 maze-100-1.map 100 100 88 55 75 92 204
+51 maze-100-1.map 100 100 79 90 98 59 206
+52 maze-100-1.map 100 100 41 61 64 45 209
+52 maze-100-1.map 100 100 23 26 61 29 209
+52 maze-100-1.map 100 100 97 5 53 21 208
+52 maze-100-1.map 100 100 12 75 38 17 208
+52 maze-100-1.map 100 100 57 3 1 70 211
+52 maze-100-1.map 100 100 5 39 71 1 208
+52 maze-100-1.map 100 100 31 9 11 56 211
+52 maze-100-1.map 100 100 57 83 95 85 208
+52 maze-100-1.map 100 100 21 49 15 29 210
+52 maze-100-1.map 100 100 51 59 77 89 208
+53 maze-100-1.map 100 100 71 62 95 95 215
+53 maze-100-1.map 100 100 3 85 1 70 213
+53 maze-100-1.map 100 100 42 17 34 13 214
+53 maze-100-1.map 100 100 43 25 63 53 212
+53 maze-100-1.map 100 100 54 21 16 15 212
+53 maze-100-1.map 100 100 54 11 23 39 215
+53 maze-100-1.map 100 100 87 70 57 62 214
+53 maze-100-1.map 100 100 33 5 45 11 214
+53 maze-100-1.map 100 100 43 81 6 63 215
+53 maze-100-1.map 100 100 98 83 88 51 214
+54 maze-100-1.map 100 100 3 40 27 13 217
+54 maze-100-1.map 100 100 41 80 11 45 219
+54 maze-100-1.map 100 100 35 79 2 45 217
+54 maze-100-1.map 100 100 60 19 52 27 216
+54 maze-100-1.map 100 100 60 65 99 65 219
+54 maze-100-1.map 100 100 82 89 86 51 216
+54 maze-100-1.map 100 100 11 27 15 3 216
+54 maze-100-1.map 100 100 23 15 3 44 219
+54 maze-100-1.map 100 100 32 49 45 49 217
+54 maze-100-1.map 100 100 28 21 45 12 218
+55 maze-100-1.map 100 100 75 99 94 93 221
+55 maze-100-1.map 100 100 89 93 47 67 220
+55 maze-100-1.map 100 100 9 39 18 87 223
+55 maze-100-1.map 100 100 17 69 63 43 220
+55 maze-100-1.map 100 100 47 11 86 13 221
+55 maze-100-1.map 100 100 5 39 25 41 222
+55 maze-100-1.map 100 100 31 24 99 43 221
+55 maze-100-1.map 100 100 41 39 31 27 222
+55 maze-100-1.map 100 100 43 47 40 69 221
+55 maze-100-1.map 100 100 45 19 91 21 220
+56 maze-100-1.map 100 100 14 93 11 63 227
+56 maze-100-1.map 100 100 63 62 99 67 225
+56 maze-100-1.map 100 100 87 53 53 77 226
+56 maze-100-1.map 100 100 62 59 27 59 225
+56 maze-100-1.map 100 100 19 67 61 51 226
+56 maze-100-1.map 100 100 85 89 44 63 225
+56 maze-100-1.map 100 100 47 89 82 99 225
+56 maze-100-1.map 100 100 91 47 57 34 225
+56 maze-100-1.map 100 100 57 86 75 45 227
+56 maze-100-1.map 100 100 39 29 63 58 227
+57 maze-100-1.map 100 100 83 29 85 30 231
+57 maze-100-1.map 100 100 77 74 29 58 228
+57 maze-100-1.map 100 100 57 45 48 59 231
+57 maze-100-1.map 100 100 43 72 53 97 231
+57 maze-100-1.map 100 100 12 23 17 79 231
+57 maze-100-1.map 100 100 3 46 59 30 228
+57 maze-100-1.map 100 100 71 97 84 59 231
+57 maze-100-1.map 100 100 65 57 99 94 231
+57 maze-100-1.map 100 100 57 18 86 25 230
+57 maze-100-1.map 100 100 50 91 67 74 230
+58 maze-100-1.map 100 100 35 46 52 45 232
+58 maze-100-1.map 100 100 11 56 42 13 234
+58 maze-100-1.map 100 100 1 77 14 17 235
+58 maze-100-1.map 100 100 68 99 45 39 235
+58 maze-100-1.map 100 100 37 85 8 35 233
+58 maze-100-1.map 100 100 39 8 7 51 235
+58 maze-100-1.map 100 100 39 58 93 79 233
+58 maze-100-1.map 100 100 85 24 45 19 235
+58 maze-100-1.map 100 100 21 56 11 41 233
+58 maze-100-1.map 100 100 71 63 59 71 232
+59 maze-100-1.map 100 100 49 2 17 79 239
+59 maze-100-1.map 100 100 13 26 5 1 239
+59 maze-100-1.map 100 100 96 37 13 38 236
+59 maze-100-1.map 100 100 73 24 8 35 236
+59 maze-100-1.map 100 100 95 27 5 33 236
+59 maze-100-1.map 100 100 34 37 53 3 239
+59 maze-100-1.map 100 100 20 93 1 62 238
+59 maze-100-1.map 100 100 13 80 12 13 238
+59 maze-100-1.map 100 100 87 26 49 20 236
+59 maze-100-1.map 100 100 24 87 19 32 238
+60 maze-100-1.map 100 100 41 73 75 79 240
+60 maze-100-1.map 100 100 77 45 51 74 241
+60 maze-100-1.map 100 100 65 71 70 89 241
+60 maze-100-1.map 100 100 47 37 46 11 241
+60 maze-100-1.map 100 100 37 53 83 73 242
+60 maze-100-1.map 100 100 85 85 43 59 240
+60 maze-100-1.map 100 100 46 47 68 97 242
+60 maze-100-1.map 100 100 63 20 5 49 243
+60 maze-100-1.map 100 100 21 37 54 31 241
+60 maze-100-1.map 100 100 28 35 67 35 243
+61 maze-100-1.map 100 100 81 27 97 15 244
+61 maze-100-1.map 100 100 81 59 83 83 246
+61 maze-100-1.map 100 100 55 89 25 48 245
+61 maze-100-1.map 100 100 22 57 7 48 246
+61 maze-100-1.map 100 100 13 19 59 31 246
+61 maze-100-1.map 100 100 3 43 79 6 247
+61 maze-100-1.map 100 100 15 17 64 13 245
+61 maze-100-1.map 100 100 37 45 71 76 247
+61 maze-100-1.map 100 100 17 46 47 43 245
+61 maze-100-1.map 100 100 27 52 4 41 246
+62 maze-100-1.map 100 100 89 79 35 55 250
+62 maze-100-1.map 100 100 57 23 19 81 248
+62 maze-100-1.map 100 100 57 1 25 13 248
+62 maze-100-1.map 100 100 11 60 29 97 251
+62 maze-100-1.map 100 100 56 29 13 78 250
+62 maze-100-1.map 100 100 7 83 32 35 251
+62 maze-100-1.map 100 100 46 13 50 41 248
+62 maze-100-1.map 100 100 23 83 41 22 251
+62 maze-100-1.map 100 100 13 5 34 31 251
+62 maze-100-1.map 100 100 94 81 59 63 251
+63 maze-100-1.map 100 100 25 87 13 65 254
+63 maze-100-1.map 100 100 77 2 30 33 252
+63 maze-100-1.map 100 100 90 83 83 91 253
+63 maze-100-1.map 100 100 24 57 45 7 253
+63 maze-100-1.map 100 100 33 24 43 48 254
+63 maze-100-1.map 100 100 47 8 27 57 253
+63 maze-100-1.map 100 100 47 31 73 23 254
+63 maze-100-1.map 100 100 95 20 41 22 252
+63 maze-100-1.map 100 100 99 96 47 65 255
+63 maze-100-1.map 100 100 37 68 65 93 253
+64 maze-100-1.map 100 100 7 37 61 29 258
+64 maze-100-1.map 100 100 61 78 68 71 256
+64 maze-100-1.map 100 100 62 61 47 26 258
+64 maze-100-1.map 100 100 51 23 99 13 258
+64 maze-100-1.map 100 100 41 42 73 81 259
+64 maze-100-1.map 100 100 53 69 95 79 256
+64 maze-100-1.map 100 100 7 43 7 98 257
+64 maze-100-1.map 100 100 95 13 6 35 259
+64 maze-100-1.map 100 100 32 21 53 18 258
+64 maze-100-1.map 100 100 99 89 77 44 257
+65 maze-100-1.map 100 100 20 39 67 11 263
+65 maze-100-1.map 100 100 73 75 39 44 261
+65 maze-100-1.map 100 100 78 31 91 12 260
+65 maze-100-1.map 100 100 41 66 89 68 262
+65 maze-100-1.map 100 100 50 35 27 55 263
+65 maze-100-1.map 100 100 65 95 40 53 261
+65 maze-100-1.map 100 100 3 44 77 16 262
+65 maze-100-1.map 100 100 77 49 96 99 263
+65 maze-100-1.map 100 100 88 81 87 41 263
+65 maze-100-1.map 100 100 14 41 23 67 261
+66 maze-100-1.map 100 100 29 41 71 76 267
+66 maze-100-1.map 100 100 21 52 55 88 266
+66 maze-100-1.map 100 100 84 77 50 45 264
+66 maze-100-1.map 100 100 47 25 73 21 266
+66 maze-100-1.map 100 100 25 33 55 85 266
+66 maze-100-1.map 100 100 66 29 15 47 267
+66 maze-100-1.map 100 100 43 47 79 65 266
+66 maze-100-1.map 100 100 43 29 16 75 265
+66 maze-100-1.map 100 100 5 33 99 36 267
+66 maze-100-1.map 100 100 39 17 33 82 267
+67 maze-100-1.map 100 100 45 35 32 43 269
+67 maze-100-1.map 100 100 53 71 21 69 270
+67 maze-100-1.map 100 100 7 36 21 1 271
+67 maze-100-1.map 100 100 51 27 70 51 269
+67 maze-100-1.map 100 100 41 38 83 95 271
+67 maze-100-1.map 100 100 49 19 95 41 268
+67 maze-100-1.map 100 100 65 55 85 61 270
+67 maze-100-1.map 100 100 63 43 75 76 269
+67 maze-100-1.map 100 100 84 69 50 41 268
+67 maze-100-1.map 100 100 53 42 87 93 269
+68 maze-100-1.map 100 100 17 45 93 51 274
+68 maze-100-1.map 100 100 97 43 1 37 274
+68 maze-100-1.map 100 100 13 17 63 19 272
+68 maze-100-1.map 100 100 96 55 49 95 273
+68 maze-100-1.map 100 100 5 81 79 9 274
+68 maze-100-1.map 100 100 97 7 11 42 275
+68 maze-100-1.map 100 100 33 20 52 31 272
+68 maze-100-1.map 100 100 43 68 85 37 275
+68 maze-100-1.map 100 100 41 3 47 30 273
+68 maze-100-1.map 100 100 39 65 83 91 274
+69 maze-100-1.map 100 100 29 32 57 91 277
+69 maze-100-1.map 100 100 45 43 53 11 276
+69 maze-100-1.map 100 100 73 6 23 8 278
+69 maze-100-1.map 100 100 63 79 38 35 277
+69 maze-100-1.map 100 100 73 27 9 15 276
+69 maze-100-1.map 100 100 29 33 57 90 279
+69 maze-100-1.map 100 100 9 6 38 17 278
+69 maze-100-1.map 100 100 47 72 83 35 277
+69 maze-100-1.map 100 100 89 39 47 67 278
+69 maze-100-1.map 100 100 35 53 81 76 277
+70 maze-100-1.map 100 100 73 40 94 7 282
+70 maze-100-1.map 100 100 21 77 65 39 282
+70 maze-100-1.map 100 100 61 43 82 99 281
+70 maze-100-1.map 100 100 20 27 11 91 283
+70 maze-100-1.map 100 100 77 65 51 63 280
+70 maze-100-1.map 100 100 1 48 80 23 280
+70 maze-100-1.map 100 100 65 71 67 60 281
+70 maze-100-1.map 100 100 54 57 27 25 283
+70 maze-100-1.map 100 100 50 11 17 50 282
+70 maze-100-1.map 100 100 69 51 87 61 280
+71 maze-100-1.map 100 100 39 33 65 39 284
+71 maze-100-1.map 100 100 28 25 54 57 284
+71 maze-100-1.map 100 100 23 31 81 27 286
+71 maze-100-1.map 100 100 23 98 9 58 284
+71 maze-100-1.map 100 100 67 69 85 91 284
+71 maze-100-1.map 100 100 69 31 3 51 286
+71 maze-100-1.map 100 100 40 91 39 29 285
+71 maze-100-1.map 100 100 40 99 97 87 287
+71 maze-100-1.map 100 100 3 55 65 31 286
+71 maze-100-1.map 100 100 6 33 91 45 287
+72 maze-100-1.map 100 100 69 85 24 43 289
+72 maze-100-1.map 100 100 51 58 19 36 288
+72 maze-100-1.map 100 100 69 3 7 73 288
+72 maze-100-1.map 100 100 8 25 21 68 288
+72 maze-100-1.map 100 100 10 9 73 5 291
+72 maze-100-1.map 100 100 5 55 96 13 291
+72 maze-100-1.map 100 100 79 46 51 64 290
+72 maze-100-1.map 100 100 12 9 59 23 291
+72 maze-100-1.map 100 100 20 21 18 71 290
+72 maze-100-1.map 100 100 45 73 68 93 289
+73 maze-100-1.map 100 100 79 16 19 19 295
+73 maze-100-1.map 100 100 81 85 89 97 292
+73 maze-100-1.map 100 100 69 8 25 22 292
+73 maze-100-1.map 100 100 89 10 13 38 294
+73 maze-100-1.map 100 100 86 65 60 45 294
+73 maze-100-1.map 100 100 23 23 11 95 292
+73 maze-100-1.map 100 100 37 39 71 91 294
+73 maze-100-1.map 100 100 35 89 3 29 292
+73 maze-100-1.map 100 100 29 53 89 91 294
+73 maze-100-1.map 100 100 80 89 75 42 294
+74 maze-100-1.map 100 100 5 54 28 3 298
+74 maze-100-1.map 100 100 65 53 80 39 299
+74 maze-100-1.map 100 100 63 3 25 14 297
+74 maze-100-1.map 100 100 61 7 45 38 299
+74 maze-100-1.map 100 100 53 23 31 64 299
+74 maze-100-1.map 100 100 7 7 77 37 296
+74 maze-100-1.map 100 100 37 36 77 87 297
+74 maze-100-1.map 100 100 30 35 58 77 296
+74 maze-100-1.map 100 100 24 31 11 75 299
+74 maze-100-1.map 100 100 81 65 34 43 297
+75 maze-100-1.map 100 100 7 55 23 60 303
+75 maze-100-1.map 100 100 49 36 87 73 303
+75 maze-100-1.map 100 100 93 51 8 23 301
+75 maze-100-1.map 100 100 25 17 74 9 301
+75 maze-100-1.map 100 100 93 6 11 41 303
+75 maze-100-1.map 100 100 85 27 17 21 302
+75 maze-100-1.map 100 100 73 99 22 33 303
+75 maze-100-1.map 100 100 83 19 27 31 300
+75 maze-100-1.map 100 100 58 57 68 65 300
+75 maze-100-1.map 100 100 5 46 91 3 301
+76 maze-100-1.map 100 100 49 51 5 33 306
+76 maze-100-1.map 100 100 25 87 7 27 306
+76 maze-100-1.map 100 100 71 13 16 73 305
+76 maze-100-1.map 100 100 79 30 23 38 304
+76 maze-100-1.map 100 100 20 47 61 38 304
+76 maze-100-1.map 100 100 27 47 63 25 306
+76 maze-100-1.map 100 100 19 52 57 37 305
+76 maze-100-1.map 100 100 59 19 27 11 304
+76 maze-100-1.map 100 100 49 35 66 37 307
+76 maze-100-1.map 100 100 43 74 80 79 306
+77 maze-100-1.map 100 100 21 9 92 23 309
+77 maze-100-1.map 100 100 99 1 83 27 310
+77 maze-100-1.map 100 100 27 65 41 62 309
+77 maze-100-1.map 100 100 9 40 53 48 310
+77 maze-100-1.map 100 100 30 27 39 77 309
+77 maze-100-1.map 100 100 88 73 61 45 311
+77 maze-100-1.map 100 100 3 57 99 46 311
+77 maze-100-1.map 100 100 7 76 77 11 311
+77 maze-100-1.map 100 100 85 7 61 25 310
+77 maze-100-1.map 100 100 42 33 70 21 308
+78 maze-100-1.map 100 100 37 30 95 15 313
+78 maze-100-1.map 100 100 33 34 67 99 315
+78 maze-100-1.map 100 100 40 25 10 85 312
+78 maze-100-1.map 100 100 15 33 1 81 314
+78 maze-100-1.map 100 100 49 70 41 21 315
+78 maze-100-1.map 100 100 36 97 9 45 313
+78 maze-100-1.map 100 100 63 77 71 51 314
+78 maze-100-1.map 100 100 5 39 52 45 313
+78 maze-100-1.map 100 100 55 60 89 53 315
+78 maze-100-1.map 100 100 67 29 4 49 315
+79 maze-100-1.map 100 100 42 11 75 3 317
+79 maze-100-1.map 100 100 55 65 34 27 319
+79 maze-100-1.map 100 100 63 32 20 21 316
+79 maze-100-1.map 100 100 49 52 4 37 316
+79 maze-100-1.map 100 100 59 99 18 51 319
+79 maze-100-1.map 100 100 25 43 37 53 318
+79 maze-100-1.map 100 100 44 87 72 49 316
+79 maze-100-1.map 100 100 16 85 51 23 319
+79 maze-100-1.map 100 100 15 57 11 23 318
+79 maze-100-1.map 100 100 43 92 19 58 318
+80 maze-100-1.map 100 100 45 33 81 76 323
+80 maze-100-1.map 100 100 17 23 64 47 323
+80 maze-100-1.map 100 100 3 14 44 19 322
+80 maze-100-1.map 100 100 16 53 47 67 321
+80 maze-100-1.map 100 100 94 51 7 55 323
+80 maze-100-1.map 100 100 16 13 45 35 321
+80 maze-100-1.map 100 100 17 62 7 19 323
+80 maze-100-1.map 100 100 93 93 71 45 322
+80 maze-100-1.map 100 100 14 9 75 19 321
+80 maze-100-1.map 100 100 42 59 86 53 322
+81 maze-100-1.map 100 100 93 31 3 75 326
+81 maze-100-1.map 100 100 41 90 69 47 327
+81 maze-100-1.map 100 100 39 37 57 36 325
+81 maze-100-1.map 100 100 69 48 59 57 327
+81 maze-100-1.map 100 100 41 33 75 7 324
+81 maze-100-1.map 100 100 64 85 43 30 326
+81 maze-100-1.map 100 100 83 13 76 31 325
+81 maze-100-1.map 100 100 23 8 99 20 324
+81 maze-100-1.map 100 100 24 93 19 29 327
+81 maze-100-1.map 100 100 96 57 41 73 327
+82 maze-100-1.map 100 100 27 25 13 93 330
+82 maze-100-1.map 100 100 72 35 48 41 330
+82 maze-100-1.map 100 100 28 9 26 49 330
+82 maze-100-1.map 100 100 33 73 40 15 329
+82 maze-100-1.map 100 100 57 43 91 59 330
+82 maze-100-1.map 100 100 49 83 15 63 330
+82 maze-100-1.map 100 100 21 20 40 43 328
+82 maze-100-1.map 100 100 53 12 26 85 330
+82 maze-100-1.map 100 100 37 61 75 48 329
+82 maze-100-1.map 100 100 78 83 23 39 331
+83 maze-100-1.map 100 100 39 16 11 99 335
+83 maze-100-1.map 100 100 13 3 51 6 333
+83 maze-100-1.map 100 100 83 36 47 95 333
+83 maze-100-1.map 100 100 36 69 98 91 332
+83 maze-100-1.map 100 100 94 1 2 61 332
+83 maze-100-1.map 100 100 17 10 87 29 333
+83 maze-100-1.map 100 100 82 47 34 67 334
+83 maze-100-1.map 100 100 50 35 26 11 332
+83 maze-100-1.map 100 100 85 3 83 31 334
+83 maze-100-1.map 100 100 19 47 73 79 334
+84 maze-100-1.map 100 100 17 19 65 29 338
+84 maze-100-1.map 100 100 7 82 49 40 336
+84 maze-100-1.map 100 100 9 47 90 9 339
+84 maze-100-1.map 100 100 13 56 56 41 338
+84 maze-100-1.map 100 100 43 27 93 39 338
+84 maze-100-1.map 100 100 9 64 91 43 339
+84 maze-100-1.map 100 100 34 51 92 67 338
+84 maze-100-1.map 100 100 32 31 20 93 336
+84 maze-100-1.map 100 100 43 56 47 27 337
+84 maze-100-1.map 100 100 13 63 13 89 338
+85 maze-100-1.map 100 100 97 84 55 45 343
+85 maze-100-1.map 100 100 45 97 15 62 341
+85 maze-100-1.map 100 100 67 36 43 35 343
+85 maze-100-1.map 100 100 57 21 5 75 342
+85 maze-100-1.map 100 100 59 12 41 37 343
+85 maze-100-1.map 100 100 31 62 74 39 342
+85 maze-100-1.map 100 100 27 12 18 49 340
+85 maze-100-1.map 100 100 3 76 94 19 340
+85 maze-100-1.map 100 100 41 67 31 33 340
+85 maze-100-1.map 100 100 24 59 70 3 342
+86 maze-100-1.map 100 100 10 11 31 85 345
+86 maze-100-1.map 100 100 71 59 33 66 345
+86 maze-100-1.map 100 100 13 5 35 33 346
+86 maze-100-1.map 100 100 55 39 10 57 347
+86 maze-100-1.map 100 100 67 9 20 65 345
+86 maze-100-1.map 100 100 53 7 53 56 345
+86 maze-100-1.map 100 100 29 64 71 5 347
+86 maze-100-1.map 100 100 14 31 4 95 346
+86 maze-100-1.map 100 100 1 14 45 30 344
+86 maze-100-1.map 100 100 31 13 15 79 346
+87 maze-100-1.map 100 100 23 29 62 63 349
+87 maze-100-1.map 100 100 86 45 19 13 349
+87 maze-100-1.map 100 100 86 5 77 28 348
+87 maze-100-1.map 100 100 36 3 61 21 351
+87 maze-100-1.map 100 100 89 7 7 21 348
+87 maze-100-1.map 100 100 18 69 65 11 349
+87 maze-100-1.map 100 100 19 59 12 9 351
+87 maze-100-1.map 100 100 27 76 65 16 350
+87 maze-100-1.map 100 100 31 23 17 89 348
+87 maze-100-1.map 100 100 34 59 93 83 351
+88 maze-100-1.map 100 100 9 33 73 54 355
+88 maze-100-1.map 100 100 2 23 46 31 352
+88 maze-100-1.map 100 100 63 41 9 54 355
+88 maze-100-1.map 100 100 87 6 10 53 354
+88 maze-100-1.map 100 100 1 16 52 15 354
+88 maze-100-1.map 100 100 95 99 41 40 353
+88 maze-100-1.map 100 100 81 43 52 37 353
+88 maze-100-1.map 100 100 26 39 91 77 355
+88 maze-100-1.map 100 100 59 42 53 8 354
+88 maze-100-1.map 100 100 83 77 25 40 353
+89 maze-100-1.map 100 100 13 39 59 60 359
+89 maze-100-1.map 100 100 97 39 25 37 358
+89 maze-100-1.map 100 100 92 1 19 20 358
+89 maze-100-1.map 100 100 67 29 7 82 359
+89 maze-100-1.map 100 100 37 41 30 35 357
+89 maze-100-1.map 100 100 95 66 57 43 357
+89 maze-100-1.map 100 100 27 83 65 2 359
+89 maze-100-1.map 100 100 4 71 49 31 357
+89 maze-100-1.map 100 100 76 81 29 35 357
+89 maze-100-1.map 100 100 25 45 71 29 358
+90 maze-100-1.map 100 100 41 9 90 25 363
+90 maze-100-1.map 100 100 34 27 13 87 361
+90 maze-100-1.map 100 100 75 4 29 65 361
+90 maze-100-1.map 100 100 3 5 63 30 363
+90 maze-100-1.map 100 100 11 91 53 10 361
+90 maze-100-1.map 100 100 81 49 49 41 360
+90 maze-100-1.map 100 100 29 61 83 72 363
+90 maze-100-1.map 100 100 9 29 44 83 361
+90 maze-100-1.map 100 100 67 45 47 97 360
+90 maze-100-1.map 100 100 92 29 41 32 360
+91 maze-100-1.map 100 100 29 49 99 92 367
+91 maze-100-1.map 100 100 33 28 41 90 364
+91 maze-100-1.map 100 100 97 18 25 22 366
+91 maze-100-1.map 100 100 85 38 37 47 365
+91 maze-100-1.map 100 100 71 23 23 48 367
+91 maze-100-1.map 100 100 61 35 49 48 365
+91 maze-100-1.map 100 100 79 35 27 1 366
+91 maze-100-1.map 100 100 38 81 17 13 367
+91 maze-100-1.map 100 100 34 43 98 89 364
+91 maze-100-1.map 100 100 52 45 1 73 367
+92 maze-100-1.map 100 100 25 17 93 11 370
+92 maze-100-1.map 100 100 30 61 81 93 369
+92 maze-100-1.map 100 100 53 1 30 73 371
+92 maze-100-1.map 100 100 21 41 93 16 371
+92 maze-100-1.map 100 100 93 51 21 38 371
+92 maze-100-1.map 100 100 89 37 53 43 370
+92 maze-100-1.map 100 100 63 35 23 43 368
+92 maze-100-1.map 100 100 83 59 29 42 371
+92 maze-100-1.map 100 100 57 49 7 45 370
+92 maze-100-1.map 100 100 85 16 45 45 371
+93 maze-100-1.map 100 100 75 74 21 61 375
+93 maze-100-1.map 100 100 5 79 1 5 374
+93 maze-100-1.map 100 100 2 89 45 12 372
+93 maze-100-1.map 100 100 17 23 48 77 375
+93 maze-100-1.map 100 100 19 75 91 22 375
+93 maze-100-1.map 100 100 21 65 73 6 373
+93 maze-100-1.map 100 100 71 1 19 69 372
+93 maze-100-1.map 100 100 45 44 86 57 374
+93 maze-100-1.map 100 100 77 31 23 77 372
+93 maze-100-1.map 100 100 52 97 12 69 374
+94 maze-100-1.map 100 100 75 92 16 69 376
+94 maze-100-1.map 100 100 83 61 41 75 376
+94 maze-100-1.map 100 100 11 85 51 9 376
+94 maze-100-1.map 100 100 6 5 60 11 376
+94 maze-100-1.map 100 100 71 64 35 61 379
+94 maze-100-1.map 100 100 12 69 26 5 378
+94 maze-100-1.map 100 100 29 29 55 94 379
+94 maze-100-1.map 100 100 15 51 2 77 377
+94 maze-100-1.map 100 100 33 25 49 76 379
+94 maze-100-1.map 100 100 27 15 97 10 377
+95 maze-100-1.map 100 100 57 33 18 3 383
+95 maze-100-1.map 100 100 33 83 76 9 381
+95 maze-100-1.map 100 100 76 23 19 62 382
+95 maze-100-1.map 100 100 36 69 93 86 380
+95 maze-100-1.map 100 100 89 77 23 47 380
+95 maze-100-1.map 100 100 51 33 87 33 380
+95 maze-100-1.map 100 100 12 13 58 41 380
+95 maze-100-1.map 100 100 39 47 28 19 381
+95 maze-100-1.map 100 100 11 36 53 70 382
+95 maze-100-1.map 100 100 1 79 1 13 382
+96 maze-100-1.map 100 100 98 17 41 6 386
+96 maze-100-1.map 100 100 39 43 91 34 385
+96 maze-100-1.map 100 100 95 36 33 11 387
+96 maze-100-1.map 100 100 23 33 85 63 384
+96 maze-100-1.map 100 100 15 13 87 17 384
+96 maze-100-1.map 100 100 10 71 33 67 387
+96 maze-100-1.map 100 100 43 9 63 32 387
+96 maze-100-1.map 100 100 97 75 46 33 385
+96 maze-100-1.map 100 100 94 83 55 37 385
+96 maze-100-1.map 100 100 15 27 61 82 385
+97 maze-100-1.map 100 100 40 3 24 75 388
+97 maze-100-1.map 100 100 58 1 10 81 388
+97 maze-100-1.map 100 100 13 10 15 63 389
+97 maze-100-1.map 100 100 97 27 25 16 389
+97 maze-100-1.map 100 100 83 53 55 37 388
+97 maze-100-1.map 100 100 31 5 95 25 388
+97 maze-100-1.map 100 100 57 8 11 98 388
+97 maze-100-1.map 100 100 25 52 84 63 390
+97 maze-100-1.map 100 100 41 17 63 73 390
+97 maze-100-1.map 100 100 69 17 39 87 388
+98 maze-100-1.map 100 100 95 37 39 8 393
+98 maze-100-1.map 100 100 39 65 92 89 395
+98 maze-100-1.map 100 100 87 27 35 2 393
+98 maze-100-1.map 100 100 89 67 27 70 393
+98 maze-100-1.map 100 100 49 7 60 63 395
+98 maze-100-1.map 100 100 45 47 65 15 392
+98 maze-100-1.map 100 100 97 19 51 41 392
+98 maze-100-1.map 100 100 39 61 23 27 394
+98 maze-100-1.map 100 100 35 46 67 63 393
+98 maze-100-1.map 100 100 23 37 94 55 395
+99 maze-100-1.map 100 100 51 49 7 83 398
+99 maze-100-1.map 100 100 62 19 31 91 397
+99 maze-100-1.map 100 100 23 61 85 72 397
+99 maze-100-1.map 100 100 17 47 63 73 396
+99 maze-100-1.map 100 100 1 67 89 17 398
+99 maze-100-1.map 100 100 65 17 6 71 397
+99 maze-100-1.map 100 100 15 48 51 71 397
+99 maze-100-1.map 100 100 42 33 99 85 397
+99 maze-100-1.map 100 100 35 84 9 19 399
+99 maze-100-1.map 100 100 60 21 35 90 396
+100 maze-100-1.map 100 100 25 47 16 5 403
+100 maze-100-1.map 100 100 15 69 41 75 400
+100 maze-100-1.map 100 100 73 75 21 67 400
+100 maze-100-1.map 100 100 66 87 21 67 403
+100 maze-100-1.map 100 100 56 31 61 51 403
+100 maze-100-1.map 100 100 9 59 65 57 402
+100 maze-100-1.map 100 100 20 63 23 71 401
+100 maze-100-1.map 100 100 71 95 25 63 402
+100 maze-100-1.map 100 100 31 13 97 41 402
+100 maze-100-1.map 100 100 33 83 43 11 402
+101 maze-100-1.map 100 100 11 23 67 50 405
+101 maze-100-1.map 100 100 65 87 47 30 407
+101 maze-100-1.map 100 100 7 67 88 3 405
+101 maze-100-1.map 100 100 35 3 74 33 405
+101 maze-100-1.map 100 100 3 92 55 5 407
+101 maze-100-1.map 100 100 63 23 55 50 407
+101 maze-100-1.map 100 100 37 3 85 33 406
+101 maze-100-1.map 100 100 87 59 64 47 405
+101 maze-100-1.map 100 100 17 53 77 87 406
+101 maze-100-1.map 100 100 81 15 50 45 407
+102 maze-100-1.map 100 100 61 33 63 41 410
+102 maze-100-1.map 100 100 31 98 50 27 410
+102 maze-100-1.map 100 100 46 49 73 18 410
+102 maze-100-1.map 100 100 47 88 35 31 411
+102 maze-100-1.map 100 100 82 75 47 23 409
+102 maze-100-1.map 100 100 21 65 89 70 409
+102 maze-100-1.map 100 100 23 53 97 45 410
+102 maze-100-1.map 100 100 33 73 59 32 411
+102 maze-100-1.map 100 100 45 28 3 82 410
+102 maze-100-1.map 100 100 82 57 57 49 411
+103 maze-100-1.map 100 100 60 37 64 45 412
+103 maze-100-1.map 100 100 50 5 61 73 413
+103 maze-100-1.map 100 100 61 69 45 6 415
+103 maze-100-1.map 100 100 15 63 77 22 413
+103 maze-100-1.map 100 100 53 53 65 5 412
+103 maze-100-1.map 100 100 31 3 99 15 412
+103 maze-100-1.map 100 100 59 21 14 1 415
+103 maze-100-1.map 100 100 58 57 5 77 413
+103 maze-100-1.map 100 100 45 27 79 89 412
+103 maze-100-1.map 100 100 75 35 45 45 412
+104 maze-100-1.map 100 100 7 93 37 31 416
+104 maze-100-1.map 100 100 69 53 52 15 419
+104 maze-100-1.map 100 100 49 15 61 57 418
+104 maze-100-1.map 100 100 12 85 25 11 419
+104 maze-100-1.map 100 100 40 77 30 35 416
+104 maze-100-1.map 100 100 59 33 31 77 416
+104 maze-100-1.map 100 100 89 66 49 26 416
+104 maze-100-1.map 100 100 19 91 43 26 419
+104 maze-100-1.map 100 100 73 41 57 39 418
+104 maze-100-1.map 100 100 69 17 34 73 419
+105 maze-100-1.map 100 100 17 54 13 75 421
+105 maze-100-1.map 100 100 55 18 67 50 420
+105 maze-100-1.map 100 100 45 93 11 32 421
+105 maze-100-1.map 100 100 35 86 68 23 422
+105 maze-100-1.map 100 100 87 27 33 85 420
+105 maze-100-1.map 100 100 62 21 55 36 422
+105 maze-100-1.map 100 100 15 27 53 78 423
+105 maze-100-1.map 100 100 99 19 17 65 420
+105 maze-100-1.map 100 100 44 21 41 68 422
+105 maze-100-1.map 100 100 80 29 30 83 422
+106 maze-100-1.map 100 100 98 5 23 72 426
+106 maze-100-1.map 100 100 48 77 47 5 427
+106 maze-100-1.map 100 100 64 35 41 47 427
+106 maze-100-1.map 100 100 46 69 6 41 426
+106 maze-100-1.map 100 100 39 23 41 69 424
+106 maze-100-1.map 100 100 39 15 51 86 427
+106 maze-100-1.map 100 100 39 76 67 38 424
+106 maze-100-1.map 100 100 55 40 68 19 426
+106 maze-100-1.map 100 100 8 97 9 18 426
+106 maze-100-1.map 100 100 3 98 55 25 425
+107 maze-100-1.map 100 100 97 57 19 53 430
+107 maze-100-1.map 100 100 67 42 49 43 431
+107 maze-100-1.map 100 100 75 16 18 85 428
+107 maze-100-1.map 100 100 3 93 17 20 431
+107 maze-100-1.map 100 100 72 27 46 49 430
+107 maze-100-1.map 100 100 25 53 95 70 431
+107 maze-100-1.map 100 100 25 5 63 41 430
+107 maze-100-1.map 100 100 25 33 97 56 429
+107 maze-100-1.map 100 100 25 44 10 3 430
+107 maze-100-1.map 100 100 39 43 94 11 431
+108 maze-100-1.map 100 100 77 26 51 50 432
+108 maze-100-1.map 100 100 17 95 31 35 434
+108 maze-100-1.map 100 100 29 22 89 8 432
+108 maze-100-1.map 100 100 35 89 74 21 435
+108 maze-100-1.map 100 100 77 16 35 82 434
+108 maze-100-1.map 100 100 83 91 17 55 434
+108 maze-100-1.map 100 100 81 31 9 84 435
+108 maze-100-1.map 100 100 31 86 77 20 434
+108 maze-100-1.map 100 100 79 27 52 43 435
+108 maze-100-1.map 100 100 19 63 97 31 434
+109 maze-100-1.map 100 100 3 15 17 78 437
+109 maze-100-1.map 100 100 46 93 14 49 438
+109 maze-100-1.map 100 100 98 23 48 53 438
+109 maze-100-1.map 100 100 1 95 59 1 436
+109 maze-100-1.map 100 100 21 67 65 26 437
+109 maze-100-1.map 100 100 18 93 59 35 437
+109 maze-100-1.map 100 100 16 13 29 97 439
+109 maze-100-1.map 100 100 61 2 60 55 436
+109 maze-100-1.map 100 100 53 55 81 27 436
+109 maze-100-1.map 100 100 11 63 61 63 438
+110 maze-100-1.map 100 100 17 20 23 91 441
+110 maze-100-1.map 100 100 93 19 37 50 443
+110 maze-100-1.map 100 100 28 79 27 65 443
+110 maze-100-1.map 100 100 1 16 76 19 440
+110 maze-100-1.map 100 100 91 15 39 51 440
+110 maze-100-1.map 100 100 99 9 41 1 442
+110 maze-100-1.map 100 100 22 83 17 69 443
+110 maze-100-1.map 100 100 43 29 29 96 441
+110 maze-100-1.map 100 100 99 31 39 37 442
+110 maze-100-1.map 100 100 95 20 41 49 441
+111 maze-100-1.map 100 100 63 54 68 1 446
+111 maze-100-1.map 100 100 23 45 38 87 445
+111 maze-100-1.map 100 100 83 18 55 47 445
+111 maze-100-1.map 100 100 87 71 40 23 447
+111 maze-100-1.map 100 100 54 91 6 39 444
+111 maze-100-1.map 100 100 89 68 46 21 444
+111 maze-100-1.map 100 100 1 55 58 83 447
+111 maze-100-1.map 100 100 9 5 95 34 447
+111 maze-100-1.map 100 100 54 43 85 28 444
+111 maze-100-1.map 100 100 33 2 96 51 446
+112 maze-100-1.map 100 100 69 25 9 95 450
+112 maze-100-1.map 100 100 85 1 9 79 450
+112 maze-100-1.map 100 100 62 49 73 47 451
+112 maze-100-1.map 100 100 34 95 41 29 451
+112 maze-100-1.map 100 100 9 19 21 91 448
+112 maze-100-1.map 100 100 8 69 57 67 449
+112 maze-100-1.map 100 100 51 33 67 45 448
+112 maze-100-1.map 100 100 75 27 16 87 451
+112 maze-100-1.map 100 100 67 17 18 93 451
+112 maze-100-1.map 100 100 33 2 43 47 449
+113 maze-100-1.map 100 100 5 94 71 6 452
+113 maze-100-1.map 100 100 43 17 43 95 454
+113 maze-100-1.map 100 100 90 83 19 39 453
+113 maze-100-1.map 100 100 58 25 66 61 452
+113 maze-100-1.map 100 100 13 35 71 99 454
+113 maze-100-1.map 100 100 69 33 29 85 452
+113 maze-100-1.map 100 100 1 12 20 75 454
+113 maze-100-1.map 100 100 95 47 41 49 452
+113 maze-100-1.map 100 100 47 75 4 55 453
+113 maze-100-1.map 100 100 15 2 21 71 453
+114 maze-100-1.map 100 100 77 8 6 97 456
+114 maze-100-1.map 100 100 65 4 1 89 459
+114 maze-100-1.map 100 100 17 43 63 87 458
+114 maze-100-1.map 100 100 57 25 2 85 459
+114 maze-100-1.map 100 100 63 63 65 10 457
+114 maze-100-1.map 100 100 55 67 61 34 459
+114 maze-100-1.map 100 100 11 52 59 94 456
+114 maze-100-1.map 100 100 30 37 75 48 456
+114 maze-100-1.map 100 100 19 62 97 67 457
+114 maze-100-1.map 100 100 51 66 6 63 456
+115 maze-100-1.map 100 100 7 52 39 58 460
+115 maze-100-1.map 100 100 21 54 15 83 463
+115 maze-100-1.map 100 100 90 17 43 11 461
+115 maze-100-1.map 100 100 41 31 67 45 460
+115 maze-100-1.map 100 100 79 57 27 60 463
+115 maze-100-1.map 100 100 65 35 54 43 463
+115 maze-100-1.map 100 100 10 9 4 89 460
+115 maze-100-1.map 100 100 92 99 29 65 461
+115 maze-100-1.map 100 100 98 39 3 3 463
+115 maze-100-1.map 100 100 61 28 21 87 463
+116 maze-100-1.map 100 100 68 63 18 39 466
+116 maze-100-1.map 100 100 40 45 32 91 464
+116 maze-100-1.map 100 100 95 20 45 53 465
+116 maze-100-1.map 100 100 27 57 81 43 464
+116 maze-100-1.map 100 100 23 33 1 92 467
+116 maze-100-1.map 100 100 23 49 35 85 464
+116 maze-100-1.map 100 100 97 53 29 66 465
+116 maze-100-1.map 100 100 63 57 7 83 466
+116 maze-100-1.map 100 100 97 59 16 69 467
+116 maze-100-1.map 100 100 47 57 7 33 464
+117 maze-100-1.map 100 100 54 15 43 63 469
+117 maze-100-1.map 100 100 84 53 29 31 471
+117 maze-100-1.map 100 100 69 66 22 49 470
+117 maze-100-1.map 100 100 19 85 27 61 468
+117 maze-100-1.map 100 100 35 97 37 33 470
+117 maze-100-1.map 100 100 39 83 31 3 468
+117 maze-100-1.map 100 100 10 5 25 67 469
+117 maze-100-1.map 100 100 23 1 93 38 469
+117 maze-100-1.map 100 100 37 32 87 60 470
+117 maze-100-1.map 100 100 59 74 23 18 470
+118 maze-100-1.map 100 100 33 73 51 35 472
+118 maze-100-1.map 100 100 11 8 75 51 473
+118 maze-100-1.map 100 100 17 62 29 81 475
+118 maze-100-1.map 100 100 55 81 3 47 474
+118 maze-100-1.map 100 100 26 17 3 95 473
+118 maze-100-1.map 100 100 89 7 33 2 475
+118 maze-100-1.map 100 100 31 86 91 11 475
+118 maze-100-1.map 100 100 49 62 13 13 475
+118 maze-100-1.map 100 100 65 27 8 3 475
+118 maze-100-1.map 100 100 89 61 26 57 473
+119 maze-100-1.map 100 100 5 87 76 11 479
+119 maze-100-1.map 100 100 87 26 59 53 479
+119 maze-100-1.map 100 100 27 64 81 47 479
+119 maze-100-1.map 100 100 91 47 9 6 477
+119 maze-100-1.map 100 100 75 3 1 93 476
+119 maze-100-1.map 100 100 53 60 89 32 478
+119 maze-100-1.map 100 100 84 15 45 83 479
+119 maze-100-1.map 100 100 53 74 3 76 476
+119 maze-100-1.map 100 100 27 90 99 45 479
+119 maze-100-1.map 100 100 63 73 60 13 479
+120 maze-100-1.map 100 100 53 85 4 63 481
+120 maze-100-1.map 100 100 94 83 22 57 480
+120 maze-100-1.map 100 100 57 14 57 85 481
+120 maze-100-1.map 100 100 76 7 3 84 482
+120 maze-100-1.map 100 100 25 25 73 73 480
+120 maze-100-1.map 100 100 73 30 57 61 481
+120 maze-100-1.map 100 100 35 59 9 41 480
+120 maze-100-1.map 100 100 33 47 19 31 482
+120 maze-100-1.map 100 100 85 53 17 51 482
+120 maze-100-1.map 100 100 27 58 89 19 481
+121 maze-100-1.map 100 100 89 73 28 29 485
+121 maze-100-1.map 100 100 44 65 15 16 486
+121 maze-100-1.map 100 100 53 35 43 1 484
+121 maze-100-1.map 100 100 77 15 3 97 484
+121 maze-100-1.map 100 100 97 33 7 3 484
+121 maze-100-1.map 100 100 81 6 51 34 484
+121 maze-100-1.map 100 100 83 96 21 27 485
+121 maze-100-1.map 100 100 13 2 39 39 487
+121 maze-100-1.map 100 100 4 1 19 65 485
+121 maze-100-1.map 100 100 39 89 21 65 486
+122 maze-100-1.map 100 100 60 65 13 11 489
+122 maze-100-1.map 100 100 33 40 17 25 489
+122 maze-100-1.map 100 100 76 37 51 71 491
+122 maze-100-1.map 100 100 89 53 19 61 490
+122 maze-100-1.map 100 100 37 51 92 7 489
+122 maze-100-1.map 100 100 24 99 25 7 489
+122 maze-100-1.map 100 100 24 57 85 3 489
+122 maze-100-1.map 100 100 65 15 25 93 490
+122 maze-100-1.map 100 100 51 33 9 94 489
+122 maze-100-1.map 100 100 35 7 68 51 491
+123 maze-100-1.map 100 100 19 69 89 9 494
+123 maze-100-1.map 100 100 68 81 5 37 493
+123 maze-100-1.map 100 100 24 69 13 83 495
+123 maze-100-1.map 100 100 93 97 49 19 494
+123 maze-100-1.map 100 100 51 74 55 22 492
+123 maze-100-1.map 100 100 67 20 59 72 492
+123 maze-100-1.map 100 100 89 14 31 3 495
+123 maze-100-1.map 100 100 57 21 59 85 494
+123 maze-100-1.map 100 100 52 37 97 31 493
+123 maze-100-1.map 100 100 53 27 95 73 492
+124 maze-100-1.map 100 100 39 3 84 3 499
+124 maze-100-1.map 100 100 85 66 13 40 498
+124 maze-100-1.map 100 100 41 41 5 25 496
+124 maze-100-1.map 100 100 19 42 34 47 498
+124 maze-100-1.map 100 100 17 1 41 46 497
+124 maze-100-1.map 100 100 29 74 37 1 497
+124 maze-100-1.map 100 100 18 49 45 78 496
+124 maze-100-1.map 100 100 49 61 69 8 497
+124 maze-100-1.map 100 100 99 98 11 71 499
+124 maze-100-1.map 100 100 41 29 83 56 497
+125 maze-100-1.map 100 100 3 59 67 85 502
+125 maze-100-1.map 100 100 65 77 21 53 500
+125 maze-100-1.map 100 100 90 85 19 60 502
+125 maze-100-1.map 100 100 23 95 25 52 501
+125 maze-100-1.map 100 100 66 7 50 93 500
+125 maze-100-1.map 100 100 15 95 71 31 500
+125 maze-100-1.map 100 100 19 62 39 73 501
+125 maze-100-1.map 100 100 6 91 21 55 503
+125 maze-100-1.map 100 100 82 41 17 69 501
+125 maze-100-1.map 100 100 48 13 35 53 501
+126 maze-100-1.map 100 100 19 65 87 41 504
+126 maze-100-1.map 100 100 3 1 39 89 504
+126 maze-100-1.map 100 100 51 69 12 77 507
+126 maze-100-1.map 100 100 24 59 91 82 506
+126 maze-100-1.map 100 100 51 66 25 10 506
+126 maze-100-1.map 100 100 55 53 61 27 504
+126 maze-100-1.map 100 100 19 44 35 65 507
+126 maze-100-1.map 100 100 15 86 92 41 504
+126 maze-100-1.map 100 100 53 95 9 57 506
+126 maze-100-1.map 100 100 21 97 41 7 506
+127 maze-100-1.map 100 100 1 16 93 25 511
+127 maze-100-1.map 100 100 31 84 52 45 510
+127 maze-100-1.map 100 100 91 21 67 50 511
+127 maze-100-1.map 100 100 1 97 42 9 509
+127 maze-100-1.map 100 100 53 10 52 95 508
+127 maze-100-1.map 100 100 17 25 79 85 510
+127 maze-100-1.map 100 100 60 99 1 54 510
+127 maze-100-1.map 100 100 10 9 61 83 509
+127 maze-100-1.map 100 100 19 32 83 89 509
+127 maze-100-1.map 100 100 65 61 86 25 511
+128 maze-100-1.map 100 100 71 75 9 40 513
+128 maze-100-1.map 100 100 13 64 25 55 513
+128 maze-100-1.map 100 100 23 62 42 77 514
+128 maze-100-1.map 100 100 39 83 54 45 513
+128 maze-100-1.map 100 100 39 93 65 13 514
+128 maze-100-1.map 100 100 47 83 8 79 513
+128 maze-100-1.map 100 100 55 71 4 49 513
+128 maze-100-1.map 100 100 10 65 47 57 515
+128 maze-100-1.map 100 100 87 83 47 27 512
+128 maze-100-1.map 100 100 31 84 7 3 515
+129 maze-100-1.map 100 100 91 3 1 16 519
+129 maze-100-1.map 100 100 61 61 77 21 516
+129 maze-100-1.map 100 100 79 97 19 42 517
+129 maze-100-1.map 100 100 55 25 63 99 518
+129 maze-100-1.map 100 100 35 73 98 29 519
+129 maze-100-1.map 100 100 15 5 54 61 519
+129 maze-100-1.map 100 100 9 95 64 27 519
+129 maze-100-1.map 100 100 36 69 8 23 518
+129 maze-100-1.map 100 100 88 3 27 3 517
+129 maze-100-1.map 100 100 1 27 15 62 519
+130 maze-100-1.map 100 100 57 73 57 1 520
+130 maze-100-1.map 100 100 93 87 24 69 523
+130 maze-100-1.map 100 100 57 41 98 25 521
+130 maze-100-1.map 100 100 99 66 45 21 521
+130 maze-100-1.map 100 100 99 47 37 72 523
+130 maze-100-1.map 100 100 16 77 46 71 522
+130 maze-100-1.map 100 100 69 25 52 91 523
+130 maze-100-1.map 100 100 1 7 14 83 523
+130 maze-100-1.map 100 100 12 99 28 65 520
+130 maze-100-1.map 100 100 21 4 63 41 521
+131 maze-100-1.map 100 100 39 73 40 51 527
+131 maze-100-1.map 100 100 6 71 83 12 524
+131 maze-100-1.map 100 100 27 99 77 23 526
+131 maze-100-1.map 100 100 62 17 47 78 524
+131 maze-100-1.map 100 100 73 45 43 29 526
+131 maze-100-1.map 100 100 81 93 45 6 527
+131 maze-100-1.map 100 100 43 12 23 98 524
+131 maze-100-1.map 100 100 42 9 62 61 524
+131 maze-100-1.map 100 100 28 91 81 9 527
+131 maze-100-1.map 100 100 67 15 51 76 527
+132 maze-100-1.map 100 100 45 80 66 29 530
+132 maze-100-1.map 100 100 9 54 41 73 529
+132 maze-100-1.map 100 100 15 66 33 77 529
+132 maze-100-1.map 100 100 65 59 95 33 528
+132 maze-100-1.map 100 100 5 81 57 89 528
+132 maze-100-1.map 100 100 79 9 55 93 528
+132 maze-100-1.map 100 100 53 69 71 25 530
+132 maze-100-1.map 100 100 43 6 11 87 529
+132 maze-100-1.map 100 100 60 67 69 29 531
+132 maze-100-1.map 100 100 25 88 55 38 528
+133 maze-100-1.map 100 100 43 92 61 34 534
+133 maze-100-1.map 100 100 28 97 47 37 535
+133 maze-100-1.map 100 100 53 83 7 80 533
+133 maze-100-1.map 100 100 16 59 73 64 534
+133 maze-100-1.map 100 100 11 52 37 42 534
+133 maze-100-1.map 100 100 1 83 77 33 534
+133 maze-100-1.map 100 100 43 62 31 7 535
+133 maze-100-1.map 100 100 41 55 16 21 535
+133 maze-100-1.map 100 100 71 24 59 74 532
+133 maze-100-1.map 100 100 79 15 29 97 532
+134 maze-100-1.map 100 100 48 63 9 73 537
+134 maze-100-1.map 100 100 17 55 92 83 537
+134 maze-100-1.map 100 100 89 23 23 93 536
+134 maze-100-1.map 100 100 73 27 61 72 539
+134 maze-100-1.map 100 100 31 95 21 49 536
+134 maze-100-1.map 100 100 11 45 71 85 536
+134 maze-100-1.map 100 100 12 87 35 3 539
+134 maze-100-1.map 100 100 69 47 45 29 538
+134 maze-100-1.map 100 100 26 17 53 92 536
+134 maze-100-1.map 100 100 16 77 47 85 539
+135 maze-100-1.map 100 100 6 39 77 97 543
+135 maze-100-1.map 100 100 16 63 93 33 541
+135 maze-100-1.map 100 100 58 85 7 82 542
+135 maze-100-1.map 100 100 1 96 44 43 540
+135 maze-100-1.map 100 100 78 71 10 29 540
+135 maze-100-1.map 100 100 69 41 23 63 540
+135 maze-100-1.map 100 100 8 79 55 77 543
+135 maze-100-1.map 100 100 54 67 73 33 541
+135 maze-100-1.map 100 100 22 89 65 34 540
+135 maze-100-1.map 100 100 54 77 77 5 541
+136 maze-100-1.map 100 100 73 85 55 22 547
+136 maze-100-1.map 100 100 94 59 14 25 546
+136 maze-100-1.map 100 100 7 89 25 66 545
+136 maze-100-1.map 100 100 10 71 83 5 547
+136 maze-100-1.map 100 100 89 31 53 72 545
+136 maze-100-1.map 100 100 29 67 1 89 546
+136 maze-100-1.map 100 100 92 31 53 71 547
+136 maze-100-1.map 100 100 28 69 5 99 547
+136 maze-100-1.map 100 100 13 47 29 43 544
+136 maze-100-1.map 100 100 61 48 99 55 547
+137 maze-100-1.map 100 100 4 51 41 65 551
+137 maze-100-1.map 100 100 37 58 83 31 551
+137 maze-100-1.map 100 100 37 61 83 31 548
+137 maze-100-1.map 100 100 39 87 59 54 549
+137 maze-100-1.map 100 100 48 59 3 73 549
+137 maze-100-1.map 100 100 43 49 7 90 551
+137 maze-100-1.map 100 100 9 91 94 7 549
+137 maze-100-1.map 100 100 63 29 53 68 549
+137 maze-100-1.map 100 100 31 3 67 49 550
+137 maze-100-1.map 100 100 95 10 59 59 549
+138 maze-100-1.map 100 100 35 97 85 25 554
+138 maze-100-1.map 100 100 87 45 67 55 554
+138 maze-100-1.map 100 100 53 3 68 91 553
+138 maze-100-1.map 100 100 60 83 71 30 554
+138 maze-100-1.map 100 100 87 6 1 11 555
+138 maze-100-1.map 100 100 43 11 55 89 554
+138 maze-100-1.map 100 100 9 81 2 17 553
+138 maze-100-1.map 100 100 45 81 93 38 555
+138 maze-100-1.map 100 100 89 14 54 33 552
+138 maze-100-1.map 100 100 21 8 64 85 552
+139 maze-100-1.map 100 100 67 14 65 81 559
+139 maze-100-1.map 100 100 24 11 45 59 557
+139 maze-100-1.map 100 100 7 93 99 57 556
+139 maze-100-1.map 100 100 44 61 77 23 559
+139 maze-100-1.map 100 100 63 71 46 19 557
+139 maze-100-1.map 100 100 47 83 71 27 556
+139 maze-100-1.map 100 100 57 93 7 73 558
+139 maze-100-1.map 100 100 7 20 65 93 557
+139 maze-100-1.map 100 100 66 29 57 65 559
+139 maze-100-1.map 100 100 11 53 79 90 557
+140 maze-100-1.map 100 100 11 25 87 92 563
+140 maze-100-1.map 100 100 49 2 89 73 561
+140 maze-100-1.map 100 100 11 50 79 67 561
+140 maze-100-1.map 100 100 83 69 57 1 562
+140 maze-100-1.map 100 100 31 20 54 77 562
+140 maze-100-1.map 100 100 79 9 55 72 561
+140 maze-100-1.map 100 100 59 92 85 19 561
+140 maze-100-1.map 100 100 91 17 53 57 562
+140 maze-100-1.map 100 100 67 14 63 79 563
+140 maze-100-1.map 100 100 73 79 21 18 561
+141 maze-100-1.map 100 100 79 16 41 87 565
+141 maze-100-1.map 100 100 95 5 63 51 566
+141 maze-100-1.map 100 100 78 25 51 84 564
+141 maze-100-1.map 100 100 59 11 75 99 564
+141 maze-100-1.map 100 100 8 75 59 78 564
+141 maze-100-1.map 100 100 91 43 3 86 565
+141 maze-100-1.map 100 100 92 1 19 96 564
+141 maze-100-1.map 100 100 75 91 69 9 564
+141 maze-100-1.map 100 100 13 73 44 63 565
+141 maze-100-1.map 100 100 23 13 31 56 565
+142 maze-100-1.map 100 100 4 95 17 59 571
+142 maze-100-1.map 100 100 97 65 13 35 570
+142 maze-100-1.map 100 100 51 9 73 74 571
+142 maze-100-1.map 100 100 43 1 36 97 571
+142 maze-100-1.map 100 100 18 5 65 49 571
+142 maze-100-1.map 100 100 95 58 19 45 571
+142 maze-100-1.map 100 100 49 3 91 79 570
+142 maze-100-1.map 100 100 36 89 71 57 569
+142 maze-100-1.map 100 100 3 51 33 41 568
+142 maze-100-1.map 100 100 59 23 68 99 569
+143 maze-100-1.map 100 100 9 88 57 44 574
+143 maze-100-1.map 100 100 1 56 87 93 575
+143 maze-100-1.map 100 100 65 82 7 81 575
+143 maze-100-1.map 100 100 53 85 39 6 573
+143 maze-100-1.map 100 100 67 58 37 87 573
+143 maze-100-1.map 100 100 25 93 43 51 572
+143 maze-100-1.map 100 100 11 98 83 12 574
+143 maze-100-1.map 100 100 1 70 77 88 572
+143 maze-100-1.map 100 100 67 77 39 24 575
+143 maze-100-1.map 100 100 88 41 28 29 572
+144 maze-100-1.map 100 100 57 9 83 91 576
+144 maze-100-1.map 100 100 16 19 77 93 579
+144 maze-100-1.map 100 100 71 38 64 79 576
+144 maze-100-1.map 100 100 71 11 80 73 579
+144 maze-100-1.map 100 100 44 95 75 31 579
+144 maze-100-1.map 100 100 40 99 71 25 579
+144 maze-100-1.map 100 100 91 5 35 87 578
+144 maze-100-1.map 100 100 21 29 76 59 579
+144 maze-100-1.map 100 100 35 47 61 40 579
+144 maze-100-1.map 100 100 12 5 65 52 576
+145 maze-100-1.map 100 100 93 53 19 45 582
+145 maze-100-1.map 100 100 40 91 43 5 581
+145 maze-100-1.map 100 100 10 43 99 60 582
+145 maze-100-1.map 100 100 63 79 28 7 581
+145 maze-100-1.map 100 100 74 95 69 24 580
+145 maze-100-1.map 100 100 20 29 84 59 582
+145 maze-100-1.map 100 100 3 94 2 11 580
+145 maze-100-1.map 100 100 90 63 51 5 581
+145 maze-100-1.map 100 100 3 37 89 94 583
+145 maze-100-1.map 100 100 83 5 1 24 581
+146 maze-100-1.map 100 100 35 45 23 15 586
+146 maze-100-1.map 100 100 17 16 39 70 586
+146 maze-100-1.map 100 100 73 95 67 20 585
+146 maze-100-1.map 100 100 23 16 35 44 586
+146 maze-100-1.map 100 100 42 1 55 84 586
+146 maze-100-1.map 100 100 99 69 37 25 586
+146 maze-100-1.map 100 100 58 85 73 22 584
+146 maze-100-1.map 100 100 77 16 69 99 585
+146 maze-100-1.map 100 100 4 19 79 64 584
+146 maze-100-1.map 100 100 55 25 80 89 587
+147 maze-100-1.map 100 100 62 63 23 87 591
+147 maze-100-1.map 100 100 34 41 61 35 589
+147 maze-100-1.map 100 100 61 46 11 82 590
+147 maze-100-1.map 100 100 77 98 19 20 588
+147 maze-100-1.map 100 100 35 67 79 36 591
+147 maze-100-1.map 100 100 67 85 17 78 591
+147 maze-100-1.map 100 100 99 60 7 29 591
+147 maze-100-1.map 100 100 7 68 68 97 588
+147 maze-100-1.map 100 100 74 15 51 55 589
+147 maze-100-1.map 100 100 40 15 95 67 589
+148 maze-100-1.map 100 100 93 5 67 49 594
+148 maze-100-1.map 100 100 75 83 57 27 594
+148 maze-100-1.map 100 100 73 37 77 90 593
+148 maze-100-1.map 100 100 21 91 1 20 593
+148 maze-100-1.map 100 100 71 21 75 85 592
+148 maze-100-1.map 100 100 73 94 7 7 595
+148 maze-100-1.map 100 100 58 19 75 96 592
+148 maze-100-1.map 100 100 79 95 69 35 594
+148 maze-100-1.map 100 100 40 71 69 4 592
+148 maze-100-1.map 100 100 97 33 51 79 592
+149 maze-100-1.map 100 100 91 2 59 75 599
+149 maze-100-1.map 100 100 80 39 21 26 596
+149 maze-100-1.map 100 100 77 73 77 5 596
+149 maze-100-1.map 100 100 47 63 23 1 598
+149 maze-100-1.map 100 100 22 99 15 59 597
+149 maze-100-1.map 100 100 61 61 22 87 597
+149 maze-100-1.map 100 100 63 91 71 24 597
+149 maze-100-1.map 100 100 20 71 61 91 599
+149 maze-100-1.map 100 100 36 23 85 59 597
+149 maze-100-1.map 100 100 37 42 11 20 596
+150 maze-100-1.map 100 100 39 58 97 14 602
+150 maze-100-1.map 100 100 23 16 88 71 602
+150 maze-100-1.map 100 100 96 97 37 19 601
+150 maze-100-1.map 100 100 98 79 13 28 600
+150 maze-100-1.map 100 100 45 81 57 47 602
+150 maze-100-1.map 100 100 13 73 61 99 602
+150 maze-100-1.map 100 100 85 41 12 31 603
+150 maze-100-1.map 100 100 91 47 55 82 603
+150 maze-100-1.map 100 100 1 37 92 65 601
+150 maze-100-1.map 100 100 67 57 83 9 600
+151 maze-100-1.map 100 100 37 5 74 79 607
+151 maze-100-1.map 100 100 91 54 49 6 604
+151 maze-100-1.map 100 100 49 76 93 1 607
+151 maze-100-1.map 100 100 16 3 25 93 605
+151 maze-100-1.map 100 100 6 5 43 69 605
+151 maze-100-1.map 100 100 14 99 83 5 605
+151 maze-100-1.map 100 100 98 33 49 91 607
+151 maze-100-1.map 100 100 73 54 11 83 607
+151 maze-100-1.map 100 100 73 41 70 75 605
+151 maze-100-1.map 100 100 39 7 61 85 604
+152 maze-100-1.map 100 100 73 75 73 35 608
+152 maze-100-1.map 100 100 58 27 65 97 609
+152 maze-100-1.map 100 100 3 85 55 55 610
+152 maze-100-1.map 100 100 63 54 82 1 608
+152 maze-100-1.map 100 100 53 77 65 27 610
+152 maze-100-1.map 100 100 73 95 76 29 609
+152 maze-100-1.map 100 100 28 95 89 9 609
+152 maze-100-1.map 100 100 53 54 1 82 608
+152 maze-100-1.map 100 100 72 83 13 79 611
+152 maze-100-1.map 100 100 83 30 37 53 609
+153 maze-100-1.map 100 100 25 8 43 74 614
+153 maze-100-1.map 100 100 67 97 19 9 612
+153 maze-100-1.map 100 100 43 9 72 99 615
+153 maze-100-1.map 100 100 87 31 43 89 614
+153 maze-100-1.map 100 100 89 83 14 35 615
+153 maze-100-1.map 100 100 83 89 3 77 612
+153 maze-100-1.map 100 100 63 75 20 27 615
+153 maze-100-1.map 100 100 84 77 67 9 613
+153 maze-100-1.map 100 100 29 9 33 50 615
+153 maze-100-1.map 100 100 53 95 92 23 615
+154 maze-100-1.map 100 100 1 5 43 65 618
+154 maze-100-1.map 100 100 13 21 85 91 618
+154 maze-100-1.map 100 100 89 15 63 63 618
+154 maze-100-1.map 100 100 47 76 25 87 617
+154 maze-100-1.map 100 100 72 81 11 79 617
+154 maze-100-1.map 100 100 82 59 5 43 617
+154 maze-100-1.map 100 100 37 64 13 10 616
+154 maze-100-1.map 100 100 13 43 75 57 616
+154 maze-100-1.map 100 100 69 81 85 28 619
+154 maze-100-1.map 100 100 42 9 58 97 618
+155 maze-100-1.map 100 100 23 97 5 17 622
+155 maze-100-1.map 100 100 15 89 57 55 620
+155 maze-100-1.map 100 100 82 19 75 79 623
+155 maze-100-1.map 100 100 77 44 14 35 620
+155 maze-100-1.map 100 100 29 49 77 1 620
+155 maze-100-1.map 100 100 46 15 85 43 621
+155 maze-100-1.map 100 100 34 41 73 10 620
+155 maze-100-1.map 100 100 65 51 35 74 623
+155 maze-100-1.map 100 100 63 79 40 9 621
+155 maze-100-1.map 100 100 13 2 49 70 622
+156 maze-100-1.map 100 100 97 82 13 50 624
+156 maze-100-1.map 100 100 15 34 65 75 625
+156 maze-100-1.map 100 100 75 3 71 92 627
+156 maze-100-1.map 100 100 27 79 51 75 624
+156 maze-100-1.map 100 100 71 15 86 79 627
+156 maze-100-1.map 100 100 31 3 63 88 627
+156 maze-100-1.map 100 100 31 23 92 93 625
+156 maze-100-1.map 100 100 31 45 75 3 626
+156 maze-100-1.map 100 100 93 82 40 17 624
+156 maze-100-1.map 100 100 99 2 49 92 624
+157 maze-100-1.map 100 100 52 77 99 45 631
+157 maze-100-1.map 100 100 27 14 66 89 628
+157 maze-100-1.map 100 100 93 97 2 61 629
+157 maze-100-1.map 100 100 91 47 51 81 630
+157 maze-100-1.map 100 100 83 95 14 81 629
+157 maze-100-1.map 100 100 87 81 36 17 629
+157 maze-100-1.map 100 100 76 35 61 99 629
+157 maze-100-1.map 100 100 78 71 29 5 631
+157 maze-100-1.map 100 100 77 25 78 73 629
+157 maze-100-1.map 100 100 96 57 57 3 629
+158 maze-100-1.map 100 100 12 21 83 80 634
+158 maze-100-1.map 100 100 35 64 75 31 635
+158 maze-100-1.map 100 100 97 13 35 58 635
+158 maze-100-1.map 100 100 72 29 68 79 632
+158 maze-100-1.map 100 100 25 19 73 70 633
+158 maze-100-1.map 100 100 27 98 56 61 634
+158 maze-100-1.map 100 100 42 53 77 21 633
+158 maze-100-1.map 100 100 53 19 93 55 632
+158 maze-100-1.map 100 100 9 95 65 59 632
+158 maze-100-1.map 100 100 53 93 87 49 634
+159 maze-100-1.map 100 100 44 3 73 95 639
+159 maze-100-1.map 100 100 43 13 39 64 637
+159 maze-100-1.map 100 100 67 4 85 83 637
+159 maze-100-1.map 100 100 36 69 94 29 638
+159 maze-100-1.map 100 100 71 79 68 33 637
+159 maze-100-1.map 100 100 65 92 33 21 639
+159 maze-100-1.map 100 100 69 13 90 63 639
+159 maze-100-1.map 100 100 91 51 6 57 639
+159 maze-100-1.map 100 100 97 93 1 63 638
+159 maze-100-1.map 100 100 55 41 23 97 636
+160 maze-100-1.map 100 100 31 47 58 19 641
+160 maze-100-1.map 100 100 96 73 1 58 640
+160 maze-100-1.map 100 100 83 47 3 19 640
+160 maze-100-1.map 100 100 41 97 87 45 642
+160 maze-100-1.map 100 100 5 9 29 48 643
+160 maze-100-1.map 100 100 37 83 43 66 643
+160 maze-100-1.map 100 100 95 33 33 59 640
+160 maze-100-1.map 100 100 83 92 26 19 642
+160 maze-100-1.map 100 100 75 59 9 47 642
+160 maze-100-1.map 100 100 49 7 81 61 642
+161 maze-100-1.map 100 100 81 19 72 81 647
+161 maze-100-1.map 100 100 63 65 1 35 644
+161 maze-100-1.map 100 100 37 61 85 49 644
+161 maze-100-1.map 100 100 54 93 9 3 647
+161 maze-100-1.map 100 100 85 41 50 3 647
+161 maze-100-1.map 100 100 48 87 96 41 646
+161 maze-100-1.map 100 100 64 79 63 36 644
+161 maze-100-1.map 100 100 93 73 7 8 647
+161 maze-100-1.map 100 100 72 73 25 21 647
+161 maze-100-1.map 100 100 67 96 29 22 646
+162 maze-100-1.map 100 100 69 22 84 87 648
+162 maze-100-1.map 100 100 93 5 59 94 649
+162 maze-100-1.map 100 100 35 44 88 27 650
+162 maze-100-1.map 100 100 57 93 87 49 650
+162 maze-100-1.map 100 100 43 97 91 3 650
+162 maze-100-1.map 100 100 69 73 91 24 649
+162 maze-100-1.map 100 100 77 90 85 29 649
+162 maze-100-1.map 100 100 77 92 30 15 648
+162 maze-100-1.map 100 100 53 12 99 80 650
+162 maze-100-1.map 100 100 8 29 77 42 648
+163 maze-100-1.map 100 100 89 68 43 11 655
+163 maze-100-1.map 100 100 98 49 55 75 655
+163 maze-100-1.map 100 100 81 57 11 28 655
+163 maze-100-1.map 100 100 23 84 64 83 652
+163 maze-100-1.map 100 100 25 83 59 97 652
+163 maze-100-1.map 100 100 96 95 1 43 655
+163 maze-100-1.map 100 100 53 20 79 57 655
+163 maze-100-1.map 100 100 17 71 74 81 653
+163 maze-100-1.map 100 100 63 21 85 85 654
+163 maze-100-1.map 100 100 75 70 39 13 653
+164 maze-100-1.map 100 100 55 81 33 73 658
+164 maze-100-1.map 100 100 54 1 85 57 657
+164 maze-100-1.map 100 100 77 75 61 29 658
+164 maze-100-1.map 100 100 86 1 53 72 656
+164 maze-100-1.map 100 100 25 71 41 69 658
+164 maze-100-1.map 100 100 74 87 95 13 659
+164 maze-100-1.map 100 100 11 83 47 66 657
+164 maze-100-1.map 100 100 77 26 71 96 658
+164 maze-100-1.map 100 100 41 94 12 5 658
+164 maze-100-1.map 100 100 67 11 98 59 659
+165 maze-100-1.map 100 100 17 89 62 59 661
+165 maze-100-1.map 100 100 55 20 72 59 660
+165 maze-100-1.map 100 100 99 94 8 61 660
+165 maze-100-1.map 100 100 59 85 25 85 662
+165 maze-100-1.map 100 100 15 23 74 65 663
+165 maze-100-1.map 100 100 86 71 76 23 660
+165 maze-100-1.map 100 100 83 82 20 79 662
+165 maze-100-1.map 100 100 89 16 53 90 662
+165 maze-100-1.map 100 100 79 22 89 69 661
+165 maze-100-1.map 100 100 51 73 1 8 661
+166 maze-100-1.map 100 100 69 75 67 32 665
+166 maze-100-1.map 100 100 27 82 34 67 666
+166 maze-100-1.map 100 100 96 63 23 16 666
+166 maze-100-1.map 100 100 10 45 84 53 666
+166 maze-100-1.map 100 100 95 93 6 35 667
+166 maze-100-1.map 100 100 86 51 21 20 666
+166 maze-100-1.map 100 100 83 65 73 18 667
+166 maze-100-1.map 100 100 56 99 93 43 665
+166 maze-100-1.map 100 100 40 79 41 97 667
+166 maze-100-1.map 100 100 91 78 73 16 664
+167 maze-100-1.map 100 100 79 19 72 97 671
+167 maze-100-1.map 100 100 21 4 31 57 669
+167 maze-100-1.map 100 100 96 41 77 76 670
+167 maze-100-1.map 100 100 81 2 56 81 668
+167 maze-100-1.map 100 100 11 24 64 65 668
+167 maze-100-1.map 100 100 76 87 24 83 670
+167 maze-100-1.map 100 100 13 60 75 48 668
+167 maze-100-1.map 100 100 93 41 35 55 668
+167 maze-100-1.map 100 100 84 39 55 4 668
+167 maze-100-1.map 100 100 63 63 23 90 671
+168 maze-100-1.map 100 100 91 59 27 14 675
+168 maze-100-1.map 100 100 91 41 34 59 675
+168 maze-100-1.map 100 100 39 6 71 94 674
+168 maze-100-1.map 100 100 76 31 81 63 673
+168 maze-100-1.map 100 100 52 5 77 49 675
+168 maze-100-1.map 100 100 63 29 43 74 673
+168 maze-100-1.map 100 100 71 65 7 57 672
+168 maze-100-1.map 100 100 77 76 65 29 673
+168 maze-100-1.map 100 100 92 57 26 11 674
+168 maze-100-1.map 100 100 91 33 7 59 674
+169 maze-100-1.map 100 100 45 85 13 95 678
+169 maze-100-1.map 100 100 97 95 10 17 679
+169 maze-100-1.map 100 100 1 13 62 89 677
+169 maze-100-1.map 100 100 95 34 77 83 677
+169 maze-100-1.map 100 100 47 88 84 49 676
+169 maze-100-1.map 100 100 29 3 77 92 677
+169 maze-100-1.map 100 100 3 53 88 53 679
+169 maze-100-1.map 100 100 83 85 33 14 677
+169 maze-100-1.map 100 100 73 74 94 31 676
+169 maze-100-1.map 100 100 99 5 29 58 679
+170 maze-100-1.map 100 100 97 87 69 8 683
+170 maze-100-1.map 100 100 61 41 98 87 683
+170 maze-100-1.map 100 100 93 46 31 53 681
+170 maze-100-1.map 100 100 81 53 23 15 680
+170 maze-100-1.map 100 100 96 21 37 63 681
+170 maze-100-1.map 100 100 3 86 48 69 682
+170 maze-100-1.map 100 100 60 13 95 72 682
+170 maze-100-1.map 100 100 63 27 43 75 680
+170 maze-100-1.map 100 100 51 54 24 87 680
+170 maze-100-1.map 100 100 91 73 73 27 680
+171 maze-100-1.map 100 100 55 13 67 73 684
+171 maze-100-1.map 100 100 89 95 7 77 684
+171 maze-100-1.map 100 100 75 79 98 53 687
+171 maze-100-1.map 100 100 60 7 88 41 684
+171 maze-100-1.map 100 100 93 15 66 87 687
+171 maze-100-1.map 100 100 88 39 9 61 687
+171 maze-100-1.map 100 100 45 83 46 67 685
+171 maze-100-1.map 100 100 53 82 84 7 686
+171 maze-100-1.map 100 100 50 3 94 93 684
+171 maze-100-1.map 100 100 97 33 72 83 685
+172 maze-100-1.map 100 100 23 87 35 59 688
+172 maze-100-1.map 100 100 92 91 56 15 690
+172 maze-100-1.map 100 100 88 81 57 6 688
+172 maze-100-1.map 100 100 50 89 30 85 690
+172 maze-100-1.map 100 100 99 33 69 90 691
+172 maze-100-1.map 100 100 35 83 47 56 691
+172 maze-100-1.map 100 100 92 67 19 10 688
+172 maze-100-1.map 100 100 55 27 89 36 691
+172 maze-100-1.map 100 100 73 74 91 11 689
+172 maze-100-1.map 100 100 91 26 81 80 690
+173 maze-100-1.map 100 100 59 21 91 49 692
+173 maze-100-1.map 100 100 79 79 97 23 694
+173 maze-100-1.map 100 100 70 41 9 53 693
+173 maze-100-1.map 100 100 37 76 63 89 695
+173 maze-100-1.map 100 100 40 99 39 74 692
+173 maze-100-1.map 100 100 17 76 93 58 694
+173 maze-100-1.map 100 100 69 8 71 61 695
+173 maze-100-1.map 100 100 42 63 9 95 695
+173 maze-100-1.map 100 100 50 71 11 88 694
+173 maze-100-1.map 100 100 78 3 82 51 692
+174 maze-100-1.map 100 100 15 16 86 57 698
+174 maze-100-1.map 100 100 5 23 69 43 696
+174 maze-100-1.map 100 100 93 83 8 69 697
+174 maze-100-1.map 100 100 87 15 63 96 697
+174 maze-100-1.map 100 100 68 69 5 19 699
+174 maze-100-1.map 100 100 63 33 93 73 698
+174 maze-100-1.map 100 100 77 59 10 21 697
+174 maze-100-1.map 100 100 79 77 98 23 697
+174 maze-100-1.map 100 100 23 15 87 58 697
+174 maze-100-1.map 100 100 87 60 23 16 696
+175 maze-100-1.map 100 100 41 75 99 27 702
+175 maze-100-1.map 100 100 71 94 95 20 702
+175 maze-100-1.map 100 100 63 99 10 85 703
+175 maze-100-1.map 100 100 66 67 57 36 700
+175 maze-100-1.map 100 100 61 91 87 9 700
+175 maze-100-1.map 100 100 61 28 84 75 700
+175 maze-100-1.map 100 100 61 2 96 73 702
+175 maze-100-1.map 100 100 17 8 97 77 701
+175 maze-100-1.map 100 100 1 51 69 63 700
+175 maze-100-1.map 100 100 74 79 19 87 703
+176 maze-100-1.map 100 100 36 41 97 27 707
+176 maze-100-1.map 100 100 64 39 93 83 707
+176 maze-100-1.map 100 100 81 84 61 28 706
+176 maze-100-1.map 100 100 69 43 6 19 705
+176 maze-100-1.map 100 100 45 58 83 3 707
+176 maze-100-1.map 100 100 77 53 65 37 704
+176 maze-100-1.map 100 100 7 45 75 45 704
+176 maze-100-1.map 100 100 90 97 55 8 704
+176 maze-100-1.map 100 100 84 69 97 53 707
+176 maze-100-1.map 100 100 81 98 29 81 705
+177 maze-100-1.map 100 100 38 1 81 85 709
+177 maze-100-1.map 100 100 67 11 68 65 709
+177 maze-100-1.map 100 100 76 59 7 80 710
+177 maze-100-1.map 100 100 97 67 82 29 709
+177 maze-100-1.map 100 100 13 11 97 72 711
+177 maze-100-1.map 100 100 79 57 79 36 709
+177 maze-100-1.map 100 100 75 75 3 3 708
+177 maze-100-1.map 100 100 3 46 93 87 709
+177 maze-100-1.map 100 100 84 53 61 40 708
+177 maze-100-1.map 100 100 95 25 37 41 710
+178 maze-100-1.map 100 100 96 95 17 79 715
+178 maze-100-1.map 100 100 23 3 71 97 714
+178 maze-100-1.map 100 100 35 5 98 91 715
+178 maze-100-1.map 100 100 31 81 84 93 715
+178 maze-100-1.map 100 100 99 91 19 79 712
+178 maze-100-1.map 100 100 11 81 35 55 714
+178 maze-100-1.map 100 100 45 97 45 81 712
+178 maze-100-1.map 100 100 28 19 91 66 712
+178 maze-100-1.map 100 100 90 37 64 9 714
+178 maze-100-1.map 100 100 85 91 97 43 712
+179 maze-100-1.map 100 100 71 96 99 27 719
+179 maze-100-1.map 100 100 88 39 24 5 718
+179 maze-100-1.map 100 100 68 87 97 25 717
+179 maze-100-1.map 100 100 93 15 85 88 717
+179 maze-100-1.map 100 100 60 7 73 49 717
+179 maze-100-1.map 100 100 82 83 93 11 717
+179 maze-100-1.map 100 100 93 67 9 73 718
+179 maze-100-1.map 100 100 96 1 27 41 719
+179 maze-100-1.map 100 100 23 97 58 83 719
+179 maze-100-1.map 100 100 39 69 6 1 719
+180 maze-100-1.map 100 100 75 4 73 67 723
+180 maze-100-1.map 100 100 19 77 95 90 723
+180 maze-100-1.map 100 100 16 11 89 55 721
+180 maze-100-1.map 100 100 13 2 37 67 721
+180 maze-100-1.map 100 100 91 81 57 27 720
+180 maze-100-1.map 100 100 61 90 8 93 722
+180 maze-100-1.map 100 100 87 61 71 1 720
+180 maze-100-1.map 100 100 98 85 78 11 722
+180 maze-100-1.map 100 100 97 65 91 22 723
+180 maze-100-1.map 100 100 88 21 96 95 720
+181 maze-100-1.map 100 100 74 83 31 83 727
+181 maze-100-1.map 100 100 83 76 93 48 726
+181 maze-100-1.map 100 100 20 91 37 57 725
+181 maze-100-1.map 100 100 99 7 79 85 726
+181 maze-100-1.map 100 100 66 99 89 3 725
+181 maze-100-1.map 100 100 97 10 93 75 727
+181 maze-100-1.map 100 100 72 39 87 37 725
+181 maze-100-1.map 100 100 97 21 80 63 725
+181 maze-100-1.map 100 100 95 73 27 23 726
+181 maze-100-1.map 100 100 95 44 93 76 726
+182 maze-100-1.map 100 100 71 7 93 91 730
+182 maze-100-1.map 100 100 39 69 2 17 731
+182 maze-100-1.map 100 100 81 98 5 1 729
+182 maze-100-1.map 100 100 87 3 34 57 729
+182 maze-100-1.map 100 100 68 93 99 50 730
+182 maze-100-1.map 100 100 15 17 91 87 730
+182 maze-100-1.map 100 100 48 93 11 87 729
+182 maze-100-1.map 100 100 21 13 78 47 729
+182 maze-100-1.map 100 100 67 45 56 31 731
+182 maze-100-1.map 100 100 83 72 1 15 729
+183 maze-100-1.map 100 100 32 11 97 67 733
+183 maze-100-1.map 100 100 77 75 3 13 732
+183 maze-100-1.map 100 100 85 71 92 3 735
+183 maze-100-1.map 100 100 83 96 1 9 735
+183 maze-100-1.map 100 100 67 75 59 27 732
+183 maze-100-1.map 100 100 62 23 77 43 735
+183 maze-100-1.map 100 100 43 80 56 71 732
+183 maze-100-1.map 100 100 16 19 71 69 733
+183 maze-100-1.map 100 100 22 7 91 34 732
+183 maze-100-1.map 100 100 1 24 41 67 733
+184 maze-100-1.map 100 100 63 88 18 93 736
+184 maze-100-1.map 100 100 91 79 13 5 736
+184 maze-100-1.map 100 100 36 5 85 61 739
+184 maze-100-1.map 100 100 85 45 81 70 737
+184 maze-100-1.map 100 100 60 13 92 93 738
+184 maze-100-1.map 100 100 59 17 67 75 738
+184 maze-100-1.map 100 100 17 91 44 99 739
+184 maze-100-1.map 100 100 87 6 29 54 736
+184 maze-100-1.map 100 100 72 67 25 16 736
+184 maze-100-1.map 100 100 49 80 34 99 738
+185 maze-100-1.map 100 100 78 25 78 59 742
+185 maze-100-1.map 100 100 27 23 97 89 740
+185 maze-100-1.map 100 100 90 99 95 35 743
+185 maze-100-1.map 100 100 28 45 16 87 742
+185 maze-100-1.map 100 100 15 97 35 59 742
+185 maze-100-1.map 100 100 71 15 69 49 740
+185 maze-100-1.map 100 100 88 43 85 79 741
+185 maze-100-1.map 100 100 45 91 22 95 741
+185 maze-100-1.map 100 100 19 77 99 81 740
+185 maze-100-1.map 100 100 66 9 73 43 741
+186 maze-100-1.map 100 100 37 43 35 79 746
+186 maze-100-1.map 100 100 23 16 75 43 747
+186 maze-100-1.map 100 100 87 81 25 12 745
+186 maze-100-1.map 100 100 31 6 77 44 746
+186 maze-100-1.map 100 100 18 83 87 66 744
+186 maze-100-1.map 100 100 28 7 64 71 744
+186 maze-100-1.map 100 100 35 44 35 86 746
+186 maze-100-1.map 100 100 3 76 68 69 744
+186 maze-100-1.map 100 100 34 67 39 77 745
+186 maze-100-1.map 100 100 36 71 34 51 746
+187 maze-100-1.map 100 100 80 39 21 77 751
+187 maze-100-1.map 100 100 75 44 71 7 749
+187 maze-100-1.map 100 100 39 9 83 44 749
+187 maze-100-1.map 100 100 29 59 14 99 749
+187 maze-100-1.map 100 100 87 35 21 79 750
+187 maze-100-1.map 100 100 75 63 79 13 750
+187 maze-100-1.map 100 100 93 81 74 15 749
+187 maze-100-1.map 100 100 88 99 98 39 748
+187 maze-100-1.map 100 100 96 67 27 77 751
+187 maze-100-1.map 100 100 25 15 65 64 751
+188 maze-100-1.map 100 100 75 49 13 7 752
+188 maze-100-1.map 100 100 69 74 9 89 755
+188 maze-100-1.map 100 100 78 97 15 83 753
+188 maze-100-1.map 100 100 86 61 75 23 755
+188 maze-100-1.map 100 100 80 55 30 17 752
+188 maze-100-1.map 100 100 9 83 69 91 752
+188 maze-100-1.map 100 100 4 13 35 62 752
+188 maze-100-1.map 100 100 72 33 99 66 754
+188 maze-100-1.map 100 100 14 1 29 46 754
+188 maze-100-1.map 100 100 44 73 9 86 752
+189 maze-100-1.map 100 100 73 46 23 7 757
+189 maze-100-1.map 100 100 8 73 76 63 756
+189 maze-100-1.map 100 100 81 71 41 82 757
+189 maze-100-1.map 100 100 35 55 1 99 758
+189 maze-100-1.map 100 100 99 15 82 47 759
+189 maze-100-1.map 100 100 93 78 27 87 757
+189 maze-100-1.map 100 100 1 99 69 84 759
+189 maze-100-1.map 100 100 80 17 71 60 758
+189 maze-100-1.map 100 100 41 6 98 87 756
+189 maze-100-1.map 100 100 29 45 15 83 756
+190 maze-100-1.map 100 100 99 96 61 27 763
+190 maze-100-1.map 100 100 7 13 64 69 761
+190 maze-100-1.map 100 100 99 74 87 31 761
+190 maze-100-1.map 100 100 94 65 64 27 760
+190 maze-100-1.map 100 100 93 7 83 84 763
+190 maze-100-1.map 100 100 29 23 75 63 762
+190 maze-100-1.map 100 100 91 36 7 12 760
+190 maze-100-1.map 100 100 95 95 95 19 760
+190 maze-100-1.map 100 100 91 96 10 79 760
+190 maze-100-1.map 100 100 13 5 89 94 761
+191 maze-100-1.map 100 100 53 97 4 99 765
+191 maze-100-1.map 100 100 28 41 10 91 764
+191 maze-100-1.map 100 100 35 69 5 89 766
+191 maze-100-1.map 100 100 28 77 93 71 765
+191 maze-100-1.map 100 100 87 74 87 13 765
+191 maze-100-1.map 100 100 43 9 95 79 766
+191 maze-100-1.map 100 100 3 14 79 71 765
+191 maze-100-1.map 100 100 97 89 73 32 767
+191 maze-100-1.map 100 100 75 70 89 18 764
+191 maze-100-1.map 100 100 41 83 94 77 767
+192 maze-100-1.map 100 100 80 79 39 84 770
+192 maze-100-1.map 100 100 88 3 79 81 771
+192 maze-100-1.map 100 100 13 85 81 69 768
+192 maze-100-1.map 100 100 88 73 4 13 770
+192 maze-100-1.map 100 100 36 15 85 35 771
+192 maze-100-1.map 100 100 21 97 73 91 770
+192 maze-100-1.map 100 100 61 95 5 94 769
+192 maze-100-1.map 100 100 86 41 43 6 770
+192 maze-100-1.map 100 100 87 17 72 97 769
+192 maze-100-1.map 100 100 68 33 84 41 768
+193 maze-100-1.map 100 100 78 67 37 78 774
+193 maze-100-1.map 100 100 34 13 91 35 773
+193 maze-100-1.map 100 100 85 93 11 93 774
+193 maze-100-1.map 100 100 25 21 65 64 773
+193 maze-100-1.map 100 100 63 67 15 73 774
+193 maze-100-1.map 100 100 97 23 92 83 773
+193 maze-100-1.map 100 100 3 99 28 55 775
+193 maze-100-1.map 100 100 35 14 87 81 773
+193 maze-100-1.map 100 100 85 15 67 73 772
+193 maze-100-1.map 100 100 89 19 86 91 773
+194 maze-100-1.map 100 100 43 57 23 97 776
+194 maze-100-1.map 100 100 43 6 96 79 776
+194 maze-100-1.map 100 100 83 41 95 36 779
+194 maze-100-1.map 100 100 46 95 33 99 779
+194 maze-100-1.map 100 100 15 99 79 99 776
+194 maze-100-1.map 100 100 7 99 73 70 779
+194 maze-100-1.map 100 100 18 5 94 95 778
+194 maze-100-1.map 100 100 99 75 37 1 776
+194 maze-100-1.map 100 100 71 97 38 73 779
+194 maze-100-1.map 100 100 8 93 80 93 776
+195 maze-100-1.map 100 100 35 75 80 85 783
+195 maze-100-1.map 100 100 95 11 99 70 781
+195 maze-100-1.map 100 100 91 62 39 84 780
+195 maze-100-1.map 100 100 73 43 3 7 782
+195 maze-100-1.map 100 100 39 71 2 89 783
+195 maze-100-1.map 100 100 3 85 77 75 780
+195 maze-100-1.map 100 100 80 67 5 26 780
+195 maze-100-1.map 100 100 75 59 22 83 783
+195 maze-100-1.map 100 100 69 33 67 65 782
+195 maze-100-1.map 100 100 92 57 3 1 781
+196 maze-100-1.map 100 100 73 29 73 64 785
+196 maze-100-1.map 100 100 64 83 27 97 785
+196 maze-100-1.map 100 100 96 55 31 93 785
+196 maze-100-1.map 100 100 27 83 93 71 786
+196 maze-100-1.map 100 100 95 17 87 60 787
+196 maze-100-1.map 100 100 25 98 73 99 785
+196 maze-100-1.map 100 100 93 14 77 55 787
+196 maze-100-1.map 100 100 13 73 63 75 784
+196 maze-100-1.map 100 100 75 62 69 30 786
+196 maze-100-1.map 100 100 19 83 89 88 787
+197 maze-100-1.map 100 100 21 87 87 99 790
+197 maze-100-1.map 100 100 99 38 85 42 790
+197 maze-100-1.map 100 100 39 1 77 56 791
+197 maze-100-1.map 100 100 98 93 92 43 788
+197 maze-100-1.map 100 100 91 31 67 67 788
+197 maze-100-1.map 100 100 95 63 93 38 791
+197 maze-100-1.map 100 100 89 43 89 51 788
+197 maze-100-1.map 100 100 93 98 92 1 788
+197 maze-100-1.map 100 100 97 82 99 37 789
+197 maze-100-1.map 100 100 34 97 47 87 791
+198 maze-100-1.map 100 100 91 62 5 17 793
+198 maze-100-1.map 100 100 88 35 63 33 795
+198 maze-100-1.map 100 100 89 9 94 59 795
+198 maze-100-1.map 100 100 37 97 35 57 794
+198 maze-100-1.map 100 100 99 41 77 56 795
+198 maze-100-1.map 100 100 85 69 13 93 792
+198 maze-100-1.map 100 100 99 86 30 79 792
+198 maze-100-1.map 100 100 85 72 45 76 792
+198 maze-100-1.map 100 100 89 88 83 11 795
+198 maze-100-1.map 100 100 97 58 29 85 793
+199 maze-100-1.map 100 100 17 97 71 95 796
+199 maze-100-1.map 100 100 85 42 24 1 798
+199 maze-100-1.map 100 100 84 41 99 32 798
+199 maze-100-1.map 100 100 98 41 82 61 798
+199 maze-100-1.map 100 100 86 39 25 83 799
+199 maze-100-1.map 100 100 99 15 89 85 796
+199 maze-100-1.map 100 100 69 40 32 21 796
+199 maze-100-1.map 100 100 76 59 96 47 796
+199 maze-100-1.map 100 100 32 71 94 77 796
+199 maze-100-1.map 100 100 26 87 91 52 798
+200 maze-100-1.map 100 100 87 89 9 81 802
+200 maze-100-1.map 100 100 1 94 78 93 800
+200 maze-100-1.map 100 100 87 60 20 1 802
+200 maze-100-1.map 100 100 20 73 73 49 801
+200 maze-100-1.map 100 100 29 90 97 99 803
+200 maze-100-1.map 100 100 22 75 93 90 802
+200 maze-100-1.map 100 100 3 87 27 42 803
+200 maze-100-1.map 100 100 86 45 81 51 801
+200 maze-100-1.map 100 100 93 6 93 97 801
+200 maze-100-1.map 100 100 31 99 37 69 800
+201 maze-100-1.map 100 100 88 95 81 9 807
+201 maze-100-1.map 100 100 65 92 1 98 806
+201 maze-100-1.map 100 100 45 83 79 69 804
+201 maze-100-1.map 100 100 90 85 36 3 804
+201 maze-100-1.map 100 100 85 99 17 83 804
+201 maze-100-1.map 100 100 73 72 22 89 806
+201 maze-100-1.map 100 100 95 11 89 57 804
+201 maze-100-1.map 100 100 87 69 1 89 806
+201 maze-100-1.map 100 100 98 29 86 41 806
+201 maze-100-1.map 100 100 99 79 31 79 804
+202 maze-100-1.map 100 100 41 7 69 46 809
+202 maze-100-1.map 100 100 98 69 30 91 810
+202 maze-100-1.map 100 100 29 83 95 64 811
+202 maze-100-1.map 100 100 78 71 13 93 811
+202 maze-100-1.map 100 100 81 42 92 41 810
+202 maze-100-1.map 100 100 85 27 71 44 809
+202 maze-100-1.map 100 100 70 97 4 87 810
+202 maze-100-1.map 100 100 27 77 68 71 811
+202 maze-100-1.map 100 100 65 29 89 59 810
+202 maze-100-1.map 100 100 27 98 77 92 810
+203 maze-100-1.map 100 100 93 16 79 42 812
+203 maze-100-1.map 100 100 85 38 99 47 815
+203 maze-100-1.map 100 100 32 89 86 41 814
+203 maze-100-1.map 100 100 92 67 94 5 812
+203 maze-100-1.map 100 100 99 92 16 87 814
+203 maze-100-1.map 100 100 79 57 26 89 813
+203 maze-100-1.map 100 100 11 99 89 87 814
+203 maze-100-1.map 100 100 79 59 34 91 815
+203 maze-100-1.map 100 100 97 67 3 9 812
+203 maze-100-1.map 100 100 99 81 97 51 812
+204 maze-100-1.map 100 100 97 5 71 67 816
+204 maze-100-1.map 100 100 79 41 99 38 819
+204 maze-100-1.map 100 100 92 47 83 39 819
+204 maze-100-1.map 100 100 33 81 68 65 817
+204 maze-100-1.map 100 100 27 97 43 73 816
+204 maze-100-1.map 100 100 39 3 69 49 816
+204 maze-100-1.map 100 100 20 85 93 63 817
+204 maze-100-1.map 100 100 27 97 33 44 817
+204 maze-100-1.map 100 100 87 37 20 5 819
+204 maze-100-1.map 100 100 68 71 95 35 817
+205 maze-100-1.map 100 100 3 10 95 99 823
+205 maze-100-1.map 100 100 91 95 94 15 823
+205 maze-100-1.map 100 100 26 99 66 91 822
+205 maze-100-1.map 100 100 80 85 19 93 821
+205 maze-100-1.map 100 100 31 99 33 45 820
+205 maze-100-1.map 100 100 91 95 93 14 821
+205 maze-100-1.map 100 100 74 43 73 31 821
+205 maze-100-1.map 100 100 15 85 79 51 822
+205 maze-100-1.map 100 100 31 92 87 58 822
+205 maze-100-1.map 100 100 3 82 77 68 822
+206 maze-100-1.map 100 100 91 88 67 25 825
+206 maze-100-1.map 100 100 71 41 71 31 826
+206 maze-100-1.map 100 100 62 27 91 97 825
+206 maze-100-1.map 100 100 87 84 97 29 825
+206 maze-100-1.map 100 100 90 37 94 49 824
+206 maze-100-1.map 100 100 94 55 11 83 825
+206 maze-100-1.map 100 100 20 1 65 71 827
+206 maze-100-1.map 100 100 9 85 99 63 824
+206 maze-100-1.map 100 100 83 53 93 51 824
+206 maze-100-1.map 100 100 71 62 32 91 824
+207 maze-100-1.map 100 100 63 27 69 45 828
+207 maze-100-1.map 100 100 31 83 99 87 828
+207 maze-100-1.map 100 100 89 54 86 45 830
+207 maze-100-1.map 100 100 98 15 68 41 828
+207 maze-100-1.map 100 100 5 94 83 83 831
+207 maze-100-1.map 100 100 27 44 31 98 828
+207 maze-100-1.map 100 100 76 49 27 1 829
+207 maze-100-1.map 100 100 15 87 99 88 829
+207 maze-100-1.map 100 100 88 55 85 47 831
+207 maze-100-1.map 100 100 99 88 15 86 830
+208 maze-100-1.map 100 100 3 84 94 77 832
+208 maze-100-1.map 100 100 97 27 76 61 833
+208 maze-100-1.map 100 100 33 75 99 62 833
+208 maze-100-1.map 100 100 79 53 84 49 835
+208 maze-100-1.map 100 100 70 43 33 1 833
+208 maze-100-1.map 100 100 67 97 34 95 833
+208 maze-100-1.map 100 100 91 35 33 86 833
+208 maze-100-1.map 100 100 75 61 91 43 834
+208 maze-100-1.map 100 100 95 66 89 19 833
+208 maze-100-1.map 100 100 79 51 14 83 833
+209 maze-100-1.map 100 100 77 52 21 87 839
+209 maze-100-1.map 100 100 97 93 87 9 838
+209 maze-100-1.map 100 100 97 3 79 44 837
+209 maze-100-1.map 100 100 13 84 97 71 837
+209 maze-100-1.map 100 100 77 51 1 6 839
+209 maze-100-1.map 100 100 41 79 96 85 839
+209 maze-100-1.map 100 100 35 95 78 71 839
+209 maze-100-1.map 100 100 66 77 22 3 838
+209 maze-100-1.map 100 100 85 81 1 81 836
+209 maze-100-1.map 100 100 87 9 89 51 836
+210 maze-100-1.map 100 100 88 99 45 77 841
+210 maze-100-1.map 100 100 31 73 95 66 841
+210 maze-100-1.map 100 100 95 87 37 83 842
+210 maze-100-1.map 100 100 99 49 79 47 842
+210 maze-100-1.map 100 100 97 74 37 76 842
+210 maze-100-1.map 100 100 21 3 69 48 843
+210 maze-100-1.map 100 100 95 88 37 77 843
+210 maze-100-1.map 100 100 95 45 68 69 843
+210 maze-100-1.map 100 100 93 76 25 93 841
+210 maze-100-1.map 100 100 65 75 99 3 842
+211 maze-100-1.map 100 100 91 36 35 91 847
+211 maze-100-1.map 100 100 1 2 90 81 846
+211 maze-100-1.map 100 100 16 5 63 77 847
+211 maze-100-1.map 100 100 87 36 87 47 847
+211 maze-100-1.map 100 100 3 89 89 95 844
+211 maze-100-1.map 100 100 99 63 82 1 845
+211 maze-100-1.map 100 100 81 59 17 3 844
+211 maze-100-1.map 100 100 83 41 85 12 845
+211 maze-100-1.map 100 100 91 59 3 92 845
+211 maze-100-1.map 100 100 21 96 89 94 844
+212 maze-100-1.map 100 100 67 73 91 41 848
+212 maze-100-1.map 100 100 88 5 95 73 849
+212 maze-100-1.map 100 100 99 77 5 25 850
+212 maze-100-1.map 100 100 11 88 80 63 850
+212 maze-100-1.map 100 100 9 3 82 39 851
+212 maze-100-1.map 100 100 92 47 69 45 851
+212 maze-100-1.map 100 100 93 63 8 99 849
+212 maze-100-1.map 100 100 90 83 26 85 848
+212 maze-100-1.map 100 100 75 57 39 81 848
+212 maze-100-1.map 100 100 68 77 91 41 849
+213 maze-100-1.map 100 100 94 1 75 48 852
+213 maze-100-1.map 100 100 74 59 89 13 853
+213 maze-100-1.map 100 100 67 67 8 3 853
+213 maze-100-1.map 100 100 83 7 96 75 855
+213 maze-100-1.map 100 100 77 45 27 85 854
+213 maze-100-1.map 100 100 9 87 97 85 854
+213 maze-100-1.map 100 100 29 88 63 77 855
+213 maze-100-1.map 100 100 91 57 3 83 854
+213 maze-100-1.map 100 100 99 55 79 49 854
+213 maze-100-1.map 100 100 97 26 71 47 855
+214 maze-100-1.map 100 100 9 6 91 97 859
+214 maze-100-1.map 100 100 82 67 37 97 859
+214 maze-100-1.map 100 100 82 57 37 85 859
+214 maze-100-1.map 100 100 18 87 65 65 857
+214 maze-100-1.map 100 100 94 3 78 47 856
+214 maze-100-1.map 100 100 17 85 73 63 858
+214 maze-100-1.map 100 100 80 55 35 77 857
+214 maze-100-1.map 100 100 89 11 92 83 857
+214 maze-100-1.map 100 100 86 61 11 85 857
+214 maze-100-1.map 100 100 67 77 90 1 857
+215 maze-100-1.map 100 100 19 84 84 53 860
+215 maze-100-1.map 100 100 79 44 31 84 862
+215 maze-100-1.map 100 100 10 99 79 55 861
+215 maze-100-1.map 100 100 87 41 11 82 863
+215 maze-100-1.map 100 100 99 63 4 89 861
+215 maze-100-1.map 100 100 97 79 89 15 860
+215 maze-100-1.map 100 100 35 82 89 54 862
+215 maze-100-1.map 100 100 9 87 85 56 863
+215 maze-100-1.map 100 100 35 89 67 77 860
+215 maze-100-1.map 100 100 32 71 81 41 863
+216 maze-100-1.map 100 100 81 45 1 12 867
+216 maze-100-1.map 100 100 97 84 32 71 864
+216 maze-100-1.map 100 100 19 3 75 67 864
+216 maze-100-1.map 100 100 80 39 1 24 866
+216 maze-100-1.map 100 100 97 83 31 75 866
+216 maze-100-1.map 100 100 81 6 95 98 866
+216 maze-100-1.map 100 100 75 61 88 11 865
+216 maze-100-1.map 100 100 69 41 33 86 865
+216 maze-100-1.map 100 100 86 53 14 83 864
+216 maze-100-1.map 100 100 83 57 1 17 866
+217 maze-100-1.map 100 100 81 45 1 15 870
+217 maze-100-1.map 100 100 77 61 1 20 871
+217 maze-100-1.map 100 100 91 93 2 9 871
+217 maze-100-1.map 100 100 74 65 1 27 869
+217 maze-100-1.map 100 100 28 91 70 43 868
+217 maze-100-1.map 100 100 69 47 89 49 870
+217 maze-100-1.map 100 100 86 9 78 53 870
+217 maze-100-1.map 100 100 67 71 16 87 871
+217 maze-100-1.map 100 100 43 79 95 72 869
+217 maze-100-1.map 100 100 95 53 6 87 869
+218 maze-100-1.map 100 100 86 7 79 53 875
+218 maze-100-1.map 100 100 96 79 31 74 874
+218 maze-100-1.map 100 100 76 47 1 17 875
+218 maze-100-1.map 100 100 3 13 89 35 872
+218 maze-100-1.map 100 100 7 95 99 70 873
+218 maze-100-1.map 100 100 71 66 31 73 873
+218 maze-100-1.map 100 100 65 73 3 17 874
+218 maze-100-1.map 100 100 13 2 93 87 873
+218 maze-100-1.map 100 100 93 63 19 91 874
+218 maze-100-1.map 100 100 14 83 65 65 873
+219 maze-100-1.map 100 100 89 37 84 9 879
+219 maze-100-1.map 100 100 9 95 97 84 879
+219 maze-100-1.map 100 100 79 55 19 99 876
+219 maze-100-1.map 100 100 87 84 37 77 877
+219 maze-100-1.map 100 100 91 17 77 42 879
+219 maze-100-1.map 100 100 88 53 33 75 879
+219 maze-100-1.map 100 100 70 41 85 46 878
+219 maze-100-1.map 100 100 21 85 63 75 876
+219 maze-100-1.map 100 100 36 75 87 83 879
+219 maze-100-1.map 100 100 69 67 89 5 878
+220 maze-100-1.map 100 100 87 51 23 89 882
+220 maze-100-1.map 100 100 67 76 1 22 882
+220 maze-100-1.map 100 100 3 90 95 75 883
+220 maze-100-1.map 100 100 17 89 91 51 880
+220 maze-100-1.map 100 100 28 73 93 82 882
+220 maze-100-1.map 100 100 77 44 36 75 882
+220 maze-100-1.map 100 100 11 81 77 40 881
+220 maze-100-1.map 100 100 91 9 95 93 880
+220 maze-100-1.map 100 100 33 73 91 82 881
+220 maze-100-1.map 100 100 99 80 9 97 883
+221 maze-100-1.map 100 100 87 99 25 98 887
+221 maze-100-1.map 100 100 72 61 9 94 886
+221 maze-100-1.map 100 100 68 63 10 85 884
+221 maze-100-1.map 100 100 3 82 93 67 887
+221 maze-100-1.map 100 100 84 51 1 99 885
+221 maze-100-1.map 100 100 23 89 95 70 885
+221 maze-100-1.map 100 100 25 91 96 67 887
+221 maze-100-1.map 100 100 69 65 81 3 886
+221 maze-100-1.map 100 100 79 49 85 13 886
+221 maze-100-1.map 100 100 71 45 11 3 886
+222 maze-100-1.map 100 100 67 66 14 99 890
+222 maze-100-1.map 100 100 45 80 87 39 891
+222 maze-100-1.map 100 100 75 41 31 86 889
+222 maze-100-1.map 100 100 11 96 91 37 891
+222 maze-100-1.map 100 100 71 44 40 79 890
+222 maze-100-1.map 100 100 35 71 77 45 888
+222 maze-100-1.map 100 100 39 73 90 81 889
+222 maze-100-1.map 100 100 41 81 73 43 890
+222 maze-100-1.map 100 100 77 43 34 77 891
+222 maze-100-1.map 100 100 15 95 75 55 888
+223 maze-100-1.map 100 100 86 39 17 97 893
+223 maze-100-1.map 100 100 25 95 95 65 892
+223 maze-100-1.map 100 100 11 99 82 57 895
+223 maze-100-1.map 100 100 77 42 89 3 895
+223 maze-100-1.map 100 100 85 35 39 77 892
+223 maze-100-1.map 100 100 13 89 82 51 893
+223 maze-100-1.map 100 100 3 82 99 77 895
+223 maze-100-1.map 100 100 81 38 43 77 893
+223 maze-100-1.map 100 100 91 53 27 97 892
+223 maze-100-1.map 100 100 71 62 19 97 893
+224 maze-100-1.map 100 100 88 99 35 97 899
+224 maze-100-1.map 100 100 9 89 67 71 896
+224 maze-100-1.map 100 100 87 41 17 95 896
+224 maze-100-1.map 100 100 74 57 21 97 897
+224 maze-100-1.map 100 100 67 67 16 97 899
+224 maze-100-1.map 100 100 91 37 15 99 898
+224 maze-100-1.map 100 100 77 47 29 74 899
+224 maze-100-1.map 100 100 28 99 89 51 899
+224 maze-100-1.map 100 100 74 63 45 77 899
+224 maze-100-1.map 100 100 7 98 75 63 897
+225 maze-100-1.map 100 100 73 45 10 85 903
+225 maze-100-1.map 100 100 22 95 77 55 901
+225 maze-100-1.map 100 100 92 83 43 82 902
+225 maze-100-1.map 100 100 90 83 8 95 900
+225 maze-100-1.map 100 100 1 94 95 97 901
+225 maze-100-1.map 100 100 39 76 64 71 900
+225 maze-100-1.map 100 100 65 64 7 97 903
+225 maze-100-1.map 100 100 37 73 67 72 903
+225 maze-100-1.map 100 100 27 93 92 71 903
+225 maze-100-1.map 100 100 7 99 81 57 900
+226 maze-100-1.map 100 100 69 39 1 20 905
+226 maze-100-1.map 100 100 3 25 91 97 904
+226 maze-100-1.map 100 100 19 99 95 83 904
+226 maze-100-1.map 100 100 77 55 3 93 904
+226 maze-100-1.map 100 100 80 51 31 95 907
+226 maze-100-1.map 100 100 77 54 19 93 905
+226 maze-100-1.map 100 100 13 97 93 88 907
+226 maze-100-1.map 100 100 83 1 79 42 907
+226 maze-100-1.map 100 100 99 69 13 91 904
+226 maze-100-1.map 100 100 11 97 67 77 904
+227 maze-100-1.map 100 100 74 65 23 95 911
+227 maze-100-1.map 100 100 69 77 13 98 911
+227 maze-100-1.map 100 100 35 99 99 61 910
+227 maze-100-1.map 100 100 35 95 95 72 909
+227 maze-100-1.map 100 100 21 93 85 38 911
+227 maze-100-1.map 100 100 93 67 29 99 908
+227 maze-100-1.map 100 100 82 61 3 97 909
+227 maze-100-1.map 100 100 77 42 19 99 909
+227 maze-100-1.map 100 100 7 91 63 69 910
+227 maze-100-1.map 100 100 93 68 26 99 908
+228 maze-100-1.map 100 100 98 79 23 91 913
+228 maze-100-1.map 100 100 67 73 44 77 913
+228 maze-100-1.map 100 100 2 85 89 56 914
+228 maze-100-1.map 100 100 67 77 86 1 915
+228 maze-100-1.map 100 100 99 98 23 98 912
+228 maze-100-1.map 100 100 90 97 11 99 915
+228 maze-100-1.map 100 100 31 98 79 59 915
+228 maze-100-1.map 100 100 99 88 29 93 913
+228 maze-100-1.map 100 100 21 89 79 53 914
+228 maze-100-1.map 100 100 77 54 22 89 912
+229 maze-100-1.map 100 100 9 99 68 69 919
+229 maze-100-1.map 100 100 98 71 22 99 916
+229 maze-100-1.map 100 100 65 74 19 98 918
+229 maze-100-1.map 100 100 3 84 79 39 919
+229 maze-100-1.map 100 100 20 93 83 54 918
+229 maze-100-1.map 100 100 17 91 75 57 916
+229 maze-100-1.map 100 100 8 93 69 60 918
+229 maze-100-1.map 100 100 13 90 89 40 918
+229 maze-100-1.map 100 100 5 89 91 39 916
+229 maze-100-1.map 100 100 28 97 83 41 919
+230 maze-100-1.map 100 100 4 89 78 47 922
+230 maze-100-1.map 100 100 75 57 29 97 922
+230 maze-100-1.map 100 100 18 99 75 48 920
+230 maze-100-1.map 100 100 17 97 93 93 920
+230 maze-100-1.map 100 100 29 96 85 57 923
+230 maze-100-1.map 100 100 73 63 6 87 921
+230 maze-100-1.map 100 100 74 57 29 93 921
+230 maze-100-1.map 100 100 92 67 33 97 921
+230 maze-100-1.map 100 100 64 75 5 89 923
+230 maze-100-1.map 100 100 81 57 19 93 922
+231 maze-100-1.map 100 100 75 65 1 92 927
+231 maze-100-1.map 100 100 83 36 7 87 925
+231 maze-100-1.map 100 100 85 43 27 97 924
+231 maze-100-1.map 100 100 18 95 69 59 927
+231 maze-100-1.map 100 100 87 83 18 89 927
+231 maze-100-1.map 100 100 81 43 21 99 924
+231 maze-100-1.map 100 100 25 97 97 83 926
+231 maze-100-1.map 100 100 5 97 71 44 927
+231 maze-100-1.map 100 100 93 69 33 97 924
+231 maze-100-1.map 100 100 1 83 73 63 924
+232 maze-100-1.map 100 100 1 93 91 82 929
+232 maze-100-1.map 100 100 79 39 17 91 930
+232 maze-100-1.map 100 100 35 95 71 61 930
+232 maze-100-1.map 100 100 79 42 14 93 928
+232 maze-100-1.map 100 100 13 96 75 45 931
+232 maze-100-1.map 100 100 89 59 27 94 929
+232 maze-100-1.map 100 100 23 89 65 64 931
+232 maze-100-1.map 100 100 91 37 23 90 929
+232 maze-100-1.map 100 100 68 77 20 95 928
+232 maze-100-1.map 100 100 69 41 39 77 930
+233 maze-100-1.map 100 100 25 95 75 65 932
+233 maze-100-1.map 100 100 89 35 13 91 932
+233 maze-100-1.map 100 100 83 53 26 95 935
+233 maze-100-1.map 100 100 93 93 3 91 932
+233 maze-100-1.map 100 100 67 63 5 99 934
+233 maze-100-1.map 100 100 79 49 22 95 933
+233 maze-100-1.map 100 100 2 89 91 93 933
+233 maze-100-1.map 100 100 1 93 82 57 935
+233 maze-100-1.map 100 100 15 91 88 81 933
+233 maze-100-1.map 100 100 75 41 44 77 933
+234 maze-100-1.map 100 100 7 87 67 73 938
+234 maze-100-1.map 100 100 35 97 73 58 937
+234 maze-100-1.map 100 100 29 96 83 35 939
+234 maze-100-1.map 100 100 36 93 84 61 936
+234 maze-100-1.map 100 100 67 69 6 89 937
+234 maze-100-1.map 100 100 73 47 7 90 939
+234 maze-100-1.map 100 100 90 81 29 97 939
+234 maze-100-1.map 100 100 23 89 69 63 936
+234 maze-100-1.map 100 100 77 49 4 87 937
+234 maze-100-1.map 100 100 72 61 37 96 938
+235 maze-100-1.map 100 100 89 59 23 99 942
+235 maze-100-1.map 100 100 79 42 25 92 940
+235 maze-100-1.map 100 100 94 83 25 98 942
+235 maze-100-1.map 100 100 19 89 77 49 942
+235 maze-100-1.map 100 100 67 72 2 83 940
+235 maze-100-1.map 100 100 86 35 26 99 942
+235 maze-100-1.map 100 100 11 88 91 33 943
+235 maze-100-1.map 100 100 91 37 30 97 943
+235 maze-100-1.map 100 100 79 46 26 93 940
+235 maze-100-1.map 100 100 3 87 69 47 942
+236 maze-100-1.map 100 100 1 94 67 77 945
+236 maze-100-1.map 100 100 94 93 15 89 947
+236 maze-100-1.map 100 100 19 98 70 41 946
+236 maze-100-1.map 100 100 16 89 76 49 944
+236 maze-100-1.map 100 100 78 47 11 88 946
+236 maze-100-1.map 100 100 67 42 5 89 945
+236 maze-100-1.map 100 100 69 69 2 85 947
+236 maze-100-1.map 100 100 31 98 63 65 945
+236 maze-100-1.map 100 100 90 37 26 99 946
+236 maze-100-1.map 100 100 34 97 77 55 945
+237 maze-100-1.map 100 100 15 89 69 71 948
+237 maze-100-1.map 100 100 95 93 15 89 948
+237 maze-100-1.map 100 100 13 88 68 77 948
+237 maze-100-1.map 100 100 34 97 89 55 949
+237 maze-100-1.map 100 100 93 92 26 93 948
+237 maze-100-1.map 100 100 81 45 31 98 951
+237 maze-100-1.map 100 100 33 99 78 53 951
+237 maze-100-1.map 100 100 19 89 90 97 949
+237 maze-100-1.map 100 100 21 93 68 43 951
+237 maze-100-1.map 100 100 71 49 1 95 948
+238 maze-100-1.map 100 100 72 45 3 81 953
+238 maze-100-1.map 100 100 76 47 27 97 953
+238 maze-100-1.map 100 100 68 77 29 97 955
+238 maze-100-1.map 100 100 35 93 63 69 952
+238 maze-100-1.map 100 100 23 89 70 43 955
+238 maze-100-1.map 100 100 69 43 5 93 954
+238 maze-100-1.map 100 100 23 98 64 65 952
+238 maze-100-1.map 100 100 11 87 79 49 954
+238 maze-100-1.map 100 100 63 68 37 95 955
+238 maze-100-1.map 100 100 34 95 78 45 952
+239 maze-100-1.map 100 100 80 45 35 93 957
+239 maze-100-1.map 100 100 66 75 32 95 956
+239 maze-100-1.map 100 100 13 87 70 69 957
+239 maze-100-1.map 100 100 75 45 3 99 958
+239 maze-100-1.map 100 100 29 99 65 75 956
+239 maze-100-1.map 100 100 71 41 20 93 957
+239 maze-100-1.map 100 100 11 87 69 49 956
+239 maze-100-1.map 100 100 88 85 37 94 956
+239 maze-100-1.map 100 100 3 81 75 44 959
+239 maze-100-1.map 100 100 93 86 23 97 959
+240 maze-100-1.map 100 100 66 77 26 99 960
+240 maze-100-1.map 100 100 73 47 13 89 962
+240 maze-100-1.map 100 100 68 69 11 88 962
+240 maze-100-1.map 100 100 73 45 17 91 962
+240 maze-100-1.map 100 100 70 43 25 93 961
+240 maze-100-1.map 100 100 28 97 70 71 960
+240 maze-100-1.map 100 100 36 93 65 74 960
+240 maze-100-1.map 100 100 93 90 34 95 960
+240 maze-100-1.map 100 100 25 99 91 89 960
+240 maze-100-1.map 100 100 63 67 33 97 960
+241 maze-100-1.map 100 100 93 86 35 97 967
+241 maze-100-1.map 100 100 71 47 29 93 964
+241 maze-100-1.map 100 100 68 77 23 97 965
+241 maze-100-1.map 100 100 67 75 37 95 966
+241 maze-100-1.map 100 100 65 64 33 98 966
+241 maze-100-1.map 100 100 13 88 75 44 966
+241 maze-100-1.map 100 100 34 99 65 65 967
+241 maze-100-1.map 100 100 73 44 11 89 967
+241 maze-100-1.map 100 100 13 90 75 45 967
+241 maze-100-1.map 100 100 31 98 69 69 967
+242 maze-100-1.map 100 100 28 97 73 45 969
+242 maze-100-1.map 100 100 93 90 37 96 968
+242 maze-100-1.map 100 100 15 90 69 40 968
+242 maze-100-1.map 100 100 69 40 1 91 971
+242 maze-100-1.map 100 100 74 49 37 95 969
+242 maze-100-1.map 100 100 23 99 71 70 969
+242 maze-100-1.map 100 100 26 93 69 39 971
+242 maze-100-1.map 100 100 64 77 37 94 970
+242 maze-100-1.map 100 100 33 99 79 43 970
+242 maze-100-1.map 100 100 69 69 31 99 968
+243 maze-100-1.map 100 100 71 43 34 95 975
+243 maze-100-1.map 100 100 93 90 33 98 974
+243 maze-100-1.map 100 100 35 99 79 41 974
+243 maze-100-1.map 100 100 35 99 93 33 972
+243 maze-100-1.map 100 100 73 47 26 99 975
+243 maze-100-1.map 100 100 75 47 33 99 974
+243 maze-100-1.map 100 100 21 99 71 47 974
+243 maze-100-1.map 100 100 35 94 89 97 973
+243 maze-100-1.map 100 100 37 95 69 49 974
+243 maze-100-1.map 100 100 35 97 64 77 975
diff --git a/JPSPlusGoalBounding/Maps/random-100-33.map b/JPSPlusGoalBounding/Maps/random-100-33.map
new file mode 100644
index 0000000..bb7c66e
--- /dev/null
+++ b/JPSPlusGoalBounding/Maps/random-100-33.map
@@ -0,0 +1,104 @@
+type octile
+height 100
+width 100
+map
+...@..@.@..@....@.@@.@........@TT@@@@@.@TT@TT@..@@TTTTT@....@@@..@..@@..@...@@...@....@T@.@....@T@..
+@....@@.@....@@.@.......@....@TTTT@.@..@TT@TTT@...@@T@@@...@T@.@...@@...........@.....@T@..@....@@@.
+..........@.@..@..@@..@....@.@TTT@..@..@T@@@@@...@T@@.@@@...@............@.......@..@.@@....@..@@@..
+..@.@......@..@..@.@......@@@T@@@..@....@.@T@...@T@@..@@@..@..@..@.@@@@....@..........@..@@.........
+...@.....@......@.........@..@@@..@@..@@...@..@@.@T@...@@.......@..@...@.@.@.@.@@@@@...@.@.@...@.@.@
+.@.....@.@@.@@.@.....@.@.@..@T@@...@...@.........@T@@.............@..@@...@T@........@...@.@@@.@....
+@.@.......@..@.@@@..@.......@T@@...@...@...@@...@.@T@..@....@..@..@.....@..@.........@..@@...@.@....
+..@...@@@.@.@..@....@.....@..@.........@@.@@@.@....@.@...@...@....@.@.@@@..@.........@@@@..@........
+..@...@....@@@.......@@@.....@...@....@@....@@.@.@...@......@@@.......@T@..@...@@.@.@.....@....@..@.
+@...@.@..@@TT@@@...@...@....@@.@...@..@..@.@@..@...@@..@..@...@@@..@@@T@@.@T@.......@.@.........@.@@
+....@......@@@TT@....@..@.@@@.@@.....@@..@@..@.@....@...@@@...@.......@..@TT@@.@.@@...@....@.@@@..@T
+..@@@.....@T@TT@T@..@.@........@..................@@T@@.....@....@...@@...@T@...@.@@.@...@@...@.@..@
+........@..@TTT@@.........@.@......@.@..@@.@@@.@....@@.@....@.@.@T@......@.@@.......@..@@...@.......
+.......@....@T@..@......@@@@..........@@..@.@...........@........@T@..@..@..@......@............@@@@
+@...........@T@@.....@..@..@@@@.....@...........@.@...@...@.......@......@...@.@..@T@..@@..@...@..@.
+.@...@.@.....@....@@....@.@...@@........@@...@@..@..@..@@@......@.@.......@.@@.@@@@@.@...@...@......
+.@.@@@...@@...@@...@@@@......@T@..@@@.@@T@@.@@.@.@.....@..@@.@..............@@.....@...@.@@........@
+..@..@.....@...@@......@@.....@..@..@...@......@@@..@.@@..@......@.@.@@.@@....@.@@...@.@..@@.@..@@..
+@...@......@...@@...@....@@@....@@@..@....@..@.@.@@@..@..@....@.@@.@.@.@....@....@.....@.@.........@
+..@@@...@@..@...@@...@.@......@@.......@....@T@......@...@.@@@@........@@..@@.@.@@..@..@..@....@....
+.@.....@@@..@..@T@@...@..@@@.@..@....@.@@.@@.@.@..@@..@......@.....@@@.@@.@..@...@........@.@..@.@.@
+.@..........@.@@@.@@....@.@..@..@.@@@....@@..@.......@.@.@....@...@T@@@.........@...@....@@....@@..@
+.....@.@....@.@T@.@..@@@........@@....@@@.@@..@..........@@.....@@.@@@@..........@.@.@@...@....@.@.@
+@.......@..@@@@@@...@@....@@@....@...@@@...@@.......@..@.......@....@@...@..@...@....@@..@..........
+@.@..@.@..@@@@T@@@@@T@.....@....@.@@@@@T@..@@@...@...@...@@.@..@......@....@...@.@.@@@...@@....@....
+....@@@@.....@TT@.@TTT@@@.@..@@@..@@T@@T@@..@...@.@@.@.@@........@@@@..@..@@......@T@@....@@.@..@@..
+@..@@.@.@@..@@@@@.@TTT@@....@.@..@T@@T@TT@@...........@....@....@@@....@@.@@@....@@@T@.@..@.@@...@@.
+...@....@@@...@@@..@@T@.......@...@@T@TTT@T@@....@...@....@...@.....@...@.@..@@...@@@.....@...@....@
+@.......@T@...@....@.@.@..@.@....@..@@TTT@@..@.@.@.......@.....@@...@..@.@..........@@@@.@@.....@.@@
+...@@@@..@....@......@...@........@...@T@..............@@@..@.@@..@...@.......@..@..@@..........@..@
+@@@.@....@.......@......@..@@..@...@..@TT@...@.@@..@.@@.@..@@....@@...@.....@...@...@....@@.........
+@.@....@@.@@..@@..@@@@........@...@....@T@................@.....@.@@@...@.@@.@.@@....@@.@@@.......@@
+...@@.....@..@.............@@@....@.@...@...@@.@...@.@.........@......@...@..@...@.....@TTT@@@@.@.@.
+@@.....@...@...@.@..@..@@......@.@T@@...@.....@....@.@...@.....@.....@..@....@.@.@.@@.@.@@@.@@@@.@..
+..@...@.....@..@..@.@....@@..@@.@.@..@..@...@..@..@.........@@.......@....@@.@.....@.....@@...@@....
+@...@@@.@..@T@@T@.....@@...@@.@.......@.@............@@.@....@.@@.....@..@@..@@@.@..@..@@...@.@....@
+....@T@.....@TTTT@.@@@.@.@.@.....@...@.......@..@.@.@@@...@..........@...@@...@@..@........@@...@...
+....@T@.@....@TT@@@@@...@@.@.@..@..@.........@.@.@......@.@.@@@.@.@...@..@@.@@.@.@...@..@..@...@T@..
+@@.@.@...@..@TT@@TT@@.....@..@..@....@.@..@..@.@......@.@.@..@..@@..@..@.........@...@@.@.......@.@.
+@T@...@....@@@@T@@TT@...@.....@.@@..@..........@@...@.@...@..@.@.....@.....@@...@....@...@.@@.@.....
+@@....@..@@..@TT@TT@@.....@..@@@..@.@@@.@....@.@@...@..@..@@...@@....@@@...@.@@@@.@@..@@..@T@.@.....
+...@@.@.@.@...@T@TTT@@..@@T@..@....@..@.@@.@...@T@.@@.@....@..@@.....@@@@.@@....@.....@T@@@@@@..@...
+..@@@.........@@TTT@@T@.@TT@@.............@..@@@T@..@..@...@@......@.@TT@............@.@..@@...@....
+...@...@@.@..@..@@@..@...@@...@..........@...@..@@.@@..@.@.....@......@T@....................@@@....
+@.@...@T@...@........@.@@..@.....@..@@...........@..@....@..@..@......@@..@..@..@..@..@@..@..@@.....
+.....@.@.@.......@@..@.....@...@.@.@...@.@@.@....@@..@.@.....@.@.@.@...@..@.@.@.@.@@.@....@@..@.@@..
+.@.@.....@.@@..@.......@.@...@@.@...@@......@@.@.@....@.....@T@.@...@@....@.......@.....@@@@...@....
+@T@...@.@.......@.@@@@.....@....@......@..@.@..@...@.@.@.....@.......@.@.@.@.@@..@..@@.@.@...@...@.@
+@@.@...@.......@T@..@..@.......@....@@..@.....@......@......@....@.....@.@...@@.@..@.@...@.@@@.@..@.
+.....@........@T@...@.....@@@@.@..@.@@....@.@@@@.@@@...@@..@.....@...@@T@@.....@T@@...@.....@.....@.
+..@...@...@.@..@@...@...@......@......@.@@@.@....@@@@.@.@......@@@@.@..@@@.@..@.@.@..@.@@.........@.
+@.@@.@.....@....@...@...@.@...@@...@.@@.@T@@..@...@T@.@.@..@..@.........@..@..@.....@......@.@.@@.@.
+...@@T@.....@@......@@...@.@...@@.@@.....@....@...@@@@...@.....@....@@@@..@@@@...@.@@.....@..@..@.@.
+.@@..@......@@@..@@@...@...@@.@T@@@......@.......@TTT@..@.@@.....@@@TT@@.@T@@@.@.@.....@@..@.@.@.@..
+@TT@.....@.@T@@@.@@.@.@.@...@.@@TTT@....@@...@@@..@T@.........@.@...@@....@....@..@@...@.@..@.......
+@T@..@@@..@.@@@......@@....@@.@TTT@..@..@T@.@TTT@..@.@@.@.@..@T@.@......@....@..@@.....@.@........@.
+@@........@.@.@.@.@...@....@T@@T@@..@@..@@..@TT@@......@@..@.@@..........@....@@@@@@.@...@@..@@.@...
+...@@...@@..@....@T@@@@...@.@..@@T@@@@@...@..@@@...@..@..@.@@..@.@...@......@..@...@@T@.@@...@..@..@
+@@@@..@......@....@..@T@.@...@.@.@....@@.@...@...@.@@......@..@.@...@......@......@T@@@.@T@...@@....
+@..@@@....@@..@.@@...@@............@..@.@...@..@@....@...@..@......@.@.......@@.@@T@TTT@TT@@.@@.....
+@@.....@...@.......@.@....@......@.........@..@T@.....@..@@@@...@.......@.@....@@TTTTTTT@@T@.@@...@.
+..@@.@....@..@.@@..@...@.@@.......@......@.@.@T@..@.@.@@.@........@..@.....@..@TTTTT@TT@.@@....@....
+.@................@T@.@............@..@@@..@@TT@.@@...@@@......@.@@.@@..@@....@@TTT@T@@.....@.@T@...
+..@@@@..@...@@.....@T@@@...@.@.@..@..@.....@@@@.@....@@@.....@@.@T@@@.@@@@@.@...@TT@@.....@@@@.@..@.
+.@......@..@...@..@.@..@..@T@..@@@@.@..@@..@.@....@@.@@T@.....@..@....@TT@@.@.@..@@.......@....@.@T@
+.........@......@........@.@T@....@...@@...@.....@@.@..@@@..@...@....@TTT@.@.....@....@......@.@.@@T
+.....@................@@.@..@..@@..@...@...@..@.@@......@T@.@.@.@.@...@@@..@@@@.@@@..@.@@@...@.....@
+@@.......@...@.....@..@@.@@....@.....@....@@....@..@.@...@....@.@...@......@@T@@@@..@@............@@
+TT@.....@T@.....@@@T@@@.@.@.@...@...@@@......@.@.@....@..@@..@.@..@.@.@.@@...@..@.@...@....@..@....@
+TT@...@.@@.....@TTTT@@.......@@...@.@....@..@......@@@@..@T@@@..@.@@...@@@@...@.@....@...@@T@.@@@...
+@@..@@@..@@..@@.@T@@T@@..@@@@@..@..@..........@@....@T@...@@.....@@....@...@@...@..@..@..@.@...@....
+@T@.@....@..@....@..@.@...@T@@@@...@.@...@.@@@....@..@........@@..@...@.......@.@.@T@.@....@.@....@.
+TT@.........@@......@....@@@......@@.....@@@.....@.@..@.@.@.@@..@@.@@.@@.....@@...@@@.@.@...@...@..@
+T@.......@..@@...@.....@@@@..@@.....@........@.@@@...@@@......@.@...@.@@.@@...@..@....@@@@.@.@.@....
+@.@@@@@..@...@.@........@......@@@@.@.....@.@@..@....@.@@...@...@@...@......@.@...@...@@..@..@@....@
+..@@TT@...@.@..@.@@...@@@..@....@TT@T@........@@..@.......@.......@..@....@..@@....@.@...@T@...@....
+@..@TTT@.@...@.@@.@...@....@@@..@@TTT@.@.@@....@@...@.@@@......@..@@..@...@....@........@@@T@..@....
+..@@@T@....@@T@@......@...@.......@@TT@....@..@T@.@@@...@..@@......@...@.@@@..@@.@.@.@.....@@@...@@.
+@...@@...@@..@@.....@.@..@.@.......@T@.@@@....@@@..@T@@..@..@@...@.........@.@@...@...@.....@@@..@..
+@@@.....@@...@...@...@@@.@..@.@@@.@@@@.@.@.@@...@.@TT@.......@...@.@..@@.@....@..@@@@..@@@@.@..@.@@@
+TT@@@..@@@....@.....@..@@@..@@.......@...@@........@T@.@.....@@.....@@@@.@..........@...@@@@T@.@@.@.
+T@@.@@.@@T@..@@.....@@...@.@TT@...@@...@@.....@.....@@@....@..@..@@@.@@.@T@....@.@.....@.@..@.....@.
+@@@.....@@....@.............@T@.@.....@@@.@@..............@.@.@@.@.......@@@.@..@@@.@@@..@.@..@.....
+TT@....@TT@@...@..@......@@.@T@..@.@.....@..@..@...@.....@...........@@@@@@.@..@@...@...@@...@@.@..@
+@TT@....@@..@.......@@..@....@@@@.........@.@..@...@...@@@.@@.@....@....@.....@T@...@...@@.@..@@@@@@
+TTTT@......@...@..@@....@.@.@@@@T@....@..@..@..@......@T@..@..@.@@@......@@.@..@..@.....@.....@..@..
+@TT@@.....@...@...@@..@@..@@....@@@@..@@.@@...@.@@...@@@....@@.......@...@.....@.@.@.@.@@.........@.
+TT@...@............@....@.@@...@...@@@@@..@@@.....@.@..@@...@.@@@.@..@...@..@.@@...@@.@@.@@.........
+T@...@T@.@.....@.@@.@..........@......@@..@.@@.................@@.@.......@............@......@.@...
+@@@@..@T@...@.@.@.@..@..........@@...@.@....@@@.@...@...@@.@.@.@.@.....@.@...@.....@@@@..@.@...@..@.
+.@@@.@@@.@..@@@.........@..@..@@..@........@.@...@@@..@.@...@@.......@.......@@...@@..@......@.@.@@.
+.........@@@.@......@....@.@.@@T@.....@.........@@....@@@....@@@@@........@..@...@...@...@..@.@..@@.
+.@..@.@......@...@.@..@@@@..@.@@@.....@....@.@...@....@@@@.@@@@..@.@.@....@.@..........@...@.....@..
+......@.@.@@....@@..@.@.......@......@@......@...@....@..@@.........@@@.@...............@..@..@@...@
+..@.@..@@@.@@.@....@@.@@.....@......@.@@.@@.....@@@..........@........@@...@@..@.@..@..............@
+..@@.......@...@.@..@..@....@...@@........@@..@.......@...@.@....@..@@T@@@.................@..@....@
+..@@@...@..@@.......@@@@@...........@@.@....@@@@@.....@...@@..@.@@@..@@......@..@......@......@.....
+.@@@@.....@@T@.@...@.@@.@@@....@@.@....@...@..........@@@.@@@.@....@...@@@@...@@...................@
+@...........@.@.@....@........@......@@@@@@.....@@@....@@.@T@@........@@T@T@........@..@..@@..@.....
+@.@.....@........@@......@...@@.....@TT@TT@@@........@@TT@TT@.....@..@TTTTTT@.......@.@.....@..@.@..
diff --git a/JPSPlusGoalBounding/Maps/random-100-33.map.pre b/JPSPlusGoalBounding/Maps/random-100-33.map.pre
new file mode 100644
index 0000000..dd2b923
Binary files /dev/null and b/JPSPlusGoalBounding/Maps/random-100-33.map.pre differ
diff --git a/JPSPlusGoalBounding/Maps/random-100-33.map.scen b/JPSPlusGoalBounding/Maps/random-100-33.map.scen
new file mode 100644
index 0000000..43c95f1
--- /dev/null
+++ b/JPSPlusGoalBounding/Maps/random-100-33.map.scen
@@ -0,0 +1,491 @@
+version 1
+1 random-100-33.map 100 100 10 47 12 51 6.82843
+1 random-100-33.map 100 100 23 24 25 28 6
+1 random-100-33.map 100 100 11 53 7 51 4.82843
+1 random-100-33.map 100 100 39 10 42 6 6.41421
+1 random-100-33.map 100 100 7 3 4 6 4.24264
+1 random-100-33.map 100 100 27 94 32 94 7.82843
+1 random-100-33.map 100 100 74 42 70 47 7.82843
+1 random-100-33.map 100 100 94 13 92 19 7.41421
+1 random-100-33.map 100 100 56 34 58 28 7.41421
+1 random-100-33.map 100 100 41 3 45 4 5.82843
+2 random-100-33.map 100 100 11 21 0 22 11.4142
+2 random-100-33.map 100 100 73 15 66 11 9.24264
+2 random-100-33.map 100 100 26 19 30 20 9
+2 random-100-33.map 100 100 39 84 37 91 10.4142
+2 random-100-33.map 100 100 7 50 10 42 10.6569
+2 random-100-33.map 100 100 4 60 5 57 8
+2 random-100-33.map 100 100 68 84 61 83 8
+2 random-100-33.map 100 100 96 3 97 12 9.41421
+2 random-100-33.map 100 100 46 44 48 54 11.4142
+2 random-100-33.map 100 100 21 65 13 69 9.65685
+3 random-100-33.map 100 100 7 92 6 84 12.4142
+3 random-100-33.map 100 100 62 34 61 21 13.4142
+3 random-100-33.map 100 100 77 83 86 88 14
+3 random-100-33.map 100 100 26 44 26 55 15.2426
+3 random-100-33.map 100 100 62 16 54 24 15.4142
+3 random-100-33.map 100 100 28 4 19 7 14.8284
+3 random-100-33.map 100 100 85 93 93 84 14.6569
+3 random-100-33.map 100 100 85 35 77 39 15.4142
+3 random-100-33.map 100 100 46 83 48 95 14.8284
+3 random-100-33.map 100 100 59 12 59 24 14.2426
+4 random-100-33.map 100 100 37 94 46 88 17.2426
+4 random-100-33.map 100 100 96 73 87 63 18.0711
+4 random-100-33.map 100 100 89 19 96 12 19.4142
+4 random-100-33.map 100 100 3 12 1 27 19.4853
+4 random-100-33.map 100 100 39 43 24 49 18.6569
+4 random-100-33.map 100 100 61 31 48 38 17.0711
+4 random-100-33.map 100 100 63 36 54 44 17.8284
+4 random-100-33.map 100 100 37 64 29 57 18.4142
+4 random-100-33.map 100 100 49 75 55 67 18.2426
+4 random-100-33.map 100 100 39 91 49 84 19.2426
+5 random-100-33.map 100 100 87 84 81 96 21.4142
+5 random-100-33.map 100 100 1 19 6 31 20.4142
+5 random-100-33.map 100 100 96 43 97 59 23.2426
+5 random-100-33.map 100 100 4 4 19 7 20.8284
+5 random-100-33.map 100 100 29 47 42 41 22.6569
+5 random-100-33.map 100 100 66 17 48 13 22.2426
+5 random-100-33.map 100 100 78 39 65 29 23.2426
+5 random-100-33.map 100 100 81 44 65 46 22.2426
+5 random-100-33.map 100 100 66 86 85 93 23.6569
+5 random-100-33.map 100 100 86 29 94 17 20.8284
+6 random-100-33.map 100 100 75 29 76 8 27.6569
+6 random-100-33.map 100 100 81 41 60 43 27.4853
+6 random-100-33.map 100 100 46 71 32 72 27.2426
+6 random-100-33.map 100 100 3 92 20 79 27.8995
+6 random-100-33.map 100 100 85 78 65 75 27.8284
+6 random-100-33.map 100 100 71 75 67 70 24.6569
+6 random-100-33.map 100 100 62 79 46 69 24.8284
+6 random-100-33.map 100 100 47 23 64 29 25.2426
+6 random-100-33.map 100 100 61 4 56 24 25.2426
+6 random-100-33.map 100 100 47 26 43 11 27.4853
+7 random-100-33.map 100 100 68 78 83 91 29.0711
+7 random-100-33.map 100 100 75 21 88 43 31.4853
+7 random-100-33.map 100 100 79 23 67 5 28.4853
+7 random-100-33.map 100 100 87 58 94 37 30.8284
+7 random-100-33.map 100 100 55 96 79 91 29.4853
+7 random-100-33.map 100 100 10 82 15 89 30.2426
+7 random-100-33.map 100 100 69 30 61 54 28.4853
+7 random-100-33.map 100 100 65 7 81 27 31.5563
+7 random-100-33.map 100 100 45 80 32 88 28.0711
+7 random-100-33.map 100 100 40 93 60 75 31.5563
+8 random-100-33.map 100 100 67 89 98 98 35.8995
+8 random-100-33.map 100 100 78 28 51 26 35.7279
+8 random-100-33.map 100 100 78 81 64 71 33.0711
+8 random-100-33.map 100 100 7 70 34 62 32.6569
+8 random-100-33.map 100 100 3 36 12 15 35.8995
+8 random-100-33.map 100 100 20 61 34 45 34.4853
+8 random-100-33.map 100 100 73 0 97 5 32.6569
+8 random-100-33.map 100 100 80 26 54 31 32.8995
+8 random-100-33.map 100 100 33 46 22 61 34.4853
+8 random-100-33.map 100 100 43 43 55 19 35.8995
+9 random-100-33.map 100 100 63 18 32 9 37.8995
+9 random-100-33.map 100 100 52 63 70 51 37.0711
+9 random-100-33.map 100 100 78 70 94 47 39.4853
+9 random-100-33.map 100 100 47 91 43 59 38.4853
+9 random-100-33.map 100 100 61 48 69 55 38.0711
+9 random-100-33.map 100 100 7 40 10 20 36.4142
+9 random-100-33.map 100 100 59 20 38 19 37.6569
+9 random-100-33.map 100 100 54 7 69 31 36.3137
+9 random-100-33.map 100 100 32 48 41 23 38.7279
+9 random-100-33.map 100 100 78 10 96 27 36.0711
+10 random-100-33.map 100 100 73 32 72 2 43.4853
+10 random-100-33.map 100 100 35 61 60 79 43.4853
+10 random-100-33.map 100 100 65 9 66 45 43.4853
+10 random-100-33.map 100 100 51 13 80 2 40.4853
+10 random-100-33.map 100 100 23 45 54 32 41.8995
+10 random-100-33.map 100 100 66 82 70 70 41.6569
+10 random-100-33.map 100 100 14 5 20 29 42.7279
+10 random-100-33.map 100 100 72 91 41 74 43.3137
+10 random-100-33.map 100 100 23 69 7 92 41.1421
+10 random-100-33.map 100 100 3 78 13 49 41.4853
+11 random-100-33.map 100 100 45 79 19 58 47.1421
+11 random-100-33.map 100 100 79 23 48 28 45.3137
+11 random-100-33.map 100 100 82 47 98 74 44.0711
+11 random-100-33.map 100 100 56 5 89 9 44.3137
+11 random-100-33.map 100 100 67 94 98 82 47.4853
+11 random-100-33.map 100 100 90 67 82 31 47.6569
+11 random-100-33.map 100 100 66 47 85 49 47.4853
+11 random-100-33.map 100 100 54 79 32 78 44.5563
+11 random-100-33.map 100 100 75 63 88 63 46.0711
+11 random-100-33.map 100 100 92 82 68 77 46.8995
+12 random-100-33.map 100 100 64 48 45 72 50.8995
+12 random-100-33.map 100 100 64 10 25 6 50.0711
+12 random-100-33.map 100 100 47 43 18 51 50.3137
+12 random-100-33.map 100 100 46 74 14 65 49.4853
+12 random-100-33.map 100 100 45 91 49 56 50.3137
+12 random-100-33.map 100 100 42 63 30 38 49.7279
+12 random-100-33.map 100 100 53 77 55 52 50.6569
+12 random-100-33.map 100 100 29 72 2 73 50.1421
+12 random-100-33.map 100 100 34 45 63 15 51.3848
+12 random-100-33.map 100 100 72 70 37 70 51.8284
+13 random-100-33.map 100 100 65 1 89 37 54.6274
+13 random-100-33.map 100 100 26 33 57 13 52.6569
+13 random-100-33.map 100 100 81 85 40 77 55.7279
+13 random-100-33.map 100 100 25 10 72 11 55.3137
+13 random-100-33.map 100 100 35 48 9 63 53.7279
+13 random-100-33.map 100 100 65 20 22 7 54.7279
+13 random-100-33.map 100 100 46 10 76 31 52.3137
+13 random-100-33.map 100 100 31 99 55 67 53.2132
+13 random-100-33.map 100 100 34 68 36 36 52.7279
+13 random-100-33.map 100 100 61 24 90 23 55.8995
+14 random-100-33.map 100 100 39 46 11 55 56.8995
+14 random-100-33.map 100 100 26 59 41 97 56.5563
+14 random-100-33.map 100 100 51 12 25 48 58.3848
+14 random-100-33.map 100 100 31 36 2 66 56.8995
+14 random-100-33.map 100 100 58 61 88 63 56.1421
+14 random-100-33.map 100 100 41 13 2 16 58.9706
+14 random-100-33.map 100 100 19 56 42 32 57.7279
+14 random-100-33.map 100 100 40 37 34 5 56.9706
+14 random-100-33.map 100 100 46 35 27 15 58.5563
+14 random-100-33.map 100 100 15 84 4 44 57.3848
+15 random-100-33.map 100 100 66 80 18 98 62.3848
+15 random-100-33.map 100 100 74 87 24 94 62.3137
+15 random-100-33.map 100 100 54 80 94 80 63.3137
+15 random-100-33.map 100 100 3 70 32 49 63.5563
+15 random-100-33.map 100 100 66 41 21 53 61.3848
+15 random-100-33.map 100 100 81 74 83 30 62.1421
+15 random-100-33.map 100 100 51 40 84 56 63.7279
+15 random-100-33.map 100 100 70 23 88 63 62.1421
+15 random-100-33.map 100 100 43 45 64 0 62.3848
+15 random-100-33.map 100 100 72 57 85 80 62.9706
+16 random-100-33.map 100 100 44 53 66 55 66.7279
+16 random-100-33.map 100 100 49 84 30 49 66.3848
+16 random-100-33.map 100 100 88 89 34 95 64.4853
+16 random-100-33.map 100 100 76 81 33 78 66.6274
+16 random-100-33.map 100 100 93 70 71 51 66.3137
+16 random-100-33.map 100 100 4 39 9 92 65.5563
+16 random-100-33.map 100 100 11 5 3 49 67.3137
+16 random-100-33.map 100 100 52 24 13 29 67.5563
+16 random-100-33.map 100 100 36 36 49 83 67.799
+16 random-100-33.map 100 100 84 0 46 36 67.799
+17 random-100-33.map 100 100 10 46 26 84 69.799
+17 random-100-33.map 100 100 76 2 25 7 68.1421
+17 random-100-33.map 100 100 64 42 20 74 71.799
+17 random-100-33.map 100 100 11 82 58 86 68.2132
+17 random-100-33.map 100 100 46 43 75 62 68.9706
+17 random-100-33.map 100 100 21 21 57 39 69.3137
+17 random-100-33.map 100 100 14 91 66 80 71.3848
+17 random-100-33.map 100 100 52 32 21 74 69.9706
+17 random-100-33.map 100 100 49 67 93 84 71.6274
+17 random-100-33.map 100 100 79 70 66 48 69.7279
+18 random-100-33.map 100 100 96 93 41 70 75.5563
+18 random-100-33.map 100 100 71 68 70 39 75.5563
+18 random-100-33.map 100 100 7 68 4 13 73.3137
+18 random-100-33.map 100 100 62 34 80 73 73.3848
+18 random-100-33.map 100 100 57 56 4 61 72.9706
+18 random-100-33.map 100 100 48 47 31 21 75.7279
+18 random-100-33.map 100 100 38 42 10 84 75.2132
+18 random-100-33.map 100 100 85 70 78 15 74.3848
+18 random-100-33.map 100 100 50 39 52 98 75.3848
+18 random-100-33.map 100 100 46 20 42 78 72.7279
+19 random-100-33.map 100 100 57 47 65 90 78.799
+19 random-100-33.map 100 100 56 41 16 81 76.3848
+19 random-100-33.map 100 100 10 73 5 13 78.5563
+19 random-100-33.map 100 100 58 29 12 66 77.6274
+19 random-100-33.map 100 100 31 42 8 10 76.8995
+19 random-100-33.map 100 100 3 37 12 86 76.3848
+19 random-100-33.map 100 100 93 46 51 73 79.1421
+19 random-100-33.map 100 100 76 22 41 66 77.6274
+19 random-100-33.map 100 100 57 39 6 71 79.0416
+19 random-100-33.map 100 100 68 97 82 52 77.3848
+20 random-100-33.map 100 100 57 13 14 20 81.799
+20 random-100-33.map 100 100 58 45 35 98 83.2132
+20 random-100-33.map 100 100 6 33 8 98 80.5563
+20 random-100-33.map 100 100 48 26 3 67 81.799
+20 random-100-33.map 100 100 48 48 8 90 83.4558
+20 random-100-33.map 100 100 94 89 35 65 82.799
+20 random-100-33.map 100 100 87 38 26 45 80.9706
+20 random-100-33.map 100 100 40 95 4 58 83.3848
+20 random-100-33.map 100 100 86 18 97 72 81.1421
+20 random-100-33.map 100 100 74 62 71 6 80.5563
+21 random-100-33.map 100 100 26 69 6 24 84.3137
+21 random-100-33.map 100 100 22 87 11 34 85.799
+21 random-100-33.map 100 100 52 24 7 27 85.5563
+21 random-100-33.map 100 100 97 75 83 21 84.1421
+21 random-100-33.map 100 100 63 48 74 90 87.3848
+21 random-100-33.map 100 100 66 0 9 25 86.0416
+21 random-100-33.map 100 100 39 50 74 71 86.4853
+21 random-100-33.map 100 100 8 32 16 97 85.1421
+21 random-100-33.map 100 100 17 74 77 84 87.5563
+21 random-100-33.map 100 100 58 0 84 50 86.8701
+22 random-100-33.map 100 100 36 61 2 13 91.3137
+22 random-100-33.map 100 100 11 63 75 74 89.1421
+22 random-100-33.map 100 100 89 64 89 1 89.1421
+22 random-100-33.map 100 100 31 89 86 77 91.7279
+22 random-100-33.map 100 100 2 29 14 72 91.1421
+22 random-100-33.map 100 100 89 50 35 7 91.9706
+22 random-100-33.map 100 100 81 85 67 30 89.3848
+22 random-100-33.map 100 100 47 74 53 9 91.0416
+22 random-100-33.map 100 100 48 47 23 34 89.5563
+22 random-100-33.map 100 100 44 22 45 94 91.3848
+23 random-100-33.map 100 100 5 39 32 7 92.5563
+23 random-100-33.map 100 100 11 76 56 24 93.8701
+23 random-100-33.map 100 100 89 40 61 84 93.5563
+23 random-100-33.map 100 100 78 95 0 93 95.2132
+23 random-100-33.map 100 100 4 61 20 1 95.3137
+23 random-100-33.map 100 100 4 73 61 25 94.3553
+23 random-100-33.map 100 100 62 23 78 81 93.2132
+23 random-100-33.map 100 100 42 34 3 15 92.1421
+23 random-100-33.map 100 100 24 26 6 68 94.1421
+23 random-100-33.map 100 100 91 34 21 53 94.2132
+24 random-100-33.map 100 100 83 95 43 40 97.3848
+24 random-100-33.map 100 100 53 16 53 95 99.0416
+24 random-100-33.map 100 100 0 92 57 54 97.8701
+24 random-100-33.map 100 100 39 93 94 48 96.3848
+24 random-100-33.map 100 100 18 5 97 11 99.1421
+24 random-100-33.map 100 100 97 80 20 98 98.5563
+24 random-100-33.map 100 100 36 61 86 27 99.6985
+24 random-100-33.map 100 100 40 43 86 69 96.3848
+24 random-100-33.map 100 100 30 49 61 99 96.4558
+24 random-100-33.map 100 100 76 93 49 34 96.3848
+25 random-100-33.map 100 100 27 43 94 3 102.456
+25 random-100-33.map 100 100 20 5 84 45 101.799
+25 random-100-33.map 100 100 92 94 80 64 101.213
+25 random-100-33.map 100 100 90 48 24 69 100.799
+25 random-100-33.map 100 100 25 82 84 69 101.556
+25 random-100-33.map 100 100 68 34 3 13 103.799
+25 random-100-33.map 100 100 75 33 13 0 101.385
+25 random-100-33.map 100 100 51 13 52 94 102.87
+25 random-100-33.map 100 100 29 64 11 4 100.971
+25 random-100-33.map 100 100 15 92 82 67 103.213
+26 random-100-33.map 100 100 24 55 90 57 104.971
+26 random-100-33.map 100 100 70 18 4 68 105.941
+26 random-100-33.map 100 100 80 5 72 80 107.042
+26 random-100-33.map 100 100 25 39 98 66 107.799
+26 random-100-33.map 100 100 4 93 12 30 107.971
+26 random-100-33.map 100 100 42 6 30 78 106.627
+26 random-100-33.map 100 100 91 43 31 80 105.627
+26 random-100-33.map 100 100 68 71 18 81 107.213
+26 random-100-33.map 100 100 85 96 78 16 107.87
+26 random-100-33.map 100 100 40 8 13 65 104.87
+27 random-100-33.map 100 100 50 92 48 8 109.113
+27 random-100-33.map 100 100 87 62 15 93 108.456
+27 random-100-33.map 100 100 97 87 64 61 109.87
+27 random-100-33.map 100 100 56 83 40 4 110.799
+27 random-100-33.map 100 100 9 18 49 67 111.385
+27 random-100-33.map 100 100 2 21 45 87 111.385
+27 random-100-33.map 100 100 73 60 15 58 109.799
+27 random-100-33.map 100 100 90 15 86 84 111.627
+27 random-100-33.map 100 100 88 36 5 50 110.799
+27 random-100-33.map 100 100 88 82 50 28 110.385
+28 random-100-33.map 100 100 43 85 84 18 115.698
+28 random-100-33.map 100 100 87 99 71 21 113.698
+28 random-100-33.map 100 100 15 93 12 28 114.385
+28 random-100-33.map 100 100 6 79 61 11 113.184
+28 random-100-33.map 100 100 78 31 2 13 113.456
+28 random-100-33.map 100 100 89 77 51 13 113.456
+28 random-100-33.map 100 100 69 30 15 93 115.527
+28 random-100-33.map 100 100 16 63 58 61 115.941
+28 random-100-33.map 100 100 79 68 11 52 113.799
+28 random-100-33.map 100 100 56 17 24 91 114.042
+29 random-100-33.map 100 100 73 1 12 59 116.698
+29 random-100-33.map 100 100 68 83 59 2 119.456
+29 random-100-33.map 100 100 12 85 68 12 116.598
+29 random-100-33.map 100 100 29 72 22 24 117.87
+29 random-100-33.map 100 100 63 86 2 35 117.213
+29 random-100-33.map 100 100 45 78 87 30 119.355
+29 random-100-33.map 100 100 93 79 44 41 118.213
+29 random-100-33.map 100 100 93 24 28 58 119.87
+29 random-100-33.map 100 100 10 67 71 2 117.113
+29 random-100-33.map 100 100 8 58 69 60 116.799
+30 random-100-33.map 100 100 96 8 49 67 120.87
+30 random-100-33.map 100 100 0 27 59 83 120.799
+30 random-100-33.map 100 100 46 9 91 78 123.698
+30 random-100-33.map 100 100 94 66 13 60 121.042
+30 random-100-33.map 100 100 94 92 33 34 123.042
+30 random-100-33.map 100 100 53 82 25 22 123.698
+30 random-100-33.map 100 100 10 99 82 67 123.698
+30 random-100-33.map 100 100 12 15 54 53 120.385
+30 random-100-33.map 100 100 6 67 93 68 123.456
+30 random-100-33.map 100 100 7 29 71 54 120.799
+31 random-100-33.map 100 100 78 63 14 79 125.113
+31 random-100-33.map 100 100 99 52 17 51 124.456
+31 random-100-33.map 100 100 48 83 18 14 124.113
+31 random-100-33.map 100 100 70 88 94 9 126.456
+31 random-100-33.map 100 100 72 87 41 5 126.456
+31 random-100-33.map 100 100 11 81 26 31 124.113
+31 random-100-33.map 100 100 9 31 62 60 127.698
+31 random-100-33.map 100 100 79 6 90 99 125.113
+31 random-100-33.map 100 100 92 95 87 22 125.698
+31 random-100-33.map 100 100 6 2 49 67 125.799
+32 random-100-33.map 100 100 32 28 26 75 131.042
+32 random-100-33.map 100 100 33 30 54 74 130.213
+32 random-100-33.map 100 100 12 87 16 14 130.456
+32 random-100-33.map 100 100 94 89 8 51 130.284
+32 random-100-33.map 100 100 1 6 93 0 128.284
+32 random-100-33.map 100 100 35 91 34 20 130.284
+32 random-100-33.map 100 100 7 19 74 51 130.113
+32 random-100-33.map 100 100 93 94 80 3 129.456
+32 random-100-33.map 100 100 99 54 10 76 130.113
+32 random-100-33.map 100 100 85 8 10 57 131.698
+33 random-100-33.map 100 100 66 77 10 15 134.627
+33 random-100-33.map 100 100 45 17 30 86 133.113
+33 random-100-33.map 100 100 96 96 87 10 133.87
+33 random-100-33.map 100 100 98 85 10 76 132.113
+33 random-100-33.map 100 100 22 85 84 50 132.698
+33 random-100-33.map 100 100 37 22 34 95 132.87
+33 random-100-33.map 100 100 9 37 64 64 134.527
+33 random-100-33.map 100 100 41 14 0 92 134.355
+33 random-100-33.map 100 100 17 0 6 99 133.213
+33 random-100-33.map 100 100 61 59 27 83 132.527
+34 random-100-33.map 100 100 64 59 3 10 138.77
+34 random-100-33.map 100 100 7 78 86 12 136.598
+34 random-100-33.map 100 100 78 6 13 88 138.598
+34 random-100-33.map 100 100 40 83 21 21 139.284
+34 random-100-33.map 100 100 30 89 20 30 138.113
+34 random-100-33.map 100 100 51 95 12 16 137.456
+34 random-100-33.map 100 100 73 3 27 89 138.77
+34 random-100-33.map 100 100 80 88 1 35 137.113
+34 random-100-33.map 100 100 2 36 82 87 138.941
+34 random-100-33.map 100 100 10 95 63 10 137.012
+35 random-100-33.map 100 100 31 94 59 66 141.841
+35 random-100-33.map 100 100 67 98 0 21 142.284
+35 random-100-33.map 100 100 6 99 24 6 143.042
+35 random-100-33.map 100 100 12 91 37 13 142.113
+35 random-100-33.map 100 100 69 69 35 7 142.284
+35 random-100-33.map 100 100 17 52 94 77 142.87
+35 random-100-33.map 100 100 88 69 3 40 140.042
+35 random-100-33.map 100 100 93 27 62 99 141.77
+35 random-100-33.map 100 100 4 51 93 70 141.698
+35 random-100-33.map 100 100 57 63 31 96 142.012
+36 random-100-33.map 100 100 41 92 21 35 146.698
+36 random-100-33.map 100 100 68 59 7 18 145.941
+36 random-100-33.map 100 100 23 30 65 86 145.456
+36 random-100-33.map 100 100 44 95 4 1 145.456
+36 random-100-33.map 100 100 92 74 24 22 146.87
+36 random-100-33.map 100 100 7 96 73 26 146.669
+36 random-100-33.map 100 100 76 59 7 93 144.355
+36 random-100-33.map 100 100 96 97 95 25 147.77
+36 random-100-33.map 100 100 99 78 2 60 144.698
+36 random-100-33.map 100 100 91 83 54 12 145.456
+37 random-100-33.map 100 100 94 81 98 17 150.284
+37 random-100-33.map 100 100 88 61 9 24 150.527
+37 random-100-33.map 100 100 0 95 61 60 150.669
+37 random-100-33.map 100 100 85 98 33 12 151.113
+37 random-100-33.map 100 100 5 18 97 52 149.355
+37 random-100-33.map 100 100 87 63 4 1 148.698
+37 random-100-33.map 100 100 51 95 7 0 148.456
+37 random-100-33.map 100 100 27 19 77 94 149.284
+37 random-100-33.map 100 100 2 18 76 61 149.627
+37 random-100-33.map 100 100 92 74 0 90 151.355
+38 random-100-33.map 100 100 10 30 99 69 155.113
+38 random-100-33.map 100 100 79 7 5 94 153.426
+38 random-100-33.map 100 100 92 95 34 13 155.456
+38 random-100-33.map 100 100 28 94 88 24 152.669
+38 random-100-33.map 100 100 72 94 17 14 155.527
+38 random-100-33.map 100 100 67 89 16 31 154.113
+38 random-100-33.map 100 100 10 18 76 68 154.042
+38 random-100-33.map 100 100 57 96 5 0 153.113
+38 random-100-33.map 100 100 77 76 23 29 153.042
+38 random-100-33.map 100 100 78 80 24 32 155.456
+39 random-100-33.map 100 100 79 70 11 5 156.941
+39 random-100-33.map 100 100 96 22 4 79 157.669
+39 random-100-33.map 100 100 33 14 92 95 156.284
+39 random-100-33.map 100 100 73 66 29 0 158.77
+39 random-100-33.map 100 100 87 70 4 28 156.456
+39 random-100-33.map 100 100 88 74 2 18 159.213
+39 random-100-33.map 100 100 4 82 98 20 158.669
+39 random-100-33.map 100 100 94 0 32 94 159.841
+39 random-100-33.map 100 100 86 11 6 94 157.426
+39 random-100-33.map 100 100 33 20 91 90 159.698
+40 random-100-33.map 100 100 71 93 2 2 163.113
+40 random-100-33.map 100 100 3 94 94 13 162.426
+40 random-100-33.map 100 100 29 12 94 99 163.941
+40 random-100-33.map 100 100 30 30 66 98 162.77
+40 random-100-33.map 100 100 10 14 82 95 162.355
+40 random-100-33.map 100 100 9 96 61 67 161.083
+40 random-100-33.map 100 100 13 88 99 24 160.669
+40 random-100-33.map 100 100 90 68 9 18 162.941
+40 random-100-33.map 100 100 16 90 94 7 160.012
+40 random-100-33.map 100 100 3 93 86 29 163.083
+41 random-100-33.map 100 100 31 27 85 84 166.698
+41 random-100-33.map 100 100 80 98 18 18 164.77
+41 random-100-33.map 100 100 34 6 98 98 165.941
+41 random-100-33.map 100 100 86 98 0 15 165.527
+41 random-100-33.map 100 100 4 0 97 76 164.698
+41 random-100-33.map 100 100 18 1 78 99 167.012
+41 random-100-33.map 100 100 14 0 68 94 167.941
+41 random-100-33.map 100 100 68 99 26 33 165.456
+41 random-100-33.map 100 100 33 29 82 84 164.527
+41 random-100-33.map 100 100 65 94 14 2 164.113
+42 random-100-33.map 100 100 87 97 27 28 171.527
+42 random-100-33.map 100 100 11 5 80 85 171.77
+42 random-100-33.map 100 100 19 95 96 3 169.426
+42 random-100-33.map 100 100 33 25 69 71 171.113
+42 random-100-33.map 100 100 9 7 85 95 171.941
+42 random-100-33.map 100 100 97 75 10 12 169.698
+42 random-100-33.map 100 100 37 5 97 88 168.113
+42 random-100-33.map 100 100 68 69 13 28 171.456
+42 random-100-33.map 100 100 19 32 80 88 168.941
+42 random-100-33.map 100 100 92 87 24 19 170.527
+43 random-100-33.map 100 100 93 19 10 98 172.912
+43 random-100-33.map 100 100 88 91 14 19 174.184
+43 random-100-33.map 100 100 83 99 30 30 172.77
+43 random-100-33.map 100 100 80 98 21 34 172.598
+43 random-100-33.map 100 100 25 3 92 90 173.941
+43 random-100-33.map 100 100 69 72 7 8 173.456
+43 random-100-33.map 100 100 25 23 95 97 173.355
+43 random-100-33.map 100 100 64 68 11 28 175.042
+43 random-100-33.map 100 100 87 93 25 30 173.284
+43 random-100-33.map 100 100 91 31 4 98 172.083
+44 random-100-33.map 100 100 32 29 88 96 177.527
+44 random-100-33.map 100 100 97 71 4 17 176.456
+44 random-100-33.map 100 100 88 90 25 30 176.113
+44 random-100-33.map 100 100 3 3 86 95 179.527
+44 random-100-33.map 100 100 94 90 22 19 176.113
+44 random-100-33.map 100 100 92 85 19 8 178.527
+44 random-100-33.map 100 100 27 1 91 88 178.355
+44 random-100-33.map 100 100 1 1 91 78 176.012
+44 random-100-33.map 100 100 93 89 21 2 178.355
+44 random-100-33.map 100 100 10 99 99 15 176.497
+45 random-100-33.map 100 100 95 82 30 22 181.527
+45 random-100-33.map 100 100 98 96 27 0 183.184
+45 random-100-33.map 100 100 4 2 65 66 181.87
+45 random-100-33.map 100 100 8 5 90 92 180.355
+45 random-100-33.map 100 100 13 0 67 71 183.184
+45 random-100-33.map 100 100 3 10 92 92 180.941
+45 random-100-33.map 100 100 18 1 93 96 180.184
+45 random-100-33.map 100 100 27 31 88 87 180.113
+45 random-100-33.map 100 100 96 97 1 12 180.184
+45 random-100-33.map 100 100 32 26 90 91 181.527
+46 random-100-33.map 100 100 18 17 96 81 187.941
+46 random-100-33.map 100 100 99 99 14 8 186.426
+46 random-100-33.map 100 100 21 11 97 80 184.941
+46 random-100-33.map 100 100 95 83 21 20 187.527
+46 random-100-33.map 100 100 90 81 18 19 185.355
+46 random-100-33.map 100 100 98 83 10 23 184.77
+46 random-100-33.map 100 100 21 30 97 98 185.598
+46 random-100-33.map 100 100 92 85 1 6 186.77
+46 random-100-33.map 100 100 19 20 99 90 184.527
+46 random-100-33.map 100 100 99 90 13 30 187.355
+47 random-100-33.map 100 100 15 28 93 81 191.77
+47 random-100-33.map 100 100 91 81 4 6 188.77
+47 random-100-33.map 100 100 1 7 96 86 188.184
+47 random-100-33.map 100 100 17 35 93 98 188.598
+47 random-100-33.map 100 100 17 35 95 96 190.941
+47 random-100-33.map 100 100 92 85 17 27 188.598
+47 random-100-33.map 100 100 0 0 94 89 191.77
+47 random-100-33.map 100 100 99 88 3 6 189.598
+47 random-100-33.map 100 100 5 4 96 85 188.184
+47 random-100-33.map 100 100 30 33 98 95 191.113
+48 random-100-33.map 100 100 1 9 98 82 194.184
+48 random-100-33.map 100 100 13 4 97 88 192.184
+48 random-100-33.map 100 100 11 7 95 87 194.184
+48 random-100-33.map 100 100 15 0 90 91 192.184
+48 random-100-33.map 100 100 97 86 17 26 193.012
+48 random-100-33.map 100 100 26 37 94 92 192.355
+48 random-100-33.map 100 100 98 82 22 29 193.77
+48 random-100-33.map 100 100 12 33 95 82 193.355
+48 random-100-33.map 100 100 99 87 17 25 195.598
+48 random-100-33.map 100 100 30 32 99 98 193.184
+49 random-100-33.map 100 100 97 83 33 31 198.77
+49 random-100-33.map 100 100 95 83 13 34 196.355
+49 random-100-33.map 100 100 94 81 19 34 196.77
+49 random-100-33.map 100 100 95 83 27 33 196.527
+49 random-100-33.map 100 100 26 35 97 86 196.184
+49 random-100-33.map 100 100 11 2 98 87 197.598
+49 random-100-33.map 100 100 93 79 13 34 196.355
+49 random-100-33.map 100 100 30 33 94 80 197.527
+49 random-100-33.map 100 100 24 32 99 80 199.184
+49 random-100-33.map 100 100 96 82 18 28 197.012
diff --git a/JPSPlusGoalBounding/Maps/room-100-10.map b/JPSPlusGoalBounding/Maps/room-100-10.map
new file mode 100644
index 0000000..4694f40
--- /dev/null
+++ b/JPSPlusGoalBounding/Maps/room-100-10.map
@@ -0,0 +1,104 @@
+type octile
+height 100
+width 100
+map
+@@@@@@@@@.@@@@@@@.@@@@@@@@@@.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@@@@.@@@@@.@@@@@@@@@@@@@@
+@.........@.........@.........@.........@.........@.........@...................@.........@.........
+@.........@.........@.........@.........@.........@...................@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+..........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@...................@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@...................@.........@.........@.........@.........@.........@...................@.........
+@.........@...................@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@...................
+@@@@@@@@@@@@@@@@.@@@@@@@.@@@@@@@@@.@@@@@@@@.@@@@@@@@@@@@@@@.@@@@@@@@@.@@@@@@@@.@@@@@@.@@@@@@@@@@.@@@
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@...................@.........@...................@...................@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@...................@.........@.........@.........@.........@.........@...................
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+..........@.........@.........@.........@...................@.........@...................@.........
+@@@@@@@@@@@@@@@.@@@@@@@@@@@@.@@@@@@.@@@@@@@@@@@@.@@@@@@@.@@@@@@.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.@@
+@.........@.........@.........@.........@.........@.........@...................@.........@.........
+@.........@.........@.........@.........@.........@...................@.........@.........@.........
+@.........@.........@.........@.........@...................@.........@.........@.........@.........
+..........@.........@.........@.........@.........@.........@.........@.........@...................
+@.........@.........@.........@...................@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@...................@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@@@@@.@@@@@@@.@@@@@@@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@@@@@.@@@@@@@@@@@@.@@@@@@.@@@@@@@@.@@@@@@@.@@@@@@@
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@...................@.........@.........@...................@.........@.........@.........
+..........@.........@.........@.........@.........@.........@.........@...................@.........
+@...................@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@...................@.........@.........@...................@.........@.........
+@@@.@@@@@@@@.@@@@@@@@@@@@@@@.@@@@@@@@@.@@@@@@@@@.@@@@.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@@@.@@@
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@...................@.........@.........@.........@...................@.........@.........@.........
+@.........@.........@.........@.........@...................@.........@...................@.........
+@.........@.........@.........@...................@.........@.........@.........@...................
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+..........@...................@.........@.........@.........@.........@.........@.........@.........
+@.@@@@@@@@@@@.@@@@@@@@@@.@@@@@@@.@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@.@@@@@@@@.@@@@@@@@@.@@@@@@@@@@@@.@@@
+..........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@...................@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@...................@.........@...................@.........@.........
+@.........@.........@...................@.........@.........@.........@.........@...................
+@...................@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@...................@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@@.@@@@@@@@@@@@.@@@@@@@@@.@@@@@@@.@@@@@@@@@@@@@@@@@@@@@@.@@@@@@@@@@@@.@@@@@@@@.@@.@@@@@@@@@.@@@@@@@@
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@...................@.........@...................@.........@.........@.........
+@...................@.........@.........@.........@.........@...................@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@...................@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@...................
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+..........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@...................@.........@.........@.........@.........
+@@@@@@@.@@@@@@@@@@@@@@@@@@@.@@@@@@@.@@@@@@@@@@@@@.@@@.@@@@@@@@.@@@@@@@@@@@@.@@@@@@@@.@@@@@@.@@@@@@@@
+@.........@.........@.........@...................@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@...................@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@...................@.........@.........@.........@.........
+@.........@.........@...................@.........@...................@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@...................
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@@@@.@@@@@@@@@@@@@@.@@@@@@@@@.@@@@@.@@@@@@@.@@@@@@@@@@@.@@@@@@@@@@@@@@@@@@@@.@@@@@@@@.@@@@@@@@@@.@@@
+@.........@.........@.............................@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@...................@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@...................
+@.........@.........@.........@.........@.........@.........@...................@.........@.........
+@.........@.........@.........@.........@...................@.........@.........@.........@.........
+....................@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@...................@.........@.........@.........@.........@.........@.........@.........
+@@@@@@.@@@@@@@@.@@@@@@@@@@@@@.@.@@@@@@@@@@@@@@@@.@@@@@.@@@@@@@.@@@@@@@@.@@@@@@@@@@@@@@@@@.@@.@@@@@@@
+@.........@...................@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@...................@.........@.........@.........@.........@.........
+..........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@.........@.........@.........
+@.........@.........@...................@.........@.........@.........@.........@.........@.........
+@...................@.........@.........@.........@...................@.........@.........@.........
+@.........@.........@.........@.........@.........@.........@.........@...................@.........
+@.........@.........@.........@.........@...................@.........@.........@.........@.........
diff --git a/JPSPlusGoalBounding/Maps/room-100-10.map.pre b/JPSPlusGoalBounding/Maps/room-100-10.map.pre
new file mode 100644
index 0000000..4ea4c9d
Binary files /dev/null and b/JPSPlusGoalBounding/Maps/room-100-10.map.pre differ
diff --git a/JPSPlusGoalBounding/Maps/room-100-10.map.scen b/JPSPlusGoalBounding/Maps/room-100-10.map.scen
new file mode 100644
index 0000000..2bf37b8
--- /dev/null
+++ b/JPSPlusGoalBounding/Maps/room-100-10.map.scen
@@ -0,0 +1,421 @@
+version 1
+1 room-100-10.map 100 100 91 28 95 23 6.65685
+1 room-100-10.map 100 100 94 92 98 93 4.41421
+1 room-100-10.map 100 100 73 92 74 88 7.82843
+1 room-100-10.map 100 100 46 8 42 6 4.82843
+1 room-100-10.map 100 100 78 19 74 14 6.65685
+1 room-100-10.map 100 100 54 75 53 70 5.41421
+1 room-100-10.map 100 100 32 39 38 38 6.41421
+1 room-100-10.map 100 100 14 72 19 74 5.82843
+1 room-100-10.map 100 100 78 36 75 31 6.24264
+1 room-100-10.map 100 100 14 57 17 62 6.82843
+2 room-100-10.map 100 100 26 43 25 51 9.82843
+2 room-100-10.map 100 100 79 82 74 74 11.2426
+2 room-100-10.map 100 100 60 42 69 47 11.0711
+2 room-100-10.map 100 100 15 14 19 22 11.4142
+2 room-100-10.map 100 100 95 86 95 92 9.65685
+2 room-100-10.map 100 100 3 43 13 41 10.8284
+2 room-100-10.map 100 100 38 75 31 82 11.6569
+2 room-100-10.map 100 100 36 84 42 78 11.6569
+2 room-100-10.map 100 100 76 67 75 78 11.4142
+2 room-100-10.map 100 100 88 38 87 42 9.82843
+3 room-100-10.map 100 100 82 99 71 96 12.2426
+3 room-100-10.map 100 100 41 41 53 39 15.6569
+3 room-100-10.map 100 100 12 64 1 57 15.6569
+3 room-100-10.map 100 100 14 25 17 12 14.2426
+3 room-100-10.map 100 100 25 60 34 52 12.8995
+3 room-100-10.map 100 100 32 74 31 87 15.8995
+3 room-100-10.map 100 100 54 18 58 8 12.4853
+3 room-100-10.map 100 100 68 88 78 82 13.6569
+3 room-100-10.map 100 100 49 70 57 78 14.8284
+3 room-100-10.map 100 100 52 25 54 39 15.6569
+4 room-100-10.map 100 100 56 64 49 62 16.0711
+4 room-100-10.map 100 100 92 41 91 29 18.6569
+4 room-100-10.map 100 100 31 83 17 89 19.3137
+4 room-100-10.map 100 100 72 37 84 29 17.6569
+4 room-100-10.map 100 100 16 92 26 83 17.4853
+4 room-100-10.map 100 100 40 25 58 23 18.8284
+4 room-100-10.map 100 100 77 36 67 33 16.0711
+4 room-100-10.map 100 100 62 87 78 84 17.2426
+4 room-100-10.map 100 100 67 13 72 5 19.2426
+4 room-100-10.map 100 100 52 37 59 22 17.8995
+5 room-100-10.map 100 100 39 69 29 57 21.3137
+5 room-100-10.map 100 100 52 38 54 58 20.8284
+5 room-100-10.map 100 100 5 64 2 81 21.0711
+5 room-100-10.map 100 100 18 25 26 13 20.7279
+5 room-100-10.map 100 100 55 81 68 69 23.2426
+5 room-100-10.map 100 100 44 87 31 75 20.8995
+5 room-100-10.map 100 100 27 91 37 76 23.8284
+5 room-100-10.map 100 100 82 41 96 36 21.4853
+5 room-100-10.map 100 100 24 54 44 56 21.6569
+5 room-100-10.map 100 100 19 83 26 94 21.8995
+6 room-100-10.map 100 100 98 62 78 59 27.4853
+6 room-100-10.map 100 100 44 79 55 58 27.5563
+6 room-100-10.map 100 100 14 47 5 65 26.8995
+6 room-100-10.map 100 100 63 48 58 68 26.3137
+6 room-100-10.map 100 100 28 38 19 25 27.5563
+6 room-100-10.map 100 100 98 71 85 87 24.3137
+6 room-100-10.map 100 100 86 53 78 55 26.4853
+6 room-100-10.map 100 100 45 83 24 72 26.7279
+6 room-100-10.map 100 100 99 67 96 84 25.8995
+6 room-100-10.map 100 100 39 74 28 59 27.3137
+7 room-100-10.map 100 100 26 81 31 58 31.8995
+7 room-100-10.map 100 100 34 86 53 95 31.799
+7 room-100-10.map 100 100 42 79 56 57 28.9706
+7 room-100-10.map 100 100 49 87 64 89 29.7279
+7 room-100-10.map 100 100 2 54 22 47 28.0711
+7 room-100-10.map 100 100 1 22 1 47 28.3137
+7 room-100-10.map 100 100 27 96 45 83 29.1421
+7 room-100-10.map 100 100 81 26 73 47 29.7279
+7 room-100-10.map 100 100 42 41 57 24 31.3137
+7 room-100-10.map 100 100 21 16 10 37 28.4853
+8 room-100-10.map 100 100 88 82 65 77 32.9706
+8 room-100-10.map 100 100 53 48 73 67 33.1421
+8 room-100-10.map 100 100 68 38 69 7 35.5563
+8 room-100-10.map 100 100 74 53 96 68 32.3137
+8 room-100-10.map 100 100 46 35 57 61 32.3137
+8 room-100-10.map 100 100 34 86 41 68 33.9706
+8 room-100-10.map 100 100 27 74 12 96 33.3848
+8 room-100-10.map 100 100 73 22 91 45 33.9706
+8 room-100-10.map 100 100 21 24 12 27 34.1421
+8 room-100-10.map 100 100 68 7 66 34 32.799
+9 room-100-10.map 100 100 15 48 48 59 39.5563
+9 room-100-10.map 100 100 36 83 7 95 39.6274
+9 room-100-10.map 100 100 95 28 86 56 39.1421
+9 room-100-10.map 100 100 17 33 31 56 36.799
+9 room-100-10.map 100 100 66 61 44 45 38.7279
+9 room-100-10.map 100 100 91 79 69 59 36.1421
+9 room-100-10.map 100 100 92 27 74 23 37.799
+9 room-100-10.map 100 100 95 19 83 45 36.7279
+9 room-100-10.map 100 100 79 26 71 44 36.3848
+9 room-100-10.map 100 100 83 85 54 75 39.6274
+10 room-100-10.map 100 100 22 58 14 26 41.5563
+10 room-100-10.map 100 100 37 48 18 53 41.3137
+10 room-100-10.map 100 100 65 48 58 17 42.1421
+10 room-100-10.map 100 100 97 71 68 53 42.3137
+10 room-100-10.map 100 100 6 34 25 22 42.5563
+10 room-100-10.map 100 100 44 29 64 3 40.3848
+10 room-100-10.map 100 100 35 58 57 32 42.9706
+10 room-100-10.map 100 100 47 36 19 33 43.7279
+10 room-100-10.map 100 100 82 54 66 32 41.5563
+10 room-100-10.map 100 100 97 1 65 7 43.4558
+11 room-100-10.map 100 100 68 88 43 77 45.2132
+11 room-100-10.map 100 100 65 62 31 83 46.2132
+11 room-100-10.map 100 100 83 96 61 73 47.8701
+11 room-100-10.map 100 100 53 22 88 32 47.3848
+11 room-100-10.map 100 100 68 82 81 52 45.1421
+11 room-100-10.map 100 100 97 27 95 63 46.3848
+11 room-100-10.map 100 100 65 27 49 57 46.9706
+11 room-100-10.map 100 100 76 59 87 97 46.5563
+11 room-100-10.map 100 100 5 53 23 67 45.3137
+11 room-100-10.map 100 100 59 52 87 77 47.1421
+12 room-100-10.map 100 100 7 99 44 84 48.0416
+12 room-100-10.map 100 100 48 58 8 44 50.0416
+12 room-100-10.map 100 100 64 17 81 49 48.2132
+12 room-100-10.map 100 100 81 84 45 93 51.3848
+12 room-100-10.map 100 100 39 24 33 57 49.6274
+12 room-100-10.map 100 100 56 61 79 38 49.4558
+12 room-100-10.map 100 100 38 81 3 72 50.6274
+12 room-100-10.map 100 100 48 96 75 97 48.9706
+12 room-100-10.map 100 100 66 76 97 48 49.0416
+12 room-100-10.map 100 100 43 67 22 54 48.1421
+13 room-100-10.map 100 100 54 67 88 39 52.0416
+13 room-100-10.map 100 100 94 52 99 4 54.799
+13 room-100-10.map 100 100 5 72 3 25 53.3848
+13 room-100-10.map 100 100 27 33 65 39 53.799
+13 room-100-10.map 100 100 29 52 58 85 53.2132
+13 room-100-10.map 100 100 32 32 9 61 52.9706
+13 room-100-10.map 100 100 15 78 51 76 52.9706
+13 room-100-10.map 100 100 59 82 49 48 53.5563
+13 room-100-10.map 100 100 62 59 94 87 52.9706
+13 room-100-10.map 100 100 7 58 14 11 52.7279
+14 room-100-10.map 100 100 21 59 63 38 57.8701
+14 room-100-10.map 100 100 34 41 67 71 58.5563
+14 room-100-10.map 100 100 36 79 9 45 57.6274
+14 room-100-10.map 100 100 93 22 85 71 57.3848
+14 room-100-10.map 100 100 83 51 54 17 57.6274
+14 room-100-10.map 100 100 81 29 56 66 59.2132
+14 room-100-10.map 100 100 66 36 51 78 57.3848
+14 room-100-10.map 100 100 46 48 2 49 58.6985
+14 room-100-10.map 100 100 33 60 56 18 59.9706
+14 room-100-10.map 100 100 57 55 22 86 56.0416
+15 room-100-10.map 100 100 75 76 41 39 62.2132
+15 room-100-10.map 100 100 55 91 42 45 63.3848
+15 room-100-10.map 100 100 88 46 48 34 61.6985
+15 room-100-10.map 100 100 26 43 61 25 61.9706
+15 room-100-10.map 100 100 79 21 92 7 62.1127
+15 room-100-10.map 100 100 27 85 8 57 60.6985
+15 room-100-10.map 100 100 93 14 47 8 60.2843
+15 room-100-10.map 100 100 93 89 55 58 60.799
+15 room-100-10.map 100 100 92 35 63 17 60.6985
+15 room-100-10.map 100 100 59 48 82 22 60.1127
+16 room-100-10.map 100 100 54 95 97 61 67.8701
+16 room-100-10.map 100 100 93 92 69 48 66.8701
+16 room-100-10.map 100 100 28 64 79 68 66.4558
+16 room-100-10.map 100 100 79 78 94 28 67.5269
+16 room-100-10.map 100 100 24 35 53 77 66.1127
+16 room-100-10.map 100 100 81 25 41 35 65.9411
+16 room-100-10.map 100 100 39 12 27 36 65.6985
+16 room-100-10.map 100 100 12 42 46 65 64.4558
+16 room-100-10.map 100 100 27 35 65 15 67.2132
+16 room-100-10.map 100 100 57 71 38 29 65.0416
+17 room-100-10.map 100 100 56 38 78 88 68.0416
+17 room-100-10.map 100 100 25 47 79 69 71.6985
+17 room-100-10.map 100 100 38 64 74 37 70.1127
+17 room-100-10.map 100 100 37 47 27 4 71.8701
+17 room-100-10.map 100 100 1 25 38 72 69.3553
+17 room-100-10.map 100 100 49 75 35 22 68.6985
+17 room-100-10.map 100 100 31 81 75 97 71.1127
+17 room-100-10.map 100 100 38 82 96 65 69.0416
+17 room-100-10.map 100 100 31 17 75 51 71.9411
+17 room-100-10.map 100 100 69 22 24 48 71.0416
+18 room-100-10.map 100 100 56 36 5 52 73.2843
+18 room-100-10.map 100 100 56 85 16 54 75.2843
+18 room-100-10.map 100 100 51 86 69 26 75.6985
+18 room-100-10.map 100 100 43 17 17 38 73.7696
+18 room-100-10.map 100 100 11 69 57 49 73.799
+18 room-100-10.map 100 100 6 39 16 97 72.8701
+18 room-100-10.map 100 100 72 61 13 43 74.6985
+18 room-100-10.map 100 100 97 69 47 36 72.4558
+18 room-100-10.map 100 100 81 28 92 93 74.9706
+18 room-100-10.map 100 100 5 38 52 65 75.3553
+19 room-100-10.map 100 100 44 76 71 25 79.1127
+19 room-100-10.map 100 100 31 43 4 97 77.2843
+19 room-100-10.map 100 100 53 96 88 37 79.9411
+19 room-100-10.map 100 100 14 96 47 41 79.9411
+19 room-100-10.map 100 100 98 97 47 63 78.598
+19 room-100-10.map 100 100 49 44 11 89 77.2843
+19 room-100-10.map 100 100 23 36 17 98 79.1127
+19 room-100-10.map 100 100 38 16 51 78 76.3553
+19 room-100-10.map 100 100 85 64 36 21 79.9411
+19 room-100-10.map 100 100 4 26 53 28 76.4558
+20 room-100-10.map 100 100 39 91 88 47 82.1127
+20 room-100-10.map 100 100 63 21 95 81 83.6985
+20 room-100-10.map 100 100 63 89 72 26 82.7696
+20 room-100-10.map 100 100 91 45 44 96 83.598
+20 room-100-10.map 100 100 99 88 99 15 82.9411
+20 room-100-10.map 100 100 9 25 34 89 81.0416
+20 room-100-10.map 100 100 77 72 19 73 83.0416
+20 room-100-10.map 100 100 52 16 13 45 81.6985
+20 room-100-10.map 100 100 25 95 46 31 82.6985
+20 room-100-10.map 100 100 19 23 43 81 81.9411
+21 room-100-10.map 100 100 72 71 37 14 84.5269
+21 room-100-10.map 100 100 86 75 93 3 85.2843
+21 room-100-10.map 100 100 83 61 15 86 85.1838
+21 room-100-10.map 100 100 75 98 55 32 85.3553
+21 room-100-10.map 100 100 63 22 91 86 87.1127
+21 room-100-10.map 100 100 43 25 9 62 86.9411
+21 room-100-10.map 100 100 61 55 78 15 84.9411
+21 room-100-10.map 100 100 72 79 33 28 84.2843
+21 room-100-10.map 100 100 79 55 39 7 86.5269
+21 room-100-10.map 100 100 67 62 9 25 87.0416
+22 room-100-10.map 100 100 92 14 54 71 88.8406
+22 room-100-10.map 100 100 77 67 5 96 90.3553
+22 room-100-10.map 100 100 65 78 2 36 90.9411
+22 room-100-10.map 100 100 71 1 79 63 88.2843
+22 room-100-10.map 100 100 78 22 44 83 90.3553
+22 room-100-10.map 100 100 94 46 24 46 88.7696
+22 room-100-10.map 100 100 68 7 24 69 91.598
+22 room-100-10.map 100 100 64 57 2 72 91.8701
+22 room-100-10.map 100 100 87 76 52 12 89.7696
+22 room-100-10.map 100 100 76 54 0 49 90.0122
+23 room-100-10.map 100 100 4 35 77 29 94.9411
+23 room-100-10.map 100 100 58 14 98 75 93.5269
+23 room-100-10.map 100 100 22 96 99 81 93.9411
+23 room-100-10.map 100 100 89 28 47 94 92.1838
+23 room-100-10.map 100 100 79 56 5 87 95.1838
+23 room-100-10.map 100 100 59 67 89 9 92.2843
+23 room-100-10.map 100 100 8 59 76 35 94.7696
+23 room-100-10.map 100 100 75 19 33 49 95.8406
+23 room-100-10.map 100 100 61 47 13 72 94.2548
+23 room-100-10.map 100 100 15 42 81 75 95.7696
+24 room-100-10.map 100 100 7 11 44 82 98.7696
+24 room-100-10.map 100 100 35 1 95 27 96.4264
+24 room-100-10.map 100 100 92 28 24 50 96.669
+24 room-100-10.map 100 100 62 96 99 24 98.6985
+24 room-100-10.map 100 100 62 1 87 76 98.5269
+24 room-100-10.map 100 100 18 31 62 98 99.669
+24 room-100-10.map 100 100 33 57 96 97 97.7696
+24 room-100-10.map 100 100 74 95 3 85 99.4264
+24 room-100-10.map 100 100 13 54 93 68 98.8701
+24 room-100-10.map 100 100 67 2 45 81 98.0122
+25 room-100-10.map 100 100 31 89 91 25 103.154
+25 room-100-10.map 100 100 57 5 45 92 100.113
+25 room-100-10.map 100 100 88 39 22 95 103.497
+25 room-100-10.map 100 100 93 81 27 48 101.77
+25 room-100-10.map 100 100 36 8 87 72 101.426
+25 room-100-10.map 100 100 88 17 88 98 102.113
+25 room-100-10.map 100 100 68 4 48 89 101.184
+25 room-100-10.map 100 100 30 81 92 31 103.255
+25 room-100-10.map 100 100 6 87 82 74 100.012
+25 room-100-10.map 100 100 46 88 37 8 101.426
+26 room-100-10.map 100 100 65 54 29 27 106.113
+26 room-100-10.map 100 100 25 38 71 18 107.255
+26 room-100-10.map 100 100 92 47 9 43 104.255
+26 room-100-10.map 100 100 9 22 59 93 106.012
+26 room-100-10.map 100 100 35 13 26 96 107.012
+26 room-100-10.map 100 100 9 65 81 36 107.77
+26 room-100-10.map 100 100 42 83 98 12 105.912
+26 room-100-10.map 100 100 15 74 76 41 104.669
+26 room-100-10.map 100 100 1 62 75 78 107.355
+26 room-100-10.map 100 100 17 91 4 13 106.355
+27 room-100-10.map 100 100 78 48 21 12 110.941
+27 room-100-10.map 100 100 38 3 26 88 111.083
+27 room-100-10.map 100 100 11 51 94 23 110.841
+27 room-100-10.map 100 100 79 1 34 75 110.355
+27 room-100-10.map 100 100 41 15 24 9 109.326
+27 room-100-10.map 100 100 14 98 52 21 110.012
+27 room-100-10.map 100 100 16 89 21 1 110.113
+27 room-100-10.map 100 100 81 99 26 37 110.841
+27 room-100-10.map 100 100 94 94 34 26 111.841
+27 room-100-10.map 100 100 78 58 27 11 111.841
+28 room-100-10.map 100 100 82 5 11 37 115.426
+28 room-100-10.map 100 100 38 11 23 97 112.497
+28 room-100-10.map 100 100 22 24 62 25 112.598
+28 room-100-10.map 100 100 21 14 11 78 112.184
+28 room-100-10.map 100 100 76 98 14 41 114.497
+28 room-100-10.map 100 100 23 84 54 2 112.012
+28 room-100-10.map 100 100 41 1 18 65 113.326
+28 room-100-10.map 100 100 49 1 18 15 112.397
+28 room-100-10.map 100 100 63 92 63 4 115.941
+28 room-100-10.map 100 100 78 46 2 72 112.184
+29 room-100-10.map 100 100 8 87 47 12 116.569
+29 room-100-10.map 100 100 88 24 13 65 118.669
+29 room-100-10.map 100 100 91 38 15 86 118.569
+29 room-100-10.map 100 100 95 5 67 97 117.841
+29 room-100-10.map 100 100 22 24 36 98 118.184
+29 room-100-10.map 100 100 88 82 4 35 118.841
+29 room-100-10.map 100 100 31 87 99 14 116.397
+29 room-100-10.map 100 100 37 4 9 68 116.426
+29 room-100-10.map 100 100 2 17 76 64 118.255
+29 room-100-10.map 100 100 62 13 18 95 119.941
+30 room-100-10.map 100 100 86 29 15 76 122.326
+30 room-100-10.map 100 100 24 23 65 75 120.598
+30 room-100-10.map 100 100 7 64 78 95 122.326
+30 room-100-10.map 100 100 12 92 41 9 120.811
+30 room-100-10.map 100 100 77 96 6 65 121.154
+30 room-100-10.map 100 100 13 8 84 48 123.426
+30 room-100-10.map 100 100 72 86 1 28 121.326
+30 room-100-10.map 100 100 59 91 79 11 123.012
+30 room-100-10.map 100 100 22 22 34 5 122.841
+30 room-100-10.map 100 100 98 27 6 21 123.74
+31 room-100-10.map 100 100 98 2 14 34 126.083
+31 room-100-10.map 100 100 87 14 13 28 125.497
+31 room-100-10.map 100 100 45 7 16 97 124.64
+31 room-100-10.map 100 100 61 91 71 8 127.184
+31 room-100-10.map 100 100 97 86 15 61 124.598
+31 room-100-10.map 100 100 92 82 9 28 124.841
+31 room-100-10.map 100 100 18 82 95 22 126.397
+31 room-100-10.map 100 100 8 6 53 3 124.426
+31 room-100-10.map 100 100 79 0 6 51 127.012
+31 room-100-10.map 100 100 26 11 86 66 124.255
+32 room-100-10.map 100 100 4 64 81 95 130.811
+32 room-100-10.map 100 100 21 9 85 57 131.598
+32 room-100-10.map 100 100 89 88 8 22 129.083
+32 room-100-10.map 100 100 73 84 25 14 129.497
+32 room-100-10.map 100 100 12 79 77 26 130.326
+32 room-100-10.map 100 100 3 76 32 1 129.497
+32 room-100-10.map 100 100 95 21 15 95 129.397
+32 room-100-10.map 100 100 7 87 66 6 131.983
+32 room-100-10.map 100 100 72 15 17 23 129.569
+32 room-100-10.map 100 100 86 23 14 72 130.983
+33 room-100-10.map 100 100 96 93 1 47 134.74
+33 room-100-10.map 100 100 9 51 85 6 133.669
+33 room-100-10.map 100 100 21 24 81 29 132.497
+33 room-100-10.map 100 100 15 4 76 86 134.012
+33 room-100-10.map 100 100 8 84 96 22 134.225
+33 room-100-10.map 100 100 7 77 94 37 135.468
+33 room-100-10.map 100 100 94 23 6 83 133.64
+33 room-100-10.map 100 100 24 17 87 84 135.255
+33 room-100-10.map 100 100 87 65 5 6 132.598
+33 room-100-10.map 100 100 72 9 19 69 132.841
+34 room-100-10.map 100 100 37 94 82 1 138.912
+34 room-100-10.map 100 100 62 94 23 26 137.811
+34 room-100-10.map 100 100 67 5 7 82 136.397
+34 room-100-10.map 100 100 6 17 98 67 138.669
+34 room-100-10.map 100 100 87 57 5 19 136.083
+34 room-100-10.map 100 100 68 6 5 96 138.397
+34 room-100-10.map 100 100 67 98 25 22 137.154
+34 room-100-10.map 100 100 94 24 13 72 136.64
+34 room-100-10.map 100 100 17 69 96 93 139.426
+34 room-100-10.map 100 100 25 26 84 58 136.255
+35 room-100-10.map 100 100 99 77 24 19 140.497
+35 room-100-10.map 100 100 87 17 15 84 140.882
+35 room-100-10.map 100 100 3 89 98 17 143.468
+35 room-100-10.map 100 100 25 88 72 19 143.64
+35 room-100-10.map 100 100 19 7 99 72 142.012
+35 room-100-10.map 100 100 12 66 84 11 141.326
+35 room-100-10.map 100 100 9 6 92 77 142.912
+35 room-100-10.map 100 100 19 17 96 6 141.154
+35 room-100-10.map 100 100 97 15 13 5 142.569
+35 room-100-10.map 100 100 96 2 2 22 143.397
+36 room-100-10.map 100 100 7 4 80 7 145.74
+36 room-100-10.map 100 100 97 28 23 27 146.054
+36 room-100-10.map 100 100 24 18 95 88 144.74
+36 room-100-10.map 100 100 2 47 92 2 144.64
+36 room-100-10.map 100 100 95 79 24 22 147.74
+36 room-100-10.map 100 100 94 12 4 88 147.882
+36 room-100-10.map 100 100 2 69 91 19 146.74
+36 room-100-10.map 100 100 4 11 73 12 146.569
+36 room-100-10.map 100 100 18 12 85 18 144.397
+36 room-100-10.map 100 100 18 3 97 81 147.912
+37 room-100-10.map 100 100 81 8 18 79 149.397
+37 room-100-10.map 100 100 22 9 76 98 151.569
+37 room-100-10.map 100 100 93 17 1 82 149.125
+37 room-100-10.map 100 100 86 86 3 4 150.74
+37 room-100-10.map 100 100 15 3 72 98 149.497
+37 room-100-10.map 100 100 87 13 8 84 151.296
+37 room-100-10.map 100 100 61 83 22 1 148.74
+37 room-100-10.map 100 100 83 89 28 2 150.569
+37 room-100-10.map 100 100 22 21 87 86 148.912
+37 room-100-10.map 100 100 78 12 6 5 148.154
+38 room-100-10.map 100 100 5 72 88 18 153.811
+38 room-100-10.map 100 100 9 87 97 2 152.054
+38 room-100-10.map 100 100 89 14 3 18 153.882
+38 room-100-10.map 100 100 72 11 25 28 155.983
+38 room-100-10.map 100 100 23 29 99 33 153.054
+38 room-100-10.map 100 100 87 7 3 72 153.326
+38 room-100-10.map 100 100 7 2 76 95 155.983
+38 room-100-10.map 100 100 77 14 9 0 153.74
+38 room-100-10.map 100 100 5 3 76 95 155.811
+38 room-100-10.map 100 100 14 4 87 96 153.569
+39 room-100-10.map 100 100 5 79 95 6 159.125
+39 room-100-10.map 100 100 96 9 21 25 158.64
+39 room-100-10.map 100 100 72 18 4 6 158.225
+39 room-100-10.map 100 100 88 9 4 85 158.468
+39 room-100-10.map 100 100 83 91 4 19 157.225
+39 room-100-10.map 100 100 28 21 93 97 159.326
+39 room-100-10.map 100 100 17 4 96 93 156.912
+39 room-100-10.map 100 100 27 8 83 96 159.054
+39 room-100-10.map 100 100 25 26 96 87 157.983
+39 room-100-10.map 100 100 88 6 15 76 159.468
+40 room-100-10.map 100 100 7 93 74 14 162.125
+40 room-100-10.map 100 100 3 79 92 5 161.368
+40 room-100-10.map 100 100 6 99 77 17 163.711
+40 room-100-10.map 100 100 79 18 14 74 161.125
+40 room-100-10.map 100 100 8 97 75 16 160.711
+40 room-100-10.map 100 100 74 19 17 97 160.296
+40 room-100-10.map 100 100 27 25 91 4 161.468
+40 room-100-10.map 100 100 95 2 6 74 162.397
+40 room-100-10.map 100 100 94 3 25 23 160.64
+40 room-100-10.map 100 100 81 14 3 76 161.64
+41 room-100-10.map 100 100 94 3 23 28 165.882
+41 room-100-10.map 100 100 91 97 7 4 164.74
+41 room-100-10.map 100 100 3 9 98 92 167.74
+41 room-100-10.map 100 100 99 1 26 25 164.054
+41 room-100-10.map 100 100 87 4 1 93 167.125
+41 room-100-10.map 100 100 88 4 4 93 165.125
+41 room-100-10.map 100 100 7 99 72 19 166.782
+41 room-100-10.map 100 100 94 1 7 79 166.539
+41 room-100-10.map 100 100 91 3 2 71 164.64
+41 room-100-10.map 100 100 7 1 95 2 165.811
+42 room-100-10.map 100 100 22 24 99 98 170.054
+42 room-100-10.map 100 100 98 99 28 4 169.468
+42 room-100-10.map 100 100 0 4 92 97 170.74
+42 room-100-10.map 100 100 91 1 2 8 169.054
+42 room-100-10.map 100 100 2 6 98 92 168.326
+42 room-100-10.map 100 100 22 26 99 98 170.882
+42 room-100-10.map 100 100 5 2 98 99 171.64
+42 room-100-10.map 100 100 23 24 98 98 168.64
+42 room-100-10.map 100 100 97 96 1 7 169.569
+42 room-100-10.map 100 100 88 4 1 96 169.368
diff --git a/JPSPlusGoalBounding/PathfindingNode.h b/JPSPlusGoalBounding/PathfindingNode.h
new file mode 100644
index 0000000..1a3f156
--- /dev/null
+++ b/JPSPlusGoalBounding/PathfindingNode.h
@@ -0,0 +1,82 @@
+/*
+ * PathfindingNode.h
+ *
+ * Copyright (c) 2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "stdafx.h"
+
+struct PathfindingNode
+{
+public:
+ PathfindingNode* m_parent;
+ short m_row, m_col;
+ unsigned int m_givenCost;
+ unsigned int m_finalCost;
+ unsigned int m_iteration;
+ unsigned char m_directionFromParent;
+
+ enum PathfindingNodeStatus
+ {
+ OnNone,
+ OnOpen,
+ OnClosed
+ };
+
+ unsigned char m_listStatus;
+};
+
+struct DijkstraPathfindingNode
+{
+public:
+ DijkstraPathfindingNode* m_parent;
+ short m_row, m_col;
+ unsigned int m_givenCost;
+ unsigned int m_iteration;
+ unsigned char m_directionFromStart;
+ unsigned char m_directionFromParent;
+ unsigned char m_blockedDirectionBitfield; // highest bit [DownLeft, Left, UpLeft, Up, UpRight, Right, DownRight, Down] lowest bit
+
+ enum PathfindingNodeStatus
+ {
+ OnNone,
+ OnOpen,
+ OnClosed
+ };
+
+ unsigned char m_listStatus;
+};
diff --git a/JPSPlusGoalBounding/PrecomputeMap.cpp b/JPSPlusGoalBounding/PrecomputeMap.cpp
new file mode 100644
index 0000000..b9c2059
--- /dev/null
+++ b/JPSPlusGoalBounding/PrecomputeMap.cpp
@@ -0,0 +1,691 @@
+/*
+ * PrecomputeMap.cpp
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "PrecomputeMap.h"
+#include "DijkstraFloodfill.h"
+#include "JPSPlus.h"
+#include
+
+using std::ifstream;
+using std::ofstream;
+
+//#define FILE_FORMAT_ASCII
+#define INVALID_GOAL_BOUNDS -1
+
+PrecomputeMap::PrecomputeMap(int width, int height, std::vector map)
+: m_mapCreated(false), m_width(width), m_height(height), m_map(map)
+{
+}
+
+PrecomputeMap::~PrecomputeMap()
+{
+}
+
+DistantJumpPoints** PrecomputeMap::CalculateMap()
+{
+ m_mapCreated = true;
+
+ InitArray(m_jumpPointMap, m_width, m_height);
+ CalculateJumpPointMap();
+
+ InitArray(m_distantJumpPointMap, m_width, m_height);
+ CalculateDistantJumpPointMap();
+
+ // Destroy the m_jumpPointMap since it isn't needed for the search
+ DestroyArray(m_jumpPointMap);
+
+ // Calculate Goal Bounds
+ //CalculateGoalBoundingDEPRECATED();
+ CalculateGoalBounding();
+
+ return m_distantJumpPointMap;
+}
+
+void PrecomputeMap::SaveMap(const char *filename)
+{
+#ifdef FILE_FORMAT_ASCII
+ ofstream file(filename);
+
+ for (int r = 0; r < m_height; r++)
+ {
+ for (int c = 0; c < m_width; c++)
+ {
+ DistantJumpPoints* jumpPoints = &m_distantJumpPointMap[r][c];
+
+ for (int i = 0; i < 8; i++)
+ {
+ file << (int)jumpPoints->jumpDistance[i] << "\t";
+ }
+ for (int dir = 0; dir < 8; dir++)
+ {
+ for (int minMaxIndex = 0; minMaxIndex < 4; minMaxIndex++)
+ {
+ file << (int)m_goalBoundsMap[r][c].bounds[dir][minMaxIndex] << "\t";
+ }
+ }
+ file << std::endl;
+ }
+ file << std::endl;
+ }
+#else
+ ofstream file(filename, std::ios::out | std::ios::binary);
+
+ for (int r = 0; r < m_height; r++)
+ {
+ for (int c = 0; c < m_width; c++)
+ {
+ if (IsWall(r, c))
+ {
+ // Don't save data if a wall
+ continue;
+ }
+
+ // Save Jump Distances
+ DistantJumpPoints* jumpPoints = &m_distantJumpPointMap[r][c];
+
+ for (int i = 0; i < 8; i++)
+ {
+ file.write((char*)&jumpPoints->jumpDistance[i], 2);
+ }
+
+ // Save Goal Bounds
+ for (int dir = 0; dir < 8; dir++)
+ {
+ if ((m_goalBoundsMap[r][c].bounds[dir][MinRow] >
+ m_goalBoundsMap[r][c].bounds[dir][MaxRow]) &&
+ (m_goalBoundsMap[r][c].bounds[dir][MinCol] >
+ m_goalBoundsMap[r][c].bounds[dir][MaxCol]))
+ {
+ // Use INVALID_GOAL_BOUNDS to represent all four values for compression
+ short value = INVALID_GOAL_BOUNDS;
+ file.write((char*)&value, 2);
+ }
+ else
+ {
+ for (int minMaxIndex = 0; minMaxIndex < 4; minMaxIndex++)
+ {
+ short value = m_goalBoundsMap[r][c].bounds[dir][minMaxIndex];
+ file.write((char*)&value, 2);
+ }
+ }
+ }
+ }
+ }
+#endif
+}
+
+void PrecomputeMap::LoadMap(const char *filename)
+{
+ m_mapCreated = true;
+
+#ifdef FILE_FORMAT_ASCII
+ ifstream file(filename, std::ios::in);
+
+ InitArray(m_jumpDistancesAndGoalBoundsMap, m_width, m_height);
+
+ for (int r = 0; r < m_height; r++)
+ {
+ for (int c = 0; c < m_width; c++)
+ {
+ JumpDistancesAndGoalBounds* map = &m_jumpDistancesAndGoalBoundsMap[r][c];
+ map->blockedDirectionBitfield = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ file >> map->jumpDistance[i];
+ }
+ for (int i = 0; i < 8; i++)
+ {
+ // Detect invalid movement from jump distances
+ // (jump distance of zero is invalid movement)
+ if(map->jumpDistance[i] == 0)
+ {
+ map->blockedDirectionBitfield |= (1 << i);
+ }
+ }
+ for (int dir = 0; dir < 8; dir++)
+ {
+ file >> m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MinRow];
+ file >> m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MaxRow];
+ file >> m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MinCol];
+ file >> m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MaxCol];
+ }
+
+ }
+ }
+#else
+ ifstream file(filename, std::ios::in | std::ios::binary);
+
+ InitArray(m_jumpDistancesAndGoalBoundsMap, m_width, m_height);
+
+ for (int r = 0; r < m_height; r++)
+ {
+ for (int c = 0; c < m_width; c++)
+ {
+ if (IsWall(r, c))
+ {
+ // Don't load data if a wall
+ continue;
+ }
+
+ JumpDistancesAndGoalBounds* map = &m_jumpDistancesAndGoalBoundsMap[r][c];
+ map->blockedDirectionBitfield = 0;
+
+ // Load Jump Distances
+ for (int i = 0; i < 8; i++)
+ {
+ file.read((char*)&map->jumpDistance[i], 2);
+ }
+
+ // Fabricate wall bitfield for each node
+ for (int i = 0; i < 8; i++)
+ {
+ // Jump distance of zero is invalid movement and means a wall
+ if(map->jumpDistance[i] == 0)
+ {
+ map->blockedDirectionBitfield |= (1 << i);
+ }
+ }
+
+ // Load Goal Bounds
+ for (int dir = 0; dir < 8; dir++)
+ {
+ short value;
+ file.read((char*)&value, 2);
+
+ if(value == INVALID_GOAL_BOUNDS)
+ {
+ m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MinRow] = m_height;
+ m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MaxRow] = 0;
+ m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MinCol] = m_width;
+ m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MaxCol] = 0;
+ }
+ else
+ {
+ m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MinRow] = value;
+ file.read((char*)&m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MaxRow], 2);
+ file.read((char*)&m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MinCol], 2);
+ file.read((char*)&m_jumpDistancesAndGoalBoundsMap[r][c].bounds[dir][MaxCol], 2);
+ }
+ }
+
+ }
+ }
+#endif
+}
+
+template
+void PrecomputeMap::InitArray(T**& t, int width, int height)
+{
+ t = new T*[height];
+ for (int i = 0; i < height; ++i)
+ {
+ t[i] = new T[width];
+ memset(t[i], 0, sizeof(T)*width);
+ }
+}
+
+template
+void PrecomputeMap::DestroyArray(T**& t)
+{
+ for (int i = 0; i < m_height; ++i)
+ delete[] t[i];
+ delete[] t;
+
+ t = 0;
+}
+
+void PrecomputeMap::CalculateJumpPointMap()
+{
+ for (int r = 0; r < m_height; ++r)
+ {
+ for (int c = 0; c < m_width; ++c)
+ {
+ if (m_map[c + (r * m_width)])
+ {
+ if (IsJumpPoint(r, c, 1, 0))
+ {
+ m_jumpPointMap[r][c] |= MovingDown;
+ }
+ if (IsJumpPoint(r, c, -1, 0))
+ {
+ m_jumpPointMap[r][c] |= MovingUp;
+ }
+ if (IsJumpPoint(r, c, 0, 1))
+ {
+ m_jumpPointMap[r][c] |= MovingRight;
+ }
+ if (IsJumpPoint(r, c, 0, -1))
+ {
+ m_jumpPointMap[r][c] |= MovingLeft;
+ }
+ }
+ }
+ }
+}
+
+bool PrecomputeMap::IsJumpPoint(int r, int c, int rowDir, int colDir)
+{
+ return
+ IsEmpty(r - rowDir, c - colDir) && // Parent not a wall (not necessary)
+ ((IsEmpty(r + colDir, c + rowDir) && // 1st forced neighbor
+ IsWall(r - rowDir + colDir, c - colDir + rowDir)) || // 1st forced neighbor (continued)
+ ((IsEmpty(r - colDir, c - rowDir) && // 2nd forced neighbor
+ IsWall(r - rowDir - colDir, c - colDir - rowDir)))); // 2nd forced neighbor (continued)
+}
+
+inline bool PrecomputeMap::IsEmpty(int r, int c)
+{
+ unsigned int colBoundsCheck = c;
+ unsigned int rowBoundsCheck = r;
+ if (colBoundsCheck < (unsigned int)m_width && rowBoundsCheck < (unsigned int)m_height)
+ {
+ return m_map[c + (r * m_width)];
+ }
+ else
+ {
+ return false;
+ }
+}
+
+inline bool PrecomputeMap::IsWall(int r, int c)
+{
+ unsigned int colBoundsCheck = c;
+ unsigned int rowBoundsCheck = r;
+ if (colBoundsCheck < (unsigned int)m_width && rowBoundsCheck < (unsigned int)m_height)
+ {
+ return !m_map[c + (r * m_width)];
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void PrecomputeMap::CalculateDistantJumpPointMap()
+{
+ // Calculate distant jump points (Left and Right)
+ for (int r = 0; r < m_height; ++r)
+ {
+ {
+ int countMovingLeft = -1;
+ bool jumpPointLastSeen = false;
+ for (int c = 0; c < m_width; ++c)
+ {
+ if (IsWall(r, c))
+ {
+ countMovingLeft = -1;
+ jumpPointLastSeen = false;
+ m_distantJumpPointMap[r][c].jumpDistance[Left] = 0;
+ continue;
+ }
+
+ countMovingLeft++;
+
+ if (jumpPointLastSeen)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Left] = countMovingLeft;
+ }
+ else // Wall last seen
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Left] = -countMovingLeft;
+ }
+
+ if ((m_jumpPointMap[r][c] & MovingLeft) > 0)
+ {
+ countMovingLeft = 0;
+ jumpPointLastSeen = true;
+ }
+ }
+ }
+
+ {
+ int countMovingRight = -1;
+ bool jumpPointLastSeen = false;
+ for (int c = m_width - 1; c >= 0; --c)
+ {
+ if (IsWall(r, c))
+ {
+ countMovingRight = -1;
+ jumpPointLastSeen = false;
+ m_distantJumpPointMap[r][c].jumpDistance[Right] = 0;
+ continue;
+ }
+
+ countMovingRight++;
+
+ if (jumpPointLastSeen)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Right] = countMovingRight;
+ }
+ else // Wall last seen
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Right] = -countMovingRight;
+ }
+
+ if ((m_jumpPointMap[r][c] & MovingRight) > 0)
+ {
+ countMovingRight = 0;
+ jumpPointLastSeen = true;
+ }
+ }
+ }
+ }
+
+ // Calculate distant jump points (Up and Down)
+ for (int c = 0; c < m_width; ++c)
+ {
+ {
+ int countMovingUp = -1;
+ bool jumpPointLastSeen = false;
+ for (int r = 0; r < m_height; ++r)
+ {
+ if (IsWall(r, c))
+ {
+ countMovingUp = -1;
+ jumpPointLastSeen = false;
+ m_distantJumpPointMap[r][c].jumpDistance[Up] = 0;
+ continue;
+ }
+
+ countMovingUp++;
+
+ if (jumpPointLastSeen)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Up] = countMovingUp;
+ }
+ else // Wall last seen
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Up] = -countMovingUp;
+ }
+
+ if ((m_jumpPointMap[r][c] & MovingUp) > 0)
+ {
+ countMovingUp = 0;
+ jumpPointLastSeen = true;
+ }
+ }
+ }
+
+ {
+ int countMovingDown = -1;
+ bool jumpPointLastSeen = false;
+ for (int r = m_height - 1; r >= 0; --r)
+ {
+ if (IsWall(r, c))
+ {
+ countMovingDown = -1;
+ jumpPointLastSeen = false;
+ m_distantJumpPointMap[r][c].jumpDistance[Down] = 0;
+ continue;
+ }
+
+ countMovingDown++;
+
+ if (jumpPointLastSeen)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Down] = countMovingDown;
+ }
+ else // Wall last seen
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[Down] = -countMovingDown;
+ }
+
+ if ((m_jumpPointMap[r][c] & MovingDown) > 0)
+ {
+ countMovingDown = 0;
+ jumpPointLastSeen = true;
+ }
+ }
+ }
+ }
+
+ // Calculate distant jump points (Diagonally UpLeft and UpRight)
+ for (int r = 0; r < m_height; ++r)
+ {
+ for (int c = 0; c < m_width; ++c)
+ {
+ if (IsEmpty(r, c))
+ {
+ if (r == 0 || c == 0 || (IsWall(r - 1, c) || IsWall(r, c - 1) || IsWall(r - 1, c - 1)))
+ {
+ // Wall one away
+ m_distantJumpPointMap[r][c].jumpDistance[UpLeft] = 0;
+ }
+ else if (IsEmpty(r - 1, c) && IsEmpty(r, c - 1) &&
+ (m_distantJumpPointMap[r - 1][c - 1].jumpDistance[Up] > 0 ||
+ m_distantJumpPointMap[r - 1][c - 1].jumpDistance[Left] > 0))
+ {
+ // Diagonal one away
+ m_distantJumpPointMap[r][c].jumpDistance[UpLeft] = 1;
+ }
+ else
+ {
+ // Increment from last
+ int jumpDistance = m_distantJumpPointMap[r - 1][c - 1].jumpDistance[UpLeft];
+
+ if (jumpDistance > 0)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[UpLeft] = 1 + jumpDistance;
+ }
+ else //if( jumpDistance <= 0 )
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[UpLeft] = -1 + jumpDistance;
+ }
+ }
+
+
+ if (r == 0 || c == m_width - 1 || (IsWall(r - 1, c) || IsWall(r, c + 1) || IsWall(r - 1, c + 1)))
+ {
+ // Wall one away
+ m_distantJumpPointMap[r][c].jumpDistance[UpRight] = 0;
+ }
+ else if (IsEmpty(r - 1, c) && IsEmpty(r, c + 1) &&
+ (m_distantJumpPointMap[r - 1][c + 1].jumpDistance[Up] > 0 ||
+ m_distantJumpPointMap[r - 1][c + 1].jumpDistance[Right] > 0))
+ {
+ // Diagonal one away
+ m_distantJumpPointMap[r][c].jumpDistance[UpRight] = 1;
+ }
+ else
+ {
+ // Increment from last
+ int jumpDistance = m_distantJumpPointMap[r - 1][c + 1].jumpDistance[UpRight];
+
+ if (jumpDistance > 0)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[UpRight] = 1 + jumpDistance;
+ }
+ else //if( jumpDistance <= 0 )
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[UpRight] = -1 + jumpDistance;
+ }
+ }
+ }
+ }
+ }
+
+ // Calculate distant jump points (Diagonally DownLeft and DownRight)
+ for (int r = m_height - 1; r >= 0; --r)
+ {
+ for (int c = 0; c < m_width; ++c)
+ {
+ if (IsEmpty(r, c))
+ {
+ if (r == m_height - 1 || c == 0 ||
+ (IsWall(r + 1, c) || IsWall(r, c - 1) || IsWall(r + 1, c - 1)))
+ {
+ // Wall one away
+ m_distantJumpPointMap[r][c].jumpDistance[DownLeft] = 0;
+ }
+ else if (IsEmpty(r + 1, c) && IsEmpty(r, c - 1) &&
+ (m_distantJumpPointMap[r + 1][c - 1].jumpDistance[Down] > 0 ||
+ m_distantJumpPointMap[r + 1][c - 1].jumpDistance[Left] > 0))
+ {
+ // Diagonal one away
+ m_distantJumpPointMap[r][c].jumpDistance[DownLeft] = 1;
+ }
+ else
+ {
+ // Increment from last
+ int jumpDistance = m_distantJumpPointMap[r + 1][c - 1].jumpDistance[DownLeft];
+
+ if (jumpDistance > 0)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[DownLeft] = 1 + jumpDistance;
+ }
+ else //if( jumpDistance <= 0 )
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[DownLeft] = -1 + jumpDistance;
+ }
+ }
+
+
+ if (r == m_height - 1 || c == m_width - 1 || (IsWall(r + 1, c) || IsWall(r, c + 1) || IsWall(r + 1, c + 1)))
+ {
+ // Wall one away
+ m_distantJumpPointMap[r][c].jumpDistance[DownRight] = 0;
+ }
+ else if (IsEmpty(r + 1, c) && IsEmpty(r, c + 1) &&
+ (m_distantJumpPointMap[r + 1][c + 1].jumpDistance[Down] > 0 ||
+ m_distantJumpPointMap[r + 1][c + 1].jumpDistance[Right] > 0))
+ {
+ // Diagonal one away
+ m_distantJumpPointMap[r][c].jumpDistance[DownRight] = 1;
+ }
+ else
+ {
+ // Increment from last
+ int jumpDistance = m_distantJumpPointMap[r + 1][c + 1].jumpDistance[DownRight];
+
+ if (jumpDistance > 0)
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[DownRight] = 1 + jumpDistance;
+ }
+ else //if( jumpDistance <= 0 )
+ {
+ m_distantJumpPointMap[r][c].jumpDistance[DownRight] = -1 + jumpDistance;
+ }
+ }
+ }
+ }
+ }
+}
+
+void PrecomputeMap::CalculateGoalBounding()
+{
+ printf("Goal Bounding Preprocessing\n");
+
+ DijkstraFloodfill* dijkstra = new DijkstraFloodfill(m_width, m_height, m_map, m_distantJumpPointMap);
+
+ InitArray(m_goalBoundsMap, m_width, m_height);
+ for (int r = 0; r < m_height; ++r)
+ {
+ for (int c = 0; c < m_width; ++c)
+ {
+ for (int dir = 0; dir < 8; ++dir)
+ {
+ m_goalBoundsMap[r][c].bounds[dir][MinRow] = m_height;
+ m_goalBoundsMap[r][c].bounds[dir][MaxRow] = 0;
+ m_goalBoundsMap[r][c].bounds[dir][MinCol] = m_width;
+ m_goalBoundsMap[r][c].bounds[dir][MaxCol] = 0;
+ }
+ }
+ }
+
+ for (int startRow = 0; startRow < m_height; ++startRow)
+ {
+ printf("Row: %d\n", startRow);
+
+ for (int startCol = 0; startCol < m_width; ++startCol)
+ {
+ if (IsWall(startRow, startCol))
+ {
+ continue;
+ }
+
+ dijkstra->Flood(startRow, startCol);
+ int currentIteration = dijkstra->GetCurrentInteration();
+
+ for (int r = 0; r < m_height; ++r)
+ {
+ for (int c = 0; c < m_width; ++c)
+ {
+ if (IsWall(r, c))
+ {
+ continue;
+ }
+
+ int iteration = dijkstra->m_mapNodes[r][c].m_iteration;
+ unsigned char status = dijkstra->m_mapNodes[r][c].m_listStatus;
+ int dir = dijkstra->m_mapNodes[r][c].m_directionFromStart;
+
+ if (iteration == currentIteration &&
+ status == PathfindingNode::OnClosed &&
+ dir >= 0 && dir <= 7)
+ {
+ int row = dijkstra->m_mapNodes[r][c].m_row;
+ int col = dijkstra->m_mapNodes[r][c].m_col;
+
+ if (m_goalBoundsMap[startRow][startCol].bounds[dir][MinRow] > row)
+ {
+ m_goalBoundsMap[startRow][startCol].bounds[dir][MinRow] = row;
+ }
+ if (m_goalBoundsMap[startRow][startCol].bounds[dir][MaxRow] < row)
+ {
+ m_goalBoundsMap[startRow][startCol].bounds[dir][MaxRow] = row;
+ }
+ if (m_goalBoundsMap[startRow][startCol].bounds[dir][MinCol] > col)
+ {
+ m_goalBoundsMap[startRow][startCol].bounds[dir][MinCol] = col;
+ }
+ if (m_goalBoundsMap[startRow][startCol].bounds[dir][MaxCol] < col)
+ {
+ m_goalBoundsMap[startRow][startCol].bounds[dir][MaxCol] = col;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ delete dijkstra;
+}
+
diff --git a/JPSPlusGoalBounding/PrecomputeMap.h b/JPSPlusGoalBounding/PrecomputeMap.h
new file mode 100644
index 0000000..e6bed7a
--- /dev/null
+++ b/JPSPlusGoalBounding/PrecomputeMap.h
@@ -0,0 +1,121 @@
+/*
+ * PrecomputeMap.h
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include
+
+enum ArrayDirections
+{
+ Down = 0,
+ DownRight = 1,
+ Right = 2,
+ UpRight = 3,
+ Up = 4,
+ UpLeft = 5,
+ Left = 6,
+ DownLeft = 7,
+ All = 8
+};
+
+enum GoalBoundsEnum
+{
+ MinRow = 0,
+ MaxRow = 1,
+ MinCol = 2,
+ MaxCol = 3
+};
+
+struct DistantJumpPoints
+{
+ short jumpDistance[8];
+};
+
+struct GoalBounds
+{
+ short bounds[8][4];
+};
+
+struct JumpDistancesAndGoalBounds
+{
+ unsigned char blockedDirectionBitfield; // highest bit [DownLeft, Left, UpLeft, Up, UpRight, Right, DownRight, Down] lowest bit
+ short jumpDistance[8];
+ short bounds[8][4];
+};
+
+class PrecomputeMap
+{
+public:
+ PrecomputeMap(int width, int height, std::vector map);
+ ~PrecomputeMap();
+
+ DistantJumpPoints** CalculateMap();
+ void SaveMap(const char *filename);
+ void LoadMap(const char *filename);
+ JumpDistancesAndGoalBounds** GetPreprocessedMap() { return m_jumpDistancesAndGoalBoundsMap; }
+ void ReleaseMap() { if (m_mapCreated) DestroyArray(m_distantJumpPointMap); }
+
+protected:
+ bool m_mapCreated;
+ int m_width;
+ int m_height;
+ std::vector m_map;
+ unsigned char** m_jumpPointMap;
+ DistantJumpPoints** m_distantJumpPointMap;
+ GoalBounds** m_goalBoundsMap;
+ JumpDistancesAndGoalBounds** m_jumpDistancesAndGoalBoundsMap;
+
+ template void InitArray(T**& t, int width, int height);
+ template void DestroyArray(T**& t);
+
+ void CalculateJumpPointMap();
+ void CalculateDistantJumpPointMap();
+ void CalculateGoalBounding();
+ bool IsJumpPoint(int r, int c, int rowDir, int colDir);
+ bool IsEmpty(int r, int c);
+ bool IsWall(int r, int c);
+
+ enum BitfieldDirections
+ {
+ MovingDown = 1 << 0,
+ MovingRight = 1 << 1,
+ MovingUp = 1 << 2,
+ MovingLeft = 1 << 3,
+ };
+};
+
diff --git a/JPSPlusGoalBounding/ScenarioLoader.cpp b/JPSPlusGoalBounding/ScenarioLoader.cpp
new file mode 100644
index 0000000..5440d56
--- /dev/null
+++ b/JPSPlusGoalBounding/ScenarioLoader.cpp
@@ -0,0 +1,84 @@
+/*
+ * scenarioLoader.cpp
+ * hog
+ *
+ * Created by Renee Jansen on 5/2/2006
+ *
+ */
+
+#include "stdafx.h"
+#include
+using std::ifstream;
+using std::ofstream;
+
+#include "ScenarioLoader.h"
+#include
+
+/**
+ * Loads the experiments from the scenario file.
+ */
+ScenarioLoader::ScenarioLoader(const char* fname)
+{
+ strncpy(scenName, fname, 1024);
+ ifstream sfile(fname,std::ios::in);
+
+ float ver;
+ string first;
+ sfile>>first;
+
+ // Check if a version number is given
+ if(first != "version"){
+ ver = 0.0;
+ sfile.seekg(0,std::ios::beg);
+ }
+ else{
+ sfile>>ver;
+ }
+
+ int sizeX = 0, sizeY = 0;
+ int bucket;
+ string map;
+ int xs, ys, xg, yg;
+ double dist;
+
+ // Read in & store experiments
+ if (ver==0.0){
+ while(sfile>>bucket>>map>>xs>>ys>>xg>>yg>>dist) {
+ Experiment exp(xs,ys,xg,yg,bucket,dist,map);
+ experiments.push_back(exp);
+ }
+ }
+ else if(ver==1.0){
+ while(sfile>>bucket>>map>>sizeX>>sizeY>>xs>>ys>>xg>>yg>>dist){
+ Experiment exp(xs,ys,xg,yg,sizeX,sizeY,bucket,dist,map);
+ experiments.push_back(exp);
+ }
+ }
+ else{
+ printf("Invalid version number.\n");
+ //assert(0);
+ }
+}
+
+void ScenarioLoader::Save(const char *fname)
+{
+// strncpy(scenName, fname, 1024);
+ ofstream ofile(fname);
+
+ float ver = 1.0;
+ ofile<<"version "<
+#include
+#include
+using std::string;
+
+
+
+static const int kNoScaling = -1;
+
+/**
+ * Experiments stored by the ScenarioLoader class.
+ */
+class ScenarioLoader;
+
+class Experiment {
+public:
+ Experiment(int sx,int sy,int gx,int gy,int b, double d, string m)
+ :startx(sx),starty(sy),goalx(gx),goaly(gy),scaleX(kNoScaling),scaleY(kNoScaling),bucket(b),distance(d),map(m){}
+ Experiment(int sx,int sy,int gx,int gy,int sizeX, int sizeY,int b, double d, string m)
+ :startx(sx),starty(sy),goalx(gx),goaly(gy),scaleX(sizeX),scaleY(sizeY),bucket(b),distance(d),map(m){}
+ int GetStartX() const {return startx;}
+ int GetStartY() const {return starty;}
+ int GetGoalX() const {return goalx;}
+ int GetGoalY() const {return goaly;}
+ int GetBucket() const {return bucket;}
+ double GetDistance() const {return distance;}
+ void GetMapName(char* mymap) const {strcpy(mymap,map.c_str());}
+ const char *GetMapName() const { return map.c_str(); }
+ int GetXScale() const {return scaleX;}
+ int GetYScale() const {return scaleY;}
+
+private:
+ friend class ScenarioLoader;
+ int startx, starty, goalx, goaly;
+ int scaleX;
+ int scaleY;
+ int bucket;
+ double distance;
+ string map;
+};
+
+/** A class which loads and stores scenarios from files.
+ * Versions currently handled: 0.0 and 1.0 (includes scale).
+ */
+
+class ScenarioLoader{
+public:
+ ScenarioLoader() { scenName[0] = 0; }
+ ScenarioLoader(const char *);
+ void Save(const char *);
+ int GetNumExperiments(){return experiments.size();}
+ const char *GetScenarioName() { return scenName; }
+ Experiment GetNthExperiment(int which)
+ {return experiments[which];}
+ void AddExperiment(Experiment which);
+ void Clear() { experiments.clear(); }
+private:
+ char scenName[1024];
+ std::vector experiments;
+};
+
+#endif
diff --git a/JPSPlusGoalBounding/SimpleUnsortedPriorityQueue.cpp b/JPSPlusGoalBounding/SimpleUnsortedPriorityQueue.cpp
new file mode 100644
index 0000000..0010811
--- /dev/null
+++ b/JPSPlusGoalBounding/SimpleUnsortedPriorityQueue.cpp
@@ -0,0 +1,65 @@
+/*
+ * SimpleUnsortedPriorityQueue.cpp
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "StdAfx.h"
+#include "SimpleUnsortedPriorityQueue.h"
+
+PathfindingNode* SimpleUnsortedPriorityQueue::Pop(void)
+{
+ // Find the cheapest node
+ unsigned int cheapestNodeCost = m_nodeArray[0]->m_finalCost;
+ int cheapestNodeIndex = 0;
+
+ for (int i = 1; i < m_nextFreeNode; ++i)
+ {
+ if (m_nodeArray[i]->m_finalCost < cheapestNodeCost)
+ {
+ cheapestNodeCost = m_nodeArray[i]->m_finalCost;
+ cheapestNodeIndex = i;
+ }
+ }
+
+ // Remember the cheapest node
+ PathfindingNode* cheapestNode = m_nodeArray[cheapestNodeIndex];
+
+ // Delete off list (put the last node where this one was)
+ m_nodeArray[cheapestNodeIndex] = m_nodeArray[--m_nextFreeNode];
+
+ return cheapestNode;
+}
diff --git a/JPSPlusGoalBounding/SimpleUnsortedPriorityQueue.h b/JPSPlusGoalBounding/SimpleUnsortedPriorityQueue.h
new file mode 100644
index 0000000..8f0ef84
--- /dev/null
+++ b/JPSPlusGoalBounding/SimpleUnsortedPriorityQueue.h
@@ -0,0 +1,64 @@
+/*
+ * SimpleUnsortedPriorityQueue.h
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "PathfindingNode.h"
+
+// This priority queue only makes sense when the open list on average contains
+// fewer than 10 elements. This is the case for JPS+ with Goal Bounding when
+// a fast stack is being used in conjunction with the open list.
+
+#pragma once
+class SimpleUnsortedPriorityQueue
+{
+public:
+ SimpleUnsortedPriorityQueue(int arraySize) : m_nextFreeNode(0) { m_nodeArray = new PathfindingNode*[arraySize]; }
+ ~SimpleUnsortedPriorityQueue(void) { delete[] m_nodeArray; }
+
+ inline void Reset() { m_nextFreeNode = 0; }
+ inline bool Empty(void) { return m_nextFreeNode == 0; }
+ inline void Add(PathfindingNode* node) { m_nodeArray[m_nextFreeNode++] = node; }
+ PathfindingNode* Pop(void);
+
+private:
+ int m_nextFreeNode;
+ bool m_identical;
+ PathfindingNode** m_nodeArray;
+};
+
diff --git a/JPSPlusGoalBounding/Timer.cpp b/JPSPlusGoalBounding/Timer.cpp
new file mode 100644
index 0000000..02c687f
--- /dev/null
+++ b/JPSPlusGoalBounding/Timer.cpp
@@ -0,0 +1,53 @@
+/*
+ * $Id: timer.cpp,v 1.6 2006/11/30 20:33:25 nathanst Exp $
+ *
+ * timer.cpp
+ * HOG file
+ *
+ * Written by Renee Jansen on 08/28/06
+ *
+ * This file is part of HOG.
+ *
+ * HOG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * HOG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HOG; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+//#include "UnitSimulation.h"
+#include "stdafx.h"
+#include "Timer.h"
+#include
+#include
+#include
+
+Timer::Timer()
+{
+ QueryPerformanceFrequency(&ticksPerSecond);
+ startTimeInUS = 0;
+ elapsedTime = 0;
+}
+
+void Timer::StartTimer()
+{
+ startTimeInUS = GetHighestResolutionTime();
+}
+
+double Timer::EndTimer()
+{
+ double currentTimeInUS = GetHighestResolutionTime();
+ double elapsedTimeInUS = currentTimeInUS - startTimeInUS;
+ elapsedTime = elapsedTimeInUS;
+
+ return elapsedTime;
+
+}
diff --git a/JPSPlusGoalBounding/Timer.h b/JPSPlusGoalBounding/Timer.h
new file mode 100644
index 0000000..578b4f7
--- /dev/null
+++ b/JPSPlusGoalBounding/Timer.h
@@ -0,0 +1,54 @@
+/*
+ * $Id: timer.h,v 1.5 2006/10/30 17:45:10 nathanst Exp $
+ *
+ * timer.h
+ * HOG file
+ *
+ * Written by Renee Jansen on 08/28/06
+ *
+ * This file is part of HOG.
+ *
+ * HOG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * HOG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HOG; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include
+#include
+#include
+
+class Timer {
+
+private:
+ //unsigned int startTimeInMS;
+ double startTimeInUS;
+ double elapsedTime;
+ LARGE_INTEGER ticksPerSecond;
+
+ float getCPUSpeed();
+
+public:
+ Timer();
+ ~Timer(){}
+
+ void StartTimer();
+ double EndTimer();
+ double GetElapsedTime(){return elapsedTime;}
+
+ inline double GetHighestResolutionTime(void) { LARGE_INTEGER qwTime; QueryPerformanceCounter(&qwTime); return((double)qwTime.QuadPart); }
+};
+
+#endif
diff --git a/JPSPlusGoalBounding/UnsortedPriorityQueue.cpp b/JPSPlusGoalBounding/UnsortedPriorityQueue.cpp
new file mode 100644
index 0000000..2061165
--- /dev/null
+++ b/JPSPlusGoalBounding/UnsortedPriorityQueue.cpp
@@ -0,0 +1,128 @@
+/*
+ * UnsortedPriorityQueue.cpp
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stdafx.h"
+#include "UnsortedPriorityQueue.h"
+
+//#define TRACK_IDENTICAL_OPTIMIZATION
+//#define ALL_NODES_EQUAL_COST // ~40% faster and still results in optimal paths in virtually all cases
+
+UnsortedPriorityQueue::UnsortedPriorityQueue(int arraySize)
+: m_nextFreeNode(0), m_iteration(0)
+{
+ m_nodeArray = new DijkstraPathfindingNode*[arraySize];
+}
+
+UnsortedPriorityQueue::~UnsortedPriorityQueue()
+{
+ delete[] m_nodeArray;
+}
+
+void UnsortedPriorityQueue::Push(DijkstraPathfindingNode* node)
+{
+ if (m_iteration != node->m_iteration)
+ {
+ m_nextFreeNode = 0;
+ m_identical = true;
+ m_iteration = node->m_iteration;
+ }
+#ifdef TRACK_IDENTICAL_OPTIMIZATION
+ else if(m_identical)
+ {
+ m_identical = node->m_finalCost == m_nodeArray[0]->m_finalCost;
+ }
+ else
+ {
+ m_identical = m_nextFreeNode == 0;
+ }
+#endif
+
+ m_nodeArray[m_nextFreeNode++] = node;
+
+}
+
+void UnsortedPriorityQueue::Remove(DijkstraPathfindingNode* node)
+{
+ for (int i = 0; i < m_nextFreeNode; ++i)
+ {
+ if (m_nodeArray[i] == node)
+ {
+ // Delete off Open list (put last node where this one was)
+ m_nodeArray[i] = m_nodeArray[--m_nextFreeNode];
+ return;
+ }
+ }
+}
+
+DijkstraPathfindingNode* UnsortedPriorityQueue::Pop(void)
+{
+#ifdef ALL_NODES_EQUAL_COST
+ // Just pop last node (all nodes are very close to each other in cost)
+ return m_nodeArray[--m_nextFreeNode];
+#else
+
+#ifdef TRACK_IDENTICAL_OPTIMIZATION
+ if(m_identical)
+ {
+ return m_nodeArray[--m_nextFreeNode];
+ }
+#endif
+
+ // Find cheapest node
+ unsigned int cheapestNodeCostFinal = m_nodeArray[0]->m_givenCost;
+ int cheapestNodeIndex = 0;
+
+ for (int i = 1; i < m_nextFreeNode; ++i)
+ {
+ if (m_nodeArray[i]->m_givenCost < cheapestNodeCostFinal)
+ {
+ cheapestNodeCostFinal = m_nodeArray[i]->m_givenCost;
+ cheapestNodeIndex = i;
+ }
+ }
+
+ // Remember cheapest node
+ DijkstraPathfindingNode* cheapestNode = m_nodeArray[cheapestNodeIndex];
+
+ // Delete off Open list (put last node where this one was)
+ m_nodeArray[cheapestNodeIndex] = m_nodeArray[--m_nextFreeNode];
+
+ return cheapestNode;
+#endif
+}
diff --git a/JPSPlusGoalBounding/UnsortedPriorityQueue.h b/JPSPlusGoalBounding/UnsortedPriorityQueue.h
new file mode 100644
index 0000000..b83683b
--- /dev/null
+++ b/JPSPlusGoalBounding/UnsortedPriorityQueue.h
@@ -0,0 +1,67 @@
+/*
+ * UnsortedPriorityQueue.h
+ *
+ * Copyright (c) 2014-2015, Steve Rabin
+ * All rights reserved.
+ *
+ * An explanation of the JPS+ algorithm is contained in Chapter 14
+ * of the book Game AI Pro 2, edited by Steve Rabin, CRC Press, 2015.
+ * A presentation on Goal Bounding titled "JPS+: Over 100x Faster than A*"
+ * can be found at www.gdcvault.com from the 2015 GDC AI Summit.
+ * A copy of this code is on the website http://www.gameaipro.com.
+ *
+ * If you develop a way to improve this code or make it faster, please
+ * contact steve.rabin@gmail.com and share your insights. I would
+ * be equally eager to hear from anyone integrating this code or using
+ * the Goal Bounding concept in a commercial application or game.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY STEVE RABIN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "PathfindingNode.h"
+
+// This array is dangerous since there are no safeguards if the max size is exceeded.
+// However, any method to detect a problem and deal with it gracefully will sacrifice speed.
+// In this code base, this is only used by the Dijkstra floodfill for Goal Bounding preprocessing.
+
+class UnsortedPriorityQueue
+{
+public:
+
+ UnsortedPriorityQueue(int arraySize);
+ ~UnsortedPriorityQueue();
+
+ inline bool Empty(int iteration) { if(m_iteration == iteration) { return m_nextFreeNode == 0; } else { return true; } }
+ inline int GetIteration() { return m_iteration; }
+ void Push(DijkstraPathfindingNode* node);
+ void Remove(DijkstraPathfindingNode* node);
+ DijkstraPathfindingNode* Pop(void);
+
+private:
+ int m_nextFreeNode;
+ int m_iteration;
+ bool m_identical;
+ DijkstraPathfindingNode** m_nodeArray;
+
+};
+
diff --git a/JPSPlusGoalBounding/main.cpp b/JPSPlusGoalBounding/main.cpp
new file mode 100644
index 0000000..7cb128e
--- /dev/null
+++ b/JPSPlusGoalBounding/main.cpp
@@ -0,0 +1,286 @@
+//
+// File.cpp
+// MapAbstraction
+//
+// Created by Nathan Sturtevant on 7/11/13.
+// Modified by Steve Rabin 12/15/14
+//
+//
+
+#include "stdafx.h"
+#include
+#include
+#include
+#include
+#include
+#include "ScenarioLoader.h"
+#include "Timer.h"
+#include "Entry.h"
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+void LoadMap(const char *fname, std::vector &map, int &w, int &h);
+
+struct stats {
+ std::vector times;
+ std::vector path;
+ std::vector lengths;
+
+ double GetTotalTime()
+ {
+ return std::accumulate(times.begin(), times.end(), 0.0);
+ }
+ double GetMaxTimestep()
+ {
+ return *std::max_element(times.begin(), times.end());
+ }
+ double Get20MoveTime()
+ {
+ for (unsigned int x = 0; x < lengths.size(); x++)
+ if (lengths[x] >= 20)
+ return std::accumulate(times.begin(), times.begin()+1+x, 0.0);
+ return GetTotalTime();
+ }
+ double GetPathLength()
+ {
+ double len = 0;
+ for (int x = 0; x < (int)path.size()-1; x++)
+ {
+ if (path[x].x == path[x+1].x || path[x].y == path[x+1].y)
+ {
+ len++;
+ }
+ else {
+ len += 1.4142;
+ }
+ }
+ return len;
+ }
+ bool ValidatePath(int width, int height, const std::vector &mapData)
+ {
+ for (int x = 0; x < (int)path.size()-1; x++)
+ {
+ if (abs(path[x].x - path[x+1].x) > 1)
+ return false;
+ if (abs(path[x].y - path[x+1].y) > 1)
+ return false;
+ if (!mapData[path[x].y*width+path[x].x])
+ return false;
+ if (!mapData[path[x+1].y*width+path[x+1].x])
+ return false;
+ if (path[x].x != path[x+1].x && path[x].y != path[x+1].y)
+ {
+ if (!mapData[path[x+1].y*width+path[x].x])
+ return false;
+ if (!mapData[path[x].y*width+path[x+1].x])
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+int _tmain(int argc, char* argv[])
+{
+ double allTestsTotalTime = 0;
+
+ WIN32_FIND_DATA ffd;
+ LARGE_INTEGER filesize;
+ TCHAR szDir[MAX_PATH];
+ size_t length_of_arg;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ DWORD dwError=0;
+
+ StringCchCopy(szDir, MAX_PATH, TEXT("Maps\\*"));
+ hFind = FindFirstFile(szDir, &ffd);
+
+ do
+ {
+ char filename[2048];
+ std::vector thePath;
+ std::vector mapData;
+ int width, height;
+ bool pre = false;
+ bool run = true;
+ bool silenceIndividualTests = false;
+
+ char mapFilename[2048] = "\0";
+ char mapScenarioFilename[2048] = "\0";
+ char mapPreprocessedFilename[2048] = "\0";
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ continue;
+ }
+ else
+ {
+ int filenameLength = 0;
+ while(ffd.cFileName[++filenameLength] != 0) {}
+
+ if (ffd.cFileName[filenameLength-3] == 'm' &&
+ ffd.cFileName[filenameLength-2] == 'a' &&
+ ffd.cFileName[filenameLength-1] == 'p')
+ {
+ char baseFilename[2048];
+ for(int i=0; i experimentStats;
+ for (int x = 0; x < scen.GetNumExperiments(); x++)
+ {
+ thePath.resize(0);
+ experimentStats.resize(x+1);
+ bool done;
+ do {
+ xyLoc s, g;
+ s.x = scen.GetNthExperiment(x).GetStartX();
+ s.y = scen.GetNthExperiment(x).GetStartY();
+ g.x = scen.GetNthExperiment(x).GetGoalX();
+ g.y = scen.GetNthExperiment(x).GetGoalY();
+
+ if(s.x == g.x && s.y == g.y)
+ {
+ done = true;
+ }
+ else
+ {
+ t.StartTimer();
+ done = GetPath(reference, s, g, thePath);
+ t.EndTimer();
+
+ if(thePath.size() > 0)
+ {
+ experimentStats[x].times.push_back(t.GetElapsedTime());
+ experimentStats[x].lengths.push_back(thePath.size());
+ for (unsigned int t = experimentStats[x].path.size(); t < thePath.size(); t++)
+ experimentStats[x].path.push_back(thePath[t]);
+ }
+ }
+ } while (done == false);
+
+ }
+ thePath.clear();
+ delete reference;
+
+ double totalTime = 0;
+ bool invalid = false;
+ bool suboptimal = false;
+ for (unsigned int x = 0; x < experimentStats.size(); x++)
+ {
+ if(!silenceIndividualTests)
+ {
+ printf("GPPC\t%s\ttotal-time\t%f\tmax-time-step\t%f\ttime-20-moves\t%f\ttotal-len\t%f\tsubopt\t%f\t", mapScenarioFilename,
+ experimentStats[x].GetTotalTime(), experimentStats[x].GetMaxTimestep(), experimentStats[x].Get20MoveTime(),
+ experimentStats[x].GetPathLength(), experimentStats[x].GetPathLength()/scen.GetNthExperiment(x).GetDistance());
+ }
+
+ if (experimentStats[x].path.size() != 0 &&
+ (experimentStats[x].ValidatePath(width, height, mapData) &&
+ scen.GetNthExperiment(x).GetStartX() == experimentStats[x].path[0].x &&
+ scen.GetNthExperiment(x).GetStartY() == experimentStats[x].path[0].y &&
+ scen.GetNthExperiment(x).GetGoalX() == experimentStats[x].path.back().x &&
+ scen.GetNthExperiment(x).GetGoalY() == experimentStats[x].path.back().y))
+ {
+ if(!silenceIndividualTests)
+ printf("valid\n");
+ }
+ else
+ {
+ invalid = true;
+ if(!silenceIndividualTests)
+ printf("invalid\n");
+ }
+ if (experimentStats[x].GetPathLength() / scen.GetNthExperiment(x).GetDistance() > 1.000005f)
+ {
+ suboptimal = true;
+ }
+
+ totalTime += experimentStats[x].GetTotalTime();
+ allTestsTotalTime += experimentStats[x].GetTotalTime();
+ }
+
+ printf("Total map time: %f,\t%s", totalTime, mapFilename);
+ if (invalid) { printf(",\tINVALID"); }
+ if (suboptimal) { printf(",\tSUBOPTIMAL"); }
+ printf("\n");
+
+ for (unsigned int x = 0; x < experimentStats.size(); x++)
+ {
+ experimentStats[x].path.clear();
+ experimentStats[x].times.clear();
+ experimentStats[x].lengths.clear();
+ }
+ experimentStats.clear();
+ scen.Clear();
+ mapData.clear();
+
+ } while (FindNextFile(hFind, &ffd) != 0);
+
+ printf("All tests total time: %f", allTestsTotalTime);
+
+ while(true) {}
+
+ return 0;
+}
+
+void LoadMap(const char *fname, std::vector &map, int &width, int &height)
+{
+ FILE *f;
+ f = fopen(fname, "r");
+ if (f)
+ {
+ fscanf(f, "type octile\nheight %d\nwidth %d\nmap\n", &height, &width);
+ map.resize(height*width);
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ char c;
+ do {
+ fscanf(f, "%c", &c);
+ } while (isspace(c));
+ map[y*width+x] = (c == '.' || c == 'G' || c == 'S');
+ }
+ }
+ fclose(f);
+ }
+}
diff --git a/JPSPlusGoalBounding/stdafx.cpp b/JPSPlusGoalBounding/stdafx.cpp
new file mode 100644
index 0000000..20d54fd
--- /dev/null
+++ b/JPSPlusGoalBounding/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// JPSPlusGoalBounding.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/JPSPlusGoalBounding/stdafx.h b/JPSPlusGoalBounding/stdafx.h
new file mode 100644
index 0000000..b005a83
--- /dev/null
+++ b/JPSPlusGoalBounding/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include
+#include
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/JPSPlusGoalBounding/targetver.h b/JPSPlusGoalBounding/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/JPSPlusGoalBounding/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include