initial commit, lordsawar source, slightly modified
[lordsawar] / src / LocationList.h
diff --git a/src/LocationList.h b/src/LocationList.h
new file mode 100644 (file)
index 0000000..3e932d9
--- /dev/null
@@ -0,0 +1,284 @@
+// Copyright (C) 2001, 2003 Michael Bartl
+// Copyright (C) 2004 Ulf Lorenz
+// Copyright (C) 2005, 2006 Andrea Paternesi
+// Copyright (C) 2007, 2008, 2009 Ben Asselstine
+// Copyright (C) 2008 Ole Laursen
+//
+//  This program 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 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program 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 Library General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+
+#ifndef LOCATIONLIST_H
+#define LOCATIONLIST_H
+
+#include <gtkmm.h>
+#include <algorithm>
+#include <list>
+#include <map>
+#include "PathCalculator.h"
+#include "vector.h"
+class Stack;
+
+/** A list for object instances
+  * 
+  * This class extends the stl lists by adding the functions getObjectAt()
+  * which return the object at position (x,y). Necessary for such things as
+  * the city list.
+  */
+
+using namespace std;
+  
+template<class T> class LocationList : public std::list<T>
+{
+ public:
+  
+  LocationList(){};  
+  ~LocationList() 
+    {
+      for (typename LocationList<T>::iterator it = this->begin(); it != this->end(); ++it)
+       delete *it;
+      d_object.clear();
+      d_id.clear();
+    };
+
+  void add(T t)
+    {
+      push_back(t);
+      d_id[t->getId()] = t;
+      int size = t->getSize();
+      for (int i = 0; i < size; i++)
+       for (int j = 0; j < size; j++)
+         {
+           Vector<int> pos = t->getPos() + Vector<int>(i,j);
+           d_object[pos] = t;
+         }
+    }
+  void subtract(T t)
+    {
+      this->erase(std::find(this->begin(), this->end(), t));
+      d_id.erase(d_id.find(t->getId()));
+      int size = t->getSize();
+      for (int i = 0; i < size; i++)
+       for (int j = 0; j < size; j++)
+         {
+           Vector<int> pos = t->getPos() + Vector<int>(i,j);
+           d_object.erase(d_object.find(pos));
+         }
+      delete t;
+    }
+
+  //! Returns the object at position (x,y).  
+  T getObjectAt(int x, int y) const
+    {
+      Vector<int> pos = Vector<int>(x,y);
+  
+      if (d_object.find(pos) == d_object.end())
+       return NULL;
+      else
+       return (*d_object.find(pos)).second;
+    }
+
+  //! Returns the object at position pos.  
+  T getObjectAt(const Vector<int>& pos) const
+    {
+      return getObjectAt(pos.x, pos.y);
+    }
+
+  T getNearestObjectInDir(const Vector<int> &pos, const Vector<int> dir) const
+    {
+      int diff = -1;
+      typename LocationList<T>::const_iterator diffit;
+      for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
+        {
+          Vector<int> p = (*it)->getPos();
+          int delta = abs(p.x - pos.x) + abs(p.y - pos.y);
+         //if dir is -1, then the difference between pos.x and p.x should be positive
+         //if dir is +1, then the difference between pos.x and p.x should be negative
+         //if looking west, and the object is to the east
+         if (dir.x < 0 && (pos.x - p.x) <= 0)
+           continue;
+         //if looking east , and the object is to the west
+         if (dir.x > 0 && (pos.x - p.x) >= 0)
+           continue;
+         //if looking north, and the object is to the south
+         if (dir.y < 0 && (pos.y - p.y) <= 0)
+           continue;
+         //if looking south, and the object is to the north
+         if (dir.y > 0 && (pos.y - p.y) >= 0)
+           continue;
+
+          if ((diff > delta) || (diff == -1))
+            {
+              diff = delta;
+              diffit = it;
+            }
+        }
+      if (diff == -1) return 0;
+      return (*diffit);
+    }
+
+  T getClosestObject (const Stack *stack, std::list<bool (*)(void*)> *filters) const
+    {
+      int diff = -1;
+      typename LocationList<T>::const_iterator diffit;
+      PathCalculator pc(stack, true, 0, 0);
+      for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
+        {
+          int delta = pc.calculate((*it)->getPos());
+          if (delta <= 0)
+            continue;
+         if (filters)
+           {
+             std::list<bool (*)(void*)>::iterator fit = filters->begin();
+             bool filtered = false;
+             for (; fit != filters->end(); fit++)
+               {
+                 if ((*fit)(*it) == true)
+                   {
+                     filtered = true;
+                     break;
+                   }
+                   
+               }
+             if (filtered)
+               continue;
+           }
+
+          if ((diff > delta) || (diff == -1))
+            {
+              diff = delta;
+              diffit = it;
+            }
+        }
+      if (diff == -1) return 0;
+      return (*diffit);
+    }
+
+  T getClosestObject (const Stack *stack) const
+    {
+      return getClosestObject (stack, NULL);
+    }
+
+  T getNearestObject (const Vector<int>& pos, std::list<bool (*)(void*)> *filters) const
+    {
+      int diff = -1;
+      typename LocationList<T>::const_iterator diffit;
+      for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
+        {
+          Vector<int> p = (*it)->getPos();
+          int delta = abs(p.x - pos.x) + abs(p.y - pos.y);
+         if (filters)
+           {
+             std::list<bool (*)(void*)>::iterator fit = filters->begin();
+             bool filtered = false;
+             for (; fit != filters->end(); fit++)
+               {
+                 if ((*fit)(*it) == true)
+                   {
+                     filtered = true;
+                     break;
+                   }
+                   
+               }
+             if (filtered)
+               continue;
+           }
+
+          if ((diff > delta) || (diff == -1))
+            {
+              diff = delta;
+              diffit = it;
+            }
+        }
+      if (diff == -1) return 0;
+      return (*diffit);
+    }
+
+  T getNearestObject (const Vector<int>& pos) const
+    {
+      return getNearestObject (pos, NULL);
+    }
+
+  T getNearestObjectBefore (const Vector<int>& pos, int dist) const
+    {
+      T t = getNearestObject(pos);
+      if (!t)
+       return NULL;
+      if (t->getPos().x <= pos.x + dist && t->getPos().x >= pos.x - dist &&
+          t->getPos().y <= pos.y + dist && t->getPos().y >= pos.y - dist)
+        return t;
+      return NULL;
+    }
+
+  T getNearestObjectAfter(const Vector<int>& pos, int dist, 
+                          std::list<bool (*)(void*)> *filters) const
+    {
+      int diff = -1;
+      typename LocationList<T>::const_iterator diffit;
+
+      for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
+        {
+         if (filters)
+           {
+             std::list<bool (*)(void*)>::iterator fit = filters->begin();
+             bool filtered = false;
+             for (; fit != filters->end(); fit++)
+               {
+                 if ((*fit)(*it) == true)
+                   {
+                     filtered = true;
+                     break;
+                   }
+                   
+               }
+             if (filtered)
+               continue;
+           }
+          
+            Vector<int> p = (*it)->getPos();
+            int delta = abs(p.x - pos.x);
+            if (delta < abs(p.y - pos.y))
+                delta = abs(p.y - pos.y);
+          
+            if ((diff > delta && delta >= dist) || (diff == -1))
+              {
+                diff = delta;
+                diffit = it;
+              }
+        }
+    
+      if (diff == -1) return 0;
+      return (*diffit);
+    }
+
+  T getById(guint32 id)
+  {
+      if (d_id.find(id) == d_id.end())
+       return NULL;
+      else
+       return (*d_id.find(id)).second;
+    return 0;
+  }
+       
+ protected:
+  typedef std::map<Vector<int>, T> PositionMap;
+  typedef std::map<guint32, T> IdMap;
+  PositionMap d_object;
+  IdMap d_id;
+
+};
+
+#endif // LOCATIONLIST_H
+
+// End of file