initial commit, lordsawar source, slightly modified
[lordsawar] / src / stacktile.cpp
1 // Copyright (C) 2009 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
16 //  02110-1301, USA.
17 #include <assert.h>
18 #include "stacktile.h"
19 #include "stack.h"
20 #include "defs.h"
21 #include "vector.h"
22 #include "player.h"
23 #include "stacklist.h"
24 #include "playerlist.h"
25 #include "Tile.h"
26
27 StackTile::StackTile(Vector<int> pos)
28   :tile(pos)
29 {
30 }
31
32 StackTile::~StackTile()
33 {
34 }
35
36 bool StackTile::canAdd(const Stack *stack)
37 {
38   //it's not a bug if the stack is already on this tile.
39   //two or more stacks have to be on the same stacktile to join.
40   //it's not a bug if more than MAX_ARMIES_ON_A_SINGLE_TILE is exceeded
41   //temporarily.  too large stacks can pass through, but not stay.
42   if (findStack(stack) != end())
43     return true;
44   return canAdd(stack->size(), stack->getOwner());
45 }
46     
47 bool StackTile::canAdd(guint32 size, Player *owner)
48 {
49   if (size == 0)
50     return false;
51   if (countNumberOfArmies(owner) + size > MAX_ARMIES_ON_A_SINGLE_TILE)
52     return false;
53   return true;
54 }
55
56 bool StackTile::leaving(Stack *stack)
57 {
58   bool first = true;
59   while (1)
60     {
61       iterator it = findStack(stack);
62       if (it == end())
63         {
64           if (first)
65             return false;
66           else
67             break;
68         }
69       erase(it);
70     }
71   return true;
72 }
73
74 void StackTile::arriving(Stack *stack)
75 {
76   add(stack);
77 }
78
79 void StackTile::add(Stack *stack)
80 {
81   iterator it = findStack(stack);
82   if (it != end()) //we replace existing entries, to make this work sans game.
83     leaving(stack);
84   struct StackTileRecord rec;
85   rec.stack_id = stack->getId();
86   rec.player_id = stack->getOwner()->getId();
87   push_back(rec);
88   //i could stack->setpos here, but i prefer to let Stack::moveToDest do that because it's movement related, and this class is not movement related.
89 }
90
91 guint32 StackTile::countNumberOfArmies(Player *owner) const
92 {
93   guint32 count = 0;
94   for (const_iterator it = begin(); it != end(); it++)
95     {
96       if ((*it).player_id == owner->getId())
97         {
98           Stack *stack = owner->getStacklist()->getStackById((*it).stack_id);
99           if (stack)
100             count += stack->size();
101         }
102     }
103   return count;
104 }
105
106 StackTile::iterator StackTile::findStack(Stack *s)
107 {
108   for (iterator it = begin(); it != end(); it++)
109     if (s->getId() == (*it).stack_id)
110       return it;
111   return end();
112 }
113
114 StackTile::const_iterator StackTile::findStack(const Stack *s) const
115 {
116   for (const_iterator it = begin(); it != end(); it++)
117     if (s->getId() == (*it).stack_id)
118       return it;
119   return end();
120 }
121
122 Stack *StackTile::getStack() const
123 {
124   if (size() > 0)
125     {
126       StackTileRecord rec = front();
127       Player *p = Playerlist::getInstance()->getPlayer(rec.player_id);
128       return p->getStacklist()->getStackById(rec.stack_id);
129     }
130   return NULL;
131 }
132
133 std::list<Stack *> StackTile::getStacks() const
134 {
135   std::list<Stack *> stacks;
136   for (const_iterator it = begin(); it != end(); it++)
137     {
138       Playerlist *pl = Playerlist::getInstance();
139       for (Playerlist::iterator i = pl->begin(); i != pl->end(); i++)
140         {
141           Stack *stack = (*i)->getStacklist()->getStackById((*it).stack_id);
142           if (stack)
143             stacks.push_back(stack);
144         }
145     }
146   return stacks;
147 }
148
149 std::list<Stack *> StackTile::getFriendlyStacks(Player *owner) const
150 {
151   std::list<Stack *> stacks;
152   for (const_iterator it = begin(); it != end(); it++)
153     {
154       if ((*it).player_id != owner->getId())
155         continue;
156       Stack *stack = owner->getStacklist()->getStackById((*it).stack_id);
157       if (stack)
158         stacks.push_back(stack);
159     }
160   return stacks;
161 }
162 Stack *StackTile::getFriendlyStack(Player *owner) const
163 {
164   //return just one of the stacks located here, but owned by OWNER
165   for (const_iterator it = begin(); it != end(); it++)
166     {
167       if ((*it).player_id != owner->getId())
168         continue;
169       Stack *stack = owner->getStacklist()->getStackById((*it).stack_id);
170       if (stack)
171         return stack;
172     }
173   return NULL;
174 }
175
176 Stack *StackTile::getEnemyStack(Player *owner) const
177 {
178   //return just one of the stacks located here, but not owned by OWNER
179   for (const_iterator it = begin(); it != end(); it++)
180     {
181       if ((*it).player_id == owner->getId())
182         continue;
183       Player *p = Playerlist::getInstance()->getPlayer((*it).player_id);
184       Stack *stack = p->getStacklist()->getStackById((*it).stack_id);
185       if (stack)
186         return stack;
187     }
188   return NULL;
189 }
190
191 std::list<Stack *> StackTile::getEnemyStacks(Player *owner) const
192 {
193   std::list<Stack *> stacks;
194   for (const_iterator it = begin(); it != end(); it++)
195     {
196       if ((*it).player_id == owner->getId())
197         continue;
198       Player *p = Playerlist::getInstance()->getPlayer((*it).player_id);
199       Stack *stack = p->getStacklist()->getStackById((*it).stack_id);
200       if (stack)
201         stacks.push_back(stack);
202     }
203   return stacks;
204 }
205
206 Stack *StackTile::getOtherStack(Stack *stack) const
207 {
208   if (findStack(stack) == end())
209     return NULL;
210   for (const_iterator it = begin(); it != end(); it++)
211     {
212       if (stack->getId() != (*it).stack_id)
213         {
214           //great, this is a stack id that isn't us.
215           //now go get the stack from somebody's stacklist.
216           if (stack->getOwner()->getId() != (*it).player_id)
217             continue;
218           Player *p = stack->getOwner();
219           Stack *other = p->getStacklist()->getStackById((*it).stack_id);
220           if (other)
221             return other;
222         }
223     }
224   return NULL;
225 }
226     
227 bool StackTile::contains(guint32 id) const
228 {
229   for (const_iterator it = begin(); it != end(); it++)
230     if ((*it).stack_id == id)
231       return true;
232   return false;
233 }
234
235 Stack *StackTile::group(Player *owner)
236 {
237   return groupStacks(owner, NULL);
238 }
239
240 void StackTile::group(Player *owner, Stack *stack)
241 {
242   groupStacks(owner, stack);
243   return;
244 }
245
246 Stack *StackTile::groupStacks(Player *owner, Stack *stack)
247 {
248   std::list<Stack*> stacks = getFriendlyStacks(owner);
249   if (stack == NULL)
250     {
251       if (stacks.size() > 0)
252         stack = stacks.front();
253     }
254   else if (findStack(stack) == end())
255     return NULL;
256
257   for (std::list<Stack*>::iterator i = stacks.begin(); i != stacks.end(); i++)
258     {
259       if (*i == stack)
260         continue;
261       bool joined = owner->stackJoin(stack, *i);
262       assert (joined == true);
263     }
264   return stack;
265 }
266
267 //! split all of the armies owned by OWNER into a stack by themselves
268 void StackTile::ungroup(Player *owner)
269 {
270   std::list<Stack*> stacks = getFriendlyStacks(owner);
271   std::list<Army *> armies;
272   for (std::list<Stack*>::iterator i = stacks.begin(); i != stacks.end(); i++)
273     {
274       bool first = true;
275       for (Stack::iterator j = (*i)->begin(); j != (*i)->end(); j++)
276         {
277           if (first == true)
278             {
279               //skip one army of every stack because it doesn't need a new one.
280               first = false;
281               continue;
282             }
283           else
284             {
285               owner->stackSplitArmy(*i, *j);
286               j = (*i)->begin();
287             }
288         }
289     }
290
291 }
292     
293 void StackTile::setDefending(Player *owner, bool defending)
294 {
295   std::list<Stack *> stks = getFriendlyStacks(owner);
296   for (std::list<Stack *>::iterator it = stks.begin(); it != stks.end(); it++)
297     (*it)->setDefending(defending);
298 }
299
300 void StackTile::setParked(Player *owner, bool parked)
301 {
302   std::list<Stack *> stks = getFriendlyStacks(owner);
303   for (std::list<Stack *>::iterator it = stks.begin(); it != stks.end(); it++)
304     (*it)->setParked(parked);
305 }