1 #include "FieldType.h"
2 
3 #include <boost/algorithm/string/case_conv.hpp>
4 #include "ConditionSource.h"
5 #include "Effects.h"
6 #include "Enums.h"
7 #include "ValueRefs.h"
8 #include "UniverseObject.h"
9 #include "../util/CheckSums.h"
10 
11 
12 namespace {
13     std::shared_ptr<Effect::EffectsGroup>
IncreaseMeter(MeterType meter_type,double increase)14     IncreaseMeter(MeterType meter_type, double increase) {
15         typedef std::vector<std::unique_ptr<Effect::Effect>> Effects;
16         auto scope = std::make_unique<Condition::Source>();
17         std::unique_ptr<Condition::Source> activation = nullptr;
18         auto vr =
19             std::make_unique<ValueRef::Operation<double>>(
20                 ValueRef::PLUS,
21                 std::make_unique<ValueRef::Variable<double>>(
22                     ValueRef::EFFECT_TARGET_VALUE_REFERENCE, std::vector<std::string>()),
23                 std::make_unique<ValueRef::Constant<double>>(increase)
24             );
25         auto effects = Effects();
26         effects.push_back(std::make_unique<Effect::SetMeter>(meter_type, std::move(vr)));
27         return std::make_shared<Effect::EffectsGroup>(std::move(scope), std::move(activation), std::move(effects));
28     }
29 }
30 
31 
FieldType(const std::string & name,const std::string & description,float stealth,const std::set<std::string> & tags,std::vector<std::unique_ptr<Effect::EffectsGroup>> && effects,const std::string & graphic)32 FieldType::FieldType(const std::string& name, const std::string& description,
33                      float stealth, const std::set<std::string>& tags,
34                      std::vector<std::unique_ptr<Effect::EffectsGroup>>&& effects,
35                      const std::string& graphic) :
36     m_name(name),
37     m_description(description),
38     m_stealth(stealth),
39     m_tags(),
40     m_effects(),
41     m_graphic(graphic)
42 {
43     for (const std::string& tag : tags)
44         m_tags.insert(boost::to_upper_copy<std::string>(tag));
45 
46     for (auto&& effect : effects)
47         m_effects.emplace_back(std::move(effect));
48 
49     if (m_stealth != 0.0f)
50         m_effects.push_back(IncreaseMeter(METER_STEALTH,    m_stealth));
51 
52     for (auto& effect : m_effects) {
53         effect->SetTopLevelContent(m_name);
54     }
55 }
56 
Dump(unsigned short ntabs) const57 std::string FieldType::Dump(unsigned short ntabs) const {
58     std::string retval = DumpIndent(ntabs) + "FieldType\n";
59     retval += DumpIndent(ntabs+1) + "name = \"" + m_name + "\"\n";
60     retval += DumpIndent(ntabs+1) + "description = \"" + m_description + "\"\n";
61     retval += DumpIndent(ntabs+1) + "location = \n";
62     if (m_effects.size() == 1) {
63         retval += DumpIndent(ntabs+1) + "effectsgroups =\n";
64         retval += m_effects[0]->Dump(ntabs+2);
65     } else {
66         retval += DumpIndent(ntabs+1) + "effectsgroups = [\n";
67         for (auto& effect : m_effects) {
68             retval += effect->Dump(ntabs+2);
69         }
70         retval += DumpIndent(ntabs+1) + "]\n";
71     }
72     retval += DumpIndent(ntabs+1) + "graphic = \"" + m_graphic + "\"\n";
73     return retval;
74 }
75 
GetCheckSum() const76 unsigned int FieldType::GetCheckSum() const {
77     unsigned int retval{0};
78 
79     CheckSums::CheckSumCombine(retval, m_name);
80     CheckSums::CheckSumCombine(retval, m_description);
81     CheckSums::CheckSumCombine(retval, m_stealth);
82     CheckSums::CheckSumCombine(retval, m_tags);
83     CheckSums::CheckSumCombine(retval, m_effects);
84     CheckSums::CheckSumCombine(retval, m_graphic);
85 
86     DebugLogger() << "FieldTypeManager checksum: " << retval;
87     return retval;
88 }
89 
90 
91 FieldTypeManager* FieldTypeManager::s_instance = nullptr;
92 
FieldTypeManager()93 FieldTypeManager::FieldTypeManager() {
94     if (s_instance)
95         throw std::runtime_error("Attempted to create more than one FieldTypeManager.");
96 
97     // Only update the global pointer on sucessful construction.
98     s_instance = this;
99 }
100 
GetFieldType(const std::string & name) const101 const FieldType* FieldTypeManager::GetFieldType(const std::string& name) const {
102     CheckPendingFieldTypes();
103     auto it = m_field_types.find(name);
104     return it != m_field_types.end() ? it->second.get() : nullptr;
105 }
106 
begin() const107 FieldTypeManager::iterator FieldTypeManager::begin() const {
108     CheckPendingFieldTypes();
109     return m_field_types.begin();
110 }
111 
end() const112 FieldTypeManager::iterator FieldTypeManager::end() const {
113     CheckPendingFieldTypes();
114     return m_field_types.end();
115 }
116 
GetFieldTypeManager()117 FieldTypeManager& FieldTypeManager::GetFieldTypeManager() {
118     static FieldTypeManager manager;
119     return manager;
120 }
121 
GetCheckSum() const122 unsigned int FieldTypeManager::GetCheckSum() const {
123     CheckPendingFieldTypes();
124     unsigned int retval{0};
125     for (auto const& name_type_pair : m_field_types)
126         CheckSums::CheckSumCombine(retval, name_type_pair);
127     CheckSums::CheckSumCombine(retval, m_field_types.size());
128 
129     return retval;
130 }
131 
SetFieldTypes(Pending::Pending<container_type> && future)132 void FieldTypeManager::SetFieldTypes(Pending::Pending<container_type>&& future)
133 { m_pending_types = std::move(future); }
134 
CheckPendingFieldTypes() const135 void FieldTypeManager::CheckPendingFieldTypes() const
136 { Pending::SwapPending(m_pending_types, m_field_types); }
137 
138 
GetFieldTypeManager()139 FieldTypeManager& GetFieldTypeManager()
140 { return FieldTypeManager::GetFieldTypeManager(); }
141 
GetFieldType(const std::string & name)142 const FieldType* GetFieldType(const std::string& name)
143 { return FieldTypeManager::GetFieldTypeManager().GetFieldType(name); }
144