5c96e16da070a74e86080e67cb5d8b3dcfec5c7f
[lordsawar] / src / reward.cpp
1 //  Copyright (C) 2007, 2008, 2009 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
16 //  02110-1301, USA.
17
18 #include <stdlib.h>
19 #include <sstream>
20 #include <vector>
21 #include <sigc++/functors/mem_fun.h>
22
23 #include "reward.h"
24 #include "army.h"
25 #include "armysetlist.h"
26 #include "playerlist.h"
27 #include "ruinlist.h"
28 #include "ruin.h"
29 #include "rewardlist.h"
30 #include "Itemlist.h"
31 #include "Item.h"
32 #include "GameMap.h"
33 #include "ruin.h"
34 #include "ucompose.hpp"
35 #include "SightMap.h"
36
37 std::string Reward::d_tag = "reward";
38
39 using namespace std;
40
41 Reward::Reward(Type type, std::string name)
42     :d_type(type), d_name(name)
43 {
44 }
45
46 Reward::Reward(XML_Helper *helper)
47 {
48   std::string type_str;
49   helper->getData(type_str, "type");
50   d_type = rewardTypeFromString(type_str);
51   helper->getData(d_name, "name");
52 }
53
54 Reward::Reward (const Reward& orig)
55         :d_type(orig.d_type), d_name(orig.d_name)
56 {
57 }
58
59 Reward::~Reward()
60 {
61 }
62
63 Reward* Reward::handle_load(XML_Helper* helper)
64 {
65     guint32 t;
66     std::string type_str;
67     helper->getData(type_str, "type");
68     t = rewardTypeFromString(type_str);
69
70     switch (t)
71     {
72         case Reward::GOLD:
73             return (new Reward_Gold(helper));
74         case Reward::ALLIES:
75             return (new Reward_Allies(helper));
76         case Reward::ITEM:
77             return (new Reward_Item(helper));
78         case Reward::RUIN:
79             return (new Reward_Ruin(helper));
80         case Reward::MAP:
81             return (new Reward_Map(helper));
82     }
83
84     return 0;
85 }
86
87 Reward_Gold::Reward_Gold(guint32 gold)
88     :Reward(Reward::GOLD), d_gold(gold)
89 {
90 }
91
92 Reward_Gold::Reward_Gold(XML_Helper* helper)
93     :Reward(helper)
94 {
95   helper->getData(d_gold, "gold");
96 }
97
98 Reward_Gold::Reward_Gold (const Reward_Gold & orig)
99         :Reward(orig), d_gold(orig.d_gold)
100 {
101 }
102
103 bool Reward_Gold::save(XML_Helper* helper) const
104 {
105   bool retval = true;
106   retval &= helper->openTag(Reward::d_tag);
107   std::string type_str = rewardTypeToString(Reward::Type(d_type));
108   retval &= helper->saveData("type", type_str);
109   retval &= helper->saveData("name", d_name);
110   retval &= helper->saveData("gold", d_gold);
111   retval &= helper->closeTag();
112   return retval;
113 }
114
115 Reward_Gold::~Reward_Gold()
116 {
117 }
118
119 guint32 Reward_Gold::getRandomGoldPieces()
120 {
121   return 310 + (rand() % 1000);
122 }
123
124 Reward_Allies::Reward_Allies(guint32 army_type, guint32 army_set, guint32 count)
125     :Reward(Reward::ALLIES), d_count(count)
126 {
127   Armysetlist *al = Armysetlist::getInstance();
128   d_army_type = army_type;
129   d_army_set = army_set;
130   d_army  = al->getArmy (army_set, army_type);
131 }
132
133 Reward_Allies::Reward_Allies(const ArmyProto *army, guint32 count)
134     :Reward(Reward::ALLIES), d_count(count)
135 {
136   d_army_type = army->getTypeId();
137   d_army_set = army->getArmyset();
138   d_army = army;
139 }
140
141 Reward_Allies::Reward_Allies(XML_Helper* helper)
142     :Reward(helper)
143 {
144   Armysetlist *al = Armysetlist::getInstance();
145   helper->getData(d_count, "num_allies");
146   helper->getData(d_army_type, "ally_type");
147   helper->getData(d_army_set, "ally_armyset");
148   d_army = al->getArmy (d_army_set, d_army_type);
149 }
150
151 Reward_Allies::Reward_Allies (const Reward_Allies& orig)
152         :Reward(orig), d_army(orig.d_army), d_army_type(orig.d_army_type), 
153         d_army_set(orig.d_army_set), d_count(orig.d_count)
154 {
155 }
156
157 bool Reward_Allies::save(XML_Helper* helper) const
158 {
159   bool retval = true;
160   retval &= helper->openTag(Reward::d_tag);
161   std::string type_str = rewardTypeToString(Reward::Type(d_type));
162   retval &= helper->saveData("type", type_str);
163   retval &= helper->saveData("name", d_name);
164   retval &= helper->saveData("num_allies", d_count);
165   retval &= helper->saveData("ally_type", d_army_type);
166   retval &= helper->saveData("ally_armyset", d_army_set);
167   retval &= helper->closeTag();
168   return retval;
169 }
170         
171 const guint32 Reward_Allies::getRandomAmountOfAllies()
172 {
173   int percent = rand() % 100;
174   if (percent < 30)
175     return 1;
176   else if (percent < 50)
177     return 2;
178   else if (percent < 70)
179     return 3;
180   else if (percent < 80)
181     return 4;
182   else if (percent < 85)
183     return 5;
184   else if (percent < 90)
185     return 6;
186   else if (percent < 95)
187     return 7;
188   else if (percent < 100)
189     return 8;
190   else
191     return 1;
192 }
193
194 const ArmyProto* Reward_Allies::randomArmyAlly()
195 {
196   Armysetlist *al = Armysetlist::getInstance();
197   Player *p = Playerlist::getInstance()->getActiveplayer();
198   if (!p)
199     p = Playerlist::getInstance()->getNeutral();
200   return al->getArmyset(p->getArmyset())->getRandomAwardableAlly();
201 }
202
203 bool Reward_Allies::addAllies(Player *p, Vector<int> pos, const ArmyProto *army, guint32 alliesCount)
204 {
205   for (unsigned int i = 0; i < alliesCount; i++)
206     {
207       Army* ally = new Army(*army, p);
208       ally->setUpkeep(0);
209       if (GameMap::getInstance()->addArmyAtPos(pos, ally) == NULL)
210         return false;
211     }
212   return true;
213 }
214
215 bool Reward_Allies::addAllies(Player *p, Location *l, const Army *army, guint32 alliesCount)
216 {
217   for (unsigned int i = 0; i < alliesCount; i++)
218     {
219       Army* ally = new Army(*army, p);
220       ally->setUpkeep(0);
221       if (GameMap::getInstance()->addArmy(l, ally) == NULL)
222         return false;
223     }
224   return true;
225 }
226
227
228 Reward_Allies::~Reward_Allies()
229 {
230 }
231
232 Reward_Item::Reward_Item(Item *item)
233     :Reward(Reward::ITEM), d_item(item)
234 {
235 }
236
237 bool Reward_Item::loadItem(std::string tag, XML_Helper* helper)
238 {
239   if (tag == Item::d_tag)
240     {
241       d_item = new Item(helper);
242       return true;
243     }
244     
245   return false;
246 }
247
248 Reward_Item::Reward_Item(XML_Helper* helper)
249     :Reward(helper)
250 {
251   helper->registerTag(Item::d_tag, sigc::mem_fun(this, &Reward_Item::loadItem));
252 }
253
254 Reward_Item::Reward_Item (const Reward_Item& orig)
255         :Reward(orig), d_item(orig.d_item)
256 {
257 }
258
259 bool Reward_Item::save(XML_Helper* helper) const
260 {
261   bool retval = true;
262   retval &= helper->openTag(Reward::d_tag);
263   std::string type_str = rewardTypeToString(Reward::Type(d_type));
264   retval &= helper->saveData("type", type_str);
265   retval &= helper->saveData("name", d_name);
266   retval &= d_item->save(helper);
267   retval &= helper->closeTag();
268   return retval;
269 }
270
271 Item *Reward_Item::getRandomItem()
272 {
273   Itemlist *il = Itemlist::getInstance();
274   Itemlist::iterator it = il->begin();
275   std::advance(it, rand() % il->size());
276   ItemProto *i = it->second;
277   return new Item(*i);
278 }
279
280 Reward_Item::~Reward_Item()
281 {
282   if (d_item)
283     delete d_item;
284 }
285
286 Reward_Ruin::Reward_Ruin(Ruin *ruin)
287     :Reward(Reward::RUIN), d_ruin_pos(ruin->getPos())
288 {
289 }
290
291 Reward_Ruin::Reward_Ruin(XML_Helper* helper)
292     :Reward(helper)
293 {
294   guint32 x;
295   guint32 y;
296   helper->getData(x, "x");
297   helper->getData(y, "y");
298   d_ruin_pos = Vector<int>(x,y);
299 }
300
301 Reward_Ruin::Reward_Ruin (const Reward_Ruin& orig)
302         :Reward(orig), d_ruin_pos(orig.d_ruin_pos)
303 {
304 }
305 bool Reward_Ruin::save(XML_Helper* helper) const
306 {
307   bool retval = true;
308   retval &= helper->openTag(Reward::d_tag);
309   std::string type_str = rewardTypeToString(Reward::Type(d_type));
310   retval &= helper->saveData("type", type_str);
311   retval &= helper->saveData("name", d_name);
312   retval &= helper->saveData("x", getRuin()->getPos().x);
313   retval &= helper->saveData("y", getRuin()->getPos().y);
314   retval &= helper->closeTag();
315   return retval;
316 }
317
318 Ruin *Reward_Ruin::getRandomHiddenRuin()
319 {
320   std::vector<Ruin *>hidden_ruins;
321   Ruinlist *rl = Ruinlist::getInstance();
322   Rewardlist *rw = Rewardlist::getInstance();
323   for (Ruinlist::iterator it = rl->begin(); it != rl->end(); it++)
324     {
325       if ((*it)->isHidden())
326         if ((*it)->getOwner() == NULL || 
327             (*it)->getOwner() == Playerlist::getInstance()->getNeutral())
328           {
329             //is it already being pointed to by a reward in the rewardlist?
330             bool found = false;
331             for (Rewardlist::iterator i = rw->begin(); i != rw->end(); i++)
332               {
333                 if ((*i)->getType() == Reward::RUIN)
334                   {
335                     Ruin *r = static_cast<Reward_Ruin*>(*i)->getRuin();
336                     if (r)
337                       {
338                         if (r->getPos() == (*it)->getPos())
339                           {
340                             found = true;
341                             break;
342                           }
343                       }
344                   }
345               }
346             if (found == false)
347               hidden_ruins.push_back(*it);
348           }
349     }
350  if (hidden_ruins.empty())
351    return NULL;
352  return hidden_ruins[rand() % hidden_ruins.size()];
353 }
354
355 Reward_Ruin::~Reward_Ruin()
356 {
357 }
358
359 Reward_Map::Reward_Map(Vector<int> pos, std::string name, 
360                        guint32 height, guint32 width)
361     :Reward(Reward::MAP, name)
362 {
363   d_sightmap = new SightMap(name, pos, height, width);
364 }
365
366 bool Reward_Map::loadMap(std::string tag, XML_Helper* helper)
367 {
368   if (tag == SightMap::d_tag)
369     {
370       d_sightmap = new SightMap(helper);
371       return true;
372     }
373     
374   return false;
375 }
376
377
378 Reward_Map::Reward_Map(XML_Helper* helper)
379     :Reward(helper)
380 {
381   helper->registerTag(SightMap::d_tag, sigc::mem_fun(this, &Reward_Map::loadMap));
382 }
383
384 Reward_Map::Reward_Map (const Reward_Map& orig)
385         :Reward(orig)
386 {
387   d_sightmap = new SightMap(*orig.d_sightmap);
388 }
389
390 bool Reward_Map::save(XML_Helper* helper) const
391 {
392   bool retval = true;
393   retval &= helper->openTag(Reward::d_tag);
394   std::string type_str = rewardTypeToString(Reward::Type(d_type));
395   retval &= helper->saveData("type", type_str);
396   retval &= helper->saveData("name", d_sightmap->getName());
397   retval &= d_sightmap->save(helper);
398   retval &= helper->closeTag();
399   return retval;
400 }
401
402 void Reward_Map::getRandomMap(int *x, int *y, int *width, int *height)
403 {
404   int map_width = GameMap::getInstance()->getWidth();
405   *x = rand() % (map_width - (map_width / 10));
406   int map_height = GameMap::getInstance()->getHeight();
407   *y = rand() % (map_height - (map_height / 10));
408   *width = ((rand() % (map_width - *x)) + (map_width / 10));
409   *height = ((rand() % (map_height - *y)) + (map_height / 10));
410 }
411
412 Reward_Map::~Reward_Map()
413 {
414   if (d_sightmap)
415     delete d_sightmap;
416 }
417
418 std::string Reward::getDescription() const
419 {
420   Glib::ustring s = "";
421   switch (getType())
422     {
423     case Reward::GOLD:
424         {
425           const Reward_Gold *g = dynamic_cast<const Reward_Gold*>(this);
426           s += String::ucompose(ngettext("%1 Gold Piece", "%1 Gold Pieces", 
427                                          g->getGold()), g->getGold());
428           return s;
429         }
430     case Reward::ALLIES:
431         {
432           const Reward_Allies *a = dynamic_cast<const Reward_Allies *>(this);
433           if (a->getArmy())
434             s += String::ucompose(_("Allies: %1 x %2"), a->getArmy()->getName(),
435                                   a->getNoOfAllies());
436           return s;
437         }
438     case Reward::ITEM:
439         {
440           const Reward_Item *i = dynamic_cast<const Reward_Item *>(this);
441           if (i->getItem())
442             s += String::ucompose(_("Item: %1"), i->getItem()->getName());
443           return s;
444         }
445     case Reward::RUIN:
446         {
447           const Reward_Ruin *r = dynamic_cast<const Reward_Ruin *>(this);
448           if (r->getRuin())
449             s += String::ucompose(_("Site: %1"), r->getRuin()->getName());
450           return s;
451         }
452     case Reward::MAP:
453         {
454           const Reward_Map *m = dynamic_cast<const Reward_Map *>(this);
455           s += String::ucompose(_("Map: %1,%2 %3x%4"), 
456                                   m->getLocation().x,
457                                   m->getLocation().y,
458                                   m->getHeight(),
459                                   m->getWidth());
460           return s;
461         }
462     }
463   return s;
464 }
465
466 std::string Reward::rewardTypeToString(const Reward::Type type)
467 {
468   switch (type)
469     {
470       case Reward::GOLD:
471         return "Reward::GOLD";
472         break;
473       case Reward::ALLIES:
474         return "Reward::ALLIES";
475         break;
476       case Reward::ITEM:
477         return "Reward::ITEM";
478         break;
479       case Reward::RUIN:
480         return "Reward::RUIN";
481         break;
482       case Reward::MAP:
483         return "Reward::MAP";
484         break;
485     }
486   return "Reward::GOLD";
487 }
488
489 Reward::Type Reward::rewardTypeFromString(const std::string str)
490 {
491   if (str.size() > 0 && isdigit(str.c_str()[0]))
492     return Reward::Type(atoi(str.c_str()));
493   if (str == "Reward::GOLD")
494     return Reward::GOLD;
495   else if (str == "Reward::ALLIES")
496     return Reward::ALLIES;
497   else if (str == "Reward::ITEM")
498     return Reward::ITEM;
499   else if (str == "Reward::RUIN")
500     return Reward::RUIN;
501   else if (str == "Reward::MAP")
502     return Reward::MAP;
503   return Reward::GOLD;
504 }
505
506 Reward* Reward::copy(const Reward* r)
507 {
508   switch(r->getType())
509     {
510     case  Reward::GOLD:
511       return (new Reward_Gold(*dynamic_cast<const Reward_Gold*>(r)));
512     case  Reward::ALLIES:
513       return (new Reward_Allies(*dynamic_cast<const Reward_Allies*>(r)));
514     case Reward::ITEM:
515       return (new Reward_Item(*dynamic_cast<const Reward_Item*>(r)));
516     case Reward::RUIN:
517       return (new Reward_Ruin(*dynamic_cast<const Reward_Ruin*>(r)));
518     case Reward::MAP:
519       return (new Reward_Map(*dynamic_cast<const Reward_Map*>(r)));
520     }
521
522   return 0;
523 }