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