initial commit, lordsawar source, slightly modified
[lordsawar] / src / shieldset.cpp
1 //  Copyright (C) 2008, 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
18 #include <iostream>
19 #include <expat.h>
20 #include "rectangle.h"
21 #include <sigc++/functors/mem_fun.h>
22
23 #include <string.h>
24 #include "shieldset.h"
25 #include "shieldstyle.h"
26 #include "File.h"
27
28 using namespace std;
29
30 std::string Shieldset::d_tag = "shieldset";
31 std::string Shieldset::file_extension = SHIELDSET_EXT;
32
33 #define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
34 //#define debug(x)
35
36 Shieldset::Shieldset(guint32 id, std::string name)
37         : d_id(id), d_name(name), d_copyright(""), d_license(""), d_info(""), 
38         d_subdir("")
39 {
40 }
41
42 Shieldset::Shieldset(XML_Helper *helper, std::string directory)
43         : d_subdir("")
44 {
45   setDirectory(directory);
46   helper->getData(d_id, "id");
47   helper->getData(d_name, "name");
48   helper->getData(d_copyright, "copyright");
49   helper->getData(d_license, "license");
50   helper->getData(d_info, "info");
51   helper->getData(d_small_width, "small_width");
52   helper->getData(d_small_height, "small_height");
53   helper->getData(d_medium_width, "medium_width");
54   helper->getData(d_medium_height, "medium_height");
55   helper->getData(d_large_width, "large_width");
56   helper->getData(d_large_height, "large_height");
57   helper->registerTag(Shield::d_tag, 
58                       sigc::mem_fun((*this), &Shieldset::loadShield));
59   helper->registerTag(ShieldStyle::d_tag, sigc::mem_fun((*this), 
60                                                         &Shieldset::loadShield));
61   clear();
62 }
63
64 Shieldset::~Shieldset()
65 {
66   uninstantiateImages();
67   for (iterator it = begin(); it != end(); it++)
68     delete *it;
69 }
70
71 ShieldStyle * Shieldset::lookupShieldByTypeAndColour(guint32 type, guint32 colour) const
72 {
73   for (const_iterator it = begin(); it != end(); it++)
74     {
75       for (Shield::const_iterator i = (*it)->begin(); i != (*it)->end(); i++)
76         {
77           if ((*i)->getType() == type && (*it)->getOwner() == colour)
78             return *i;
79         }
80     }
81   return NULL;
82 }
83
84 Gdk::Color Shieldset::getColor(guint32 owner) const
85 {
86   for (const_iterator it = begin(); it != end(); it++)
87     {
88       if ((*it)->getOwner() == owner)
89         return (*it)->getColor();
90     }
91   return Gdk::Color("black");
92 }
93
94 bool Shieldset::loadShield(std::string tag, XML_Helper* helper)
95 {
96   if (tag == Shield::d_tag)
97     {
98       Shield* sh = new Shield(helper);
99       push_back(sh);
100       return true;
101     }
102   if (tag == ShieldStyle::d_tag)
103     {
104       ShieldStyle *sh = new ShieldStyle(helper);
105       (*back()).push_back(sh);
106       return true;
107     }
108   return false;
109 }
110
111
112 class ShieldsetLoader
113 {
114 public:
115     ShieldsetLoader(std::string filename)
116       {
117         shieldset = NULL;
118         dir = File::get_dirname(filename);
119         if (File::nameEndsWith(filename, Shieldset::file_extension) == false)
120           filename += Shieldset::file_extension;
121         XML_Helper helper(filename, ios::in, false);
122         helper.registerTag(Shieldset::d_tag, sigc::mem_fun((*this), &ShieldsetLoader::load));
123         if (!helper.parse())
124           {
125             std::cerr << "Error, while loading an shieldset. Shieldset Name: ";
126             std::cerr <<File::get_basename(File::get_dirname(filename))<<
127               std::endl <<std::flush;
128             if (shieldset != NULL)
129               delete shieldset;
130             shieldset = NULL;
131           }
132       };
133     bool load(std::string tag, XML_Helper* helper)
134       {
135         if (tag == Shieldset::d_tag)
136           {
137             shieldset = new Shieldset(helper, dir);
138             return true;
139           }
140         return false;
141       };
142     std::string dir;
143     Shieldset *shieldset;
144 };
145
146 Shieldset *Shieldset::create(std::string filename)
147 {
148   ShieldsetLoader d(filename);
149   return d.shieldset;
150 }
151
152 void Shieldset::getFilenames(std::list<std::string> &files) const
153 {
154   for (const_iterator it = begin(); it != end(); it++)
155     for (Shield::const_iterator i = (*it)->begin(); i != (*it)->end(); i++)
156       {
157         std::string file = (*i)->getImageName();
158         if (std::find(files.begin(), files.end(), file) == files.end())
159           files.push_back(file);
160       }
161 }
162
163 bool Shieldset::save(XML_Helper *helper) const
164 {
165   bool retval = true;
166
167   retval &= helper->openTag(d_tag);
168   retval &= helper->saveData("id", d_id);
169   retval &= helper->saveData("name", d_name);
170   retval &= helper->saveData("copyright", d_copyright);
171   retval &= helper->saveData("license", d_license);
172   retval &= helper->saveData("info", d_info);
173   retval &= helper->saveData("small_width", d_small_width);
174   retval &= helper->saveData("small_height", d_small_height);
175   retval &= helper->saveData("medium_width", d_medium_width);
176   retval &= helper->saveData("medium_height", d_medium_height);
177   retval &= helper->saveData("large_width", d_large_width);
178   retval &= helper->saveData("large_height", d_large_height);
179   for (const_iterator it = begin(); it != end(); it++)
180     retval &= (*it)->save(helper);
181   retval &= helper->closeTag();
182   return retval;
183 }
184
185 void Shieldset::instantiateImages()
186 {
187   for (iterator it = begin(); it != end(); it++)
188     (*it)->instantiateImages(this);
189 }
190
191 void Shieldset::uninstantiateImages()
192 {
193   for (iterator it = begin(); it != end(); it++)
194     (*it)->uninstantiateImages();
195 }
196
197 std::string Shieldset::getConfigurationFile() const
198 {
199   return getDirectory() + d_subdir + file_extension;
200 }
201
202 std::list<std::string> Shieldset::scanUserCollection()
203 {
204   return File::scanFiles(File::getUserShieldsetDir(), file_extension);
205 }
206
207 std::list<std::string> Shieldset::scanSystemCollection()
208 {
209   std::list<std::string> retlist = File::scanFiles(File::getShieldsetDir(), 
210                                                    file_extension);
211   if (retlist.empty())
212     {
213       std::cerr << "Couldn't find any shieldsets!" << std::endl;
214       std::cerr << "Please check the path settings in /etc/lordsawarrc or ~/.lordsawarrc" << std::endl;
215       std::cerr << "Exiting!" << std::endl;
216       exit(-1);
217     }
218
219   return retlist;
220 }
221
222         
223 bool Shieldset::validate() const
224 {
225   bool valid = true;
226   if (validateNumberOfShields() == false)
227     return false;
228   for (unsigned int i = Shield::WHITE; i <= Shield::NEUTRAL; i++)
229     {
230       if (validateShieldImages(Shield::Colour(i)) == false)
231         return false;
232     }
233   return valid;
234 }
235
236 bool Shieldset::validateNumberOfShields() const
237 {
238   int players[MAX_PLAYERS + 1][3];
239   memset(players, 0, sizeof(players));
240   //need at least 3 complete player shields, one of which must be neutral.
241   for (const_iterator it = begin(); it != end(); it++)
242     {
243       for (Shield::const_iterator i = (*it)->begin(); i != (*it)->end(); i++)
244         {
245           int idx = 0;
246           switch ((*i)->getType())
247             {
248             case ShieldStyle::SMALL: idx = 0; break;
249             case ShieldStyle::MEDIUM: idx = 1; break;
250             case ShieldStyle::LARGE: idx = 2; break;
251             }
252           players[(*it)->getOwner()][idx]++;
253         }
254     }
255   int count = 0;
256   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
257     {
258       if (players[i][0] > 0 && players[i][1] > 0 && players[i][2] > 0)
259         count++;
260     }
261   if (count <= 2)
262     return false;
263   if (players[MAX_PLAYERS][0] == 0 || players[MAX_PLAYERS][1] == 0 || players[MAX_PLAYERS][2] == 0)
264     return false;
265   return true;
266 }
267
268 bool Shieldset::validateShieldImages(Shield::Colour c) const
269 {
270   //if we have a shield, it should have all 3 sizes.
271   int player[3];
272   memset(player, 0, sizeof(player));
273   for (const_iterator it = begin(); it != end(); it++)
274     {
275       if ((*it)->getOwner() != guint32(c))
276         continue;
277       for (Shield::const_iterator i = (*it)->begin(); i != (*it)->end(); i++)
278         {
279           int idx = 0;
280           switch ((*i)->getType())
281             {
282             case ShieldStyle::SMALL: idx = 0; break;
283             case ShieldStyle::MEDIUM: idx = 1; break;
284             case ShieldStyle::LARGE: idx = 2; break;
285             }
286           if ((*i)->getImageName().empty() == false)
287             player[idx]++;
288         }
289     }
290   int count = player[0] + player[1] + player[2];
291   if (count <= 2)
292     return false;
293   return true;
294 }
295 //End of file