New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
/* Copyright (C) 2015 Wildfire Games.
|
2010-09-03 11:32:12 +02:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. 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.
|
|
|
|
*
|
|
|
|
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef INCLUDED_PRIORITYQUEUE
|
|
|
|
#define INCLUDED_PRIORITYQUEUE
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Priority queues for pathfinder.
|
|
|
|
* (These probably aren't suitable for more general uses.)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef NDEBUG
|
|
|
|
#define PRIORITYQUEUE_DEBUG 0
|
|
|
|
#else
|
|
|
|
#define PRIORITYQUEUE_DEBUG 1
|
|
|
|
#endif
|
|
|
|
|
2011-07-24 13:42:35 +02:00
|
|
|
template <typename Item, typename CMP>
|
2010-09-03 11:32:12 +02:00
|
|
|
struct QueueItemPriority
|
|
|
|
{
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
bool operator()(const Item& a, const Item& b) const
|
2010-09-03 11:32:12 +02:00
|
|
|
{
|
2011-07-24 13:42:35 +02:00
|
|
|
if (CMP()(b.rank, a.rank)) // higher costs are lower priority
|
2010-09-03 11:32:12 +02:00
|
|
|
return true;
|
2011-07-24 13:42:35 +02:00
|
|
|
if (CMP()(a.rank, b.rank))
|
2010-09-03 11:32:12 +02:00
|
|
|
return false;
|
|
|
|
// Need to tie-break to get a consistent ordering
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
if (CMP()(b.h, a.h)) // higher heuristic costs are lower priority
|
|
|
|
return true;
|
|
|
|
if (CMP()(a.h, b.h))
|
|
|
|
return false;
|
2010-09-03 11:32:12 +02:00
|
|
|
if (a.id < b.id)
|
|
|
|
return true;
|
|
|
|
if (b.id < a.id)
|
|
|
|
return false;
|
|
|
|
#if PRIORITYQUEUE_DEBUG
|
|
|
|
debug_warn(L"duplicate tiles in queue");
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Priority queue implemented as a binary heap.
|
|
|
|
* This is quite dreadfully slow in MSVC's debug STL implementation,
|
|
|
|
* so we shouldn't use it unless we reimplement the heap functions more efficiently.
|
|
|
|
*/
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
template <typename ID, typename R, typename H, typename CMP = std::less<R> >
|
2010-09-03 11:32:12 +02:00
|
|
|
class PriorityQueueHeap
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Item
|
|
|
|
{
|
|
|
|
ID id;
|
|
|
|
R rank; // f = g+h (estimated total cost of path through here)
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
H h; // heuristic cost
|
2010-09-03 11:32:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void push(const Item& item)
|
|
|
|
{
|
|
|
|
m_Heap.push_back(item);
|
2011-07-24 13:42:35 +02:00
|
|
|
push_heap(m_Heap.begin(), m_Heap.end(), QueueItemPriority<Item, CMP>());
|
2010-09-03 11:32:12 +02:00
|
|
|
}
|
|
|
|
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
void promote(ID id, R UNUSED(oldrank), R newrank, H newh)
|
2010-09-03 11:32:12 +02:00
|
|
|
{
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
// Loop backwards since it seems a little faster in practice
|
|
|
|
for (ssize_t n = m_Heap.size() - 1; n >= 0; --n)
|
2010-09-03 11:32:12 +02:00
|
|
|
{
|
|
|
|
if (m_Heap[n].id == id)
|
|
|
|
{
|
|
|
|
#if PRIORITYQUEUE_DEBUG
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m_Heap[n].rank > newrank);
|
2010-09-03 11:32:12 +02:00
|
|
|
#endif
|
|
|
|
m_Heap[n].rank = newrank;
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
m_Heap[n].h = newh;
|
2011-07-24 13:42:35 +02:00
|
|
|
push_heap(m_Heap.begin(), m_Heap.begin()+n+1, QueueItemPriority<Item, CMP>());
|
2010-09-03 11:32:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Item pop()
|
|
|
|
{
|
|
|
|
#if PRIORITYQUEUE_DEBUG
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m_Heap.size());
|
2010-09-03 11:32:12 +02:00
|
|
|
#endif
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
Item r = m_Heap[0];
|
2011-07-24 13:42:35 +02:00
|
|
|
pop_heap(m_Heap.begin(), m_Heap.end(), QueueItemPriority<Item, CMP>());
|
2010-09-03 11:32:12 +02:00
|
|
|
m_Heap.pop_back();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty()
|
|
|
|
{
|
|
|
|
return m_Heap.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t size()
|
|
|
|
{
|
|
|
|
return m_Heap.size();
|
|
|
|
}
|
|
|
|
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
m_Heap.clear();
|
|
|
|
}
|
|
|
|
|
2010-09-03 11:32:12 +02:00
|
|
|
std::vector<Item> m_Heap;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Priority queue implemented as an unsorted array.
|
|
|
|
* This means pop() is O(n), but push and promote are O(1), and n is typically small
|
|
|
|
* (average around 50-100 in some rough tests).
|
|
|
|
* It seems fractionally slower than a binary heap in optimised builds, but is
|
|
|
|
* much simpler and less susceptible to MSVC's painfully slow debug STL.
|
|
|
|
*/
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
template <typename ID, typename R, typename H, typename CMP = std::less<R> >
|
2010-09-03 11:32:12 +02:00
|
|
|
class PriorityQueueList
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Item
|
|
|
|
{
|
|
|
|
ID id;
|
|
|
|
R rank; // f = g+h (estimated total cost of path through here)
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
H h; // heuristic cost
|
2010-09-03 11:32:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void push(const Item& item)
|
|
|
|
{
|
|
|
|
m_List.push_back(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
Item* find(ID id)
|
|
|
|
{
|
|
|
|
for (size_t n = 0; n < m_List.size(); ++n)
|
|
|
|
{
|
|
|
|
if (m_List[n].id == id)
|
|
|
|
return &m_List[n];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
void promote(ID id, R UNUSED(oldrank), R newrank, H newh)
|
2010-09-03 11:32:12 +02:00
|
|
|
{
|
|
|
|
find(id)->rank = newrank;
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
find(id)->h = newh;
|
2010-09-03 11:32:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Item pop()
|
|
|
|
{
|
|
|
|
#if PRIORITYQUEUE_DEBUG
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m_List.size());
|
2010-09-03 11:32:12 +02:00
|
|
|
#endif
|
|
|
|
// Loop backwards looking for the best (it's most likely to be one
|
|
|
|
// we've recently pushed, so going backwards saves a bit of copying)
|
|
|
|
Item best = m_List.back();
|
|
|
|
size_t bestidx = m_List.size()-1;
|
|
|
|
for (ssize_t i = (ssize_t)bestidx-1; i >= 0; --i)
|
|
|
|
{
|
2011-07-24 13:42:35 +02:00
|
|
|
if (QueueItemPriority<Item, CMP>()(best, m_List[i]))
|
2010-09-03 11:32:12 +02:00
|
|
|
{
|
|
|
|
bestidx = i;
|
|
|
|
best = m_List[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Swap the matched element with the last in the list, then pop the new last
|
|
|
|
m_List[bestidx] = m_List[m_List.size()-1];
|
|
|
|
m_List.pop_back();
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty()
|
|
|
|
{
|
|
|
|
return m_List.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t size()
|
|
|
|
{
|
|
|
|
return m_List.size();
|
|
|
|
}
|
|
|
|
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
m_List.clear();
|
|
|
|
}
|
|
|
|
|
2010-09-03 11:32:12 +02:00
|
|
|
std::vector<Item> m_List;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // INCLUDED_PRIORITYQUEUE
|