1 /*
2  * Copyright 2010-2014 OpenXcom Developers.
3  *
4  * This file is part of OpenXcom.
5  *
6  * OpenXcom is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * OpenXcom is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #ifndef OPENXCOM_RULEREGION_H
20 #define OPENXCOM_RULEREGION_H
21 
22 #include <string>
23 #include <vector>
24 #include <yaml-cpp/yaml.h>
25 #include "../fmath.h"
26 #include "../Savegame/WeightedOptions.h"
27 
28 namespace OpenXcom
29 {
30 
31 /**
32  * Defines a rectangle in polar coordinates.
33  * It is used to define areas for a mission zone.
34  */
35 struct MissionArea
36 {
37 	double lonMin, lonMax, latMin, latMax;
38 
39     bool operator== (const MissionArea& ma) const
40 	{
41 		return AreSame(lonMax, ma.lonMax) && AreSame(lonMin, ma.lonMin) && AreSame(latMax, ma.latMax) && AreSame(latMin, ma.latMin);
42 	}
43 };
44 
45 /**
46  * A zone (set of areas) on the globe.
47  */
48 struct MissionZone
49 {
50 	std::vector<MissionArea> areas;
51 
swapMissionZone52 	void swap(MissionZone &other)
53 	{
54 		areas.swap(other.areas);
55 	}
56 };
57 
58 class City;
59 
60 /**
61  * Represents a specific region of the world.
62  * Contains constant info about a region like area
63  * covered and base construction costs.
64  */
65 class RuleRegion
66 {
67 private:
68 	std::string _type;
69 	int _cost;
70 	std::vector<double> _lonMin, _lonMax, _latMin, _latMax;
71 	std::vector<City*> _cities;
72 	/// Weighted list of the different mission types for this region.
73 	WeightedOptions _missionWeights;
74 	/// Weight of this region when selecting regions for alien missions.
75 	size_t _regionWeight;
76 	/// All the mission zones in this region.
77 	std::vector<MissionZone> _missionZones;
78 	/// Do missions in the region defined by this string instead.
79 	std::string _missionRegion;
80 public:
81 	static const int CITY_MISSION_ZONE = 3;
82 	static const int ALIEN_BASE_ZONE = 4;
83 	/// Creates a blank region ruleset.
84 	RuleRegion(const std::string &type);
85 	/// Cleans up the region ruleset.
86 	~RuleRegion();
87 	/// Loads the region from YAML.
88 	void load(const YAML::Node& node);
89 	/// Gets the region's type.
90 	std::string getType() const;
91 	/// Gets the region's base cost.
92 	int getBaseCost() const;
93 	/// Checks if a point is inside the region.
94 	bool insideRegion(double lon, double lat) const;
95 	/// Gets the cities in this region.
96 	std::vector<City*> *getCities();
97 	/// Gets the weight of this region for mission selection.
98 	size_t getWeight() const;
99 	/// Gets the weighted list of missions for this region.
getAvailableMissions()100 	const WeightedOptions &getAvailableMissions() const { return _missionWeights; }
101 	/// Gets the substitute mission region.
getMissionRegion()102 	const std::string &getMissionRegion() const { return _missionRegion; }
103 	/// Gets a random point inside a mission site.
104 	std::pair<double, double> getRandomPoint(size_t site) const;
105 	/// Gets the maximum longitude.
getLonMax()106 	const std::vector<double> &getLonMax() const { return _lonMax; }
107 	/// Gets the minimum longitude.
getLonMin()108 	const std::vector<double> &getLonMin() const { return _lonMin; }
109 	/// Gets the maximum latitude.
getLatMax()110 	const std::vector<double> &getLatMax() const { return _latMax; }
111 	/// Gets the minimum latitude.
getLatMin()112 	const std::vector<double> &getLatMin() const { return _latMin; }
113 	const std::vector<MissionZone> &getMissionZones() const;
114 };
115 
116 }
117 
118 namespace YAML
119 {
120 	template<>
121 	struct convert<OpenXcom::MissionArea>
122 	{
123 		static Node encode(const OpenXcom::MissionArea& rhs)
124 		{
125 			Node node;
126 			node.push_back(rhs.lonMin);
127 			node.push_back(rhs.lonMax);
128 			node.push_back(rhs.latMin);
129 			node.push_back(rhs.latMax);
130 			return node;
131 		}
132 
133 		static bool decode(const Node& node, OpenXcom::MissionArea& rhs)
134 		{
135 			if (!node.IsSequence() || node.size() != 4)
136 				return false;
137 
138 			rhs.lonMin = node[0].as<double>();
139 			rhs.lonMax = node[1].as<double>();
140 			rhs.latMin = node[2].as<double>();
141 			rhs.latMax = node[3].as<double>();
142 			return true;
143 		}
144 	};
145 
146 	template<>
147 	struct convert<OpenXcom::MissionZone>
148 	{
149 		static Node encode(const OpenXcom::MissionZone& rhs)
150 		{
151 			Node node;
152 			node = rhs.areas;
153 			return node;
154 		}
155 
156 		static bool decode(const Node& node, OpenXcom::MissionZone& rhs)
157 		{
158 			if (!node.IsSequence())
159 				return false;
160 
161 			rhs.areas = node.as< std::vector<OpenXcom::MissionArea> >(rhs.areas);
162 			return true;
163 		}
164 	};
165 }
166 
167 #endif
168