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