1 // Copyright (C) 2003, 2004, 2005 Ulf Lorenz
2 // Copyright (C) 2004, 2005, 2006 Andrea Paternesi
3 // Copyright (C) 2007-2009, 2011, 2014, 2015, 2017 Ben Asselstine
4 // Copyright (C) 2007, 2008 Ole Laursen
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 <sigc++/functors/mem_fun.h>
22 
23 #include "QuestsManager.h"
24 
25 #include "Quest.h"
26 #include "QKillHero.h"
27 #include "QEnemyArmies.h"
28 #include "QCitySack.h"
29 #include "QCityRaze.h"
30 #include "QCityOccupy.h"
31 #include "QEnemyArmytype.h"
32 #include "QPillageGold.h"
33 #include "stacklist.h"
34 #include "SightMap.h"
35 #include "rewardlist.h"
36 #include "army.h"
37 #include "xmlhelper.h"
38 #include "history.h"
39 #include "stackreflist.h"
40 #include "hero.h"
41 #include "rnd.h"
42 
43 Glib::ustring QuestsManager::d_tag = "questlist";
44 
45 QuestsManager* QuestsManager::s_instance = NULL;
46 
47 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
48 #define debug(x)
49 
50 
getInstance()51 QuestsManager* QuestsManager::getInstance()
52 {
53     if (s_instance == 0)
54         s_instance = new QuestsManager();
55     return s_instance;
56 }
57 
getInstance(XML_Helper * helper)58 QuestsManager* QuestsManager::getInstance(XML_Helper* helper)
59 {
60     if (s_instance)
61         deleteInstance();
62 
63     s_instance = new QuestsManager(helper);
64     return s_instance;
65 }
66 
deleteInstance()67 void QuestsManager::deleteInstance()
68 {
69     debug("QuestsManager: deleteInstance")
70     delete s_instance;
71     s_instance = 0;
72 }
73 
QuestsManager()74 QuestsManager::QuestsManager()
75 {
76     sharedInit();
77 }
78 
QuestsManager(XML_Helper * helper)79 QuestsManager::QuestsManager(XML_Helper* helper)
80 {
81     sharedInit();
82     debug("QuestsManager: registerTag!");
83     helper->registerTag(Quest::d_tag, sigc::mem_fun(this, &QuestsManager::load));
84 }
85 
~QuestsManager()86 QuestsManager::~QuestsManager()
87 {
88   d_completed_quests.unique ();
89   for (auto q : d_completed_quests)
90     delete q;
91 
92   for (std::map<guint32,Quest*>::iterator it = d_quests.begin();
93        it != d_quests.end(); it++)
94     delete (*it).second;
95   cleanup();
96 }
97 
createNewQuest(guint32 heroId,bool razing_possible)98 Quest* QuestsManager::createNewQuest(guint32 heroId, bool razing_possible)
99 {
100     // don't let a hero have more than one quest
101     if (d_quests.count(heroId))
102         return NULL;
103 
104     int which = 0;
105     while (!which)
106     {
107         which = 1 + Rnd::rand() % 7;
108         // if this quest is not feasible - try again with another
109         // quest:
110         if ((*(d_questsFeasible[which-1]))(heroId) == 0)
111             which = 0;
112     }
113     // ok - this quest can be completed
114 
115     Quest *quest = NULL;
116     switch (which)
117     {
118         case 1:
119             quest = new QuestKillHero(*this, heroId);
120             break;
121         case 2:
122             quest = new QuestEnemyArmies(*this, heroId);
123             break;
124         case 3:
125             quest = new QuestCitySack(*this, heroId);
126             break;
127         case 4:
128 	    if (razing_possible)
129 	      quest = new QuestCityRaze(*this, heroId);
130 	    else
131 	      quest = new QuestCitySack(*this, heroId);
132             break;
133         case 5:
134             quest = new QuestCityOccupy(*this, heroId);
135             break;
136         case 6:
137             quest = new QuestEnemyArmytype(*this, heroId);
138             break;
139         case 7:
140             quest = new QuestPillageGold(*this, heroId);
141             break;
142     }
143 
144     if (quest)
145     {
146         d_quests[heroId] = quest;
147     }
148 
149     return quest;
150 }
151 
createNewKillHeroQuest(guint32 heroId,guint32 targetHeroId)152 Quest* QuestsManager::createNewKillHeroQuest(guint32 heroId, guint32 targetHeroId)
153 {
154   Quest *quest = new QuestKillHero(*this, heroId, targetHeroId);
155 
156   d_quests[heroId] = quest;
157 
158   return quest;
159 }
160 
createNewEnemyArmiesQuest(guint32 heroId,guint32 num_armies,guint32 victim_player_id)161 Quest* QuestsManager::createNewEnemyArmiesQuest(guint32 heroId,
162 						guint32 num_armies,
163 						guint32 victim_player_id)
164 {
165   Quest *quest = new QuestEnemyArmies(*this, heroId, num_armies,
166 				      victim_player_id);
167 
168   d_quests[heroId] = quest;
169 
170   return quest;
171 }
172 
createNewCitySackQuest(guint32 heroId,guint32 cityId)173 Quest* QuestsManager::createNewCitySackQuest(guint32 heroId, guint32 cityId)
174 {
175   Quest *quest = new QuestCitySack(*this, heroId, cityId);
176 
177   d_quests[heroId] = quest;
178 
179   return quest;
180 }
181 
createNewCityRazeQuest(guint32 heroId,guint32 cityId)182 Quest* QuestsManager::createNewCityRazeQuest(guint32 heroId, guint32 cityId)
183 {
184   Quest *quest = new QuestCityRaze(*this, heroId, cityId);
185 
186   d_quests[heroId] = quest;
187 
188   return quest;
189 }
190 
createNewCityOccupyQuest(guint32 heroId,guint32 cityId)191 Quest* QuestsManager::createNewCityOccupyQuest(guint32 heroId, guint32 cityId)
192 {
193   Quest *quest = new QuestCityOccupy(*this, heroId, cityId);
194 
195   d_quests[heroId] = quest;
196 
197   return quest;
198 }
199 
createNewEnemyArmytypeQuest(guint32 heroId,guint32 armyTypeId)200 Quest* QuestsManager::createNewEnemyArmytypeQuest(guint32 heroId,
201 						  guint32 armyTypeId)
202 {
203   Quest *quest = new QuestEnemyArmytype(*this, heroId, armyTypeId);
204 
205   d_quests[heroId] = quest;
206 
207   return quest;
208 }
209 
createNewPillageGoldQuest(guint32 heroId,guint32 amount)210 Quest* QuestsManager::createNewPillageGoldQuest(guint32 heroId, guint32 amount)
211 {
212   Quest *quest = new QuestPillageGold(*this, heroId, amount);
213 
214   d_quests[heroId] = quest;
215 
216   return quest;
217 }
218 
questCompleted(guint32 heroId)219 void QuestsManager::questCompleted(guint32 heroId)
220 {
221     Quest *quest = getHeroQuest (heroId);
222     Player *p = quest->getHero()->getOwner();
223 
224     p->heroCompletesQuest(quest->getHero());
225     Stack *stack = p->getStacklist()->getArmyStackById(heroId);
226 
227     Reward *reward = Reward::createRandomReward(true, true);
228     StackReflist *stacks = new StackReflist();
229     p->giveReward(stack, reward, stacks, true);
230     quest_completed.emit(quest, reward);
231     if (reward->getType() == Reward::ALLIES)
232       p->addHistory(new History_HeroFindsAllies(quest->getHero()));
233     else if (reward->getType() == Reward::RUIN)
234       {
235         Ruin *r = dynamic_cast<Reward_Ruin*>(reward)->getRuin();
236         p->addHistory(new History_HeroRewardRuin(dynamic_cast<Hero*>(quest->getHero()), r));
237       }
238     delete reward;
239     delete stacks;
240 
241     //debug("deactivate quest");
242 
243     quest->deactivate ();
244     d_quests.erase(heroId);
245     d_completed_quests.push_back (quest);
246     //debug("quest deactivated");
247 }
248 
questExpired(guint32 heroId)249 void QuestsManager::questExpired(guint32 heroId)
250 {
251     Quest *quest = getHeroQuest (heroId);
252 
253     if (quest == 0)
254         return;
255 
256     //quest_expired.emit(quest);
257 
258     debug("deactivate quest");
259     deactivateQuest(heroId);
260     debug("quest deactivated");
261 }
262 
getPlayerQuests(const Player * player) const263 std::vector<Quest*> QuestsManager::getPlayerQuests(const Player *player) const
264 {
265   std::vector<Quest*> res;
266   // loop through the player's heroes
267   // for every hero check any pending quests
268   const Stacklist* sl = player->getStacklist();
269   std::list<Hero*> heroes = sl->getHeroes();
270   for (std::list<Hero*>::iterator it = heroes.begin(); it != heroes.end(); it++)
271     {
272       guint32 heroId = (*it)->getId();
273 
274       if (d_quests.count(heroId) > 0)
275         {
276           std::map<guint32, Quest*>::const_iterator qit = d_quests.find(heroId);
277           if (qit == d_quests.end())
278             continue;
279           Quest *q = (*qit).second;
280           if (q && q->isPendingDeletion() == true)
281             continue;
282           if (!q)
283             continue;
284           debug("heroId = " << heroId << " - has quest: " << q);
285           res.push_back(q);
286         }
287     }
288   return res;
289 }
290 
getHeroQuest(guint32 hero_id) const291 Quest* QuestsManager::getHeroQuest(guint32 hero_id) const
292 {
293   std::map<guint32, Quest*>::const_iterator qit;
294   qit = d_quests.find(hero_id);
295   if (qit == d_quests.end())
296     return NULL;
297   Quest *q = (*qit).second;
298   if (q && q->isPendingDeletion() == true)
299     return NULL;
300   return (*qit).second;
301 }
302 
save(XML_Helper * helper) const303 bool QuestsManager::save(XML_Helper* helper) const
304 {
305   debug("Saving quests\n");
306 
307   bool retval = true;
308   retval &= helper->openTag(QuestsManager::d_tag);
309 
310   for (std::map<guint32,Quest*>::const_iterator it = d_quests.begin();
311        it != d_quests.end(); it++)
312     {
313       if ((*it).second == NULL)
314 	continue;
315       retval &= ((*it).second)->save(helper);
316     }
317   for (std::list<Quest *>::const_iterator it = d_inactive_quests.begin();
318        it != d_inactive_quests.end(); it++)
319     retval &= (*it)->save(helper);
320 
321   debug("Quests saved\n");
322   retval &= helper->closeTag();
323   return retval;
324 }
325 
load(Glib::ustring tag,XML_Helper * helper)326 bool QuestsManager::load(Glib::ustring tag, XML_Helper* helper)
327 {
328   debug("QuestsManager: load tag = " << tag);
329 
330   if (tag == Quest::d_tag)
331     {
332       guint32  questType, hero;
333       Glib::ustring quest_type_str;
334       helper->getData(quest_type_str, "type");
335       questType = Quest::questTypeFromString(quest_type_str);
336       helper->getData(hero, "hero");
337 
338       debug("quest load: type = " << questType << ", heroId = " << hero);
339 
340       Quest *quest=0;
341       switch (static_cast<Quest::Type>(questType)) {
342       case Quest::KILLHERO:
343 	quest = new QuestKillHero(*this, helper);
344 	break;
345       case Quest::KILLARMIES:
346 	quest = new QuestEnemyArmies(*this, helper);
347 	break;
348       case Quest::CITYSACK:
349 	quest = new QuestCitySack(*this, helper);
350 	break;
351       case Quest::CITYRAZE:
352 	quest = new QuestCityRaze(*this, helper);
353 	break;
354       case Quest::CITYOCCUPY:
355 	quest = new QuestCityOccupy(*this, helper);
356 	break;
357       case Quest::KILLARMYTYPE:
358 	quest = new QuestEnemyArmytype(*this, helper);
359 	break;
360       case Quest::PILLAGEGOLD:
361 	quest = new QuestPillageGold(*this, helper);
362 	break;
363       }
364 
365       debug("quest created: q = " << quest);
366       if (quest)
367 	{
368 	  if (quest->isPendingDeletion())
369 	    d_inactive_quests.push_back(quest);
370 	  else
371 	    d_quests[hero] = quest;
372 	}
373       return true;
374     }
375   return false;
376 }
377 
sharedInit()378 void QuestsManager::sharedInit()
379 {
380   debug("QuestsManager constructor")
381 
382     // now prepare the vector of pointers to the
383     // functions (class static members) checking feasibility
384     // for every quest
385     d_questsFeasible.push_back(&(QuestKillHero::isFeasible));
386   d_questsFeasible.push_back(&(QuestEnemyArmies::isFeasible));
387   d_questsFeasible.push_back(&(QuestCitySack::isFeasible));
388   d_questsFeasible.push_back(&(QuestCityRaze::isFeasible));
389   d_questsFeasible.push_back(&(QuestCityOccupy::isFeasible));
390   d_questsFeasible.push_back(&(QuestEnemyArmytype::isFeasible));
391   d_questsFeasible.push_back(&(QuestPillageGold::isFeasible));
392 }
393 
deactivateQuest(guint32 heroId)394 void QuestsManager::deactivateQuest(guint32 heroId)
395 {
396   Quest *q = getHeroQuest (heroId);
397   q->deactivate();
398   d_inactive_quests.push_back(q);
399   // delete it from hash of active quests
400   d_quests.erase(heroId);
401 }
402 
cleanup()403 void QuestsManager::cleanup()
404 {
405   debug("QuestsManager: cleanup!");
406 
407   std::list<Quest *>::iterator it = d_inactive_quests.begin();
408   while(it != d_inactive_quests.end())
409     {
410       Quest *q =(*it);
411       it = d_inactive_quests.erase(it);
412       if (q)
413 	delete q;
414     }
415 }
416 
getActiveQuests()417 std::vector<Quest*> QuestsManager::getActiveQuests ()
418 {
419   std::vector<Quest*> quests;
420   for (std::map<guint32,Quest*>::iterator it = d_quests.begin();
421        it != d_quests.end(); it++)
422     {
423       if ((*it).second == NULL)
424 	continue;
425       if ((*it).second->isPendingDeletion() == true)
426 	continue;
427       quests.push_back ((*it).second);
428     }
429   return quests;
430 }
431 
armyDied(Army * a,std::vector<guint32> & culprits)432 void QuestsManager::armyDied(Army *a, std::vector<guint32>& culprits)
433 {
434   //tell all quests that an army died
435   //each quest takes care of what happens when an army dies
436   std::vector<Quest *> quests = getActiveQuests ();
437   for (auto q : quests)
438     {
439       //was this hero a perpetrator?
440       bool heroIsCulprit = false;
441       for (unsigned int i = 0; i <culprits.size(); i++)
442 	{
443 	  if (culprits[i] == q->getHeroId())
444 	    {
445 	      heroIsCulprit = true;
446 	      break;
447 	    }
448 	}
449       q->armyDied(a, heroIsCulprit);
450     }
451 
452   //is it a hero that has an outstanding quest?
453   //this is what deactivates a quest upon hero death
454   Quest *quest = getHeroQuest (a->getId());
455   if (quest && quest->isPendingDeletion() == false)
456     questExpired(a->getId());
457 }
458 
cityAction(City * c,Stack * s,CityDefeatedAction action,int gold)459 void QuestsManager::cityAction(City *c, Stack *s,
460 			       CityDefeatedAction action, int gold)
461 {
462   std::vector<Quest *> quests = getActiveQuests ();
463   for (auto q : quests)
464     {
465       if (!s)
466         q->cityAction(c, action, false, gold);
467       else
468 	{
469           //XXX XXX XXX why do we have to check for null here?
470 	  for (Stack::iterator sit = s->begin(); sit != s->end(); sit++)
471 	    {
472               if (q->isPendingDeletion())
473 		break;
474 	      if ((*sit)->getId() == q->getHeroId())
475 		q->cityAction(c, action, true, gold);
476 	    }
477 	  for (Stack::iterator sit = s->begin(); sit != s->end(); sit++)
478 	    {
479               if (q->isPendingDeletion())
480 		break;
481 	      if ((*sit)->getId() != q->getHeroId())
482 		q->cityAction(c, action, false, gold);
483 	    }
484 	}
485     }
486 }
487 
cityRazed(City * c,Stack * s)488 void QuestsManager::cityRazed(City *c, Stack *s)
489 {
490   cityAction(c, s, CITY_DEFEATED_RAZE, 0);
491   //did we raze a city we care about in another quest?
492 }
493 
citySacked(City * c,Stack * s,int gold)494 void QuestsManager::citySacked(City *c, Stack *s, int gold)
495 {
496   cityAction(c, s, CITY_DEFEATED_SACK, gold);
497 }
498 
cityPillaged(City * c,Stack * s,int gold)499 void QuestsManager::cityPillaged(City *c, Stack *s, int gold)
500 {
501   cityAction(c, s, CITY_DEFEATED_PILLAGE, gold);
502 }
503 
cityOccupied(City * c,Stack * s)504 void QuestsManager::cityOccupied(City *c, Stack *s)
505 {
506   cityAction(c, s, CITY_DEFEATED_OCCUPY, 0);
507 }
508 
nextTurn(Player * p)509 void QuestsManager::nextTurn(Player *p)
510 {
511   d_completed_quests.unique ();
512   for (auto q : d_completed_quests)
513     delete q;
514   d_completed_quests.clear ();
515   // go through our inactive list and remove quests belonging to us
516   for (std::list<Quest*>::iterator it = d_inactive_quests.begin();
517        it != d_inactive_quests.end(); it++)
518     {
519       if ((*it)->getOwner() == p)
520 	{
521 	  Quest *q = *it;
522 	  quest_expired.emit(q);
523 	  it = d_inactive_quests.erase(it);
524 	  if (q)
525 	    delete q;
526 	}
527     }
528 }
529