341d3141356d326fc60e3b9bbceaa05866b4813f
[lordsawar] / src / LocationBox.cpp
1 // Copyright (C) 2000, 2001, 2003 Michael Bartl
2 // Copyright (C) 2000, 2001, 2002, 2004, 2005 Ulf Lorenz
3 // Copyright (C) 2006 Andrea Paternesi
4 // Copyright (C) 2006, 2007, 2008, 2009 Ben Asselstine
5 //
6 //  This program is free software; you can redistribute it and/or modify
7 //  it under the terms of the GNU General Public License as published by
8 //  the Free Software Foundation; either version 3 of the License, or
9 //  (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU Library General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
19 //  02110-1301, USA.
20
21 #include "LocationBox.h"
22 #include "army.h"
23 #include "player.h"
24 #include "playerlist.h"
25 #include "stacklist.h"
26 #include "stack.h"
27 #include "FogMap.h"
28 #include "GameMap.h"
29 #include "stacktile.h"
30
31 #include "xmlhelper.h"
32
33 LocationBox::LocationBox(Vector<int> pos, guint32 size)
34     :Immovable(pos), d_size(size)
35 {
36 }
37
38 LocationBox::LocationBox(Vector<int> src, Vector<int> dest)
39     :Immovable(dist(Vector<int>(0,0), src) < dist(Vector<int>(0,0), dest) ?
40                src : dest)
41 {
42   if (dest.x > src.x)
43     d_size =  dest.x - src.x + 1;
44   else if (dest.x < src.x)
45     d_size =  src.x - dest.x + 1;
46   else
47     {
48       if (dest.y > src.y)
49         d_size =  dest.y - src.y + 1;
50       else
51         d_size =  src.y - dest.y + 1;
52     }
53 }
54
55 LocationBox::LocationBox(const LocationBox& loc)
56   : Immovable(loc), d_size(loc.d_size)
57 {
58 }
59
60 LocationBox::LocationBox(const LocationBox& loc, Vector<int> pos)
61   : Immovable(pos), d_size(loc.d_size)
62 {
63 }
64
65 LocationBox::LocationBox(XML_Helper* helper, guint32 size)
66     :Immovable(helper)
67 {
68     d_size = size;
69 }
70
71 LocationBox::~LocationBox()
72 {
73 }
74
75 Stack *LocationBox::addArmy(Army *a) const
76 {
77   Vector<int> pos = Vector<int>(-1,-1);
78   Stack* stack = getFreeStack(a->getOwner(), pos);
79
80   //no stacks with enough room for one more army, found lets create one.
81   if (!stack)
82     {
83       // No stack found in the entire location
84       if (pos == Vector<int>(-1,-1))
85         return NULL;
86             
87       Player *p = a->getOwner();
88       stack = new Stack(p, pos);
89       stack->add(a);
90       p->addStack(stack);
91     }
92   else
93     stack->add(a);
94
95   if (stack->size() > 1)
96     stack->sortForViewing(true);
97   stack->setDefending(false);
98   stack->setParked(false);
99   return stack;
100 }
101
102 bool LocationBox::isFull(Player *p) const
103 {
104   for (unsigned int i = 0; i < d_size; i++)
105     for (unsigned int j = 0; j < d_size; j++)
106       {
107         Vector<int> pos = getPos() + Vector<int>(j,i);
108         StackTile *stile = GameMap::getInstance()->getTile(pos)->getStacks();
109         if (stile->canAdd(1, p) == true)
110           return false;
111       }
112     return true;
113 }
114
115 Stack* LocationBox::getFreeStack(Player *p, Vector<int> &tile) const
116 {
117   for (unsigned int i = 0; i < d_size; i++)
118     for (unsigned int j = 0; j < d_size; j++)
119       {
120         Vector<int> pos = getPos() + Vector<int>(j,i);
121         if (GameMap::canAddArmy(pos) == false)
122           continue;
123         StackTile *stile = GameMap::getInstance()->getTile(pos)->getStacks();
124         Stack *stack = stile->getFriendlyStack(p);
125         if (stack == NULL)
126           {
127             tile = pos;
128             return NULL;
129           }
130         else 
131           {
132             Stack *enemy = stile->getEnemyStack(p);
133             if (!enemy && stack->isFull() == false)
134               return stack;
135           }
136         }
137   tile = Vector<int>(-1,-1);
138   return NULL;
139 }
140
141 bool LocationBox::isVisible(Player *player) const
142 {
143   for (unsigned int i = 0; i < d_size; i++)
144     for (unsigned int j = 0; j < d_size; j++)
145       {
146         Vector<int> pos;
147         pos.x = getPos().x + i;
148         pos.y = getPos().y + j;
149         if (FogMap::isClear(pos, player))
150           return true;
151       }
152   return false;
153 }
154
155 void LocationBox::deFog() const
156 {
157   Player *p = Playerlist::getActiveplayer();
158   if (!p)
159     return;
160   FogMap *fogmap = p->getFogMap();
161   fogmap->alterFogRadius (getPos(), 3, FogMap::OPEN);
162 }
163
164 void LocationBox::deFog(Player *p) const
165 {
166   if (!p)
167     return;
168   FogMap *fogmap = p->getFogMap();
169   if (!fogmap)
170     return;
171   fogmap->alterFogRadius (getPos(), 3, FogMap::OPEN);
172 }
173
174 bool LocationBox::contains(Vector<int> pos) const
175 {
176     return (pos.x >= getPos().x) && (pos.x < getPos().x + (int) d_size) 
177       && (pos.y >= getPos().y) && (pos.y < getPos().y + (int) d_size);
178 }
179
180     
181 bool LocationBox::isCompletelyObscuredByFog(Player *p) const
182 {
183   for (unsigned int i = 0; i < d_size; i++)
184     for (unsigned int j = 0; j < d_size; j++)
185       {
186         Vector<int> pos = Vector<int>(i,j);
187         if (p->getFogMap()->isCompletelyObscuredFogTile(pos) == false)
188           return false;
189       }
190   return true;
191 }
192
193 Vector<int> LocationBox::getNearestPos(Movable *m) const
194 {
195   return getNearestPos(m->getPos());
196 }
197
198 Vector<int> LocationBox::getNearestPos(Vector<int> pos) const
199 {
200   int min_dist = -1;
201   Vector<int> closest_tile = Vector<int>(-1,-1);
202   for (unsigned int i = 0; i < d_size; i++)
203     for (unsigned int j = 0; j < d_size; j++)
204       {
205         Vector<int> target = Vector<int>(i,j) + getPos();
206         int d = dist(pos, target);
207         if (d < min_dist || min_dist == -1)
208           {
209             min_dist = d;
210             closest_tile = target;
211           }
212       }
213   return closest_tile;
214 }