public ISpace ConstructSpace()
        {
            Stack<ISpaceCandidate> stack = new Stack<ISpaceCandidate>();
            HashSet<int> closedList = new HashSet<int>();
            //Dictionary<int, ISpaceCandidate> debugClosedList = new Dictionary<int, ISpaceCandidate>();

            int nodesExplored = 0;
            int dupesRemoved = 0;

            SpaceCandidate initialCandidate = new SpaceCandidate(m_mission);

            stack.Push(initialCandidate);

            while (stack.Count > 0)
            {
                ISpaceCandidate curNode = stack.Pop();
                nodesExplored++;

                if (curNode.IsComplete)
                {
                    return curNode.Space;
                }

                List<ISpaceCandidate> successors = curNode.Expand();
                foreach (ISpaceCandidate successor in successors)
                {
                    /*
                     * Tests if we ever have a hash collision when spaces aren't identical.
                     * I tried a couple dozen times and never had this occur.
                    if (closedList.Contains(curNode.GetHashCode()) &&
                        !SpaceImpl.TestAreEqual((SpaceImpl)curNode.Space, (SpaceImpl)debugClosedList[curNode.GetHashCode()].Space))
                    {
                        // debug me!
                        SpaceImpl a = (SpaceImpl)curNode.Space;
                        SpaceImpl b = (SpaceImpl)debugClosedList[curNode.GetHashCode()].Space;
                        int c = 7;
                    }
                     */

                    if (!closedList.Contains(successor.GetHashCode()))
                    {
                        closedList.Add(successor.GetHashCode());
                        //debugClosedList.Add(successor.GetHashCode(), curNode);
                        stack.Push(successor);
                    }
                    else
                    {
                        dupesRemoved++;
                    }
                }
            }

            return null;
        }
        public ISpace ConstructSpace()
        {
            PriorityQueue<ISpaceCandidate, float> openList = new PriorityQueue<ISpaceCandidate, float>();
            HashSet<int> closedList = new HashSet<int>();

            SpaceCandidate initialCandidate = new SpaceCandidate(m_mission);

            openList.Enqueue(initialCandidate, 0.0f);

            while (openList.Count > 0)
            {
                ISpaceCandidate curNode = openList.Dequeue().Value;

                // closedList simply checks the hash.  yes, its possible that then we'll get a false
                //  positive later because two things hash to the same value.  i dont want to impl
                //  a more rigorous Equals function and use a dict, so i'm hoping that these false
                //  positives are minimal given the 4 billion possible hash values.
                if (closedList.Contains(curNode.GetHashCode()))
                {
                    continue;
                }
                closedList.Add(curNode.GetHashCode());

                if (curNode.IsComplete)
                {
                    return curNode.Space;
                }

                foreach (ISpaceCandidate successor in curNode.Expand())
                {
                    float cost = successor.Cost;
                    float heuristic = m_heuristic(successor);

                    openList.Enqueue(successor, 1000000 - (cost + heuristic));
                }
            }

            return null;
        }
        protected SpaceCandidate DeepCopy()
        {
            SpaceCandidate copy = new SpaceCandidate();

            copy.m_cost = this.m_cost;
            copy.m_space = this.m_space.DeepCopy();
            copy.m_mission = this.m_mission.DeepCopy();

            // TODO
            // should only be removed once this class is finalized for testing.
            // so we don't have obscure bugs caused by forgetting to copy a new field
            //  which was added later.
            //throw new NotImplementedException();

            return copy;
        }