initial commit, lordsawar source, slightly modified
[lordsawar] / src / GameScenario.cpp
1 // Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004, 2006 Andrea Paternesi
4 // Copyright (C) 2006, 2007, 2008 Ben Asselstine
5 // Copyright (C) 2007, 2008 Ole Laursen
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 3 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU Library General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
20 //  02110-1301, USA.
21
22 #include <iostream>
23 #include <iomanip>
24 #include <fstream>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <sigc++/functors/mem_fun.h>
28 #include <string.h>
29
30 #include "ucompose.hpp"
31 #include "GameScenario.h"
32 #include "MapGenerator.h"
33 #include "playerlist.h"
34 #include "FogMap.h"
35 #include "citylist.h"
36 #include "ruinlist.h"
37 #include "rewardlist.h"
38 #include "templelist.h"
39 #include "bridgelist.h"
40 #include "portlist.h"
41 #include "roadlist.h"
42 #include "signpostlist.h"
43 #include "city.h"
44 #include "ruin.h"
45 #include "File.h"
46 #include "armysetlist.h"
47 #include "tilesetlist.h"
48 #include "citysetlist.h"
49 #include "shieldsetlist.h"
50 #include "stacklist.h"
51 #include "stack.h"
52 #include "GameMap.h"
53 #include "player.h"
54 #include "Configuration.h"
55 #include "real_player.h"
56 #include "ai_dummy.h"
57 #include "ai_fast.h"
58 #include "counter.h"
59 #include "army.h"
60 #include "QuestsManager.h"
61 #include "Itemlist.h"
62 #include "player.h"
63 #include "vectoredunitlist.h"
64 #include "history.h"
65 #include "xmlhelper.h"
66 #include "tarhelper.h"
67 #include "stacktile.h"
68 #include "GraphicsCache.h"
69
70 std::string GameScenario::d_tag = "scenario";
71 using namespace std;
72
73 #define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
74 //#define debug(x)
75
76 GameScenario::GameScenario(std::string name,std::string comment, bool turnmode,
77                            GameScenario::PlayMode playmode)
78     :d_name(name),d_comment(comment), d_copyright(""), d_license(""),
79     d_turnmode(turnmode), d_playmode(playmode), inhibit_autosave_removal(false)
80 {
81     Armysetlist::getInstance();
82     Tilesetlist::getInstance();
83     Shieldsetlist::getInstance();
84
85     if (fl_counter == 0)
86       fl_counter = new FL_Counter();
87
88     setNewRandomId();
89 }
90
91 //savegame has an absolute path
92 GameScenario::GameScenario(string savegame, bool& broken)
93   :d_turnmode(true), d_playmode(GameScenario::HOTSEAT), 
94     inhibit_autosave_removal(false)
95 {
96   Tar_Helper t(savegame, std::ios::in);
97   loadArmysets(&t);
98   loadTilesets(&t);
99   loadCitysets(&t);
100   loadShieldsets(&t);
101   std::string filename = t.getFirstFile(broken);
102   XML_Helper helper(filename, std::ios::in, Configuration::s_zipfiles);
103   broken = loadWithHelper(helper);
104   File::erase(filename);
105   helper.close();
106   t.Close();
107 }
108
109 bool GameScenario::loadArmysets(Tar_Helper *t)
110 {
111   bool broken = false;
112   std::list<std::string> armysets;
113   armysets = t->getFilenamesWithExtension(Armyset::file_extension);
114   for (std::list<std::string>::iterator it = armysets.begin(); 
115        it != armysets.end(); it++)
116     {
117       Armyset *armyset = Armysetlist::getInstance()->import(t, *it, broken);
118       if (armyset)
119         Armysetlist::getInstance()->getArmyset(armyset->getId())->instantiateImages();
120     }
121   return !broken;
122 }
123
124 bool GameScenario::loadTilesets(Tar_Helper *t)
125 {
126   bool broken = false;
127   std::list<std::string> tilesets;
128   tilesets = t->getFilenamesWithExtension(Tileset::file_extension);
129   for (std::list<std::string>::iterator it = tilesets.begin(); 
130        it != tilesets.end(); it++)
131     {
132       std::string filename = t->getFile(*it, broken);
133       Tileset *tileset = Tileset::create(filename);
134       tileset->setSubDir(File::get_basename(*it));
135
136       //extract all the files and remember where we extracted them
137       std::list<std::string> delfiles;
138       delfiles.push_back(filename);
139       std::list<std::string> files;
140       tileset->getFilenames(files);
141       for (std::list<std::string>::iterator i = files.begin(); i != files.end(); i++)
142         delfiles.push_back (t->getFile(*i + ".png", broken));
143
144       std::string subdir = "";
145       guint32 id = 0;
146       Tilesetlist::getInstance()->addToPersonalCollection(tileset, subdir, id);
147
148       for (std::list<std::string>::iterator it = delfiles.begin(); it != delfiles.end(); it++)
149         File::erase(*it);
150   
151       Tilesetlist::getInstance()->getTileset(tileset->getId())->instantiateImages();
152     }
153   return !broken;
154 }
155
156 bool GameScenario::loadCitysets(Tar_Helper *t)
157 {
158   bool broken = false;
159   std::list<std::string> citysets;
160   citysets = t->getFilenamesWithExtension(Cityset::file_extension);
161   for (std::list<std::string>::iterator it = citysets.begin(); 
162        it != citysets.end(); it++)
163     {
164       std::string filename = t->getFile(*it, broken);
165       Cityset *cityset = Cityset::create(filename);
166       cityset->setSubDir(File::get_basename(*it));
167
168       //extract all the files and remember where we extracted them
169       std::list<std::string> delfiles;
170       delfiles.push_back(filename);
171       std::list<std::string> files;
172       cityset->getFilenames(files);
173       for (std::list<std::string>::iterator i = files.begin(); i != files.end(); i++)
174         delfiles.push_back (t->getFile(*i + ".png", broken));
175
176       std::string subdir = "";
177       guint32 id = 0;
178       Citysetlist::getInstance()->addToPersonalCollection(cityset, subdir, id);
179
180       for (std::list<std::string>::iterator it = delfiles.begin(); it != delfiles.end(); it++)
181         File::erase(*it);
182   
183       Citysetlist::getInstance()->getCityset(cityset->getId())->instantiateImages();
184     }
185   return !broken;
186 }
187
188 bool GameScenario::loadShieldsets(Tar_Helper *t)
189 {
190   bool broken = false;
191   std::list<std::string> shieldsets;
192   shieldsets = t->getFilenamesWithExtension(Shieldset::file_extension);
193   for (std::list<std::string>::iterator it = shieldsets.begin(); 
194        it != shieldsets.end(); it++)
195     {
196       std::string filename = t->getFile(*it, broken);
197       Shieldset *shieldset = Shieldset::create(filename);
198       shieldset->setSubDir(File::get_basename(*it));
199
200       //extract all the files and remember where we extracted them
201       std::list<std::string> delfiles;
202       delfiles.push_back(filename);
203       std::list<std::string> files;
204       shieldset->getFilenames(files);
205       for (std::list<std::string>::iterator i = files.begin(); i != files.end(); i++)
206         delfiles.push_back (t->getFile(*i + ".png", broken));
207
208       std::string subdir = "";
209       guint32 id = 0;
210       Shieldsetlist::getInstance()->addToPersonalCollection(shieldset, subdir, id);
211
212       for (std::list<std::string>::iterator it = delfiles.begin(); it != delfiles.end(); it++)
213         File::erase(*it);
214   
215
216       Shieldsetlist::getInstance()->getShieldset(shieldset->getId())->instantiateImages();
217     }
218   return !broken;
219 }
220
221 GameScenario::GameScenario(XML_Helper &helper, bool& broken)
222   : d_turnmode(true), d_playmode(GameScenario::HOTSEAT),
223     inhibit_autosave_removal(false)
224 {
225   broken = loadWithHelper(helper);
226 }
227
228 void GameScenario::quickStartEvenlyDivided()
229 {
230   Playerlist *plist = Playerlist::getInstance();
231   Citylist *clist = Citylist::getInstance();
232   Vector <int> pos;
233   // no neutral cities
234   // divvy up the neutral cities among other non-neutral players
235   int cities_left = clist->size() - plist->size() + 1;
236   unsigned int citycount[MAX_PLAYERS];
237   memset (citycount, 0, sizeof (citycount));
238   Playerlist::iterator pit = plist->begin();
239
240   while (cities_left > 0)
241     {
242       if (*pit != plist->getNeutral())
243         {
244           citycount[(*pit)->getId()]++;
245           cities_left--;
246         }
247
248       pit++;
249       if (pit == plist->end())
250         pit = plist->begin();
251     }
252
253   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
254     {
255       for (unsigned int j = 0; j < citycount[i]; j++)
256         {
257           Player *p = plist->getPlayer(i);
258           if (!p)
259             continue;
260           if (p == plist->getNeutral())
261             continue;
262           pos = clist->getFirstCity(p)->getPos();
263           City *c = clist->getNearestNeutralCity(pos);
264           if (c)
265             {
266               //does the city contain any stacks yet?
267               //change their allegience to us.
268               for (unsigned int x = 0 ; x < c->getSize(); x++)
269                 {
270                   for (unsigned int y = 0; y < c->getSize(); y++)
271                     {
272                       StackTile *stile = 
273                         GameMap::getStacks(c->getPos() + Vector<int>(x,y));
274                       std::list<Stack*> stks = stile->getStacks();
275                       for (std::list<Stack *>::iterator i = stks.begin(); 
276                            i != stks.end(); i++)
277                         Stacklist::changeOwnership(*i, p);
278                     }
279                 }
280
281               //now give the city to us.
282               c->conquer(p);
283               History_CityWon *item = new History_CityWon();
284               item->fillData(c);
285               p->addHistory(item);
286             }
287         }
288     }
289 }
290
291 void GameScenario::quickStartAIHeadStart()
292 {
293   float head_start_factor = 0.05;
294   //each AI player gets this percent of total cities.
295
296   Playerlist *plist = Playerlist::getInstance();
297   Citylist *clist = Citylist::getInstance();
298   Vector <int> pos;
299
300   unsigned int citycount = clist->size() * head_start_factor;
301   if (citycount == 0)
302     citycount = 1;
303   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
304     {
305       for (unsigned int j = 0; j < citycount; j++)
306         {
307           Player *p = plist->getPlayer(i);
308           if (!p)
309             continue;
310           if (p == plist->getNeutral())
311             continue;
312           if (p->getType() == Player::HUMAN)
313             continue;
314           pos = clist->getFirstCity(p)->getPos();
315           City *c = clist->getNearestNeutralCity(pos);
316           if (c)
317             {
318               //does the city contain any stacks yet?
319               //change their allegience to us.
320               for (unsigned int x = 0 ; x < c->getSize(); x++)
321                 {
322                   for (unsigned int y = 0; y < c->getSize(); y++)
323                     {
324                       StackTile *stile = 
325                         GameMap::getStacks(c->getPos() + Vector<int>(x,y));
326                       std::list<Stack*> stks = stile->getStacks();
327                       for (std::list<Stack *>::iterator i = stks.begin(); 
328                            i != stks.end(); i++)
329                         Stacklist::changeOwnership(*i, p);
330                     }
331                 }
332
333               //now give the city to us.
334               c->conquer(p);
335               History_CityWon *item = new History_CityWon();
336               item->fillData(c);
337               p->addHistory(item);
338             }
339         }
340     }
341 }
342
343 bool GameScenario::setupFog(bool hidden_map)
344 {
345   Playerlist *pl = Playerlist::getInstance();
346   Playerlist::iterator it = pl->begin();
347   for (; it != pl->end(); it++)
348     {
349       if (hidden_map)
350         (*it)->getFogMap()->fill(FogMap::CLOSED);
351       else
352         (*it)->getFogMap()->fill(FogMap::OPEN);
353     }
354   return true;
355 }
356
357 bool GameScenario::setupStacks(bool hidden_map)
358 {
359   if (!hidden_map)
360     return true;
361   for (Playerlist::iterator it = Playerlist::getInstance()->begin();
362        it != Playerlist::getInstance()->end(); it++)
363     {
364       if ((*it) == Playerlist::getInstance()->getNeutral())
365         continue;
366       for (Stacklist::iterator sit = (*it)->getStacklist()->begin(); 
367            sit != (*it)->getStacklist()->end(); sit++)
368         (*sit)->deFog();
369     }
370   return true;
371 }
372
373 bool GameScenario::setupMapRewards()
374 {
375   debug("GameScenario::setupMapRewards")
376   //okay, let's make some maps
377   //split the terrain into a 3x3 grid
378   Vector<int> step = Vector<int>(GameMap::getWidth() / 3, 
379                                  GameMap::getHeight() / 3);
380   Reward_Map *reward = new Reward_Map(Vector<int>(step.x * 0, 0), 
381                                       _("Northwestern map"), step.x, step.y);
382   Rewardlist::getInstance()->push_back(reward);
383   reward = new Reward_Map(Vector<int>(step.x * 1, 0), 
384                           _("Northern map"), step.x, step.y);
385   Rewardlist::getInstance()->push_back(reward);
386   reward = new Reward_Map(Vector<int>(step.x * 2, 0), 
387                           _("Northeastern map"), step.x, step.y);
388   Rewardlist::getInstance()->push_back(reward);
389   reward = new Reward_Map(Vector<int>(step.x * 0, step.y * 1), 
390                           _("Western map"), step.x, step.y);
391   Rewardlist::getInstance()->push_back(reward);
392   reward = new Reward_Map(Vector<int>(step.x * 1, step.y * 1), 
393                           _("Central map"), step.x, step.y);
394   Rewardlist::getInstance()->push_back(reward);
395   reward = new Reward_Map(Vector<int>(step.x * 2, step.y * 1), 
396                           _("Eastern map"), step.x, step.y);
397   Rewardlist::getInstance()->push_back(reward);
398   reward = new Reward_Map(Vector<int>(step.x * 0, step.y * 2), 
399                           _("Southwestern map"), step.x, step.y);
400   Rewardlist::getInstance()->push_back(reward);
401   reward = new Reward_Map(Vector<int>(step.x * 1, step.y * 2), 
402                           _("Southern map"), step.x, step.y);
403   Rewardlist::getInstance()->push_back(reward);
404   reward = new Reward_Map(Vector<int>(step.x * 2, step.y * 2), 
405                           _("Southeastern map"), step.x, step.y);
406   Rewardlist::getInstance()->push_back(reward);
407   return true;
408 }
409
410 bool GameScenario::setupRuinRewards()
411 {
412   debug("GameScenario::setupRuinRewards")
413     for (Ruinlist::iterator it = Ruinlist::getInstance()->begin();
414          it != Ruinlist::getInstance()->end(); it++)
415       {
416         if ((*it)->isHidden() == true)
417           {
418             //add it to the reward list
419             Reward_Ruin *newReward = new Reward_Ruin((*it)); //make a reward
420             newReward->setName(newReward->getDescription());
421             Rewardlist::getInstance()->push_back(newReward); //add it
422           }
423         else
424           {
425             if ((*it)->hasSage() == false && (*it)->getReward() == NULL)
426               (*it)->populateWithRandomReward();
427           }
428       }
429   return true;
430 }
431
432 bool GameScenario::setupItemRewards()
433 {
434   debug("GameScenario::setupItemRewards")
435   Itemlist *il = Itemlist::getInstance();
436   Itemlist::iterator iter;
437   for (iter = il->begin(); iter != il->end(); iter++)
438     {
439       Item templateItem = *iter->second;
440       Item *newItem = new Item(templateItem); //instantiate it
441       Reward_Item *newReward = new Reward_Item(newItem); //make a reward
442       newReward->setName(newReward->getDescription());
443       Rewardlist::getInstance()->push_back(newReward); //add it
444     }
445
446   return true;
447 }
448
449 bool GameScenario::setupRewards(bool hidden_map)
450 {
451   if (Rewardlist::getInstance()->size() != 0)
452     return true;
453   setupItemRewards();
454   setupRuinRewards();
455   if (hidden_map)
456     setupMapRewards();
457   return true;
458 }
459
460 bool GameScenario::setupCities(GameParameters::QuickStartPolicy quick_start)
461 {
462   debug("GameScenario::setupCities")
463
464   for (Playerlist::iterator it = Playerlist::getInstance()->begin();
465        it != Playerlist::getInstance()->end(); it++)
466     {
467       if ((*it) == Playerlist::getInstance()->getNeutral())
468         continue;
469       City *city = Citylist::getInstance()->getFirstCity(*it);
470       if (city)
471         {
472           city->deFog(city->getOwner());
473           History_CityWon *item = new History_CityWon();
474           item->fillData(city);
475           city->getOwner()->addHistory(item);
476         }
477     }
478
479   if (quick_start == GameParameters::EVENLY_DIVIDED)
480     quickStartEvenlyDivided();
481   else if (quick_start == GameParameters::AI_HEAD_START)
482     quickStartAIHeadStart();
483
484   for (Citylist::iterator it = Citylist::getInstance()->begin();
485        it != Citylist::getInstance()->end(); it++)
486     {
487       if ((*it)->getOwner() == Playerlist::getInstance()->getNeutral())
488         {
489           switch (GameScenario::s_neutral_cities)
490             {
491             case GameParameters::AVERAGE:
492               (*it)->produceScout();
493               break;
494             case GameParameters::STRONG:
495               (*it)->produceStrongestProductionBase();
496               break;
497             case GameParameters::ACTIVE:
498               if (rand () % 100 >  20)
499                 (*it)->produceStrongestProductionBase();
500               else
501                 (*it)->produceWeakestProductionBase();
502               break;
503             case GameParameters::DEFENSIVE:
504               (*it)->produceScout();
505               (*it)->produceScout();
506               break;
507             }
508           (*it)->setActiveProductionSlot(-1);
509         }
510       else
511         {
512           if ((*it)->isCapital())
513             (*it)->produceStrongestProductionBase();
514           else
515             (*it)->produceWeakestProductionBase();
516
517           (*it)->setActiveProductionSlot(0);
518         }
519
520     }
521
522   return true;
523 }
524 void GameScenario::setupDiplomacy(bool diplomacy)
525 {
526   Playerlist *pl = Playerlist::getInstance();
527     // Set up diplomacy
528     for (Playerlist::iterator pit = pl->begin(); pit != pl->end(); pit++)
529       {
530         if (pl->getNeutral() == (*pit))
531           continue;
532         for (Playerlist::iterator it = pl->begin(); it != pl->end(); it++)
533           {
534             if (pl->getNeutral() == (*it))
535               continue;
536             if (*pit == *it)
537               continue;
538             if (diplomacy == false)
539               {
540                 (*pit)->proposeDiplomacy(Player::PROPOSE_WAR, *it);
541                 (*pit)->declareDiplomacy(Player::AT_WAR, *it);
542               }
543             else 
544               {
545                 (*pit)->proposeDiplomacy(Player::NO_PROPOSAL, *it);
546                 (*pit)->declareDiplomacy(Player::AT_PEACE, *it);
547               }
548           }
549       }
550     if (diplomacy)
551       pl->calculateDiplomaticRankings();
552 }
553
554 bool GameScenario::loadWithHelper(XML_Helper& helper)
555 {
556   Armysetlist::getInstance();
557   Tilesetlist::getInstance();
558   Shieldsetlist::getInstance();
559
560   bool broken = false;
561
562   helper.registerTag(d_tag, sigc::mem_fun(this, &GameScenario::load));
563   helper.registerTag(Itemlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
564   helper.registerTag(Playerlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
565   helper.registerTag(GameMap::d_tag, sigc::mem_fun(this, &GameScenario::load));
566   helper.registerTag(Citylist::d_tag, sigc::mem_fun(this, &GameScenario::load));
567   helper.registerTag(Templelist::d_tag, sigc::mem_fun(this, &GameScenario::load));
568   helper.registerTag(Ruinlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
569   helper.registerTag(Rewardlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
570   helper.registerTag(Signpostlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
571   helper.registerTag(Roadlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
572   helper.registerTag(FL_Counter::d_tag, sigc::mem_fun(this, &GameScenario::load));
573   helper.registerTag(QuestsManager::d_tag, sigc::mem_fun(this, &GameScenario::load));
574   helper.registerTag(Bridgelist::d_tag, sigc::mem_fun(this, &GameScenario::load));
575   helper.registerTag(Portlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
576   helper.registerTag(VectoredUnitlist::d_tag, sigc::mem_fun(this, &GameScenario::load));
577
578   if (!helper.parse())
579     broken = true;
580
581   GameMap::getInstance()->updateStackPositions();
582   GameMap::getInstance()->calculateBlockedAvenues();
583
584   return broken;
585 }
586
587
588 GameScenario::~GameScenario()
589 {
590   // GameMap is a Singleton so we need a function to delete it
591   GameMap::deleteInstance();
592   Itemlist::deleteInstance();
593   Playerlist::deleteInstance();
594   Citylist::deleteInstance();
595   Templelist::deleteInstance();
596   Ruinlist::deleteInstance();
597   Rewardlist::deleteInstance();
598   Signpostlist::deleteInstance();
599   Portlist::deleteInstance();
600   Bridgelist::deleteInstance();
601   Roadlist::deleteInstance();
602   QuestsManager::deleteInstance();
603   VectoredUnitlist::deleteInstance();
604
605   if (fl_counter)
606     {
607       delete fl_counter;
608       fl_counter = 0;
609     }
610   if (Configuration::s_autosave_policy == 1 && 
611       inhibit_autosave_removal == false)
612     {
613       std::string filename = File::getSavePath() + "autosave.sav";
614       File::erase(filename);
615     }
616   GameScenarioOptions::s_round = 0;
617
618
619 std::string GameScenario::getName(bool translate) const
620 {
621   if (translate)
622     return __(d_name);
623
624   return d_name;
625 }
626
627 std::string GameScenario::getComment(bool translate) const
628 {
629   if (translate)
630     return __(d_comment);
631
632   return d_comment;
633 }
634
635 bool GameScenario::saveGame(string filename, string extension) const
636 {
637   bool retval = true;
638   string goodfilename=filename;
639
640   if (File::nameEndsWith(filename, extension) == false)
641     goodfilename += "." + extension;
642
643   std::string tmpfile = "lw.XXXX";
644   int fd = Glib::file_open_tmp(tmpfile, "lw.XXXX");
645   close(fd);
646   XML_Helper helper(tmpfile, ios::out, Configuration::s_zipfiles);
647   retval &= saveWithHelper(helper);
648   helper.close();
649
650   if (retval == false)
651     return false;
652
653   Tar_Helper t(goodfilename, std::ios::out);
654   t.saveFile(tmpfile, File::get_basename(goodfilename, true));
655   File::erase(tmpfile);
656   std::list<std::string> files;
657
658   Cityset *cs = GameMap::getInstance()->getCityset();
659   cs->getFilenames(files);
660   t.saveFile(cs->getConfigurationFile());
661   for (std::list<std::string>::iterator it = files.begin(); it !=files.end();
662        it++)
663     t.saveFile(cs->getFile(*it));
664
665   files.clear();
666   Shieldset *ss = GameMap::getInstance()->getShieldset();
667   ss->getFilenames(files);
668   t.saveFile(ss->getConfigurationFile());
669   for (std::list<std::string>::iterator it = files.begin(); it !=files.end();
670        it++)
671     t.saveFile(ss->getFile(*it));
672
673   files.clear();
674   Tileset *ts = GameMap::getInstance()->getTileset();
675   ts->getFilenames(files);
676   t.saveFile(ts->getConfigurationFile());
677   for (std::list<std::string>::iterator it = files.begin(); it !=files.end();
678        it++)
679     t.saveFile(ts->getFile(*it));
680
681   Playerlist *plist = Playerlist::getInstance();
682   std::list<guint32> armysets;
683   for (Playerlist::iterator it = plist->begin(); it != plist->end(); it++)
684     {
685       guint32 armyset = (*it)->getArmyset();
686       if (std::find(armysets.begin(), armysets.end(), armyset) == 
687           armysets.end())
688         armysets.push_back(armyset);
689     }
690   for (std::list<guint32>::iterator it = armysets.begin(); it!= armysets.end();
691        it++)
692     {
693       files.clear();
694       Armyset *as = Armysetlist::getInstance()->getArmyset(*it);
695       t.saveFile(as->getConfigurationFile());
696       as->getFilenames(files);
697       for (std::list<std::string>::iterator i = files.begin(); 
698            i != files.end(); i++)
699         t.saveFile(as->getFile(*i));
700     }
701
702   t.Close();
703   return true;
704
705 }
706
707 bool GameScenario::saveWithHelper(XML_Helper &helper) const
708 {
709   bool retval = true;
710
711   //start writing
712   retval &= helper.begin(LORDSAWAR_SAVEGAME_VERSION);
713   retval &= helper.openTag("lordsawar");
714
715   //if retval is still true it propably doesn't change throughout the rest
716   //now save the single object's data
717   retval &= fl_counter->save(&helper);
718   retval &= Itemlist::getInstance()->save(&helper);
719   retval &= Playerlist::getInstance()->save(&helper);
720   retval &= GameMap::getInstance()->save(&helper);
721   retval &= Citylist::getInstance()->save(&helper);
722   retval &= Templelist::getInstance()->save(&helper);
723   retval &= Ruinlist::getInstance()->save(&helper);
724   retval &= Rewardlist::getInstance()->save(&helper);
725   retval &= Signpostlist::getInstance()->save(&helper);
726   retval &= Roadlist::getInstance()->save(&helper);
727   retval &= Portlist::getInstance()->save(&helper);
728   retval &= Bridgelist::getInstance()->save(&helper);
729   retval &= QuestsManager::getInstance()->save(&helper);
730   retval &= VectoredUnitlist::getInstance()->save(&helper);
731
732   //save the private GameScenario data last due to dependencies
733   retval &= helper.openTag(GameScenario::d_tag);
734   retval &= helper.saveData("id", d_id);
735   retval &= helper.saveData("name", d_name);
736   retval &= helper.saveData("comment", d_comment);
737   retval &= helper.saveData("copyright", d_copyright);
738   retval &= helper.saveData("license", d_license);
739   retval &= helper.saveData("turn", s_round);
740   retval &= helper.saveData("turnmode", d_turnmode);
741   retval &= helper.saveData("view_enemies", s_see_opponents_stacks);
742   retval &= helper.saveData("view_production", s_see_opponents_production);
743   std::string quest_policy_str = Configuration::questPolicyToString(GameParameters::QuestPolicy(s_play_with_quests));
744   retval &= helper.saveData("quests", quest_policy_str);
745   retval &= helper.saveData("hidden_map", s_hidden_map);
746   retval &= helper.saveData("diplomacy", s_diplomacy);
747   retval &= helper.saveData("cusp_of_war", s_cusp_of_war);
748   std::string neutral_cities_str = Configuration::neutralCitiesToString(GameParameters::NeutralCities(s_neutral_cities));
749   retval &= helper.saveData("neutral_cities", neutral_cities_str);
750   std::string razing_cities_str = Configuration::razingCitiesToString(GameParameters::RazingCities(s_razing_cities));
751   retval &= helper.saveData("razing_cities", razing_cities_str);
752   retval &= helper.saveData("intense_combat", s_intense_combat);
753   retval &= helper.saveData("military_advisor", s_military_advisor);
754   retval &= helper.saveData("random_turns", s_random_turns);
755   retval &= helper.saveData("surrender_already_offered", 
756                             s_surrender_already_offered);
757   std::string playmode_str = playModeToString(GameScenario::PlayMode(d_playmode));
758   retval &= helper.saveData("playmode", playmode_str);
759
760   retval &= helper.closeTag();
761
762   retval &= helper.closeTag();
763
764   return retval;
765 }
766
767 bool GameScenario::load(std::string tag, XML_Helper* helper)
768 {
769   if (tag == GameScenario::d_tag)
770     {
771       if (helper->getVersion() != LORDSAWAR_SAVEGAME_VERSION)
772         {
773           cerr << "savefile has wrong version, we want ";
774           std::cerr <<LORDSAWAR_SAVEGAME_VERSION <<",\n";
775           cerr << "savefile offers " <<helper->getVersion() <<".\n";
776           return false;
777         }
778
779       debug("loading scenario")
780
781       helper->getData(d_id, "id");
782       helper->getData(d_turnmode, "turnmode");
783       helper->getData(d_name, "name");
784       helper->getData(d_comment, "comment");
785       helper->getData(d_copyright, "copyright");
786       helper->getData(d_license, "license");
787       helper->getData(s_round, "turn");
788       helper->getData(s_see_opponents_stacks, "view_enemies");
789       helper->getData(s_see_opponents_production, "view_production");
790       std::string quest_policy_str;
791       helper->getData(quest_policy_str, "quests");
792       s_play_with_quests = Configuration::questPolicyFromString(quest_policy_str);
793       helper->getData(s_hidden_map, "hidden_map");
794       helper->getData(s_diplomacy, "diplomacy");
795       helper->getData(s_cusp_of_war, "cusp_of_war");
796       std::string neutral_cities_str;
797       helper->getData(neutral_cities_str, "neutral_cities");
798       s_neutral_cities = Configuration::neutralCitiesFromString(neutral_cities_str);
799       std::string razing_cities_str;
800       helper->getData(razing_cities_str, "razing_cities");
801       s_razing_cities = Configuration::razingCitiesFromString(razing_cities_str);
802       helper->getData(s_intense_combat, "intense_combat");
803       helper->getData(s_military_advisor, "military_advisor");
804       helper->getData(s_random_turns, "random_turns");
805       helper->getData(s_surrender_already_offered, 
806                       "surrender_already_offered");
807       std::string playmode_str;
808       helper->getData(playmode_str, "playmode");
809       d_playmode = GameScenario::playModeFromString(playmode_str);
810
811       return true;
812     }
813   
814   if (tag == FL_Counter::d_tag)
815     {
816       debug("loading counter")
817         fl_counter = new FL_Counter(helper);
818       return true;
819     }
820
821   if (tag == Itemlist::d_tag)
822     {
823       debug("loading items");
824       Itemlist::getInstance(helper);
825       return true;
826     }
827
828   if (tag == Playerlist::d_tag)
829     {
830       debug("loading players");
831       Playerlist::getInstance(helper);
832       return true;
833     }
834
835   if (tag == GameMap::d_tag)
836     {
837       debug("loading map")
838         GameMap::getInstance(helper);
839       return true;
840     }
841
842   if (tag == Citylist::d_tag)
843     {
844       debug("loading cities")
845
846         Citylist::getInstance(helper);
847       return true;
848     }
849
850   if (tag == Templelist::d_tag)
851     {
852       debug("loading temples")
853         Templelist::getInstance(helper);
854       return true;
855     }
856
857   if (tag == Ruinlist::d_tag)
858     {
859       debug("loading ruins")
860         Ruinlist::getInstance(helper);
861       return true;
862     }
863
864   if (tag == Rewardlist::d_tag)
865     {
866       debug("loading rewards")
867         Rewardlist::getInstance(helper);
868       return true;
869     }
870
871   if (tag == Signpostlist::d_tag)
872     {
873       debug("loading signposts")
874         Signpostlist::getInstance(helper);
875       return true;
876     }
877
878   if (tag == Roadlist::d_tag)
879     {
880       debug("loading roads")
881         Roadlist::getInstance(helper);
882       return true;
883     }
884
885   if (tag == QuestsManager::d_tag)
886     {
887       debug("loading quests")
888         QuestsManager::getInstance(helper);
889       return true;
890     }
891
892   if (tag == VectoredUnitlist::d_tag)
893     {
894       debug("loading vectored units")
895         VectoredUnitlist::getInstance(helper);
896       return true;
897     }
898
899   if (tag == Portlist::d_tag)
900     {
901       debug("loading ports")
902         Portlist::getInstance(helper);
903       return true;
904     }
905
906   if (tag == Bridgelist::d_tag)
907     {
908       debug("loading bridges")
909         Bridgelist::getInstance(helper);
910       return true;
911     }
912
913   return false;
914 }
915
916 bool GameScenario::autoSave()
917 {
918   Glib::ustring filename = "";
919   if (Configuration::s_autosave_policy == 2)
920     filename = String::ucompose("autosave-%1.sav", Glib::ustring::format(std::setfill(L'0'), std::setw(3), s_round - 1));
921   else if (Configuration::s_autosave_policy == 1)
922     filename = "autosave.sav";
923   else
924     return true;
925   // autosave to the file "autosave.sav". This is crude, but should work
926   //
927   // As a more enhanced version: autosave to a temporary file, then rename
928   // the file. Avoids screwing up the autosave if something goes wrong
929   // (and we have a savefile for debugging)
930   if (!saveGame(File::getSavePath() + "tmp.sav"))
931     {
932       std::cerr<< "Autosave failed.\n";
933       return false;
934     }
935   if (rename(std::string(File::getSavePath() + "tmp.sav").c_str(),
936              std::string(File::getSavePath() + filename).c_str()))
937     {
938       char* err = strerror(errno);
939       std::cerr << "Error while trying to rename the temporary file to autosave.sav\n";
940       std::cerr << "Error: " <<err <<std::endl;
941       return false;
942     }
943   return true;
944 }
945
946 void GameScenario::nextRound()
947 {
948   s_round++;
949   autoSave();
950 }
951
952 std::string GameScenario::playModeToString(const GameScenario::PlayMode mode)
953 {
954   switch (mode)
955     {
956       case GameScenario::HOTSEAT:
957         return "GameScenario::HOTSEAT";
958         break;
959       case GameScenario::NETWORKED:
960         return "GameScenario::NETWORKED";
961         break;
962       case GameScenario::PLAY_BY_MAIL:
963         return "GameScenario::PLAY_BY_MAIL";
964         break;
965     }
966   return "GameScenario::HOTSEAT";
967 }
968
969 GameScenario::PlayMode GameScenario::playModeFromString(const std::string str)
970 {
971   if (str.size() > 0 && isdigit(str.c_str()[0]))
972     return GameScenario::PlayMode(atoi(str.c_str()));
973   if (str == "GameScenario::HOTSEAT")
974     return GameScenario::HOTSEAT;
975   else if (str == "GameScenario::NETWORKED")
976     return GameScenario::NETWORKED;
977   else if (str == "GameScenario::PLAY_BY_MAIL")
978     return GameScenario::PLAY_BY_MAIL;
979   return GameScenario::HOTSEAT;
980 }
981         
982 void GameScenario::setNewRandomId()
983 {
984   d_id = String::ucompose("%1%2%3", time(NULL), getpid(), rand());
985 }
986         
987 bool GameScenario::validate(std::list<std::string> &errors, std::list<std::string> &warnings)
988 {
989   std::string s;
990   Playerlist *pl = Playerlist::getInstance();
991   guint32 num = pl->countPlayersAlive();
992   if (num < 2)
993     errors.push_back(_("There must be at least 2 players in the scenario."));
994
995   num = Citylist::getInstance()->countCities();
996   if (num < 2)
997     errors.push_back(_("There must be at least 2 cities in the scenario."));
998
999   for (Playerlist::iterator it = pl->begin(); it != pl->end(); it++)
1000     {
1001       if (*it == pl->getNeutral())
1002         continue;
1003       if ((*it)->isDead() == true)
1004         continue;
1005       if (Citylist::getInstance()->getFirstCity(*it) == NULL)
1006         {
1007           s = String::ucompose
1008             (_("The player called `%1' lacks a starting city."), 
1009              (*it)->getName().c_str());
1010           errors.push_back(s);
1011           break;
1012         }
1013     }
1014
1015   guint32 count = 0;
1016   Citylist *cl = Citylist::getInstance();
1017   for (Citylist::iterator it = cl->begin(); it != cl->end(); it++)
1018     {
1019       if ((*it)->isUnnamed() == true)
1020         count++;
1021     }
1022   if (count > 0)
1023     {
1024       s = String::ucompose(ngettext("There is %1 unnamed city", "There are %1 unnamed cities", count), count);
1025       warnings.push_back(s);
1026     }
1027
1028   count = 0;
1029   Ruinlist *rl = Ruinlist::getInstance();
1030   for (Ruinlist::iterator it = rl->begin(); it != rl->end(); it++)
1031     {
1032       if ((*it)->isUnnamed() == true)
1033         count++;
1034     }
1035   if (count > 0)
1036     {
1037       std::string s;
1038       s = String::ucompose(ngettext("There is %1 unnamed ruin", "There are %1 unnamed ruins", count), count);
1039       warnings.push_back(s);
1040     }
1041
1042   count = 0;
1043   Templelist *tl = Templelist::getInstance();
1044   for (Templelist::iterator it = tl->begin(); it != tl->end(); it++)
1045     {
1046       if ((*it)->isUnnamed() == true)
1047         count++;
1048     }
1049   if (count > 0)
1050     {
1051       std::string s;
1052       s = String::ucompose(ngettext("There is %1 unnamed temple", "There are %1 unnamed temples", count), count);
1053       warnings.push_back(s);
1054     }
1055
1056   count = 0;
1057   Stacklist *sl = Playerlist::getInstance()->getNeutral()->getStacklist();
1058   for (Stacklist::iterator it = sl->begin(); it != sl->end(); it++)
1059     {
1060       if (Citylist::getInstance()->getObjectAt((*it)->getPos()) == NULL)
1061         count++;
1062     }
1063   if (count > 0)
1064     {
1065       std::string s;
1066       s = String::ucompose(ngettext("There is %1 neutral stack not in a city", "There are %1 neutral stacks not in cities", count), count);
1067       warnings.push_back(s);
1068     }
1069
1070       
1071   if (GameMap::getInstance()->checkCityAccessibility() == false)
1072     errors.push_back(_("Not all cities are reachable by a non-flying unit."));
1073
1074   if (errors.size() ==  0)
1075     return true;
1076   return false;
1077 }
1078
1079 void GameScenario::initialize(GameParameters g)
1080 {
1081   setupFog(g.hidden_map);
1082   setupCities(g.quick_start);
1083   setupStacks(g.hidden_map);
1084   setupRewards(g.hidden_map);
1085   setupDiplomacy(g.diplomacy);
1086   if (s_random_turns)
1087     Playerlist::getInstance()->randomizeOrder();
1088   nextRound();
1089   if (d_playmode == GameScenario::NETWORKED)
1090     Playerlist::getInstance()->turnHumansIntoNetworkPlayers();
1091   else
1092     autoSave();
1093   GameMap::getInstance()->updateStackPositions();
1094
1095   if (d_name == "AutoGenerated")
1096     {
1097       if (GameMap::getInstance()->checkCityAccessibility() == false)
1098         exit (0);
1099     }
1100 }
1101
1102 class ParamLoader
1103 {
1104 public:
1105     ParamLoader(std::string filename, bool &broken) {
1106       Tar_Helper t(filename, std::ios::in);
1107       std::string tmpfile = t.getFirstFile(broken);
1108       XML_Helper helper(tmpfile, std::ios::in, Configuration::s_zipfiles);
1109       helper.registerTag(GameMap::d_tag, 
1110                          sigc::mem_fun(this, &ParamLoader::loadParam));
1111       helper.registerTag(GameScenario::d_tag, 
1112                          sigc::mem_fun(this, &ParamLoader::loadParam));
1113       helper.registerTag(Playerlist::d_tag, 
1114                          sigc::mem_fun(this, &ParamLoader::loadParam));
1115       helper.registerTag(Player::d_tag, 
1116                          sigc::mem_fun(this, &ParamLoader::loadParam));
1117       bool retval = helper.parse();
1118       File::erase(tmpfile);
1119       if (broken == false)
1120         broken = !retval;
1121       helper.close();
1122     }
1123     bool loadParam(std::string tag, XML_Helper* helper)
1124       {
1125         if (tag == Playerlist::d_tag)
1126           {
1127             helper->getData(d_neutral, "neutral");
1128             return true;
1129           }
1130         if (tag == Player::d_tag)
1131           {
1132             int type;
1133             int id;
1134             std::string name;
1135             GameParameters::Player p;
1136             helper->getData(id, "id");
1137             p.id = id;
1138             helper->getData(type, "type");
1139             switch (Player::Type(type))
1140               {
1141               case Player::HUMAN: 
1142                 p.type = GameParameters::Player::HUMAN;
1143                 break;
1144               case Player::AI_FAST: 
1145                 p.type = GameParameters::Player::EASY;
1146                 break;
1147               case Player::AI_DUMMY: 
1148                 p.type = GameParameters::Player::EASY;
1149                 break;
1150               case Player::AI_SMART: 
1151                 p.type = GameParameters::Player::HARD;
1152                 break;
1153               case Player::NETWORKED: 
1154                 p.type = GameParameters::Player::HUMAN;
1155                 break;
1156               }
1157             helper->getData(name, "name");
1158             p.name = name;
1159             if (p.id != d_neutral) //is not neutral
1160               game_params.players.push_back(p);
1161             else
1162               {
1163                 int armyset_id;
1164                 helper->getData(armyset_id, "armyset");
1165                 Armysetlist *al = Armysetlist::getInstance();
1166                 Armyset *armyset = al->getArmyset(armyset_id);
1167                 game_params.army_theme = armyset->getSubDir();
1168               }
1169
1170             return true;
1171           }
1172         if (tag == GameMap::d_tag)
1173           {
1174             helper->getData(game_params.shield_theme, "shieldset");
1175             helper->getData(game_params.tile_theme, "tileset");
1176             helper->getData(game_params.city_theme, "cityset");
1177             return true;
1178           }
1179         if (tag == GameScenario::d_tag)
1180           {
1181             helper->getData(game_params.see_opponents_stacks, 
1182                             "view_enemies");
1183             helper->getData(game_params.see_opponents_production, 
1184                             "view_production");
1185             std::string quest_policy_str;
1186             helper->getData(quest_policy_str, "quests");
1187             game_params.play_with_quests = 
1188               Configuration::questPolicyFromString(quest_policy_str);
1189             helper->getData(game_params.hidden_map, "hidden_map");
1190             helper->getData(game_params.diplomacy, "diplomacy");
1191             helper->getData(game_params.cusp_of_war, "cusp_of_war");
1192             std::string neutral_cities_str;
1193             helper->getData(neutral_cities_str, "neutral_cities");
1194             game_params.neutral_cities = 
1195               Configuration::neutralCitiesFromString(neutral_cities_str);
1196             std::string razing_cities_str;
1197             helper->getData(razing_cities_str, "razing_cities");
1198             game_params.razing_cities = 
1199               Configuration::razingCitiesFromString(razing_cities_str);
1200             helper->getData(game_params.intense_combat, 
1201                             "intense_combat");
1202             helper->getData(game_params.military_advisor, 
1203                             "military_advisor");
1204             helper->getData(game_params.random_turns, "random_turns");
1205             return true;
1206           }
1207         return false;
1208       };
1209     GameParameters game_params;
1210     int d_neutral;
1211 };
1212 GameParameters GameScenario::loadGameParameters(std::string filename, bool &broken)
1213 {
1214   ParamLoader loader(filename, broken);
1215   
1216   return loader.game_params;
1217 }
1218
1219 class PlayModeLoader
1220 {
1221 public:
1222     PlayModeLoader(std::string filename, bool broken) {
1223       play_mode = GameScenario::HOTSEAT;
1224       Tar_Helper t(filename, std::ios::in);
1225       std::string file = File::get_basename(filename, true);
1226       std::string tmpfile = t.getFirstFile(broken);
1227       XML_Helper helper(tmpfile, std::ios::in, Configuration::s_zipfiles);
1228       helper.registerTag(GameScenario::d_tag, 
1229                          sigc::mem_fun(this, &PlayModeLoader::loadParam));
1230       bool retval = helper.parse();
1231       File::erase(tmpfile);
1232       if (broken == false)
1233         broken = !retval;
1234       helper.close();
1235     }
1236     bool loadParam(std::string tag, XML_Helper* helper)
1237       {
1238         if (tag == GameScenario::d_tag)
1239           {
1240             std::string playmode_str;
1241             helper->getData(playmode_str, "playmode");
1242             play_mode = GameScenario::playModeFromString(playmode_str);
1243             return true;
1244           }
1245         return false;
1246       };
1247     GameScenario::PlayMode play_mode;
1248 };
1249
1250 GameScenario::PlayMode GameScenario::loadPlayMode(std::string filename, bool &broken)
1251 {
1252   PlayModeLoader loader(filename, broken);
1253   return loader.play_mode;
1254 }
1255
1256 class DetailsLoader
1257 {
1258 public:
1259     DetailsLoader(std::string filename, bool &broken) {
1260       player_count = 0; city_count = 0; name = ""; comment = "";
1261       Tar_Helper t(filename, std::ios::in);
1262       std::string tmpfile = t.getFirstFile(broken);
1263       XML_Helper helper(tmpfile, std::ios::in, Configuration::s_zipfiles);
1264       helper.registerTag(GameScenario::d_tag, 
1265                          sigc::mem_fun(this, &DetailsLoader::loadDetails));
1266       helper.registerTag(Player::d_tag, 
1267                          sigc::mem_fun(this, &DetailsLoader::loadDetails));
1268       helper.registerTag(City::d_tag, 
1269                      sigc::mem_fun(this, &DetailsLoader::loadDetails));
1270       bool retval = helper.parse();
1271       if (!broken)
1272         broken = !retval;
1273       File::erase(tmpfile);
1274     }
1275
1276     bool loadDetails(std::string tag, XML_Helper* helper)
1277       {
1278         if (tag == GameScenario::d_tag)
1279           {
1280             helper->getData(name, "name");
1281             helper->getData(comment, "comment");
1282             return true;
1283           }
1284         if (tag == Player::d_tag)
1285           {
1286             player_count++;
1287             return true;
1288           }
1289         if (tag == City::d_tag)
1290           {
1291             city_count++;
1292             return true;
1293           }
1294         return false;
1295       };
1296     Tar_Helper *t;
1297     std::string name, comment;
1298     guint32 player_count, city_count;
1299 };
1300 void GameScenario::loadDetails(std::string filename, bool &broken, guint32 &player_count, guint32 &city_count, std::string &name, std::string &comment)
1301 {
1302   DetailsLoader loader(filename, broken);
1303   if (broken == false)
1304     {
1305       player_count = loader.player_count;
1306       city_count = loader.city_count;
1307       name = loader.name;
1308       comment = loader.comment;
1309     }
1310   return;
1311 }
1312