1 // Copyright (C) 2000, 2001, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004, 2005 Andrea Paternesi
4 // Copyright (C) 2007, 2008, 2014, 2015, 2020 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 "ucompose.hpp"
24 #include "armybase.h"
25 #include "xmlhelper.h"
26 #include "Tile.h"
27 #include "defs.h"
28 
29 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
30 #define debug(x)
31 
ArmyBase(const ArmyBase & a)32 ArmyBase::ArmyBase(const ArmyBase& a)
33 : d_upkeep(a.d_upkeep), d_strength(a.d_strength), d_max_moves(a.d_max_moves),
34     d_sight(a.d_sight), d_move_bonus(a.d_move_bonus),
35     d_army_bonus(a.d_army_bonus), d_xp_value(a.d_xp_value)
36 {
37 }
38 
ArmyBase()39 ArmyBase::ArmyBase()
40   : d_upkeep(0),
41     d_strength(0), d_max_moves(0), d_sight(0),
42     d_move_bonus(0), d_army_bonus(0), d_xp_value(0.0)
43 {
44 }
45 
ArmyBase(XML_Helper * helper)46 ArmyBase::ArmyBase(XML_Helper* helper)
47 {
48   helper->getData(d_upkeep, "upkeep");
49   Glib::ustring move_bonus_str;
50   helper->getData(move_bonus_str, "move_bonus");
51   d_move_bonus = moveFlagsFromString(move_bonus_str);
52   Glib::ustring army_bonus_str;
53   helper->getData(army_bonus_str, "army_bonus");
54   d_army_bonus = bonusFlagsFromString(army_bonus_str);
55   helper->getData(d_max_moves, "max_moves");
56   helper->getData(d_strength, "strength");
57   helper->getData(d_sight, "sight");
58   helper->getData(d_xp_value, "expvalue");
59 }
60 
saveData(XML_Helper * helper) const61 bool ArmyBase::saveData(XML_Helper* helper) const
62 {
63   bool retval = true;
64   retval &= helper->saveData("upkeep", d_upkeep);
65   Glib::ustring move_bonus_str = moveFlagsToString(d_move_bonus);
66   retval &= helper->saveData("move_bonus", move_bonus_str);
67   Glib::ustring army_bonus_str = bonusFlagsToString(d_army_bonus);
68   retval &= helper->saveData("army_bonus", army_bonus_str);
69   retval &= helper->saveData("max_moves", d_max_moves);
70   retval &= helper->saveData("strength", d_strength);
71   retval &= helper->saveData("sight", d_sight);
72   retval &= helper->saveData("expvalue", d_xp_value);
73   return retval;
74 }
75 
getArmyBonusDescription() const76 Glib::ustring ArmyBase::getArmyBonusDescription() const
77 {
78   guint32 bonus = d_army_bonus;
79   Glib::ustring s = "";
80   if (bonus & ArmyBase::ADD1STRINOPEN && bonus & ArmyBase::ADD2STRINOPEN)
81     s += String::ucompose("%1%2", s == "" ? " " : "& ",
82 			  _("+3 str in open"));
83   else if (bonus & ArmyBase::ADD1STRINOPEN)
84     s += String::ucompose("%1%2", s == "" ? " " : "& ",
85 			  _("+1 str in open"));
86   else if (bonus & ArmyBase::ADD2STRINOPEN)
87     s += String::ucompose("%1%2", s == "" ? " " : "& ",
88 			  _("+2 str in open"));
89   if (bonus & ArmyBase::ADD1STRINFOREST && bonus & ArmyBase::ADD2STRINFOREST)
90     s += String::ucompose("%1%2", s == "" ? " " : "& ",
91 			  _("+3 str in woods"));
92   else if (bonus & ArmyBase::ADD1STRINFOREST)
93     s += String::ucompose("%1%2", s == "" ? " " : "& ",
94 			  _("+1 str in woods"));
95   else if (bonus & ArmyBase::ADD2STRINFOREST)
96     s += String::ucompose("%1%2", s == "" ? " " : "& ",
97 			  _("+2 str in woods"));
98   if (bonus & ArmyBase::ADD1STRINHILLS && bonus & ArmyBase::ADD2STRINHILLS)
99     s += String::ucompose("%1%2", s == "" ? " " : " & ",
100 			  _("+3 str in hills"));
101   else if (bonus & ArmyBase::ADD1STRINHILLS)
102     s += String::ucompose("%1%2", s == "" ? " " : " & ",
103 			  _("+1 str in hills"));
104   else if (bonus & ArmyBase::ADD2STRINHILLS)
105     s += String::ucompose("%1%2", s == "" ? " " : " & ",
106 			  _("+2 str in hills"));
107 
108   if (bonus & ArmyBase::ADD1STRINCITY && bonus & ArmyBase::ADD2STRINCITY)
109     s += String::ucompose("%1%2", s == "" ? " " : " & ",
110 			  _("+3 str in city"));
111   else if (bonus & ArmyBase::ADD1STRINCITY)
112     s += String::ucompose("%1%2", s == "" ? " " : " & ",
113 			  _("+1 str in city"));
114   else if (bonus & ArmyBase::ADD2STRINCITY)
115     s += String::ucompose("%1%2", s == "" ? " " : " & ",
116 			  _("+2 str in city"));
117   if (bonus & ArmyBase::ADD1STACKINHILLS)
118     s += String::ucompose("%1%2", s == "" ? " " : " & ",
119 			  _("+1 stack in hills"));
120   if (bonus & ArmyBase::SUBALLCITYBONUS)
121     s += String::ucompose("%1%2", s == "" ? " " : " & ",
122 			  _("Cancel city bonus"));
123   if (bonus & ArmyBase::SUB1ENEMYSTACK && bonus & ArmyBase::SUB2ENEMYSTACK)
124     s += String::ucompose("%1%2", s == "" ? " " : " & ",
125 			  _("-3 enemy stack"));
126   else if (bonus & ArmyBase::SUB1ENEMYSTACK)
127     s += String::ucompose("%1%2", s == "" ? " " : " & ",
128 			  _("-1 enemy stack"));
129   else if (bonus & ArmyBase::SUB2ENEMYSTACK)
130     s += String::ucompose("%1%2", s == "" ? " " : " & ",
131 			  _("-2 enemy stack"));
132 
133   if (bonus & ArmyBase::ADD1STACK && bonus & ArmyBase::ADD2STACK)
134     s += String::ucompose("%1%2", s == "" ? " " : " & ", _("+3 stack"));
135   else if (bonus & ArmyBase::ADD1STACK)
136     s += String::ucompose("%1%2", s == "" ? " " : " & ", _("+1 stack"));
137   else if (bonus & ArmyBase::ADD2STACK)
138     s += String::ucompose("%1%2", s == "" ? " " : " & ", _("+2 stack"));
139   if (bonus & ArmyBase::SUBALLNONHEROBONUS)
140     s += String::ucompose("%1%2", s == "" ? " " : " & ",
141 			  _("cancel non-hero"));
142   if (bonus & ArmyBase::SUBALLHEROBONUS)
143     s += String::ucompose("%1%2", s == "" ? " " : " & ",
144 			  _("cancel hero"));
145   return s;
146 }
147 
moveFlagsToString(const guint32 bonus)148 Glib::ustring ArmyBase::moveFlagsToString(const guint32 bonus)
149 {
150   Glib::ustring move_bonuses;
151   //we don't add grass, because it's always implied.
152   if (bonus & Tile::WATER)
153     move_bonuses += " " + Tile::tileTypeToString(Tile::WATER);
154   if (bonus & Tile::FOREST)
155     move_bonuses += " " + Tile::tileTypeToString(Tile::FOREST);
156   if (bonus & Tile::HILLS)
157     move_bonuses += " " + Tile::tileTypeToString(Tile::HILLS);
158   if (bonus & Tile::MOUNTAIN)
159     move_bonuses += " " + Tile::tileTypeToString(Tile::MOUNTAIN);
160   if (bonus & Tile::SWAMP)
161     move_bonuses += " " + Tile::tileTypeToString(Tile::SWAMP);
162   return move_bonuses;
163 }
164 
moveFlagsFromString(const Glib::ustring str)165 guint32 ArmyBase::moveFlagsFromString(const Glib::ustring str)
166 {
167   return XML_Helper::flagsFromString(str, Tile::tileTypeFromString);
168 }
169 
bonusFlagToString(const ArmyBase::Bonus bonus)170 Glib::ustring ArmyBase::bonusFlagToString(const ArmyBase::Bonus bonus)
171 {
172   switch (bonus)
173     {
174     case ArmyBase::ADD1STRINOPEN: return "ArmyBase::ADD1STRINOPEN";
175     case ArmyBase::ADD2STRINOPEN: return "ArmyBase::ADD2STRINOPEN";
176     case ArmyBase::ADD1STRINFOREST: return "ArmyBase::ADD1STRINFOREST";
177     case ArmyBase::ADD1STRINHILLS: return "ArmyBase::ADD1STRINHILLS";
178     case ArmyBase::ADD1STRINCITY: return "ArmyBase::ADD1STRINCITY";
179     case ArmyBase::ADD2STRINCITY: return "ArmyBase::ADD2STRINCITY";
180     case ArmyBase::ADD1STACKINHILLS: return "ArmyBase::ADD1STACKINHILLS";
181     case ArmyBase::SUBALLCITYBONUS: return "ArmyBase::SUBALLCITYBONUS";
182     case ArmyBase::SUB1ENEMYSTACK: return "ArmyBase::SUB1ENEMYSTACK";
183     case ArmyBase::ADD1STACK: return "ArmyBase::ADD1STACK";
184     case ArmyBase::ADD2STACK: return "ArmyBase::ADD2STACK";
185     case ArmyBase::SUBALLNONHEROBONUS: return "ArmyBase::SUBALLNONHEROBONUS";
186     case ArmyBase::SUBALLHEROBONUS: return "ArmyBase::SUBALLHEROBONUS";
187     case ArmyBase::FORTIFY: return "ArmyBase::FORTIFY";
188     case ArmyBase::ADD2STRINFOREST: return "ArmyBase::ADD2STRINFOREST";
189     case ArmyBase::ADD2STRINHILLS: return "ArmyBase::ADD2STRINHILLS";
190     case ArmyBase::SUB2ENEMYSTACK: return "ArmyBase::SUB2ENEMYSTACK";
191     }
192   return "";
193 }
194 
bonusFlagsToString(const guint32 bonus)195 Glib::ustring ArmyBase::bonusFlagsToString(const guint32 bonus)
196 {
197   Glib::ustring bonuses;
198   if (bonus & ArmyBase::ADD1STRINOPEN)
199     bonuses += " " + bonusFlagToString(ArmyBase::ADD1STRINOPEN);
200   if (bonus & ArmyBase::ADD2STRINOPEN)
201     bonuses += " " + bonusFlagToString(ArmyBase::ADD2STRINOPEN);
202   if (bonus & ArmyBase::ADD1STRINFOREST)
203     bonuses += " " + bonusFlagToString(ArmyBase::ADD1STRINFOREST);
204   if (bonus & ArmyBase::ADD1STRINHILLS)
205     bonuses += " " + bonusFlagToString(ArmyBase::ADD1STRINHILLS);
206   if (bonus & ArmyBase::ADD1STRINCITY)
207     bonuses += " " + bonusFlagToString(ArmyBase::ADD1STRINCITY);
208   if (bonus & ArmyBase::ADD2STRINCITY)
209     bonuses += " " + bonusFlagToString(ArmyBase::ADD2STRINCITY);
210   if (bonus & ArmyBase::ADD1STACKINHILLS)
211     bonuses += " " + bonusFlagToString(ArmyBase::ADD1STACKINHILLS);
212   if (bonus & ArmyBase::SUBALLCITYBONUS)
213     bonuses += " " + bonusFlagToString(ArmyBase::SUBALLCITYBONUS);
214   if (bonus & ArmyBase::SUB1ENEMYSTACK)
215     bonuses += " " + bonusFlagToString(ArmyBase::SUB1ENEMYSTACK);
216   if (bonus & ArmyBase::ADD1STACK)
217     bonuses += " " + bonusFlagToString(ArmyBase::ADD1STACK);
218   if (bonus & ArmyBase::ADD2STACK)
219     bonuses += " " + bonusFlagToString(ArmyBase::ADD2STACK);
220   if (bonus & ArmyBase::SUBALLNONHEROBONUS)
221     bonuses += " " + bonusFlagToString(ArmyBase::SUBALLNONHEROBONUS);
222   if (bonus & ArmyBase::SUBALLHEROBONUS)
223     bonuses += " " + bonusFlagToString(ArmyBase::SUBALLHEROBONUS);
224   if (bonus & ArmyBase::FORTIFY)
225     bonuses += " " + bonusFlagToString(ArmyBase::FORTIFY);
226   if (bonus & ArmyBase::ADD2STRINFOREST)
227     bonuses += " " + bonusFlagToString(ArmyBase::ADD2STRINFOREST);
228   if (bonus & ArmyBase::ADD2STRINHILLS)
229     bonuses += " " + bonusFlagToString(ArmyBase::ADD2STRINHILLS);
230   if (bonus & ArmyBase::SUB2ENEMYSTACK)
231     bonuses += " " + bonusFlagToString(ArmyBase::SUB2ENEMYSTACK);
232   return bonuses;
233 }
234 
bonusFlagsFromString(const Glib::ustring str)235 guint32 ArmyBase::bonusFlagsFromString(const Glib::ustring str)
236 {
237   return XML_Helper::flagsFromString(str, bonusFlagFromString);
238 }
239 
bonusFlagFromString(const Glib::ustring str)240 guint32 ArmyBase::bonusFlagFromString(const Glib::ustring str)
241 {
242   if (str.size() > 0 && isdigit(str.c_str()[0]))
243     return ArmyBase::Bonus(atoi(str.c_str()));
244   if (str == "ArmyBase::ADD1STRINOPEN") return ArmyBase::ADD1STRINOPEN;
245   else if (str == "ArmyBase::ADD2STRINOPEN") return ArmyBase::ADD2STRINOPEN;
246   else if (str == "ArmyBase::ADD1STRINFOREST") return ArmyBase::ADD1STRINFOREST;
247   else if (str == "ArmyBase::ADD1STRINHILLS") return ArmyBase::ADD1STRINHILLS;
248   else if (str == "ArmyBase::ADD1STRINCITY") return ArmyBase::ADD1STRINCITY;
249   else if (str == "ArmyBase::ADD2STRINCITY") return ArmyBase::ADD2STRINCITY;
250   else if (str == "ArmyBase::ADD1STACKINHILLS") return ArmyBase::ADD1STACKINHILLS;
251   else if (str == "ArmyBase::SUBALLCITYBONUS") return ArmyBase::SUBALLCITYBONUS;
252   else if (str == "ArmyBase::SUB1ENEMYSTACK") return ArmyBase::SUB1ENEMYSTACK;
253   else if (str == "ArmyBase::ADD1STACK") return ArmyBase::ADD1STACK;
254   else if (str == "ArmyBase::ADD2STACK") return ArmyBase::ADD2STACK;
255   else if (str == "ArmyBase::SUBALLNONHEROBONUS") return ArmyBase::SUBALLNONHEROBONUS;
256   else if (str == "ArmyBase::SUBALLHEROBONUS") return ArmyBase::SUBALLHEROBONUS;
257   else if (str == "ArmyBase::FORTIFY") return ArmyBase::FORTIFY;
258   else if (str == "ArmyBase::ADD2STRINFOREST") return ArmyBase::ADD2STRINFOREST;
259   else if (str == "ArmyBase::ADD2STRINHILLS") return ArmyBase::ADD2STRINHILLS;
260   else if (str == "ArmyBase::SUB2ENEMYSTACK") return ArmyBase::SUB2ENEMYSTACK;
261   return ArmyBase::ADD1STRINOPEN;
262 }
263 
getMoveBonusDescription() const264 Glib::ustring ArmyBase::getMoveBonusDescription() const
265 {
266   guint32 bonus = getMoveBonus ();
267   if (bonus == Tile::isFlying ())
268     return _("Flies");
269   else
270     {
271       if (bonus == Tile::GRASS)
272         return "";
273       else
274         {
275           Glib::ustring s = "";
276           bool first = true;
277           if (bonus & Tile::WATER)
278             {
279               s += (first ? " " : ", ") +
280                 Tile::tileTypeToFriendlyName(Tile::WATER);
281               first = false;
282             }
283           if (bonus & Tile::FOREST)
284             {
285               s += (first ? " " : ", ") +
286                 Tile::tileTypeToFriendlyName(Tile::FOREST);
287               first = false;
288             }
289           if (bonus & Tile::HILLS)
290             {
291               s += (first ? " " : ", ") +
292                 Tile::tileTypeToFriendlyName(Tile::HILLS);
293               first = false;
294             }
295           if (bonus & Tile::MOUNTAIN)
296             {
297               s += (first ? " " : ", ") +
298                 Tile::tileTypeToFriendlyName(Tile::MOUNTAIN);
299               first = false;
300             }
301           if (bonus & Tile::SWAMP)
302             {
303               s += (first ? " " : ", ") +
304                 Tile::tileTypeToFriendlyName(Tile::SWAMP);
305               first = false;
306             }
307           return s;
308         }
309     }
310   return "";
311 }
312