initial commit, lordsawar source, slightly modified
[lordsawar] / src / cityset.cpp
1 // Copyright (C) 2008 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 <sigc++/functors/mem_fun.h>
19
20 #include "cityset.h"
21
22 #include "File.h"
23 #include "xmlhelper.h"
24 #include "gui/image-helpers.h"
25 #include "city.h"
26 #include "ruin.h"
27 #include "temple.h"
28
29 std::string Cityset::d_tag = "cityset";
30 std::string Cityset::file_extension = CITYSET_EXT;
31
32 using namespace std;
33
34 #include <iostream>
35 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
36 #define debug(x)
37
38 #define DEFAULT_CITY_TILE_SIZE 40
39 Cityset::Cityset(guint32 id, std::string name)
40         : d_id(id), d_name(name), d_copyright(""), d_license(""), 
41         d_tileSize(DEFAULT_CITY_TILE_SIZE), d_subdir("")
42 {
43         d_cities_filename = "";
44         d_razedcities_filename = "";
45         d_port_filename = "";
46         d_signpost_filename = "";
47         d_ruins_filename = "";
48         d_temples_filename = "";
49         d_towers_filename = "";
50         for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
51           citypics[i] = NULL;
52         for (unsigned int i = 0; i < MAX_PLAYERS; i++)
53           razedcitypics[i] = NULL;
54         port = NULL;
55         signpost = NULL;
56         for (unsigned int i = 0; i < RUIN_TYPES; i++)
57           ruinpics[i] = NULL;
58         for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
59           templepics[i] = NULL;
60         for (unsigned int i = 0; i < MAX_PLAYERS; i++)
61           towerpics[i] = NULL;
62
63         d_city_tile_width = 2;
64         d_temple_tile_width = 1;
65         d_ruin_tile_width = 1;
66 }
67
68 Cityset::Cityset(XML_Helper *helper, std::string directory)
69         :Set()
70 {
71   setDirectory(directory);
72   helper->getData(d_id, "id"); 
73   helper->getData(d_name, "name"); 
74   helper->getData(d_copyright, "copyright"); 
75   helper->getData(d_license, "license"); 
76   helper->getData(d_info, "info");
77   helper->getData(d_tileSize, "tilesize");
78   helper->getData(d_cities_filename, "cities");
79   helper->getData(d_razedcities_filename, "razed_cities");
80   helper->getData(d_port_filename, "port");
81   helper->getData(d_signpost_filename, "signpost");
82   helper->getData(d_ruins_filename, "ruins");
83   helper->getData(d_temples_filename, "temples");
84   helper->getData(d_towers_filename, "towers");
85   helper->getData(d_city_tile_width, "city_tile_width");
86   helper->getData(d_temple_tile_width, "temple_tile_width");
87   helper->getData(d_ruin_tile_width, "ruin_tile_width");
88   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
89     citypics[i] = NULL;
90   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
91     razedcitypics[i] = NULL;
92   for (unsigned int i = 0; i < RUIN_TYPES; i++)
93     ruinpics[i] = NULL;
94   for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
95     templepics[i] = NULL;
96   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
97     towerpics[i] = NULL;
98   port = NULL;
99   signpost = NULL;
100 }
101
102 Cityset::~Cityset()
103 {
104   uninstantiateImages();
105 }
106
107 class CitysetLoader
108 {
109 public:
110     CitysetLoader(std::string filename)
111       {
112         cityset = NULL;
113         dir = File::get_dirname(filename);
114         if (File::nameEndsWith(filename, Cityset::file_extension) == false)
115           filename += Cityset::file_extension;
116         XML_Helper helper(filename, ios::in, false);
117         helper.registerTag(Cityset::d_tag, sigc::mem_fun((*this), &CitysetLoader::load));
118         if (!helper.parse())
119           {
120             std::cerr << "Error, while loading an cityset. Cityset Name: ";
121             std::cerr <<File::get_basename(filename)<<std::endl <<std::flush;
122             if (cityset != NULL)
123               delete cityset;
124             cityset = NULL;
125           }
126       };
127     bool load(std::string tag, XML_Helper* helper)
128       {
129         if (tag == Cityset::d_tag)
130           {
131             cityset = new Cityset(helper, dir);
132             return true;
133           }
134         return false;
135       };
136     std::string dir;
137     Cityset *cityset;
138 };
139 Cityset *Cityset::create(std::string file)
140 {
141   CitysetLoader d(file);
142   return d.cityset;
143 }
144 void Cityset::getFilenames(std::list<std::string> &files)
145 {
146   files.push_back(d_cities_filename);
147   files.push_back(d_razedcities_filename);
148   files.push_back(d_port_filename);
149   files.push_back(d_signpost_filename);
150   files.push_back(d_ruins_filename);
151   files.push_back(d_temples_filename);
152   files.push_back(d_towers_filename);
153 }
154
155 bool Cityset::save(XML_Helper *helper)
156 {
157   bool retval = true;
158
159   retval &= helper->openTag(d_tag);
160   retval &= helper->saveData("id", d_id); 
161   retval &= helper->saveData("name", d_name); 
162   retval &= helper->saveData("copyright", d_copyright); 
163   retval &= helper->saveData("license", d_license); 
164   retval &= helper->saveData("info", d_info);
165   retval &= helper->saveData("tilesize", d_tileSize);
166   retval &= helper->saveData("cities", d_cities_filename);
167   retval &= helper->saveData("razed_cities", d_razedcities_filename);
168   retval &= helper->saveData("port", d_port_filename);
169   retval &= helper->saveData("signpost", d_signpost_filename);
170   retval &= helper->saveData("ruins", d_ruins_filename);
171   retval &= helper->saveData("temples", d_temples_filename);
172   retval &= helper->saveData("towers", d_towers_filename);
173   retval &= helper->saveData("city_tile_width", d_city_tile_width);
174   retval &= helper->saveData("temple_tile_width", d_temple_tile_width);
175   retval &= helper->saveData("ruin_tile_width", d_ruin_tile_width);
176   retval &= helper->closeTag();
177   return retval;
178 }
179
180 void Cityset::uninstantiateImages()
181 {
182   if (getPortImage() != NULL)
183     {
184       delete getPortImage();
185       setPortImage(NULL);
186     }
187   if (getSignpostImage() != NULL)
188     {
189       delete getSignpostImage();
190       setSignpostImage(NULL);
191     }
192   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
193     {
194       if (getCityImage(i) != NULL)
195         {
196           delete getCityImage(i);
197           setCityImage(i, NULL);
198         }
199     }
200   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
201     {
202       if (getRazedCityImage(i) != NULL)
203         {
204           delete getRazedCityImage(i);
205           setRazedCityImage(i, NULL);
206         }
207     }
208   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
209     {
210       if (getTowerImage(i) != NULL)
211         {
212           delete getTowerImage(i);
213           setTowerImage(i, NULL);
214         }
215     }
216   for (unsigned int i = 0; i < RUIN_TYPES; i++)
217     {
218       if (getRuinImage(i) != NULL)
219         {
220           delete getRuinImage(i);
221           setRuinImage(i, NULL);
222         }
223     }
224   for (unsigned int i = 0; i < TEMPLE_TYPES; i++)
225     {
226       if (getTempleImage(i) != NULL)
227         {
228           delete getTempleImage(i);
229           setTempleImage(i, NULL);
230         }
231     }
232 }
233
234 void Cityset::instantiateImages(std::string port_filename,
235                                 std::string signpost_filename,
236                                 std::string cities_filename,
237                                 std::string razed_cities_filename,
238                                 std::string towers_filename,
239                                 std::string ruins_filename,
240                                 std::string temples_filename)
241 {
242   if (port_filename.empty() == false)
243     setPortImage (PixMask::create(port_filename));
244   if (signpost_filename.empty() == false)
245     setSignpostImage (PixMask::create(signpost_filename));
246
247       
248   int citysize = d_tileSize * d_city_tile_width;
249   if (cities_filename.empty() == false)
250     {
251       std::vector<PixMask* > citypics;
252       citypics = disassemble_row(cities_filename, MAX_PLAYERS + 1);
253       for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
254         {
255           if (citypics[i]->get_width() != citysize)
256             PixMask::scale(citypics[i], citysize, citysize);
257           setCityImage(i, citypics[i]);
258         }
259     }
260
261   if (razed_cities_filename.empty() == false)
262     {
263       std::vector<PixMask* > razedcitypics;
264       razedcitypics = disassemble_row(razed_cities_filename, MAX_PLAYERS);
265       for (unsigned int i = 0; i < MAX_PLAYERS; i++)
266         {
267           if (razedcitypics[i]->get_width() != citysize)
268             PixMask::scale(razedcitypics[i], citysize, citysize);
269           setRazedCityImage(i, razedcitypics[i]);
270         }
271     }
272
273   if (towers_filename.empty() == false)
274     {
275       std::vector<PixMask* > towerpics = disassemble_row(towers_filename, 
276                                                          MAX_PLAYERS);
277       for (unsigned int i = 0; i < MAX_PLAYERS; i++)
278         {
279           if (towerpics[i]->get_width() != (int)d_tileSize)
280             PixMask::scale(towerpics[i], d_tileSize, d_tileSize);
281           setTowerImage(i, towerpics[i]);
282         }
283     }
284
285   if (ruins_filename.empty() == false)
286     {
287       std::vector<PixMask* > ruinpics = disassemble_row(ruins_filename, RUIN_TYPES);
288       int ruinsize = d_tileSize * d_ruin_tile_width;
289       for (unsigned int i = 0; i < RUIN_TYPES ; i++)
290         {
291           if (ruinpics[i]->get_width() != ruinsize)
292             PixMask::scale(ruinpics[i], ruinsize, ruinsize);
293           setRuinImage(i, ruinpics[i]);
294         }
295     }
296
297   if (temples_filename.empty() == false)
298     {
299       std::vector<PixMask* > templepics;
300       templepics = disassemble_row(temples_filename, TEMPLE_TYPES);
301       int templesize = d_tileSize * d_temple_tile_width;
302       for (unsigned int i = 0; i < TEMPLE_TYPES ; i++)
303         {
304           if (templepics[i]->get_width() != templesize)
305             PixMask::scale(templepics[i], templesize, templesize);
306           setTempleImage(i, templepics[i]);
307         }
308     }
309 }
310
311 void Cityset::instantiateImages()
312 {
313   debug("Loading images for cityset " << getName());
314   uninstantiateImages();
315   std::string port_filename = "";
316   std::string signpost_filename = "";
317   std::string cities_filename = "";
318   std::string razed_cities_filename = "";
319   std::string towers_filename = "";
320   std::string ruins_filename = "";
321   std::string temples_filename = "";
322
323   if (getPortFilename().empty() == false)
324     port_filename = getFile(getPortFilename());
325   if (getSignpostFilename().empty() == false)
326     signpost_filename = getFile(getSignpostFilename());
327   if (getCitiesFilename().empty() == false)
328     cities_filename = getFile(getCitiesFilename());
329   if (getRazedCitiesFilename().empty() == false)
330     razed_cities_filename = getFile(getRazedCitiesFilename());
331   if (getTowersFilename().empty() == false)
332     towers_filename = getFile(getTowersFilename());
333   if (getRuinsFilename().empty() == false)
334     ruins_filename = getFile(getRuinsFilename());
335   if (getTemplesFilename().empty() == false)
336     temples_filename = getFile(getTemplesFilename());
337   instantiateImages(port_filename, signpost_filename, cities_filename,
338                     razed_cities_filename, towers_filename, ruins_filename,
339                     temples_filename);
340 }
341
342 std::string Cityset::getConfigurationFile()
343 {
344   return getDirectory() + d_subdir + file_extension;
345 }
346
347 std::list<std::string> Cityset::scanUserCollection()
348 {
349   return File::scanFiles(File::getUserCitysetDir(), file_extension);
350 }
351
352 std::list<std::string> Cityset::scanSystemCollection()
353 {
354   std::list<std::string> retlist = File::scanFiles(File::getCitysetDir(), 
355                                                    file_extension);
356   if (retlist.empty())
357     {
358       std::cerr << "Couldn't find any citysets!" << std::endl;
359       std::cerr << "Please check the path settings in /etc/lordsawarrc or ~/.lordsawarrc" << std::endl;
360       std::cerr << "Exiting!" << std::endl;
361       exit(-1);
362     }
363
364   return retlist;
365 }
366
367         
368 bool Cityset::validate()
369 {
370   bool valid = true;
371   if (validateCitiesFilename() == false)
372     return false;
373   if (validateRazedCitiesFilename() == false)
374     return false;
375   if (validatePortFilename() == false)
376     return false;
377   if (validateSignpostFilename() == false)
378     return false;
379   if (validateRuinsFilename() == false)
380     return false;
381   if (validateTemplesFilename() == false)
382     return false;
383   if (validateTowersFilename() == false)
384     return false;
385   if (validateCityTileWidth() == false)
386     return false;
387   if (validateRuinTileWidth() == false)
388     return false;
389   if (validateTempleTileWidth() == false)
390     return false;
391   return valid;
392 }
393 bool Cityset::validateCitiesFilename()
394 {
395   if (getCitiesFilename().empty() == true)
396     return false;
397   return true;
398 }
399 bool Cityset::validateRazedCitiesFilename()
400 {
401   if (getRazedCitiesFilename().empty() == true)
402     return false;
403   return true;
404 }
405 bool Cityset::validateSignpostFilename()
406 {
407   if (getSignpostFilename().empty() == true)
408     return false;
409   return true;
410 }
411 bool Cityset::validatePortFilename()
412 {
413   if (getPortFilename().empty() == true)
414     return false;
415   return true;
416 }
417 bool Cityset::validateRuinsFilename()
418 {
419   if (getRuinsFilename().empty() == true)
420     return false;
421   return true;
422 }
423 bool Cityset::validateTemplesFilename()
424 {
425   if (getTemplesFilename().empty() == true)
426     return false;
427   return true;
428 }
429 bool Cityset::validateTowersFilename()
430 {
431   if (getTowersFilename().empty() == true)
432     return false;
433   return true;
434 }
435 bool Cityset::validateCityTileWidth()
436 {
437   if (getCityTileWidth() <= 0)
438     return false;
439   return true; 
440 }
441 bool Cityset::validateRuinTileWidth()
442 {
443   if (getRuinTileWidth() <= 0)
444     return false;
445   return true; 
446 }
447 bool Cityset::validateTempleTileWidth()
448 {
449   if (getTempleTileWidth() <= 0)
450     return false;
451   return true; 
452 }
453 bool Cityset::tileWidthsEqual(Cityset *cityset)
454 {
455   if (getCityTileWidth() == cityset->getCityTileWidth() &&
456       getRuinTileWidth() == cityset->getRuinTileWidth() &&
457       getTempleTileWidth() == cityset->getTempleTileWidth())
458     return true;
459   return false;
460 }
461 // End of file