1 // Copyright 2015-2018 the openage authors. See copying.md for legal info.
2 
3 #pragma once
4 
5 #include <functional>
6 #include <string>
7 
8 namespace openage {
9 
10 class ResourceBundle;
11 
12 /**
13  * A resource
14  */
15 class Resource {
16 public:
17 
18 	Resource();
19 
20 	virtual int id() const = 0;
21 
22 	virtual std::string name() const = 0;
23 
24 	// TODO add images and icons
25 
26 };
27 
28 class ResourceProducer : public Resource {
29 public:
30 
ResourceProducer(int id,std::string name)31 	ResourceProducer(int id, std::string name)
32 		:
33 		_id{id},
34 		_name{name} { }
35 
id()36 	int id() const override { return _id; }
37 
name()38 	std::string name() const override { return _name; }
39 
40 private:
41 
42 	int _id;
43 	std::string _name;
44 };
45 
46 /**
47  * All the resources.
48  *
49  * The the ids of the resources must be inside [0, count).
50  *
51  * The static variables wood, food, gold, stone are the ids of the representing resource.
52  * Any extension of Resources must use this ids as they are an engine dependency (at the moment).
53  */
54 class Resources {
55 public:
56 
57 	Resources();
58 
59 	virtual unsigned int get_count() const = 0;
60 
61 	virtual const Resource& get_resource(int id) const = 0;
62 
63 	ResourceBundle create_bundle() const;
64 
65 	// TODO remove when the engine is fully decupled from the data
66 	static const int wood = 0;
67 	static const int food = 1;
68 	static const int gold = 2;
69 	static const int stone = 3;
70 
71 };
72 
73 class ClassicResources : public Resources {
74 public:
75 
ClassicResources()76 	ClassicResources()
77 		:
78 		resources{{Resources::wood, "wood"},
79 		          {Resources::food, "food"},
80 		          {Resources::gold, "gold"},
81 		          {Resources::stone, "stone"}} {
82 	}
83 
get_count()84 	unsigned int get_count() const override { return 4; }
85 
get_resource(int id)86 	const Resource& get_resource(int id) const override { return this->resources[id]; };
87 
88 private:
89 
90 	const ResourceProducer resources[4];
91 };
92 
93 // TODO remove, here for backwards compatibility
94 enum class game_resource : int {
95 	wood = 0,
96 	food = 1,
97 	gold = 2,
98 	stone = 3,
99 	RESOURCE_TYPE_COUNT = 4
100 };
101 
102 
103 /**
104  * A set of amounts of game resources.
105  *
106  * Can be also used to store other information about the resources.
107  *
108  * TODO change amounts from doubles to integers
109  */
110 class ResourceBundle {
111 public:
112 
113 	// TODO remove, here for backwards compatibility
114 	ResourceBundle();
115 
116 	ResourceBundle(const Resources& resources);
117 
118 	virtual ~ResourceBundle();
119 
120 	ResourceBundle(const ResourceBundle& other);
121 
122 	ResourceBundle clone() const;
123 
124 	bool operator> (const ResourceBundle& other) const;
125 	bool operator>= (const ResourceBundle& other) const;
126 
127 	ResourceBundle& operator+= (const ResourceBundle& other);
128 	ResourceBundle& operator-= (const ResourceBundle& other);
129 
130 	ResourceBundle& operator*= (const double a);
131 
132 	/**
133 	 * Round each value to the nearest integer.
134 	 * Returns itself.
135 	 */
136 	ResourceBundle& round();
137 
138 	bool has(const ResourceBundle& amount) const;
139 
140 	bool has(const ResourceBundle& amount1, const ResourceBundle& amount2) const;
141 
142 	/**
143 	 * If amount can't be deducted return false, else deduct the given amount
144 	 * and return true.
145 	 */
146 	bool deduct(const ResourceBundle& amount);
147 
148 	void set(const ResourceBundle& amount);
149 
150 	void set_all(const double amount);
151 
152 	void limit(const ResourceBundle& limits);
153 
154 	double& operator[] (const game_resource res) { return value[static_cast<int>(res)]; }
155 	double& operator[] (const int id) { return value[id]; }
156 
157 	// Getters
158 
get(const game_resource res)159 	double get(const game_resource res) const { return value[static_cast<int>(res)]; }
get(const int id)160 	double get(const int id) const { return value[id]; }
161 
162 	/**
163 	 * Returns the sum of all the resources.
164 	 */
165 	double sum() const;
166 
167 	/**
168 	 * The number of resources
169 	 */
get_count()170 	int get_count() const { return count; };
171 
172 private:
173 
174 	ResourceBundle(const int count);
175 
176 	void expand(const ResourceBundle& other);
177 
178 	void expand(const int count);
179 
180 	/**
181 	 * The number of resources
182 	 */
183 	int count;
184 
185 	double *value;
186 
187 	int min_count(const ResourceBundle& other);
188 
189 };
190 
191 } // namespace openage
192 
193 namespace std {
194 
195 std::string to_string(const openage::game_resource &res);
196 
197 /**
198  * hasher for game resource
199  */
200 template<> struct hash<openage::game_resource> {
201 	typedef underlying_type<openage::game_resource>::type underlying_type;
202 
203 	size_t operator()(const openage::game_resource &arg) const {
204 		hash<underlying_type> hasher;
205 		return hasher(static_cast<underlying_type>(arg));
206 	}
207 };
208 
209 } // namespace std
210