1 //  Copyright (C) 2000, 2001, 2003 Michael Bartl
2 //  Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 //  Copyright (C) 2002 Mark L. Amidon
4 //  Copyright (C) 2005 Andrea Paternesi
5 //  Copyright (C) 2006, 2007, 2008, 2014, 2015 Ben Asselstine
6 //  Copyright (C) 2008 Ole Laursen
7 //
8 //  This program is free software; you can redistribute it and/or modify
9 //  it under the terms of the GNU General Public License as published by
10 //  the Free Software Foundation; either version 3 of the License, or
11 //  (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU Library General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 //  02110-1301, USA.
22 
23 #include <sstream>
24 #include "prodslotlist.h"
25 #include "path.h"
26 #include "army.h"
27 #include "armyprodbase.h"
28 #include "hero.h"
29 #include "stacklist.h"
30 #include "stack.h"
31 #include "playerlist.h"
32 #include "armysetlist.h"
33 #include "citylist.h"
34 #include "GameMap.h"
35 #include "vectoredunitlist.h"
36 #include "vectoredunit.h"
37 #include "action.h"
38 #include "xmlhelper.h"
39 
40 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
41 #define debug(x)
42 
ProdSlotlist(guint32 numslots)43 ProdSlotlist::ProdSlotlist(guint32 numslots)
44      : d_active_production_slot(-1), d_duration(-1)
45 {
46   // Initialise armytypes
47   for (unsigned int i = 0; i < numslots; i++)
48     push_back(new ProdSlot());
49 
50 }
51 
ProdSlotlist(XML_Helper * helper)52 ProdSlotlist::ProdSlotlist(XML_Helper* helper)
53 {
54   helper->getData(d_active_production_slot, "active_production_slot");
55   helper->getData(d_duration, "duration");
56   helper->registerTag(ProdSlot::d_tag,
57 		      sigc::mem_fun(this, &ProdSlotlist::load));
58 }
59 
load(Glib::ustring tag,XML_Helper * helper)60 bool ProdSlotlist::load(Glib::ustring tag, XML_Helper *helper)
61 {
62   if (tag == ProdSlot::d_tag)
63     {
64       push_back(new ProdSlot(helper));
65       return true;
66     }
67   return false;
68 }
69 
ProdSlotlist(const ProdSlotlist & c)70 ProdSlotlist::ProdSlotlist(const ProdSlotlist& c)
71     :std::vector<ProdSlot*>(),
72     d_active_production_slot(c.d_active_production_slot),
73     d_duration(c.d_duration)
74 {
75   for (std::vector<ProdSlot*>::const_iterator it = c.begin();
76        it != c.end(); it++)
77     push_back(new ProdSlot(*(*it)));
78 }
79 
save(XML_Helper * helper) const80 bool ProdSlotlist::save(XML_Helper* helper) const
81 {
82     bool retval = true;
83 
84     retval &= helper->saveData("active_production_slot",
85 			       d_active_production_slot);
86     retval &= helper->saveData("duration", d_duration);
87 
88     for (unsigned int i = 0; i < size(); i++)
89       {
90 	if ((*this)[i])
91 	  retval &= (*this)[i]->save(helper);
92       }
93     return retval;
94 }
95 
~ProdSlotlist()96 ProdSlotlist::~ProdSlotlist()
97 {
98   for (unsigned int i = 0; i < size(); i++)
99     delete (*this)[i];
100   clear();
101 }
102 
getNoOfProductionBases() const103 guint32 ProdSlotlist::getNoOfProductionBases() const
104 {
105   unsigned int max = 0;
106   for (unsigned int i = 0; i < getMaxNoOfProductionBases(); i++)
107     {
108       if (getProductionBase(i))
109         max++;
110     }
111   return max;
112 }
113 
setActiveProductionSlot(int index)114 void ProdSlotlist::setActiveProductionSlot(int index)
115 {
116     if (index == -1)
117     {
118         d_active_production_slot = index;
119         d_duration = -1;
120         return;
121     }
122 
123     // return on wrong data
124     if (((index >= (int)size())) ||
125 	(index >= 0 && getArmytype(index) == -1))
126         return;
127 
128     d_active_production_slot = index;
129     const ArmyProdBase* a = getProductionBase(index);
130 
131     // set the duration to produce this armytype
132     if (a)
133         d_duration = a->getProduction();
134 }
135 
getFreeSlot() const136 int ProdSlotlist::getFreeSlot()  const
137 {
138      int index=-1;
139 
140      debug(getName()<< " BASIC SLOTS=" << size())
141      for (unsigned int i = 0; i < size(); i++)
142      {
143          debug(getName()<< " Index Value=" << (*this)[i])
144          if ((*this)[i]->getArmyProdBase() == NULL)
145          {
146              index=i;
147              return i;
148          }
149      }
150 
151      return index;
152 }
153 
hasProductionBase(const ArmyProto * army) const154 bool ProdSlotlist::hasProductionBase(const ArmyProto * army) const
155 {
156   return hasProductionBase(army->getId());
157 }
158 
addProductionBase(int idx,ArmyProdBase * army)159 void ProdSlotlist::addProductionBase(int idx, ArmyProdBase *army)
160 {
161     if (idx < 0)
162     {
163         // try to find an unoccupied production slot. If there is none, pick
164         // the slot with the highest index.
165         for (unsigned int i = 0; i < size(); i++)
166             if ((*this)[i]->getArmyProdBase() == NULL)
167             {
168                 idx = i;
169                 break;
170             }
171 
172         if (idx < 0)
173         {
174             idx = size() - 1;
175         }
176     }
177     if (idx >= (int)size())
178       return;
179 
180     if ((*this)[idx]->getArmyProdBase())
181       {
182 	bool restore_production = false;
183 	if (d_active_production_slot == idx)
184 	  restore_production = true;
185 	removeProductionBase(idx);
186 	(*this)[idx]->setArmyProdBase(army);
187 	if (restore_production)
188 	  setActiveProductionSlot(idx);
189       }
190     else
191       (*this)[idx]->setArmyProdBase(army);
192 }
193 
removeProductionBase(int idx)194 void ProdSlotlist::removeProductionBase(int idx)
195 {
196     if ((idx < 0) || (idx > (int)(getMaxNoOfProductionBases() - 1)))
197         return;
198 
199     if ((*this)[idx]->getArmyProdBase() != NULL)
200       (*this)[idx]->clear();
201 
202     if (d_active_production_slot == idx)
203         setActiveProductionSlot(-1);
204 }
205 
hasProductionBase(int type) const206 bool ProdSlotlist::hasProductionBase(int type) const
207 {
208   if (type < 0)
209     return false;
210   for (unsigned int i = 0; i < size(); i++)
211     {
212       if ((*this)[i]->getArmyProdBase() == NULL)
213 	continue;
214       if ((*this)[i]->getArmyProdBase()->getTypeId() == (unsigned int) type)
215 	return true;
216     }
217 
218   return false;
219 }
220 
getArmytype(int slot) const221 int ProdSlotlist::getArmytype(int slot) const
222 {
223   if (slot < 0)
224     return -1;
225 
226   if (slot >= (int)size())
227     return -1;
228   if ((*this)[slot]->getArmyProdBase() == NULL)
229     return -1;
230   return (*this)[slot]->getArmyProdBase()->getTypeId();
231 }
232 
getProductionBase(int slot) const233 const ArmyProdBase * ProdSlotlist::getProductionBase(int slot) const
234 {
235   if (getArmytype(slot) == -1)
236     return 0;
237   return (*this)[slot]->getArmyProdBase();
238 }
239 
getActiveProductionBase() const240 const ArmyProdBase *ProdSlotlist::getActiveProductionBase() const
241 {
242   return getProductionBase(d_active_production_slot);
243 }
244 
getProductionBaseBelongingTo(const Army * army) const245 const ArmyProdBase *ProdSlotlist::getProductionBaseBelongingTo(const Army *army) const
246 {
247   if (!army)
248     return NULL;
249   for (unsigned int i = 0; i < this->getMaxNoOfProductionBases(); i++)
250     {
251       const ArmyProdBase* armyprodbase = this->getProductionBase(i);
252       if (armyprodbase == NULL)
253 	continue;
254       if (army->getArmyset() == armyprodbase->getArmyset() &&
255 	  army->getTypeId() == armyprodbase->getTypeId())
256 	return armyprodbase;
257     }
258   return NULL;
259 }
260 
removeArmyProdBasesWithoutAType(guint32 armyset)261 bool ProdSlotlist::removeArmyProdBasesWithoutAType(guint32 armyset)
262 {
263   bool removed = false;
264   for (unsigned int i = 0; i < size(); i++)
265     {
266       const ArmyProdBase* armyprodbase = this->getProductionBase(i);
267       if (armyprodbase == NULL)
268 	continue;
269       ArmyProto *a = Armysetlist::getInstance()->getArmy (armyset, armyprodbase->getTypeId());
270       if (!a)
271         removeProductionBase(i);
272       //XXX XXX XXX should we squeeze out the empty spaces?
273     }
274   return removed;
275 }
276 // End of file
277