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

@@ -6,8 +6,7 @@
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
2,2,2,2,2,2,2,2,2,2,2,2*4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
# add * to specify a wandering monster loc; 2*4 indicates all four locs are here
# 2*1 would be more normal if you have wandering monsters
# add * to specify a wandering monster loc; 2*4 indicates the fourth loc is here
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2

View File

@@ -12,8 +12,7 @@
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
2,2,2,2,2,2,2,2,2,2,2,2,2*4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
# add * to specify a wandering monster loc; 2*4 indicates all four locs are here
# 2*1 would be more normal if you have wandering monsters
# add * to specify a wandering monster loc; 2*4 indicates the fourth loc is here
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
2,2,2,2,2,2,2,2,2,2,2,2,2@17,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
# @17 means that preset item number 17 is on this space; it can be applied multiple times, eg 2@17@9

View File

@@ -17,6 +17,7 @@
#include "tarball.hpp"
#include "gzstream.h"
#include "tinyprint.hpp"
#include "map_parse.hpp"
#define DONE_BUTTON_ITEM 1
@@ -108,7 +109,7 @@ static bool is_minmax(int lo, int hi, int val) {
return minmax(lo, hi, val) == val;
}
void writeScenarioToXml(ticpp::Printer&& data) {
static void writeScenarioToXml(ticpp::Printer&& data) {
data.OpenElement("scenario");
data.PushAttribute("boes", scenario.format_ed_version());
data.PushElement("title", scenario.scen_name);
@@ -241,7 +242,7 @@ void writeScenarioToXml(ticpp::Printer&& data) {
data.CloseElement("scenario");
}
void writeTerrainToXml(ticpp::Printer&& data) {
static void writeTerrainToXml(ticpp::Printer&& data) {
data.OpenElement("terrains");
for(size_t i = 0; i < scenario.ter_types.size(); i++) {
data.OpenElement("terrain");
@@ -285,7 +286,7 @@ void writeTerrainToXml(ticpp::Printer&& data) {
data.CloseElement("terrains");
}
void writeItemsToXml(ticpp::Printer&& data) {
static void writeItemsToXml(ticpp::Printer&& data) {
data.OpenElement("items");
for(size_t i = 0; i < scenario.scen_items.size(); i++) {
data.OpenElement("item");
@@ -335,7 +336,7 @@ void writeItemsToXml(ticpp::Printer&& data) {
data.CloseElement("items");
}
void writeMonstersToXml(ticpp::Printer&& data) {
static void writeMonstersToXml(ticpp::Printer&& data) {
std::ostringstream str;
data.OpenElement("monsters");
for(size_t i = 1; i < scenario.scen_monsters.size(); i++) {
@@ -479,7 +480,7 @@ void writeMonstersToXml(ticpp::Printer&& data) {
data.CloseElement("monsters");
}
void writeOutdoorsToXml(ticpp::Printer&& data, cOutdoors& sector) {
static void writeOutdoorsToXml(ticpp::Printer&& data, cOutdoors& sector) {
data.OpenElement("sector");
data.PushAttribute("boes", scenario.format_ed_version());
data.PushElement("name", sector.out_name);
@@ -512,7 +513,7 @@ void writeOutdoorsToXml(ticpp::Printer&& data, cOutdoors& sector) {
data.CloseElement("sector");
}
void writeTownToXml(ticpp::Printer&& data, cTown& town) {
static void writeTownToXml(ticpp::Printer&& data, cTown& town) {
static const char directions[] = {'n', 'w', 's', 'e'};
data.OpenElement("town");
data.PushAttribute("boes", scenario.format_ed_version());
@@ -647,6 +648,96 @@ void writeTownToXml(ticpp::Printer&& data, cTown& town) {
data.CloseElement("town");
}
map_data buildOutMapData(location which) {
cOutdoors& sector = *scenario.outdoors[which.x][which.y];
map_data terrain;
for(size_t x = 0; x < 48; x++) {
for(size_t y = 0; y < 48; y++) {
terrain.set(x, y, sector.terrain[x][y]);
if(sector.special_spot[x][y])
terrain.addFeature(x, y, eMapFeature::FIELD, SPECIAL_SPOT);
}
}
for(size_t i = 0; i < 18; i++) {
if(sector.special_id[i] >= 0)
terrain.addFeature(sector.special_locs[i].x, sector.special_locs[i].y, eMapFeature::SPECIAL_NODE, sector.special_id[i]);
}
for(size_t i = 0; i < 8; i++) {
if(sector.exit_dests[i] >= 0)
terrain.addFeature(sector.exit_locs[i].x, sector.exit_locs[i].y, eMapFeature::TOWN, sector.exit_dests[i]);
}
for(size_t i = 0; i < sector.sign_strs.size(); i++) {
if(!sector.sign_strs[i].empty())
terrain.addFeature(sector.sign_locs[i].x, sector.sign_locs[i].y, eMapFeature::SIGN, i);
}
for(size_t i = 0; i < 4; i++) {
terrain.addFeature(sector.wandering_locs[i].x, sector.wandering_locs[i].y, eMapFeature::WANDERING, i);
}
for(size_t i = 0; i < 30; i++) {
if(scenario.boats[i].which_town == 200 && scenario.boats[i].sector == which) {
int j = i;
if(scenario.boats[i].property) j *= -1;
terrain.addFeature(scenario.boats[i].loc.x, scenario.boats[i].loc.y, eMapFeature::HORSE, j);
}
if(scenario.horses[i].which_town == 200 && scenario.horses[i].sector == which) {
int j = i;
if(scenario.horses[i].property) j *= -1;
terrain.addFeature(scenario.horses[i].loc.x, scenario.horses[i].loc.y, eMapFeature::HORSE, j);
}
}
return terrain;
}
map_data buildTownMapData(size_t which) {
cTown& town = *scenario.towns[which];
map_data terrain;
for(size_t x = 0; x < town.max_dim(); x++) {
for(size_t y = 0; y < town.max_dim(); y++) {
terrain.set(x, y, town.terrain(x,y));
}
}
for(size_t i = 0; i < 50; i++) {
if(town.spec_id[i] >= 0)
terrain.addFeature(town.special_locs[i].x, town.special_locs[i].y, eMapFeature::SPECIAL_NODE, town.spec_id[i]);
}
for(size_t i = 0; i < town.sign_strs.size(); i++) {
if(!town.sign_strs[i].empty())
terrain.addFeature(town.sign_locs[i].x, town.sign_locs[i].y, eMapFeature::SIGN, i);
}
for(size_t i = 0; i < 4; i++) {
terrain.addFeature(town.wandering_locs[i].x, town.wandering_locs[i].y, eMapFeature::WANDERING, i);
}
for(size_t i = 0; i < town.preset_items.size(); i++) {
if(town.preset_items[i].code >= 0)
terrain.addFeature(town.preset_items[i].loc.x, town.preset_items[i].loc.y, eMapFeature::ITEM, i);
}
for(size_t i = 0; i < town.preset_fields.size(); i++) {
if(town.preset_fields[i].type > 0)
terrain.addFeature(town.preset_fields[i].loc.x,town.preset_fields[i].loc.y,eMapFeature::FIELD,town.preset_fields[i].type);
}
for(size_t i = 0; i < town.creatures.size(); i++) {
if(town.creatures[i].number > 0)
terrain.addFeature(town.creatures[i].start_loc.x, town.creatures[i].start_loc.y, eMapFeature::CREATURE, i);
}
for(size_t i = 0; i < 30; i++) {
if(scenario.boats[i].which_town == which) {
int j = i;
if(scenario.boats[i].property) j *= -1;
terrain.addFeature(scenario.boats[i].loc.x, scenario.boats[i].loc.y, eMapFeature::HORSE, j);
}
if(scenario.horses[i].which_town == which) {
int j = i;
if(scenario.horses[i].property) j *= -1;
terrain.addFeature(scenario.horses[i].loc.x, scenario.horses[i].loc.y, eMapFeature::HORSE, j);
}
}
terrain.addFeature(town.start_locs[0].x, town.start_locs[0].y, eMapFeature::ENTRANCE_SOUTH);
terrain.addFeature(town.start_locs[1].x, town.start_locs[1].y, eMapFeature::ENTRANCE_WEST);
terrain.addFeature(town.start_locs[2].x, town.start_locs[2].y, eMapFeature::ENTRANCE_NORTH);
terrain.addFeature(town.start_locs[3].x, town.start_locs[3].y, eMapFeature::ENTRANCE_EAST);
return terrain;
}
void save_scenario(fs::path toFile) {
// TODO: I'm not certain 1.0.0 is the correct version here?
scenario.format.prog_make_ver[0] = 1;
@@ -689,6 +780,7 @@ void save_scenario(fs::path toFile) {
// Then the map.
std::ostream& out_map = scen_file.newFile("scenario/out/" + file_basename + ".map");
buildOutMapData(loc(x,y)).writeTo(out_map);
// And the special nodes.
std::ostream& out_spec = scen_file.newFile("scenario/out/" + file_basename + ".spec");
@@ -705,6 +797,7 @@ void save_scenario(fs::path toFile) {
// Then the map.
std::ostream& town_map = scen_file.newFile("scenario/towns/" + file_basename + ".map");
buildTownMapData(i).writeTo(town_map);
// And the special nodes.
std::ostream& town_spec = scen_file.newFile("scenario/towns/" + file_basename + ".spec");

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);