/* * ResourceSet.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once typedef si32 TResource; typedef si64 TResourceCap; //to avoid overflow when adding integers. Signed values are easier to control. class JsonNode; class JsonSerializeFormat; namespace Res { class ResourceSet; bool canAfford(const ResourceSet &res, const ResourceSet &price); //can a be used to pay price b enum ERes { WOOD = 0, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD, MITHRIL, WOOD_AND_ORE = 127, // special case for town bonus resource INVALID = -1 }; //class to be representing a vector of resource class ResourceSet : public std::vector<int> { public: DLL_LINKAGE ResourceSet(); // read resources set from json. Format example: { "gold": 500, "wood":5 } DLL_LINKAGE ResourceSet(const JsonNode & node); DLL_LINKAGE ResourceSet(TResource wood, TResource mercury, TResource ore, TResource sulfur, TResource crystal, TResource gems, TResource gold, TResource mithril = 0); #define scalarOperator(OPSIGN) \ ResourceSet operator OPSIGN(const TResource &rhs) const \ { \ ResourceSet ret = *this; \ for(int i = 0; i < (int)size(); i++) \ ret[i] = at(i) OPSIGN rhs; \ \ return ret; \ } #define vectorOperator(OPSIGN) \ ResourceSet operator OPSIGN(const ResourceSet &rhs) const \ { \ ResourceSet ret = *this; \ for(int i = 0; i < (int)size(); i++) \ ret[i] = at(i) OPSIGN rhs[i]; \ \ return ret; \ } #define opEqOperator(OPSIGN, RHS_TYPE) \ ResourceSet& operator OPSIGN ## =(const RHS_TYPE &rhs) \ { \ return *this = *this OPSIGN rhs; \ } scalarOperator(+) scalarOperator(-) scalarOperator(*) scalarOperator(/) opEqOperator(+, TResource) opEqOperator(-, TResource) opEqOperator(*, TResource) vectorOperator(+) vectorOperator(-) opEqOperator(+, ResourceSet) opEqOperator(-, ResourceSet) #undef scalarOperator #undef vectorOperator #undef opEqOperator //to be used for calculations of type "how many units of sth can I afford?" int operator/(const ResourceSet &rhs) { int ret = INT_MAX; for(int i = 0; i < (int)size(); i++) if(rhs[i]) vstd::amin(ret, at(i) / rhs[i]); return ret; } ResourceSet & operator=(const TResource &rhs) { for(int i = 0; i < (int)size(); i++) at(i) = rhs; return *this; } ResourceSet operator-() const { ResourceSet ret; for(int i = 0; i < (int)size(); i++) ret[i] = -at(i); return ret; } // WARNING: comparison operators are used for "can afford" relation: a <= b means that foreach i a[i] <= b[i] // that doesn't work the other way: a > b doesn't mean that a cannot be afforded with b, it's still b can afford a // bool operator<(const ResourceSet &rhs) // { // for(int i = 0; i < size(); i++) // if(at(i) >= rhs[i]) // return false; // // return true; // } template <typename Handler> void serialize(Handler &h, const int version) { h & static_cast<std::vector<int>&>(*this); } DLL_LINKAGE void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName); DLL_LINKAGE void amax(const TResourceCap &val); //performs vstd::amax on each element DLL_LINKAGE void amin(const TResourceCap &val); //performs vstd::amin on each element DLL_LINKAGE void positive(); //values below 0 are set to 0 - upgrade cost can't be negative, for example DLL_LINKAGE bool nonZero() const; //returns true if at least one value is non-zero; DLL_LINKAGE bool canAfford(const ResourceSet &price) const; DLL_LINKAGE bool canBeAfforded(const ResourceSet &res) const; DLL_LINKAGE TResourceCap marketValue() const; DLL_LINKAGE std::string toString() const; //special iterator of iterating over non-zero resources in set class DLL_LINKAGE nziterator { struct ResEntry { Res::ERes resType; TResourceCap resVal; } cur; const ResourceSet &rs; void advance(); public: nziterator(const ResourceSet &RS); bool valid(); nziterator operator++(); nziterator operator++(int); const ResEntry& operator*() const; const ResEntry* operator->() const; }; }; } typedef Res::ResourceSet TResources;