1 // Copyright (C) 2001, 2003 Michael Bartl
2 // Copyright (C) 2004 Ulf Lorenz
3 // Copyright (C) 2005, 2006 Andrea Paternesi
4 // Copyright (C) 2007, 2008, 2009, 2012, 2014, 2015 Ben Asselstine
5 // Copyright (C) 2008 Ole Laursen
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 3 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU Library General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 //  02110-1301, USA.
21 
22 #pragma once
23 #ifndef LOCATIONLIST_H
24 #define LOCATIONLIST_H
25 
26 #include <gtkmm.h>
27 #include <algorithm>
28 #include <list>
29 #include <map>
30 #include "PathCalculator.h"
31 #include "vector.h"
32 #include "stack.h"
33 #include "maptile.h"
34 #include "Location.h"
35 
36 //! A template for holding and operatig on lists of Location objects.
37 /** A list for object instances
38   *
39   * This class extends the stl lists by adding the functions getObjectAt()
40   * which return the object at position (x,y). Necessary for such things as
41   * the city list.
42   */
43 
44 template<class T> class LocationList : public std::list<T>
45 {
46  public:
47 
LocationList()48   LocationList(){};
~LocationList()49   ~LocationList()
50     {
51       for (typename LocationList<T>::iterator it = this->begin(); it != this->end(); ++it)
52 	delete *it;
53       d_object.clear();
54       d_id.clear();
55     };
56 
add(T t)57   void add(T t)
58     {
59       this->push_back(t);
60       d_id[t->getId()] = t;
61       int s = t->getSize();
62       for (int i = 0; i < s; i++)
63 	for (int j = 0; j < s; j++)
64 	  {
65 	    Vector<int> pos = t->getPos() + Vector<int>(i,j);
66 	    d_object[pos] = t;
67 	  }
68     }
subtract(T t)69   void subtract(T t)
70     {
71       this->erase(std::find(this->begin(), this->end(), t));
72       d_id.erase(d_id.find(t->getId()));
73       int s = t->getSize();
74       for (int i = 0; i < s; i++)
75 	for (int j = 0; j < s; j++)
76 	  {
77 	    Vector<int> pos = t->getPos() + Vector<int>(i,j);
78             if (d_object.find(pos) != d_object.end())
79               d_object.erase(d_object.find(pos));
80 	  }
81       delete t;
82     }
83 
84   //! Returns the object at position (x,y).
getObjectAt(int x,int y)85   T getObjectAt(int x, int y) const
86     {
87       Vector<int> pos = Vector<int>(x,y);
88 
89       if (d_object.find(pos) == d_object.end())
90 	return NULL;
91       else
92 	return (*d_object.find(pos)).second;
93     }
94 
95   //! Returns the object at position pos.
getObjectAt(const Vector<int> & pos)96   T getObjectAt(const Vector<int>& pos) const
97     {
98       return getObjectAt(pos.x, pos.y);
99     }
100 
resizeLocations(Maptile::Building building_type,guint32 tile_width,guint32 old_tile_width,void (* func1)(Location *,Maptile::Building,guint32),void (* func2)(Location *,Maptile::Building,guint32))101 void resizeLocations(Maptile::Building building_type, guint32 tile_width, guint32 old_tile_width, void (*func1)(Location*, Maptile::Building, guint32), void (*func2)(Location*, Maptile::Building, guint32))
102 {
103   if (old_tile_width > tile_width)
104     {
105       for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
106         func1(*it, building_type, old_tile_width);
107     }
108   std::list<T> objs;
109   for (typename LocationList<T>::iterator it = this->begin(); it != this->end(); ++it)
110     objs.push_back(*it);
111 
112   for (typename std::list<T>::iterator i = objs.begin(); i != objs.end(); ++i)
113   //for (typename LocationList<T>::iterator it = this->begin(); it != this->end(); ++it)
114     func2((*i), building_type, tile_width);
115 }
116 
getNearestObjectInDir(const Vector<int> & pos,const Vector<int> dir)117   T getNearestObjectInDir(const Vector<int> &pos, const Vector<int> dir) const
118     {
119       int diff = -1;
120       typename LocationList<T>::const_iterator diffit;
121       for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
122         {
123           Vector<int> p = (*it)->getPos();
124           int delta = abs(p.x - pos.x) + abs(p.y - pos.y);
125 	  //if dir is -1, then the difference between pos.x and p.x should be positive
126 	  //if dir is +1, then the difference between pos.x and p.x should be negative
127 	  //if looking west, and the object is to the east
128 	  if (dir.x < 0 && (pos.x - p.x) <= 0)
129 	    continue;
130 	  //if looking east , and the object is to the west
131 	  if (dir.x > 0 && (pos.x - p.x) >= 0)
132 	    continue;
133 	  //if looking north, and the object is to the south
134 	  if (dir.y < 0 && (pos.y - p.y) <= 0)
135 	    continue;
136 	  //if looking south, and the object is to the north
137 	  if (dir.y > 0 && (pos.y - p.y) >= 0)
138 	    continue;
139 
140           if ((diff > delta) || (diff == -1))
141             {
142               diff = delta;
143               diffit = it;
144             }
145         }
146       if (diff == -1) return 0;
147       return (*diffit);
148     }
149 
getClosestObject(const Stack * stack,std::list<bool (*)(void *)> * filters)150   T getClosestObject (const Stack *stack, std::list<bool (*)(void*)> *filters) const
151     {
152       int diff = -1;
153       typename LocationList<T>::const_iterator diffit;
154       PathCalculator pc(stack, true, 0, 0);
155       for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
156         {
157           int delta = pc.calculate((*it)->getPos());
158           if (delta <= 0)
159             continue;
160 	  if (filters)
161 	    {
162 	      std::list<bool (*)(void*)>::iterator fit = filters->begin();
163 	      bool filtered = false;
164 	      for (; fit != filters->end(); fit++)
165 	        {
166 	          if ((*fit)(*it) == true)
167 	            {
168 		      filtered = true;
169 		      break;
170 	            }
171 
172 	        }
173 	      if (filtered)
174 	        continue;
175 	    }
176 
177           if ((diff > delta) || (diff == -1))
178             {
179               diff = delta;
180               diffit = it;
181             }
182         }
183       if (diff == -1) return 0;
184       return (*diffit);
185     }
186 
getClosestObject(const Stack * stack)187   T getClosestObject (const Stack *stack) const
188     {
189       return getClosestObject (stack, NULL);
190     }
191 
getNearestObject(const Vector<int> & pos,std::list<bool (*)(void *)> * filters)192   T getNearestObject (const Vector<int>& pos, std::list<bool (*)(void*)> *filters) const
193     {
194       int diff = -1;
195       typename LocationList<T>::const_iterator diffit;
196       for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
197         {
198           Vector<int> p = (*it)->getPos();
199           int delta = abs(p.x - pos.x) + abs(p.y - pos.y);
200 	  if (filters)
201 	    {
202 	      std::list<bool (*)(void*)>::iterator fit = filters->begin();
203 	      bool filtered = false;
204 	      for (; fit != filters->end(); fit++)
205 	        {
206 	          if ((*fit)(*it) == true)
207 	            {
208 		      filtered = true;
209 		      break;
210 	            }
211 
212 	        }
213 	      if (filtered)
214 	        continue;
215 	    }
216 
217           if ((diff > delta) || (diff == -1))
218             {
219               diff = delta;
220               diffit = it;
221             }
222         }
223       if (diff == -1) return 0;
224       return (*diffit);
225     }
226 
getNearestObject(const Vector<int> & pos)227   T getNearestObject (const Vector<int>& pos) const
228     {
229       return getNearestObject (pos, NULL);
230     }
231 
getNearestObjectBefore(const Vector<int> & pos,int dist)232   T getNearestObjectBefore (const Vector<int>& pos, int dist) const
233     {
234       T t = getNearestObject(pos);
235       if (!t)
236 	return NULL;
237       if (t->getPos().x <= pos.x + dist && t->getPos().x >= pos.x - dist &&
238           t->getPos().y <= pos.y + dist && t->getPos().y >= pos.y - dist)
239         return t;
240       return NULL;
241     }
242 
getNearestObjectAfter(const Vector<int> & pos,int dist,std::list<bool (*)(void *)> * filters)243   T getNearestObjectAfter(const Vector<int>& pos, int dist,
244 			   std::list<bool (*)(void*)> *filters) const
245     {
246       int diff = -1;
247       typename LocationList<T>::const_iterator diffit;
248 
249       for (typename LocationList<T>::const_iterator it = this->begin(); it != this->end(); ++it)
250         {
251 	  if (filters)
252 	    {
253 	      std::list<bool (*)(void*)>::iterator fit = filters->begin();
254 	      bool filtered = false;
255 	      for (; fit != filters->end(); fit++)
256 	        {
257 	          if ((*fit)(*it) == true)
258 	            {
259 		      filtered = true;
260 		      break;
261 	            }
262 
263 	        }
264 	      if (filtered)
265 	        continue;
266 	    }
267 
268             Vector<int> p = (*it)->getPos();
269             int delta = abs(p.x - pos.x);
270             if (delta < abs(p.y - pos.y))
271                 delta = abs(p.y - pos.y);
272 
273             if ((diff > delta && delta >= dist) || (diff == -1))
274               {
275                 diff = delta;
276                 diffit = it;
277               }
278         }
279 
280       if (diff == -1) return 0;
281       return (*diffit);
282     }
283 
getById(guint32 id)284   T getById(guint32 id)
285   {
286       if (d_id.find(id) == d_id.end())
287 	return NULL;
288       else
289 	return (*d_id.find(id)).second;
290     return 0;
291   }
292 
293  protected:
294   typedef std::map<Vector<int>, T> PositionMap;
295   typedef std::map<guint32, T> IdMap;
296   PositionMap d_object;
297   IdMap d_id;
298 
299 };
300 
301 #endif // LOCATIONLIST_H
302 
303 // End of file
304