Implement writing of town/outdoors map data to file

This commit is contained in:
2015-01-23 18:21:20 -05:00
parent f00675c4f4
commit 9b067b62e4
5 changed files with 158 additions and 15 deletions

View File

@@ -10,6 +10,8 @@
#include <fstream>
#include <cctype>
#include <iterator>
#include <numeric>
using namespace std;
@@ -57,7 +59,7 @@ map_data load_map(fs::path path, bool isTown) {
curFeature = eMapFeature::TOWN;
} else if(c == '@' && isTown) {
curFeature = eMapFeature::ITEM;
} else if(c == '&' && isTown) {
} else if(c == '&') {
curFeature = eMapFeature::FIELD;
} else if(c == '$') {
curFeature = eMapFeature::CREATURE;
@@ -89,9 +91,9 @@ map_data load_map(fs::path path, bool isTown) {
void map_data::set(unsigned int x, unsigned int y, unsigned int val) {
// First make sure the location exists
if(y > grid.size())
if(y >= grid.size())
grid.resize(y + 1);
if(x > grid[y].size())
if(x >= grid[y].size())
grid[y].resize(x + 1);
grid[y][x] = val;
}
@@ -107,6 +109,51 @@ void map_data::addFeature(unsigned int x, unsigned int y, eMapFeature feature, i
features.insert({loc,{feature,val}});
}
auto map_data::getFeatures(unsigned int x, unsigned int y) -> std::vector<feature_t> {
std::vector<feature_t> ls;
if(y >= grid.size()) return ls;
if(x >= grid[y].size()) return ls;
using iter_t = decltype(features)::const_iterator;
std::pair<iter_t,iter_t> range = features.equal_range(loc(x,y));
if(range.first == range.second) return ls;
for(auto iter = range.first; iter != range.second; iter++)
ls.push_back(iter->second);
return ls;
}
void map_data::writeTo(std::ostream& out) {
unsigned int height = grid.size();
unsigned int width = std::accumulate(grid.begin(), grid.end(), 0, [](size_t m, std::vector<int>& v){
return std::max(m, v.size());
});
for(unsigned int x = 0; x < width; x++) {
bool first = true;
for(unsigned int y = 0; y < height; y++) {
if(!first) out << ',';
first = false;
out << grid[y][x];
for(auto feat : getFeatures(x,y)) {
switch(feat.first) {
case eMapFeature::NONE: case eMapFeature::VEHICLE: break;
case eMapFeature::SPECIAL_NODE: out << ':' << feat.second; break;
case eMapFeature::SIGN: out << '!' << feat.second; break;
case eMapFeature::WANDERING: out << '*' << feat.second; break;
case eMapFeature::TOWN: case eMapFeature::ITEM: out << '@' << feat.second; break;
case eMapFeature::CREATURE: out << '$' << feat.second; break;
case eMapFeature::FIELD: out << '&' << feat.second; break;
case eMapFeature::ENTRANCE_EAST: out << '>'; break;
case eMapFeature::ENTRANCE_NORTH: out << '^'; break;
case eMapFeature::ENTRANCE_SOUTH: out << 'v'; break;
case eMapFeature::ENTRANCE_WEST: out << '<'; break;
case eMapFeature::BOAT: out << (feat.second < 0 ? 'b' : 'B') << abs(feat.second); break;
case eMapFeature::HORSE: out << (feat.second < 0 ? 'h' : 'H') << abs(feat.second); break;
}
}
}
out << '\n';
}
}
bool loc_compare::operator()(location a, location b) const {
// This is just a lexicographical ordering.
if(a.x != b.x) return a.x < b.x;

View File

@@ -11,6 +11,7 @@
#include <vector>
#include <map>
#include <iosfwd>
#include <boost/filesystem/path.hpp>
#include "location.h"
@@ -38,12 +39,16 @@ struct loc_compare {
bool operator()(location a, location b) const;
};
struct map_data {
class map_data {
std::vector<std::vector<int>> grid;
std::multimap<location,std::pair<eMapFeature,int>,loc_compare> features;
using feature_t = std::pair<eMapFeature,int>;
std::multimap<location,feature_t,loc_compare> features;
public:
void set(unsigned int x, unsigned int y, unsigned int val);
unsigned int get(unsigned int x, unsigned int y);
void addFeature(unsigned int x, unsigned int y, eMapFeature feature, int val = 0);
std::vector<feature_t> getFeatures(unsigned int x, unsigned int y);
void writeTo(std::ostream& out);
};
map_data load_map(fs::path path, bool isTown);