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